From a503520ac51d16558ce91f7d7fc9d30a910d928c Mon Sep 17 00:00:00 2001 From: Thomas Waldmann Date: Tue, 21 May 2013 23:34:25 +0200 Subject: [PATCH 1/2] copy _compat.py from flask in here (and adapt docstring) --- flask/_compat.py | 104 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 100 insertions(+), 4 deletions(-) diff --git a/flask/_compat.py b/flask/_compat.py index 3743a54c..776a2dd7 100644 --- a/flask/_compat.py +++ b/flask/_compat.py @@ -3,11 +3,107 @@ 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. + Some py2/py3 compatibility support based on a stripped down + version of six so we don't have to depend on a specific version + of it. :copyright: (c) 2013 by Armin Ronacher. :license: BSD, see LICENSE for more details. """ +import sys + +PY2 = sys.version_info[0] == 2 +PYPY = hasattr(sys, 'pypy_translation_info') +_identity = lambda x: x + + +if not PY2: + unichr = chr + range_type = range + text_type = str + string_types = (str,) + + iterkeys = lambda d: iter(d.keys()) + itervalues = lambda d: iter(d.values()) + iteritems = lambda d: iter(d.items()) + + import pickle + from io import BytesIO, StringIO + NativeStringIO = StringIO + + def reraise(tp, value, tb=None): + if value.__traceback__ is not tb: + raise value.with_traceback(tb) + raise value + + ifilter = filter + imap = map + izip = zip + intern = sys.intern + + implements_iterator = _identity + implements_to_string = _identity + encode_filename = _identity + get_next = lambda x: x.__next__ + +else: + unichr = unichr + text_type = unicode + range_type = xrange + string_types = (str, unicode) + + iterkeys = lambda d: d.iterkeys() + itervalues = lambda d: d.itervalues() + iteritems = lambda d: d.iteritems() + + import cPickle as pickle + from cStringIO import StringIO as BytesIO, StringIO + NativeStringIO = BytesIO + + exec('def reraise(tp, value, tb=None):\n raise tp, value, tb') + + from itertools import imap, izip, ifilter + intern = intern + + def implements_iterator(cls): + cls.next = cls.__next__ + del cls.__next__ + return cls + + def implements_to_string(cls): + cls.__unicode__ = cls.__str__ + cls.__str__ = lambda x: x.__unicode__().encode('utf-8') + return cls + + get_next = lambda x: x.next + + def encode_filename(filename): + if isinstance(filename, unicode): + return filename.encode('utf-8') + return filename + + +def with_metaclass(meta, *bases): + # This requires a bit of explanation: the basic idea is to make a + # dummy metaclass for one level of class instanciation that replaces + # itself with the actual metaclass. Because of internal type checks + # we also need to make sure that we downgrade the custom metaclass + # for one level to something closer to type (that's why __call__ and + # __init__ comes back from type etc.). + # + # This has the advantage over six.with_metaclass in that it does not + # introduce dummy classes into the final MRO. + class metaclass(meta): + __call__ = type.__call__ + __init__ = type.__init__ + def __new__(cls, name, this_bases, d): + if this_bases is None: + return type.__new__(cls, name, (), d) + return meta(name, bases, d) + return metaclass('temporary_class', None, {}) + + +try: + from urllib.parse import quote_from_bytes as url_quote +except ImportError: + from urllib import quote as url_quote From e1d356fb713f3272db2a23f9f898c34c5dc79dc0 Mon Sep 17 00:00:00 2001 From: Thomas Waldmann Date: Wed, 22 May 2013 01:33:04 +0200 Subject: [PATCH 2/2] ported some more stuff to py 3.3 removed init_jinja_globals hack from app.py after consulting mitsuhiko (didn't work on py 3.3 "as is") removed with_statement future imports, not needed any more needs more work on 2.7 as well as on 3.3 --- examples/flaskr/flaskr.py | 2 +- examples/minitwit/minitwit.py | 2 +- flask/_compat.py | 6 ++++++ flask/app.py | 33 +++++++++------------------------ flask/config.py | 5 ++--- flask/exthook.py | 3 ++- flask/helpers.py | 9 ++++----- flask/testing.py | 4 +--- flask/testsuite/__init__.py | 5 ++--- flask/testsuite/appctx.py | 2 -- flask/testsuite/basic.py | 4 +--- flask/testsuite/blueprints.py | 2 -- flask/testsuite/config.py | 1 - flask/testsuite/deprecations.py | 19 +------------------ flask/testsuite/ext.py | 5 ++--- flask/testsuite/helpers.py | 4 +--- flask/testsuite/regression.py | 4 +--- flask/testsuite/reqctx.py | 2 -- flask/testsuite/signals.py | 1 - flask/testsuite/subclassing.py | 2 +- flask/testsuite/templating.py | 2 -- flask/testsuite/testing.py | 2 -- flask/testsuite/views.py | 2 +- scripts/flaskext_test.py | 2 -- 24 files changed, 36 insertions(+), 87 deletions(-) diff --git a/examples/flaskr/flaskr.py b/examples/flaskr/flaskr.py index 0647fc7b..20254660 100644 --- a/examples/flaskr/flaskr.py +++ b/examples/flaskr/flaskr.py @@ -9,7 +9,7 @@ :copyright: (c) 2010 by Armin Ronacher. :license: BSD, see LICENSE for more details. """ -from __future__ import with_statement + from sqlite3 import dbapi2 as sqlite3 from flask import Flask, request, session, g, redirect, url_for, abort, \ render_template, flash, _app_ctx_stack diff --git a/examples/minitwit/minitwit.py b/examples/minitwit/minitwit.py index a92da6af..2863de50 100644 --- a/examples/minitwit/minitwit.py +++ b/examples/minitwit/minitwit.py @@ -8,7 +8,7 @@ :copyright: (c) 2010 by Armin Ronacher. :license: BSD, see LICENSE for more details. """ -from __future__ import with_statement + import time from sqlite3 import dbapi2 as sqlite3 from hashlib import md5 diff --git a/flask/_compat.py b/flask/_compat.py index 776a2dd7..27f61137 100644 --- a/flask/_compat.py +++ b/flask/_compat.py @@ -22,6 +22,7 @@ if not PY2: range_type = range text_type = str string_types = (str,) + integer_types = (int, ) iterkeys = lambda d: iter(d.keys()) itervalues = lambda d: iter(d.values()) @@ -46,11 +47,14 @@ if not PY2: encode_filename = _identity get_next = lambda x: x.__next__ + from urllib.parse import urlparse + else: unichr = unichr text_type = unicode range_type = xrange string_types = (str, unicode) + integer_types = (int, long) iterkeys = lambda d: d.iterkeys() itervalues = lambda d: d.itervalues() @@ -82,6 +86,8 @@ else: return filename.encode('utf-8') return filename + from urlparse import urlparse + def with_metaclass(meta, *bases): # This requires a bit of explanation: the basic idea is to make a diff --git a/flask/app.py b/flask/app.py index 0337c608..dc684489 100644 --- a/flask/app.py +++ b/flask/app.py @@ -9,8 +9,6 @@ :license: BSD, see LICENSE for more details. """ -from __future__ import with_statement - import os import sys from threading import Lock @@ -36,6 +34,7 @@ from .templating import DispatchingJinjaLoader, Environment, \ _default_template_ctx_processor from .signals import request_started, request_finished, got_request_exception, \ request_tearing_down, appcontext_tearing_down +from flask._compat import reraise, string_types, integer_types # a lock used for logger initialization _logger_lock = Lock() @@ -585,21 +584,7 @@ class Flask(_PackageBoundObject): @locked_cached_property def jinja_env(self): """The Jinja2 environment used to load templates.""" - rv = self.create_jinja_environment() - - # Hack to support the init_jinja_globals method which is supported - # until 1.0 but has an API deficiency. - if getattr(self.init_jinja_globals, 'im_func', None) is not \ - Flask.init_jinja_globals.__func__: - from warnings import warn - warn(DeprecationWarning('This flask class uses a customized ' - 'init_jinja_globals() method which is deprecated. ' - 'Move the code from that method into the ' - 'create_jinja_environment() method instead.')) - self.__dict__['jinja_env'] = rv - self.init_jinja_globals() - - return rv + return self.create_jinja_environment() @property def got_first_request(self): @@ -1090,7 +1075,7 @@ class Flask(_PackageBoundObject): def _register_error_handler(self, key, code_or_exception, f): if isinstance(code_or_exception, HTTPException): code_or_exception = code_or_exception.code - if isinstance(code_or_exception, (int, long)): + if isinstance(code_or_exception, integer_types): assert code_or_exception != 500 or key is None, \ 'It is currently not possible to register a 500 internal ' \ 'server error on a per-blueprint level.' @@ -1137,7 +1122,7 @@ class Flask(_PackageBoundObject): def is_prime(n): if n == 2: return True - for i in xrange(2, int(math.ceil(math.sqrt(n))) + 1): + for i in range(2, int(math.ceil(math.sqrt(n))) + 1): if n % i == 0: return False return True @@ -1383,7 +1368,7 @@ class Flask(_PackageBoundObject): if isinstance(e, typecheck): return handler(e) - raise exc_type, exc_value, tb + reraise(exc_type, exc_value, tb) def handle_exception(self, e): """Default exception handling that kicks in when an exception @@ -1405,7 +1390,7 @@ class Flask(_PackageBoundObject): # (the function was actually called from the except part) # otherwise, we just raise the error again if exc_value is e: - raise exc_type, exc_value, tb + reraise(exc_type, exc_value, tb) else: raise e @@ -1565,14 +1550,14 @@ class Flask(_PackageBoundObject): # set the headers and status. We do this because there can be # some extra logic involved when creating these objects with # specific values (like defualt content type selection). - if isinstance(rv, basestring): + if isinstance(rv, string_types): rv = self.response_class(rv, headers=headers, status=status) headers = status = None else: rv = self.response_class.force_type(rv, request.environ) if status is not None: - if isinstance(status, basestring): + if isinstance(status, string_types): rv.status = status else: rv.status_code = status @@ -1633,7 +1618,7 @@ class Flask(_PackageBoundObject): # still the same one we can reraise it with the original traceback, # otherwise we raise it from here. if error is exc_value: - raise exc_type, exc_value, tb + reraise(exc_type, exc_value, tb) raise error def preprocess_request(self): diff --git a/flask/config.py b/flask/config.py index 3afe623a..ddb113a5 100644 --- a/flask/config.py +++ b/flask/config.py @@ -9,13 +9,12 @@ :license: BSD, see LICENSE for more details. """ -from __future__ import with_statement - import imp import os import errno from werkzeug.utils import import_string +from flask._compat import string_types class ConfigAttribute(object): @@ -158,7 +157,7 @@ class Config(dict): :param obj: an import name or object """ - if isinstance(obj, basestring): + if isinstance(obj, string_types): obj = import_string(obj) for key in dir(obj): if key.isupper(): diff --git a/flask/exthook.py b/flask/exthook.py index 26578f0f..89dac47b 100644 --- a/flask/exthook.py +++ b/flask/exthook.py @@ -21,6 +21,7 @@ """ import sys import os +from flask._compat import reraise class ExtensionImporter(object): @@ -77,7 +78,7 @@ class ExtensionImporter(object): # we swallow it and try the next choice. The skipped frame # is the one from __import__ above which we don't care about if self.is_important_traceback(realname, tb): - raise exc_type, exc_value, tb.tb_next + reraise(exc_type, exc_value, tb.tb_next) continue module = sys.modules[fullname] = sys.modules[realname] if '.' not in modname: diff --git a/flask/helpers.py b/flask/helpers.py index 68ebc74e..1359bba6 100644 --- a/flask/helpers.py +++ b/flask/helpers.py @@ -9,8 +9,6 @@ :license: BSD, see LICENSE for more details. """ -from __future__ import with_statement - import os import sys import pkgutil @@ -27,6 +25,7 @@ from functools import update_wrapper from werkzeug.datastructures import Headers from werkzeug.exceptions import NotFound import six +from flask._compat import string_types, text_type # this was moved in 0.7 try: @@ -467,7 +466,7 @@ def send_file(filename_or_fp, mimetype=None, as_attachment=False, :data:`~flask.current_app`. """ mtime = None - if isinstance(filename_or_fp, basestring): + if isinstance(filename_or_fp, string_types): filename = filename_or_fp file = None else: @@ -478,7 +477,7 @@ def send_file(filename_or_fp, mimetype=None, as_attachment=False, # XXX: this behavior is now deprecated because it was unreliable. # removed in Flask 1.0 if not attachment_filename and not mimetype \ - and isinstance(filename, basestring): + and isinstance(filename, string_types): warn(DeprecationWarning('The filename support for file objects ' 'passed to send_file is now deprecated. Pass an ' 'attach_filename if you want mimetypes to be guessed.'), @@ -540,7 +539,7 @@ def send_file(filename_or_fp, mimetype=None, as_attachment=False, os.path.getmtime(filename), os.path.getsize(filename), adler32( - filename.encode('utf-8') if isinstance(filename, unicode) + filename.encode('utf-8') if isinstance(filename, text_type) else filename ) & 0xffffffff )) diff --git a/flask/testing.py b/flask/testing.py index bdd3860f..ef116cf3 100644 --- a/flask/testing.py +++ b/flask/testing.py @@ -10,12 +10,10 @@ :license: BSD, see LICENSE for more details. """ -from __future__ import with_statement - from contextlib import contextmanager from werkzeug.test import Client, EnvironBuilder from flask import _request_ctx_stack -from urlparse import urlparse +from flask._compat import urlparse def make_test_environ_builder(app, path='/', base_url=None, *args, **kwargs): diff --git a/flask/testsuite/__init__.py b/flask/testsuite/__init__.py index 9027369c..82fa3232 100644 --- a/flask/testsuite/__init__.py +++ b/flask/testsuite/__init__.py @@ -11,17 +11,16 @@ """ from __future__ import print_function -from __future__ import with_statement import os import sys import flask import warnings import unittest -from StringIO import StringIO from functools import update_wrapper from contextlib import contextmanager from werkzeug.utils import import_string, find_modules +from flask._compat import reraise, StringIO def add_to_path(path): @@ -159,7 +158,7 @@ class _ExceptionCatcher(object): self.test_case.fail('Expected exception of type %r' % exception_name) elif not issubclass(exc_type, self.exc_type): - raise exc_type, exc_value, tb + reraise(exc_type, exc_value, tb) return True diff --git a/flask/testsuite/appctx.py b/flask/testsuite/appctx.py index aa71e11e..afed923a 100644 --- a/flask/testsuite/appctx.py +++ b/flask/testsuite/appctx.py @@ -9,8 +9,6 @@ :license: BSD, see LICENSE for more details. """ -from __future__ import with_statement - import flask import unittest from flask.testsuite import FlaskTestCase diff --git a/flask/testsuite/basic.py b/flask/testsuite/basic.py index 89159a16..974b4ebc 100644 --- a/flask/testsuite/basic.py +++ b/flask/testsuite/basic.py @@ -9,8 +9,6 @@ :license: BSD, see LICENSE for more details. """ -from __future__ import with_statement - import re import uuid import flask @@ -1060,7 +1058,7 @@ class BasicFunctionalityTestCase(FlaskTestCase): 1/0 c = app.test_client() - for x in xrange(3): + for x in range(3): with self.assert_raises(ZeroDivisionError): c.get('/fail') diff --git a/flask/testsuite/blueprints.py b/flask/testsuite/blueprints.py index eba43e63..331854a6 100644 --- a/flask/testsuite/blueprints.py +++ b/flask/testsuite/blueprints.py @@ -9,8 +9,6 @@ :license: BSD, see LICENSE for more details. """ -from __future__ import with_statement - import flask import unittest import warnings diff --git a/flask/testsuite/config.py b/flask/testsuite/config.py index ca142cff..415d8aca 100644 --- a/flask/testsuite/config.py +++ b/flask/testsuite/config.py @@ -8,7 +8,6 @@ :copyright: (c) 2011 by Armin Ronacher. :license: BSD, see LICENSE for more details. """ -from __future__ import with_statement import os import sys diff --git a/flask/testsuite/deprecations.py b/flask/testsuite/deprecations.py index 795a5d3d..56371822 100644 --- a/flask/testsuite/deprecations.py +++ b/flask/testsuite/deprecations.py @@ -9,30 +9,13 @@ :license: BSD, see LICENSE for more details. """ -from __future__ import with_statement - import flask import unittest from flask.testsuite import FlaskTestCase, catch_warnings class DeprecationsTestCase(FlaskTestCase): - - def test_init_jinja_globals(self): - class MyFlask(flask.Flask): - def init_jinja_globals(self): - self.jinja_env.globals['foo'] = '42' - - with catch_warnings() as log: - app = MyFlask(__name__) - @app.route('/') - def foo(): - return app.jinja_env.globals['foo'] - - c = app.test_client() - self.assert_equal(c.get('/').data, '42') - self.assert_equal(len(log), 1) - self.assert_('init_jinja_globals' in str(log[0]['message'])) + """not used currently""" def suite(): diff --git a/flask/testsuite/ext.py b/flask/testsuite/ext.py index 6f6a34f4..147e23b0 100644 --- a/flask/testsuite/ext.py +++ b/flask/testsuite/ext.py @@ -8,7 +8,6 @@ :copyright: (c) 2011 by Armin Ronacher. :license: BSD, see LICENSE for more details. """ -from __future__ import with_statement import sys import unittest @@ -22,7 +21,7 @@ class ExtImportHookTestCase(FlaskTestCase): # that a real flaskext could be in there which would disable our # fake package. Secondly we want to make sure that the flaskext # import hook does not break on reloading. - for entry, value in sys.modules.items(): + for entry, value in list(sys.modules.items()): if (entry.startswith('flask.ext.') or entry.startswith('flask_') or entry.startswith('flaskext.') or @@ -100,7 +99,7 @@ class ExtImportHookTestCase(FlaskTestCase): self.assert_equal(test_function(), 42) def test_flaskext_broken_package_no_module_caching(self): - for x in xrange(2): + for x in range(2): with self.assert_raises(ImportError): import flask.ext.broken diff --git a/flask/testsuite/helpers.py b/flask/testsuite/helpers.py index ac618538..2808a409 100644 --- a/flask/testsuite/helpers.py +++ b/flask/testsuite/helpers.py @@ -9,16 +9,14 @@ :license: BSD, see LICENSE for more details. """ -from __future__ import with_statement - import os import flask import unittest 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 +from flask._compat import StringIO def has_encoding(name): diff --git a/flask/testsuite/regression.py b/flask/testsuite/regression.py index 00219856..b8140d6f 100644 --- a/flask/testsuite/regression.py +++ b/flask/testsuite/regression.py @@ -9,8 +9,6 @@ :license: BSD, see LICENSE for more details. """ -from __future__ import with_statement - import os import gc import sys @@ -77,7 +75,7 @@ class MemoryTestCase(FlaskTestCase): if sys.version_info >= (2, 7) and \ not hasattr(sys, 'pypy_translation_info'): with self.assert_no_leak(): - for x in xrange(10): + for x in range(10): fire() def test_safe_join_toplevel_pardir(self): diff --git a/flask/testsuite/reqctx.py b/flask/testsuite/reqctx.py index 89a47728..0f0282e5 100644 --- a/flask/testsuite/reqctx.py +++ b/flask/testsuite/reqctx.py @@ -9,8 +9,6 @@ :license: BSD, see LICENSE for more details. """ -from __future__ import with_statement - import flask import unittest try: diff --git a/flask/testsuite/signals.py b/flask/testsuite/signals.py index 0e5d0cea..637c2c66 100644 --- a/flask/testsuite/signals.py +++ b/flask/testsuite/signals.py @@ -8,7 +8,6 @@ :copyright: (c) 2011 by Armin Ronacher. :license: BSD, see LICENSE for more details. """ -from __future__ import with_statement import flask import unittest diff --git a/flask/testsuite/subclassing.py b/flask/testsuite/subclassing.py index 89aa9150..3e8d75c1 100644 --- a/flask/testsuite/subclassing.py +++ b/flask/testsuite/subclassing.py @@ -11,9 +11,9 @@ """ import flask import unittest -from StringIO import StringIO from logging import StreamHandler from flask.testsuite import FlaskTestCase +from flask._compat import StringIO class FlaskSubclassingTestCase(FlaskTestCase): diff --git a/flask/testsuite/templating.py b/flask/testsuite/templating.py index 635210f7..c8d1dd22 100644 --- a/flask/testsuite/templating.py +++ b/flask/testsuite/templating.py @@ -9,8 +9,6 @@ :license: BSD, see LICENSE for more details. """ -from __future__ import with_statement - import flask import unittest from flask.testsuite import FlaskTestCase diff --git a/flask/testsuite/testing.py b/flask/testsuite/testing.py index 2872ecdc..a37f6e6c 100644 --- a/flask/testsuite/testing.py +++ b/flask/testsuite/testing.py @@ -9,8 +9,6 @@ :license: BSD, see LICENSE for more details. """ -from __future__ import with_statement - import flask import unittest from flask.testsuite import FlaskTestCase diff --git a/flask/testsuite/views.py b/flask/testsuite/views.py index f09c1266..6c3ae816 100644 --- a/flask/testsuite/views.py +++ b/flask/testsuite/views.py @@ -8,7 +8,7 @@ :copyright: (c) 2011 by Armin Ronacher. :license: BSD, see LICENSE for more details. """ -from __future__ import with_statement + import flask import flask.views import unittest diff --git a/scripts/flaskext_test.py b/scripts/flaskext_test.py index d1d5d991..5b0d9d22 100644 --- a/scripts/flaskext_test.py +++ b/scripts/flaskext_test.py @@ -9,8 +9,6 @@ :license: BSD, see LICENSE for more details. """ -from __future__ import with_statement - import os import sys import shutil