summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Carter <john@therefromhere.org>2019-01-19 14:11:28 +1300
committerJohn Carter <john@therefromhere.org>2019-01-19 14:11:28 +1300
commitcdaf2c628a0b2bca5f808f13eb2fd150c508ca6b (patch)
treedbcc58797b6feb15bea7966ac36fefa7dc3f7a90
parent9f3193da7408cec9ac9c612e047d1c48ba9e542c (diff)
downloadwebtest-cdaf2c628a0b2bca5f808f13eb2fd150c508ca6b.tar.gz
Converted lint check_* functions to raise AssertionError instead of assert
So they still check when PYTHONOPTIMIZE>=1
-rw-r--r--tests/test_lint.py6
-rw-r--r--webtest/lint.py226
2 files changed, 149 insertions, 83 deletions
diff --git a/tests/test_lint.py b/tests/test_lint.py
index e0b7f31..1472edf 100644
--- a/tests/test_lint.py
+++ b/tests/test_lint.py
@@ -43,7 +43,6 @@ def application(environ, start_response):
return resp(environ, start_response)
-@unittest.skipIf(sys.flags.optimize > 0, "skip assert tests if optimize is enabled")
class TestLatin1Assertion(unittest.TestCase):
def test_valid_type(self):
@@ -66,9 +65,9 @@ class TestToString(unittest.TestCase):
self.assertEqual(to_string(b'foo'), 'foo')
-@unittest.skipIf(sys.flags.optimize > 0, "skip assert tests if optimize is enabled")
class TestMiddleware(unittest.TestCase):
+ @unittest.skipIf(sys.flags.optimize > 0, "skip assert tests if optimize is enabled")
def test_lint_too_few_args(self):
linter = middleware(application)
with self.assertRaisesRegexp(AssertionError, "Two arguments required"):
@@ -76,6 +75,7 @@ class TestMiddleware(unittest.TestCase):
with self.assertRaisesRegexp(AssertionError, "Two arguments required"):
linter({})
+ @unittest.skipIf(sys.flags.optimize > 0, "skip assert tests if optimize is enabled")
def test_lint_no_keyword_args(self):
linter = middleware(application)
with self.assertRaisesRegexp(AssertionError, "No keyword arguments "
@@ -144,7 +144,6 @@ class TestMiddleware2(unittest.TestCase):
# don't know what to assert here... a bit cheating, just covers code
-@unittest.skipIf(sys.flags.optimize > 0, "skip assert tests if optimize is enabled")
class TestCheckContentType(unittest.TestCase):
def test_no_content(self):
status = "204 No Content"
@@ -162,7 +161,6 @@ class TestCheckContentType(unittest.TestCase):
self.assertRaises(AssertionError, check_content_type, status, headers)
-@unittest.skipIf(sys.flags.optimize > 0, "skip assert tests if optimize is enabled")
class TestCheckHeaders(unittest.TestCase):
@unittest.skipIf(PY3, 'unicode is str in Python3')
diff --git a/webtest/lint.py b/webtest/lint.py
index a477f40..f4c2b25 100644
--- a/webtest/lint.py
+++ b/webtest/lint.py
@@ -199,8 +199,10 @@ def middleware(application, global_conf=None):
environ['wsgi.errors'] = ErrorWrapper(environ['wsgi.errors'])
iterator = application(environ, start_response_wrapper)
- assert isinstance(iterator, Iterable), (
- "The application must return an iterator, if only an empty list")
+ if not isinstance(iterator, Iterable):
+ raise AssertionError(
+ "The application must return an iterator, if only an empty list"
+ )
check_iterator(iterator)
@@ -316,21 +318,25 @@ class IteratorWrapper(object):
def check_environ(environ):
- assert type(environ) is dict, (
- "Environment is not of the right type: %r (environment: %r)"
- % (type(environ), environ))
+ if type(environ) is not dict:
+ raise AssertionError(
+ "Environment is not of the right type: %r (environment: %r)"
+ % (type(environ), environ)
+ )
for key in ['REQUEST_METHOD', 'SERVER_NAME', 'SERVER_PORT',
'wsgi.version', 'wsgi.input', 'wsgi.errors',
'wsgi.multithread', 'wsgi.multiprocess',
'wsgi.run_once']:
- assert key in environ, (
- "Environment missing required key: %r" % key)
+ if key not in environ:
+ raise AssertionError("Environment missing required key: %r" % key)
for key in ['HTTP_CONTENT_TYPE', 'HTTP_CONTENT_LENGTH']:
- assert key not in environ, (
- "Environment should not have the key: %s "
- "(use %s instead)" % (key, key[5:]))
+ if key in environ:
+ raise AssertionError(
+ "Environment should not have the key: %s "
+ "(use %s instead)" % (key, key[5:])
+ )
if 'QUERY_STRING' not in environ:
warnings.warn(
@@ -343,14 +349,21 @@ def check_environ(environ):
if '.' in key:
# Extension, we don't care about its type
continue
- assert type(environ[key]) in METADATA_TYPE, (
- "Environmental variable %s is not a string: %r (value: %r)"
- % (key, type(environ[key]), environ[key]))
+ if type(environ[key]) not in METADATA_TYPE:
+ raise AssertionError(
+ "Environmental variable %s is not a string: %r (value: %r)"
+ % (key, type(environ[key]), environ[key])
+ )
+
+ if type(environ['wsgi.version']) is not tuple:
+ raise AssertionError(
+ "wsgi.version should be a tuple (%r)" % environ['wsgi.version']
+ )
- assert type(environ['wsgi.version']) is tuple, (
- "wsgi.version should be a tuple (%r)" % environ['wsgi.version'])
- assert environ['wsgi.url_scheme'] in ('http', 'https'), (
- "wsgi.url_scheme unknown: %r" % environ['wsgi.url_scheme'])
+ if environ['wsgi.url_scheme'] not in ('http', 'https'):
+ raise AssertionError(
+ "wsgi.url_scheme unknown: %r" % environ['wsgi.url_scheme']
+ )
check_input(environ['wsgi.input'])
check_errors(environ['wsgi.errors'])
@@ -361,62 +374,89 @@ def check_environ(environ):
"Unknown REQUEST_METHOD: %r" % environ['REQUEST_METHOD'],
WSGIWarning)
- assert (not environ.get('SCRIPT_NAME')
- or environ['SCRIPT_NAME'].startswith(SLASH)), (
- "SCRIPT_NAME doesn't start with /: %r" % environ['SCRIPT_NAME'])
- assert (not environ.get('PATH_INFO')
- or environ['PATH_INFO'].startswith(SLASH)), (
- "PATH_INFO doesn't start with /: %r" % environ['PATH_INFO'])
+ if environ.get('SCRIPT_NAME') and not environ['SCRIPT_NAME'].startswith(SLASH):
+ raise AssertionError(
+ "SCRIPT_NAME doesn't start with /: %r" % environ['SCRIPT_NAME']
+ )
+
+ if environ.get('PATH_INFO') and not environ['PATH_INFO'].startswith(SLASH):
+ raise AssertionError(
+ "PATH_INFO doesn't start with /: %r" % environ['PATH_INFO']
+ )
+
if environ.get('CONTENT_LENGTH'):
- assert int(environ['CONTENT_LENGTH']) >= 0, (
- "Invalid CONTENT_LENGTH: %r" % environ['CONTENT_LENGTH'])
+ if int(environ['CONTENT_LENGTH']) < 0:
+ raise AssertionError(
+ "Invalid CONTENT_LENGTH: %r" % environ['CONTENT_LENGTH']
+ )
if not environ.get('SCRIPT_NAME'):
- assert 'PATH_INFO' in environ, (
- "One of SCRIPT_NAME or PATH_INFO are required (PATH_INFO "
- "should at least be '/' if SCRIPT_NAME is empty)")
- assert environ.get('SCRIPT_NAME') != SLASH, (
- "SCRIPT_NAME cannot be '/'; it should instead be '', and "
- "PATH_INFO should be '/'")
+ if 'PATH_INFO' not in environ:
+ raise AssertionError(
+ "One of SCRIPT_NAME or PATH_INFO are required (PATH_INFO "
+ "should at least be '/' if SCRIPT_NAME is empty)"
+ )
+
+ if environ.get('SCRIPT_NAME') == SLASH:
+ raise AssertionError(
+ "SCRIPT_NAME cannot be '/'; it should instead be '', and "
+ "PATH_INFO should be '/'"
+ )
def check_input(wsgi_input):
for attr in ['read', 'readline', 'readlines', '__iter__']:
- assert hasattr(wsgi_input, attr), (
- "wsgi.input (%r) doesn't have the attribute %s"
- % (wsgi_input, attr))
+ if not hasattr(wsgi_input, attr):
+ raise AssertionError(
+ "wsgi.input (%r) doesn't have the attribute %s"
+ % (wsgi_input, attr)
+ )
def check_errors(wsgi_errors):
for attr in ['flush', 'write', 'writelines']:
- assert hasattr(wsgi_errors, attr), (
- "wsgi.errors (%r) doesn't have the attribute %s"
- % (wsgi_errors, attr))
+ if not hasattr(wsgi_errors, attr):
+ raise AssertionError(
+ "wsgi.errors (%r) doesn't have the attribute %s"
+ % (wsgi_errors, attr)
+ )
def check_status(status):
- assert type(status) in METADATA_TYPE, (
- "Status must be a %s (not %r)" % (METADATA_TYPE, status))
+ if type(status) not in METADATA_TYPE:
+ raise AssertionError("Status must be a %s (not %r)" % (METADATA_TYPE, status))
+
status = to_string(status)
- assert len(status) > 5, (
- "The status string (%r) should be a three-digit "
- "integer followed by a single space and a status explanation"
- ) % status
- assert status[:3].isdigit(), (
- "The status string (%r) should start with"
- "three digits") % status
+
+ if len(status) <= 5:
+ raise AssertionError(
+ "The status string (%r) should be a three-digit "
+ "integer followed by a single space and a status explanation" % status
+ )
+
+ if not status[:3].isdigit():
+ raise AssertionError(
+ "The status string (%r) should start with three digits" % status
+ )
status_int = int(status[:3])
- assert status_int >= 100, (
- "The status code must be greater or equal than "
- "100 (got %d)") % status_int
- assert status[3] == ' ', (
- "The status string (%r) should start with three"
- "digits and a space (4th characters is not a space here)") % status
+
+ if status_int < 100:
+ raise AssertionError(
+ "The status code must be greater or equal than 100 (got %d)" % status_int
+ )
+
+ if status[3] != ' ':
+ raise AssertionError(
+ "The status string (%r) should start with three"
+ "digits and a space (4th characters is not a space here)" % status
+ )
def _assert_latin1_str(string, message):
- assert type(string) is str, message
+ if type(string) is not str:
+ raise AssertionError(message)
+
if type(string) is text_type:
try:
string.encode('latin1')
@@ -426,13 +466,18 @@ def _assert_latin1_str(string, message):
def check_headers(headers):
- assert type(headers) is list, (
- "Headers (%r) must be of type list: %r"
- % (headers, type(headers)))
+ if type(headers) is not list:
+ raise AssertionError(
+ "Headers (%r) must be of type list: %r" % (headers, type(headers))
+ )
+
for item in headers:
- assert type(item) is tuple, (
- "Individual headers (%r) must be of type tuple: %r"
- % (item, type(item)))
+ if type(item) is not tuple:
+ raise AssertionError(
+ "Individual headers (%r) must be of type tuple: %r"
+ % (item, type(item))
+ )
+
assert len(item) == 2
name, value = item
_assert_latin1_str(
@@ -441,24 +486,37 @@ def check_headers(headers):
"(not Py2 unicode or Py3 bytes type). "
"%r is not a valid latin1 string" % (name,)
)
- assert name.lower() != 'status', (
- "The Status header cannot be used; it conflicts with CGI "
- "script, and HTTP status is not given through headers "
- "(value: %r)." % value)
- assert '\n' not in name and ':' not in name, (
- "Header names may not contain ':' or '\\n': %r" % name)
- assert header_re.search(name), "Bad header name: %r" % name
- assert not name.endswith('-') and not name.endswith('_'), (
- "Names may not end in '-' or '_': %r" % name)
+
+ if name.lower() == 'status':
+ raise AssertionError(
+ "The Status header cannot be used; it conflicts with CGI "
+ "script, and HTTP status is not given through headers "
+ "(value: %r)." % value
+ )
+
+ if '\n' in name or ':' in name:
+ raise AssertionError(
+ "Header names may not contain ':' or '\\n': %r" % name
+ )
+
+ if not header_re.search(name):
+ raise AssertionError("Bad header name: %r" % name)
+
+ if name.endswith('-') or name.endswith('_'):
+ raise AssertionError("Names may not end in '-' or '_': %r" % name)
+
_assert_latin1_str(
value,
"Header values must be latin1 string "
"(not Py2 unicode or Py3 bytes type)."
"%r is not a valid latin1 string" % (value,)
)
- assert not bad_header_value_re.search(value), (
- "Bad header value: %r (bad char: %r)"
- % (str_value, bad_header_value_re.search(value).group(0)))
+
+ if bad_header_value_re.search(value):
+ raise AssertionError(
+ "Bad header value: %r (bad char: %r)"
+ % (str_value, bad_header_value_re.search(value).group(0))
+ )
def check_content_type(status, headers):
@@ -482,15 +540,22 @@ def check_content_type(status, headers):
WSGIWarning)
return
else:
- assert 0, (("Content-Type header found in a %s response, "
- "which must not return content.") % code)
+ raise AssertionError(
+ "Content-Type header found in a %s response, "
+ "which must not return content." % code
+ )
+
if code not in NO_MESSAGE_BODY and length is not None and length > 0:
- assert 0, "No Content-Type header found in headers (%s)" % headers
+ raise AssertionError(
+ "No Content-Type header found in headers (%s)" % headers
+ )
def check_exc_info(exc_info):
- assert exc_info is None or type(exc_info) is tuple, (
- "exc_info (%r) is not a tuple: %r" % (exc_info, type(exc_info)))
+ if exc_info is not None and type(exc_info) is not tuple:
+ raise AssertionError(
+ "exc_info (%r) is not a tuple: %r" % (exc_info, type(exc_info))
+ )
# More exc_info checks?
@@ -499,8 +564,11 @@ def check_iterator(iterator):
# Technically a bytes (str for py2.x) 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, valid_type), (
- "You should not return a bytes as your application iterator, "
- "instead return a single-item list containing that string.")
+
+ if isinstance(iterator, valid_type):
+ raise AssertionError(
+ "You should not return a bytes as your application iterator, "
+ "instead return a single-item list containing that string."
+ )
__all__ = ['middleware']