summaryrefslogtreecommitdiff
path: root/webtest
diff options
context:
space:
mode:
authorGael Pasgrimaud <gael@gawel.org>2011-08-22 02:33:45 +0200
committerGael Pasgrimaud <gael@gawel.org>2011-08-22 02:33:45 +0200
commitf82dddf866f18d248d34ec6518c87eeb68a1d30d (patch)
tree1a75a5db011bf737ae30b81854aee956723ba2df /webtest
parentc2ee929a59b7ea6b22f880032e7735be566605cc (diff)
downloadwebtest-f82dddf866f18d248d34ec6518c87eeb68a1d30d.tar.gz
pep8
Diffstat (limited to 'webtest')
-rw-r--r--webtest/app.py124
1 files changed, 82 insertions, 42 deletions
diff --git a/webtest/app.py b/webtest/app.py
index 5f22923..7099d67 100644
--- a/webtest/app.py
+++ b/webtest/app.py
@@ -1,5 +1,7 @@
-# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
-# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+# (c) 2005 Ian Bicking and contributors; written for Paste
+# (http://pythonpaste.org)
+# Licensed under the MIT license:
+# http://www.opensource.org/licenses/mit-license.php
"""
Routines for testing WSGI applications.
@@ -26,6 +28,7 @@ from webtest import lint
__all__ = ['TestApp', 'TestRequest']
+
def tempnam_no_warning(*args):
"""
An os.tempnam with the warning turned off, because sometimes
@@ -34,6 +37,7 @@ def tempnam_no_warning(*args):
"""
return os.tempnam(*args)
+
class NoDefault(object):
pass
@@ -45,9 +49,11 @@ except NameError:
l.sort()
return l
+
class AppError(Exception):
pass
+
class CaptureStdout(object):
def __init__(self, actual):
@@ -68,6 +74,7 @@ class CaptureStdout(object):
def getvalue(self):
return self.captured.getvalue()
+
class TestResponse(Response):
"""
@@ -76,7 +83,6 @@ class TestResponse(Response):
_forms_indexed = None
-
def forms__get(self):
"""
Returns a dictionary of ``Form`` objects. Indexes are both in
@@ -116,7 +122,7 @@ class TestResponse(Response):
return self.unicode_body
return self.body
- _tag_re = re.compile(r'<(/?)([:a-z0-9_\-]*)(.*?)>', re.S|re.I)
+ _tag_re = re.compile(r'<(/?)([:a-z0-9_\-]*)(.*?)>', re.S | re.I)
def _parse_forms(self):
forms = self._forms_indexed = {}
@@ -239,8 +245,8 @@ class TestResponse(Response):
html_pat = _make_pattern(html_pattern)
_tag_re = re.compile(r'<%s\s+(.*?)>(.*?)</%s>' % (tag, tag),
- re.I+re.S)
- _script_re = re.compile(r'<script.*?>.*?</script>', re.I|re.S)
+ re.I + re.S)
+ _script_re = re.compile(r'<script.*?>.*?</script>', re.I | re.S)
bad_spans = []
for match in _script_re.finditer(self.testbody):
bad_spans.append((match.start(), match.end()))
@@ -346,10 +352,12 @@ class TestResponse(Response):
href = to_str(href)
if 'params' in args:
- args['params'] = [tuple(map(to_str, p)) for p in args['params']]
+ args['params'] = [tuple(map(to_str, p)) \
+ for p in args['params']]
if 'upload_files' in args:
- args['upload_files'] = [map(to_str, f) for f in args['upload_files']]
+ args['upload_files'] = [map(to_str, f) \
+ for f in args['upload_files']]
if 'content_type' in args:
args['content_type'] = to_str(args['content_type'])
@@ -378,7 +386,8 @@ class TestResponse(Response):
def unicode_normal_body__get(self):
if not self.charset:
raise AttributeError(
- "You cannot access Response.unicode_normal_body unless charset is set")
+ ("You cannot access Response.unicode_normal_body "
+ "unless charset is set"))
return self.normal_body.decode(self.charset)
unicode_normal_body = property(
@@ -462,7 +471,7 @@ class TestResponse(Response):
if self.body:
br = repr(self.body)
if len(br) > 18:
- br = br[:10]+'...'+br[-5:]
+ br = br[:10] + '...' + br[-5:]
br += '/%s' % len(self.body)
body = ' body=%s' % br
else:
@@ -519,7 +528,8 @@ class TestResponse(Response):
from elementtree import ElementTree
except ImportError:
raise ImportError(
- "You must have ElementTree installed (or use Python 2.5) to use response.xml")
+ ("You must have ElementTree installed "
+ "(or use Python 2.5) to use response.xml"))
# ElementTree can't parse unicode => use `body` instead of `testbody`
return ElementTree.XML(self.body)
@@ -560,11 +570,9 @@ class TestResponse(Response):
def json(self):
"""
- Return the response as a JSON response. You must have
- `simplejson
- <http://svn.red-bean.com/bob/simplejson/tags/simplejson-1.7/docs/index.html>`_
- installed to use this, or be using a Python version with the
- json module.
+ Return the response as a JSON response. You must have `simplejson
+ <http://goo.gl/B9g6s>`_ installed to use this, or be using a Python
+ version with the json module.
The content type must be application/json to use this.
"""
@@ -618,12 +626,14 @@ class TestResponse(Response):
url = 'file:' + fn.replace(os.sep, '/')
webbrowser.open_new(url)
+
class TestRequest(Request):
# for py.test
disabled = True
ResponseClass = TestResponse
+
class TestApp(object):
"""
Wraps a WSGI application in a more convenient interface for
@@ -645,7 +655,8 @@ class TestApp(object):
disabled = True
RequestClass = TestRequest
- def __init__(self, app, extra_environ=None, relative_to=None, use_unicode=True):
+ def __init__(self, app, extra_environ=None, relative_to=None,
+ use_unicode=True):
if isinstance(app, (str, unicode)):
from paste.deploy import loadapp
# @@: Should pick up relative_to from calling module's
@@ -731,9 +742,9 @@ class TestApp(object):
return self.do_request(req, status=status,
expect_errors=expect_errors)
- def _gen_request(self, method, url, params='', headers=None, extra_environ=None,
- status=None, upload_files=None, expect_errors=False,
- content_type=None):
+ def _gen_request(self, method, url, params='', headers=None,
+ extra_environ=None, status=None, upload_files=None,
+ expect_errors=False, content_type=None):
"""
Do a generic request.
"""
@@ -743,13 +754,15 @@ class TestApp(object):
params = urllib.urlencode(params, doseq=True)
if hasattr(params, 'items'):
params = urllib.urlencode(params.items(), doseq=True)
- if upload_files or (content_type and content_type.startswith('multipart')):
+ if upload_files or \
+ (content_type and content_type.startswith('multipart')):
params = cgi.parse_qsl(params, keep_blank_values=True)
content_type, params = self.encode_multipart(
params, upload_files or ())
environ['CONTENT_TYPE'] = content_type
elif params:
- environ.setdefault('CONTENT_TYPE', 'application/x-www-form-urlencoded')
+ environ.setdefault('CONTENT_TYPE',
+ 'application/x-www-form-urlencoded')
if '?' in url:
url, environ['QUERY_STRING'] = url.split('?', 1)
else:
@@ -781,7 +794,7 @@ class TestApp(object):
Returns a ``webob.Response`` object.
"""
return self._gen_request('POST', url, params=params, headers=headers,
- extra_environ=extra_environ,status=status,
+ extra_environ=extra_environ, status=status,
upload_files=upload_files,
expect_errors=expect_errors,
content_type=content_type)
@@ -799,7 +812,7 @@ class TestApp(object):
Returns a ``webob.Response`` object.
"""
return self._gen_request('PUT', url, params=params, headers=headers,
- extra_environ=extra_environ,status=status,
+ extra_environ=extra_environ, status=status,
upload_files=upload_files,
expect_errors=expect_errors,
content_type=content_type)
@@ -816,8 +829,9 @@ class TestApp(object):
'DELETE request. Most web servers will ignore it'),
lint.WSGIWarning)
return self._gen_request('DELETE', url, params=params, headers=headers,
- extra_environ=extra_environ,status=status,
- upload_files=None, expect_errors=expect_errors)
+ extra_environ=extra_environ, status=status,
+ upload_files=None,
+ expect_errors=expect_errors)
def head(self, url, headers=None, extra_environ=None,
status=None, expect_errors=False):
@@ -827,8 +841,9 @@ class TestApp(object):
Returns a ``webob.Response`` object.
"""
return self._gen_request('HEAD', url, headers=headers,
- extra_environ=extra_environ,status=status,
- upload_files=None, expect_errors=expect_errors)
+ extra_environ=extra_environ, status=status,
+ upload_files=None,
+ expect_errors=expect_errors)
def encode_multipart(self, params, files):
"""
@@ -839,15 +854,16 @@ class TestApp(object):
boundary = '----------a_BoUnDaRy%s$' % random.random()
lines = []
for key, value in params:
- lines.append('--'+boundary)
+ lines.append('--' + boundary)
lines.append('Content-Disposition: form-data; name="%s"' % key)
lines.append('')
lines.append(value)
for file_info in files:
key, filename, value = self._get_file_info(file_info)
- lines.append('--'+boundary)
- lines.append('Content-Disposition: form-data; name="%s"; filename="%s"'
- % (key, filename))
+ lines.append('--' + boundary)
+ lines.append(
+ 'Content-Disposition: form-data; name="%s"; filename="%s"'
+ % (key, filename))
fcontent = mimetypes.guess_type(filename)[0]
lines.append('Content-Type: %s' %
(fcontent or 'application/octet-stream'))
@@ -878,7 +894,6 @@ class TestApp(object):
"you gave: %r"
% repr(file_info)[:100])
-
def request(self, url_or_req, status=None, expect_errors=False,
**req_params):
"""
@@ -1021,7 +1036,10 @@ class TestApp(object):
########################################
-_attr_re = re.compile(r'([^= \n\r\t]+)[ \n\r\t]*(?:=[ \n\r\t]*(?:"([^"]*)"|\'([^\']*)\'|([^"\'][^ \n\r\t>]*)))?', re.S)
+_attr_re = re.compile(
+ (r'([^= \n\r\t]+)[ \n\r\t]*(?:=[ \n\r\t]*(?:"([^"]*)"|\'([^\']*)'
+ r'\'|([^"\'][^ \n\r\t>]*)))?'), re.S)
+
def _parse_attrs(text):
attrs = {}
@@ -1035,6 +1053,7 @@ def _parse_attrs(text):
attrs[str(attr_name)] = attr_body
return attrs
+
class Field(object):
"""
@@ -1081,9 +1100,11 @@ class Field(object):
value += ' id="%s"' % self.id
return value + '>'
+
class NoValue(object):
pass
+
class Select(Field):
"""
@@ -1133,6 +1154,7 @@ class Select(Field):
Field.classes['select'] = Select
+
class MultipleSelect(Field):
"""
@@ -1167,7 +1189,8 @@ class MultipleSelect(Field):
def value__get(self):
selected_values = []
if self.selectedIndices:
- selected_values = [self.options[i][0] for i in self.selectedIndices]
+ selected_values = [self.options[i][0] \
+ for i in self.selectedIndices]
elif not self._forced_values:
selected_values = []
for option, checked in self.options:
@@ -1183,6 +1206,7 @@ class MultipleSelect(Field):
Field.classes['multiple_select'] = MultipleSelect
+
class Radio(Select):
"""
@@ -1201,9 +1225,9 @@ class Radio(Select):
value = property(value__get, Select.value__set)
-
Field.classes['radio'] = Radio
+
class Checkbox(Field):
"""
@@ -1230,6 +1254,7 @@ class Checkbox(Field):
Field.classes['checkbox'] = Checkbox
+
class Text(Field):
"""
Field representing ``<input type="text">``
@@ -1262,6 +1287,7 @@ class File(Field):
Field.classes['file'] = File
+
class Textarea(Text):
"""
Field representing ``<textarea>``
@@ -1269,6 +1295,7 @@ class Textarea(Text):
Field.classes['textarea'] = Textarea
+
class Hidden(Text):
"""
Field representing ``<input type="hidden">``
@@ -1276,6 +1303,7 @@ class Hidden(Text):
Field.classes['hidden'] = Hidden
+
class Submit(Field):
"""
Field representing ``<input type="submit">`` and ``<button>``
@@ -1297,6 +1325,7 @@ Field.classes['button'] = Submit
Field.classes['image'] = Submit
+
class Form(object):
"""
@@ -1326,7 +1355,8 @@ class Form(object):
_tag_re = re.compile(r'<(/?)([a-z0-9_\-]*)([^>]*?)>', re.I)
_label_re = re.compile(
- '''<label\s+(?:[^>]*)for=(?:"|')([a-z0-9_\-]+)(?:"|')(?:[^>]*)>''', re.I)
+ '''<label\s+(?:[^>]*)for=(?:"|')([a-z0-9_\-]+)(?:"|')(?:[^>]*)>''',
+ re.I)
FieldClass = Field
@@ -1354,7 +1384,8 @@ class Form(object):
if tag == 'textarea' and end:
assert in_textarea, (
"</textarea> with no <textarea> at %s" % match.start())
- in_textarea[0].value = html_unquote(self.text[in_textarea[1]:match.start()])
+ in_textarea[0].value = html_unquote(
+ self.text[in_textarea[1]:match.start()])
in_textarea = None
continue
if end:
@@ -1371,7 +1402,8 @@ class Form(object):
if tag == 'input' and attrs.get('type') == 'radio':
field = fields.get(name)
if not field:
- field = self.FieldClass.classes['radio'](self, tag, name, match.start(), **attrs)
+ field = self.FieldClass.classes['radio'](
+ self, tag, name, match.start(), **attrs)
fields.setdefault(name, []).append(field)
else:
field = field[0]
@@ -1383,9 +1415,11 @@ class Form(object):
if tag == 'input':
tag_type = attrs.get('type', 'text').lower()
if tag_type == "select" and attrs.get("multiple"):
- FieldClass = self.FieldClass.classes.get("multiple_select", self.FieldClass)
+ FieldClass = self.FieldClass.classes.get("multiple_select",
+ self.FieldClass)
else:
- FieldClass = self.FieldClass.classes.get(tag_type, self.FieldClass)
+ FieldClass = self.FieldClass.classes.get(tag_type,
+ self.FieldClass)
field = FieldClass(self, tag, name, match.start(), **attrs)
if tag == 'textarea':
assert not in_textarea, (
@@ -1413,7 +1447,8 @@ class Form(object):
self.action = attrs.get('action', '')
self.method = attrs.get('method', 'GET')
self.id = attrs.get('id')
- self.enctype = attrs.get('enctype', 'application/x-www-form-urlencoded')
+ self.enctype = attrs.get('enctype',
+ 'application/x-www-form-urlencoded')
else:
assert 0, "No </form> tag found"
assert self.action is not None, (
@@ -1573,11 +1608,13 @@ class Form(object):
## Utility functions
########################################
+
def _stringify(value):
if isinstance(value, unicode):
return value
return str(value)
+
def _popget(d, key, default=None):
"""
Pop the key if found (else return default)
@@ -1586,6 +1623,7 @@ def _popget(d, key, default=None):
return d.pop(key)
return default
+
def _space_prefix(pref, full, sep=None, indent=None, include_sep=True):
"""
Anything shared by pref and full will be replaced with spaces
@@ -1611,6 +1649,7 @@ def _space_prefix(pref, full, sep=None, indent=None, include_sep=True):
else:
return sep.join(full)
+
def _make_pattern(pat):
if pat is None:
return None
@@ -1623,6 +1662,7 @@ def _make_pattern(pat):
assert 0, (
"Cannot make callable pattern object out of %r" % pat)
+
def html_unquote(v):
"""
Unquote (some) entities in HTML. (incomplete)