From 2f6e15f00e1b2929fb1709961223abc6607f6ba9 Mon Sep 17 00:00:00 2001 From: Alexandre Detiste Date: Thu, 14 Mar 2024 21:59:43 +0100 Subject: [PATCH 1/5] remove most python2 compatibility --- README.rst | 2 +- paste/auth/auth_tkt.py | 32 +++++-------- paste/auth/basic.py | 9 +++- paste/auth/cas.py | 2 +- paste/auth/cookie.py | 31 +++++------- paste/auth/digest.py | 27 ++++++----- paste/auth/grantip.py | 5 +- paste/auth/open_id.py | 5 +- paste/cascade.py | 2 +- paste/cgiapp.py | 9 ++-- paste/cgitb_catcher.py | 11 ++--- paste/debug/prints.py | 8 +--- paste/debug/profile.py | 5 +- paste/debug/testserver.py | 4 +- paste/errordocument.py | 6 +-- paste/evalexception/evalcontext.py | 7 ++- paste/evalexception/middleware.py | 12 ++--- paste/exceptions/collector.py | 2 +- paste/exceptions/errormiddleware.py | 9 ++-- paste/exceptions/formatter.py | 5 +- paste/exceptions/reporter.py | 2 +- paste/exceptions/serial_number_generator.py | 9 ++-- paste/fixture.py | 43 +++++++---------- paste/gzipper.py | 5 +- paste/httpexceptions.py | 15 ++---- paste/httpheaders.py | 40 +++++----------- paste/httpserver.py | 14 ++---- paste/lint.py | 13 +++-- paste/modpython.py | 3 +- paste/proxy.py | 33 ++----------- paste/recursive.py | 7 ++- paste/registry.py | 5 +- paste/reloader.py | 1 - paste/request.py | 27 ++++------- paste/session.py | 15 ++---- paste/translogger.py | 7 ++- paste/url.py | 17 ++----- paste/urlmap.py | 11 ++--- paste/urlparser.py | 33 ++++--------- paste/util/PySourceColor.py | 2 +- paste/util/converters.py | 6 +-- paste/util/finddata.py | 1 - paste/util/html.py | 24 ---------- paste/util/intset.py | 27 +++++------ paste/util/ip4.py | 7 ++- paste/util/killthread.py | 3 +- paste/util/looper.py | 8 ++-- paste/util/multidict.py | 25 ++++------ paste/util/quoting.py | 27 ++++------- paste/util/scgiserver.py | 3 +- paste/util/template.py | 48 +++++++------------ paste/wsgilib.py | 44 ++++++++--------- paste/wsgiwrappers.py | 10 +--- tests/cgiapp_data/form.cgi | 2 - tests/cgiapp_data/stderr.cgi | 1 - tests/test_auth/test_auth_cookie.py | 8 +--- tests/test_auth/test_auth_digest.py | 8 ++-- tests/test_auth/test_auth_tkt.py | 17 ++----- tests/test_cgitb_catcher.py | 5 +- tests/test_config.py | 7 +-- tests/test_doctests.py | 4 +- .../test_exceptions/test_error_middleware.py | 5 +- tests/test_exceptions/test_httpexceptions.py | 24 +++++++--- tests/test_fileapp.py | 17 ++----- tests/test_grantip.py | 3 +- tests/test_gzipper.py | 4 +- tests/test_httpheaders.py | 26 +++++++++- tests/test_httpserver.py | 11 +---- tests/test_multidict.py | 25 +++++----- tests/test_registry.py | 18 +++---- tests/test_request.py | 4 +- tests/test_request_form.py | 4 +- tests/test_session.py | 4 +- tests/test_urlmap.py | 8 ++-- tests/test_util/test_datetimeutil.py | 7 ++- tests/test_util/test_quoting.py | 17 +++---- tests/test_wsgiwrappers.py | 11 ++--- tests/urlparser_data/hook/app.py | 4 +- tests/urlparser_data/hook/index.py | 4 +- tests/urlparser_data/not_found/user/list.py | 4 +- 80 files changed, 367 insertions(+), 613 deletions(-) delete mode 100644 paste/util/html.py diff --git a/README.rst b/README.rst index 951e81d2..a0ab4409 100644 --- a/README.rst +++ b/README.rst @@ -3,7 +3,7 @@ Patches are accepted to keep it on life support, but for the most part, please consider using other options.* -**As of release 3.7.0 Paste no longer tries to support Python 2. If you are +**As of release 3.7.0 Paste no longer supports Python 2. If you are required to continue using Python 2 please pin an earlier version of Paste.** Paste provides several pieces of "middleware" (or filters) that can be nested diff --git a/paste/auth/auth_tkt.py b/paste/auth/auth_tkt.py index 5364b2ca..96d40070 100644 --- a/paste/auth/auth_tkt.py +++ b/paste/auth/auth_tkt.py @@ -43,19 +43,12 @@ except ImportError: # mimic hashlib (will work for md5, fail for secure hashes) import md5 as hashlib -try: - from http.cookies import SimpleCookie -except ImportError: - # Python 2 - from Cookie import SimpleCookie +from http.cookies import SimpleCookie +from urllib.parse import quote as url_quote +from urllib.parse import unquote as url_unquote + from paste import request -try: - from urllib import quote as url_quote # Python 2.X - from urllib import unquote as url_unquote -except ImportError: - from urllib.parse import quote as url_quote # Python 3+ - from urllib.parse import unquote as url_unquote DEFAULT_DIGEST = hashlib.md5 @@ -103,7 +96,7 @@ def __init__(self, secret, userid, ip, tokens=(), user_data='', self.secret = secret self.userid = userid self.ip = ip - if not isinstance(tokens, six.string_types): + if not isinstance(tokens, str): tokens = ','.join(tokens) self.tokens = tokens self.user_data = user_data @@ -113,7 +106,7 @@ def __init__(self, secret, userid, ip, tokens=(), user_data='', self.time = time self.cookie_name = cookie_name self.secure = secure - if isinstance(digest_algo, six.binary_type): + if isinstance(digest_algo, bytes): # correct specification of digest from hashlib or fail self.digest_algo = getattr(hashlib, digest_algo) else: @@ -133,11 +126,8 @@ def cookie_value(self): def cookie(self): c = SimpleCookie() - if six.PY3: - import base64 - cookie_value = base64.b64encode(self.cookie_value()) - else: - cookie_value = self.cookie_value().encode('base64').strip().replace('\n', '') + import base64 + cookie_value = base64.b64encode(self.cookie_value()) c[self.cookie_name] = cookie_value c[self.cookie_name]['path'] = '/' if self.secure: @@ -164,7 +154,7 @@ def parse_ticket(secret, ticket, ip, digest_algo=DEFAULT_DIGEST): If the ticket cannot be parsed, ``BadTicket`` will be raised with an explanation. """ - if isinstance(digest_algo, six.binary_type): + if isinstance(digest_algo, bytes): # correct specification of digest from hashlib or fail digest_algo = getattr(hashlib, digest_algo) digest_hexa_size = digest_algo().digest_size * 2 @@ -225,7 +215,7 @@ def encode_ip_timestamp(ip, timestamp): def maybe_encode(s, encoding='utf8'): - if isinstance(s, six.text_type): + if isinstance(s, str): s = s.encode(encoding) return s @@ -359,7 +349,7 @@ def cookie_setting_start_response(status, headers, exc_info=None): return self.app(environ, cookie_setting_start_response) def set_user_cookie(self, environ, userid, tokens, user_data): - if not isinstance(tokens, six.string_types): + if not isinstance(tokens, str): tokens = ','.join(tokens) if self.include_ip: remote_addr = environ['REMOTE_ADDR'] diff --git a/paste/auth/basic.py b/paste/auth/basic.py index adfd5ae7..3055d527 100644 --- a/paste/auth/basic.py +++ b/paste/auth/basic.py @@ -22,9 +22,16 @@ .. [1] http://www.w3.org/Protocols/HTTP/1.0/draft-ietf-http-spec.html#BasicAA """ from base64 import b64decode + import six + from paste.httpexceptions import HTTPUnauthorized -from paste.httpheaders import * +from paste.httpheaders import ( + AUTHORIZATION, + AUTH_TYPE, + REMOTE_USER, + WWW_AUTHENTICATE, +) class AuthBasicAuthenticator(object): """ diff --git a/paste/auth/cas.py b/paste/auth/cas.py index 44e4e988..489ee65b 100644 --- a/paste/auth/cas.py +++ b/paste/auth/cas.py @@ -18,7 +18,7 @@ of processing. It has the secondary goal of allowing for other authentication methods to be used concurrently. """ -from six.moves.urllib.parse import urlencode +from urllib.parse import urlencode from paste.request import construct_url from paste.httpexceptions import HTTPSeeOther, HTTPForbidden diff --git a/paste/auth/cookie.py b/paste/auth/cookie.py index d00f17b3..74ba8af1 100644 --- a/paste/auth/cookie.py +++ b/paste/auth/cookie.py @@ -75,8 +75,7 @@ def __init__(self, content, cookie): def new_secret(): """ returns a 64 byte secret """ secret = ''.join(random.sample(_all_chars, 64)) - if six.PY3: - secret = secret.encode('utf8') + secret = secret.encode('utf8') return secret class AuthCookieSigner(object): @@ -127,7 +126,7 @@ class AuthCookieSigner(object): """ def __init__(self, secret = None, timeout = None, maxlen = None): self.timeout = timeout or 30 - if isinstance(timeout, six.string_types): + if isinstance(timeout, str): raise ValueError( "Timeout must be a number (minutes), not a string (%r)" % timeout) @@ -141,20 +140,13 @@ def sign(self, content): cookie is handled server-side in the auth() function. """ timestamp = make_time(time.time() + 60*self.timeout) - if six.PY3: - content = content.encode('utf8') - timestamp = timestamp.encode('utf8') - - if six.PY3: - cookie = base64.encodebytes( - hmac.new(self.secret, content, sha1).digest() + - timestamp + - content) - else: - cookie = base64.encodestring( - hmac.new(self.secret, content, sha1).digest() + - timestamp + - content) + content = content.encode('utf8') + timestamp = timestamp.encode('utf8') + + cookie = base64.encodebytes( + hmac.new(self.secret, content, sha1).digest() + + timestamp + + content) cookie = cookie.replace(b"/", b"_").replace(b"=", b"~") cookie = cookie.replace(b'\n', b'').replace(b'\r', b'') if len(cookie) > self.maxlen: @@ -312,8 +304,7 @@ def response_hook(status, response_headers, exc_info=None): if content: content = ";".join(content) content = self.signer.sign(content) - if six.PY3: - content = content.decode('utf8') + content = content.decode('utf8') cookie = '%s=%s; Path=/;' % (self.cookie_name, content) if 'https' == environ['wsgi.url_scheme']: cookie += ' secure;' @@ -386,7 +377,7 @@ def make_auth_cookie( which is a typical browser maximum) """ - if isinstance(scanlist, six.string_types): + if isinstance(scanlist, str): scanlist = scanlist.split() if secret is None and global_conf.get('secret'): secret = global_conf['secret'] diff --git a/paste/auth/digest.py b/paste/auth/digest.py index 8c8690c4..e787fe8d 100644 --- a/paste/auth/digest.py +++ b/paste/auth/digest.py @@ -30,14 +30,20 @@ .. [1] http://www.faqs.org/rfcs/rfc2617.html """ from paste.httpexceptions import HTTPUnauthorized -from paste.httpheaders import * +from paste.httpheaders import ( + AUTHORIZATION, + AUTH_TYPE, + PATH_INFO, + REMOTE_USER, + REQUEST_METHOD, + SCRIPT_NAME, +) try: from hashlib import md5 except ImportError: from md5 import md5 import time, random -from six.moves.urllib.parse import quote as url_quote -import six +from urllib.parse import quote as url_quote def _split_auth_string(auth_string): """ split a digest auth string into individual key=value strings """ @@ -69,8 +75,7 @@ def _auth_to_kv_pairs(auth_string): def digest_password(realm, username, password): """ construct the appropriate hashcode needed for HTTP digest """ content = "%s:%s:%s" % (username, realm, password) - if six.PY3: - content = content.encode('utf8') + content = content.encode('utf8') return md5(content).hexdigest() class AuthDigestAuthenticator(object): @@ -83,13 +88,11 @@ def __init__(self, realm, authfunc): def build_authentication(self, stale = ''): """ builds the authentication error """ content = "%s:%s" % (time.time(), random.random()) - if six.PY3: - content = content.encode('utf-8') + content = content.encode('utf-8') nonce = md5(content).hexdigest() content = "%s:%s" % (time.time(), random.random()) - if six.PY3: - content = content.encode('utf-8') + content = content.encode('utf-8') opaque = md5(content).hexdigest() self.nonce[nonce] = None @@ -107,15 +110,13 @@ def compute(self, ha1, username, response, method, if not ha1: return self.build_authentication() content = '%s:%s' % (method, path) - if six.PY3: - content = content.encode('utf8') + content = content.encode('utf8') ha2 = md5(content).hexdigest() if qop: chk = "%s:%s:%s:%s:%s:%s" % (ha1, nonce, nc, cnonce, qop, ha2) else: chk = "%s:%s:%s" % (ha1, nonce, ha2) - if six.PY3: - chk = chk.encode('utf8') + chk = chk.encode('utf8') if response != md5(chk).hexdigest(): if nonce in self.nonce: del self.nonce[nonce] diff --git a/paste/auth/grantip.py b/paste/auth/grantip.py index 3fe6e1cf..f498bee7 100644 --- a/paste/auth/grantip.py +++ b/paste/auth/grantip.py @@ -3,10 +3,9 @@ """ Grant roles and logins based on IP address. """ -import six from paste.util import ip4 -class GrantIPMiddleware(object): +class GrantIPMiddleware: """ On each request, ``ip_map`` is checked against ``REMOTE_ADDR`` @@ -35,7 +34,7 @@ def __init__(self, app, ip_map, clobber_username=True): self.clobber_username = clobber_username def _convert_user_role(self, username, roles): - if roles and isinstance(roles, six.string_types): + if roles and isinstance(roles, str): roles = roles.split(',') return (username, roles) diff --git a/paste/auth/open_id.py b/paste/auth/open_id.py index f79f7f8c..0ec3f3d0 100644 --- a/paste/auth/open_id.py +++ b/paste/auth/open_id.py @@ -58,7 +58,6 @@ import cgi import urlparse import re -import six import paste.request from paste import httpexceptions @@ -77,7 +76,7 @@ def quoteattr(s): from openid.consumer import consumer from openid.oidutil import appendArgs -class AuthOpenIDHandler(object): +class AuthOpenIDHandler: """ This middleware implements OpenID Consumer behavior to authenticate a URL against an OpenID Server. @@ -399,7 +398,7 @@ def make_open_id_middleware( from paste.deploy.converters import asbool from paste.util import import_string catch_401 = asbool(catch_401) - if url_to_username and isinstance(url_to_username, six.string_types): + if url_to_username and isinstance(url_to_username, str): url_to_username = import_string.eval_import(url_to_username) apply_auth_tkt = asbool(apply_auth_tkt) new_app = AuthOpenIDHandler( diff --git a/paste/cascade.py b/paste/cascade.py index 3f6b6617..d198564e 100644 --- a/paste/cascade.py +++ b/paste/cascade.py @@ -8,7 +8,7 @@ from paste import httpexceptions from paste.util import converters import tempfile -from six import BytesIO +from io import BytesIO __all__ = ['Cascade'] diff --git a/paste/cgiapp.py b/paste/cgiapp.py index bd45a5dd..255ef2cb 100644 --- a/paste/cgiapp.py +++ b/paste/cgiapp.py @@ -7,7 +7,7 @@ import os import sys import subprocess -from six.moves.urllib.parse import quote +from urllib.parse import quote try: import select except ImportError: @@ -24,7 +24,7 @@ class CGIError(Exception): act like a proper CGI script. """ -class CGIApplication(object): +class CGIApplication: """ This object acts as a proxy to a CGI application. You pass in the @@ -148,9 +148,8 @@ def write(self, data): name, value = line1.split(b':', 1) value = value.lstrip() name = name.strip() - if six.PY3: - name = name.decode('utf8') - value = value.decode('utf8') + name = name.decode('utf8') + value = value.decode('utf8') if name.lower() == 'status': if ' ' not in value: # WSGI requires this space, sometimes CGI scripts don't set it: diff --git a/paste/cgitb_catcher.py b/paste/cgitb_catcher.py index 0bb8e14d..b8f7e877 100644 --- a/paste/cgitb_catcher.py +++ b/paste/cgitb_catcher.py @@ -10,8 +10,7 @@ """ import cgitb -import six -from six.moves import cStringIO as StringIO +from io import StringIO import sys from paste.util import converters @@ -32,7 +31,7 @@ def __init__(self, app, global_conf = {} if display is NoDefault: display = global_conf.get('debug') - if isinstance(display, six.string_types): + if isinstance(display, str): display = converters.asbool(display) self.display = display self.logdir = logdir @@ -49,8 +48,7 @@ def __call__(self, environ, start_response): [('content-type', 'text/html')], exc_info) response = self.exception_handler(exc_info, environ) - if six.PY3: - response = response.encode('utf8') + response = response.encode('utf8') return [response] def catching_iter(self, app_iter, environ): @@ -74,8 +72,7 @@ def catching_iter(self, app_iter, environ): response += ( '
Error in .close():
%s' % close_response) - if six.PY3: - response = response.encode('utf8') + response = response.encode('utf8') yield response def exception_handler(self, exc_info, environ): diff --git a/paste/debug/prints.py b/paste/debug/prints.py index b660bfa4..87a19acc 100644 --- a/paste/debug/prints.py +++ b/paste/debug/prints.py @@ -17,13 +17,12 @@ """ -from cStringIO import StringIO +from io import StringIO import re import cgi from paste.util import threadedprint from paste import wsgilib from paste import response -import six import sys _threadedprint_installed = False @@ -36,9 +35,6 @@ def __init__(self, files): self.files = files def write(self, v): - if isinstance(v, unicode): - # WSGI is picky in this case - v = str(v) for file in self.files: file.write(v) @@ -72,7 +68,7 @@ def __init__(self, app, global_conf=None, force_content_type=False, # the entry point self.app = app self.force_content_type = force_content_type - if isinstance(print_wsgi_errors, six.string_types): + if isinstance(print_wsgi_errors, str): from paste.deploy.converters import asbool print_wsgi_errors = asbool(print_wsgi_errors) self.print_wsgi_errors = print_wsgi_errors diff --git a/paste/debug/profile.py b/paste/debug/profile.py index 470a54a8..fdbee745 100644 --- a/paste/debug/profile.py +++ b/paste/debug/profile.py @@ -12,9 +12,8 @@ import hotshot.stats import threading import cgi -import six import time -from cStringIO import StringIO +from io import StringIO from paste import response __all__ = ['ProfileMiddleware', 'profile_decorator'] @@ -201,7 +200,7 @@ def profile(self, func, *args, **kw): f.close() if exc_info: # We captured an exception earlier, now we re-raise it - six.reraise(exc_info[0], exc_info[1], exc_info[2]) + raise exc_info return result def format_function(self, func, *args, **kw): diff --git a/paste/debug/testserver.py b/paste/debug/testserver.py index 8044c7cf..2a147060 100755 --- a/paste/debug/testserver.py +++ b/paste/debug/testserver.py @@ -11,7 +11,7 @@ """ import time -from paste.httpserver import * +from paste.httpserver import WSGIServer class WSGIRegressionServer(WSGIServer): """ @@ -67,7 +67,7 @@ def serve(application, host=None, port=None, handler=None): return server if __name__ == '__main__': - from six.moves.urllib.request import urlopen + from urllib.request import urlopen from paste.wsgilib import dump_environ server = serve(dump_environ) baseuri = ("http://%s:%s" % server.server_address) diff --git a/paste/errordocument.py b/paste/errordocument.py index f7e28909..6dc7b068 100644 --- a/paste/errordocument.py +++ b/paste/errordocument.py @@ -11,11 +11,10 @@ import warnings import sys -from six.moves.urllib import parse as urlparse +from urllib import parse as urlparse from paste.recursive import ForwardRequestException, RecursiveMiddleware, RecursionLoop from paste.util import converters from paste.response import replace_header -import six def forward(app, codes): """ @@ -91,8 +90,7 @@ def keep_status_start_response(status, headers, exc_info=None): keep_status_start_response('500 Server Error', [('Content-type', 'text/plain')], sys.exc_info()) body = ('Error: %s. (Error page could not be fetched)' % self.status) - if six.PY3: - body = body.encode('utf8') + body = body.encode('utf8') return [body] diff --git a/paste/evalexception/evalcontext.py b/paste/evalexception/evalcontext.py index 42f2efa7..a7bf5d5d 100644 --- a/paste/evalexception/evalcontext.py +++ b/paste/evalexception/evalcontext.py @@ -1,15 +1,14 @@ # (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org) # Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php -from six.moves import cStringIO as StringIO +from io import StringIO import traceback import threading import pdb -import six import sys exec_lock = threading.Lock() -class EvalContext(object): +class EvalContext: """ Class that represents a interactive interface. It has its own @@ -35,7 +34,7 @@ def exec_expr(self, s): sys.stdout = out try: code = compile(s, '', "single", 0, 1) - six.exec_(code, self.globs, self.namespace) + exec(code, self.globs, self.namespace) debugger.set_continue() except KeyboardInterrupt: raise diff --git a/paste/evalexception/middleware.py b/paste/evalexception/middleware.py index 6820e784..b9ee1998 100644 --- a/paste/evalexception/middleware.py +++ b/paste/evalexception/middleware.py @@ -25,13 +25,11 @@ ``wsgi.errors``, so you can open it up in another browser window. """ -from __future__ import print_function - +import html import sys import os import traceback -import six -from six.moves import cStringIO as StringIO +from io import cStringIO as StringIO import pprint import itertools import time @@ -44,7 +42,6 @@ from paste import request from paste import response from paste.evalexception import evalcontext -from paste.util import html limit = 200 @@ -163,7 +160,7 @@ def get_debug_count(environ): if 'paste.evalexception.debug_count' in environ: return environ['paste.evalexception.debug_count'] else: - environ['paste.evalexception.debug_count'] = next = six.next(debug_counter) + environ['paste.evalexception.debug_count'] = next = next(debug_counter) return next class EvalException(object): @@ -418,8 +415,7 @@ def content(self): 'repost_button': repost_button or '', 'head_html': head_html, 'body': html} - if six.PY3: - page = page.encode('utf8') + page = page.encode('utf8') return [page] def eval_javascript(self): diff --git a/paste/exceptions/collector.py b/paste/exceptions/collector.py index 632ce066..84900013 100644 --- a/paste/exceptions/collector.py +++ b/paste/exceptions/collector.py @@ -23,7 +23,7 @@ import sys import traceback import time -from six.moves import cStringIO as StringIO +from io import StringIO import linecache from paste.exceptions import serial_number_generator import warnings diff --git a/paste/exceptions/errormiddleware.py b/paste/exceptions/errormiddleware.py index 9b533c55..2fabcb84 100644 --- a/paste/exceptions/errormiddleware.py +++ b/paste/exceptions/errormiddleware.py @@ -7,11 +7,10 @@ import sys import traceback import cgi -from six.moves import cStringIO as StringIO +from io import StringIO from paste.exceptions import formatter, collector, reporter from paste import wsgilib from paste import request -import six __all__ = ['ErrorMiddleware', 'handle_exception'] @@ -152,8 +151,7 @@ def __call__(self, environ, start_response): exc_info) # @@: it would be nice to deal with bad content types here response = self.exception_handler(exc_info, environ) - if six.PY3: - response = response.encode('utf8') + response = response.encode('utf8') return [response] finally: # clean up locals... @@ -245,8 +243,7 @@ def next(self): [('content-type', 'text/html')], exc_info) - if six.PY3: - response = response.encode('utf8') + response = response.encode('utf8') return response __next__ = next diff --git a/paste/exceptions/formatter.py b/paste/exceptions/formatter.py index 3ff7e6c2..8f78da6d 100644 --- a/paste/exceptions/formatter.py +++ b/paste/exceptions/formatter.py @@ -7,9 +7,8 @@ # @@: TODO: # Use this: http://www.zope.org/Members/tino/VisualTraceback/VisualTracebackNews -import six import re -from paste.util import html +import html from paste.util import PySourceColor def html_quote(s): @@ -77,7 +76,7 @@ def format_collected_data(self, exc_data): lines.append(self.format_long_source( source, long_source)) etype = exc_data.exception_type - if not isinstance(etype, six.string_types): + if not isinstance(etype, str): etype = etype.__name__ exc_info = self.format_exception_info( etype, diff --git a/paste/exceptions/reporter.py b/paste/exceptions/reporter.py index 7c0c2662..369f6e74 100644 --- a/paste/exceptions/reporter.py +++ b/paste/exceptions/reporter.py @@ -66,7 +66,7 @@ def check_params(self): raise ValueError("You must set to_addresses") if not self.from_address: raise ValueError("You must set from_address") - if isinstance(self.to_addresses, (str, unicode)): + if isinstance(self.to_addresses, str): self.to_addresses = [self.to_addresses] def assemble_email(self, exc_data): diff --git a/paste/exceptions/serial_number_generator.py b/paste/exceptions/serial_number_generator.py index 3f80107e..f7e11e55 100644 --- a/paste/exceptions/serial_number_generator.py +++ b/paste/exceptions/serial_number_generator.py @@ -23,7 +23,7 @@ def make_identifier(number): """ Encodes a number as an identifier. """ - if not isinstance(number, six.integer_types): + if not isinstance(number, int): raise ValueError( "You can only make identifiers out of integers (not %r)" % number) @@ -61,12 +61,11 @@ def hash_identifier(s, length, pad=True, hasher=md5, prefix='', raise ValueError( "md5 cannot create hashes longer than 26 characters in " "length (you gave %s)" % length) - if isinstance(s, six.text_type): + if isinstance(s, int): s = s.encode('utf-8') - elif not isinstance(s, six.binary_type): + elif not isinstance(s, bytes): s = str(s) - if six.PY3: - s = s.encode('utf-8') + s = s.encode('utf-8') h = hasher(s) bin_hash = h.digest() modulo = base ** length diff --git a/paste/fixture.py b/paste/fixture.py index aeb1579d..821e60d9 100644 --- a/paste/fixture.py +++ b/paste/fixture.py @@ -9,8 +9,6 @@ effects of command-line scripts. """ -from __future__ import print_function - import sys import random import mimetypes @@ -20,12 +18,12 @@ import smtplib import shlex import re -import six import subprocess -from six.moves import cStringIO as StringIO -from six.moves.urllib.parse import urlencode -from six.moves.urllib import parse as urlparse +from io import StringIO +from urllib.parse import urlencode +from urllib import parse as urlparse from six.moves.http_cookies import BaseCookie +import six from paste import wsgilib from paste import lint @@ -122,7 +120,7 @@ def __init__(self, app, namespace=None, relative_to=None, ``post_request_hook`` is a function, similar to ``pre_request_hook``, to be called after requests are made. """ - if isinstance(app, (six.binary_type, six.text_type)): + if isinstance(app, (bytes, str)): from paste.deploy import loadapp # @@: Should pick up relative_to from calling module's # __file__ @@ -185,7 +183,7 @@ def get(self, url, params=None, headers=None, extra_environ=None, extra_environ = {} __tracebackhide__ = True # Hide from pytest: if params: - if not isinstance(params, (six.binary_type, six.text_type)): + if not isinstance(params, (bytes, str)): params = urlencode(params, doseq=True) if '?' in url: url += '&' @@ -219,7 +217,7 @@ def _gen_request(self, method, url, params=b'', headers=None, extra_environ=None if hasattr(params, 'items'): # Some other multi-dict like format params = urlencode(params.items()) - if six.PY3 and isinstance(params, six.text_type): + if isinstance(params, str): params = params.encode('utf8') if upload_files: params = urlparse.parse_qsl(params, keep_blank_values=True) @@ -235,7 +233,7 @@ def _gen_request(self, method, url, params=b'', headers=None, extra_environ=None environ['QUERY_STRING'] = '' environ['CONTENT_LENGTH'] = str(len(params)) environ['REQUEST_METHOD'] = method - environ['wsgi.input'] = six.BytesIO(params) + environ['wsgi.input'] = io.BytesIO(params) self._set_headers(headers, environ) environ.update(extra_environ) req = TestRequest(url, environ, expect_errors) @@ -330,8 +328,7 @@ def encode_multipart(self, params, files): """ boundary = '----------a_BoUnDaRy%s$' % random.random() content_type = 'multipart/form-data; boundary=%s' % boundary - if six.PY3: - boundary = boundary.encode('ascii') + boundary = boundary.encode('ascii') lines = [] for key, value in params: @@ -452,8 +449,7 @@ def _check_status(self, status, res): if res.status >= 200 and res.status < 400: return body = res.body - if six.PY3: - body = body.decode('utf8', 'xmlcharrefreplace') + body = body.decode('utf8', 'xmlcharrefreplace') raise AppError( "Bad response: %s (not 200 OK or 3xx redirect for %s)\n%s" % (res.full_status, res.request.url, @@ -556,8 +552,7 @@ def _parse_forms(self): form_texts = [] started = None body = self.body - if not six.PY2: - body = body.decode('utf8', 'xmlcharrefreplace') + body = body.decode('utf8', 'xmlcharrefreplace') for match in self._tag_re.finditer(body): end = match.group(1) == '/' tag = match.group(2).lower() @@ -813,9 +808,9 @@ def __contains__(self, s): of the response. Whitespace is normalized when searching for a string. """ - if not isinstance(s, (six.binary_type, six.text_type)): + if not isinstance(s, (bytes, str)): s = str(s) - if isinstance(s, six.text_type): + if isinstance(s, str): ## FIXME: we don't know that this response uses utf8: s = s.encode('utf8') return (self.body.find(s) != -1 @@ -833,7 +828,7 @@ def mustcontain(self, *strings, **kw): if 'no' in kw: no = kw['no'] del kw['no'] - if isinstance(no, (six.binary_type, six.text_type)): + if isinstance(no, (bytes, str)): no = [no] else: no = [] @@ -855,16 +850,14 @@ def mustcontain(self, *strings, **kw): def __repr__(self): body = self.body - if six.PY3: - body = body.decode('utf8', 'xmlcharrefreplace') + body = body.decode('utf8', 'xmlcharrefreplace') body = body[:20] return '' % (self.full_status, body) def __str__(self): simple_body = b'\n'.join([l for l in self.body.splitlines() if l.strip()]) - if six.PY3: - simple_body = simple_body.decode('utf8', 'xmlcharrefreplace') + simple_body = simple_body.decode('utf8', 'xmlcharrefreplace') return 'Response: %s\n%s\n%s' % ( self.status, '\n'.join(['%s: %s' % (n, v) for n, v in self.headers]), @@ -1713,7 +1706,7 @@ def _space_prefix(pref, full, sep=None, indent=None, include_sep=True): def _make_pattern(pat): if pat is None: return None - if isinstance(pat, (six.binary_type, six.text_type)): + if isinstance(pat, (bytes, str)): pat = re.compile(pat) if hasattr(pat, 'search'): return pat.search @@ -1740,7 +1733,7 @@ def setup_module(module=None): if module is None: # The module we were called from must be the module... module = sys._getframe().f_back.f_globals['__name__'] - if isinstance(module, (six.binary_type, six.text_type)): + if isinstance(module, (bytes, str)): module = sys.modules[module] if hasattr(module, 'reset_state'): module.reset_state() diff --git a/paste/gzipper.py b/paste/gzipper.py index 0882c677..fa55eeaa 100644 --- a/paste/gzipper.py +++ b/paste/gzipper.py @@ -11,9 +11,10 @@ """ import gzip +import io + from paste.response import header_value, remove_header from paste.httpheaders import CONTENT_LENGTH -import six class GzipOutput(object): pass @@ -45,7 +46,7 @@ class GzipResponse(object): def __init__(self, start_response, compress_level): self.start_response = start_response self.compress_level = compress_level - self.buffer = six.BytesIO() + self.buffer = io.BytesIO() self.compressible = False self.content_length = None diff --git a/paste/httpexceptions.py b/paste/httpexceptions.py index 0b68c2df..3d7dfeac 100644 --- a/paste/httpexceptions.py +++ b/paste/httpexceptions.py @@ -74,7 +74,6 @@ """ -import six from paste.wsgilib import catch_errors_app from paste.response import has_header, header_value, replace_header from paste.request import resolve_relative_url @@ -178,9 +177,9 @@ def __init__(self, detail=None, headers=None, comment=None): assert isinstance(headers, (type(None), list)), ( "headers must be None or a list: %r" % headers) - assert isinstance(detail, (type(None), six.binary_type, six.text_type)), ( + assert isinstance(detail, (type(None), bytes, str)), ( "detail must be None or a string: %r" % detail) - assert isinstance(comment, (type(None), six.binary_type, six.text_type)), ( + assert isinstance(comment, (type(None), bytes, str)), ( "comment must be None or a string: %r" % comment) self.headers = headers or tuple() for req in self.required_headers: @@ -206,10 +205,6 @@ def make_body(self, environ, template, escfunc, comment_escfunc=None): if self.headers: for (k, v) in self.headers: args[k.lower()] = escfunc(v) - if six.PY2: - for key, value in args.items(): - if isinstance(value, six.text_type): - args[key] = value.encode('utf8', 'xmlcharrefreplace') return template % args def plain(self, environ): @@ -238,7 +233,7 @@ def prepare_content(self, environ): else: replace_header(headers, 'content-type', 'text/plain') content = self.plain(environ) - if isinstance(content, six.text_type): + if isinstance(content, str): content = content.encode('utf8') cur_content_type = ( header_value(headers, 'content-type') @@ -594,8 +589,8 @@ class HTTPVersionNotSupported(HTTPServerError): __all__ = ['HTTPException', 'HTTPRedirection', 'HTTPError' ] _exceptions = {} -for name, value in six.iteritems(dict(globals())): - if (isinstance(value, (type, six.class_types)) and +for name, value in dict(globals()).items(): + if (isinstance(value, type) and issubclass(value, HTTPException) and value.code): _exceptions[value.code] = value diff --git a/paste/httpheaders.py b/paste/httpheaders.py index 54571387..a1e91a9b 100644 --- a/paste/httpheaders.py +++ b/paste/httpheaders.py @@ -135,16 +135,9 @@ """ import mimetypes -import six from time import time as now -try: - # Python 3 - from email.utils import formatdate, parsedate_tz, mktime_tz - from urllib.request import AbstractDigestAuthHandler, parse_keqv_list, parse_http_list -except ImportError: - # Python 2 - from rfc822 import formatdate, parsedate_tz, mktime_tz - from urllib2 import AbstractDigestAuthHandler, parse_keqv_list, parse_http_list +from email.utils import formatdate, parsedate_tz, mktime_tz +from urllib.request import AbstractDigestAuthHandler, parse_keqv_list, parse_http_list from .httpexceptions import HTTPBadRequest @@ -171,7 +164,7 @@ def update(self, environ, value): SCRIPT_NAME = EnvironVariable("SCRIPT_NAME") PATH_INFO = EnvironVariable("PATH_INFO") -for _name, _obj in six.iteritems(dict(globals())): +for _name, _obj in dict(globals()).items(): if isinstance(_obj, EnvironVariable): __all__.append(_name) @@ -737,7 +730,7 @@ def _compose(self, public=None, private=None, no_cache=None, result.append('max-age=%d' % max_age) if s_maxage is not None: result.append('s-maxage=%d' % s_maxage) - for (k, v) in six.iteritems(extensions): + for (k, v) in extensions.items(): if k not in self.extensions: raise AssertionError("unexpected extension used: '%s'" % k) result.append('%s="%s"' % (k.replace("_", "-"), v)) @@ -1016,24 +1009,15 @@ def compose(self, digest=None, basic=None, username=None, password=None, (token, challenge) = challenge.split(' ', 1) chal = parse_keqv_list(parse_http_list(challenge)) class FakeRequest(object): - if six.PY3: - @property - def full_url(self): - return path + @property + def full_url(self): + return path - selector = full_url + selector = full_url - @property - def data(self): - return None - else: - def get_full_url(self): - return path - - get_selector = get_full_url - - def has_data(self): - return False + @property + def data(self): + return None def get_method(self): return method or "GET" @@ -1111,6 +1095,6 @@ def get_method(self): __all__.append(headname) __pudge_all__ = __all__[:] -for _name, _obj in six.iteritems(dict(globals())): +for _name, _obj in dict(globals()).items(): if isinstance(_obj, type) and issubclass(_obj, HTTPHeader): __pudge_all__.append(_name) diff --git a/paste/httpserver.py b/paste/httpserver.py index 8023bfda..50dc3c6e 100755 --- a/paste/httpserver.py +++ b/paste/httpserver.py @@ -17,13 +17,11 @@ # @@: add support for chunked encoding, this is not a 1.1 server # till this is completed. -from __future__ import print_function import atexit import traceback import io import socket, sys, threading import posixpath -import six import time import os from itertools import count @@ -31,7 +29,7 @@ from six.moves import queue from six.moves.BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer from six.moves.socketserver import ThreadingMixIn -from six.moves.urllib.parse import unquote, urlsplit +from urllib.parse import unquote, urlsplit from paste.util import converters import logging try: @@ -171,7 +169,7 @@ def wsgi_start_response(self, status, response_headers, exc_info=None): if exc_info: try: if self.wsgi_headers_sent: - six.reraise(exc_info[0], exc_info[1], exc_info[2]) + raise exc_info else: # In this case, we're going to assume that the # higher-level code is currently handling the @@ -602,7 +600,7 @@ def __init__( self.daemon = daemon if logger is None: logger = logging.getLogger('paste.httpserver.ThreadPool') - if isinstance(logger, six.string_types): + if isinstance(logger, str): logger = logging.getLogger(logger) self.logger = logger self.error_email = error_email @@ -760,7 +758,7 @@ def thread_exists(self, thread_id): return thread_id in threading._active def add_worker_thread(self, *args, **kwargs): - index = six.next(self._worker_count) + index = next(self._worker_count) worker = threading.Thread(target=self.worker_thread_callback, args=args, kwargs=kwargs, name=("worker %d" % index)) @@ -803,7 +801,7 @@ def kill_hung_threads(self): import pprint info_desc = pprint.pformat(info) except: - out = six.StringIO() + out = io.StringIO() traceback.print_exc(file=out) info_desc = 'Error:\n%s' % out.getvalue() self.notify_problem( @@ -917,8 +915,6 @@ def worker_thread_callback(self, message=None): del self.worker_tracker[thread_id] except KeyError: pass - if six.PY2: - sys.exc_clear() self.idle_workers.append(thread_id) finally: try: diff --git a/paste/lint.py b/paste/lint.py index 7e5ac79a..0e2093ce 100644 --- a/paste/lint.py +++ b/paste/lint.py @@ -110,7 +110,6 @@ """ import re -import six import sys import warnings @@ -185,12 +184,12 @@ def __init__(self, wsgi_input): def read(self, *args): assert len(args) <= 1 v = self.input.read(*args) - assert isinstance(v, six.binary_type) + assert isinstance(v, bytes) return v def readline(self, *args): v = self.input.readline(*args) - assert isinstance(v, six.binary_type) + assert isinstance(v, bytes) return v def readlines(self, *args): @@ -198,7 +197,7 @@ def readlines(self, *args): lines = self.input.readlines(*args) assert isinstance(lines, list) for line in lines: - assert isinstance(line, six.binary_type) + assert isinstance(line, bytes) return lines def __iter__(self): @@ -217,7 +216,7 @@ def __init__(self, wsgi_errors): self.errors = wsgi_errors def write(self, s): - assert isinstance(s, six.string_types) + assert isinstance(s, str) self.errors.write(s) def flush(self): @@ -236,7 +235,7 @@ def __init__(self, wsgi_writer): self.writer = wsgi_writer def __call__(self, s): - assert isinstance(s, six.binary_type) + assert isinstance(s, bytes) self.writer(s) class PartialIteratorWrapper(object): @@ -262,7 +261,7 @@ def __iter__(self): def next(self): assert not self.closed, ( "Iterator read after closed") - v = six.next(self.iterator) + v = next(self.iterator) if self.check_start_response is not None: assert self.check_start_response, ( "The application returns and we started iterating over its body, but start_response has not yet been called") diff --git a/paste/modpython.py b/paste/modpython.py index d20a588f..a84f7b2d 100644 --- a/paste/modpython.py +++ b/paste/modpython.py @@ -49,7 +49,6 @@ http://projects.amor.org/misc/svn/modpython_gateway.py """ -import six import traceback try: @@ -177,7 +176,7 @@ def start_response(self, status, headers, exc_info=None): if exc_info: try: if self.started: - six.reraise(exc_info[0], exc_info[1], exc_info[2]) + raise exc_info finally: exc_info = None diff --git a/paste/proxy.py b/paste/proxy.py index 67d4b1be..0ca7ff74 100644 --- a/paste/proxy.py +++ b/paste/proxy.py @@ -30,9 +30,8 @@ """ from six.moves import http_client as httplib -from six.moves.urllib import parse as urlparse -from six.moves.urllib.parse import quote -import six +from urllib import parse as urlparse +from urllib.parse import quote from paste import httpexceptions from paste.util.converters import aslist @@ -252,31 +251,9 @@ def parse_headers(message): Turn a Message object into a list of WSGI-style headers. """ headers_out = [] - if six.PY3: - for header, value in message.items(): - if header.lower() not in filtered_headers: - headers_out.append((header, value)) - else: - for full_header in message.headers: - if not full_header: - # Shouldn't happen, but we'll just ignore - continue - if full_header[0].isspace(): - # Continuation line, add to the last header - if not headers_out: - raise ValueError( - "First header starts with a space (%r)" % full_header) - last_header, last_value = headers_out.pop() - value = last_value + ' ' + full_header.strip() - headers_out.append((last_header, value)) - continue - try: - header, value = full_header.split(':', 1) - except: - raise ValueError("Invalid header: %r" % full_header) - value = value.strip() - if header.lower() not in filtered_headers: - headers_out.append((header, value)) + for header, value in message.items(): + if header.lower() not in filtered_headers: + headers_out.append((header, value)) return headers_out def make_transparent_proxy( diff --git a/paste/recursive.py b/paste/recursive.py index 0bef920e..897d6f39 100644 --- a/paste/recursive.py +++ b/paste/recursive.py @@ -23,9 +23,8 @@ (aborting the current request). """ -import six import warnings -from six.moves import cStringIO as StringIO +from io import StringIO __all__ = ['RecursiveMiddleware'] __pudge_all__ = ['RecursiveMiddleware', 'ForwardRequestException'] @@ -320,7 +319,7 @@ def activate(self, environ): response = IncludedResponse() def start_response(status, headers, exc_info=None): if exc_info: - six.reraise(exc_info[0], exc_info[1], exc_info[2]) + raise exc_info response.status = status response.headers = headers return response.write @@ -374,7 +373,7 @@ def activate(self, environ): response = IncludedAppIterResponse() def start_response(status, headers, exc_info=None): if exc_info: - six.reraise(exc_info[0], exc_info[1], exc_info[2]) + raise exc_info response.status = status response.headers = headers return response.write diff --git a/paste/registry.py b/paste/registry.py index e218e031..02623d48 100644 --- a/paste/registry.py +++ b/paste/registry.py @@ -89,7 +89,6 @@ def somefunc(): quick way to work around it is documented. """ -import six import paste.util.threadinglocal as threadinglocal __all__ = ['StackedObjectProxy', 'RegistryManager', 'StackedObjectRestorer', @@ -348,7 +347,7 @@ def multiregister(self, stacklist): def cleanup(self): """Remove all objects from all StackedObjectProxy instances that were tracked at this Registry context""" - for stacked, obj in six.itervalues(self.reglist[-1]): + for stacked, obj in self.reglist[-1].values(): stacked._pop_object(obj) self.reglist.pop() @@ -501,7 +500,7 @@ def save_registry_state(self, environ): # their methods to act differently when a restoration context is active # in the current thread for reglist in registry.reglist: - for stacked, obj in six.itervalues(reglist): + for stacked, obj in reglist.values(): self.enable_restoration(stacked) def get_saved_proxied_obj(self, stacked, request_id): diff --git a/paste/reloader.py b/paste/reloader.py index 0193dca8..97440ac7 100644 --- a/paste/reloader.py +++ b/paste/reloader.py @@ -40,7 +40,6 @@ def watch_config_files(): ``watch_config_files`` and check all the filenames it returns. """ -from __future__ import print_function import os import sys import time diff --git a/paste/request.py b/paste/request.py index 30d40bfe..bb0d9eec 100644 --- a/paste/request.py +++ b/paste/request.py @@ -18,20 +18,10 @@ """ import cgi -from six.moves.urllib import parse as urlparse -from six.moves.urllib.parse import quote, parse_qsl -try: - # Python 3 - from http.cookies import SimpleCookie, CookieError -except ImportError: - # Python 2 - from Cookie import SimpleCookie, CookieError - -try: - from UserDict import DictMixin -except ImportError: - from collections.abc import MutableMapping as DictMixin -import six +from collections.abc import MutableMapping as DictMixin +from urllib import parse as urlparse +from urllib.parse import quote, parse_qsl +from http.cookies import SimpleCookie, CookieError from paste.util.multidict import MultiDict @@ -174,11 +164,10 @@ def parse_formvars(environ, include_get_vars=True, encoding=None, errors=None): environ['QUERY_STRING'] = '' inp = environ['wsgi.input'] kwparms = {} - if six.PY3: - if encoding: - kwparms['encoding'] = encoding - if errors: - kwparms['errors'] = errors + if encoding: + kwparms['encoding'] = encoding + if errors: + kwparms['errors'] = errors fs = cgi.FieldStorage(fp=inp, environ=environ, keep_blank_values=True, diff --git a/paste/session.py b/paste/session.py index ae208e72..09f6c196 100644 --- a/paste/session.py +++ b/paste/session.py @@ -23,17 +23,11 @@ expired. """ -try: - # Python 3 - from http.cookies import SimpleCookie -except ImportError: - # Python 2 - from Cookie import SimpleCookie +from http.cookies import SimpleCookie import time import random import os import datetime -import six import threading import tempfile @@ -48,7 +42,7 @@ from paste import wsgilib from paste import request -class SessionMiddleware(object): +class SessionMiddleware: def __init__(self, application, global_conf=None, **factory_kw): self.application = application @@ -149,8 +143,7 @@ def unique_id(self, for_object=None): if for_object is not None: r.append(id(for_object)) content = str(r) - if six.PY3: - content = content.encode('utf8') + content = content.encode('utf8') md5_hash = md5(content) try: return md5_hash.hexdigest() @@ -188,7 +181,7 @@ def __init__(self, sid, create=False, session_file_path=tempfile.gettempdir(), chmod=None, expiration=2880, # in minutes: 48 hours ): - if chmod and isinstance(chmod, (six.binary_type, six.text_type)): + if chmod and isinstance(chmod, (bytes, str)): chmod = int(chmod, 8) self.chmod = chmod if not sid: diff --git a/paste/translogger.py b/paste/translogger.py index 56d2831e..3a898dde 100644 --- a/paste/translogger.py +++ b/paste/translogger.py @@ -5,11 +5,10 @@ """ import logging -import six import time from six.moves.urllib.parse import quote -class TransLogger(object): +class TransLogger: """ This logging middleware will log all requests as they go through. They are, by default, sent to a logger named ``'wsgi'`` at the @@ -115,9 +114,9 @@ def make_filter( setup_console_handler=True, set_logger_level=logging.DEBUG): from paste.util.converters import asbool - if isinstance(logging_level, (six.binary_type, six.text_type)): + if isinstance(logging_level, (bytes, str)): logging_level = logging._levelNames[logging_level] - if isinstance(set_logger_level, (six.binary_type, six.text_type)): + if isinstance(set_logger_level, (bytes, str)): set_logger_level = logging._levelNames[set_logger_level] return TransLogger( app, diff --git a/paste/url.py b/paste/url.py index b13d5756..00d44016 100644 --- a/paste/url.py +++ b/paste/url.py @@ -4,10 +4,9 @@ """ This module implements a class for handling URLs. """ -from six.moves.urllib.parse import parse_qsl, quote, unquote, urlencode +import html +from urllib.parse import parse_qsl, quote, unquote, urlencode from paste import request -import six -from paste.util import html # Imported lazily from FormEncode: variabledecode = None @@ -39,13 +38,8 @@ def js_repr(v): for key, value in v]) elif isinstance(v, str): return repr(v) - elif isinstance(v, unicode): - # @@: how do you do Unicode literals in Javascript? - return repr(v.encode('UTF-8')) elif isinstance(v, (float, int)): return repr(v) - elif isinstance(v, long): - return repr(v).lstrip('L') elif hasattr(v, '__js_repr__'): return v.__js_repr__() else: @@ -53,7 +47,7 @@ def js_repr(v): "I don't know how to turn %r into a Javascript representation" % v) -class URLResource(object): +class URLResource: """ This is an abstract superclass for different kinds of URLs @@ -184,10 +178,7 @@ def addpath(self, *paths): params=u.original_params) return u - if six.PY3: - __truediv__ = addpath - else: - __div__ = addpath + __truediv__ = addpath def become(self, OtherClass): return OtherClass(self.url, vars=self.vars, diff --git a/paste/urlmap.py b/paste/urlmap.py index 3e05c270..8ef1da05 100644 --- a/paste/urlmap.py +++ b/paste/urlmap.py @@ -4,15 +4,10 @@ Map URL prefixes to WSGI applications. See ``URLMap`` """ +import html import re import os -from paste.util import html -try: - # Python 3 - from collections.abc import MutableMapping as DictMixin -except ImportError: - # Python 2 - from UserDict import DictMixin +from collections.abc import MutableMapping as DictMixin from paste import httpexceptions @@ -241,7 +236,7 @@ def __init__(self, map, base_paste_url, base_path, builder): self.builder = builder def __setitem__(self, url, app): - if isinstance(app, (str, unicode)): + if isinstance(app, str): app_fn = os.path.join(self.base_path, app) app = self.builder(app_fn) url = self.map.normalize_url(url) diff --git a/paste/urlparser.py b/paste/urlparser.py index d4a67ce3..53539543 100644 --- a/paste/urlparser.py +++ b/paste/urlparser.py @@ -5,13 +5,8 @@ """ import os -import six import sys - -if six.PY2: - import imp -else: - import importlib.util as imputil +import importlib.util as imputil import mimetypes try: @@ -139,7 +134,7 @@ def __init__(self, global_conf, "'constructor .ext = import_expr'; you gave %r " "(=%r)" % (name, value)) ext = name[len('constructor '):].strip() - if isinstance(value, (str, unicode)): + if isinstance(value, str): value = import_string.eval_import(value) self.constructors[ext] = value @@ -392,22 +387,12 @@ def load_module_from_name(environ, filename, module_name, errors): base_name = module_name module = None - if six.PY2: - fp = None - try: - fp, pathname, stuff = imp.find_module( - base_name, [os.path.dirname(filename)]) - module = imp.load_module(module_name, fp, pathname, stuff) - finally: - if fp is not None: - fp.close() - else: - # imp is deprecated and will be removed in Python 3.12 - spec = imputil.spec_from_file_location(base_name, filename) - if spec is not None: - module = imputil.module_from_spec(spec) - sys.modules[base_name] = module - spec.loader.exec_module(module) + # imp is deprecated and will be removed in Python 3.12 + spec = imputil.spec_from_file_location(base_name, filename) + if spec is not None: + module = imputil.module_from_spec(spec) + sys.modules[base_name] = module + spec.loader.exec_module(module) return module @@ -541,7 +526,7 @@ class PkgResourcesParser(StaticURLParser): def __init__(self, egg_or_spec, resource_name, manager=None, root_resource=None): if pkg_resources is None: raise NotImplementedError("This class requires pkg_resources.") - if isinstance(egg_or_spec, (six.binary_type, six.text_type)): + if isinstance(egg_or_spec, (bytes, str)): self.egg = pkg_resources.get_distribution(egg_or_spec) else: self.egg = egg_or_spec diff --git a/paste/util/PySourceColor.py b/paste/util/PySourceColor.py index c576eada..3d7f5cc5 100644 --- a/paste/util/PySourceColor.py +++ b/paste/util/PySourceColor.py @@ -195,7 +195,7 @@ def / name import token import tokenize import traceback -from six.moves import cStringIO as StringIO +from io import StringIO # Do not edit NAME = token.NAME NUMBER = token.NUMBER diff --git a/paste/util/converters.py b/paste/util/converters.py index 11451bc2..fd379759 100644 --- a/paste/util/converters.py +++ b/paste/util/converters.py @@ -1,11 +1,9 @@ # (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org) # Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php -import six - def asbool(obj): - if isinstance(obj, (six.binary_type, six.text_type)): + if isinstance(obj, (bytes, str)): obj = obj.strip().lower() if obj in ['true', 'yes', 'on', 'y', 't', '1']: return True @@ -17,7 +15,7 @@ def asbool(obj): return bool(obj) def aslist(obj, sep=None, strip=True): - if isinstance(obj, (six.binary_type, six.text_type)): + if isinstance(obj, (bytes, str)): lst = obj.split(sep) if strip: lst = [v.strip() for v in lst] diff --git a/paste/util/finddata.py b/paste/util/finddata.py index 6cc64161..764238fa 100644 --- a/paste/util/finddata.py +++ b/paste/util/finddata.py @@ -4,7 +4,6 @@ # you can't import this from another package, when you don't know if # that package is installed yet. -from __future__ import print_function import sys from fnmatch import fnmatchcase from pathlib import Path diff --git a/paste/util/html.py b/paste/util/html.py deleted file mode 100644 index b0e2ab33..00000000 --- a/paste/util/html.py +++ /dev/null @@ -1,24 +0,0 @@ -# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php - -"""Provide an html.escape method that is python method safe.""" - -import six - -if six.PY3: - from html import escape -else: - # This is a copy from Python3. - def escape(s, quote=True): - """ - Replace special characters "&", "<" and ">" to HTML-safe sequences. If - the optional flag quote is true (the default), the quotation mark - characters, both double quote (") and single quote (') characters are - also translated. - """ - s = s.replace("&", "&") # Must be done first! - s = s.replace("<", "<") - s = s.replace(">", ">") - if quote: - s = s.replace('"', """) - s = s.replace('\'', "'") - return s diff --git a/paste/util/intset.py b/paste/util/intset.py index 3e026e29..40d5566d 100644 --- a/paste/util/intset.py +++ b/paste/util/intset.py @@ -6,7 +6,6 @@ Copyright (C) 2006, Heiko Wundram. Released under the MIT license. """ -import six # Version information # ------------------- @@ -20,7 +19,7 @@ # Utility classes # --------------- -class _Infinity(object): +class _Infinity: """Internal type used to represent infinity values.""" __slots__ = ["_neg"] @@ -63,7 +62,7 @@ def __ne__(self,value): def __repr__(self): return "None" -_VALID_TYPES = six.integer_types + (_Infinity,) +_VALID_TYPES = (int, _Infinity) @@ -121,19 +120,19 @@ def __init__(self,*args,**kwargs): # Check keyword arguments. if kwargs: raise ValueError("Invalid keyword argument.") - if not ( isinstance(self._min, six.integer_types) or self._min is _MININF ): + if not ( isinstance(self._min, int) or self._min is _MININF ): raise TypeError("Invalid type of min argument.") - if not ( isinstance(self._max, six.integer_types) or self._max is _MAXINF ): + if not ( isinstance(self._max, int) or self._max is _MAXINF ): raise TypeError("Invalid type of max argument.") if ( self._min is not _MININF and self._max is not _MAXINF and self._min > self._max ): raise ValueError("Minimum is not smaller than maximum.") - if isinstance(self._max, six.integer_types): + if isinstance(self._max, int): self._max += 1 # Process arguments. for arg in args: - if isinstance(arg, six.integer_types): + if isinstance(arg, int): start, stop = arg, arg+1 elif isinstance(arg,tuple): if len(arg) != 2: @@ -147,14 +146,14 @@ def __init__(self,*args,**kwargs): stop = self._max # Check arguments. - if not ( isinstance(start, six.integer_types) or start is _MININF ): + if not ( isinstance(start, int) or start is _MININF ): raise TypeError("Invalid type of tuple start.") - if not ( isinstance(stop, six.integer_types) or stop is _MAXINF ): + if not ( isinstance(stop, int) or stop is _MAXINF ): raise TypeError("Invalid type of tuple stop.") if ( start is not _MININF and stop is not _MAXINF and start > stop ): continue - if isinstance(stop, six.integer_types): + if isinstance(stop, int): stop += 1 else: raise TypeError("Invalid argument.") @@ -215,7 +214,7 @@ def _normalize(self): def __coerce__(self,other): if isinstance(other,IntSet): return self, other - elif isinstance(other, six.integer_types + (tuple,)): + elif isinstance(other, (int, tuple,)): try: return self, self.__class__(other) except TypeError: @@ -458,7 +457,7 @@ def __iter__(self): elif r[1] is _MAXINF: ubranges.append([r[0],1]) else: - for val in xrange(r[0],r[1]): + for val in range(r[0],r[1]): yield val if ubranges: while True: @@ -475,10 +474,10 @@ def __repr__(self): rv = [] for start, stop in self._ranges: - if ( isinstance(start, six.integer_types) and isinstance(stop, six.integer_types) + if ( isinstance(start, int) and isinstance(stop, int) and stop-start == 1 ): rv.append("%r" % start) - elif isinstance(stop, six.integer_types): + elif isinstance(stop, int): rv.append("(%r,%r)" % (start,stop-1)) else: rv.append("(%r,%r)" % (start,stop)) diff --git a/paste/util/ip4.py b/paste/util/ip4.py index 9ce17b8d..8c486537 100644 --- a/paste/util/ip4.py +++ b/paste/util/ip4.py @@ -21,7 +21,6 @@ from paste.util import intset import socket -import six # IP4Range class @@ -88,14 +87,14 @@ def __init__(self,*args): addr1, addr2 = argval if isinstance(addr1,str): addr1 = self._parseAddrRange(addr1)[0] - elif not isinstance(addr1, six.integer_types): + elif not isinstance(addr1, int): raise TypeError("Invalid argument.") if isinstance(addr2,str): addr2 = self._parseAddrRange(addr2)[1] - elif not isinstance(addr2, six.integer_types): + elif not isinstance(addr2, int): raise TypeError("Invalid argument.") args[i] = (addr1,addr2) - elif not isinstance(argval, six.integer_types): + elif not isinstance(argval, int): raise TypeError("Invalid argument.") # Initialize the integer set. diff --git a/paste/util/killthread.py b/paste/util/killthread.py index 4df4f424..a79fb226 100644 --- a/paste/util/killthread.py +++ b/paste/util/killthread.py @@ -1,7 +1,6 @@ """ Kill a thread, from http://sebulba.wikispaces.com/recipe+thread2 """ -import six try: import ctypes except ImportError: @@ -16,7 +15,7 @@ def async_raise(tid, exctype): tid is the value given by thread.get_ident() (an integer). Raise SystemExit to kill a thread.""" - if not isinstance(exctype, (six.class_types, type)): + if not isinstance(exctype, type): raise TypeError("Only types can be raised (not instances)") if not isinstance(tid, int): raise TypeError("tid must be an integer") diff --git a/paste/util/looper.py b/paste/util/looper.py index b56358a7..b28abc7c 100644 --- a/paste/util/looper.py +++ b/paste/util/looper.py @@ -20,10 +20,8 @@ __all__ = ['looper'] -import six - -class looper(object): +class looper: """ Helper for looping (particularly in templates) @@ -44,7 +42,7 @@ def __repr__(self): return '<%s for %r>' % ( self.__class__.__name__, self.seq) -class looper_iter(object): +class looper_iter: def __init__(self, seq): self.seq = list(seq) @@ -141,7 +139,7 @@ def last_group(self, getter=None): def _compare_group(self, item, other, getter): if getter is None: return item != other - elif (isinstance(getter, (six.binary_type, six.text_type)) + elif (isinstance(getter, (bytes, str)) and getter.startswith('.')): getter = getter[1:] if getter.endswith('()'): diff --git a/paste/util/multidict.py b/paste/util/multidict.py index 0a304d37..2db51254 100644 --- a/paste/util/multidict.py +++ b/paste/util/multidict.py @@ -2,15 +2,8 @@ # Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php import cgi import copy -import six import sys - -try: - # Python 3 - from collections.abc import MutableMapping as DictMixin -except ImportError: - # Python 2 - from UserDict import DictMixin +from collections.abc import MutableMapping as DictMixin class MultiDict(DictMixin): @@ -34,7 +27,7 @@ def __init__(self, *args, **kw): self._items = list(items) else: self._items = [] - self._items.extend(six.iteritems(kw)) + self._items.extend(kw.items()) def __getitem__(self, key): for k, v in self._items: @@ -265,13 +258,11 @@ def _decode_value(self, value): """ if isinstance(value, cgi.FieldStorage): # decode FieldStorage's field name and filename - decode_name = self.decode_keys and isinstance(value.name, six.binary_type) - if six.PY2 or decode_name: + decode_name = self.decode_keys and isinstance(value.name, bytes) + if decode_name: value = copy.copy(value) if decode_name: value.name = value.name.decode(self.encoding, self.errors) - if six.PY2: - value.filename = value.filename.decode(self.encoding, self.errors) else: try: value = value.decode(self.encoding, self.errors) @@ -318,7 +309,7 @@ def mixed(self): request. """ unicode_mixed = {} - for key, value in six.iteritems(self.multi.mixed()): + for key, value in self.multi.mixed().items(): if isinstance(value, list): value = [self._decode_value(value) for value in value] else: @@ -332,7 +323,7 @@ def dict_of_lists(self): list of values. """ unicode_dict = {} - for key, value in six.iteritems(self.multi.dict_of_lists()): + for key, value in self.multi.dict_of_lists().items(): value = [self._decode_value(value) for value in value] unicode_dict[self._decode_key(key)] = value return unicode_dict @@ -388,10 +379,10 @@ def iterkeys(self): def items(self): return [(self._decode_key(k), self._decode_value(v)) for \ - k, v in six.iteritems(self.multi)] + k, v in self.multi.items()] def iteritems(self): - for k, v in six.iteritems(self.multi): + for k, v in self.multi.items(): yield (self._decode_key(k), self._decode_value(v)) def values(self): diff --git a/paste/util/quoting.py b/paste/util/quoting.py index b3d28a49..72369e1e 100644 --- a/paste/util/quoting.py +++ b/paste/util/quoting.py @@ -1,12 +1,12 @@ # (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org) # Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php -import six import re from six.moves import html_entities -from six.moves.urllib.parse import quote, unquote +from urllib.parse import quote, unquote +import six -from paste.util import html +import html __all__ = ['html_quote', 'html_unquote', 'url_quote', 'url_unquote', @@ -22,21 +22,12 @@ def html_quote(v, encoding=None): encoding = encoding or default_encoding if v is None: return '' - elif isinstance(v, six.binary_type): - if six.PY3: - return html.escape(v.decode(encoding), 1).encode(encoding) - else: - return html.escape(v, 1) - elif isinstance(v, six.text_type): - if six.PY3: - return html.escape(v, 1) - else: - return html.escape(v.encode(encoding), 1) + elif isinstance(v, bytes): + return html.escape(v.decode(encoding), 1).encode(encoding) + elif isinstance(v, str): + return html.escape(v, 1) else: - if six.PY3: - return html.escape(six.text_type(v), 1) - else: - return html.escape(six.text_type(v).encode(encoding), 1) + return html.escape(str(v), 1) _unquote_re = re.compile(r'&([a-zA-Z]+);') def _entity_subber(match, name2c=html_entities.name2codepoint): @@ -51,7 +42,7 @@ def html_unquote(s, encoding=None): Decode the value. """ - if isinstance(s, six.binary_type): + if isinstance(s, bytes): s = s.decode(encoding or default_encoding) return _unquote_re.sub(_entity_subber, s) diff --git a/paste/util/scgiserver.py b/paste/util/scgiserver.py index 1c86c868..f49371b5 100644 --- a/paste/util/scgiserver.py +++ b/paste/util/scgiserver.py @@ -25,7 +25,6 @@ def __init__(self, *args, **kwargs): writing a nice extensible SCGI server for Python! """ -import six import sys import time from scgi import scgi_server @@ -91,7 +90,7 @@ def start_response(status, response_headers, exc_info=None): try: if headers_sent: # Re-raise original exception if headers sent - six.reraise(exc_info[0], exc_info[1], exc_info[2]) + raise exc_info finally: exc_info = None # avoid dangling circular ref elif headers_set: diff --git a/paste/util/template.py b/paste/util/template.py index c1f22f38..eec35f1f 100644 --- a/paste/util/template.py +++ b/paste/util/template.py @@ -34,7 +34,7 @@ def foo(bar): import six import sys from html import escape -from six.moves.urllib.parse import quote +from urllib.parse import quote from paste.util.looper import looper __all__ = ['TemplateError', 'Template', 'sub', 'HTMLTemplate', @@ -78,7 +78,7 @@ class Template(object): def __init__(self, content, name=None, namespace=None): self.content = content - self._unicode = isinstance(content, six.text_type) + self._unicode = isinstance(content, str) self.name = name self._parsed = parse(content, name=name) if namespace is None: @@ -124,7 +124,7 @@ def _interpret(self, ns): def _interpret_codes(self, codes, ns, out): __traceback_hide__ = True for item in codes: - if isinstance(item, six.string_types): + if isinstance(item, str): out.append(item) else: self._interpret_code(item, ns, out) @@ -185,7 +185,7 @@ def _interpret_if(self, parts, ns, out): __traceback_hide__ = True # @@: if/else/else gets through for part in parts: - assert not isinstance(part, six.string_types) + assert not isinstance(part, str) name, pos = part[0], part[1] if name == 'else': result = True @@ -213,7 +213,7 @@ def _eval(self, code, ns, pos): def _exec(self, code, ns, pos): __traceback_hide__ = True try: - six.exec_(code, ns) + exec(code, ns) except: exc_info = sys.exc_info() e = exc_info[1] @@ -225,26 +225,20 @@ def _repr(self, value, pos): try: if value is None: return '' - if self._unicode: - try: - value = six.text_type(value) - except UnicodeDecodeError: - value = str(value) - else: - value = str(value) + value = str(value) except: exc_info = sys.exc_info() e = exc_info[1] e.args = (self._add_line_info(e.args[0], pos),) six.reraise(exc_info[0], e, exc_info[2]) else: - if self._unicode and isinstance(value, six.binary_type): + if self._unicode and isinstance(value, bytes): if not self.decode_encoding: raise UnicodeDecodeError( 'Cannot decode str value %r into unicode ' '(no default_encoding provided)' % value) value = value.decode(self.default_encoding) - elif not self._unicode and isinstance(value, six.text_type): + elif not self._unicode and isinstance(value, str): if not self.decode_encoding: raise UnicodeEncodeError( 'Cannot encode unicode value %r into str ' @@ -317,24 +311,14 @@ def __repr__(self): def html_quote(value): if value is None: return '' - if not isinstance(value, six.string_types): - if six.PY2 and hasattr(value, '__unicode__'): - value = unicode(value) - else: - value = str(value) + if not isinstance(value, str): + value = str(value) value = escape(value, 1) - if six.PY2 and isinstance(value, unicode): - value = value.encode('ascii', 'xmlcharrefreplace') return value def url(v): - if not isinstance(v, six.string_types): - if six.PY2 and hasattr(v, '__unicode__'): - v = unicode(v) - else: - v = str(v) - if six.PY2 and isinstance(v, unicode): - v = v.encode('utf8') + if not isinstance(v, str): + v = str(v) return quote(v) def attr(**kw): @@ -447,7 +431,7 @@ def trim_lex(tokens): """ for i in range(len(tokens)): current = tokens[i] - if isinstance(tokens[i], six.string_types): + if isinstance(tokens[i], str): # we don't trim this continue item = current[0] @@ -461,8 +445,8 @@ def trim_lex(tokens): next = '' else: next = tokens[i+1] - if (not isinstance(next, six.string_types) - or not isinstance(prev, six.string_types)): + if (not isinstance(next, str) + or not isinstance(prev, str)): continue if ((not prev or trail_whitespace_re.search(prev)) and (not next or lead_whitespace_re.search(next))): @@ -541,7 +525,7 @@ def parse(s, name=None): return result def parse_expr(tokens, name, context=()): - if isinstance(tokens[0], six.string_types): + if isinstance(tokens[0], str): return tokens[0], tokens[1:] expr, pos = tokens[0] expr = expr.strip() diff --git a/paste/wsgilib.py b/paste/wsgilib.py index c05ef2c4..a7623272 100644 --- a/paste/wsgilib.py +++ b/paste/wsgilib.py @@ -5,21 +5,20 @@ A module of many disparate routines. """ -from __future__ import print_function - # functions which moved to paste.request and paste.response # Deprecated around 15 Dec 2005 +import io +import sys +import warnings +from traceback import print_exception +from io import StringIO +from urllib.parse import unquote, urlsplit + from paste.request import get_cookies, parse_querystring, parse_formvars from paste.request import construct_url, path_info_split, path_info_pop from paste.response import HeaderDict, has_header, header_value, remove_header from paste.response import error_body_response, error_response, error_response_app -from traceback import print_exception -import six -import sys -from six.moves import cStringIO as StringIO -from six.moves.urllib.parse import unquote, urlsplit -import warnings __all__ = ['add_close', 'add_start_close', 'capture_output', 'catch_errors', 'catch_errors_app', 'chained_app_iters', 'construct_url', @@ -28,7 +27,7 @@ 'interactive', 'intercept_output', 'path_info_pop', 'path_info_split', 'raw_interactive', 'send_file'] -class add_close(object): +class add_close: """ An an iterable that iterates over app_iter, then calls close_func. @@ -119,10 +118,10 @@ def __iter__(self): def next(self): if len(self.chained) == 1: - return six.next(self.chained[0]) + return next(self.chained[0]) else: try: - return six.next(self.chained[0]) + return next(self.chained[0]) except StopIteration: self.chained.pop(0) return self.next() @@ -138,7 +137,7 @@ def close(self): except: got_exc = sys.exc_info() if got_exc: - six.reraise(got_exc[0], got_exc[1], got_exc[2]) + raise got_exc def __del__(self): if not self._closed: @@ -164,7 +163,7 @@ def __iter__(self): def next(self): content = next(self.app_iter) - if isinstance(content, six.text_type): + if isinstance(content, str): content = content.encode(self.encoding, self.errors) return content __next__ = next @@ -209,7 +208,7 @@ def __iter__(self): def next(self): try: - return six.next(self.app_iter) + return next(self.app_iter) except StopIteration: if self.ok_callback: self.ok_callback() @@ -261,7 +260,7 @@ def __iter__(self): def next(self): try: - return six.next(self.app_iter) + return next(self.app_iter) except StopIteration: if self.ok_callback: self.ok_callback() @@ -278,7 +277,7 @@ def next(self): app_iter = iter(new_app_iterable) if hasattr(new_app_iterable, 'close'): self.close = new_app_iterable.close - self.next = lambda: six.next(app_iter) + self.next = lambda: next(app_iter) return self.next() __next__ = next @@ -291,7 +290,7 @@ def raw_interactive(application, path='', raise_on_wsgi_error=False, if raise_on_wsgi_error: errors = ErrorRaiser() else: - errors = six.StringIO() + errors = io.StringIO() basic_environ = { # mandatory CGI variables 'REQUEST_METHOD': 'GET', # always mandatory @@ -303,7 +302,7 @@ def raw_interactive(application, path='', raise_on_wsgi_error=False, # mandatory wsgi variables 'wsgi.version': (1, 0), 'wsgi.url_scheme': 'http', - 'wsgi.input': six.BytesIO(), + 'wsgi.input': io.BytesIO(), 'wsgi.errors': errors, 'wsgi.multithread': False, 'wsgi.multiprocess': False, @@ -325,7 +324,7 @@ def raw_interactive(application, path='', raise_on_wsgi_error=False, basic_environ['HTTP_HOST'] = basic_environ['SERVER_NAME'] istream = basic_environ['wsgi.input'] if isinstance(istream, bytes): - basic_environ['wsgi.input'] = six.BytesIO(istream) + basic_environ['wsgi.input'] = io.BytesIO(istream) basic_environ['CONTENT_LENGTH'] = len(istream) data = {} output = [] @@ -336,7 +335,7 @@ def start_response(status, headers, exc_info=None): try: if headers_sent: # Re-raise original exception only if headers sent - six.reraise(exc_info[0], exc_info[1], exc_info[2]) + raise exc_info finally: # avoid dangling circular reference exc_info = None @@ -352,7 +351,7 @@ def start_response(status, headers, exc_info=None): try: try: for s in app_iter: - if not isinstance(s, six.binary_type): + if not isinstance(s, bytes): raise ValueError( "The app_iter response can only contain bytes (not " "unicode); got: %r" % s) @@ -425,8 +424,7 @@ def dump_environ(environ, start_response): output.append(environ['wsgi.input'].read(int(content_length))) output.append("\n") output = "".join(output) - if six.PY3: - output = output.encode('utf8') + output = output.encode('utf8') headers = [('Content-Type', 'text/plain'), ('Content-Length', str(len(output)))] start_response("200 OK", headers) diff --git a/paste/wsgiwrappers.py b/paste/wsgiwrappers.py index 66bd8967..6dc2db6b 100644 --- a/paste/wsgiwrappers.py +++ b/paste/wsgiwrappers.py @@ -8,13 +8,7 @@ import re import warnings from pprint import pformat -try: - # Python 3 - from http.cookies import SimpleCookie -except ImportError: - # Python 2 - from Cookie import SimpleCookie -import six +from http.cookies import SimpleCookie from paste.request import EnvironHeaders, get_cookie_dict, \ parse_dict_querystring, parse_formvars @@ -411,7 +405,7 @@ def delete_cookie(self, key, path='/', domain=None): self.cookies[key]['max-age'] = 0 def _set_content(self, content): - if not isinstance(content, (six.binary_type, six.text_type)): + if not isinstance(content, (bytes, str)): self._iter = content if isinstance(content, list): self._is_str_iter = True diff --git a/tests/cgiapp_data/form.cgi b/tests/cgiapp_data/form.cgi index 5ad8f68b..2e87f6c4 100755 --- a/tests/cgiapp_data/form.cgi +++ b/tests/cgiapp_data/form.cgi @@ -1,7 +1,5 @@ #!/usr/bin/env python -from __future__ import print_function - import sys # Quiet warnings in this CGI so that it does not upset tests. diff --git a/tests/cgiapp_data/stderr.cgi b/tests/cgiapp_data/stderr.cgi index d2520b6f..ed4e1938 100755 --- a/tests/cgiapp_data/stderr.cgi +++ b/tests/cgiapp_data/stderr.cgi @@ -1,5 +1,4 @@ #!/usr/bin/env python -from __future__ import print_function import sys print('Status: 500 Server Error') print('Content-type: text/html') diff --git a/tests/test_auth/test_auth_cookie.py b/tests/test_auth/test_auth_cookie.py index 38e37b83..19deb4df 100644 --- a/tests/test_auth/test_auth_cookie.py +++ b/tests/test_auth/test_auth_cookie.py @@ -2,9 +2,6 @@ # This module is part of the Python Paste Project and is released under # the MIT License: http://www.opensource.org/licenses/mit-license.php -from six.moves import xrange -import six - from paste.auth import cookie from paste.wsgilib import raw_interactive, dump_environ from paste.response import header_value @@ -36,11 +33,10 @@ def test_basic(key='key', val='bingles'): (status,headers,content,errors) = \ raw_interactive(app,{'HTTP_COOKIE': cookie}) expected = ("%s: %s" % (key,val.replace("\n","\n "))) - if six.PY3: - expected = expected.encode('utf8') + expected = expected.encode('utf8') assert expected in content def test_roundtrip(): - roundtrip = str('').join(map(chr, xrange(256))) + roundtrip = str('').join(map(chr, range(256))) test_basic(roundtrip,roundtrip) diff --git a/tests/test_auth/test_auth_digest.py b/tests/test_auth/test_auth_digest.py index 25fc3e51..2a4c4aa9 100644 --- a/tests/test_auth/test_auth_digest.py +++ b/tests/test_auth/test_auth_digest.py @@ -7,15 +7,13 @@ from paste.httpexceptions import * from paste.httpheaders import AUTHORIZATION, WWW_AUTHENTICATE, REMOTE_USER import os -import six def application(environ, start_response): content = REMOTE_USER(environ) start_response("200 OK",(('Content-Type', 'text/plain'), ('Content-Length', len(content)))) - if six.PY3: - content = content.encode('utf8') + content = content.encode('utf8') return [content] realm = "tag:clarkevans.com,2005:testing" @@ -60,8 +58,8 @@ def test_digest(): if os.environ.get("TEST_SOCKET", ""): - from six.moves.urllib.error import HTTPError - from six.moves.urllib.request import build_opener, HTTPDigestAuthHandler + from urllib.error import HTTPError + from urllib.request import build_opener, HTTPDigestAuthHandler from paste.debug.testserver import serve server = serve(application) diff --git a/tests/test_auth/test_auth_tkt.py b/tests/test_auth/test_auth_tkt.py index 4713ea08..a7419f30 100644 --- a/tests/test_auth/test_auth_tkt.py +++ b/tests/test_auth/test_auth_tkt.py @@ -1,13 +1,7 @@ import hashlib -import six -if six.PY3: - import base64 +import base64 +from http.cookies import SimpleCookie from paste.auth.auth_tkt import AuthTicket -try: - from http.cookies import SimpleCookie -except ImportError: - # Python 2 - from Cookie import SimpleCookie def test_auth_ticket_digest_and_cookie_value(): @@ -108,11 +102,8 @@ def test_auth_ticket_cookie(): for test_args, test_kwargs, expected_values in test_parameters: token = AuthTicket(*test_args, **test_kwargs) expected_cookie = SimpleCookie() - if six.PY3: - # import pdb; pdb.set_trace() - expected_cookie_value = base64.b64encode(expected_values['cookie_value']) - else: - expected_cookie_value = expected_values['cookie_value'].encode('base64') + # import pdb; pdb.set_trace() + expected_cookie_value = base64.b64encode(expected_values['cookie_value']) expected_cookie[expected_values['name']] = expected_cookie_value expected_cookie[expected_values['name']]['path'] = expected_values['path'] diff --git a/tests/test_cgitb_catcher.py b/tests/test_cgitb_catcher.py index a63f7d88..5247aa0e 100644 --- a/tests/test_cgitb_catcher.py +++ b/tests/test_cgitb_catcher.py @@ -46,10 +46,7 @@ def yielder(args): def test_makes_exception(): res = do_request(bad_app) print(res) - if six.PY3: - assert 'bad_app() takes 0 positional arguments but 2 were given' in res - else: - assert 'bad_app() takes no arguments (2 given' in res + assert 'bad_app() takes 0 positional arguments but 2 were given' in res assert 'iterator = application(environ, start_response_wrapper)' in res assert 'lint.py' in res assert 'cgitb_catcher.py' in res diff --git a/tests/test_config.py b/tests/test_config.py index bc3dcf01..939c0171 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -2,7 +2,6 @@ # Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php import pytest -import six from paste.config import CONFIG, ConfigMiddleware from paste.fixture import TestApp @@ -20,8 +19,7 @@ def app_with_config(environ, start_response): start_response('200 OK', [('Content-type','text/plain')]) lines = ['Variable is: %s\n' % CONFIG[test_key], 'Variable is (in environ): %s' % environ['paste.config'][test_key]] - if six.PY3: - lines = [line.encode('utf8') for line in lines] + lines = [line.encode('utf8') for line in lines] return lines class NestingAppWithConfig(object): @@ -34,8 +32,7 @@ def __call__(self, environ, start_response): supplement = ['Nesting variable is: %s' % CONFIG[test_key], 'Nesting variable is (in environ): %s' % \ environ['paste.config'][test_key]] - if six.PY3: - supplement = [line.encode('utf8') for line in supplement] + supplement = [line.encode('utf8') for line in supplement] response.extend(supplement) return response diff --git a/tests/test_doctests.py b/tests/test_doctests.py index b243ea3b..3e9a5ee0 100644 --- a/tests/test_doctests.py +++ b/tests/test_doctests.py @@ -2,7 +2,6 @@ import os import pytest -import six from paste.util.import_string import simple_import @@ -30,8 +29,7 @@ ] options = doctest.ELLIPSIS | doctest.REPORT_ONLY_FIRST_FAILURE -if six.PY3: - options |= doctest.IGNORE_EXCEPTION_DETAIL +options |= doctest.IGNORE_EXCEPTION_DETAIL @pytest.mark.parametrize('filename', filenames) diff --git a/tests/test_exceptions/test_error_middleware.py b/tests/test_exceptions/test_error_middleware.py index 95ab177a..91fbc46e 100644 --- a/tests/test_exceptions/test_error_middleware.py +++ b/tests/test_exceptions/test_error_middleware.py @@ -73,10 +73,7 @@ def test_makes_exception(): res = do_request(bad_app) assert '' in result[0] assert "302 Found" == saved[0][0] - if six.PY3: - assert "text/html; charset=utf8" == header_value(saved[0][1], 'content-type') - else: - assert "text/html" == header_value(saved[0][1], 'content-type') + assert "text/html; charset=utf8" == header_value(saved[0][1], 'content-type') assert "/bing/foo" == header_value(saved[0][1],'location') result = list(app({'HTTP_ACCEPT': 'text/plain'},saveit)) assert "text/plain; charset=utf8" == header_value(saved[1][1],'content-type') diff --git a/tests/test_fileapp.py b/tests/test_fileapp.py index ee7da6a7..d209bb9e 100644 --- a/tests/test_fileapp.py +++ b/tests/test_fileapp.py @@ -5,13 +5,7 @@ import random import os import tempfile -try: - # Python 3 - from email.utils import parsedate_tz, mktime_tz -except ImportError: - # Python 2 - from rfc822 import parsedate_tz, mktime_tz -import six +from email.utils import parsedate_tz, mktime_tz from paste import fileapp from paste.fileapp import * @@ -101,8 +95,7 @@ def test_modified(): def test_file(): tempfile = "test_fileapp.%s.txt" % (random.random()) content = LETTERS * 20 - if six.PY3: - content = content.encode('utf8') + content = content.encode('utf8') with open(tempfile, "wb") as fp: fp.write(content) try: @@ -182,8 +175,7 @@ def _excercize_range(build,content): def test_range(): content = LETTERS * 5 - if six.PY3: - content = content.encode('utf8') + content = content.encode('utf8') def build(range, status=206): app = DataApp(content) return TestApp(app).get("/",headers={'Range': range}, status=status) @@ -193,8 +185,7 @@ def build(range, status=206): def test_file_range(): tempfile = "test_fileapp.%s.txt" % (random.random()) content = LETTERS * (1+(fileapp.CACHE_SIZE // len(LETTERS))) - if six.PY3: - content = content.encode('utf8') + content = content.encode('utf8') assert len(content) > fileapp.CACHE_SIZE with open(tempfile, "wb") as fp: fp.write(content) diff --git a/tests/test_grantip.py b/tests/test_grantip.py index cd5c98a8..34e184c2 100644 --- a/tests/test_grantip.py +++ b/tests/test_grantip.py @@ -9,8 +9,7 @@ def application(environ, start_response): ':', str(environ.get('REMOTE_USER_TOKENS')), ] - if six.PY3: - lines = [line.encode('utf8') for line in lines] + lines = [line.encode('utf8') for line in lines] return lines ip_map = { '127.0.0.1': (None, 'system'), diff --git a/tests/test_gzipper.py b/tests/test_gzipper.py index d56c4060..e468bbbc 100644 --- a/tests/test_gzipper.py +++ b/tests/test_gzipper.py @@ -1,7 +1,7 @@ from paste.fixture import TestApp from paste.gzipper import middleware import gzip -import six +import io def simple_app(environ, start_response): start_response('200 OK', @@ -17,7 +17,7 @@ def test_gzip(): '/', extra_environ=dict(HTTP_ACCEPT_ENCODING='gzip')) assert int(res.header('content-length')) == len(res.body) assert res.body != b'this is a test' - actual = gzip.GzipFile(fileobj=six.BytesIO(res.body)).read() + actual = gzip.GzipFile(fileobj=io.BytesIO(res.body)).read() assert actual == b'this is a test' def test_gzip_head(): diff --git a/tests/test_httpheaders.py b/tests/test_httpheaders.py index 8c560d20..a43f3a43 100644 --- a/tests/test_httpheaders.py +++ b/tests/test_httpheaders.py @@ -1,6 +1,30 @@ -from paste.httpheaders import * import time +from paste.httpheaders import ( + normalize_headers, + ACCEPT, + ACCEPT_CHARSET, + AGE, + ALLOW, + CACHE_CONTROL, + CONTENT_DISPOSITION, + CONTENT_ENCODING, + CONTENT_LENGTH, + CONTENT_TYPE, + DATE, + EXPIRES, + ETAG, + FROM, + IF_MODIFIED_SINCE, + PRAGMA, + RANGE, + REFERER, + UPGRADE, + VIA, + VARY, + WWW_AUTHENTICATE, +) + def _test_generic(collection): assert 'bing' == VIA(collection) REFERER.update(collection,'internal:/some/path') diff --git a/tests/test_httpserver.py b/tests/test_httpserver.py index 7b64a458..fa33d69e 100644 --- a/tests/test_httpserver.py +++ b/tests/test_httpserver.py @@ -2,10 +2,7 @@ import io import socket -import six - from paste.httpserver import LimitedLengthFile, WSGIHandler, serve -from six.moves import StringIO class MockServer(object): @@ -14,7 +11,7 @@ class MockServer(object): class MockSocket(object): def makefile(self, mode, bufsize): - return StringIO() + return io.StringIO() def test_environ(): @@ -59,10 +56,6 @@ def test_limited_length_file(): def test_limited_length_file_tell_on_socket(): backing_read, backing_write = socket.socketpair() - if six.PY2: - # On Python 2, socketpair() returns an internal socket type rather than - # the public one. - backing_read = socket.socket(_sock=backing_read) f = LimitedLengthFile(backing_read.makefile('rb'), 10) backing_write.send(b'0123456789') backing_write.close() @@ -130,4 +123,4 @@ def test_address_family_v6(): assert (str(p) == port) except (socket.error, OSError) as err: # v6 support not available in this OS, pass the test - assert True \ No newline at end of file + assert True diff --git a/tests/test_multidict.py b/tests/test_multidict.py index f6619fc9..ed6c920c 100644 --- a/tests/test_multidict.py +++ b/tests/test_multidict.py @@ -6,7 +6,6 @@ import io import pytest -import six from paste.util.multidict import MultiDict, UnicodeMultiDict @@ -63,15 +62,15 @@ def _test_unicode_dict(decode_param_names=False): d.errors = 'ignore' if decode_param_names: - key_str = six.text_type + key_str = str k = lambda key: key d.decode_keys = True else: - key_str = six.binary_type + key_str = bytes k = lambda key: key.encode() def assert_unicode(obj): - assert isinstance(obj, six.text_type) + assert isinstance(obj, str) def assert_key_str(obj): assert isinstance(obj, key_str) @@ -79,7 +78,7 @@ def assert_key_str(obj): def assert_unicode_item(obj): key, value = obj assert isinstance(key, key_str) - assert isinstance(value, six.text_type) + assert isinstance(value, str) assert d.items() == [(k('a'), u'a test')] map(assert_key_str, d.keys()) @@ -106,9 +105,9 @@ def assert_unicode_item(obj): assert d.items() == [(k('a'), u'a test'), (k('c'), u'3 test')] list(map(assert_unicode_item, d.items())) assert d.pop('xxx', u'5 test') == u'5 test' - assert isinstance(d.pop('xxx', u'5 test'), six.text_type) + assert isinstance(d.pop('xxx', u'5 test'), str) assert d.getone(k('a')) == u'a test' - assert isinstance(d.getone(k('a')), six.text_type) + assert isinstance(d.getone(k('a')), str) assert d.popitem() == (k('c'), u'3 test') d[k('c')] = b'3 test' assert_unicode_item(d.popitem()) @@ -122,16 +121,16 @@ def assert_unicode_item(obj): assert isinstance(items[1][0], key_str) assert isinstance(items[1][1], list) - assert isinstance(d.setdefault(k('y'), b'y test'), six.text_type) - assert isinstance(d[k('y')], six.text_type) + assert isinstance(d.setdefault(k('y'), b'y test'), str) + assert isinstance(d[k('y')], str) assert d.mixed() == {k('a'): u'a test', k('y'): u'y test', k('z'): item} assert d.dict_of_lists() == {k('a'): [u'a test'], k('y'): [u'y test'], k('z'): [item]} del d[k('z')] - list(map(assert_unicode_item, six.iteritems(d.mixed()))) + list(map(assert_unicode_item, d.mixed().items())) list(map(assert_unicode_item, [(key, value[0]) for \ - key, value in six.iteritems(d.dict_of_lists())])) + key, value in d.dict_of_lists().items()])) assert k('a') in d dcopy = d.copy() @@ -155,9 +154,9 @@ def assert_unicode_item(obj): ufs = d[k('f')] assert isinstance(ufs, cgi.FieldStorage) assert ufs.name == fs.name - assert isinstance(ufs.name, str if six.PY3 else key_str) + assert isinstance(ufs.name, str) assert ufs.filename == fs.filename - assert isinstance(ufs.filename, six.text_type) + assert isinstance(ufs.filename, str) assert isinstance(ufs.value, bytes) assert ufs.value == b'hello' ufs = None diff --git a/tests/test_registry.py b/tests/test_registry.py index e0794dcc..80fac29d 100644 --- a/tests/test_registry.py +++ b/tests/test_registry.py @@ -23,8 +23,7 @@ def simpleapp_withregistry(environ, start_response): response_headers = [('Content-type','text/plain')] start_response(status, response_headers) body = 'Hello world!Value is %s\n' % regobj.keys() - if six.PY3: - body = body.encode('utf8') + body = body.encode('utf8') return [body] def simpleapp_withregistry_default(environ, start_response): @@ -32,8 +31,7 @@ def simpleapp_withregistry_default(environ, start_response): response_headers = [('Content-type','text/plain')] start_response(status, response_headers) body = 'Hello world!Value is %s\n' % secondobj - if six.PY3: - body = body.encode('utf8') + body = body.encode('utf8') return [body] @@ -52,8 +50,7 @@ def __call__(self, environ, start_response): response_headers = [('Content-type','text/plain')] start_response(status, response_headers) body = 'Hello world!\nThe variable is %s' % str(regobj) - if six.PY3: - body = body.encode('utf8') + body = body.encode('utf8') return [body] class RegistryUsingIteratorApp(object): @@ -68,8 +65,7 @@ def __call__(self, environ, start_response): response_headers = [('Content-type','text/plain')] start_response(status, response_headers) body = 'Hello world!\nThe variable is %s' % str(regobj) - if six.PY3: - body = body.encode('utf8') + body = body.encode('utf8') return iter([body]) class RegistryMiddleMan(object): @@ -84,8 +80,7 @@ def __call__(self, environ, start_response): environ['paste.registry'].register(self.var, self.value) line = ('\nInserted by middleware!\nInsertValue at depth %s is %s' % (self.depth, str(regobj))) - if six.PY3: - line = line.encode('utf8') + line = line.encode('utf8') app_response = [line] app_iter = None app_iter = self.app(environ, start_response) @@ -100,8 +95,7 @@ def __call__(self, environ, start_response): app_response.extend(response) line = ('\nAppended by middleware!\nAppendValue at \ depth %s is %s' % (self.depth, str(regobj))) - if six.PY3: - line = line.encode('utf8') + line = line.encode('utf8') app_response.append(line) return app_response diff --git a/tests/test_request.py b/tests/test_request.py index 072304df..40286425 100644 --- a/tests/test_request.py +++ b/tests/test_request.py @@ -4,7 +4,6 @@ from paste.fixture import * from paste.request import * from paste.wsgiwrappers import WSGIRequest -import six def simpleapp(environ, start_response): status = '200 OK' @@ -16,8 +15,7 @@ def simpleapp(environ, start_response): ' and Val is %s\n' % request.GET.get('name'), 'The languages are: %s\n' % request.languages, 'The accepttypes is: %s\n' % request.match_accept(['text/html', 'application/xml'])] - if six.PY3: - body = [line.encode('utf8') for line in body] + body = [line.encode('utf8') for line in body] return body def test_gets(): diff --git a/tests/test_request_form.py b/tests/test_request_form.py index ce74e7d2..76a0149c 100644 --- a/tests/test_request_form.py +++ b/tests/test_request_form.py @@ -1,4 +1,4 @@ -import six +import io from paste.request import * from paste.util.multidict import MultiDict @@ -18,7 +18,7 @@ def make_post(body): 'CONTENT_TYPE': 'application/x-www-form-urlencoded', 'CONTENT_LENGTH': str(len(body)), 'REQUEST_METHOD': 'POST', - 'wsgi.input': six.BytesIO(body), + 'wsgi.input': io.BytesIO(body), } return e diff --git a/tests/test_session.py b/tests/test_session.py index b67bda5a..9dbb1ae3 100644 --- a/tests/test_session.py +++ b/tests/test_session.py @@ -1,6 +1,5 @@ from paste.session import SessionMiddleware from paste.fixture import TestApp -import six info = [] @@ -14,8 +13,7 @@ def wsgi_app(environ, start_response): sess = environ['paste.session.factory']() if 'info' in sess: body = str(sess['info']) - if six.PY3: - body = body.encode('utf8') + body = body.encode('utf8') return [body] else: return [b'no-info'] diff --git a/tests/test_urlmap.py b/tests/test_urlmap.py index f7ec729a..d7b67765 100644 --- a/tests/test_urlmap.py +++ b/tests/test_urlmap.py @@ -1,14 +1,12 @@ -from paste.urlmap import * -from paste.fixture import * -import six +from paste.urlmap import URLMap +from paste.fixture import TestApp def make_app(response_text): def app(environ, start_response): headers = [('Content-type', 'text/html')] start_response('200 OK', headers) body = response_text % environ - if six.PY3: - body = body.encode('ascii') + body = body.encode('ascii') return [body] return app diff --git a/tests/test_util/test_datetimeutil.py b/tests/test_util/test_datetimeutil.py index 45d96c79..84770372 100644 --- a/tests/test_util/test_datetimeutil.py +++ b/tests/test_util/test_datetimeutil.py @@ -4,7 +4,12 @@ # Some of this code was funded by: http://prometheusresearch.com from time import localtime from datetime import date -from paste.util.datetimeutil import * +from paste.util.datetimeutil import ( + normalize_date, + normalize_time, + normalize_timedelta, + parse_date, +) def test_timedelta(): assert('' == normalize_timedelta("")) diff --git a/tests/test_util/test_quoting.py b/tests/test_util/test_quoting.py index 6df11395..bca7908e 100644 --- a/tests/test_util/test_quoting.py +++ b/tests/test_util/test_quoting.py @@ -1,17 +1,16 @@ from paste.util import quoting -import six import unittest class TestQuoting(unittest.TestCase): def test_html_unquote(self): self.assertEqual(quoting.html_unquote(b'<hey you>'), - u'') + '') self.assertEqual(quoting.html_unquote(b''), - u'') + '') self.assertEqual(quoting.html_unquote(b'&blahblah;'), - u'&blahblah;') + '&blahblah;') self.assertEqual(quoting.html_unquote(b'\xe1\x80\xa9'), - u'\u1029') + '\u1029') def test_html_quote(self): self.assertEqual(quoting.html_quote(1), @@ -22,9 +21,5 @@ def test_html_quote(self): '<hey!>') self.assertEqual(quoting.html_quote(b''), b'<hey!>') - if six.PY3: - self.assertEqual(quoting.html_quote(u'<\u1029>'), - u'<\u1029>') - else: - self.assertEqual(quoting.html_quote(u'<\u1029>'), - '<\xe1\x80\xa9>') + self.assertEqual(quoting.html_quote('<\u1029>'), + '<\u1029>') diff --git a/tests/test_wsgiwrappers.py b/tests/test_wsgiwrappers.py index bfdd4b30..1bdf1b0f 100644 --- a/tests/test_wsgiwrappers.py +++ b/tests/test_wsgiwrappers.py @@ -5,7 +5,6 @@ import io from paste.fixture import TestApp from paste.wsgiwrappers import WSGIRequest, WSGIResponse -import six class AssertApp(object): def __init__(self, assertfunc): @@ -87,7 +86,7 @@ def handle_fileupload(environ, start_response): assert isinstance(request.POST.keys()[0], str) fs = request.POST['thefile'] assert isinstance(fs, cgi.FieldStorage) - assert isinstance(fs.filename, six.text_type) + assert isinstance(fs.filename, str) assert fs.filename == u'寿司.txt' assert fs.value == b'Sushi' @@ -107,7 +106,7 @@ def test_wsgiresponse_charset(): response.write('test3') status, headers, content = response.wsgi_response() for data in content: - assert isinstance(data, six.binary_type) + assert isinstance(data, bytes) WSGIResponse.defaults._push_object(dict(content_type='text/html', charset='iso-8859-1')) @@ -118,7 +117,7 @@ def test_wsgiresponse_charset(): response.write('test3') status, headers, content = response.wsgi_response() for data in content: - assert isinstance(data, six.binary_type) + assert isinstance(data, bytes) finally: WSGIResponse.defaults._pop_object() @@ -131,7 +130,7 @@ def test_wsgiresponse_charset(): response.write(u'test1') status, headers, content = response.wsgi_response() for data in content: - assert isinstance(data, six.text_type) + assert isinstance(data, str) finally: WSGIResponse.defaults._pop_object() @@ -142,7 +141,7 @@ def test_wsgiresponse_charset(): response.write(u'test1') status, headers, content = response.wsgi_response() for data in content: - assert isinstance(data, six.text_type) + assert isinstance(data, str) finally: WSGIResponse.defaults._pop_object() diff --git a/tests/urlparser_data/hook/app.py b/tests/urlparser_data/hook/app.py index 1a980134..8c06b92e 100644 --- a/tests/urlparser_data/hook/app.py +++ b/tests/urlparser_data/hook/app.py @@ -1,9 +1,7 @@ -import six def application(environ, start_response): start_response('200 OK', [('Content-type', 'text/html')]) body = 'user: %s' % environ['app.user'] - if six.PY3: - body = body.encode('ascii') + body = body.encode('ascii') return [body] diff --git a/tests/urlparser_data/hook/index.py b/tests/urlparser_data/hook/index.py index 92f3d662..faa91eee 100644 --- a/tests/urlparser_data/hook/index.py +++ b/tests/urlparser_data/hook/index.py @@ -1,9 +1,7 @@ -import six def application(environ, start_response): start_response('200 OK', [('Content-type', 'text/html')]) body = 'index: %s' % environ['app.user'] - if six.PY3: - body = body.encode('ascii') + body = body.encode('ascii') return [body] diff --git a/tests/urlparser_data/not_found/user/list.py b/tests/urlparser_data/not_found/user/list.py index fd7482f7..ed3cb01a 100644 --- a/tests/urlparser_data/not_found/user/list.py +++ b/tests/urlparser_data/not_found/user/list.py @@ -1,8 +1,6 @@ -import six def application(environ, start_response): start_response('200 OK', [('Content-type', 'text/plain')]) body = 'user: %s' % environ.get('app.user') - if six.PY3: - body = body.encode('ascii') + body = body.encode('ascii') return [body] From f8fb2ab5d247df5dd0b1d34298b316f7d5e49c87 Mon Sep 17 00:00:00 2001 From: Alexandre Detiste Date: Thu, 14 Mar 2024 22:03:58 +0100 Subject: [PATCH 2/5] remove ref to cStringIO --- paste/debug/doctest_webapp.py | 2 +- paste/debug/watchthreads.py | 2 +- paste/debug/wdg_validate.py | 2 +- paste/evalexception/middleware.py | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/paste/debug/doctest_webapp.py b/paste/debug/doctest_webapp.py index ffcfaa74..f86c5086 100755 --- a/paste/debug/doctest_webapp.py +++ b/paste/debug/doctest_webapp.py @@ -16,7 +16,7 @@ import re import cgi import rfc822 -from cStringIO import StringIO +from io import StringIO from paste.util import PySourceColor diff --git a/paste/debug/watchthreads.py b/paste/debug/watchthreads.py index b06ccea4..63c47276 100644 --- a/paste/debug/watchthreads.py +++ b/paste/debug/watchthreads.py @@ -6,7 +6,7 @@ import cgi import time import traceback -from cStringIO import StringIO +from io import StringIO from thread import get_ident from paste import httpexceptions from paste.request import construct_url, parse_formvars diff --git a/paste/debug/wdg_validate.py b/paste/debug/wdg_validate.py index 225baf98..a9d72dd7 100644 --- a/paste/debug/wdg_validate.py +++ b/paste/debug/wdg_validate.py @@ -5,7 +5,7 @@ `WDG HTML Validator `_ """ -from cStringIO import StringIO +from io import StringIO import subprocess from paste.response import header_value import re diff --git a/paste/evalexception/middleware.py b/paste/evalexception/middleware.py index b9ee1998..34434e18 100644 --- a/paste/evalexception/middleware.py +++ b/paste/evalexception/middleware.py @@ -29,7 +29,7 @@ import sys import os import traceback -from io import cStringIO as StringIO +from io import StringIO import pprint import itertools import time From 426e721a1268d4e8f50e078c79568ff5367d716e Mon Sep 17 00:00:00 2001 From: Alexandre Detiste Date: Thu, 14 Mar 2024 22:07:30 +0100 Subject: [PATCH 3/5] fix import io --- paste/fixture.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/paste/fixture.py b/paste/fixture.py index 821e60d9..87fa15c4 100644 --- a/paste/fixture.py +++ b/paste/fixture.py @@ -10,6 +10,7 @@ """ import sys +import io import random import mimetypes import time @@ -19,7 +20,6 @@ import shlex import re import subprocess -from io import StringIO from urllib.parse import urlencode from urllib import parse as urlparse from six.moves.http_cookies import BaseCookie @@ -471,7 +471,7 @@ def _make_response(self, resp, total_time): class CaptureStdout(object): def __init__(self, actual): - self.captured = StringIO() + self.captured = io.StringIO() self.actual = actual def write(self, s): From 447a6ded3c4d672267df0b9e0b9b7bf3de71106f Mon Sep 17 00:00:00 2001 From: Alexandre Detiste Date: Thu, 14 Mar 2024 22:09:00 +0100 Subject: [PATCH 4/5] next() is a reserved name in Python3 --- paste/evalexception/middleware.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/paste/evalexception/middleware.py b/paste/evalexception/middleware.py index 34434e18..95d3af7b 100644 --- a/paste/evalexception/middleware.py +++ b/paste/evalexception/middleware.py @@ -160,8 +160,8 @@ def get_debug_count(environ): if 'paste.evalexception.debug_count' in environ: return environ['paste.evalexception.debug_count'] else: - environ['paste.evalexception.debug_count'] = next = next(debug_counter) - return next + environ['paste.evalexception.debug_count'] = _next = next(debug_counter) + return _next class EvalException(object): From 38a30bbcfa2eb5d439ac00b860d4b52a56bed2e4 Mon Sep 17 00:00:00 2001 From: Alexandre Detiste Date: Thu, 14 Mar 2024 22:13:19 +0100 Subject: [PATCH 5/5] fix regression --- paste/exceptions/serial_number_generator.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/paste/exceptions/serial_number_generator.py b/paste/exceptions/serial_number_generator.py index f7e11e55..c2fcc9a0 100644 --- a/paste/exceptions/serial_number_generator.py +++ b/paste/exceptions/serial_number_generator.py @@ -61,7 +61,7 @@ def hash_identifier(s, length, pad=True, hasher=md5, prefix='', raise ValueError( "md5 cannot create hashes longer than 26 characters in " "length (you gave %s)" % length) - if isinstance(s, int): + if isinstance(s, str): s = s.encode('utf-8') elif not isinstance(s, bytes): s = str(s)