From 1b753cb1b1764de5bf3afe1f96032362208febc6 Mon Sep 17 00:00:00 2001 From: Thomas Waldmann Date: Sat, 18 May 2013 17:47:40 +0200 Subject: [PATCH 1/6] require 'six' in setup.py, add flask._compat for stuff not yet in 'six' --- flask/_compat.py | 13 +++++++++++++ setup.py | 1 + 2 files changed, 14 insertions(+) create mode 100644 flask/_compat.py diff --git a/flask/_compat.py b/flask/_compat.py new file mode 100644 index 00000000..3743a54c --- /dev/null +++ b/flask/_compat.py @@ -0,0 +1,13 @@ +# -*- coding: utf-8 -*- +""" + flask._compat + ~~~~~~~~~~~~~ + + Some py2/py3 compatibility support that is not yet available in + "six" 1.3.0. + There are bugs open for "six" for all this stuff, so we can remove it + again from here as soon as we require a new enough "six" release. + + :copyright: (c) 2013 by Armin Ronacher. + :license: BSD, see LICENSE for more details. +""" diff --git a/setup.py b/setup.py index 2f9c95ca..e25d435f 100644 --- a/setup.py +++ b/setup.py @@ -90,6 +90,7 @@ setup( zip_safe=False, platforms='any', install_requires=[ + 'six>=1.3.0', 'Werkzeug>=0.7', 'Jinja2>=2.4', 'itsdangerous>=0.17' From cfbfff2d2692a94bdb29133c2e7bb6b792cb337d Mon Sep 17 00:00:00 2001 From: Thomas Waldmann Date: Sat, 18 May 2013 17:57:43 +0200 Subject: [PATCH 2/6] python-modernize automated changes: misc. minor stuff --- flask/testsuite/__init__.py | 3 ++- flask/testsuite/config.py | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/flask/testsuite/__init__.py b/flask/testsuite/__init__.py index 5d86fa3d..7938a784 100644 --- a/flask/testsuite/__init__.py +++ b/flask/testsuite/__init__.py @@ -10,6 +10,7 @@ :license: BSD, see LICENSE for more details. """ +from __future__ import print_function from __future__ import with_statement import os @@ -221,4 +222,4 @@ def main(): try: unittest.main(testLoader=BetterLoader(), defaultTest='suite') except Exception, e: - print 'Error: %s' % e + print('Error: %s' % e) diff --git a/flask/testsuite/config.py b/flask/testsuite/config.py index bf72925b..2027f578 100644 --- a/flask/testsuite/config.py +++ b/flask/testsuite/config.py @@ -113,7 +113,7 @@ class LimitedLoaderMockWrapper(object): def __getattr__(self, name): if name in ('archive', 'get_filename'): msg = 'Mocking a loader which does not have `%s.`' % name - raise AttributeError, msg + raise AttributeError(msg) return getattr(self.loader, name) From 0f8c47c988fbecc30785959065a53e00861c8558 Mon Sep 17 00:00:00 2001 From: Thomas Waldmann Date: Sat, 18 May 2013 18:00:15 +0200 Subject: [PATCH 3/6] python-modernize automated changes: fix_dict --- flask/sessions.py | 3 ++- flask/templating.py | 5 +++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/flask/sessions.py b/flask/sessions.py index 31b5900b..3746da7f 100644 --- a/flask/sessions.py +++ b/flask/sessions.py @@ -17,6 +17,7 @@ from werkzeug.datastructures import CallbackDict from . import Markup, json from itsdangerous import URLSafeTimedSerializer, BadSignature +import six def total_seconds(td): @@ -68,7 +69,7 @@ class TaggedJSONSerializer(object): elif isinstance(value, datetime): return {' d': http_date(value)} elif isinstance(value, dict): - return dict((k, _tag(v)) for k, v in value.iteritems()) + return dict((k, _tag(v)) for k, v in six.iteritems(value)) elif isinstance(value, str): try: return unicode(value) diff --git a/flask/templating.py b/flask/templating.py index 2cc09c4d..754c6893 100644 --- a/flask/templating.py +++ b/flask/templating.py @@ -15,6 +15,7 @@ from jinja2 import BaseLoader, Environment as BaseEnvironment, \ from .globals import _request_ctx_stack, _app_ctx_stack from .signals import template_rendered from .module import blueprint_is_module +import six def _default_template_ctx_processor(): @@ -79,7 +80,7 @@ class DispatchingJinjaLoader(BaseLoader): except (ValueError, KeyError): pass - for blueprint in self.app.blueprints.itervalues(): + for blueprint in six.itervalues(self.app.blueprints): if blueprint_is_module(blueprint): continue loader = blueprint.jinja_loader @@ -92,7 +93,7 @@ class DispatchingJinjaLoader(BaseLoader): if loader is not None: result.update(loader.list_templates()) - for name, blueprint in self.app.blueprints.iteritems(): + for name, blueprint in six.iteritems(self.app.blueprints): loader = blueprint.jinja_loader if loader is not None: for template in loader.list_templates(): From dcd052366b43df7bfe730c2e991ff37c617ba52b Mon Sep 17 00:00:00 2001 From: Thomas Waldmann Date: Sat, 18 May 2013 18:03:37 +0200 Subject: [PATCH 4/6] python-modernize automated changes: fix_next --- flask/helpers.py | 3 ++- flask/sessions.py | 2 +- flask/testsuite/helpers.py | 3 ++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/flask/helpers.py b/flask/helpers.py index d24dde6b..a302995c 100644 --- a/flask/helpers.py +++ b/flask/helpers.py @@ -26,6 +26,7 @@ from functools import update_wrapper from werkzeug.datastructures import Headers from werkzeug.exceptions import NotFound +import six # this was moved in 0.7 try: @@ -128,7 +129,7 @@ def stream_with_context(generator_or_function): # pushed. This item is discarded. Then when the iteration continues the # real generator is executed. wrapped_g = generator() - wrapped_g.next() + six.advance_iterator(wrapped_g) return wrapped_g diff --git a/flask/sessions.py b/flask/sessions.py index 3746da7f..b8e37014 100644 --- a/flask/sessions.py +++ b/flask/sessions.py @@ -85,7 +85,7 @@ class TaggedJSONSerializer(object): def object_hook(obj): if len(obj) != 1: return obj - the_key, the_value = obj.iteritems().next() + the_key, the_value = six.advance_iterator(obj.iteritems()) if the_key == ' t': return tuple(the_value) elif the_key == ' u': diff --git a/flask/testsuite/helpers.py b/flask/testsuite/helpers.py index fdf2d89f..5604f85f 100644 --- a/flask/testsuite/helpers.py +++ b/flask/testsuite/helpers.py @@ -18,6 +18,7 @@ from logging import StreamHandler from StringIO import StringIO from flask.testsuite import FlaskTestCase, catch_warnings, catch_stderr from werkzeug.http import parse_cache_control_header, parse_options_header +import six def has_encoding(name): @@ -507,7 +508,7 @@ class StreamingTestCase(FlaskTestCase): def close(self): called.append(42) def next(self): - return self._gen.next() + return six.advance_iterator(self._gen) @app.route('/') def index(): def generate(): From 522cd0009367d1f775b0e978681426773f51ce14 Mon Sep 17 00:00:00 2001 From: Thomas Waldmann Date: Sat, 18 May 2013 18:12:30 +0200 Subject: [PATCH 5/6] python-modernize automated changes: fix_unicode (but without six.u()) --- flask/json.py | 3 ++- flask/sessions.py | 4 ++-- flask/testsuite/basic.py | 3 ++- flask/testsuite/blueprints.py | 3 ++- flask/testsuite/helpers.py | 6 +++--- flask/testsuite/testing.py | 3 ++- 6 files changed, 13 insertions(+), 9 deletions(-) diff --git a/flask/json.py b/flask/json.py index 717eb2ab..dee2e189 100644 --- a/flask/json.py +++ b/flask/json.py @@ -17,6 +17,7 @@ from werkzeug.http import http_date # Use the same json implementation as itsdangerous on which we # depend anyways. from itsdangerous import simplejson as _json +import six # figure out if simplejson escapes slashes. This behavior was changed @@ -59,7 +60,7 @@ class JSONEncoder(_json.JSONEncoder): if isinstance(o, uuid.UUID): return str(o) if hasattr(o, '__html__'): - return unicode(o.__html__()) + return six.text_type(o.__html__()) return _json.JSONEncoder.default(self, o) diff --git a/flask/sessions.py b/flask/sessions.py index b8e37014..04b7f8af 100644 --- a/flask/sessions.py +++ b/flask/sessions.py @@ -63,7 +63,7 @@ class TaggedJSONSerializer(object): elif isinstance(value, uuid.UUID): return {' u': value.hex} elif callable(getattr(value, '__html__', None)): - return {' m': unicode(value.__html__())} + return {' m': six.text_type(value.__html__())} elif isinstance(value, list): return [_tag(x) for x in value] elif isinstance(value, datetime): @@ -72,7 +72,7 @@ class TaggedJSONSerializer(object): return dict((k, _tag(v)) for k, v in six.iteritems(value)) elif isinstance(value, str): try: - return unicode(value) + return six.text_type(value) except UnicodeError: raise UnexpectedUnicodeError(u'A byte string with ' u'non-ASCII data was passed to the session system ' diff --git a/flask/testsuite/basic.py b/flask/testsuite/basic.py index 5f6dbe4b..7cdf2211 100644 --- a/flask/testsuite/basic.py +++ b/flask/testsuite/basic.py @@ -22,6 +22,7 @@ from flask.testsuite import FlaskTestCase, emits_module_deprecation_warning from werkzeug.exceptions import BadRequest, NotFound from werkzeug.http import parse_date from werkzeug.routing import BuildError +import six class BasicFunctionalityTestCase(FlaskTestCase): @@ -277,7 +278,7 @@ class BasicFunctionalityTestCase(FlaskTestCase): @app.route('/test') def test(): - return unicode(flask.session.permanent) + return six.text_type(flask.session.permanent) client = app.test_client() rv = client.get('/') diff --git a/flask/testsuite/blueprints.py b/flask/testsuite/blueprints.py index ea047918..97426c8e 100644 --- a/flask/testsuite/blueprints.py +++ b/flask/testsuite/blueprints.py @@ -18,6 +18,7 @@ from flask.testsuite import FlaskTestCase, emits_module_deprecation_warning from werkzeug.exceptions import NotFound from werkzeug.http import parse_cache_control_header from jinja2 import TemplateNotFound +import six # import moduleapp here because it uses deprecated features and we don't @@ -304,7 +305,7 @@ class BlueprintTestCase(FlaskTestCase): @bp.route('/bar') def bar(bar): - return unicode(bar) + return six.text_type(bar) app = flask.Flask(__name__) app.register_blueprint(bp, url_prefix='/1', url_defaults={'bar': 23}) diff --git a/flask/testsuite/helpers.py b/flask/testsuite/helpers.py index 5604f85f..ac618538 100644 --- a/flask/testsuite/helpers.py +++ b/flask/testsuite/helpers.py @@ -36,7 +36,7 @@ class JSONTestCase(FlaskTestCase): app = flask.Flask(__name__) @app.route('/json', methods=['POST']) def return_json(): - return unicode(flask.request.json) + return six.text_type(flask.request.json) c = app.test_client() rv = c.post('/json', data='malformed', content_type='application/json') self.assert_equal(rv.status_code, 400) @@ -45,7 +45,7 @@ class JSONTestCase(FlaskTestCase): app = flask.Flask(__name__) @app.route('/json', methods=['POST']) def return_json(): - return unicode(flask.request.json) + return six.text_type(flask.request.json) c = app.test_client() rv = c.post('/json', data='malformed', content_type='application/json') self.assert_equal(rv.status_code, 400) @@ -97,7 +97,7 @@ class JSONTestCase(FlaskTestCase): app = flask.Flask(__name__) @app.route('/add', methods=['POST']) def add(): - return unicode(flask.request.json['a'] + flask.request.json['b']) + return six.text_type(flask.request.json['a'] + flask.request.json['b']) c = app.test_client() rv = c.post('/add', data=flask.json.dumps({'a': 1, 'b': 2}), content_type='application/json') diff --git a/flask/testsuite/testing.py b/flask/testsuite/testing.py index 92e3f267..92be9d33 100644 --- a/flask/testsuite/testing.py +++ b/flask/testsuite/testing.py @@ -14,6 +14,7 @@ from __future__ import with_statement import flask import unittest from flask.testsuite import FlaskTestCase +import six class TestToolsTestCase(FlaskTestCase): @@ -85,7 +86,7 @@ class TestToolsTestCase(FlaskTestCase): @app.route('/') def index(): - return unicode(flask.session['foo']) + return six.text_type(flask.session['foo']) with app.test_client() as c: with c.session_transaction() as sess: From 287905e67c2f22df3c3055a0cca025931726cd02 Mon Sep 17 00:00:00 2001 From: Thomas Waldmann Date: Sat, 18 May 2013 18:39:10 +0200 Subject: [PATCH 6/6] py3 compat: use six.reload_module --- flask/testsuite/ext.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/flask/testsuite/ext.py b/flask/testsuite/ext.py index 034ab5be..096a70f8 100644 --- a/flask/testsuite/ext.py +++ b/flask/testsuite/ext.py @@ -13,7 +13,7 @@ from __future__ import with_statement import sys import unittest from flask.testsuite import FlaskTestCase - +from six import reload_module class ExtImportHookTestCase(FlaskTestCase): @@ -29,7 +29,7 @@ class ExtImportHookTestCase(FlaskTestCase): entry == 'flaskext') and value is not None: sys.modules.pop(entry, None) from flask import ext - reload(ext) + reload_module(ext) # reloading must not add more hooks import_hooks = 0