From: Thomas Waldmann Date: Fri, 17 May 2013 21:52:14 +0000 (+0200) Subject: python 3 port: automated changes by a slightly modified python-modernize X-Git-Tag: 2.7~89 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e0003555f8df3e1cc6721ca759f277b6fe21f3d4;p=thirdparty%2Fjinja.git python 3 port: automated changes by a slightly modified python-modernize (replacing unicode with six.text_type, but not replacing u"" by six.u("")) --- diff --git a/jinja2/_markupsafe/__init__.py b/jinja2/_markupsafe/__init__.py index ec7bd572..6aae11a4 100644 --- a/jinja2/_markupsafe/__init__.py +++ b/jinja2/_markupsafe/__init__.py @@ -10,6 +10,9 @@ """ import re from itertools import imap +import six +from six.moves import map +from six.moves import zip __all__ = ['Markup', 'soft_unicode', 'escape', 'escape_silent'] @@ -76,12 +79,12 @@ class Markup(unicode): def __add__(self, other): if hasattr(other, '__html__') or isinstance(other, basestring): - return self.__class__(unicode(self) + unicode(escape(other))) + return self.__class__(six.text_type(self) + six.text_type(escape(other))) return NotImplemented def __radd__(self, other): if hasattr(other, '__html__') or isinstance(other, basestring): - return self.__class__(unicode(escape(other)) + unicode(self)) + return self.__class__(six.text_type(escape(other)) + six.text_type(self)) return NotImplemented def __mul__(self, num): @@ -139,7 +142,7 @@ class Markup(unicode): except ValueError: pass return u'' - return _entity_re.sub(handle_match, unicode(self)) + return _entity_re.sub(handle_match, six.text_type(self)) def striptags(self): r"""Unescape markup into an unicode string and strip all tags. This @@ -167,7 +170,7 @@ class Markup(unicode): orig = getattr(unicode, name) def func(self, *args, **kwargs): args = _escape_argspec(list(args), enumerate(args)) - _escape_argspec(kwargs, kwargs.iteritems()) + _escape_argspec(kwargs, six.iteritems(kwargs)) return self.__class__(orig(self, *args, **kwargs)) func.__name__ = orig.__name__ func.__doc__ = orig.__doc__ @@ -211,7 +214,7 @@ class _MarkupEscapeHelper(object): __getitem__ = lambda s, x: _MarkupEscapeHelper(s.obj[x]) __str__ = lambda s: str(escape(s.obj)) - __unicode__ = lambda s: unicode(escape(s.obj)) + __unicode__ = lambda s: six.text_type(escape(s.obj)) __repr__ = lambda s: str(escape(repr(s.obj))) __int__ = lambda s: int(s.obj) __float__ = lambda s: float(s.obj) diff --git a/jinja2/_markupsafe/_bundle.py b/jinja2/_markupsafe/_bundle.py index e694faf2..d23730f6 100644 --- a/jinja2/_markupsafe/_bundle.py +++ b/jinja2/_markupsafe/_bundle.py @@ -10,6 +10,7 @@ :copyright: Copyright 2010 by the Jinja team, see AUTHORS. :license: BSD, see LICENSE for details. """ +from __future__ import print_function import sys import os import re @@ -25,7 +26,7 @@ def rewrite_imports(lines): def main(): if len(sys.argv) != 2: - print 'error: only argument is path to markupsafe' + print('error: only argument is path to markupsafe') sys.exit(1) basedir = os.path.dirname(__file__) markupdir = sys.argv[1] diff --git a/jinja2/_markupsafe/_native.py b/jinja2/_markupsafe/_native.py index 7b95828e..97065bb0 100644 --- a/jinja2/_markupsafe/_native.py +++ b/jinja2/_markupsafe/_native.py @@ -9,6 +9,7 @@ :license: BSD, see LICENSE for more details. """ from jinja2._markupsafe import Markup +import six def escape(s): @@ -18,7 +19,7 @@ def escape(s): """ if hasattr(s, '__html__'): return s.__html__() - return Markup(unicode(s) + return Markup(six.text_type(s) .replace('&', '&') .replace('>', '>') .replace('<', '<') @@ -41,5 +42,5 @@ def soft_unicode(s): string is not converted back to unicode. """ if not isinstance(s, unicode): - s = unicode(s) + s = six.text_type(s) return s diff --git a/jinja2/_markupsafe/tests.py b/jinja2/_markupsafe/tests.py index c1ce3943..449df493 100644 --- a/jinja2/_markupsafe/tests.py +++ b/jinja2/_markupsafe/tests.py @@ -1,6 +1,7 @@ import gc import unittest from jinja2._markupsafe import Markup, escape, escape_silent +import six class MarkupTestCase(unittest.TestCase): @@ -9,7 +10,7 @@ class MarkupTestCase(unittest.TestCase): # adding two strings should escape the unsafe one unsafe = '' safe = Markup('username') - assert unsafe + safe == unicode(escape(unsafe)) + unicode(safe) + assert unsafe + safe == six.text_type(escape(unsafe)) + six.text_type(safe) # string interpolations are safe to use too assert Markup('%s') % '' == \ @@ -55,8 +56,8 @@ class MarkupLeakTestCase(unittest.TestCase): def test_markup_leaks(self): counts = set() - for count in xrange(20): - for item in xrange(1000): + for count in range(20): + for item in range(1000): escape("foo") escape("") escape(u"foo") diff --git a/jinja2/compiler.py b/jinja2/compiler.py index b21cb386..35f7d028 100644 --- a/jinja2/compiler.py +++ b/jinja2/compiler.py @@ -16,6 +16,9 @@ from jinja2.nodes import EvalContext from jinja2.visitor import NodeVisitor from jinja2.exceptions import TemplateAssertionError from jinja2.utils import Markup, concat, escape, is_python_keyword, next +import six +from six.moves import map +from six.moves import zip operators = { @@ -30,7 +33,7 @@ operators = { } try: - exec '(0 if 0 else 0)' + exec('(0 if 0 else 0)') except SyntaxError: have_condexpr = False else: @@ -51,7 +54,7 @@ def unoptimize_before_dead_code(): def f(): if 0: dummy(x) return f -unoptimize_before_dead_code = bool(unoptimize_before_dead_code().func_closure) +unoptimize_before_dead_code = bool(unoptimize_before_dead_code().__closure__) def generate(node, environment, name, filename, stream=None, @@ -78,7 +81,7 @@ def has_safe_repr(value): return False return True elif isinstance(value, dict): - for key, value in value.iteritems(): + for key, value in six.iteritems(value): if not has_safe_repr(key): return False if not has_safe_repr(value): @@ -542,7 +545,7 @@ class CodeGenerator(NodeVisitor): self.write(', ') self.visit(kwarg, frame) if extra_kwargs is not None: - for key, value in extra_kwargs.iteritems(): + for key, value in six.iteritems(extra_kwargs): self.write(', %s=%s' % (key, value)) if node.dyn_args: self.write(', *') @@ -558,7 +561,7 @@ class CodeGenerator(NodeVisitor): self.visit(kwarg.value, frame) self.write(', ') if extra_kwargs is not None: - for key, value in extra_kwargs.iteritems(): + for key, value in six.iteritems(extra_kwargs): self.write('%r: %s, ' % (key, value)) if node.dyn_kwargs is not None: self.write('}, **') @@ -625,7 +628,7 @@ class CodeGenerator(NodeVisitor): def pop_scope(self, aliases, frame): """Restore all aliases and delete unused variables.""" - for name, alias in aliases.iteritems(): + for name, alias in six.iteritems(aliases): self.writeline('l_%s = %s' % (name, alias)) to_delete = set() for name in frame.identifiers.declared_locally: @@ -827,7 +830,7 @@ class CodeGenerator(NodeVisitor): self.outdent(2 + (not self.has_known_extends)) # at this point we now have the blocks collected and can visit them too. - for name, block in self.blocks.iteritems(): + for name, block in six.iteritems(self.blocks): block_frame = Frame(eval_ctx) block_frame.inspect(block.body) block_frame.block = name @@ -1216,7 +1219,7 @@ class CodeGenerator(NodeVisitor): return if self.environment.finalize: - finalize = lambda x: unicode(self.environment.finalize(x)) + finalize = lambda x: six.text_type(self.environment.finalize(x)) else: finalize = unicode diff --git a/jinja2/debug.py b/jinja2/debug.py index 3ac4041a..c653e366 100644 --- a/jinja2/debug.py +++ b/jinja2/debug.py @@ -15,6 +15,7 @@ import traceback from types import TracebackType from jinja2.utils import CodeType, missing, internal_code from jinja2.exceptions import TemplateSyntaxError +import six # on pypy we can take advantage of transparent proxies try: @@ -25,7 +26,7 @@ except ImportError: # how does the raise helper look like? try: - exec "raise TypeError, 'foo'" + exec("raise TypeError, 'foo'") except SyntaxError: raise_helper = 'raise __jinja_exception__[1]' except TypeError: @@ -158,7 +159,7 @@ def translate_exception(exc_info, initial_skip=0): frames = [] # skip some internal frames if wanted - for x in xrange(initial_skip): + for x in range(initial_skip): if tb is not None: tb = tb.tb_next initial_tb = tb @@ -206,7 +207,7 @@ def fake_exc_info(exc_info, filename, lineno): locals = ctx.get_all() else: locals = {} - for name, value in real_locals.iteritems(): + for name, value in six.iteritems(real_locals): if name.startswith('l_') and value is not missing: locals[name[2:]] = value @@ -254,7 +255,7 @@ def fake_exc_info(exc_info, filename, lineno): # execute the code and catch the new traceback try: - exec code in globals, locals + exec(code, globals, locals) except: exc_info = sys.exc_info() new_tb = exc_info[2].tb_next diff --git a/jinja2/environment.py b/jinja2/environment.py index 1b5dc40d..71f022f3 100644 --- a/jinja2/environment.py +++ b/jinja2/environment.py @@ -21,6 +21,11 @@ from jinja2.exceptions import TemplateSyntaxError, TemplateNotFound, \ TemplatesNotFound from jinja2.utils import import_string, LRUCache, Markup, missing, \ concat, consume, internalcode, _encode_filename +import six +from functools import reduce +from six.moves import filter +from six.moves import map +from six.moves import zip # for direct template usage we have up to ten living environments @@ -292,7 +297,7 @@ class Environment(object): yet. This is used by :ref:`extensions ` to register callbacks and configuration values without breaking inheritance. """ - for key, value in attributes.iteritems(): + for key, value in six.iteritems(attributes): if not hasattr(self, key): setattr(self, key, value) @@ -323,7 +328,7 @@ class Environment(object): rv.overlayed = True rv.linked_to = self - for key, value in args.iteritems(): + for key, value in six.iteritems(args): if value is not missing: setattr(rv, key, value) @@ -333,7 +338,7 @@ class Environment(object): rv.cache = copy_cache(self.cache) rv.extensions = {} - for key, value in self.extensions.iteritems(): + for key, value in six.iteritems(self.extensions): rv.extensions[key] = value.bind(rv) if extensions is not missing: rv.extensions.update(load_extensions(rv, extensions)) @@ -407,7 +412,7 @@ class Environment(object): of the extensions to be applied you have to filter source through the :meth:`preprocess` method. """ - source = unicode(source) + source = six.text_type(source) try: return self.lexer.tokeniter(source, name, filename) except TemplateSyntaxError: @@ -420,7 +425,7 @@ class Environment(object): because there you usually only want the actual source tokenized. """ return reduce(lambda s, e: e.preprocess(s, name, filename), - self.iter_extensions(), unicode(source)) + self.iter_extensions(), six.text_type(source)) def _tokenize(self, source, name, filename=None, state=None): """Called by the parser to do the preprocessing and filtering @@ -577,7 +582,7 @@ class Environment(object): def write_file(filename, data, mode): if zip: info = ZipInfo(filename) - info.external_attr = 0755 << 16L + info.external_attr = 0o755 << 16 zip_file.writestr(info, data) else: f = open(os.path.join(target, filename), mode) @@ -601,7 +606,7 @@ class Environment(object): source, filename, _ = self.loader.get_source(self, name) try: code = self.compile(source, name, filename, True, True) - except TemplateSyntaxError, e: + except TemplateSyntaxError as e: if not ignore_errors: raise log_function('Could not compile "%s": %s' % (name, e)) @@ -843,7 +848,7 @@ class Template(object): 'environment': environment, '__file__': code.co_filename } - exec code in namespace + exec(code, namespace) rv = cls._from_namespace(environment, namespace, globals) rv._uptodate = uptodate return rv @@ -1003,7 +1008,7 @@ class TemplateModule(object): return Markup(concat(self._body_stream)) def __str__(self): - return unicode(self).encode('utf-8') + return six.text_type(self).encode('utf-8') # unicode goes after __str__ because we configured 2to3 to rename # __unicode__ to __str__. because the 2to3 tree is not designed to diff --git a/jinja2/exceptions.py b/jinja2/exceptions.py index 841aabbd..90025210 100644 --- a/jinja2/exceptions.py +++ b/jinja2/exceptions.py @@ -8,6 +8,9 @@ :copyright: (c) 2010 by the Jinja Team. :license: BSD, see LICENSE for more details. """ +import six +from six.moves import map +from six.moves import zip class TemplateError(Exception): @@ -15,7 +18,7 @@ class TemplateError(Exception): def __init__(self, message=None): if message is not None: - message = unicode(message).encode('utf-8') + message = six.text_type(message).encode('utf-8') Exception.__init__(self, message) @property @@ -83,7 +86,7 @@ class TemplateSyntaxError(TemplateError): self.translated = False def __str__(self): - return unicode(self).encode('utf-8') + return six.text_type(self).encode('utf-8') # unicode goes after __str__ because we configured 2to3 to rename # __unicode__ to __str__. because the 2to3 tree is not designed to diff --git a/jinja2/ext.py b/jinja2/ext.py index 206756fe..984a4d95 100644 --- a/jinja2/ext.py +++ b/jinja2/ext.py @@ -17,6 +17,7 @@ from jinja2.environment import Environment from jinja2.runtime import Undefined, concat from jinja2.exceptions import TemplateAssertionError, TemplateSyntaxError from jinja2.utils import contextfunction, import_string, Markup, next +import six # the only real useful gettext functions for a Jinja template. Note @@ -354,7 +355,7 @@ class InternationalizationExtension(Extension): # enough to handle the variable expansion and autoescape # handling itself if self.environment.newstyle_gettext: - for key, value in variables.iteritems(): + for key, value in six.iteritems(variables): # the function adds that later anyways in case num was # called num, so just skip it. if num_called_num and key == 'num': @@ -601,7 +602,7 @@ def babel_extract(fileobj, keywords, comment_tags, options): try: node = environment.parse(source) tokens = list(environment.lex(environment.preprocess(source))) - except TemplateSyntaxError, e: + except TemplateSyntaxError as e: if not silent: raise # skip templates with syntax errors diff --git a/jinja2/filters.py b/jinja2/filters.py index 47f07684..43387aeb 100644 --- a/jinja2/filters.py +++ b/jinja2/filters.py @@ -17,6 +17,9 @@ from jinja2.utils import Markup, escape, pformat, urlize, soft_unicode, \ unicode_urlencode from jinja2.runtime import Undefined from jinja2.exceptions import FilterArgumentError +import six +from six.moves import map +from six.moves import zip _word_re = re.compile(r'\w+(?u)') @@ -68,7 +71,7 @@ def do_forceescape(value): """Enforce HTML escaping. This will probably double escape variables.""" if hasattr(value, '__html__'): value = value.__html__() - return escape(unicode(value)) + return escape(six.text_type(value)) def do_urlencode(value): @@ -79,7 +82,7 @@ def do_urlencode(value): """ itemiter = None if isinstance(value, dict): - itemiter = value.iteritems() + itemiter = six.iteritems(value) elif not isinstance(value, basestring): try: itemiter = iter(value) @@ -110,7 +113,7 @@ def do_replace(eval_ctx, s, old, new, count=None): if count is None: count = -1 if not eval_ctx.autoescape: - return unicode(s).replace(unicode(old), unicode(new), count) + return six.text_type(s).replace(six.text_type(old), six.text_type(new), count) if hasattr(old, '__html__') or hasattr(new, '__html__') and \ not hasattr(s, '__html__'): s = escape(s) @@ -155,7 +158,7 @@ def do_xmlattr(_eval_ctx, d, autospace=True): """ rv = u' '.join( u'%s="%s"' % (escape(key), escape(value)) - for key, value in d.iteritems() + for key, value in six.iteritems(d) if value is not None and not isinstance(value, Undefined) ) if autospace and rv: @@ -309,7 +312,7 @@ def do_join(eval_ctx, value, d=u'', attribute=None): # no automatic escaping? joining is a lot eaiser then if not eval_ctx.autoescape: - return unicode(d).join(imap(unicode, value)) + return six.text_type(d).join(imap(unicode, value)) # if the delimiter doesn't have an html representation we check # if any of the items has. If yes we do a coercion to Markup @@ -320,11 +323,11 @@ def do_join(eval_ctx, value, d=u'', attribute=None): if hasattr(item, '__html__'): do_escape = True else: - value[idx] = unicode(item) + value[idx] = six.text_type(item) if do_escape: d = escape(d) else: - d = unicode(d) + d = six.text_type(d) return d.join(value) # no html involved, to normal joining @@ -333,14 +336,14 @@ def do_join(eval_ctx, value, d=u'', attribute=None): def do_center(value, width=80): """Centers the value in a field of a given width.""" - return unicode(value).center(width) + return six.text_type(value).center(width) @environmentfilter def do_first(environment, seq): """Return the first item of a sequence.""" try: - return iter(seq).next() + return six.advance_iterator(iter(seq)) except StopIteration: return environment.undefined('No first item, sequence was empty.') @@ -349,7 +352,7 @@ def do_first(environment, seq): def do_last(environment, seq): """Return the last item of a sequence.""" try: - return iter(reversed(seq)).next() + return six.advance_iterator(iter(reversed(seq))) except StopIteration: return environment.undefined('No last item, sequence was empty.') @@ -539,7 +542,7 @@ def do_striptags(value): """ if hasattr(value, '__html__'): value = value.__html__() - return Markup(unicode(value)).striptags() + return Markup(six.text_type(value)).striptags() def do_slice(value, slices, fill_with=None): @@ -567,7 +570,7 @@ def do_slice(value, slices, fill_with=None): items_per_slice = length // slices slices_with_extra = length % slices offset = 0 - for slice_number in xrange(slices): + for slice_number in range(slices): start = offset + slice_number * items_per_slice if slice_number < slices_with_extra: offset += 1 @@ -692,7 +695,8 @@ class _GroupTuple(tuple): grouper = property(itemgetter(0)) list = property(itemgetter(1)) - def __new__(cls, (key, value)): + def __new__(cls, xxx_todo_changeme): + (key, value) = xxx_todo_changeme return tuple.__new__(cls, (key, list(value))) @@ -733,7 +737,7 @@ def do_mark_safe(value): def do_mark_unsafe(value): """Mark a value as unsafe. This is the reverse operation for :func:`safe`.""" - return unicode(value) + return six.text_type(value) def do_reverse(value): diff --git a/jinja2/lexer.py b/jinja2/lexer.py index 69865d08..5d24718f 100644 --- a/jinja2/lexer.py +++ b/jinja2/lexer.py @@ -19,6 +19,7 @@ from operator import itemgetter from collections import deque from jinja2.exceptions import TemplateSyntaxError from jinja2.utils import LRUCache, next +import six # cache for the lexers. Exists in order to be able to have multiple @@ -126,7 +127,7 @@ operators = { ';': TOKEN_SEMICOLON } -reverse_operators = dict([(v, k) for k, v in operators.iteritems()]) +reverse_operators = dict([(v, k) for k, v in six.iteritems(operators)]) assert len(operators) == len(reverse_operators), 'operators dropped' operator_re = re.compile('(%s)' % '|'.join(re.escape(x) for x in sorted(operators, key=lambda x: -len(x)))) @@ -319,7 +320,7 @@ class TokenStream(object): def skip(self, n=1): """Got n tokens ahead.""" - for x in xrange(n): + for x in range(n): next(self) def next_if(self, expr): @@ -526,7 +527,7 @@ class Lexer(object): value = self._normalize_newlines(value[1:-1]) \ .encode('ascii', 'backslashreplace') \ .decode('unicode-escape') - except Exception, e: + except Exception as e: msg = str(e).split(':')[-1].strip() raise TemplateSyntaxError(msg, lineno, name, filename) # if we can express it as bytestring (ascii only) @@ -549,7 +550,7 @@ class Lexer(object): """This method tokenizes the text and returns the tokens in a generator. Use this method if you just want to tokenize a template. """ - source = '\n'.join(unicode(source).splitlines()) + source = '\n'.join(six.text_type(source).splitlines()) pos = 0 lineno = 1 stack = ['root'] @@ -590,7 +591,7 @@ class Lexer(object): # yield for the current token the first named # group that matched elif token == '#bygroup': - for key, value in m.groupdict().iteritems(): + for key, value in six.iteritems(m.groupdict()): if value is not None: yield lineno, key, value lineno += value.count('\n') @@ -647,7 +648,7 @@ class Lexer(object): stack.pop() # resolve the new state by group checking elif new_state == '#bygroup': - for key, value in m.groupdict().iteritems(): + for key, value in six.iteritems(m.groupdict()): if value is not None: stack.append(key) break diff --git a/jinja2/loaders.py b/jinja2/loaders.py index c90bbe72..a2749227 100644 --- a/jinja2/loaders.py +++ b/jinja2/loaders.py @@ -13,6 +13,7 @@ import sys import weakref from types import ModuleType from os import path +import six try: from hashlib import sha1 except ImportError: @@ -359,7 +360,7 @@ class PrefixLoader(BaseLoader): def list_templates(self): result = [] - for prefix, loader in self.mapping.iteritems(): + for prefix, loader in six.iteritems(self.mapping): for template in loader.list_templates(): result.append(prefix + self.delimiter + template) return result diff --git a/jinja2/nodes.py b/jinja2/nodes.py index f9da1da5..5651a41c 100644 --- a/jinja2/nodes.py +++ b/jinja2/nodes.py @@ -16,6 +16,7 @@ import operator from itertools import chain, izip from collections import deque from jinja2.utils import Markup, MethodType, FunctionType +import six #: the types we support for context functions @@ -142,7 +143,7 @@ class Node(object): setattr(self, attr, attributes.pop(attr, None)) if attributes: raise TypeError('unknown attribute %r' % - iter(attributes).next()) + six.advance_iterator(iter(attributes))) def iter_fields(self, exclude=None, only=None): """This method iterates over all fields that are defined and yields @@ -440,7 +441,7 @@ class Const(Literal): constant value in the generated code, otherwise it will raise an `Impossible` exception. """ - from compiler import has_safe_repr + from .compiler import has_safe_repr if not has_safe_repr(value): raise Impossible() return cls(value, lineno=lineno, environment=environment) @@ -687,7 +688,7 @@ class Concat(Expr): def as_const(self, eval_ctx=None): eval_ctx = get_eval_context(self, eval_ctx) - return ''.join(unicode(x.as_const(eval_ctx)) for x in self.nodes) + return ''.join(six.text_type(x.as_const(eval_ctx)) for x in self.nodes) class Compare(Expr): diff --git a/jinja2/parser.py b/jinja2/parser.py index 21253389..b4b06fe8 100644 --- a/jinja2/parser.py +++ b/jinja2/parser.py @@ -12,6 +12,8 @@ from jinja2 import nodes from jinja2.exceptions import TemplateSyntaxError, TemplateAssertionError from jinja2.utils import next from jinja2.lexer import describe_token, describe_token_expr +from six.moves import map +from six.moves import zip #: statements that callinto diff --git a/jinja2/runtime.py b/jinja2/runtime.py index 5c399841..750b630a 100644 --- a/jinja2/runtime.py +++ b/jinja2/runtime.py @@ -14,6 +14,7 @@ from jinja2.utils import Markup, partial, soft_unicode, escape, missing, \ concat, internalcode, next, object_type_repr from jinja2.exceptions import UndefinedError, TemplateRuntimeError, \ TemplateNotFound +import six # these variables are exported to the template runtime @@ -63,7 +64,7 @@ def new_context(environment, template_name, blocks, vars=None, # we don't want to modify the dict passed if shared: parent = dict(parent) - for key, value in locals.iteritems(): + for key, value in six.iteritems(locals): if key[:2] == 'l_' and value is not missing: parent[key[2:]] = value return Context(environment, parent, template_name, blocks) @@ -119,7 +120,7 @@ class Context(object): # create the initial mapping of blocks. Whenever template inheritance # takes place the runtime will update this mapping with the new blocks # from the template. - self.blocks = dict((k, [v]) for k, v in blocks.iteritems()) + self.blocks = dict((k, [v]) for k, v in six.iteritems(blocks)) def super(self, name, current): """Render a parent block.""" @@ -191,7 +192,7 @@ class Context(object): self.parent, True, None, locals) context.vars.update(self.vars) context.eval_ctx = self.eval_ctx - context.blocks.update((k, list(v)) for k, v in self.blocks.iteritems()) + context.blocks.update((k, list(v)) for k, v in six.iteritems(self.blocks)) return context def _all(meth): @@ -483,7 +484,7 @@ class Undefined(object): _fail_with_undefined_error def __str__(self): - return unicode(self).encode('utf-8') + return six.text_type(self).encode('utf-8') # unicode goes after __str__ because we configured 2to3 to rename # __unicode__ to __str__. because the 2to3 tree is not designed to diff --git a/jinja2/sandbox.py b/jinja2/sandbox.py index a1cbb29a..b9b17162 100644 --- a/jinja2/sandbox.py +++ b/jinja2/sandbox.py @@ -90,7 +90,7 @@ def safe_range(*args): """A range that can't generate ranges with a length of more than MAX_RANGE items. """ - rng = xrange(*args) + rng = range(*args) if len(rng) > MAX_RANGE: raise OverflowError('range too big, maximum size for range is %d' % MAX_RANGE) diff --git a/jinja2/tests.py b/jinja2/tests.py index 50510b0d..74017e51 100644 --- a/jinja2/tests.py +++ b/jinja2/tests.py @@ -10,6 +10,7 @@ """ import re from jinja2.runtime import Undefined +import six try: from collections import Mapping as MappingType @@ -76,12 +77,12 @@ def test_none(value): def test_lower(value): """Return true if the variable is lowercased.""" - return unicode(value).islower() + return six.text_type(value).islower() def test_upper(value): """Return true if the variable is uppercased.""" - return unicode(value).isupper() + return six.text_type(value).isupper() def test_string(value): diff --git a/jinja2/testsuite/__init__.py b/jinja2/testsuite/__init__.py index 1f10ef68..e39e8777 100644 --- a/jinja2/testsuite/__init__.py +++ b/jinja2/testsuite/__init__.py @@ -59,7 +59,7 @@ class JinjaTestCase(unittest.TestCase): def assert_traceback_matches(self, callback, expected_tb): try: callback() - except Exception, e: + except Exception as e: tb = format_exception(*sys.exc_info()) if re.search(expected_tb.strip(), ''.join(tb)) is None: raise self.fail('Traceback did not match:\n\n%s\nexpected:\n%s' diff --git a/jinja2/testsuite/api.py b/jinja2/testsuite/api.py index c8f96347..53854372 100644 --- a/jinja2/testsuite/api.py +++ b/jinja2/testsuite/api.py @@ -16,6 +16,7 @@ from jinja2 import Environment, Undefined, DebugUndefined, \ StrictUndefined, UndefinedError, meta, \ is_undefined, Template, DictLoader from jinja2.utils import Cycler +import six env = Environment() @@ -50,8 +51,8 @@ class ExtendedAPITestCase(JinjaTestCase): c = Cycler(*items) for item in items + items: assert c.current == item - assert c.next() == item - c.next() + assert six.advance_iterator(c) == item + six.advance_iterator(c) assert c.current == 2 c.reset() assert c.current == 1 @@ -107,8 +108,8 @@ class MetaTestCase(JinjaTestCase): def test_find_refererenced_templates(self): ast = env.parse('{% extends "layout.html" %}{% include helper %}') i = meta.find_referenced_templates(ast) - assert i.next() == 'layout.html' - assert i.next() is None + assert six.advance_iterator(i) == 'layout.html' + assert six.advance_iterator(i) is None assert list(i) == [] ast = env.parse('{% extends "layout.html" %}' @@ -141,21 +142,21 @@ class StreamingTestCase(JinjaTestCase): def test_basic_streaming(self): tmpl = env.from_string("
    {% for item in seq %}
  • {{ loop.index " "}} - {{ item }}
  • {%- endfor %}
") - stream = tmpl.stream(seq=range(4)) - self.assert_equal(stream.next(), '
    ') - self.assert_equal(stream.next(), '
  • 1 - 0
  • ') - self.assert_equal(stream.next(), '
  • 2 - 1
  • ') - self.assert_equal(stream.next(), '
  • 3 - 2
  • ') - self.assert_equal(stream.next(), '
  • 4 - 3
  • ') - self.assert_equal(stream.next(), '
') + stream = tmpl.stream(seq=list(range(4))) + self.assert_equal(six.advance_iterator(stream), '
    ') + self.assert_equal(six.advance_iterator(stream), '
  • 1 - 0
  • ') + self.assert_equal(six.advance_iterator(stream), '
  • 2 - 1
  • ') + self.assert_equal(six.advance_iterator(stream), '
  • 3 - 2
  • ') + self.assert_equal(six.advance_iterator(stream), '
  • 4 - 3
  • ') + self.assert_equal(six.advance_iterator(stream), '
') def test_buffered_streaming(self): tmpl = env.from_string("
    {% for item in seq %}
  • {{ loop.index " "}} - {{ item }}
  • {%- endfor %}
") - stream = tmpl.stream(seq=range(4)) + stream = tmpl.stream(seq=list(range(4))) stream.enable_buffering(size=3) - self.assert_equal(stream.next(), u'
  • 1 - 0
  • 2 - 1
  • ') - self.assert_equal(stream.next(), u'
  • 3 - 2
  • 4 - 3
') + self.assert_equal(six.advance_iterator(stream), u'
  • 1 - 0
  • 2 - 1
  • ') + self.assert_equal(six.advance_iterator(stream), u'
  • 3 - 2
  • 4 - 3
') def test_streaming_behavior(self): tmpl = env.from_string("") @@ -222,7 +223,7 @@ class UndefinedTestCase(JinjaTestCase): def test_none_gives_proper_error(self): try: Environment().getattr(None, 'split')() - except UndefinedError, e: + except UndefinedError as e: assert e.message == "'None' has no attribute 'split'" else: assert False, 'expected exception' @@ -230,7 +231,7 @@ class UndefinedTestCase(JinjaTestCase): def test_object_repr(self): try: Undefined(obj=42, name='upper')() - except UndefinedError, e: + except UndefinedError as e: assert e.message == "'int object' has no attribute 'upper'" else: assert False, 'expected exception' diff --git a/jinja2/testsuite/core_tags.py b/jinja2/testsuite/core_tags.py index 2b5f5801..409a5791 100644 --- a/jinja2/testsuite/core_tags.py +++ b/jinja2/testsuite/core_tags.py @@ -22,7 +22,7 @@ class ForLoopTestCase(JinjaTestCase): def test_simple(self): tmpl = env.from_string('{% for item in seq %}{{ item }}{% endfor %}') - assert tmpl.render(seq=range(10)) == '0123456789' + assert tmpl.render(seq=list(range(10))) == '0123456789' def test_else(self): tmpl = env.from_string('{% for item in seq %}XXX{% else %}...{% endfor %}') @@ -55,12 +55,12 @@ class ForLoopTestCase(JinjaTestCase): tmpl = env.from_string('''{% for item in seq %}{{ loop.cycle('<1>', '<2>') }}{% endfor %}{% for item in seq %}{{ loop.cycle(*through) }}{% endfor %}''') - output = tmpl.render(seq=range(4), through=('<1>', '<2>')) + output = tmpl.render(seq=list(range(4)), through=('<1>', '<2>')) assert output == '<1><2>' * 4 def test_scope(self): tmpl = env.from_string('{% for item in seq %}{% endfor %}{{ item }}') - output = tmpl.render(seq=range(10)) + output = tmpl.render(seq=list(range(10))) assert not output def test_varlen(self): diff --git a/jinja2/testsuite/ext.py b/jinja2/testsuite/ext.py index 6ca6c228..65251a54 100644 --- a/jinja2/testsuite/ext.py +++ b/jinja2/testsuite/ext.py @@ -18,6 +18,7 @@ from jinja2.exceptions import TemplateAssertionError from jinja2.ext import Extension from jinja2.lexer import Token, count_newlines from jinja2.utils import next +import six # 2.x / 3.x try: @@ -222,7 +223,7 @@ class ExtensionsTestCase(JinjaTestCase): original = Environment(extensions=[TestExtension]) overlay = original.overlay() for env in original, overlay: - for ext in env.extensions.itervalues(): + for ext in six.itervalues(env.extensions): assert ext.environment is env def test_preprocessor_extension(self): diff --git a/jinja2/testsuite/filters.py b/jinja2/testsuite/filters.py index b037e240..cd954636 100644 --- a/jinja2/testsuite/filters.py +++ b/jinja2/testsuite/filters.py @@ -12,6 +12,9 @@ import unittest from jinja2.testsuite import JinjaTestCase from jinja2 import Markup, Environment +import six +from six.moves import map +from six.moves import zip env = Environment() @@ -47,14 +50,14 @@ class FilterTestCase(JinjaTestCase): def test_batch(self): tmpl = env.from_string("{{ foo|batch(3)|list }}|" "{{ foo|batch(3, 'X')|list }}") - out = tmpl.render(foo=range(10)) + out = tmpl.render(foo=list(range(10))) assert out == ("[[0, 1, 2], [3, 4, 5], [6, 7, 8], [9]]|" "[[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 'X', 'X']]") def test_slice(self): tmpl = env.from_string('{{ foo|slice(3)|list }}|' '{{ foo|slice(3, "X")|list }}') - out = tmpl.render(foo=range(10)) + out = tmpl.render(foo=list(range(10))) assert out == ("[[0, 1, 2, 3], [4, 5, 6], [7, 8, 9]]|" "[[0, 1, 2, 3], [4, 5, 6, 'X'], [7, 8, 9, 'X']]") @@ -109,7 +112,7 @@ class FilterTestCase(JinjaTestCase): def test_first(self): tmpl = env.from_string('{{ foo|first }}') - out = tmpl.render(foo=range(10)) + out = tmpl.render(foo=list(range(10))) assert out == '0' def test_float(self): @@ -155,7 +158,7 @@ class FilterTestCase(JinjaTestCase): def test_last(self): tmpl = env.from_string('''{{ foo|last }}''') - out = tmpl.render(foo=range(10)) + out = tmpl.render(foo=list(range(10))) assert out == '9' def test_length(self): @@ -171,12 +174,12 @@ class FilterTestCase(JinjaTestCase): def test_pprint(self): from pprint import pformat tmpl = env.from_string('''{{ data|pprint }}''') - data = range(1000) + data = list(range(1000)) assert tmpl.render(data=data) == pformat(data) def test_random(self): tmpl = env.from_string('''{{ seq|random }}''') - seq = range(100) + seq = list(range(100)) for _ in range(10): assert int(tmpl.render(seq=seq)) in seq @@ -188,7 +191,7 @@ class FilterTestCase(JinjaTestCase): def test_string(self): x = [1, 2, 3, 4, 5] tmpl = env.from_string('''{{ obj|string }}''') - assert tmpl.render(obj=x) == unicode(x) + assert tmpl.render(obj=x) == six.text_type(x) def test_title(self): tmpl = env.from_string('''{{ "foo bar"|title }}''') @@ -297,7 +300,7 @@ class FilterTestCase(JinjaTestCase): def __init__(self, value): self.value = value def __unicode__(self): - return unicode(self.value) + return six.text_type(self.value) tmpl = env.from_string('''{{ items|sort(attribute='value')|join }}''') assert tmpl.render(items=map(Magic, [3, 2, 4, 1])) == '1234' diff --git a/jinja2/testsuite/imports.py b/jinja2/testsuite/imports.py index 1cb12cbd..3db9008d 100644 --- a/jinja2/testsuite/imports.py +++ b/jinja2/testsuite/imports.py @@ -83,7 +83,7 @@ class IncludesTestCase(JinjaTestCase): self.assert_raises(TemplateNotFound, t.render) try: t.render() - except TemplatesNotFound, e: + except TemplatesNotFound as e: assert e.templates == ['missing', 'missing2'] assert e.name == 'missing2' else: diff --git a/jinja2/testsuite/inheritance.py b/jinja2/testsuite/inheritance.py index 355aa0c9..7909b031 100644 --- a/jinja2/testsuite/inheritance.py +++ b/jinja2/testsuite/inheritance.py @@ -148,7 +148,7 @@ class InheritanceTestCase(JinjaTestCase): })) t = env.from_string('{% extends "master.html" %}{% block item %}' '{{ item }}{% endblock %}') - assert t.render(seq=range(5)) == '[0][1][2][3][4]' + assert t.render(seq=list(range(5))) == '[0][1][2][3][4]' def test_super_in_scoped_block(self): env = Environment(loader=DictLoader({ @@ -157,7 +157,7 @@ class InheritanceTestCase(JinjaTestCase): })) t = env.from_string('{% extends "master.html" %}{% block item %}' '{{ super() }}|{{ item * 2 }}{% endblock %}') - assert t.render(seq=range(5)) == '[0|0][1|2][2|4][3|6][4|8]' + assert t.render(seq=list(range(5))) == '[0|0][1|2][2|4][3|6][4|8]' def test_scoped_block_after_inheritance(self): env = Environment(loader=DictLoader({ diff --git a/jinja2/testsuite/lexnparse.py b/jinja2/testsuite/lexnparse.py index 77b76ec1..e162463e 100644 --- a/jinja2/testsuite/lexnparse.py +++ b/jinja2/testsuite/lexnparse.py @@ -15,6 +15,7 @@ from jinja2.testsuite import JinjaTestCase from jinja2 import Environment, Template, TemplateSyntaxError, \ UndefinedError, nodes +import six env = Environment() @@ -42,7 +43,7 @@ class LexerTestCase(JinjaTestCase): env = Environment('{%', '%}', '${', '}') tmpl = env.from_string('''{% for item in seq %}${{'foo': item}|upper}{% endfor %}''') - assert tmpl.render(seq=range(3)) == "{'FOO': 0}{'FOO': 1}{'FOO': 2}" + assert tmpl.render(seq=list(range(3))) == "{'FOO': 0}{'FOO': 1}{'FOO': 2}" def test_comments(self): env = Environment('', '{', '}') @@ -52,7 +53,7 @@ class LexerTestCase(JinjaTestCase):
  • {item}
  • ''') - assert tmpl.render(seq=range(3)) == ("
      \n
    • 0
    • \n " + assert tmpl.render(seq=list(range(3))) == ("
        \n
      • 0
      • \n " "
      • 1
      • \n
      • 2
      • \n
      ") def test_string_escapes(self): @@ -68,11 +69,11 @@ class LexerTestCase(JinjaTestCase): def test_operators(self): from jinja2.lexer import operators - for test, expect in operators.iteritems(): + for test, expect in six.iteritems(operators): if test in '([{}])': continue stream = env.lexer.tokenize('{{ %s }}' % test) - stream.next() + six.advance_iterator(stream) assert stream.current.type == expect def test_normalizing(self): @@ -92,7 +93,7 @@ class ParserTestCase(JinjaTestCase): ''') - assert tmpl.render(seq=range(5)) == '01234' + assert tmpl.render(seq=list(range(5))) == '01234' def test_erb_syntax(self): env = Environment('<%', '%>', '<%=', '%>', '<%#', '%>') @@ -101,7 +102,7 @@ class ParserTestCase(JinjaTestCase): <% for item in seq -%> <%= item %> <%- endfor %>''') - assert tmpl.render(seq=range(5)) == '01234' + assert tmpl.render(seq=list(range(5))) == '01234' def test_comment_syntax(self): env = Environment('', '${', '}', '') @@ -110,7 +111,7 @@ class ParserTestCase(JinjaTestCase): ${item} ''') - assert tmpl.render(seq=range(5)) == '01234' + assert tmpl.render(seq=list(range(5))) == '01234' def test_balancing(self): tmpl = env.from_string('''{{{'foo':'bar'}.foo}}''') @@ -130,8 +131,8 @@ and bar comment #} % for item in seq: ${item} % endfor''') - assert [int(x.strip()) for x in tmpl.render(seq=range(5)).split()] == \ - range(5) + assert [int(x.strip()) for x in tmpl.render(seq=list(range(5))).split()] == \ + list(range(5)) env = Environment('<%', '%>', '${', '}', '<%#', '%>', '%', '##') tmpl = env.from_string('''\ @@ -139,8 +140,8 @@ and bar comment #} % for item in seq: ${item} ## the rest of the stuff % endfor''') - assert [int(x.strip()) for x in tmpl.render(seq=range(5)).split()] == \ - range(5) + assert [int(x.strip()) for x in tmpl.render(seq=list(range(5))).split()] == \ + list(range(5)) def test_line_syntax_priority(self): # XXX: why is the whitespace there in front of the newline? @@ -166,7 +167,7 @@ and bar comment #} def assert_error(code, expected): try: Template(code) - except TemplateSyntaxError, e: + except TemplateSyntaxError as e: assert str(e) == expected, 'unexpected error message' else: assert False, 'that was supposed to be an error' @@ -335,9 +336,9 @@ class SyntaxTestCase(JinjaTestCase): assert tmpl.render() == 'foobarbaz' def test_notin(self): - bar = xrange(100) + bar = range(100) tmpl = env.from_string('''{{ not 42 in bar }}''') - assert tmpl.render(bar=bar) == unicode(not 42 in bar) + assert tmpl.render(bar=bar) == six.text_type(not 42 in bar) def test_implicit_subscribed_tuple(self): class Foo(object): diff --git a/jinja2/testsuite/regression.py b/jinja2/testsuite/regression.py index 4db90769..5c3633f5 100644 --- a/jinja2/testsuite/regression.py +++ b/jinja2/testsuite/regression.py @@ -14,6 +14,8 @@ from jinja2.testsuite import JinjaTestCase from jinja2 import Template, Environment, DictLoader, TemplateSyntaxError, \ TemplateNotFound, PrefixLoader +from six.moves import map +from six.moves import zip env = Environment() @@ -118,7 +120,7 @@ class BugTestCase(JinjaTestCase): ''') - assert tmpl.render().split() == map(unicode, range(1, 11)) * 5 + assert tmpl.render().split() == map(unicode, list(range(1, 11))) * 5 def test_weird_inline_comment(self): env = Environment(line_statement_prefix='%') @@ -242,7 +244,7 @@ class BugTestCase(JinjaTestCase): })) try: env.get_template('foo/bar.html') - except TemplateNotFound, e: + except TemplateNotFound as e: assert e.name == 'foo/bar.html' else: assert False, 'expected error here' diff --git a/jinja2/testsuite/security.py b/jinja2/testsuite/security.py index 4518eac6..c892fed2 100644 --- a/jinja2/testsuite/security.py +++ b/jinja2/testsuite/security.py @@ -18,6 +18,7 @@ from jinja2.sandbox import SandboxedEnvironment, \ from jinja2 import Markup, escape from jinja2.exceptions import SecurityError, TemplateSyntaxError, \ TemplateRuntimeError +import six class PrivateStuff(object): @@ -76,7 +77,7 @@ class SandboxTestCase(JinjaTestCase): # adding two strings should escape the unsafe one unsafe = '' safe = Markup('username') - assert unsafe + safe == unicode(escape(unsafe)) + unicode(safe) + assert unsafe + safe == six.text_type(escape(unsafe)) + six.text_type(safe) # string interpolations are safe to use too assert Markup('%s') % '' == \ @@ -114,7 +115,7 @@ class SandboxTestCase(JinjaTestCase): '{{ say_hello("foo") }}') escaped_out = '

      Hello <blink>foo</blink>!

      ' assert t.render() == escaped_out - assert unicode(t.module) == escaped_out + assert six.text_type(t.module) == escaped_out assert escape(t.module) == escaped_out assert t.module.say_hello('foo') == escaped_out assert escape(t.module.say_hello('foo')) == escaped_out @@ -136,7 +137,7 @@ class SandboxTestCase(JinjaTestCase): t = env.from_string('{{ %s }}' % expr) try: t.render(ctx) - except TemplateRuntimeError, e: + except TemplateRuntimeError as e: pass else: self.fail('expected runtime error') @@ -153,7 +154,7 @@ class SandboxTestCase(JinjaTestCase): t = env.from_string('{{ %s }}' % expr) try: t.render(ctx) - except TemplateRuntimeError, e: + except TemplateRuntimeError as e: pass else: self.fail('expected runtime error') diff --git a/jinja2/testsuite/utils.py b/jinja2/testsuite/utils.py index be2e902f..cab9b09a 100644 --- a/jinja2/testsuite/utils.py +++ b/jinja2/testsuite/utils.py @@ -60,8 +60,8 @@ class MarkupLeakTestCase(JinjaTestCase): def test_markup_leaks(self): counts = set() - for count in xrange(20): - for item in xrange(1000): + for count in range(20): + for item in range(1000): escape("foo") escape("") escape(u"foo") diff --git a/jinja2/utils.py b/jinja2/utils.py index 401b5793..121a008b 100644 --- a/jinja2/utils.py +++ b/jinja2/utils.py @@ -11,6 +11,7 @@ import re import sys import errno +import six try: from urllib.parse import quote_from_bytes as url_quote except ImportError: @@ -52,7 +53,7 @@ try: raise TypeError(_test_gen_bug) yield None _concat(_test_gen_bug()) -except TypeError, _error: +except TypeError as _error: if not _error.args or _error.args[0] is not _test_gen_bug: def concat(gen): try: @@ -73,7 +74,7 @@ try: next = next except NameError: def next(x): - return x.next() + return six.advance_iterator(x) # if this python version is unable to deal with unicode filenames @@ -105,7 +106,7 @@ def _func(): FunctionType = type(_func) GeneratorType = type(_func()) MethodType = type(_C.method) -CodeType = type(_C.method.func_code) +CodeType = type(_C.method.__code__) try: raise TypeError() except TypeError: @@ -156,7 +157,7 @@ def environmentfunction(f): def internalcode(f): """Marks the function as internally used""" - internal_code.add(f.func_code) + internal_code.add(f.__code__) return f @@ -226,7 +227,7 @@ def open_if_exists(filename, mode='rb'): """ try: return open(filename, mode) - except IOError, e: + except IOError as e: if e.errno not in (errno.ENOENT, errno.EISDIR): raise @@ -275,7 +276,7 @@ def urlize(text, trim_url_limit=None, nofollow=False): trim_url = lambda x, limit=trim_url_limit: limit is not None \ and (x[:limit] + (len(x) >=limit and '...' or '')) or x - words = _word_split_re.split(unicode(escape(text))) + words = _word_split_re.split(six.text_type(escape(text))) nofollow_attr = nofollow and ' rel="nofollow"' or '' for i, word in enumerate(words): match = _punctuation_re.match(word) @@ -312,7 +313,7 @@ def generate_lorem_ipsum(n=5, html=True, min=20, max=100): words = LOREM_IPSUM_WORDS.split() result = [] - for _ in xrange(n): + for _ in range(n): next_capitalized = True last_comma = last_fullstop = 0 word = None @@ -320,7 +321,7 @@ def generate_lorem_ipsum(n=5, html=True, min=20, max=100): p = [] # each paragraph contains out of 20 to 100 words. - for idx, _ in enumerate(xrange(randrange(min, max))): + for idx, _ in enumerate(range(randrange(min, max))): while True: word = choice(words) if word != last: @@ -363,10 +364,10 @@ def unicode_urlencode(obj, charset='utf-8'): representation first. """ if not isinstance(obj, basestring): - obj = unicode(obj) + obj = six.text_type(obj) if isinstance(obj, unicode): obj = obj.encode(charset) - return unicode(url_quote(obj)) + return six.text_type(url_quote(obj)) class LRUCache(object):