Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make LintMiddleware Python 3 compatible and add tests #1518

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGES.rst
Expand Up @@ -16,6 +16,8 @@ Unreleased
- Fix the filename format string in
:class:`~middleware.profiler.ProfilerMiddleware` to correctly handle
float values. (:issue:`1511`)
- Update :class:`~middleware.lint.LintMiddleware` to work on Python 3.
(:issue:`1510`)


Version 0.15.2
Expand Down
10 changes: 8 additions & 2 deletions src/werkzeug/middleware/lint.py
Expand Up @@ -14,6 +14,8 @@
"""
from warnings import warn

from .._compat import implements_iterator
from .._compat import PY2
from .._compat import string_types
from ..datastructures import Headers
from ..http import is_entity_header
Expand Down Expand Up @@ -124,18 +126,22 @@ def __call__(self, s):
self._chunks.append(len(s))


@implements_iterator
class GuardedIterator(object):
def __init__(self, iterator, headers_set, chunks):
self._iterator = iterator
self._next = iter(iterator).next
if PY2:
self._next = iter(iterator).next
else:
self._next = iter(iterator).__next__
self.closed = False
self.headers_set = headers_set
self.chunks = chunks

def __iter__(self):
return self

def next(self):
def __next__(self):
if self.closed:
warn("Iterated over closed 'app_iter'.", WSGIWarning, stacklevel=2)

Expand Down
87 changes: 87 additions & 0 deletions tests/middleware/test_lint.py
@@ -0,0 +1,87 @@
# -*- coding: utf-8 -*-
import pytest

from werkzeug.middleware.lint import HTTPWarning
from werkzeug.middleware.lint import LintMiddleware
from werkzeug.middleware.lint import WSGIWarning
from werkzeug.test import create_environ
from werkzeug.test import run_wsgi_app


def dummy_application(environ, start_response):
start_response("200 OK", [("Content-Type", "text/plain")])
return ["Foo"]


def test_lint_middleware():
""" Test lint middleware runs for a dummy applications without warnings """
app = LintMiddleware(dummy_application)

environ = create_environ("/test")
app_iter, status, headers = run_wsgi_app(app, environ, buffered=True)
assert status == "200 OK"


@pytest.mark.parametrize(
"key, value, message",
[
("wsgi.version", (0, 7), "Environ is not a WSGI 1.0 environ."),
("SCRIPT_NAME", "test", "'SCRIPT_NAME' does not start with a slash:"),
("PATH_INFO", "test", "'PATH_INFO' does not start with a slash:"),
],
)
def test_lint_middleware_check_environ(key, value, message):
app = LintMiddleware(dummy_application)

environ = create_environ("/test")
environ[key] = value
with pytest.warns(WSGIWarning, match=message):
app_iter, status, headers = run_wsgi_app(app, environ, buffered=True)
assert status == "200 OK"


def test_lint_middleware_invalid_status():
def my_dummy_application(environ, start_response):
start_response("20 OK", [("Content-Type", "text/plain")])
return ["Foo"]

app = LintMiddleware(my_dummy_application)

environ = create_environ("/test")
with pytest.warns(WSGIWarning) as record:
run_wsgi_app(app, environ, buffered=True)

# Returning status 20 should raise three different warnings
assert len(record) == 3


@pytest.mark.parametrize(
"headers, message",
[
(tuple([("Content-Type", "text/plain")]), "header list is not a list"),
(["fo"], "Headers must tuple 2-item tuples"),
([("status", "foo")], "The status header is not supported"),
],
)
def test_lint_middleware_http_headers(headers, message):
def my_dummy_application(environ, start_response):
start_response("200 OK", headers)
return ["Foo"]

app = LintMiddleware(my_dummy_application)

environ = create_environ("/test")
with pytest.warns(WSGIWarning, match=message):
run_wsgi_app(app, environ, buffered=True)


def test_lint_middleware_invalid_location():
def my_dummy_application(environ, start_response):
start_response("200 OK", [("location", "foo")])
return ["Foo"]

app = LintMiddleware(my_dummy_application)

environ = create_environ("/test")
with pytest.warns(HTTPWarning, match="absolute URLs required for location header"):
run_wsgi_app(app, environ, buffered=True)