diff options
author | Bert JW Regeer <bertjw@regeer.org> | 2018-11-14 23:25:51 -0700 |
---|---|---|
committer | Bert JW Regeer <bertjw@regeer.org> | 2020-11-28 12:19:50 -0800 |
commit | 0c5700be0f8747ed138ebd1cb3c8bcaf4dd3d64c (patch) | |
tree | 467468b24f3b01fc970268fcda815d4a3ec1e937 | |
parent | e0452f46429da71a65a84b44bd6cc7cf0cb6dd84 (diff) | |
download | webob-0c5700be0f8747ed138ebd1cb3c8bcaf4dd3d64c.tar.gz |
Goodbye compat.PY2 lines
-rw-r--r-- | src/webob/client.py | 6 | ||||
-rw-r--r-- | src/webob/cookies.py | 41 | ||||
-rw-r--r-- | src/webob/descriptors.py | 32 | ||||
-rw-r--r-- | src/webob/multidict.py | 113 | ||||
-rw-r--r-- | src/webob/request.py | 66 | ||||
-rw-r--r-- | src/webob/response.py | 33 | ||||
-rw-r--r-- | tests/performance_test.py | 6 | ||||
-rw-r--r-- | tests/test_cookies.py | 26 | ||||
-rw-r--r-- | tests/test_misc.py | 14 | ||||
-rw-r--r-- | tests/test_multidict.py | 7 |
10 files changed, 72 insertions, 272 deletions
diff --git a/src/webob/client.py b/src/webob/client.py index 0ba9654..89b9223 100644 --- a/src/webob/client.py +++ b/src/webob/client.py @@ -9,7 +9,6 @@ except ImportError: from webob.compat import url_quote import socket from webob import exc -from webob.compat import PY2 __all__ = ["send_request_app", "SendRequest"] @@ -135,10 +134,7 @@ class SendRequest: Turn a Message object into a list of WSGI-style headers. """ headers_out = [] - if not PY2: - headers = message._headers - else: - headers = message.headers + headers = message._headers for full_header in headers: if not full_header: # pragma: no cover # Shouldn't happen, but we'll just ignore diff --git a/src/webob/cookies.py b/src/webob/cookies.py index 81bf7a3..b4fb2b4 100644 --- a/src/webob/cookies.py +++ b/src/webob/cookies.py @@ -9,15 +9,7 @@ import string import time import warnings -from webob.compat import ( - MutableMapping, - PY2, - text_type, - bytes_, - text_, - native_, - string_types, -) +from webob.compat import MutableMapping, text_type, bytes_, text_, native_, string_types from webob.util import strings_differ @@ -67,8 +59,7 @@ class RequestCookies(MutableMapping): had_header = header is not None header = header or "" - if not PY2: - header = header.encode("latin-1") + header = header.encode("latin-1") bytes_name = bytes_(name, "ascii") if value is None: @@ -157,17 +148,6 @@ class RequestCookies(MutableMapping): def items(self): return self._cache.items() - if PY2: - - def iterkeys(self): - return self._cache.iterkeys() # noqa: B301 - - def itervalues(self): - return self._cache.itervalues() # noqa: B301 - - def iteritems(self): - return self._cache.iteritems() # noqa: B301 - def __contains__(self, name): return name in self._cache @@ -227,8 +207,7 @@ class Cookie(dict): def _parse_cookie(data): - if not PY2: - data = data.encode("latin-1") + data = data.encode("latin-1") for key, val in _rx_cookie.findall(data): yield key, _unquote(val) @@ -375,12 +354,16 @@ _re_cookie_str = _re_cookie_str_key + _re_cookie_str_equal + _re_cookie_str_val _rx_cookie = re.compile(bytes_(_re_cookie_str, "ascii")) _rx_unquote = re.compile(bytes_(r"\\([0-3][0-7][0-7]|.)", "ascii")) -_bchr = chr if PY2 else (lambda i: bytes([i])) + +def _bchr(i): + return bytes([i]) + + _ch_unquote_map = dict((bytes_("%03o" % i), _bchr(i)) for i in range(256)) _ch_unquote_map.update((v, v) for v in list(_ch_unquote_map.values())) -_b_dollar_sign = "$" if PY2 else ord("$") -_b_quote_mark = '"' if PY2 else ord('"') +_b_dollar_sign = ord("$") +_b_quote_mark = ord('"') def _unquote(v): @@ -432,9 +415,7 @@ _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()) +_escape_map = dict((ord(k), bytes_(v, "ascii")) for k, v in _escape_map.items()) _escape_char = _escape_map.__getitem__ weekdays = ("Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun") diff --git a/src/webob/descriptors.py b/src/webob/descriptors.py index ede7436..beea809 100644 --- a/src/webob/descriptors.py +++ b/src/webob/descriptors.py @@ -6,7 +6,7 @@ from collections import namedtuple from webob.byterange import ContentRange, Range -from webob.compat import PY2, text_type +from webob.compat import text_type from webob.datetime_utils import parse_date, serialize_date @@ -85,27 +85,13 @@ def environ_decoder(key, default=_not_given, rfc_section=None, encattr=None): def upath_property(key): - if PY2: + def fget(req): + encoding = req.url_encoding + return req.environ.get(key, "").encode("latin-1").decode(encoding) - def fget(req): - encoding = req.url_encoding - return req.environ.get(key, "").decode(encoding) - - def fset(req, val): - encoding = req.url_encoding - if isinstance(val, text_type): - val = val.encode(encoding) - req.environ[key] = val - - else: - - def fget(req): - encoding = req.url_encoding - return req.environ.get(key, "").encode("latin-1").decode(encoding) - - def fset(req, val): - encoding = req.url_encoding - req.environ[key] = val.encode(encoding).decode("latin-1") + def fset(req, val): + encoding = req.url_encoding + req.environ[key] = val.encode(encoding).decode("latin-1") return property(fget, fset, doc="upath_property(%r)" % key) @@ -149,9 +135,9 @@ def header_getter(header, rfc_section): if value is not None: if "\n" in value or "\r" in value: raise ValueError("Header value may not contain control characters") + if not isinstance(value, str): + raise ValueError("Value must be text_type") - if isinstance(value, text_type) and PY2: - value = value.encode("latin-1") r._headerlist.append((header, value)) def fdel(r): diff --git a/src/webob/multidict.py b/src/webob/multidict.py index abe69ee..f291d68 100644 --- a/src/webob/multidict.py +++ b/src/webob/multidict.py @@ -7,7 +7,7 @@ Gives a multi-value dictionary object (MultiDict) plus several wrappers import binascii import warnings -from webob.compat import MutableMapping, PY2, iteritems_, itervalues_, url_encode +from webob.compat import MutableMapping, iteritems_, itervalues_, url_encode __all__ = ["MultiDict", "NestedMultiDict", "NoVars", "GetDict"] @@ -71,21 +71,15 @@ class MultiDict(MutableMapping): "quoted-printable": binascii.a2b_qp, } - if not PY2: - if charset == "utf8": + if charset == "utf8": - def decode(b): - return b - - else: - - def decode(b): - return b.encode("utf8").decode(charset) + def decode(b): + return b else: def decode(b): - return b.decode(charset) + return b.encode("utf8").decode(charset) if field.filename: field.filename = decode(field.filename) @@ -94,14 +88,12 @@ class MultiDict(MutableMapping): value = field.value if transfer_encoding in supported_transfer_encoding: - if not PY2: - # binascii accepts bytes - value = value.encode("utf8") + # binascii accepts bytes + value = value.encode("utf8") value = supported_transfer_encoding[transfer_encoding](value) - if not PY2: - # binascii returns bytes - value = value.decode("utf8") + # binascii returns bytes + value = value.decode("utf8") obj.add(field.name, decode(value)) return obj @@ -281,43 +273,19 @@ class MultiDict(MutableMapping): # All the iteration: # - def iterkeys(self): + def keys(self): for k, _ in self._items: yield k - if PY2: - - def keys(self): - return [k for k, v in self._items] - - else: - keys = iterkeys - - __iter__ = iterkeys + __iter__ = keys - def iteritems(self): + def items(self): return iter(self._items) - if PY2: - - def items(self): - return self._items[:] - - else: - items = iteritems - - def itervalues(self): + def values(self): for _, v in self._items: yield v - if PY2: - - def values(self): - return [v for k, v in self._items] - - else: - values = itervalues - _dummy = object() @@ -461,46 +429,22 @@ class NestedMultiDict(MultiDict): return False - def iteritems(self): + def items(self): for d in self.dicts: for item in iteritems_(d): yield item - if PY2: - - def items(self): - return list(self.iteritems()) # noqa: B301 - - else: - items = iteritems - - def itervalues(self): + def values(self): for d in self.dicts: for value in itervalues_(d): yield value - if PY2: - - def values(self): - return list(self.itervalues()) # noqa: B301 - - else: - values = itervalues - - def __iter__(self): + def keys(self): for d in self.dicts: for key in d: yield key - iterkeys = __iter__ - - if PY2: - - def keys(self): - return list(self.iterkeys()) # noqa: B301 - - else: - keys = iterkeys + __iter__ = keys class NoVars(object): @@ -559,27 +503,12 @@ class NoVars(object): def __len__(self): return 0 - def iterkeys(self): + def keys(self): return iter([]) - if PY2: - - def __cmp__(self, other): - return cmp({}, other) # noqa: F821 - - def keys(self): - return [] - - items = keys - values = keys - itervalues = iterkeys - iteritems = iterkeys - else: - keys = iterkeys - items = iterkeys - values = iterkeys - - __iter__ = iterkeys + items = keys + values = keys + __iter__ = keys def _hide_passwd(items): diff --git a/src/webob/request.py b/src/webob/request.py index aef25ae..a64c1f2 100644 --- a/src/webob/request.py +++ b/src/webob/request.py @@ -22,7 +22,6 @@ from webob.acceptparse import ( from webob.cachecontrol import CacheControl, serialize_cache_control from webob.compat import ( - PY2, bytes_, native_, parse_qsl_text, @@ -158,9 +157,6 @@ class BaseRequest(object): return val encoding = getattr(self, encattr) - if PY2: - return val.decode(encoding) - if encoding in _LATIN_ENCODINGS: # shortcut return val return bytes_(val, "latin-1").decode(encoding) @@ -170,10 +166,7 @@ class BaseRequest(object): encoding = getattr(self, encattr) else: encoding = "ascii" - if PY2: # pragma: no cover - self.environ[key] = bytes_(val, encoding) - else: - self.environ[key] = bytes_(val, encoding).decode("latin-1") + self.environ[key] = bytes_(val, encoding).decode("latin-1") @property def charset(self): @@ -215,18 +208,13 @@ class BaseRequest(object): fs_environ = self.environ.copy() fs_environ.setdefault("CONTENT_LENGTH", "0") fs_environ["QUERY_STRING"] = "" - if PY2: - fs = cgi_FieldStorage( - fp=self.body_file, environ=fs_environ, keep_blank_values=True - ) - else: - fs = cgi_FieldStorage( - fp=self.body_file, - environ=fs_environ, - keep_blank_values=True, - encoding=charset, - errors=errors, - ) + fs = cgi_FieldStorage( + fp=self.body_file, + environ=fs_environ, + keep_blank_values=True, + encoding=charset, + errors=errors, + ) fout = t.transcode_fs(fs, r._content_type_raw) @@ -798,17 +786,12 @@ class BaseRequest(object): # default of 0 is better: fs_environ.setdefault("CONTENT_LENGTH", "0") fs_environ["QUERY_STRING"] = "" - if PY2: - fs = cgi_FieldStorage( - fp=self.body_file, environ=fs_environ, keep_blank_values=True - ) - else: - fs = cgi_FieldStorage( - fp=self.body_file, - environ=fs_environ, - keep_blank_values=True, - encoding="utf8", - ) + fs = cgi_FieldStorage( + fp=self.body_file, + environ=fs_environ, + keep_blank_values=True, + encoding="utf8", + ) self.body_file_raw.seek(0) vars = MultiDict.from_fieldstorage(fs) @@ -1659,29 +1642,14 @@ class Transcoder(object): # this doesn't look like a form submission return q_orig - if PY2: - q = urlparse.parse_qsl(q, self.charset) - t = self._trans - q = [(t(k), t(v)) for k, v in q] - else: - q = list(parse_qsl_text(q, self.charset)) + q = list(parse_qsl_text(q, self.charset)) return url_encode(q) def transcode_fs(self, fs, content_type): # transcode FieldStorage - if PY2: - - def decode(b): - if b is not None: - return b.decode(self.charset, self.errors) - else: - return b - - else: - - def decode(b): - return b + def decode(b): + return b data = [] for field in fs.list or (): diff --git a/src/webob/response.py b/src/webob/response.py index 58195ac..4d49016 100644 --- a/src/webob/response.py +++ b/src/webob/response.py @@ -7,15 +7,7 @@ from hashlib import md5 from webob.byterange import ContentRange from webob.cachecontrol import CacheControl, serialize_cache_control -from webob.compat import ( - PY2, - bytes_, - native_, - string_types, - text_type, - url_quote, - urlparse, -) +from webob.compat import bytes_, native_, string_types, text_type, url_quote, urlparse from webob.cookies import Cookie, make_cookie from webob.datetime_utils import ( parse_date_delta, @@ -395,7 +387,8 @@ class Response(object): self.body parts += map("%s: %s".__mod__, self.headerlist) if not skip_body and self.body: - parts += ["", self.body if PY2 else self.text] + parts += ["", self.text] + return "\r\n".join(parts) # @@ -416,11 +409,10 @@ class Response(object): else: self.status_code = code return - if not PY2: - if isinstance(value, bytes): - value = value.decode("ascii") - elif isinstance(value, text_type): - value = value.encode("ascii") + + if isinstance(value, bytes): + value = value.decode("ascii") + if not isinstance(value, str): raise TypeError( "You must set status to a string or integer (not %s)" % type(value) @@ -860,9 +852,6 @@ class Response(object): self._content_type__del() return else: - if PY2 and isinstance(value, text_type): - value = value.encode("latin-1") - if not isinstance(value, string_types): raise TypeError("content_type requires value to be of string_types") @@ -1592,12 +1581,8 @@ def _request_uri(environ): elif url.endswith(":443") and environ["wsgi.url_scheme"] == "https": url = url[:-4] - if PY2: - script_name = environ.get("SCRIPT_NAME", "/") - path_info = environ.get("PATH_INFO", "") - else: - script_name = bytes_(environ.get("SCRIPT_NAME", "/"), "latin-1") - path_info = bytes_(environ.get("PATH_INFO", ""), "latin-1") + script_name = bytes_(environ.get("SCRIPT_NAME", "/"), "latin-1") + path_info = bytes_(environ.get("PATH_INFO", ""), "latin-1") url += url_quote(script_name) qpath_info = url_quote(path_info) diff --git a/tests/performance_test.py b/tests/performance_test.py index 4c4917f..9b4397b 100644 --- a/tests/performance_test.py +++ b/tests/performance_test.py @@ -1,6 +1,5 @@ #!/usr/bin/env python from webob.response import Response -from webob.compat import PY2 def make_middleware(app): @@ -43,10 +42,7 @@ if __name__ == "__main__": print("Hit ^C to end") try: while 1: - if PY2: - raw_input() # noqa: F821 - else: - input() + input() finally: os.kill(proc.pid, signal.SIGKILL) else: diff --git a/tests/test_cookies.py b/tests/test_cookies.py index 578bfb8..6f62eb0 100644 --- a/tests/test_cookies.py +++ b/tests/test_cookies.py @@ -6,9 +6,6 @@ from webob import cookies from webob.compat import text_ from webob.compat import native_ -py2only = pytest.mark.skipif("sys.version_info >= (3, 0)") -py3only = pytest.mark.skipif("sys.version_info < (3, 0)") - def setup_module(module): cookies._should_raise = True @@ -407,40 +404,17 @@ class TestRequestCookies(object): inst = self._makeOne(environ) assert sorted(list(inst.items())) == [("a", "1"), ("b", val), ("c", "3")] - @py2only - def test_iterkeys(self): - environ = {"HTTP_COOKIE": 'a=1; b="La Pe\\303\\261a"; c=3'} - inst = self._makeOne(environ) - assert sorted(list(inst.iterkeys())) == ["a", "b", "c"] - - @py3only def test_iterkeys_py3(self): environ = {"HTTP_COOKIE": b'a=1; b="La Pe\\303\\261a"; c=3'.decode("utf-8")} inst = self._makeOne(environ) assert sorted(list(inst.keys())) == ["a", "b", "c"] - @py2only - def test_itervalues(self): - val = text_(b"La Pe\xc3\xb1a", "utf-8") - environ = {"HTTP_COOKIE": 'a=1; b="La Pe\\303\\261a"; c=3'} - inst = self._makeOne(environ) - sorted(list(inst.itervalues())) == ["1", "3", val] - - @py3only def test_itervalues_py3(self): val = text_(b"La Pe\xc3\xb1a", "utf-8") environ = {"HTTP_COOKIE": b'a=1; b="La Pe\\303\\261a"; c=3'.decode("utf-8")} inst = self._makeOne(environ) sorted(list(inst.values())) == ["1", "3", val] - @py2only - def test_iteritems(self): - val = text_(b"La Pe\xc3\xb1a", "utf-8") - environ = {"HTTP_COOKIE": 'a=1; b="La Pe\\303\\261a"; c=3'} - inst = self._makeOne(environ) - assert sorted(list(inst.iteritems())) == [("a", "1"), ("b", val), ("c", "3")] - - @py3only def test_iteritems_py3(self): val = text_(b"La Pe\xc3\xb1a", "utf-8") environ = {"HTTP_COOKIE": b'a=1; b="La Pe\\303\\261a"; c=3'.decode("utf-8")} diff --git a/tests/test_misc.py b/tests/test_misc.py index 1b6c629..42d0479 100644 --- a/tests/test_misc.py +++ b/tests/test_misc.py @@ -1,10 +1,6 @@ import pytest - -from webob.util import html_escape from webob.compat import text_ - -py2only = pytest.mark.skipif("sys.version_info >= (3, 0)") -py3only = pytest.mark.skipif("sys.version_info < (3, 0)") +from webob.util import html_escape class t_esc_HTML(object): @@ -43,8 +39,7 @@ class t_esc_SuperMoose(object): ("è", "&egrave;"), # The apostrophe is *not* escaped, which some might consider to be # a serious bug (see, e.g. http://www.cvedetails.com/cve/CVE-2010-2480/) - pytest.param("'", "'", marks=py2only), - pytest.param("'", "'", marks=py3only), + pytest.param("'", "'"), (text_("the majestic m\xf8ose"), "the majestic møose"), # 8-bit strings are passed through (text_("\xe9"), "é"), @@ -59,10 +54,7 @@ class t_esc_SuperMoose(object): (t_esc_SuperMoose(), "møose"), (t_esc_Unicode(), "é"), (t_esc_UnsafeAttrs(), "<UnsafeAttrs>"), - pytest.param(Exception("expected a '<'."), "expected a '<'.", marks=py2only), - pytest.param( - Exception("expected a '<'."), "expected a '<'.", marks=py3only - ), + pytest.param(Exception("expected a '<'."), "expected a '<'."), ], ) def test_html_escape(input, expected): diff --git a/tests/test_multidict.py b/tests/test_multidict.py index 5c9fa85..f040d4a 100644 --- a/tests/test_multidict.py +++ b/tests/test_multidict.py @@ -41,11 +41,8 @@ class BaseDictTests(object): def test_dict_api(self): self.assertTrue("a" in self.d.mixed()) self.assertTrue("a" in self.d.keys()) - self.assertTrue("a" in self.d.iterkeys()) self.assertTrue(("b", "1") in self.d.items()) - self.assertTrue(("b", "1") in self.d.iteritems()) self.assertTrue("1" in self.d.values()) - self.assertTrue("1" in self.d.itervalues()) self.assertEqual(len(self.d), 4) def test_set_del_item(self): @@ -502,10 +499,6 @@ class NoVarsTestCase(unittest.TestCase): d = self._get_instance() self.assertEqual(list(d.keys()), []) - def test_iterkeys(self): - d = self._get_instance() - self.assertEqual(list(d.iterkeys()), []) - class DummyField(object): def __init__(self, name, value, filename=None): |