now works with 2to3, passes all the tests in py25-27,31,32 #231

Closed
wants to merge 5 commits into
from
Jump to file
+810 −473
Split
View
@@ -57,8 +57,12 @@
from setuptools import setup
except ImportError:
from distutils.core import setup
+import sys
+kwargs = {}
+if sys.version_info >= (3, ):
+ kwargs['use_2to3'] = True
setup(
name='Werkzeug',
version='0.9-dev',
@@ -83,5 +87,6 @@
include_package_data=True,
test_suite='werkzeug.testsuite.suite',
zip_safe=False,
- platforms='any'
+ platforms='any',
+ **kwargs
)
View
@@ -0,0 +1,10 @@
+[tox]
+envlist=py25,py26,py27,py31,py32
+
+[testenv]
+changedir=envtmpdir
+commands={envpython} run-tests.py
+
+[testenv:py25]
+deps=
+ simplejson
@@ -106,8 +106,8 @@
object_origins = {}
-for module, items in all_by_module.iteritems():
- for item in items:
+for module in all_by_module:
+ for item in all_by_module[module]:
object_origins[item] = module
View
@@ -9,15 +9,23 @@
:license: BSD, see LICENSE for more details.
"""
import inspect
+import sys
from weakref import WeakKeyDictionary
-from cStringIO import StringIO
+try:
+ from io import BytesIO
+except ImportError:
+ from cStringIO import StringIO as BytesIO # Python < 2.6
from Cookie import SimpleCookie, Morsel, CookieError
from time import gmtime
from datetime import datetime, date
+if sys.version_info >= (3, ):
+ _b = lambda _: _ if isinstance(_, bytes) else _.encode('utf-8')
+else:
+ _b = str
_logger = None
-_empty_stream = StringIO('')
+_empty_stream = BytesIO(_b(''))
_signature_cache = WeakKeyDictionary()
_epoch_ord = date(1970, 1, 1).toordinal()
@@ -344,7 +352,10 @@ def __repr__(self):
def _easteregg(app):
"""Like the name says. But who knows how it works?"""
- gyver = '\n'.join([x + (77 - len(x)) * ' ' for x in '''
+ from base64 import b64decode
+ from zlib import decompress
+ gyver = _b('\n').join([x + (77 - len(x)) * _b(' ') for x in
+ decompress(b64decode(_b('''
eJyFlzuOJDkMRP06xRjymKgDJCDQStBYT8BCgK4gTwfQ2fcFs2a2FzvZk+hvlcRvRJD148efHt9m
9Xz94dRY5hGt1nrYcXx7us9qlcP9HHNh28rz8dZj+q4rynVFFPdlY4zH873NKCexrDM6zxxRymzz
4QIxzK4bth1PV7+uHn6WXZ5C4ka/+prFzx3zWLMHAVZb8RRUxtFXI5DTQ2n3Hi2sNI+HK43AOWSY
@@ -375,7 +386,7 @@ def _easteregg(app):
krEDuNoJCHNlZYhKpvw4mspVWxqo415n8cD62N9+EfHrAvqQnINStetek7RY2Urv8nxsnGaZfRr/
nhXbJ6m/yl1LzYqscDZA9QHLNbdaSTTr+kFg3bC0iYbX/eQy0Bv3h4B50/SGYzKAXkCeOLI3bcAt
mj2Z/FM1vQWgDynsRwNvrWnJHlespkrp8+vO1jNaibm+PhqXPPv30YwDZ6jApe3wUjFQobghvW9p
-7f2zLkGNv8b191cD/3vs9Q833z8t'''.decode('base64').decode('zlib').splitlines()])
+7f2zLkGNv8b191cD/3vs9Q833z8t'''))).splitlines()])
def easteregged(environ, start_response):
def injecting_start_response(status, headers, exc_info=None):
headers.append(('X-Powered-By', 'Werkzeug'))
@@ -62,15 +62,16 @@ def get_sidebar(user):
try:
from hashlib import md5
except ImportError:
- from md5 import new as md5
+ from md5 import new as md5 # Python < 2.5
from itertools import izip
from time import time
from werkzeug.posixemulation import rename
+from werkzeug._internal import _b
try:
import cPickle as pickle
except ImportError:
- import pickle
+ import pickle # Python >= 3
def _items(mappingorseq):
@@ -84,8 +85,11 @@ def _items(mappingorseq):
... assert k*k == v
"""
- return mappingorseq.iteritems() if hasattr(mappingorseq, 'iteritems') \
- else mappingorseq
+ if hasattr(mappingorseq, 'items'):
+ return mappingorseq.items()
+ if hasattr(mappingorseq, 'iteritems'):
+ return mappingorseq.iteritems()
+ return mappingorseq
class BaseCache(object):
@@ -495,15 +499,15 @@ def dump_object(self, value):
t = type(value)
if t is int or t is long:
return str(value)
- return '!' + pickle.dumps(value)
+ return _b('!') + pickle.dumps(value)
def load_object(self, value):
"""The reversal of :meth:`dump_object`. This might be callde with
None.
"""
if value is None:
return None
- if value.startswith('!'):
+ if value.startswith(_b('!')):
return pickle.loads(value[1:])
try:
return int(value)
@@ -629,7 +633,7 @@ def clear(self):
pass
def _get_filename(self, key):
- hash = md5(key).hexdigest()
+ hash = md5(_b(key)).hexdigest()
return os.path.join(self._path, hash)
def get(self, key):
@@ -89,12 +89,18 @@ def application(environ, start_response):
:license: BSD, see LICENSE for more details.
"""
import cPickle as pickle
+from base64 import b64decode, b64encode
from hmac import new as hmac
from time import time
from werkzeug.urls import url_quote_plus, url_unquote_plus
-from werkzeug._internal import _date_to_unix
+from werkzeug._internal import _b, _date_to_unix
from werkzeug.contrib.sessions import ModificationTrackingDict
-from werkzeug.security import safe_str_cmp
+from werkzeug.security import safe_bytes_cmp, safe_str_cmp
+
+try:
+ bytes
+except NameError:
+ bytes = str # Python < 2.6
from hashlib import sha1 as _default_hash
@@ -147,8 +153,8 @@ def __init__(self, data=None, secret_key=None, new=True):
ModificationTrackingDict.__init__(self, data or ())
# explicitly convert it into a bytestring because python 2.6
# no longer performs an implicit string conversion on hmac
- if secret_key is not None:
- secret_key = str(secret_key)
+ if isinstance(secret_key, unicode):
+ secret_key = secret_key.encode('ascii')
self.secret_key = secret_key
self.new = new
@@ -176,7 +182,9 @@ def quote(cls, value):
if cls.serialization_method is not None:
value = cls.serialization_method.dumps(value)
if cls.quote_base64:
- value = ''.join(value.encode('base64').splitlines()).strip()
+ value = _b('').join(b64encode(value).splitlines()).strip()
+ if not isinstance(value, str):
+ return value.decode('latin1')
return value
@classmethod
@@ -187,8 +195,9 @@ def unquote(cls, value):
:param value: the value to unquote.
"""
try:
+ value = value.encode('ascii')
if cls.quote_base64:
- value = value.decode('base64')
+ value = b64decode(value)
if cls.serialization_method is not None:
value = cls.serialization_method.loads(value)
return value
@@ -219,9 +228,9 @@ def serialize(self, expires=None):
url_quote_plus(key),
self.quote(value)
))
- mac.update('|' + result[-1])
+ mac.update(_b('|' + result[-1]))
return '%s?%s' % (
- mac.digest().encode('base64').strip(),
+ b64encode(mac.digest()).decode('ascii').strip(),
'&'.join(result)
)
@@ -233,8 +242,8 @@ def unserialize(cls, string, secret_key):
:param secret_key: the secret key used to serialize the cookie.
:return: a new :class:`SecureCookie`.
"""
- if isinstance(string, unicode):
- string = string.encode('utf-8', 'replace')
+ if isinstance(secret_key, unicode):
+ secret_key = secret_key.encode('ascii')
try:
base64_hash, data = string.split('?', 1)
except (ValueError, IndexError):
@@ -243,26 +252,24 @@ def unserialize(cls, string, secret_key):
items = {}
mac = hmac(secret_key, None, cls.hash_method)
for item in data.split('&'):
- mac.update('|' + item)
+ mac.update(_b('|' + item))
if not '=' in item:
items = None
break
key, value = item.split('=', 1)
# try to make the key a string
key = url_unquote_plus(key)
- try:
- key = str(key)
- except UnicodeError:
- pass
items[key] = value
# no parsing error and the mac looks okay, we can now
# sercurely unpickle our cookie.
try:
- client_hash = base64_hash.decode('base64')
+ client_hash = b64decode(base64_hash.encode('ascii'))
except Exception:
items = client_hash = None
- if items is not None and safe_str_cmp(client_hash, mac.digest()):
+ safe_cmp = (safe_bytes_cmp if isinstance(client_hash[0], int)
+ else safe_str_cmp)
+ if items is not None and safe_cmp(client_hash, mac.digest()):
try:
for key, value in items.iteritems():
items[key] = cls.unquote(value)
@@ -65,6 +65,7 @@ def application(environ, start_response):
from werkzeug.utils import dump_cookie, parse_cookie
from werkzeug.wsgi import ClosingIterator
from werkzeug.posixemulation import rename
+from werkzeug._internal import _b
_sha1_re = re.compile(r'^[a-f0-9]{40}$')
@@ -77,7 +78,7 @@ def _urandom():
def generate_key(salt=None):
- return sha1('%s%s%s' % (salt, time(), _urandom())).hexdigest()
+ return sha1(_b('%s%s%s' % (salt, time(), _urandom()))).hexdigest()
class ModificationTrackingDict(CallbackDict):
@@ -211,7 +212,7 @@ def __init__(self, path=None, filename_template='werkzeug_%s.sess',
if path is None:
path = tempfile.gettempdir()
self.path = path
- if isinstance(filename_template, unicode):
+ if sys.version_info < (3, ) and isinstance(filename_template, unicode):
filename_template = filename_template.encode(
sys.getfilesystemencoding() or 'utf-8')
assert not filename_template.endswith(_fs_transaction_suffix), \
@@ -224,7 +225,7 @@ def get_session_filename(self, sid):
# out of the box, this should be a strict ASCII subset but
# you might reconfigure the session object to have a more
# arbitrary string.
- if isinstance(sid, unicode):
+ if sys.version_info < (3, ) and isinstance(sid, unicode):
sid = sid.encode(sys.getfilesystemencoding() or 'utf-8')
return path.join(self.path, self.filename_template % sid)
@@ -21,6 +21,7 @@ class Request(RequestBase, JSONRequestMixin):
:license: BSD, see LICENSE for more details.
"""
import codecs
+import sys
from werkzeug.exceptions import BadRequest
from werkzeug.utils import cached_property
from werkzeug.http import dump_options_header, parse_options_header
@@ -164,12 +165,16 @@ def path(self):
info in the WSGI environment but will not include a leading slash.
"""
path = (self.environ.get('PATH_INFO') or '').lstrip('/')
+ if sys.version_info >= (3, ):
+ return path
return _decode_unicode(path, self.charset, self.encoding_errors)
@cached_property
def script_root(self):
"""The root path of the script includling a trailing slash."""
path = (self.environ.get('SCRIPT_NAME') or '').rstrip('/') + '/'
+ if sys.version_info >= (3, ):
+ return path
return _decode_unicode(path, self.charset, self.encoding_errors)
Oops, something went wrong.