Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
32 changes: 11 additions & 21 deletions paste/auth/auth_tkt.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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
Expand All @@ -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:
Expand All @@ -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:
Expand All @@ -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
Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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']
Expand Down
9 changes: 8 additions & 1 deletion paste/auth/basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
"""
Expand Down
2 changes: 1 addition & 1 deletion paste/auth/cas.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
31 changes: 11 additions & 20 deletions paste/auth/cookie.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down Expand Up @@ -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)
Expand All @@ -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:
Expand Down Expand Up @@ -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;'
Expand Down Expand Up @@ -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']
Expand Down
27 changes: 14 additions & 13 deletions paste/auth/digest.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 """
Expand Down Expand Up @@ -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):
Expand All @@ -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
Expand All @@ -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]
Expand Down
5 changes: 2 additions & 3 deletions paste/auth/grantip.py
Original file line number Diff line number Diff line change
Expand Up @@ -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``
Expand Down Expand Up @@ -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)

Expand Down
5 changes: 2 additions & 3 deletions paste/auth/open_id.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@
import cgi
import urlparse
import re
import six

import paste.request
from paste import httpexceptions
Expand All @@ -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.
Expand Down Expand Up @@ -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(
Expand Down
2 changes: 1 addition & 1 deletion paste/cascade.py
Original file line number Diff line number Diff line change
Expand Up @@ -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']

Expand Down
9 changes: 4 additions & 5 deletions paste/cgiapp.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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
Expand Down Expand Up @@ -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:
Expand Down
11 changes: 4 additions & 7 deletions paste/cgitb_catcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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):
Expand All @@ -74,8 +72,7 @@ def catching_iter(self, app_iter, environ):
response += (
'<hr noshade>Error in .close():<br>%s'
% close_response)
if six.PY3:
response = response.encode('utf8')
response = response.encode('utf8')
yield response

def exception_handler(self, exc_info, environ):
Expand Down
2 changes: 1 addition & 1 deletion paste/debug/doctest_webapp.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
import re
import cgi
import rfc822
from cStringIO import StringIO
from io import StringIO
from paste.util import PySourceColor


Expand Down
Loading