summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBert JW Regeer <bertjw@regeer.org>2018-11-14 23:25:51 -0700
committerBert JW Regeer <bertjw@regeer.org>2020-11-28 12:19:50 -0800
commit0c5700be0f8747ed138ebd1cb3c8bcaf4dd3d64c (patch)
tree467468b24f3b01fc970268fcda815d4a3ec1e937
parente0452f46429da71a65a84b44bd6cc7cf0cb6dd84 (diff)
downloadwebob-0c5700be0f8747ed138ebd1cb3c8bcaf4dd3d64c.tar.gz
Goodbye compat.PY2 lines
-rw-r--r--src/webob/client.py6
-rw-r--r--src/webob/cookies.py41
-rw-r--r--src/webob/descriptors.py32
-rw-r--r--src/webob/multidict.py113
-rw-r--r--src/webob/request.py66
-rw-r--r--src/webob/response.py33
-rw-r--r--tests/performance_test.py6
-rw-r--r--tests/test_cookies.py26
-rw-r--r--tests/test_misc.py14
-rw-r--r--tests/test_multidict.py7
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;", "&amp;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("'", "&#x27;", marks=py3only),
+ pytest.param("'", "&#x27;"),
(text_("the majestic m\xf8ose"), "the majestic m&#248;ose"),
# 8-bit strings are passed through
(text_("\xe9"), "&#233;"),
@@ -59,10 +54,7 @@ class t_esc_SuperMoose(object):
(t_esc_SuperMoose(), "m&#248;ose"),
(t_esc_Unicode(), "&#233;"),
(t_esc_UnsafeAttrs(), "&lt;UnsafeAttrs&gt;"),
- pytest.param(Exception("expected a '<'."), "expected a '&lt;'.", marks=py2only),
- pytest.param(
- Exception("expected a '<'."), "expected a &#x27;&lt;&#x27;.", marks=py3only
- ),
+ pytest.param(Exception("expected a '<'."), "expected a &#x27;&lt;&#x27;."),
],
)
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):