summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBert JW Regeer <bertjw@regeer.org>2018-10-15 23:00:08 -0600
committerBert JW Regeer <bertjw@regeer.org>2018-10-15 23:00:08 -0600
commit5c062aef9397b27915c5cc2ed2f202bff7494eca (patch)
treeea877ab1e27e43bb59c3c614684e6198fac2cb10
parent9c41ccfe9d6fba5a35e356792d3b28e6c1451b17 (diff)
downloadwebob-5c062aef9397b27915c5cc2ed2f202bff7494eca.tar.gz
Fix many flake8 warnings/errors
-rw-r--r--src/webob/acceptparse.py153
-rw-r--r--src/webob/byterange.py24
-rw-r--r--src/webob/client.py6
-rw-r--r--src/webob/compat.py6
-rw-r--r--src/webob/cookies.py66
-rw-r--r--src/webob/datetime_utils.py2
-rw-r--r--src/webob/dec.py2
-rw-r--r--src/webob/descriptors.py6
-rw-r--r--src/webob/exc.py78
-rw-r--r--src/webob/headers.py2
-rw-r--r--src/webob/multidict.py81
-rw-r--r--src/webob/request.py11
-rw-r--r--src/webob/response.py8
-rw-r--r--tests/conftest.py2
-rw-r--r--tests/performance_test.py6
-rw-r--r--tests/test_client_functional.py2
-rw-r--r--tests/test_descriptors.py4
-rw-r--r--tests/test_etag.py3
-rw-r--r--tests/test_etag_nose.py2
-rw-r--r--tests/test_exc.py14
-rw-r--r--tests/test_headers.py6
-rw-r--r--tests/test_in_wsgiref.py2
-rw-r--r--tests/test_misc.py2
-rw-r--r--tests/test_multidict.py2
-rw-r--r--tests/test_request.py101
-rw-r--r--tests/test_static.py8
-rw-r--r--tests/test_transcode.py17
27 files changed, 460 insertions, 156 deletions
diff --git a/src/webob/acceptparse.py b/src/webob/acceptparse.py
index a759815..9226971 100644
--- a/src/webob/acceptparse.py
+++ b/src/webob/acceptparse.py
@@ -40,18 +40,21 @@ def _item_n_weight_re(item_re):
def _item_qvalue_pair_to_header_element(pair):
item, qvalue = pair
+
if qvalue == 1.0:
element = item
elif qvalue == 0.0:
element = "{};q=0".format(item)
else:
element = "{};q={}".format(item, qvalue)
+
return element
def _list_0_or_more__compiled_re(element_re):
# RFC 7230 Section 7 "ABNF List Extension: #rule":
# #element => [ ( "," / element ) *( OWS "," [ OWS element ] ) ]
+
return re.compile(
"^(?:$)|"
+ "(?:"
@@ -72,6 +75,7 @@ def _list_1_or_more__compiled_re(element_re):
# RFC 7230 Section 7 "ABNF List Extension: #rule":
# 1#element => *( "," OWS ) element *( OWS "," [ OWS element ] )
# and RFC 7230 Errata ID: 4169
+
return re.compile(
"^(?:,"
+ OWS_re
@@ -105,6 +109,7 @@ class AcceptOffer(namedtuple("AcceptOffer", ["type", "subtype", "params"])):
"""
value = self.type + "/" + self.subtype
+
return Accept._form_media_range(value, self.params)
@@ -246,12 +251,15 @@ class Accept(object):
For media type and extension parameter values.
"""
+
if param_value == "":
param_value = '""'
else:
param_value = param_value.replace("\\", "\\\\").replace('"', r"\"")
+
if not token_compiled_re.match(param_value):
param_value = '"' + param_value + '"'
+
return param_value
@classmethod
@@ -263,6 +271,7 @@ class Accept(object):
string or a (name, value) tuple.
"""
extension_params_segment = ""
+
for item in extension_params:
try:
extension_params_segment += ";" + item
@@ -272,6 +281,7 @@ class Accept(object):
param_value=param_value
)
extension_params_segment += ";" + param_name + "=" + param_value
+
return extension_params_segment
@classmethod
@@ -283,9 +293,11 @@ class Accept(object):
(parameter name, parameter value) tuples.
"""
media_type_params_segment = ""
+
for param_name, param_value in media_type_params:
param_value = cls._escape_and_quote_parameter_value(param_value=param_value)
media_type_params_segment += ";" + param_name + "=" + param_value
+
return type_subtype + media_type_params_segment
@classmethod
@@ -311,6 +323,7 @@ class Accept(object):
element = "{};q=0{}".format(media_range, extension_params_segment)
else:
element = "{};q={}{}".format(media_range, qvalue, extension_params_segment)
+
return element
@classmethod
@@ -321,10 +334,12 @@ class Accept(object):
media_type_params = cls.parameters_compiled_re.findall(
media_type_params_segment
)
+
for index, (name, value) in enumerate(media_type_params):
if value.startswith('"') and value.endswith('"'):
value = cls._process_quoted_string_token(token=value)
media_type_params[index] = (name, value)
+
return media_type_params
@classmethod
@@ -335,6 +350,7 @@ class Accept(object):
# RFC 7230, section 3.2.6 "Field Value Components": "Recipients that
# process the value of a quoted-string MUST handle a quoted-pair as if
# it were replaced by the octet following the backslash."
+
return re.sub(r"\\(?![\\])", "", token[1:-1]).replace("\\\\", "\\")
@classmethod
@@ -342,17 +358,21 @@ class Accept(object):
"""
Convert Python value to header string for __add__/__radd__.
"""
+
if isinstance(value, str):
return value
+
if hasattr(value, "items"):
if value == {}:
value = []
else:
value_list = []
+
for media_range, item in value.items():
# item is either (media range, (qvalue, extension
# parameters segment)), or (media range, qvalue) (supported
# for backward compatibility)
+
if isinstance(item, (float, int)):
value_list.append((media_range, item, ""))
else:
@@ -360,8 +380,10 @@ class Accept(object):
value = sorted(
value_list, key=lambda item: item[1], reverse=True # qvalue
)
+
if isinstance(value, (tuple, list)):
header_elements = []
+
for item in value:
if isinstance(item, (tuple, list)):
item = cls._iterable_to_header_element(iterable=item)
@@ -369,6 +391,7 @@ class Accept(object):
header_str = ", ".join(header_elements)
else:
header_str = str(value)
+
return header_str
@classmethod
@@ -405,6 +428,7 @@ class Accept(object):
# Using Python stdlib's `re` module, there is currently no way to check
# the match *and* get all the groups using the same regex, so we have
# to do this in steps using multiple regexes.
+
if cls.accept_compiled_re.match(value) is None:
raise ValueError("Invalid value for an Accept header.")
@@ -430,10 +454,12 @@ class Accept(object):
qvalue = float(qvalue) if qvalue else 1.0
extension_params = groups[3]
+
if extension_params:
extension_params = cls.accept_ext_compiled_re.findall(
extension_params
)
+
for index, (token_key, token_value) in enumerate(extension_params):
if token_value:
if token_value.startswith('"') and token_value.endswith(
@@ -467,17 +493,21 @@ class Accept(object):
:raises ValueError: If the offer does not match the required format.
"""
+
if isinstance(offer, AcceptOffer):
return offer
match = cls.media_type_compiled_re.match(offer)
+
if not match:
raise ValueError("Invalid value for an Accept offer.")
groups = match.groups()
offer_type, offer_subtype = groups[0].split("/")
offer_params = cls._parse_media_type_params(media_type_params_segment=groups[1])
+
if offer_type == "*" or offer_subtype == "*":
raise ValueError("Invalid value for an Accept offer.")
+
return AcceptOffer(
offer_type.lower(),
offer_subtype.lower(),
@@ -494,12 +524,14 @@ class Accept(object):
"""
parsed_offers = []
+
for index, offer in enumerate(offers):
try:
parsed_offer = cls.parse_offer(offer)
except ValueError:
continue
parsed_offers.append([index, parsed_offer])
+
return parsed_offers
@@ -518,6 +550,7 @@ class AcceptValidHeader(Accept):
@property
def header_value(self):
"""(``str`` or ``None``) The header value."""
+
return self._header_value
@property
@@ -544,6 +577,7 @@ class AcceptValidHeader(Accept):
*extension_params* is the extension parameters, as a list where each
item is either a parameter string or a (parameter name, value) tuple.
"""
+
return self._parsed
def __init__(self, header_value):
@@ -595,6 +629,7 @@ class AcceptValidHeader(Accept):
instance, then a new :class:`AcceptValidHeader` instance with the same
header value as ``self`` is returned.
"""
+
if isinstance(other, AcceptValidHeader):
if other.header_value == "":
return self.__class__(header_value=self.header_value)
@@ -618,6 +653,7 @@ class AcceptValidHeader(Accept):
For this class, it always returns ``True``.
"""
+
return True
__nonzero__ = __bool__ # Python 2
@@ -660,14 +696,16 @@ class AcceptValidHeader(Accept):
"will change in the future to better conform to the RFC.",
DeprecationWarning,
)
+
for (
media_range,
- quality,
- media_type_params,
- extension_params,
+ _quality,
+ _media_type_params,
+ _extension_params,
) in self._parsed_nonzero:
if self._old_match(media_range, offer):
return True
+
return False
def __iter__(self):
@@ -696,7 +734,7 @@ class AcceptValidHeader(Accept):
DeprecationWarning,
)
- for media_range, qvalue, media_type_params, extension_params in sorted(
+ for media_range, _qvalue, _media_type_params, _extension_params in sorted(
self._parsed_nonzero, key=lambda i: i[1], reverse=True
):
yield media_range
@@ -707,6 +745,7 @@ class AcceptValidHeader(Accept):
See the docstring for :meth:`AcceptValidHeader.__add__`.
"""
+
return self._add_instance_and_non_accept_type(
instance=self, other=other, instance_on_the_right=True
)
@@ -925,8 +964,6 @@ class AcceptValidHeader(Accept):
elif offer_media_type_params == range_media_type_params:
specificity = 4
else: # pragma: no cover
- # no cover because of
- # https://bitbucket.org/ned/coveragepy/issues/254/incorrect-coverage-on-continue-statement
continue
else:
if range_subtype == "*" and offer_type == range_type:
@@ -934,8 +971,6 @@ class AcceptValidHeader(Accept):
elif range_type_subtype == "*/*":
specificity = 1
else: # pragma: no cover
- # no cover because of
- # https://bitbucket.org/ned/coveragepy/issues/254/incorrect-coverage-on-continue-statement
continue
try:
if specificity <= (acceptable_offers_n_quality_factors[offer][2]):
@@ -1521,6 +1556,7 @@ class AcceptNoHeader(_AcceptInvalidOrNoHeader):
def __str__(self):
"""Return the ``str`` ``'<no header in request>'``."""
+
return "<no header in request>"
def _add_instance_and_non_accept_type(self, instance, other):
@@ -1554,6 +1590,7 @@ class AcceptInvalidHeader(_AcceptInvalidOrNoHeader):
@property
def header_value(self):
"""(``str`` or ``None``) The header value."""
+
return self._header_value
@property
@@ -1563,6 +1600,7 @@ class AcceptInvalidHeader(_AcceptInvalidOrNoHeader):
As the header is invalid and cannot be parsed, this is ``None``.
"""
+
return self._parsed
def __init__(self, header_value):
@@ -1604,6 +1642,7 @@ class AcceptInvalidHeader(_AcceptInvalidOrNoHeader):
header value, or an :class:`AcceptInvalidHeader` instance, a new
:class:`AcceptNoHeader` instance is returned.
"""
+
if isinstance(other, AcceptValidHeader):
return AcceptValidHeader(header_value=other.header_value)
@@ -1618,6 +1657,7 @@ class AcceptInvalidHeader(_AcceptInvalidOrNoHeader):
See the docstring for :meth:`AcceptValidHeader.__add__`.
"""
+
return self._add_instance_and_non_accept_type(
instance=self, other=other, instance_on_the_right=True
)
@@ -1630,6 +1670,7 @@ class AcceptInvalidHeader(_AcceptInvalidOrNoHeader):
def __str__(self):
"""Return the ``str`` ``'<invalid header value>'``."""
+
return "<invalid header value>"
def _add_instance_and_non_accept_type(
@@ -1660,6 +1701,7 @@ def create_accept_header(header_value):
| If `header_value` is an invalid ``Accept`` header, an
:class:`AcceptInvalidHeader` instance.
"""
+
if header_value is None:
return AcceptNoHeader()
try:
@@ -1684,6 +1726,7 @@ def accept_property():
def fget(request):
"""Get an object representing the header in the request."""
+
return create_accept_header(header_value=request.environ.get(ENVIRON_KEY))
def fset(request, value):
@@ -1709,6 +1752,7 @@ def accept_property():
:class:`AcceptInvalidHeader` instance
* object of any other type that returns a value for ``__str__``
"""
+
if value is None or isinstance(value, AcceptNoHeader):
fdel(request=request)
else:
@@ -1754,8 +1798,10 @@ class AcceptCharset(object):
else:
if hasattr(value, "items"):
value = sorted(value.items(), key=lambda item: item[1], reverse=True)
+
if isinstance(value, (tuple, list)):
result = []
+
for item in value:
if isinstance(item, (tuple, list)):
item = _item_qvalue_pair_to_header_element(pair=item)
@@ -1763,6 +1809,7 @@ class AcceptCharset(object):
header_str = ", ".join(result)
else:
header_str = str(value)
+
return header_str
@classmethod
@@ -1780,6 +1827,7 @@ class AcceptCharset(object):
# Using Python stdlib's `re` module, there is currently no way to check
# the match *and* get all the groups using the same regex, so we have
# to use one regex to check the match, and another to get the groups.
+
if cls.accept_charset_compiled_re.match(value) is None:
raise ValueError("Invalid value for an Accept-Charset header.")
@@ -1808,6 +1856,7 @@ class AcceptCharsetValidHeader(AcceptCharset):
@property
def header_value(self):
"""(``str``) The header value."""
+
return self._header_value
@property
@@ -1817,6 +1866,7 @@ class AcceptCharsetValidHeader(AcceptCharset):
A list of (charset, quality value) tuples.
"""
+
return self._parsed
def __init__(self, header_value):
@@ -1859,6 +1909,7 @@ class AcceptCharsetValidHeader(AcceptCharset):
instance, a new :class:`AcceptCharsetValidHeader` instance with the
same header value as ``self`` is returned.
"""
+
if isinstance(other, AcceptCharsetValidHeader):
return create_accept_charset_header(
header_value=self.header_value + ", " + other.header_value
@@ -1881,6 +1932,7 @@ class AcceptCharsetValidHeader(AcceptCharset):
For this class, it always returns ``True``.
"""
+
return True
__nonzero__ = __bool__ # Python 2
@@ -1913,9 +1965,11 @@ class AcceptCharsetValidHeader(AcceptCharset):
"will change in the future to better conform to the RFC.",
DeprecationWarning,
)
- for mask, quality in self._parsed_nonzero:
+
+ for mask, _quality in self._parsed_nonzero:
if self._old_match(mask, offer):
return True
+
return False
def __iter__(self):
@@ -1943,8 +1997,11 @@ class AcceptCharsetValidHeader(AcceptCharset):
"future.",
DeprecationWarning,
)
- for m, q in sorted(self._parsed_nonzero, key=lambda i: i[1], reverse=True):
- yield m
+
+ for mask, _quality in sorted(
+ self._parsed_nonzero, key=lambda i: i[1], reverse=True
+ ):
+ yield mask
def __radd__(self, other):
"""
@@ -1952,6 +2009,7 @@ class AcceptCharsetValidHeader(AcceptCharset):
See the docstring for :meth:`AcceptCharsetValidHeader.__add__`.
"""
+
return self._add_instance_and_non_accept_charset_type(
instance=self, other=other, instance_on_the_right=True
)
@@ -2194,9 +2252,9 @@ class AcceptCharsetValidHeader(AcceptCharset):
DeprecationWarning,
)
bestq = 0
- for mask, q in self.parsed:
+ for mask, quality in self.parsed:
if self._old_match(mask, offer):
- bestq = max(bestq, q)
+ bestq = max(bestq, quality)
return bestq or None
@@ -2436,7 +2494,7 @@ class AcceptCharsetNoHeader(_AcceptCharsetInvalidOrNoHeader):
* a ``str`` header value
* a ``dict``, where keys are charsets and values are qvalues
* a ``tuple`` or ``list``, where each item is a charset ``str`` or a
- ``tuple`` or ``list`` (charset, qvalue) pair (``str``\ s and pairs
+ ``tuple`` or ``list`` (charset, qvalue) pair (``str`` and pairs
can be mixed within the ``tuple`` or ``list``)
* an :class:`AcceptCharsetValidHeader`, :class:`AcceptCharsetNoHeader`,
or :class:`AcceptCharsetInvalidHeader` instance
@@ -2474,6 +2532,7 @@ class AcceptCharsetNoHeader(_AcceptCharsetInvalidOrNoHeader):
def __str__(self):
"""Return the ``str`` ``'<no header in request>'``."""
+
return "<no header in request>"
def _add_instance_and_non_accept_charset_type(self, instance, other):
@@ -2509,6 +2568,7 @@ class AcceptCharsetInvalidHeader(_AcceptCharsetInvalidOrNoHeader):
@property
def header_value(self):
"""(``str`` or ``None``) The header value."""
+
return self._header_value
@property
@@ -2518,6 +2578,7 @@ class AcceptCharsetInvalidHeader(_AcceptCharsetInvalidOrNoHeader):
As the header is invalid and cannot be parsed, this is ``None``.
"""
+
return self._parsed
def __init__(self, header_value):
@@ -2553,6 +2614,7 @@ class AcceptCharsetInvalidHeader(_AcceptCharsetInvalidOrNoHeader):
invalid header value, or an :class:`AcceptCharsetInvalidHeader`
instance, a new :class:`AcceptCharsetNoHeader` instance is returned.
"""
+
if isinstance(other, AcceptCharsetValidHeader):
return AcceptCharsetValidHeader(header_value=other.header_value)
@@ -2569,6 +2631,7 @@ class AcceptCharsetInvalidHeader(_AcceptCharsetInvalidOrNoHeader):
See the docstring for :meth:`AcceptCharsetValidHeader.__add__`.
"""
+
return self._add_instance_and_non_accept_charset_type(
instance=self, other=other, instance_on_the_right=True
)
@@ -2581,6 +2644,7 @@ class AcceptCharsetInvalidHeader(_AcceptCharsetInvalidOrNoHeader):
def __str__(self):
"""Return the ``str`` ``'<invalid header value>'``."""
+
return "<invalid header value>"
def _add_instance_and_non_accept_charset_type(
@@ -2611,6 +2675,7 @@ def create_accept_charset_header(header_value):
| If `header_value` is an invalid ``Accept-Charset`` header, an
:class:`AcceptCharsetInvalidHeader` instance.
"""
+
if header_value is None:
return AcceptCharsetNoHeader()
try:
@@ -2635,6 +2700,7 @@ def accept_charset_property():
def fget(request):
"""Get an object representing the header in the request."""
+
return create_accept_charset_header(
header_value=request.environ.get(ENVIRON_KEY)
)
@@ -2655,6 +2721,7 @@ def accept_charset_property():
or :class:`AcceptCharsetInvalidHeader` instance
* object of any other type that returns a value for ``__str__``
"""
+
if value is None or isinstance(value, AcceptCharsetNoHeader):
fdel(request=request)
else:
@@ -2705,8 +2772,10 @@ class AcceptEncoding(object):
else:
if hasattr(value, "items"):
value = sorted(value.items(), key=lambda item: item[1], reverse=True)
+
if isinstance(value, (tuple, list)):
result = []
+
for item in value:
if isinstance(item, (tuple, list)):
item = _item_qvalue_pair_to_header_element(pair=item)
@@ -2714,6 +2783,7 @@ class AcceptEncoding(object):
header_str = ", ".join(result)
else:
header_str = str(value)
+
return header_str
@classmethod
@@ -2731,6 +2801,7 @@ class AcceptEncoding(object):
# Using Python stdlib's `re` module, there is currently no way to check
# the match *and* get all the groups using the same regex, so we have
# to use one regex to check the match, and another to get the groups.
+
if cls.accept_encoding_compiled_re.match(value) is None:
raise ValueError("Invalid value for an Accept-Encoding header.")
@@ -2759,6 +2830,7 @@ class AcceptEncodingValidHeader(AcceptEncoding):
@property
def header_value(self):
"""(``str`` or ``None``) The header value."""
+
return self._header_value
@property
@@ -2773,6 +2845,7 @@ class AcceptEncodingValidHeader(AcceptEncoding):
*qvalue* (``float``) is the quality value of the codings.
"""
+
return self._parsed
def __init__(self, header_value):
@@ -2820,6 +2893,7 @@ class AcceptEncodingValidHeader(AcceptEncoding):
:class:`AcceptEncodingValidHeader` instance with the same header value
as ``self`` is returned.
"""
+
if isinstance(other, AcceptEncodingValidHeader):
if other.header_value == "":
return self.__class__(header_value=self.header_value)
@@ -2845,6 +2919,7 @@ class AcceptEncodingValidHeader(AcceptEncoding):
For this class, it always returns ``True``.
"""
+
return True
__nonzero__ = __bool__ # Python 2
@@ -2880,7 +2955,8 @@ class AcceptEncodingValidHeader(AcceptEncoding):
"will change in the future to better conform to the RFC.",
DeprecationWarning,
)
- for mask, quality in self._parsed_nonzero:
+
+ for mask, _quality in self._parsed_nonzero:
if self._old_match(mask, offer):
return True
@@ -2911,8 +2987,10 @@ class AcceptEncodingValidHeader(AcceptEncoding):
DeprecationWarning,
)
- for m, q in sorted(self._parsed_nonzero, key=lambda i: i[1], reverse=True):
- yield m
+ for mask, _quality in sorted(
+ self._parsed_nonzero, key=lambda i: i[1], reverse=True
+ ):
+ yield mask
def __radd__(self, other):
"""
@@ -2920,6 +2998,7 @@ class AcceptEncodingValidHeader(AcceptEncoding):
See the docstring for :meth:`AcceptEncodingValidHeader.__add__`.
"""
+
return self._add_instance_and_non_accept_encoding_type(
instance=self, other=other, instance_on_the_right=True
)
@@ -3470,6 +3549,7 @@ class AcceptEncodingNoHeader(_AcceptEncodingInvalidOrNoHeader):
def __str__(self):
"""Return the ``str`` ``'<no header in request>'``."""
+
return "<no header in request>"
def _add_instance_and_non_accept_encoding_type(self, instance, other):
@@ -3504,6 +3584,7 @@ class AcceptEncodingInvalidHeader(_AcceptEncodingInvalidOrNoHeader):
@property
def header_value(self):
"""(``str`` or ``None``) The header value."""
+
return self._header_value
@property
@@ -3513,6 +3594,7 @@ class AcceptEncodingInvalidHeader(_AcceptEncodingInvalidOrNoHeader):
As the header is invalid and cannot be parsed, this is ``None``.
"""
+
return self._parsed
def __init__(self, header_value):
@@ -3550,6 +3632,7 @@ class AcceptEncodingInvalidHeader(_AcceptEncodingInvalidOrNoHeader):
invalid header value, or an :class:`AcceptEncodingInvalidHeader`
instance, a new :class:`AcceptEncodingNoHeader` instance is returned.
"""
+
if isinstance(other, AcceptEncodingValidHeader):
return AcceptEncodingValidHeader(header_value=other.header_value)
@@ -3566,6 +3649,7 @@ class AcceptEncodingInvalidHeader(_AcceptEncodingInvalidOrNoHeader):
See the docstring for :meth:`AcceptEncodingValidHeader.__add__`.
"""
+
return self._add_instance_and_non_accept_encoding_type(
instance=self, other=other, instance_on_the_right=True
)
@@ -3578,6 +3662,7 @@ class AcceptEncodingInvalidHeader(_AcceptEncodingInvalidOrNoHeader):
def __str__(self):
"""Return the ``str`` ``'<invalid header value>'``."""
+
return "<invalid header value>"
def _add_instance_and_non_accept_encoding_type(
@@ -3608,6 +3693,7 @@ def create_accept_encoding_header(header_value):
| If `header_value` is an invalid ``Accept-Encoding`` header, an
:class:`AcceptEncodingInvalidHeader` instance.
"""
+
if header_value is None:
return AcceptEncodingNoHeader()
try:
@@ -3632,6 +3718,7 @@ def accept_encoding_property():
def fget(request):
"""Get an object representing the header in the request."""
+
return create_accept_encoding_header(
header_value=request.environ.get(ENVIRON_KEY)
)
@@ -3654,6 +3741,7 @@ def accept_encoding_property():
:class:`AcceptEncodingInvalidHeader` instance
* object of any other type that returns a value for ``__str__``
"""
+
if value is None or isinstance(value, AcceptEncodingNoHeader):
fdel(request=request)
else:
@@ -3704,8 +3792,10 @@ class AcceptLanguage(object):
else:
if hasattr(value, "items"):
value = sorted(value.items(), key=lambda item: item[1], reverse=True)
+
if isinstance(value, (tuple, list)):
result = []
+
for element in value:
if isinstance(element, (tuple, list)):
element = _item_qvalue_pair_to_header_element(pair=element)
@@ -3713,6 +3803,7 @@ class AcceptLanguage(object):
header_str = ", ".join(result)
else:
header_str = str(value)
+
return header_str
@classmethod
@@ -3730,6 +3821,7 @@ class AcceptLanguage(object):
# Using Python stdlib's `re` module, there is currently no way to check
# the match *and* get all the groups using the same regex, so we have
# to use one regex to check the match, and another to get the groups.
+
if cls.accept_language_compiled_re.match(value) is None:
raise ValueError("Invalid value for an Accept-Language header.")
@@ -3776,6 +3868,7 @@ class AcceptLanguageValidHeader(AcceptLanguage):
@property
def header_value(self):
"""(``str`` or ``None``) The header value."""
+
return self._header_value
@property
@@ -3785,6 +3878,7 @@ class AcceptLanguageValidHeader(AcceptLanguage):
A list of (language range, quality value) tuples.
"""
+
return self._parsed
def __add__(self, other):
@@ -3814,6 +3908,7 @@ class AcceptLanguageValidHeader(AcceptLanguage):
instance, a new :class:`AcceptLanguageValidHeader` instance with the
same header value as ``self`` is returned.
"""
+
if isinstance(other, AcceptLanguageValidHeader):
return create_accept_language_header(
header_value=self.header_value + ", " + other.header_value
@@ -3836,6 +3931,7 @@ class AcceptLanguageValidHeader(AcceptLanguage):
For this class, it always returns ``True``.
"""
+
return True
__bool__ = __nonzero__ # Python 3
@@ -3885,9 +3981,11 @@ class AcceptLanguageValidHeader(AcceptLanguage):
"will change in the future to better conform to the RFC.",
DeprecationWarning,
)
- for mask, quality in self._parsed_nonzero:
+
+ for mask, _quality in self._parsed_nonzero:
if self._old_match(mask, offer):
return True
+
return False
def __iter__(self):
@@ -3916,8 +4014,10 @@ class AcceptLanguageValidHeader(AcceptLanguage):
DeprecationWarning,
)
- for m, q in sorted(self._parsed_nonzero, key=lambda i: i[1], reverse=True):
- yield m
+ for mask, _quality in sorted(
+ self._parsed_nonzero, key=lambda i: i[1], reverse=True
+ ):
+ yield mask
def __radd__(self, other):
"""
@@ -3925,6 +4025,7 @@ class AcceptLanguageValidHeader(AcceptLanguage):
See the docstring for :meth:`AcceptLanguageValidHeader.__add__`.
"""
+
return self._add_instance_and_non_accept_language_type(
instance=self, other=other, instance_on_the_right=True
)
@@ -4207,6 +4308,7 @@ class AcceptLanguageValidHeader(AcceptLanguage):
:rfc:`RFC 7231 <7231>`.
:meth:`AcceptLanguageValidHeader.lookup` is a possible alternative
+
for finding a best match -- it conforms to, and is suggested as a
matching scheme for the ``Accept-Language`` header in, :rfc:`RFC
7231, section 5.3.5 <7231#section-5.3.5>` -- but please be aware
@@ -4217,6 +4319,7 @@ class AcceptLanguageValidHeader(AcceptLanguage):
Each language tag in `offers` is checked against each non-0 range in
the header. If the two are a match according to WebOb's old criterion
+
for a match, the quality value of the match is the qvalue of the
language range from the header multiplied by the server quality value
of the offer (if the server quality value is not supplied, it is 1).
@@ -4424,6 +4527,7 @@ class AcceptLanguageValidHeader(AcceptLanguage):
| The difference between supplying a ``str`` to
`default_tag` and `default` is that `default_tag` is
checked against ``q=0`` ranges in the header to see
+
if it matches one of the ranges specified as not
acceptable, whereas a ``str`` for the `default`
argument is simply returned.
@@ -5002,6 +5106,7 @@ class AcceptLanguageNoHeader(_AcceptLanguageInvalidOrNoHeader):
def __str__(self):
"""Return the ``str`` ``'<no header in request>'``."""
+
return "<no header in request>"
def _add_instance_and_non_accept_language_type(self, instance, other):
@@ -5045,6 +5150,7 @@ class AcceptLanguageInvalidHeader(_AcceptLanguageInvalidOrNoHeader):
@property
def header_value(self):
"""(``str`` or ``None``) The header value."""
+
return self._header_value
@property
@@ -5054,6 +5160,7 @@ class AcceptLanguageInvalidHeader(_AcceptLanguageInvalidOrNoHeader):
As the header is invalid and cannot be parsed, this is ``None``.
"""
+
return self._parsed
def __add__(self, other):
@@ -5082,6 +5189,7 @@ class AcceptLanguageInvalidHeader(_AcceptLanguageInvalidOrNoHeader):
invalid header value, or an :class:`AcceptLanguageInvalidHeader`
instance, a new :class:`AcceptLanguageNoHeader` instance is returned.
"""
+
if isinstance(other, AcceptLanguageValidHeader):
return AcceptLanguageValidHeader(header_value=other.header_value)
@@ -5098,6 +5206,7 @@ class AcceptLanguageInvalidHeader(_AcceptLanguageInvalidOrNoHeader):
See the docstring for :meth:`AcceptLanguageValidHeader.__add__`.
"""
+
return self._add_instance_and_non_accept_language_type(
instance=self, other=other, instance_on_the_right=True
)
@@ -5110,6 +5219,7 @@ class AcceptLanguageInvalidHeader(_AcceptLanguageInvalidOrNoHeader):
def __str__(self):
"""Return the ``str`` ``'<invalid header value>'``."""
+
return "<invalid header value>"
def _add_instance_and_non_accept_language_type(
@@ -5140,6 +5250,7 @@ def create_accept_language_header(header_value):
| If `header_value` is an invalid ``Accept-Language`` header, an
:class:`AcceptLanguageInvalidHeader` instance.
"""
+
if header_value is None:
return AcceptLanguageNoHeader()
try:
@@ -5164,6 +5275,7 @@ def accept_language_property():
def fget(request):
"""Get an object representing the header in the request."""
+
return create_accept_language_header(
header_value=request.environ.get(ENVIRON_KEY)
)
@@ -5185,6 +5297,7 @@ def accept_language_property():
:class:`AcceptLanguageInvalidHeader` instance
* object of any other type that returns a value for ``__str__``
"""
+
if value is None or isinstance(value, AcceptLanguageNoHeader):
fdel(request=request)
else:
diff --git a/src/webob/byterange.py b/src/webob/byterange.py
index 5abb15b..c8c0480 100644
--- a/src/webob/byterange.py
+++ b/src/webob/byterange.py
@@ -8,7 +8,7 @@ _rx_content_range = re.compile(r"bytes (?:(\d+)-(\d+)|[*])/(?:(\d+)|[*])")
class Range(object):
"""
- Represents the Range header.
+ Represents the Range header.
"""
def __init__(self, start, end):
@@ -18,9 +18,9 @@ class Range(object):
def range_for_length(self, length):
"""
- *If* there is only one range, and *if* it is satisfiable by
- the given length, then return a (start, end) non-inclusive range
- of bytes to serve. Otherwise return None
+ *If* there is only one range, and *if* it is satisfiable by
+ the given length, then return a (start, end) non-inclusive range
+ of bytes to serve. Otherwise return None
"""
if length is None:
return None
@@ -37,13 +37,13 @@ class Range(object):
def content_range(self, length):
"""
- Works like range_for_length; returns None or a ContentRange object
+ Works like range_for_length; returns None or a ContentRange object
- You can use it like::
+ You can use it like::
- response.content_range = req.range.content_range(response.content_length)
+ response.content_range = req.range.content_range(response.content_length)
- Though it's still up to you to actually serve that content range!
+ Though it's still up to you to actually serve that content range!
"""
range = self.range_for_length(length)
if range is None:
@@ -68,7 +68,7 @@ class Range(object):
@classmethod
def parse(cls, header):
"""
- Parse the header; may return None if header is invalid
+ Parse the header; may return None if header is invalid
"""
m = _rx_range.match(header or "")
if not m:
@@ -117,16 +117,16 @@ class ContentRange(object):
def __iter__(self):
"""
- Mostly so you can unpack this, like:
+ Mostly so you can unpack this, like:
- start, stop, length = res.content_range
+ start, stop, length = res.content_range
"""
return iter([self.start, self.stop, self.length])
@classmethod
def parse(cls, value):
"""
- Parse the header. May return None if it cannot parse.
+ Parse the header. May return None if it cannot parse.
"""
m = _rx_content_range.match(value or "")
if not m:
diff --git a/src/webob/client.py b/src/webob/client.py
index f669d37..0ba9654 100644
--- a/src/webob/client.py
+++ b/src/webob/client.py
@@ -80,8 +80,8 @@ class SendRequest:
content_length = int(environ.get("CONTENT_LENGTH", "0"))
except ValueError:
content_length = 0
- ## FIXME: there is no streaming of the body, and that might be useful
- ## in some cases
+ # FIXME: there is no streaming of the body, and that might be useful
+ # in some cases
if content_length:
body = environ["wsgi.input"].read(content_length)
else:
@@ -158,7 +158,7 @@ class SendRequest:
else: # pragma: no cover
try:
header, value = full_header.split(":", 1)
- except:
+ except Exception:
raise ValueError("Invalid header: %r" % (full_header,))
value = value.strip()
if "\n" in value or "\r\n" in value: # pragma: no cover
diff --git a/src/webob/compat.py b/src/webob/compat.py
index 357fc83..9d343a0 100644
--- a/src/webob/compat.py
+++ b/src/webob/compat.py
@@ -1,5 +1,7 @@
# code stolen from "six"
+# flake8: noqa
+
import sys
import types
from cgi import parse_header
@@ -104,10 +106,10 @@ if PY3:
else:
def iteritems_(d):
- return d.iteritems()
+ return d.iteritems() # noqa: B301
def itervalues_(d):
- return d.itervalues()
+ return d.itervalues() # noqa: B301
if PY3: # pragma: no cover
diff --git a/src/webob/cookies.py b/src/webob/cookies.py
index 50429cc..b3343fb 100644
--- a/src/webob/cookies.py
+++ b/src/webob/cookies.py
@@ -46,20 +46,27 @@ class RequestCookies(MutableMapping):
env = self._environ
header = env.get("HTTP_COOKIE", "")
cache, cache_header = env.get(self._cache_key, ({}, None))
+
if cache_header == header:
return cache
- d = lambda b: b.decode("utf8")
+
+ def d(b):
+ return b.decode("utf8")
+
cache = dict((d(k), d(v)) for k, v in parse_cookie(header))
env[self._cache_key] = (cache, header)
+
return cache
def _mutate_header(self, name, value):
header = self._environ.get("HTTP_COOKIE")
had_header = header is not None
header = header or ""
+
if not PY2:
header = header.encode("latin-1")
bytes_name = bytes_(name, "ascii")
+
if value is None:
replacement = None
else:
@@ -67,15 +74,19 @@ class RequestCookies(MutableMapping):
replacement = bytes_name + b"=" + bytes_val
matches = _rx_cookie.finditer(header)
found = False
+
for match in matches:
start, end = match.span()
match_name = match.group(1)
+
if match_name == bytes_name:
found = True
+
if replacement is None: # remove value
header = header[:start].rstrip(b" ;") + header[end:]
else: # replace value
header = header[:start] + replacement + header[end:]
+
break
else:
if replacement is not None:
@@ -94,20 +105,25 @@ class RequestCookies(MutableMapping):
def _valid_cookie_name(self, name):
if not isinstance(name, string_types):
raise TypeError(name, "cookie name must be a string")
+
if not isinstance(name, text_type):
name = text_(name, "utf-8")
try:
bytes_cookie_name = bytes_(name, "ascii")
except UnicodeEncodeError:
raise TypeError("cookie name must be encodable to ascii")
+
if not _valid_cookie_name(bytes_cookie_name):
raise TypeError("cookie name must be valid according to RFC 6265")
+
return name
def __setitem__(self, name, value):
name = self._valid_cookie_name(name)
+
if not isinstance(value, string_types):
raise ValueError(value, "cookie value must be a string")
+
if not isinstance(value, text_type):
try:
value = text_(value, "utf-8")
@@ -124,6 +140,7 @@ class RequestCookies(MutableMapping):
def __delitem__(self, name):
name = self._valid_cookie_name(name)
found = self._mutate_header(name, None)
+
if not found:
raise KeyError(name)
@@ -139,13 +156,13 @@ class RequestCookies(MutableMapping):
if PY2:
def iterkeys(self):
- return self._cache.iterkeys()
+ return self._cache.iterkeys() # noqa: B301
def itervalues(self):
- return self._cache.itervalues()
+ return self._cache.itervalues() # noqa: B301
def iteritems(self):
- return self._cache.iteritems()
+ return self._cache.iteritems() # noqa: B301
def __contains__(self, name):
return name in self._cache
@@ -170,6 +187,7 @@ class Cookie(dict):
def load(self, data):
morsel = {}
+
for key, val in _parse_cookie(data):
if key.lower() in _c_keys:
morsel[key] = val
@@ -179,10 +197,12 @@ class Cookie(dict):
def add(self, key, val):
if not isinstance(key, bytes):
key = key.encode("ascii", "replace")
+
if not _valid_cookie_name(key):
return {}
r = Morsel(key, val)
dict.__setitem__(self, key, r)
+
return r
__setitem__ = add
@@ -205,6 +225,7 @@ class Cookie(dict):
def _parse_cookie(data):
if not PY2:
data = data.encode("latin-1")
+
for key, val in _rx_cookie.findall(data):
yield key, _unquote(val)
@@ -213,6 +234,7 @@ def parse_cookie(data):
"""
Parse cookies ignoring anything except names and values
"""
+
return ((k, v) for k, v in _parse_cookie(data) if _valid_cookie_name(k))
@@ -228,6 +250,7 @@ def serialize_max_age(v):
v = str(v.seconds + v.days * 24 * 60 * 60)
elif isinstance(v, int):
v = str(v)
+
return bytes_(v)
@@ -240,11 +263,14 @@ def serialize_cookie_date(v):
return v.encode("ascii")
elif isinstance(v, int):
v = timedelta(seconds=v)
+
if isinstance(v, timedelta):
v = datetime.utcnow() + v
+
if isinstance(v, (datetime, date)):
v = v.timetuple()
r = time.strftime("%%s, %d-%%s-%Y %H:%M:%S GMT", v)
+
return bytes_(r % (weekdays[v[6]], months[v[1]]), "ascii")
@@ -253,6 +279,7 @@ def serialize_samesite(v):
if v.lower() not in (b"strict", b"lax"):
raise ValueError("SameSite must be 'Strict' or 'Lax'")
+
return v
@@ -276,6 +303,7 @@ class Morsel(dict):
def __setitem__(self, k, v):
k = bytes_(k.lower(), "ascii")
+
if k in _c_keys:
dict.__setitem__(self, k, v)
@@ -283,23 +311,30 @@ class Morsel(dict):
result = []
add = result.append
add(self.name + b"=" + _value_quote(self.value))
+
if full:
for k in _c_valkeys:
v = self[k]
+
if v:
info = _c_renames[k]
name = info["name"]
quoter = info["quoter"]
add(name + b"=" + quoter(v))
expires = self[b"expires"]
+
if expires:
add(b"expires=" + expires)
+
if self.secure:
add(b"secure")
+
if self.httponly:
add(b"HttpOnly")
+
if self.samesite:
add(b"SameSite=" + self.samesite)
+
return native_(b"; ".join(result), "ascii")
__str__ = serialize
@@ -340,8 +375,10 @@ _b_quote_mark = '"' if PY2 else ord('"')
def _unquote(v):
# assert isinstance(v, bytes)
+
if v and v[0] == v[-1] == _b_quote_mark:
v = v[1:-1]
+
return _rx_unquote.sub(_ch_unquote, v)
@@ -384,6 +421,7 @@ _valid_token_bytes = bytes_(_valid_token_chars)
_escape_noop_chars = _allowed_cookie_chars + " "
_escape_map = dict((chr(i), "\\%03o" % i) for i in range(256))
_escape_map.update(zip(_escape_noop_chars, _escape_noop_chars))
+
if not PY2:
# convert to {int -> bytes}
_escape_map = dict((ord(k), bytes_(v, "ascii")) for k, v in _escape_map.items())
@@ -425,6 +463,7 @@ def _value_quote(v):
# invalid characters in our value)
leftovers = v.translate(None, _allowed_cookie_bytes)
+
if leftovers:
__warn_or_raise(
"Cookie value contains invalid bytes: (%r). Future versions "
@@ -434,6 +473,7 @@ def _value_quote(v):
"Invalid characters in cookie value",
)
# raise ValueError('Invalid characters in cookie value')
+
return b'"' + b"".join(map(_escape_char, v)) + b'"'
return v
@@ -512,6 +552,7 @@ def make_cookie(
"""
# We are deleting the cookie, override max_age and expires
+
if value is None:
value = b""
# Note that the max-age value of zero is technically contraspec;
@@ -541,20 +582,28 @@ def make_cookie(
if domain is not None:
morsel.domain = bytes_(domain)
+
if path is not None:
morsel.path = bytes_(path)
+
if httponly:
morsel.httponly = True
+
if secure:
morsel.secure = True
+
if max_age is not None:
morsel.max_age = max_age
+
if expires is not None:
morsel.expires = expires
+
if comment is not None:
morsel.comment = bytes_(comment)
+
if samesite is not None:
morsel.samesite = samesite
+
return morsel.serialize()
@@ -567,6 +616,7 @@ class JSONSerializer(object):
def loads(self, bstruct):
# NB: json.loads raises ValueError if no json object can be decoded
# so we don't have to do it explicitly here.
+
return json.loads(text_(bstruct, encoding="utf-8"))
@@ -586,6 +636,7 @@ class Base64Serializer(object):
Returns a bytestring.
"""
cstruct = self.serializer.dumps(appstruct) # will be bytes
+
return base64.urlsafe_b64encode(cstruct)
def loads(self, bstruct):
@@ -659,6 +710,7 @@ class SignedSerializer(object):
"""
cstruct = self.serializer.dumps(appstruct) # will be bytes
sig = hmac.new(self.salted_secret, cstruct, self.digestmod).digest()
+
return base64.urlsafe_b64encode(sig + cstruct).rstrip(b"=")
def loads(self, bstruct):
@@ -775,6 +827,7 @@ class CookieProfile(object):
self.serializer,
)
selfish.request = request
+
return selfish
def get_value(self):
@@ -820,6 +873,7 @@ class CookieProfile(object):
samesite=samesite,
)
response.headerlist.extend(cookies)
+
return response
def get_headers(
@@ -837,6 +891,7 @@ class CookieProfile(object):
Returns a list of headers that should be set for the cookies to
be correctly tracked.
"""
+
if value is None:
max_age = 0
bstruct = None
@@ -871,6 +926,7 @@ class CookieProfile(object):
"""
# If the user doesn't provide values, grab the defaults
+
if domains is _default:
domains = self.domains
@@ -890,6 +946,7 @@ class CookieProfile(object):
samesite = self.samesite
# Length selected based upon http://browsercookielimits.x64.me
+
if value is not None and len(value) > 4093:
raise ValueError(
"Cookie value is too long to store (%s bytes)" % len(value)
@@ -1033,4 +1090,5 @@ class SignedCookieProfile(CookieProfile):
self.original_serializer,
)
selfish.request = request
+
return selfish
diff --git a/src/webob/datetime_utils.py b/src/webob/datetime_utils.py
index c0958df..8cbedbe 100644
--- a/src/webob/datetime_utils.py
+++ b/src/webob/datetime_utils.py
@@ -66,7 +66,7 @@ def parse_date(value):
return None
try:
value = native_(value)
- except:
+ except Exception:
return None
t = parsedate_tz(value)
if t is None:
diff --git a/src/webob/dec.py b/src/webob/dec.py
index 044ebc0..def23db 100644
--- a/src/webob/dec.py
+++ b/src/webob/dec.py
@@ -128,7 +128,7 @@ class wsgify(object):
except HTTPException as exc:
resp = exc
if resp is None:
- ## FIXME: I'm not sure what this should be?
+ # FIXME: I'm not sure what this should be?
resp = req.response
if isinstance(resp, text_type):
resp = bytes_(resp, req.charset)
diff --git a/src/webob/descriptors.py b/src/webob/descriptors.py
index 5442044..ede7436 100644
--- a/src/webob/descriptors.py
+++ b/src/webob/descriptors.py
@@ -207,9 +207,9 @@ def date_header(header, rfc_section):
return converter_date(header_getter(header, rfc_section))
-########################
-## Converter functions
-########################
+#######################
+# Converter functions
+#######################
_rx_etag = re.compile(r'(?:^|\s)(W/)?"((?:\\"|.)*?)"')
diff --git a/src/webob/exc.py b/src/webob/exc.py
index b57ba1a..d6ae1ec 100644
--- a/src/webob/exc.py
+++ b/src/webob/exc.py
@@ -200,13 +200,16 @@ def lazify(func):
def no_escape(value):
if value is None:
return ""
+
if not isinstance(value, text_type):
if hasattr(value, "__unicode__"):
value = value.__unicode__()
+
if isinstance(value, bytes):
value = text_(value, "utf-8")
else:
value = text_type(value)
+
return value
@@ -216,6 +219,7 @@ def strip_tags(value):
value = br_re.sub("\n", value)
value = comment_re.sub("", value)
value = tag_re.sub("", value)
+
return value
@@ -230,7 +234,7 @@ class HTTPException(Exception):
class WSGIHTTPException(Response, HTTPException):
- ## You should set in subclasses:
+ # You should set in subclasses:
# code = 200
# title = 'OK'
# explanation = 'why this happens'
@@ -266,7 +270,7 @@ ${body}"""
</html>"""
)
- ## Set this to True for responses that should have no request body
+ # Set this to True for responses that should have no request body
empty_body = False
def __init__(
@@ -280,16 +284,20 @@ ${body}"""
):
Response.__init__(self, status="%s %s" % (self.code, self.title), **kw)
Exception.__init__(self, detail)
+
if headers:
self.headers.extend(headers)
self.detail = detail
self.comment = comment
+
if body_template is not None:
self.body_template = body_template
self.body_template_obj = Template(body_template)
+
if self.empty_body:
del self.content_type
del self.content_length
+
if json_formatter is not None:
self.json_formatter = json_formatter
@@ -303,28 +311,35 @@ ${body}"""
"detail": escape(self.detail or ""),
"comment": escape(self.comment or ""),
}
+
if self.comment:
args["html_comment"] = "<!-- %s -->" % escape(self.comment)
else:
args["html_comment"] = ""
+
if WSGIHTTPException.body_template_obj is not self.body_template_obj:
# Custom template; add headers to args
+
for k, v in environ.items():
args[k] = escape(v)
+
for k, v in self.headers.items():
args[k.lower()] = escape(v)
t_obj = self.body_template_obj
+
return t_obj.safe_substitute(args)
def plain_body(self, environ):
body = self._make_body(environ, no_escape)
body = strip_tags(body)
+
return self.plain_template_obj.substitute(
status=self.status, title=self.title, body=body
)
def html_body(self, environ):
body = self._make_body(environ, html_escape)
+
return self.html_template_obj.substitute(status=self.status, body=body)
def json_formatter(self, body, status, title, environ):
@@ -335,6 +350,7 @@ ${body}"""
jsonbody = self.json_formatter(
body=body, status=self.status, title=self.title, environ=environ
)
+
return json.dumps(jsonbody)
def generate_response(self, environ, start_response):
@@ -361,16 +377,20 @@ ${body}"""
body, status=self.status, headerlist=headerlist, content_type=content_type
)
resp.content_type = content_type
+
return resp(environ, start_response)
def __call__(self, environ, start_response):
is_head = environ["REQUEST_METHOD"] == "HEAD"
+
if self.has_body or self.empty_body or is_head:
app_iter = Response.__call__(self, environ, start_response)
else:
app_iter = self.generate_response(environ, start_response)
+
if is_head:
app_iter = []
+
return app_iter
@property
@@ -410,9 +430,9 @@ class HTTPOk(WSGIHTTPException):
title = "OK"
-############################################################
-## 2xx success
-############################################################
+###########################################################
+# 2xx success
+###########################################################
class HTTPCreated(HTTPOk):
@@ -505,9 +525,9 @@ class HTTPPartialContent(HTTPOk):
title = "Partial Content"
-############################################################
-## 3xx redirection
-############################################################
+###########################################################
+# 3xx redirection
+###########################################################
class _HTTPMove(HTTPRedirection):
@@ -547,11 +567,13 @@ ${html_comment}"""
super(_HTTPMove, self).__init__(
detail=detail, headers=headers, comment=comment, body_template=body_template
)
+
if location is not None:
if "\n" in location or "\r" in location:
raise ValueError("Control characters are not allowed in location")
self.location = location
+
if add_slash:
raise TypeError(
"You can only provide one of the arguments location "
@@ -561,13 +583,16 @@ ${html_comment}"""
def __call__(self, environ, start_response):
req = Request(environ)
+
if self.add_slash:
url = req.path_url
url += "/"
+
if req.environ.get("QUERY_STRING"):
url += "?" + req.environ["QUERY_STRING"]
self.location = url
self.location = urlparse.urljoin(req.path_url, self.location)
+
return super(_HTTPMove, self).__call__(environ, start_response)
@@ -696,9 +721,9 @@ class HTTPPermanentRedirect(_HTTPMove):
title = "Permanent Redirect"
-############################################################
-## 4xx client error
-############################################################
+###########################################################
+# 4xx client error
+###########################################################
class HTTPClientError(HTTPError):
@@ -1021,7 +1046,7 @@ class HTTPUnprocessableEntity(HTTPClientError):
code: 422, title: Unprocessable Entity
"""
- ## Note: from WebDAV
+ # Note: from WebDAV
code = 422
title = "Unprocessable Entity"
explanation = "Unable to process the contained instructions"
@@ -1036,7 +1061,7 @@ class HTTPLocked(HTTPClientError):
code: 423, title: Locked
"""
- ## Note: from WebDAV
+ # Note: from WebDAV
code = 423
title = "Locked"
explanation = "The resource is locked"
@@ -1052,7 +1077,7 @@ class HTTPFailedDependency(HTTPClientError):
code: 424, title: Failed Dependency
"""
- ## Note: from WebDAV
+ # Note: from WebDAV
code = 424
title = "Failed Dependency"
explanation = (
@@ -1132,16 +1157,16 @@ class HTTPUnavailableForLegalReasons(HTTPClientError):
explanation = "The resource is not available due to legal reasons."
-############################################################
-## 5xx Server Error
-############################################################
-# Response status codes beginning with the digit "5" indicate cases in
-# which the server is aware that it has erred or is incapable of
-# performing the request. Except when responding to a HEAD request, the
-# server SHOULD include an entity containing an explanation of the error
-# situation, and whether it is a temporary or permanent condition. User
-# agents SHOULD display any included entity to the user. These response
-# codes are applicable to any request method.
+###########################################################
+# 5xx Server Error
+###########################################################
+# Response status codes beginning with the digit "5" indicate cases in which
+# the server is aware that it has erred or is incapable of performing the
+# request. Except when responding to a HEAD request, the server SHOULD include
+# an entity containing an explanation of the error situation, and whether it
+# is a temporary or permanent condition. User agents SHOULD display any
+# included entity to the user. These response codes are applicable to any
+# request method.
class HTTPServerError(HTTPError):
@@ -1304,6 +1329,7 @@ class HTTPExceptionMiddleware(object):
def repl_start_response(status, headers, exc_info=None):
if exc_info is None:
exc_info = parent_exc_info
+
return start_response(status, headers, exc_info)
return parent_exc_info[1](environ, repl_start_response)
@@ -1317,6 +1343,7 @@ except ImportError: # pragma: no cover
else: # pragma: no cover
for name in dir(httpexceptions):
obj = globals().get(name)
+
if (
obj
and isinstance(obj, type)
@@ -1329,6 +1356,7 @@ else: # pragma: no cover
__all__ = ["HTTPExceptionMiddleware", "status_map"]
status_map = {}
+
for name, value in list(globals().items()):
if (
isinstance(value, (type, class_types))
@@ -1336,6 +1364,7 @@ for name, value in list(globals().items()):
and not name.startswith("_")
):
__all__.append(name)
+
if all(
(
getattr(value, "code", None),
@@ -1346,6 +1375,7 @@ for name, value in list(globals().items()):
)
):
status_map[value.code] = value
+
if hasattr(value, "explanation"):
value.explanation = " ".join(value.explanation.strip().split())
del name, value
diff --git a/src/webob/headers.py b/src/webob/headers.py
index 5edf44f..2eaaa8b 100644
--- a/src/webob/headers.py
+++ b/src/webob/headers.py
@@ -52,7 +52,7 @@ class ResponseHeaders(MultiDict):
def __contains__(self, key):
key = key.lower()
- for k, v in self._items:
+ for k, _ in self._items:
if k.lower() == key:
return True
return False
diff --git a/src/webob/multidict.py b/src/webob/multidict.py
index 83cd251..368397f 100644
--- a/src/webob/multidict.py
+++ b/src/webob/multidict.py
@@ -24,9 +24,10 @@ class MultiDict(MutableMapping):
raise TypeError(
"MultiDict can only be called with one positional " "argument"
)
+
if args:
if hasattr(args[0], "iteritems"):
- items = list(args[0].iteritems())
+ items = list(args[0].iteritems()) # noqa: B301
elif hasattr(args[0], "items"):
items = list(args[0].items())
else:
@@ -34,6 +35,7 @@ class MultiDict(MutableMapping):
self._items = items
else:
self._items = []
+
if kw:
self._items.extend(kw.items())
@@ -42,6 +44,7 @@ class MultiDict(MutableMapping):
"""
Create a dict that is a view on the given list
"""
+
if not isinstance(lst, list):
raise TypeError(
"%s.view_list(obj) takes only actual list objects, not %r"
@@ -49,6 +52,7 @@ class MultiDict(MutableMapping):
)
obj = cls()
obj._items = lst
+
return obj
@classmethod
@@ -58,6 +62,7 @@ class MultiDict(MutableMapping):
"""
obj = cls()
# fs.list can be None when there's nothing to parse
+
for field in fs.list or ():
charset = field.type_options.get("charset", "utf8")
transfer_encoding = field.headers.get("Content-Transfer-Encoding", None)
@@ -65,27 +70,40 @@ class MultiDict(MutableMapping):
"base64": binascii.a2b_base64,
"quoted-printable": binascii.a2b_qp,
}
+
if not PY2:
if charset == "utf8":
- decode = lambda b: b
+
+ def decode(b):
+ return b
+
else:
- decode = lambda b: b.encode("utf8").decode(charset)
+
+ def decode(b):
+ return b.encode("utf8").decode(charset)
+
else:
- decode = lambda b: b.decode(charset)
+
+ def decode(b):
+ return b.decode(charset)
+
if field.filename:
field.filename = decode(field.filename)
obj.add(field.name, field)
else:
value = field.value
+
if transfer_encoding in supported_transfer_encoding:
if not PY2:
# binascii accepts bytes
value = value.encode("utf8")
value = supported_transfer_encoding[transfer_encoding](value)
+
if not PY2:
# binascii returns bytes
value = value.decode("utf8")
obj.add(field.name, decode(value))
+
return obj
def __getitem__(self, key):
@@ -111,6 +129,7 @@ class MultiDict(MutableMapping):
"""
Return a list of all values matching the key (may be an empty list)
"""
+
return [v for k, v in self._items if k == key]
def getone(self, key):
@@ -119,10 +138,13 @@ class MultiDict(MutableMapping):
values were found.
"""
v = self.getall(key)
+
if not v:
raise KeyError("Key not found: %r" % key)
+
if len(v) > 1:
raise KeyError("Multiple values match %r: %r" % (key, v))
+
return v[0]
def mixed(self):
@@ -135,10 +157,12 @@ class MultiDict(MutableMapping):
"""
result = {}
multi = {}
+
for key, value in self.items():
if key in result:
# We do this to not clobber any lists that are
# *actual* values in this dictionary:
+
if key in multi:
result[key].append(value)
else:
@@ -146,6 +170,7 @@ class MultiDict(MutableMapping):
multi[key] = None
else:
result[key] = value
+
return result
def dict_of_lists(self):
@@ -153,24 +178,29 @@ class MultiDict(MutableMapping):
Returns a dictionary where each key is associated with a list of values.
"""
r = {}
+
for key, val in self.items():
r.setdefault(key, []).append(val)
+
return r
def __delitem__(self, key):
items = self._items
found = False
+
for i in range(len(items) - 1, -1, -1):
if items[i][0] == key:
del items[i]
found = True
+
if not found:
raise KeyError(key)
def __contains__(self, key):
- for k, v in self._items:
+ for k, _ in self._items:
if k == key:
return True
+
return False
has_key = __contains__
@@ -186,6 +216,7 @@ class MultiDict(MutableMapping):
if key == k:
return v
self._items.append((key, default))
+
return default
def pop(self, key, *args):
@@ -193,11 +224,14 @@ class MultiDict(MutableMapping):
raise TypeError(
"pop expected at most 2 arguments, got %s" % repr(1 + len(args))
)
+
for i in range(len(self._items)):
if self._items[i][0] == key:
v = self._items[i][1]
del self._items[i]
+
return v
+
if args:
return args[0]
else:
@@ -209,6 +243,7 @@ class MultiDict(MutableMapping):
def update(self, *args, **kw):
if args:
lst = args[0]
+
if len(lst) != len(dict(lst)):
# this does not catch the cases where we overwrite existing
# keys, but those would produce too many warning
@@ -230,22 +265,24 @@ class MultiDict(MutableMapping):
else:
for k, v in other:
self._items.append((k, v))
+
if kwargs:
self.update(kwargs)
def __repr__(self):
items = map("(%r, %r)".__mod__, _hide_passwd(self.items()))
+
return "%s([%s])" % (self.__class__.__name__, ", ".join(items))
def __len__(self):
return len(self._items)
- ##
- ## All the iteration:
- ##
+ #
+ # All the iteration:
+ #
def iterkeys(self):
- for k, v in self._items:
+ for k, _ in self._items:
yield k
if PY2:
@@ -270,7 +307,7 @@ class MultiDict(MutableMapping):
items = iteritems
def itervalues(self):
- for k, v in self._items:
+ for _, v in self._items:
yield v
if PY2:
@@ -294,7 +331,9 @@ class GetDict(MultiDict):
MultiDict.__init__(self, data)
def on_change(self):
- e = lambda t: t.encode("utf8")
+ def e(t):
+ return t.encode("utf8")
+
data = [(e(k), e(v)) for k, v in self.items()]
qs = url_encode(data)
self.env["QUERY_STRING"] = qs
@@ -319,16 +358,19 @@ class GetDict(MultiDict):
def setdefault(self, key, default=None):
result = MultiDict.setdefault(self, key, default)
self.on_change()
+
return result
def pop(self, key, *args):
result = MultiDict.pop(self, key, *args)
self.on_change()
+
return result
def popitem(self):
result = MultiDict.popitem(self)
self.on_change()
+
return result
def update(self, *args, **kwargs):
@@ -342,10 +384,12 @@ class GetDict(MultiDict):
def __repr__(self):
items = map("(%r, %r)".__mod__, _hide_passwd(self.items()))
# TODO: GET -> GetDict
+
return "GET([%s])" % (", ".join(items))
def copy(self):
# Copies shouldn't be tracked
+
return MultiDict(self)
@@ -360,6 +404,7 @@ class NestedMultiDict(MultiDict):
def __getitem__(self, key):
for d in self.dicts:
value = d.get(key, _dummy)
+
if value is not _dummy:
return value
raise KeyError(key)
@@ -378,8 +423,10 @@ class NestedMultiDict(MultiDict):
def getall(self, key):
result = []
+
for d in self.dicts:
result.extend(d.getall(key))
+
return result
# Inherited:
@@ -394,20 +441,24 @@ class NestedMultiDict(MultiDict):
for d in self.dicts:
if key in d:
return True
+
return False
has_key = __contains__
def __len__(self):
v = 0
+
for d in self.dicts:
v += len(d)
+
return v
def __nonzero__(self):
for d in self.dicts:
if d:
return True
+
return False
def iteritems(self):
@@ -418,7 +469,7 @@ class NestedMultiDict(MultiDict):
if PY2:
def items(self):
- return list(self.iteritems())
+ return list(self.iteritems()) # noqa: B301
else:
items = iteritems
@@ -431,7 +482,7 @@ class NestedMultiDict(MultiDict):
if PY2:
def values(self):
- return list(self.itervalues())
+ return list(self.itervalues()) # noqa: B301
else:
values = itervalues
@@ -446,7 +497,7 @@ class NestedMultiDict(MultiDict):
if PY2:
def keys(self):
- return list(self.iterkeys())
+ return list(self.iterkeys()) # noqa: B301
else:
keys = iterkeys
@@ -514,7 +565,7 @@ class NoVars(object):
if PY2:
def __cmp__(self, other):
- return cmp({}, other)
+ return cmp({}, other) # noqa: F821
def keys(self):
return []
diff --git a/src/webob/request.py b/src/webob/request.py
index 64fdd73..96fb16c 100644
--- a/src/webob/request.py
+++ b/src/webob/request.py
@@ -71,6 +71,7 @@ class _NoDefault:
NoDefault = _NoDefault()
+DEFAULT = object()
PATH_SAFE = "/~!$&'()*+,;=:@"
@@ -1422,7 +1423,7 @@ class LegacyRequest(BaseRequest):
class AdhocAttrMixin(object):
_setattr_stacklevel = 3
- def __setattr__(self, attr, value, DEFAULT=object()):
+ def __setattr__(self, attr, value, DEFAULT=DEFAULT):
if getattr(self.__class__, attr, DEFAULT) is not DEFAULT or attr.startswith(
"_"
):
@@ -1430,13 +1431,13 @@ class AdhocAttrMixin(object):
else:
self.environ.setdefault("webob.adhoc_attrs", {})[attr] = value
- def __getattr__(self, attr, DEFAULT=object()):
+ def __getattr__(self, attr, DEFAULT=DEFAULT):
try:
return self.environ["webob.adhoc_attrs"][attr]
except KeyError:
raise AttributeError(attr)
- def __delattr__(self, attr, DEFAULT=object()):
+ def __delattr__(self, attr, DEFAULT=DEFAULT):
if getattr(self.__class__, attr, DEFAULT) is not DEFAULT:
return object.__delattr__(self, attr)
try:
@@ -1488,7 +1489,7 @@ def environ_from_url(path):
"wsgi.multithread": False,
"wsgi.multiprocess": False,
"wsgi.run_once": False,
- #'webob.is_body_seekable': True,
+ 'webob.is_body_seekable': True,
}
return env
@@ -1503,7 +1504,7 @@ def environ_add_POST(env, data, content_type=None):
has_files = False
if hasattr(data, "items"):
data = list(data.items())
- for k, v in data:
+ for _, v in data:
if isinstance(v, (tuple, list)):
has_files = True
break
diff --git a/src/webob/response.py b/src/webob/response.py
index b6f25f0..8c8ade6 100644
--- a/src/webob/response.py
+++ b/src/webob/response.py
@@ -613,8 +613,8 @@ class Response(object):
"""
if not self.charset and not self.default_body_encoding:
raise AttributeError(
- "You cannot access Response.text unless charset or default_body_encoding"
- " is set"
+ "You cannot access Response.text unless charset or "
+ "default_body_encoding is set"
)
decoding = self.charset or self.default_body_encoding
body = self.body
@@ -623,8 +623,8 @@ class Response(object):
def _text__set(self, value):
if not self.charset and not self.default_body_encoding:
raise AttributeError(
- "You cannot access Response.text unless charset or default_body_encoding"
- " is set"
+ "You cannot access Response.text unless charset or "
+ "default_body_encoding is set"
)
if not isinstance(value, text_type):
raise TypeError(
diff --git a/tests/conftest.py b/tests/conftest.py
index 58b3fd1..e84fabe 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -40,7 +40,7 @@ def _make_test_server(app):
)
server.timeout = 5
return server
- except:
+ except BaseException:
if i == 1:
raise
diff --git a/tests/performance_test.py b/tests/performance_test.py
index 182d2f4..4c4917f 100644
--- a/tests/performance_test.py
+++ b/tests/performance_test.py
@@ -1,5 +1,6 @@
#!/usr/bin/env python
from webob.response import Response
+from webob.compat import PY2
def make_middleware(app):
@@ -42,7 +43,10 @@ if __name__ == "__main__":
print("Hit ^C to end")
try:
while 1:
- raw_input()
+ if PY2:
+ raw_input() # noqa: F821
+ else:
+ input()
finally:
os.kill(proc.pid, signal.SIGKILL)
else:
diff --git a/tests/test_client_functional.py b/tests/test_client_functional.py
index 31ff40f..d84ef86 100644
--- a/tests/test_client_functional.py
+++ b/tests/test_client_functional.py
@@ -32,7 +32,7 @@ def test_client(serve, client_app=None):
del req.environ["SERVER_NAME"]
del req.environ["SERVER_PORT"]
assert req.send(client_app).status_code == 200
- req.headers["Host"] = server.url.lstrip("http://")
+ req.headers["Host"] = server.url.replace("http://", "")
del req.environ["SERVER_NAME"]
del req.environ["SERVER_PORT"]
resp = req.send(client_app)
diff --git a/tests/test_descriptors.py b/tests/test_descriptors.py
index 1a5294c..9d3eecc 100644
--- a/tests/test_descriptors.py
+++ b/tests/test_descriptors.py
@@ -587,7 +587,7 @@ def test_parse_range_type():
from webob.descriptors import parse_range
val = parse_range("bytes=1-500")
- assert type(val) is type(Range.parse("bytes=1-500"))
+ assert type(val) is type(Range.parse("bytes=1-500")) # noqa: E701
def test_parse_range_values():
@@ -709,7 +709,7 @@ def test_parse_content_range_stop():
def test_serialize_content_range_none():
from webob.descriptors import serialize_content_range
- assert serialize_content_range(None) == "None" ### XXX: Seems wrong
+ assert serialize_content_range(None) == "None" # XXX: Seems wrong
def test_serialize_content_range_emptystr():
diff --git a/tests/test_etag.py b/tests/test_etag.py
index 113c938..f256636 100644
--- a/tests/test_etag.py
+++ b/tests/test_etag.py
@@ -1,5 +1,3 @@
-import pytest
-
from webob.etag import ETagMatcher, IfRange, etag_property
@@ -16,6 +14,7 @@ class Test_etag_properties(object):
self.__dict__.update(**kwargs)
d = Dummy(**kw)
+
return d
def test_fget_missing_key(self):
diff --git a/tests/test_etag_nose.py b/tests/test_etag_nose.py
index 5f780c4..8a8cd5d 100644
--- a/tests/test_etag_nose.py
+++ b/tests/test_etag_nose.py
@@ -1,5 +1,3 @@
-import pytest
-
from webob.etag import IfRange, ETagMatcher
from webob import Response
diff --git a/tests/test_exc.py b/tests/test_exc.py
index e0b5045..35454c9 100644
--- a/tests/test_exc.py
+++ b/tests/test_exc.py
@@ -200,7 +200,7 @@ def test_WSGIHTTPException_respects_accept_text_html():
assert header[1].startswith("text/html")
exc = webob_exc.WSGIHTTPException()
- resp = exc.generate_response(
+ exc.generate_response(
environ={
"wsgi.url_scheme": "HTTP",
"SERVER_NAME": "localhost",
@@ -219,7 +219,7 @@ def test_WSGIHTTPException_respects_accept_text_plain():
assert header[1].startswith("text/plain")
exc = webob_exc.WSGIHTTPException()
- resp = exc.generate_response(
+ exc.generate_response(
environ={
"wsgi.url_scheme": "HTTP",
"SERVER_NAME": "localhost",
@@ -238,7 +238,7 @@ def test_WSGIHTTPException_respects_accept_star_star():
assert header[1].startswith("text/html")
exc = webob_exc.WSGIHTTPException()
- resp = exc.generate_response(
+ exc.generate_response(
environ={
"wsgi.url_scheme": "HTTP",
"SERVER_NAME": "localhost",
@@ -425,13 +425,6 @@ def test_HTTPMove_location_not_none():
def test_HTTPMove_location_newlines():
- environ = {
- "wsgi.url_scheme": "HTTP",
- "SERVER_NAME": "localhost",
- "SERVER_PORT": "80",
- "REQUEST_METHOD": "HEAD",
- "PATH_INFO": "/",
- }
with pytest.raises(ValueError):
webob_exc._HTTPMove(location="http://example.com\r\nX-Test: false")
@@ -560,7 +553,6 @@ def test_HTTPExceptionMiddleware_exception_exc_info_none():
try:
old_sys = webob_exc.sys
- sys = DummySys()
res = m(environ, start_response)
assert res is None
finally:
diff --git a/tests/test_headers.py b/tests/test_headers.py
index 7534688..e07721a 100644
--- a/tests/test_headers.py
+++ b/tests/test_headers.py
@@ -83,7 +83,7 @@ def test_ResponseHeaders_contains():
d = headers.ResponseHeaders()
d["a"] = 1
assert "a" in d
- assert not "b" in d
+ assert "b" not in d
def test_EnvironHeaders_delitem():
@@ -114,12 +114,12 @@ def test_EnvironHeaders_contains():
def test__trans_key_not_basestring():
result = headers._trans_key(None)
- assert result == None
+ assert result is None
def test__trans_key_not_a_header():
result = headers._trans_key("")
- assert result == None
+ assert result is None
def test__trans_key_key2header():
diff --git a/tests/test_in_wsgiref.py b/tests/test_in_wsgiref.py
index 9999708..41439fc 100644
--- a/tests/test_in_wsgiref.py
+++ b/tests/test_in_wsgiref.py
@@ -76,7 +76,7 @@ def _test_app_req_interrupt(env, sr):
log.info("Running test: %s", req.path_info)
with pytest.raises(IOError):
op(req)
- except:
+ except BaseException:
_global_res.put(sys.exc_info())
else:
_global_res.put(None)
diff --git a/tests/test_misc.py b/tests/test_misc.py
index a823043..1b6c629 100644
--- a/tests/test_misc.py
+++ b/tests/test_misc.py
@@ -1,7 +1,7 @@
import pytest
from webob.util import html_escape
-from webob.compat import text_, PY3
+from webob.compat import text_
py2only = pytest.mark.skipif("sys.version_info >= (3, 0)")
py3only = pytest.mark.skipif("sys.version_info < (3, 0)")
diff --git a/tests/test_multidict.py b/tests/test_multidict.py
index 8938779..5c9fa85 100644
--- a/tests/test_multidict.py
+++ b/tests/test_multidict.py
@@ -52,7 +52,7 @@ class BaseDictTests(object):
d = self._get_instance()
self.assertTrue("a" in d)
del d["a"]
- self.assertTrue(not "a" in d)
+ self.assertTrue("a" not in d)
def test_pop(self):
d = self._get_instance()
diff --git a/tests/test_request.py b/tests/test_request.py
index 6832675..e1f7da6 100644
--- a/tests/test_request.py
+++ b/tests/test_request.py
@@ -38,10 +38,12 @@ class TestRequestCommon(object):
def _makeOne(self, *arg, **kw):
cls = self._getTargetClass()
+
return cls(*arg, **kw)
def _blankOne(self, *arg, **kw):
cls = self._getTargetClass()
+
return cls.blank(*arg, **kw)
def test_ctor_environ_getter_raises_WTF(self):
@@ -126,7 +128,7 @@ class TestRequestCommon(object):
req = self._makeOne(environ)
req.body_file = AFTER
assert req.body_file is AFTER
- assert req.content_length == None
+ assert req.content_length is None
def test_body_file_deleter(self):
body = b"input"
@@ -528,6 +530,9 @@ class TestRequestCommon(object):
@pytest.mark.parametrize("method", ["POST", "PUT", "PATCH", "DELETE"])
def test_POST_json_no_content_type(self, method):
+ from webob.request import NoVars
+ from webob.multidict import MultiDict
+
data = b'{"password": "last centurion", "email": "rory@wiggy.net"}'
wsgi_input = BytesIO(data)
environ = {
@@ -541,6 +546,10 @@ class TestRequestCommon(object):
r_2 = req.POST
r_3 = req.body
assert r_1 == b'{"password": "last centurion", "email": "rory@wiggy.net"}'
+ if method == "POST":
+ assert isinstance(r_2, MultiDict)
+ else:
+ assert isinstance(r_2, NoVars)
assert r_3 == b'{"password": "last centurion", "email": "rory@wiggy.net"}'
@pytest.mark.parametrize("method", ["POST", "PUT", "PATCH", "DELETE"])
@@ -639,8 +648,9 @@ class TestRequestCommon(object):
environ = {"HTTP_COOKIE": "a=b"}
req = self._blankOne("/", environ)
clone = req.copy_get()
+
for k, v in req.environ.items():
- if k in ("CONTENT_LENGTH", "webob.is_body_seekable"):
+ if k in {"CONTENT_LENGTH"}:
assert k not in clone.environ
elif k == "wsgi.input":
assert clone.environ[k] is not v
@@ -651,7 +661,7 @@ class TestRequestCommon(object):
req = self._blankOne("/")
req.accept_encoding = "gzip,deflate"
req.remove_conditional_headers()
- assert bool(req.accept_encoding) == False
+ assert bool(req.accept_encoding) is False
def test_remove_conditional_headers_if_modified_since(self):
from webob.datetime_utils import UTC
@@ -660,7 +670,7 @@ class TestRequestCommon(object):
req = self._blankOne("/")
req.if_modified_since = datetime(2006, 1, 1, 12, 0, tzinfo=UTC)
req.remove_conditional_headers()
- assert req.if_modified_since == None
+ assert req.if_modified_since is None
def test_remove_conditional_headers_if_none_match(self):
req = self._blankOne("/")
@@ -673,13 +683,13 @@ class TestRequestCommon(object):
req = self._blankOne("/")
req.if_range = "foo, bar"
req.remove_conditional_headers()
- assert bool(req.if_range) == False
+ assert bool(req.if_range) is False
def test_remove_conditional_headers_range(self):
req = self._blankOne("/")
req.range = "bytes=0-100"
req.remove_conditional_headers()
- assert req.range == None
+ assert req.range is None
def test_is_body_readable_POST(self):
req = self._blankOne(
@@ -875,6 +885,7 @@ class TestRequestCommon(object):
def application(environ, start_response):
start_response("200 OK", [("content-type", "text/plain")])
+
return ["...\n"]
status, headers, output = req.call_application(application)
@@ -889,6 +900,7 @@ class TestRequestCommon(object):
def application(environ, start_response):
write = start_response("200 OK", [("content-type", "text/plain")])
write("...\n")
+
return []
status, headers, output = req.call_application(application)
@@ -911,11 +923,12 @@ class TestRequestCommon(object):
environ["test._call_application_called_close"] = True
write("...\n")
+
return AppIter()
status, headers, output = req.call_application(application)
assert "".join(output) == "...\n...\n"
- assert environ["test._call_application_called_close"] == True
+ assert environ["test._call_application_called_close"] is True
def test_call_application_raises_exc_info(self):
environ = {}
@@ -924,9 +937,10 @@ class TestRequestCommon(object):
def application(environ, start_response):
try:
raise RuntimeError("OH NOES")
- except:
+ except BaseException:
exc_info = sys.exc_info()
start_response("200 OK", [("content-type", "text/plain")], exc_info)
+
return ["...\n"]
with pytest.raises(RuntimeError):
@@ -939,9 +953,10 @@ class TestRequestCommon(object):
def application(environ, start_response):
try:
raise RuntimeError("OH NOES")
- except:
+ except BaseException:
exc_info = sys.exc_info()
start_response("200 OK", [("content-type", "text/plain")], exc_info)
+
return ["...\n"]
status, headers, output, exc_info = req.call_application(application, True)
@@ -1142,7 +1157,7 @@ class TestRequestCommon(object):
req = Request.blank("/", POST="x" * tlen)
assert req.content_length == tlen
req.body_file = _Helper_test_request_wrong_clen(req.body_file)
- assert req.content_length == None
+ assert req.content_length is None
req.content_length = tlen + 100
req.is_body_seekable = is_seekable
assert req.content_length == tlen + 100
@@ -1161,10 +1176,12 @@ class TestBaseRequest(object):
def _makeOne(self, *arg, **kw):
cls = self._getTargetClass()
+
return cls(*arg, **kw)
def _blankOne(self, *arg, **kw):
cls = self._getTargetClass()
+
return cls.blank(*arg, **kw)
def test_method(self):
@@ -1338,7 +1355,7 @@ class TestBaseRequest(object):
def test_client_addr_no_xff_no_remote_addr(self):
environ = {}
req = self._makeOne(environ)
- assert req.client_addr == None
+ assert req.client_addr is None
def test_host_port_w_http_host_and_no_port(self):
environ = {"wsgi.url_scheme": "http", "HTTP_HOST": "example.com"}
@@ -1545,7 +1562,7 @@ class TestBaseRequest(object):
}
req = self._makeOne(environ)
popped = req.path_info_pop()
- assert popped == None
+ assert popped is None
assert environ["SCRIPT_NAME"] == "/script"
def test_path_info_pop_just_leading_slash(self):
@@ -1589,7 +1606,7 @@ class TestBaseRequest(object):
}
req = self._makeOne(environ)
popped = req.path_info_pop(PATTERN)
- assert popped == None
+ assert popped is None
assert environ["SCRIPT_NAME"] == "/script"
assert environ["PATH_INFO"] == "/path/info"
@@ -1634,7 +1651,7 @@ class TestBaseRequest(object):
}
req = self._makeOne(environ)
peeked = req.path_info_peek()
- assert peeked == None
+ assert peeked is None
assert environ["SCRIPT_NAME"] == "/script"
assert environ["PATH_INFO"] == ""
@@ -1735,7 +1752,7 @@ class TestBaseRequest(object):
def test_encget_doesnt_raises_with_default(self):
inst = self._makeOne({})
- assert inst.encget("a", None) == None
+ assert inst.encget("a", None) is None
def test_encget_with_encattr(self):
val = native_(b"\xc3\xab", "latin-1")
@@ -1795,10 +1812,12 @@ class TestLegacyRequest(object):
def _makeOne(self, *arg, **kw):
cls = self._getTargetClass()
+
return cls(*arg, **kw)
def _blankOne(self, *arg, **kw):
cls = self._getTargetClass()
+
return cls.blank(*arg, **kw)
def test_method(self):
@@ -1984,7 +2003,7 @@ class TestLegacyRequest(object):
def test_client_addr_no_xff_no_remote_addr(self):
environ = {}
req = self._makeOne(environ)
- assert req.client_addr == None
+ assert req.client_addr is None
def test_host_port_w_http_host_and_no_port(self):
environ = {"wsgi.url_scheme": "http", "HTTP_HOST": "example.com"}
@@ -2026,7 +2045,7 @@ class TestLegacyRequest(object):
req = self._makeOne(environ)
assert req.host_port == "6453"
- def test_host_port_ipv6(self):
+ def test_host_ipv6(self):
environ = {"wsgi.url_scheme": "https", "HTTP_HOST": "[2001:DB8::1]"}
req = self._makeOne(environ)
assert req.host_port == "443"
@@ -2179,7 +2198,7 @@ class TestLegacyRequest(object):
}
req = self._makeOne(environ)
assert req.relative_url(
- "other/page" == True, "http://example.com/script/other/page"
+ "other/page" is True, "http://example.com/script/other/page"
)
def test_relative_url_to_app_true_w_leading_slash(self):
@@ -2192,7 +2211,7 @@ class TestLegacyRequest(object):
"QUERY_STRING": "foo=bar&baz=bam",
}
req = self._makeOne(environ)
- assert req.relative_url("/other/page" == True, "http://example.com/other/page")
+ assert req.relative_url("/other/page" is True, "http://example.com/other/page")
def test_relative_url_to_app_false_other_w_leading_slash(self):
environ = {
@@ -2231,7 +2250,7 @@ class TestLegacyRequest(object):
}
req = self._makeOne(environ)
popped = req.path_info_pop()
- assert popped == None
+ assert popped is None
assert environ["SCRIPT_NAME"] == "/script"
def test_path_info_pop_just_leading_slash(self):
@@ -2275,7 +2294,7 @@ class TestLegacyRequest(object):
}
req = self._makeOne(environ)
popped = req.path_info_pop(PATTERN)
- assert popped == None
+ assert popped is None
assert environ["SCRIPT_NAME"] == "/script"
assert environ["PATH_INFO"] == "/path/info"
@@ -2320,7 +2339,7 @@ class TestLegacyRequest(object):
}
req = self._makeOne(environ)
peeked = req.path_info_peek()
- assert peeked == None
+ assert peeked is None
assert environ["SCRIPT_NAME"] == "/script"
assert environ["PATH_INFO"] == ""
@@ -2401,7 +2420,7 @@ class TestLegacyRequest(object):
def test_encget_doesnt_raises_with_default(self):
inst = self._makeOne({})
- assert inst.encget("a", None) == None
+ assert inst.encget("a", None) is None
def test_encget_with_encattr(self):
val = native_(b"\xc3\xab", "latin-1")
@@ -2457,6 +2476,7 @@ class TestRequestConstructorWarnings(object):
def _makeOne(self, *arg, **kw):
cls = self._getTargetClass()
+
return cls(*arg, **kw)
def test_ctor_w_unicode_errors(self):
@@ -2519,10 +2539,12 @@ class TestRequest_functional(object):
def _makeOne(self, *arg, **kw):
cls = self._getTargetClass()
+
return cls(*arg, **kw)
def _blankOne(self, *arg, **kw):
cls = self._getTargetClass()
+
return cls.blank(*arg, **kw)
def test_gets(self):
@@ -2580,7 +2602,9 @@ class TestRequest_functional(object):
assert b"accepttypes is: application/xml,text/html" in res
def test_accept_acceptable_offers(self):
- fut = lambda r, offers: r.accept.acceptable_offers(offers)
+ def fut(r, offers):
+ return r.accept.acceptable_offers(offers)
+
accept = self._blankOne("/").accept
assert not accept
assert self._blankOne("/", headers={"Accept": ""}).accept
@@ -2663,6 +2687,7 @@ class TestRequest_functional(object):
request = self._blankOne("/?foo=bar&baz", headers=headers)
status, headerlist, app_iter = request.call_application(simpleapp)
res = b"".join(app_iter)
+
for thing in (
"if_modified_since: "
+ "datetime.datetime(1994, 10, 29, 19, 43, 31, tzinfo=UTC)",
@@ -2921,6 +2946,7 @@ class TestRequest_functional(object):
"Cache-Control": "max-age=0",
}
r = self._makeOne({"a": 1}, headers=headers)
+
for i in headers.keys():
assert i in r.headers and "HTTP_" + i.upper().replace("-", "_") in r.environ
r.headers = {"Server": "Apache"}
@@ -2950,8 +2976,8 @@ class TestRequest_functional(object):
assert a.path_info_pop() == "foo"
assert a.path_info_peek() == "bar"
assert a.path_info_pop() == "bar"
- assert a.path_info_peek() == None
- assert a.path_info_pop() == None
+ assert a.path_info_peek() is None
+ assert a.path_info_pop() is None
def test_urlvars_property(self):
# Testing urlvars setter/getter/deleter
@@ -3206,6 +3232,7 @@ class TestRequest_functional(object):
def test_middleware_body(self):
def app(env, sr):
sr("200 OK", [])
+
return [env["wsgi.input"].read()]
def mw(env, sr):
@@ -3213,6 +3240,7 @@ class TestRequest_functional(object):
data = req.body_file.read()
resp = req.get_response(app)
resp.headers["x-data"] = data
+
return resp(env, sr)
req = self._blankOne("/", method="PUT", body=b"abc")
@@ -3262,9 +3290,9 @@ class TestRequest_functional(object):
assert hasattr(req.environ["wsgi.input"], "next") or hasattr(
req.environ["wsgi.input"], "__next__"
)
- assert req.environ["wsgi.multiprocess"] == False
- assert req.environ["wsgi.multithread"] == False
- assert req.environ["wsgi.run_once"] == False
+ assert req.environ["wsgi.multiprocess"] is False
+ assert req.environ["wsgi.multithread"] is False
+ assert req.environ["wsgi.run_once"] is False
assert req.environ["wsgi.url_scheme"] == "http"
assert req.environ["wsgi.version"], 1 == 0
@@ -3410,7 +3438,7 @@ class TestRequest_functional(object):
# Conditional Requests
server_token = "opaque-token"
# shouldn't return 304
- assert not server_token in req.if_none_match
+ assert server_token not in req.if_none_match
req.if_none_match = server_token
assert isinstance(req.if_none_match, ETagMatcher)
# You *should* return 304
@@ -3474,6 +3502,7 @@ class TestRequest_functional(object):
def wsgi_app(environ, start_response):
start_response("200 OK", [("Content-Type", "text/plain")])
+
return [b"Hi!"]
assert req.call_application(wsgi_app) == (
@@ -3498,6 +3527,7 @@ class TestRequest_functional(object):
def wsgi_app(environ, start_response):
start_response("204 No Content", [])
+
return [b""]
assert req.call_application(wsgi_app) == ("204 No Content", [], [b""])
@@ -3518,6 +3548,7 @@ class TestRequest_functional(object):
def wsgi_app(environ, start_response):
start_response("200 OK", [])
+
return [b""]
assert req.call_application(wsgi_app) == ("200 OK", [], [b""])
@@ -3539,6 +3570,7 @@ class TestRequest_functional(object):
def wsgi_app(environ, start_response):
start_response("200 OK", [("Content-Type", "text/plain")])
+
return [b"Hi!"]
res = req.get_response(wsgi_app, catch_exc_info=True)
@@ -3561,8 +3593,10 @@ class TestRequest_functional(object):
assert int(headers1.get("Content-Length", "0")) == int(
headers2.get("Content-Length", "0")
)
+
if "Content-Length" in headers1:
del headers1["Content-Length"]
+
if "Content-Length" in headers2:
del headers2["Content-Length"]
assert headers1 == headers2
@@ -3628,7 +3662,7 @@ class TestFakeCGIBody(object):
body = FakeCGIBody(
{"bananas": "bananas"}, "multipart/form-data; boundary=foobar"
)
- assert body.fileno() == None
+ assert body.fileno() is None
def test_iter(self):
from webob.request import FakeCGIBody
@@ -3811,6 +3845,7 @@ def simpleapp(environ, start_response):
start_response(status, response_headers)
request = Request(environ)
request.remote_user = "bob"
+
return [
bytes_(x)
for x in [
@@ -3957,12 +3992,14 @@ class UnseekableInput(object):
if size == -1:
t = self.data[self.pos :]
self.pos = len(self.data)
+
return t
else:
if self.pos + size > len(self.data):
size = len(self.data) - self.pos
t = self.data[self.pos : self.pos + size]
self.pos += size
+
return t
@@ -3978,10 +4015,12 @@ class _Helper_test_request_wrong_clen(object):
def read(self, *args):
r = self.f.read(*args)
+
if not r:
if self.file_ended:
raise AssertionError("Reading should stop after first empty string")
self.file_ended = True
+
return r
def seek(self, pos):
diff --git a/tests/test_static.py b/tests/test_static.py
index 229f8da..5845e6d 100644
--- a/tests/test_static.py
+++ b/tests/test_static.py
@@ -15,6 +15,7 @@ from webob.response import Response
def get_response(app, path="/", **req_kw):
"""Convenient function to query an application"""
req = Request(environ_from_url(path), **req_kw)
+
return req.get_response(app)
@@ -23,6 +24,7 @@ def create_file(content, *paths):
path = os.path.join(*paths)
with open(path, "wb") as fp:
fp.write(bytes_(content))
+
return path
@@ -69,7 +71,8 @@ class TestFileApp(unittest.TestCase):
app = static.FileApp(self.tempfile)
# Alias
- resp = lambda method: get_response(app, method=method)
+ def resp(method):
+ return get_response(app, method=method)
self.assertEqual(200, resp(method="GET").status_code)
self.assertEqual(200, resp(method="HEAD").status_code)
@@ -96,6 +99,8 @@ class TestFileApp(unittest.TestCase):
def test_use_wsgi_filewrapper(self):
class TestWrapper(object):
+ __slots__ = ("file", "block_size")
+
def __init__(self, file, block_size):
self.file = file
self.block_size = block_size
@@ -219,6 +224,7 @@ class TestDirectoryApp(unittest.TestCase):
def test_file_app_factory(self):
def make_fileapp(*args, **kwargs):
make_fileapp.called = True
+
return Response()
make_fileapp.called = False
diff --git a/tests/test_transcode.py b/tests/test_transcode.py
index cb18fe4..3a85a12 100644
--- a/tests/test_transcode.py
+++ b/tests/test_transcode.py
@@ -2,9 +2,18 @@ from webob.request import Request, Transcoder
from webob.response import Response
from webob.compat import text_, native_
-t1 = b'--BOUNDARY\r\nContent-Disposition: form-data; name="a"\r\n\r\n\xea\xf3...\r\n--BOUNDARY--'
-t2 = b'--BOUNDARY\r\nContent-Disposition: form-data; name="a"; filename="file"\r\n\r\n\xea\xf3...\r\n--BOUNDARY--'
-t3 = b'--BOUNDARY\r\nContent-Disposition: form-data; name="a"; filename="\xea\xf3..."\r\n\r\nfoo\r\n--BOUNDARY--'
+t1 = (
+ b'--BOUNDARY\r\nContent-Disposition: form-data; name="a"\r\n\r\n\xea\xf3...'
+ b"\r\n--BOUNDARY--"
+)
+t2 = (
+ b'--BOUNDARY\r\nContent-Disposition: form-data; name="a"; filename="file"\r\n'
+ b"\r\n\xea\xf3...\r\n--BOUNDARY--"
+)
+t3 = (
+ b'--BOUNDARY\r\nContent-Disposition: form-data; name="a"; filename="\xea\xf3...'
+ b'"\r\n\r\nfoo\r\n--BOUNDARY--'
+)
def test_transcode():
@@ -18,6 +27,7 @@ def test_transcode():
r = Response(text_("%s\n%r" % (v.filename, v.value)))
else:
r = Response(v)
+
return r(env, sr)
text = b"\xea\xf3...".decode("cp1251")
@@ -27,6 +37,7 @@ def test_transcode():
req.environ[
"CONTENT_TYPE"
] = "multipart/form-data; charset=windows-1251; boundary=BOUNDARY"
+
return req.get_response(tapp)
r = test(t1)