Skip to content

Commit

Permalink
merge back lint/lint3. removed to_string and join_bytes from everywhere
Browse files Browse the repository at this point in the history
  • Loading branch information
gawel committed Dec 6, 2012
1 parent cd190e7 commit 510e988
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 546 deletions.
20 changes: 9 additions & 11 deletions tests/test_field_order.py
@@ -1,7 +1,6 @@
import collections import collections
from tests.compat import unittest from tests.compat import unittest
from webtest.compat import to_bytes from webtest.compat import to_bytes
from webtest.compat import join_bytes
from webtest.compat import binary_type from webtest.compat import binary_type
from webtest.compat import PY3 from webtest.compat import PY3
from webob import Request from webob import Request
Expand Down Expand Up @@ -34,7 +33,7 @@ def submit_app(environ, start_response):
req = Request(environ) req = Request(environ)
status = "200 OK" status = "200 OK"
if req.method == "GET": if req.method == "GET":
body = to_bytes(""" body = """
<html> <html>
<head><title>form page</title></head> <head><title>form page</title></head>
<body> <body>
Expand All @@ -49,14 +48,13 @@ def submit_app(environ, start_response):
</form> </form>
</body> </body>
</html> </html>
""" % (form_id, form_fields_text)) """ % (form_id, form_fields_text)
else: else:
body_head = to_bytes( body_head = """
"""
<html> <html>
<head><title>display page</title></head> <head><title>display page</title></head>
<body> <body>
""") """


body_parts = [] body_parts = []
for (name, value) in req.POST.items(): for (name, value) in req.POST.items():
Expand All @@ -69,16 +67,16 @@ def submit_app(environ, start_response):
body_parts.append("%s:%s\n" % ( body_parts.append("%s:%s\n" % (
name, value)) name, value))


body_foot = to_bytes( body_foot = """ </body>
""" </body>
</html> </html>
""") """
body = body_head + join_bytes("", body_parts) + body_foot body = body_head + "".join(body_parts) + body_foot
if not isinstance(body, binary_type):
body = body.encode('utf8')
headers = [ headers = [
('Content-Type', 'text/html; charset=utf-8'), ('Content-Type', 'text/html; charset=utf-8'),
('Content-Length', str(len(body)))] ('Content-Length', str(len(body)))]
start_response(status, headers) start_response(status, headers)
assert(isinstance(body, binary_type))
return [body] return [body]
return submit_app return submit_app


Expand Down
6 changes: 1 addition & 5 deletions webtest/app.py
Expand Up @@ -34,13 +34,9 @@
from webtest.compat import dumps from webtest.compat import dumps
from webtest.compat import loads from webtest.compat import loads
from webtest.compat import PY3 from webtest.compat import PY3
from webtest import lint
from webob import Request, Response from webob import Request, Response


if PY3:
from webtest import lint3 as lint
else:
from webtest import lint # NOQA

__all__ = ['TestApp', 'TestRequest'] __all__ = ['TestApp', 'TestRequest']




Expand Down
6 changes: 0 additions & 6 deletions webtest/compat.py
Expand Up @@ -25,12 +25,6 @@ def to_bytes(value, charset='latin1'):
return value.encode(charset) return value.encode(charset)
return value return value


to_string = six.u


def join_bytes(sep, l):
l = [to_bytes(e) for e in l]
return to_bytes(sep).join(l)


if PY3: if PY3:
string_types = (str,) string_types = (str,)
Expand Down
94 changes: 66 additions & 28 deletions webtest/lint.py
Expand Up @@ -110,10 +110,14 @@
sys.stderr, because we only know it isn't called when the object sys.stderr, because we only know it isn't called when the object
is garbage collected). is garbage collected).
""" """
from __future__ import unicode_literals


import re import re
import sys import sys
import warnings import warnings
from six import PY3
from six import binary_type
from six import string_types


header_re = re.compile(r'^[a-zA-Z][a-zA-Z0-9\-_]*$') header_re = re.compile(r'^[a-zA-Z][a-zA-Z0-9\-_]*$')
bad_header_value_re = re.compile(r'[\000-\037]') bad_header_value_re = re.compile(r'[\000-\037]')
Expand All @@ -123,6 +127,15 @@
'TRACE', 'PATCH', 'TRACE', 'PATCH',
) )


METADATA_TYPE = PY3 and (str, binary_type) or (str,)


def to_string(value):
if not isinstance(value, string_types):
return value.decode('latin1')
else:
return value



class WSGIWarning(Warning): class WSGIWarning(Warning):
""" """
Expand Down Expand Up @@ -194,20 +207,20 @@ def __init__(self, wsgi_input):
def read(self, *args): def read(self, *args):
assert len(args) <= 1 assert len(args) <= 1
v = self.input.read(*args) v = self.input.read(*args)
assert type(v) is type("") assert type(v) is binary_type
return v return v


def readline(self, *args): def readline(self, *args):
v = self.input.readline(*args) v = self.input.readline(*args)
assert type(v) is type("") assert type(v) is binary_type
return v return v


def readlines(self, *args): def readlines(self, *args):
assert len(args) <= 1 assert len(args) <= 1
lines = self.input.readlines(*args) lines = self.input.readlines(*args)
assert type(lines) is type([]) assert type(lines) is type([])
for line in lines: for line in lines:
assert type(line) is type("") assert type(line) is binary_type
return lines return lines


def __iter__(self): def __iter__(self):
Expand All @@ -227,7 +240,7 @@ def __init__(self, wsgi_errors):
self.errors = wsgi_errors self.errors = wsgi_errors


def write(self, s): def write(self, s):
assert type(s) is type("") assert type(s) is binary_type
self.errors.write(s) self.errors.write(s)


def flush(self): def flush(self):
Expand All @@ -247,7 +260,7 @@ def __init__(self, wsgi_writer):
self.writer = wsgi_writer self.writer = wsgi_writer


def __call__(self, s): def __call__(self, s):
assert type(s) is type("") assert type(s) is binary_type
self.writer(s) self.writer(s)




Expand Down Expand Up @@ -281,9 +294,9 @@ def next(self):
"The application returns and we started iterating over its" "The application returns and we started iterating over its"
" body, but start_response has not yet been called") " body, but start_response has not yet been called")
self.check_start_response = None self.check_start_response = None
assert isinstance(v, str), ( assert isinstance(v, binary_type), (
"Iterator %r returned a non-str object: %r" "Iterator %r returned a non-%r object: %r"
% (self.iterator, v)) % (self.iterator, binary_type, v))
return v return v


__next__ = next __next__ = next
Expand Down Expand Up @@ -329,7 +342,7 @@ def check_environ(environ):
if '.' in key: if '.' in key:
# Extension, we don't care about its type # Extension, we don't care about its type
continue continue
assert type(environ[key]) is str, ( assert type(environ[key]) in METADATA_TYPE, (
"Environmental variable %s is not a string: %r (value: %r)" "Environmental variable %s is not a string: %r (value: %r)"
% (key, type(environ[key]), environ[key])) % (key, type(environ[key]), environ[key]))


Expand Down Expand Up @@ -381,8 +394,8 @@ def check_errors(wsgi_errors):




def check_status(status): def check_status(status):
assert type(status) is str, ( assert type(status) in METADATA_TYPE, (
"Status must be a string (not %r)" % status) "Status must be a %s (not %r)" % (METADATA_TYPE, status))
# Implicitly check that we can turn it into an integer: # Implicitly check that we can turn it into an integer:
status_code = status.split(None, 1)[0] status_code = status.split(None, 1)[0]
assert len(status_code) == 3, ( assert len(status_code) == 3, (
Expand All @@ -400,26 +413,40 @@ def check_headers(headers):
assert type(headers) is list, ( assert type(headers) is list, (
"Headers (%r) must be of type list: %r" "Headers (%r) must be of type list: %r"
% (headers, type(headers))) % (headers, type(headers)))
header_names = {}
for item in headers: for item in headers:
assert type(item) is tuple, ( assert type(item) is tuple, (
"Individual headers (%r) must be of type tuple: %r" "Individual headers (%r) must be of type tuple: %r"
% (item, type(item))) % (item, type(item)))
assert len(item) == 2 assert len(item) == 2
name, value = item name, value = item
assert name.lower() != 'status', ( if PY3 and type(name) is str:
try:
name.encode('latin1')
except UnicodeEncodeError:
raise AssertionError((
"Headers name must be latin1 string or bytes."
"%r is not a valid latin1 string" % (name,)))
str_name = to_string(name)
assert str_name.lower() != 'status', (
"The Status header cannot be used; it conflicts with CGI " "The Status header cannot be used; it conflicts with CGI "
"script, and HTTP status is not given through headers " "script, and HTTP status is not given through headers "
"(value: %r)." % value) "(value: %r)." % value)
header_names[name.lower()] = None assert '\n' not in str_name and ':' not in str_name, (
assert '\n' not in name and ':' not in name, (
"Header names may not contain ':' or '\\n': %r" % name) "Header names may not contain ':' or '\\n': %r" % name)
assert header_re.search(name), "Bad header name: %r" % name assert header_re.search(str_name), "Bad header name: %r" % name
assert not name.endswith('-') and not name.endswith('_'), ( assert not str_name.endswith('-') and not str_name.endswith('_'), (
"Names may not end in '-' or '_': %r" % name) "Names may not end in '-' or '_': %r" % name)
assert not bad_header_value_re.search(value), ( if PY3 and type(value) is str:
try:
value.encode('latin1')
except UnicodeEncodeError:
raise AssertionError((
"Headers values must be latin1 string or bytes."
"%r is not a valid latin1 string" % (value,)))
str_value = to_string(value)
assert not bad_header_value_re.search(str_value), (
"Bad header value: %r (bad char: %r)" "Bad header value: %r (bad char: %r)"
% (value, bad_header_value_re.search(value).group(0))) % (str_value, bad_header_value_re.search(str_value).group(0)))




def check_content_type(status, headers): def check_content_type(status, headers):
Expand All @@ -430,10 +457,13 @@ def check_content_type(status, headers):
NO_MESSAGE_TYPE = (204, 304) NO_MESSAGE_TYPE = (204, 304)
length = None length = None
for name, value in headers: for name, value in headers:
if name.lower() == 'content-length' and value.isdigit(): str_name = to_string(name)
if str_name.lower() == 'content-length' and value.isdigit():
length = int(value) length = int(value)
break
for name, value in headers: for name, value in headers:
if name.lower() == 'content-type': str_name = to_string(name)
if str_name.lower() == 'content-type':
if code not in NO_MESSAGE_TYPE: if code not in NO_MESSAGE_TYPE:
return return
elif length == 0: elif length == 0:
Expand All @@ -449,18 +479,26 @@ def check_content_type(status, headers):




def check_exc_info(exc_info): def check_exc_info(exc_info):
assert exc_info is None or type(exc_info) is type(()), ( assert exc_info is None or type(exc_info) is tuple, (
"exc_info (%r) is not a tuple: %r" % (exc_info, type(exc_info))) "exc_info (%r) is not a tuple: %r" % (exc_info, type(exc_info)))
# More exc_info checks? # More exc_info checks?




def check_iterator(iterator): def check_iterator(iterator):
# Technically a string is legal, which is why it's a really bad if PY3:
# idea, because it may cause the response to be returned # Technically a bytes is legal, which is why it's a really bad
# character-by-character # idea, because it may cause the response to be returned
assert not isinstance(iterator, str), ( # character-by-character
"You should not return a string as your application iterator, " assert not isinstance(iterator, bytes), (
"instead return a single-item list containing that string.") "You should not return a bytes as your application iterator, "
"instead return a single-item list containing that string.")
else:
# Technically a string is legal, which is why it's a really bad
# idea, because it may cause the response to be returned
# character-by-character
assert not isinstance(iterator, str), (
"You should not return a string as your application iterator, "
"instead return a single-item list containing that string.")




def make_middleware(application, global_conf): def make_middleware(application, global_conf):
Expand Down

0 comments on commit 510e988

Please sign in to comment.