summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArmin Ronacher <armin.ronacher@active-4.com>2013-05-19 14:16:13 +0100
committerArmin Ronacher <armin.ronacher@active-4.com>2013-05-19 14:16:13 +0100
commite909867721a000beaec6340d17ecc39eac6fad4e (patch)
treec1d9e48fa658c6b0f006b1635d0644b62d83d0b2
parentcd7bf5b00f77adc0f875efb9d945b9b42271f53a (diff)
downloadjinja2-e909867721a000beaec6340d17ecc39eac6fad4e.tar.gz
Moved all six usages (ignoring testsuite) into jinja2._compat
-rw-r--r--jinja2/_compat.py52
-rw-r--r--jinja2/bccache.py8
-rw-r--r--jinja2/compiler.py30
-rw-r--r--jinja2/debug.py18
-rw-r--r--jinja2/environment.py38
-rw-r--r--jinja2/exceptions.py18
-rw-r--r--jinja2/ext.py11
-rw-r--r--jinja2/filters.py40
-rw-r--r--jinja2/lexer.py15
-rw-r--r--jinja2/loaders.py15
-rw-r--r--jinja2/meta.py9
-rw-r--r--jinja2/nodes.py15
-rw-r--r--jinja2/runtime.py43
-rw-r--r--jinja2/sandbox.py15
-rw-r--r--jinja2/tests.py19
-rw-r--r--jinja2/utils.py36
16 files changed, 199 insertions, 183 deletions
diff --git a/jinja2/_compat.py b/jinja2/_compat.py
index 8c1963c..f10ef65 100644
--- a/jinja2/_compat.py
+++ b/jinja2/_compat.py
@@ -12,6 +12,9 @@
:license: BSD, see LICENSE for details.
"""
import six
+import sys
+
+PY3 = six.PY3
# https://bitbucket.org/gutworth/six/issue/25/add-unichr
try:
@@ -22,3 +25,52 @@ except NameError:
range_type = six.moves.xrange
next = six.advance_iterator
imap = six.moves.map
+izip = six.moves.zip
+text_type = six.text_type
+string_types = six.string_types
+
+iteritems = six.iteritems
+
+if six.PY3:
+ from io import BytesIO, StringIO
+ NativeStringIO = StringIO
+else:
+ from cStringIO import StringIO as BytesIO
+ from StringIO import StringIO
+ NativeStringIO = BytesIO
+
+try:
+ import cPickle as pickle
+except ImportError:
+ import pickle
+
+ifilter = six.moves.filter
+reraise = six.reraise
+Iterator = six.Iterator
+with_metaclass = six.with_metaclass
+
+try:
+ from collections import Mapping as mapping_types
+except ImportError:
+ import UserDict
+ mapping_types = (UserDict.UserDict, UserDict.DictMixin, dict)
+
+
+# common types. These do exist in the special types module too which however
+# does not exist in IronPython out of the box. Also that way we don't have
+# to deal with implementation specific stuff here
+class _C(object):
+ def method(self): pass
+def _func():
+ yield None
+function_type = type(_func)
+generator_type = type(_func())
+method_type = type(_C().method)
+code_type = type(_C.method.__code__)
+try:
+ raise TypeError()
+except TypeError:
+ _tb = sys.exc_info()[2]
+ traceback_type = type(_tb)
+ frame_type = type(_tb.tb_frame)
+del _C, _tb, _func
diff --git a/jinja2/bccache.py b/jinja2/bccache.py
index f022918..dbfc3c2 100644
--- a/jinja2/bccache.py
+++ b/jinja2/bccache.py
@@ -18,14 +18,10 @@ from os import path, listdir
import sys
import marshal
import tempfile
-from six.moves import cPickle as pickle
-from six import BytesIO
import fnmatch
-try:
- from hashlib import sha1
-except ImportError:
- from sha import new as sha1
+from hashlib import sha1
from jinja2.utils import open_if_exists
+from jinja2._compat import BytesIO, pickle
# marshal works better on 3.x, one hack less required
diff --git a/jinja2/compiler.py b/jinja2/compiler.py
index ce8e06d..4c7a52d 100644
--- a/jinja2/compiler.py
+++ b/jinja2/compiler.py
@@ -8,8 +8,6 @@
:copyright: (c) 2010 by the Jinja Team.
:license: BSD, see LICENSE for more details.
"""
-import six
-
from itertools import chain
from copy import deepcopy
from jinja2 import nodes
@@ -17,8 +15,8 @@ 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
-from jinja2._compat import range_type, next
-from six.moves import cStringIO as StringIO, map
+from jinja2._compat import range_type, next, text_type, string_types, \
+ iteritems, NativeStringIO, imap
operators = {
@@ -69,7 +67,7 @@ def has_safe_repr(value):
if value is None or value is NotImplemented or value is Ellipsis:
return True
if isinstance(value, (bool, int, float, complex, range_type,
- Markup) + six.string_types):
+ Markup) + string_types):
return True
if isinstance(value, (tuple, list, set, frozenset)):
for item in value:
@@ -77,7 +75,7 @@ def has_safe_repr(value):
return False
return True
elif isinstance(value, dict):
- for key, value in six.iteritems(value):
+ for key, value in iteritems(value):
if not has_safe_repr(key):
return False
if not has_safe_repr(value):
@@ -367,7 +365,7 @@ class CodeGenerator(NodeVisitor):
def __init__(self, environment, name, filename, stream=None,
defer_init=False):
if stream is None:
- stream = StringIO()
+ stream = NativeStringIO()
self.environment = environment
self.name = name
self.filename = filename
@@ -541,7 +539,7 @@ class CodeGenerator(NodeVisitor):
self.write(', ')
self.visit(kwarg, frame)
if extra_kwargs is not None:
- for key, value in six.iteritems(extra_kwargs):
+ for key, value in iteritems(extra_kwargs):
self.write(', %s=%s' % (key, value))
if node.dyn_args:
self.write(', *')
@@ -557,7 +555,7 @@ class CodeGenerator(NodeVisitor):
self.visit(kwarg.value, frame)
self.write(', ')
if extra_kwargs is not None:
- for key, value in six.iteritems(extra_kwargs):
+ for key, value in iteritems(extra_kwargs):
self.write('%r: %s, ' % (key, value))
if node.dyn_kwargs is not None:
self.write('}, **')
@@ -624,7 +622,7 @@ class CodeGenerator(NodeVisitor):
def pop_scope(self, aliases, frame):
"""Restore all aliases and delete unused variables."""
- for name, alias in six.iteritems(aliases):
+ for name, alias in iteritems(aliases):
self.writeline('l_%s = %s' % (name, alias))
to_delete = set()
for name in frame.identifiers.declared_locally:
@@ -826,7 +824,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 six.iteritems(self.blocks):
+ for name, block in iteritems(self.blocks):
block_frame = Frame(eval_ctx)
block_frame.inspect(block.body)
block_frame.block = name
@@ -930,7 +928,7 @@ class CodeGenerator(NodeVisitor):
func_name = 'get_or_select_template'
if isinstance(node.template, nodes.Const):
- if isinstance(node.template.value, six.string_types):
+ if isinstance(node.template.value, string_types):
func_name = 'get_template'
elif isinstance(node.template.value, (tuple, list)):
func_name = 'select_template'
@@ -1039,7 +1037,7 @@ class CodeGenerator(NodeVisitor):
discarded_names[0])
else:
self.writeline('context.exported_vars.difference_'
- 'update((%s))' % ', '.join(map(repr, discarded_names)))
+ 'update((%s))' % ', '.join(imap(repr, discarded_names)))
def visit_For(self, node, frame):
# when calculating the nodes for the inner frame we have to exclude
@@ -1224,9 +1222,9 @@ class CodeGenerator(NodeVisitor):
return
if self.environment.finalize:
- finalize = lambda x: six.text_type(self.environment.finalize(x))
+ finalize = lambda x: text_type(self.environment.finalize(x))
else:
- finalize = six.text_type
+ finalize = text_type
# if we are inside a frame that requires output checking, we do so
outdent_later = False
@@ -1375,7 +1373,7 @@ class CodeGenerator(NodeVisitor):
public_names[0])
else:
self.writeline('context.exported_vars.update((%s))' %
- ', '.join(map(repr, public_names)))
+ ', '.join(imap(repr, public_names)))
# -- Expression Visitors
diff --git a/jinja2/debug.py b/jinja2/debug.py
index 31c25cc..815cc18 100644
--- a/jinja2/debug.py
+++ b/jinja2/debug.py
@@ -13,9 +13,9 @@
import sys
import traceback
from types import TracebackType
-from jinja2.utils import CodeType, missing, internal_code
+from jinja2.utils import missing, internal_code
from jinja2.exceptions import TemplateSyntaxError
-import six
+from jinja2._compat import iteritems, reraise, code_type
# on pypy we can take advantage of transparent proxies
try:
@@ -190,7 +190,7 @@ def translate_exception(exc_info, initial_skip=0):
# reraise it unchanged.
# XXX: can we backup here? when could this happen?
if not frames:
- six.reraise(exc_info[0], exc_info[1], exc_info[2])
+ reraise(exc_info[0], exc_info[1], exc_info[2])
return ProcessedTraceback(exc_info[0], exc_info[1], frames)
@@ -207,7 +207,7 @@ def fake_exc_info(exc_info, filename, lineno):
locals = ctx.get_all()
else:
locals = {}
- for name, value in six.iteritems(real_locals):
+ for name, value in iteritems(real_locals):
if name.startswith('l_') and value is not missing:
locals[name[2:]] = value
@@ -245,11 +245,11 @@ def fake_exc_info(exc_info, filename, lineno):
location = 'block "%s"' % function[6:]
else:
location = 'template'
- code = CodeType(0, code.co_nlocals, code.co_stacksize,
- code.co_flags, code.co_code, code.co_consts,
- code.co_names, code.co_varnames, filename,
- location, code.co_firstlineno,
- code.co_lnotab, (), ())
+ code = code_type(0, code.co_nlocals, code.co_stacksize,
+ code.co_flags, code.co_code, code.co_consts,
+ code.co_names, code.co_varnames, filename,
+ location, code.co_firstlineno,
+ code.co_lnotab, (), ())
except:
pass
diff --git a/jinja2/environment.py b/jinja2/environment.py
index 450cac1..ee35b89 100644
--- a/jinja2/environment.py
+++ b/jinja2/environment.py
@@ -27,9 +27,9 @@ from jinja2.exceptions import TemplateSyntaxError, TemplateNotFound, \
TemplatesNotFound, TemplateRuntimeError
from jinja2.utils import import_string, LRUCache, Markup, missing, \
concat, consume, internalcode, _encode_filename
-import six
+from jinja2._compat import imap, ifilter, string_types, iteritems, \
+ text_type, reraise, PY3, Iterator, next
from functools import reduce
-from six.moves import filter, map
# for direct template usage we have up to ten living environments
@@ -80,7 +80,7 @@ def load_extensions(environment, extensions):
"""
result = {}
for extension in extensions:
- if isinstance(extension, six.string_types):
+ if isinstance(extension, string_types):
extension = import_string(extension)
result[extension.identifier] = extension(environment)
return result
@@ -315,7 +315,7 @@ class Environment(object):
yet. This is used by :ref:`extensions <writing-extensions>` to register
callbacks and configuration values without breaking inheritance.
"""
- for key, value in six.iteritems(attributes):
+ for key, value in iteritems(attributes):
if not hasattr(self, key):
setattr(self, key, value)
@@ -347,7 +347,7 @@ class Environment(object):
rv.overlayed = True
rv.linked_to = self
- for key, value in six.iteritems(args):
+ for key, value in iteritems(args):
if value is not missing:
setattr(rv, key, value)
@@ -357,7 +357,7 @@ class Environment(object):
rv.cache = copy_cache(self.cache)
rv.extensions = {}
- for key, value in six.iteritems(self.extensions):
+ for key, value in iteritems(self.extensions):
rv.extensions[key] = value.bind(rv)
if extensions is not missing:
rv.extensions.update(load_extensions(rv, extensions))
@@ -376,7 +376,7 @@ class Environment(object):
try:
return obj[argument]
except (TypeError, LookupError):
- if isinstance(argument, six.string_types):
+ if isinstance(argument, string_types):
try:
attr = str(argument)
except Exception:
@@ -467,7 +467,7 @@ class Environment(object):
of the extensions to be applied you have to filter source through
the :meth:`preprocess` method.
"""
- source = six.text_type(source)
+ source = text_type(source)
try:
return self.lexer.tokeniter(source, name, filename)
except TemplateSyntaxError:
@@ -480,7 +480,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(), six.text_type(source))
+ self.iter_extensions(), text_type(source))
def _tokenize(self, source, name, filename=None, state=None):
"""Called by the parser to do the preprocessing and filtering
@@ -534,7 +534,7 @@ class Environment(object):
"""
source_hint = None
try:
- if isinstance(source, six.string_types):
+ if isinstance(source, string_types):
source_hint = source
source = self._parse(source, name, filename)
if self.optimized:
@@ -708,7 +708,7 @@ class Environment(object):
filter_func = lambda x: '.' in x and \
x.rsplit('.', 1)[1] in extensions
if filter_func is not None:
- x = filter(filter_func, x)
+ x = ifilter(filter_func, x)
return x
def handle_exception(self, exc_info=None, rendered=False, source_hint=None):
@@ -731,7 +731,7 @@ class Environment(object):
if self.exception_handler is not None:
self.exception_handler(traceback)
exc_type, exc_value, tb = traceback.standard_exc_info
- six.reraise(exc_type, exc_value, tb)
+ reraise(exc_type, exc_value, tb)
def join_path(self, template, parent):
"""Join a template with the parent. By default all the lookups are
@@ -818,7 +818,7 @@ class Environment(object):
.. versionadded:: 2.3
"""
- if isinstance(template_name_or_list, six.string_types):
+ if isinstance(template_name_or_list, string_types):
return self.get_template(template_name_or_list, parent, globals)
elif isinstance(template_name_or_list, Template):
return template_name_or_list
@@ -1040,7 +1040,7 @@ class Template(object):
@property
def debug_info(self):
"""The debug info mapping."""
- return [tuple(map(int, x.split('='))) for x in
+ return [tuple(imap(int, x.split('='))) for x in
self._debug_info.split('&')]
def __repr__(self):
@@ -1067,7 +1067,7 @@ class TemplateModule(object):
def __str__(self):
s = self.__unicode__()
- return s if six.PY3 else s.encode('utf-8')
+ return s if PY3 else s.encode('utf-8')
def __unicode__(self):
return concat(self._body_stream)
@@ -1099,7 +1099,7 @@ class TemplateExpression(object):
return rv
-class TemplateStream(six.Iterator):
+class TemplateStream(Iterator):
"""A template stream works pretty much like an ordinary python generator
but it can buffer multiple items to reduce the number of total iterations.
Per default the output is unbuffered which means that for every unbuffered
@@ -1124,7 +1124,7 @@ class TemplateStream(six.Iterator):
Template('Hello {{ name }}!').stream(name='foo').dump('hello.html')
"""
close = False
- if isinstance(fp, six.string_types):
+ if isinstance(fp, string_types):
fp = open(fp, encoding is None and 'w' or 'wb')
close = True
try:
@@ -1143,7 +1143,7 @@ class TemplateStream(six.Iterator):
def disable_buffering(self):
"""Disable the output buffering."""
- self._next = lambda: six.next(self._gen)
+ self._next = lambda: next(self._gen)
self.buffered = False
def enable_buffering(self, size=5):
@@ -1171,7 +1171,7 @@ class TemplateStream(six.Iterator):
c_size = 0
self.buffered = True
- self._next = lambda: six.next(generator(lambda: six.next(self._gen)))
+ self._next = lambda: next(generator(lambda: next(self._gen)))
def __iter__(self):
return self
diff --git a/jinja2/exceptions.py b/jinja2/exceptions.py
index 9fe698b..0075be0 100644
--- a/jinja2/exceptions.py
+++ b/jinja2/exceptions.py
@@ -9,8 +9,7 @@
:license: BSD, see LICENSE for more details.
"""
import sys
-import six
-from six.moves import map
+from jinja2._compat import imap, text_type, PY3
class TemplateError(Exception):
@@ -19,7 +18,7 @@ class TemplateError(Exception):
if sys.version_info[0] < 3:
def __init__(self, message=None):
if message is not None:
- message = six.text_type(message).encode('utf-8')
+ message = text_type(message).encode('utf-8')
Exception.__init__(self, message)
@property
@@ -75,7 +74,7 @@ class TemplatesNotFound(TemplateNotFound):
def __init__(self, names=(), message=None):
if message is None:
message = u'none of the templates given were found: ' + \
- u', '.join(map(six.text_type, names))
+ u', '.join(imap(text_type, names))
TemplateNotFound.__init__(self, names and names[-1] or None, message)
self.templates = list(names)
@@ -94,10 +93,6 @@ class TemplateSyntaxError(TemplateError):
# function translated the syntax error into a new traceback
self.translated = False
- def __str__(self):
- s = self.__unicode__()
- return s if six.PY3 else s.encode('utf-8')
-
def __unicode__(self):
# for translated errors we only return the message
if self.translated:
@@ -121,6 +116,13 @@ class TemplateSyntaxError(TemplateError):
return u'\n'.join(lines)
+ if PY3:
+ __str__ = __unicode__
+ del __unicode__
+ else:
+ def __str__(self):
+ return self.__unicode__().encode('utf-8')
+
class TemplateAssertionError(TemplateSyntaxError):
"""Like a template syntax error, but covers cases where something in the
diff --git a/jinja2/ext.py b/jinja2/ext.py
index 8ded3d1..a88c088 100644
--- a/jinja2/ext.py
+++ b/jinja2/ext.py
@@ -20,8 +20,7 @@ from jinja2.environment import Environment
from jinja2.runtime import concat
from jinja2.exceptions import TemplateAssertionError, TemplateSyntaxError
from jinja2.utils import contextfunction, import_string, Markup
-from jinja2._compat import next
-import six
+from jinja2._compat import next, with_metaclass, string_types, iteritems
# the only real useful gettext functions for a Jinja template. Note
@@ -39,7 +38,7 @@ class ExtensionRegistry(type):
return rv
-class Extension(six.with_metaclass(ExtensionRegistry, object)):
+class Extension(with_metaclass(ExtensionRegistry, object)):
"""Extensions can be used to add extra functionality to the Jinja template
system at the parser level. Custom extensions are bound to an environment
but may not store environment specific data on `self`. The reason for
@@ -210,7 +209,7 @@ class InternationalizationExtension(Extension):
self.environment.globals.pop(key, None)
def _extract(self, source, gettext_functions=GETTEXT_FUNCTIONS):
- if isinstance(source, six.string_types):
+ if isinstance(source, string_types):
source = self.environment.parse(source)
return extract_from_ast(source, gettext_functions)
@@ -369,7 +368,7 @@ class InternationalizationExtension(Extension):
# enough to handle the variable expansion and autoescape
# handling itself
if self.environment.newstyle_gettext:
- for key, value in six.iteritems(variables):
+ for key, value in 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':
@@ -491,7 +490,7 @@ def extract_from_ast(node, gettext_functions=GETTEXT_FUNCTIONS,
strings = []
for arg in node.args:
if isinstance(arg, nodes.Const) and \
- isinstance(arg.value, six.string_types):
+ isinstance(arg.value, string_types):
strings.append(arg.value)
else:
strings.append(None)
diff --git a/jinja2/filters.py b/jinja2/filters.py
index f0fbb38..2f6ffd0 100644
--- a/jinja2/filters.py
+++ b/jinja2/filters.py
@@ -10,7 +10,6 @@
"""
import re
import math
-import six
from random import choice
from operator import itemgetter
@@ -19,8 +18,7 @@ from jinja2.utils import Markup, escape, pformat, urlize, soft_unicode, \
unicode_urlencode
from jinja2.runtime import Undefined
from jinja2.exceptions import FilterArgumentError
-from jinja2._compat import next
-from six.moves import map
+from jinja2._compat import next, imap, string_types, text_type, iteritems
_word_re = re.compile(r'\w+(?u)')
@@ -58,7 +56,7 @@ def make_attrgetter(environment, attribute):
passed object with the rules of the environment. Dots are allowed
to access attributes of attributes.
"""
- if not isinstance(attribute, six.string_types) or '.' not in attribute:
+ if not isinstance(attribute, string_types) or '.' not in attribute:
return lambda x: environment.getitem(x, attribute)
attribute = attribute.split('.')
def attrgetter(item):
@@ -72,7 +70,7 @@ def do_forceescape(value):
"""Enforce HTML escaping. This will probably double escape variables."""
if hasattr(value, '__html__'):
value = value.__html__()
- return escape(six.text_type(value))
+ return escape(text_type(value))
def do_urlencode(value):
@@ -83,8 +81,8 @@ def do_urlencode(value):
"""
itemiter = None
if isinstance(value, dict):
- itemiter = six.iteritems(value)
- elif not isinstance(value, six.string_types):
+ itemiter = iteritems(value)
+ elif not isinstance(value, string_types):
try:
itemiter = iter(value)
except TypeError:
@@ -114,7 +112,7 @@ def do_replace(eval_ctx, s, old, new, count=None):
if count is None:
count = -1
if not eval_ctx.autoescape:
- return six.text_type(s).replace(six.text_type(old), six.text_type(new), count)
+ return text_type(s).replace(text_type(old), text_type(new), count)
if hasattr(old, '__html__') or hasattr(new, '__html__') and \
not hasattr(s, '__html__'):
s = escape(s)
@@ -159,7 +157,7 @@ def do_xmlattr(_eval_ctx, d, autospace=True):
"""
rv = u' '.join(
u'%s="%s"' % (escape(key), escape(value))
- for key, value in six.iteritems(d)
+ for key, value in iteritems(d)
if value is not None and not isinstance(value, Undefined)
)
if autospace and rv:
@@ -214,7 +212,7 @@ def do_dictsort(value, case_sensitive=False, by='key'):
'"key" or "value"')
def sort_func(item):
value = item[pos]
- if isinstance(value, six.string_types) and not case_sensitive:
+ if isinstance(value, string_types) and not case_sensitive:
value = value.lower()
return value
@@ -251,7 +249,7 @@ def do_sort(environment, value, reverse=False, case_sensitive=False,
"""
if not case_sensitive:
def sort_func(item):
- if isinstance(item, six.string_types):
+ if isinstance(item, string_types):
item = item.lower()
return item
else:
@@ -309,11 +307,11 @@ def do_join(eval_ctx, value, d=u'', attribute=None):
The `attribute` parameter was added.
"""
if attribute is not None:
- value = map(make_attrgetter(eval_ctx.environment, attribute), value)
+ value = imap(make_attrgetter(eval_ctx.environment, attribute), value)
# no automatic escaping? joining is a lot eaiser then
if not eval_ctx.autoescape:
- return six.text_type(d).join(map(six.text_type, value))
+ return text_type(d).join(imap(text_type, 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
@@ -324,20 +322,20 @@ def do_join(eval_ctx, value, d=u'', attribute=None):
if hasattr(item, '__html__'):
do_escape = True
else:
- value[idx] = six.text_type(item)
+ value[idx] = text_type(item)
if do_escape:
d = escape(d)
else:
- d = six.text_type(d)
+ d = text_type(d)
return d.join(value)
# no html involved, to normal joining
- return soft_unicode(d).join(map(soft_unicode, value))
+ return soft_unicode(d).join(imap(soft_unicode, value))
def do_center(value, width=80):
"""Centers the value in a field of a given width."""
- return six.text_type(value).center(width)
+ return text_type(value).center(width)
@environmentfilter
@@ -552,7 +550,7 @@ def do_striptags(value):
"""
if hasattr(value, '__html__'):
value = value.__html__()
- return Markup(six.text_type(value)).striptags()
+ return Markup(text_type(value)).striptags()
def do_slice(value, slices, fill_with=None):
@@ -727,7 +725,7 @@ def do_sum(environment, iterable, attribute=None, start=0):
attributes. Also the `start` parameter was moved on to the right.
"""
if attribute is not None:
- iterable = map(make_attrgetter(environment, attribute), iterable)
+ iterable = imap(make_attrgetter(environment, attribute), iterable)
return sum(iterable, start)
@@ -747,14 +745,14 @@ def do_mark_safe(value):
def do_mark_unsafe(value):
"""Mark a value as unsafe. This is the reverse operation for :func:`safe`."""
- return six.text_type(value)
+ return text_type(value)
def do_reverse(value):
"""Reverse the object or return an iterator the iterates over it the other
way round.
"""
- if isinstance(value, six.string_types):
+ if isinstance(value, string_types):
return value[::-1]
try:
return reversed(value)
diff --git a/jinja2/lexer.py b/jinja2/lexer.py
index 07cf5c6..87e0920 100644
--- a/jinja2/lexer.py
+++ b/jinja2/lexer.py
@@ -15,13 +15,12 @@
:license: BSD, see LICENSE for more details.
"""
import re
-import six
from operator import itemgetter
from collections import deque
from jinja2.exceptions import TemplateSyntaxError
from jinja2.utils import LRUCache
-from jinja2._compat import next
+from jinja2._compat import next, iteritems, Iterator, text_type
# cache for the lexers. Exists in order to be able to have multiple
@@ -135,7 +134,7 @@ operators = {
';': TOKEN_SEMICOLON
}
-reverse_operators = dict([(v, k) for k, v in six.iteritems(operators)])
+reverse_operators = dict([(v, k) for k, v in 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))))
@@ -271,7 +270,7 @@ class Token(tuple):
)
-class TokenStreamIterator(six.Iterator):
+class TokenStreamIterator(Iterator):
"""The iterator for tokenstreams. Iterate over the stream
until the eof token is reached.
"""
@@ -291,7 +290,7 @@ class TokenStreamIterator(six.Iterator):
return token
-class TokenStream(six.Iterator):
+class TokenStream(Iterator):
"""A token stream is an iterable that yields :class:`Token`\s. The
parser however does not iterate over it but calls :meth:`next` to go
one token ahead. The current active token is stored as :attr:`current`.
@@ -598,7 +597,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 = six.text_type(source)
+ source = text_type(source)
lines = source.splitlines()
if self.keep_trailing_newline and source:
for newline in ('\r\n', '\r', '\n'):
@@ -646,7 +645,7 @@ class Lexer(object):
# yield for the current token the first named
# group that matched
elif token == '#bygroup':
- for key, value in six.iteritems(m.groupdict()):
+ for key, value in iteritems(m.groupdict()):
if value is not None:
yield lineno, key, value
lineno += value.count('\n')
@@ -703,7 +702,7 @@ class Lexer(object):
stack.pop()
# resolve the new state by group checking
elif new_state == '#bygroup':
- for key, value in six.iteritems(m.groupdict()):
+ for key, value in iteritems(m.groupdict()):
if value is not None:
stack.append(key)
break
diff --git a/jinja2/loaders.py b/jinja2/loaders.py
index f8e4f99..a9a2625 100644
--- a/jinja2/loaders.py
+++ b/jinja2/loaders.py
@@ -13,13 +13,10 @@ import sys
import weakref
from types import ModuleType
from os import path
-import six
-try:
- from hashlib import sha1
-except ImportError:
- from sha import new as sha1
+from hashlib import sha1
from jinja2.exceptions import TemplateNotFound
from jinja2.utils import open_if_exists, internalcode
+from jinja2._compat import string_types, iteritems
def split_template_path(template):
@@ -154,7 +151,7 @@ class FileSystemLoader(BaseLoader):
"""
def __init__(self, searchpath, encoding='utf-8'):
- if isinstance(searchpath, six.string_types):
+ if isinstance(searchpath, string_types):
searchpath = [searchpath]
self.searchpath = list(searchpath)
self.encoding = encoding
@@ -307,7 +304,7 @@ class FunctionLoader(BaseLoader):
rv = self.load_func(template)
if rv is None:
raise TemplateNotFound(template)
- elif isinstance(rv, six.string_types):
+ elif isinstance(rv, string_types):
return rv, None, None
return rv
@@ -360,7 +357,7 @@ class PrefixLoader(BaseLoader):
def list_templates(self):
result = []
- for prefix, loader in six.iteritems(self.mapping):
+ for prefix, loader in iteritems(self.mapping):
for template in loader.list_templates():
result.append(prefix + self.delimiter + template)
return result
@@ -432,7 +429,7 @@ class ModuleLoader(BaseLoader):
# create a fake module that looks for the templates in the
# path given.
mod = _TemplateModule(package_name)
- if isinstance(path, six.string_types):
+ if isinstance(path, string_types):
path = [path]
else:
path = list(path)
diff --git a/jinja2/meta.py b/jinja2/meta.py
index 26ae0b9..3110cff 100644
--- a/jinja2/meta.py
+++ b/jinja2/meta.py
@@ -11,7 +11,8 @@
"""
from jinja2 import nodes
from jinja2.compiler import CodeGenerator
-import six
+from jinja2._compat import string_types
+
class TrackingCodeGenerator(CodeGenerator):
"""We abuse the code generator for introspection."""
@@ -77,7 +78,7 @@ def find_referenced_templates(ast):
# something const, only yield the strings and ignore
# non-string consts that really just make no sense
if isinstance(template_name, nodes.Const):
- if isinstance(template_name.value, six.string_types):
+ if isinstance(template_name.value, string_types):
yield template_name.value
# something dynamic in there
else:
@@ -87,7 +88,7 @@ def find_referenced_templates(ast):
yield None
continue
# constant is a basestring, direct template name
- if isinstance(node.template.value, six.string_types):
+ if isinstance(node.template.value, string_types):
yield node.template.value
# a tuple or list (latter *should* not happen) made of consts,
# yield the consts that are strings. We could warn here for
@@ -95,7 +96,7 @@ def find_referenced_templates(ast):
elif isinstance(node, nodes.Include) and \
isinstance(node.template.value, (tuple, list)):
for template_name in node.template.value:
- if isinstance(template_name, six.string_types):
+ if isinstance(template_name, string_types):
yield template_name
# something else we don't care about, we could warn here
else:
diff --git a/jinja2/nodes.py b/jinja2/nodes.py
index e276f7e..26ba348 100644
--- a/jinja2/nodes.py
+++ b/jinja2/nodes.py
@@ -12,17 +12,16 @@
:copyright: (c) 2010 by the Jinja Team.
:license: BSD, see LICENSE for more details.
"""
-import six
import operator
from collections import deque
-from jinja2.utils import Markup, MethodType, FunctionType
-from jinja2._compat import next
-from six.moves import zip
+from jinja2.utils import Markup
+from jinja2._compat import next, izip, with_metaclass, text_type, \
+ method_type, function_type
#: the types we support for context functions
-_context_function_types = (FunctionType, MethodType)
+_context_function_types = (function_type, method_type)
_binop_to_func = {
@@ -105,7 +104,7 @@ def get_eval_context(node, ctx):
return ctx
-class Node(six.with_metaclass(NodeType, object)):
+class Node(with_metaclass(NodeType, object)):
"""Baseclass for all Jinja2 nodes. There are a number of nodes available
of different types. There are four major types:
@@ -139,7 +138,7 @@ class Node(six.with_metaclass(NodeType, object)):
len(self.fields),
len(self.fields) != 1 and 's' or ''
))
- for name, arg in zip(self.fields, fields):
+ for name, arg in izip(self.fields, fields):
setattr(self, name, arg)
for attr in self.attributes:
setattr(self, attr, attributes.pop(attr, None))
@@ -690,7 +689,7 @@ class Concat(Expr):
def as_const(self, eval_ctx=None):
eval_ctx = get_eval_context(self, eval_ctx)
- return ''.join(six.text_type(x.as_const(eval_ctx)) for x in self.nodes)
+ return ''.join(text_type(x.as_const(eval_ctx)) for x in self.nodes)
class Compare(Expr):
diff --git a/jinja2/runtime.py b/jinja2/runtime.py
index f2c4719..489bcca 100644
--- a/jinja2/runtime.py
+++ b/jinja2/runtime.py
@@ -14,9 +14,8 @@ from jinja2.utils import Markup, soft_unicode, escape, missing, concat, \
internalcode, object_type_repr
from jinja2.exceptions import UndefinedError, TemplateRuntimeError, \
TemplateNotFound
-from jinja2._compat import next
-import six
-from six.moves import map
+from jinja2._compat import next, imap, text_type, iteritems, Iterator, \
+ string_types, PY3
# these variables are exported to the template runtime
@@ -42,7 +41,7 @@ _last_iteration = object()
def markup_join(seq):
"""Concatenation that escapes if necessary and converts to unicode."""
buf = []
- iterator = map(soft_unicode, seq)
+ iterator = imap(soft_unicode, seq)
for arg in iterator:
buf.append(arg)
if hasattr(arg, '__html__'):
@@ -52,7 +51,7 @@ def markup_join(seq):
def unicode_join(seq):
"""Simple args to unicode conversion and concatenation."""
- return concat(map(six.text_type, seq))
+ return concat(imap(text_type, seq))
def new_context(environment, template_name, blocks, vars=None,
@@ -69,7 +68,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 six.iteritems(locals):
+ for key, value in iteritems(locals):
if key[:2] == 'l_' and value is not missing:
parent[key[2:]] = value
return Context(environment, parent, template_name, blocks)
@@ -125,7 +124,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 six.iteritems(blocks))
+ self.blocks = dict((k, [v]) for k, v in iteritems(blocks))
def super(self, name, current):
"""Render a parent block."""
@@ -208,7 +207,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 six.iteritems(self.blocks))
+ context.blocks.update((k, list(v)) for k, v in iteritems(self.blocks))
return context
def _all(meth):
@@ -357,7 +356,7 @@ class LoopContext(object):
)
-class LoopContextIterator(six.Iterator):
+class LoopContextIterator(Iterator):
"""The iterator for a loop context."""
__slots__ = ('context',)
@@ -472,7 +471,7 @@ class Undefined(object):
if self._undefined_hint is None:
if self._undefined_obj is missing:
hint = '%r is undefined' % self._undefined_name
- elif not isinstance(self._undefined_name, six.string_types):
+ elif not isinstance(self._undefined_name, string_types):
hint = '%s has no element %r' % (
object_type_repr(self._undefined_obj),
self._undefined_name
@@ -499,13 +498,16 @@ class Undefined(object):
__float__ = __complex__ = __pow__ = __rpow__ = \
_fail_with_undefined_error
- def __str__(self):
- s = self.__unicode__()
- return s if six.PY3 else s.encode('utf-8')
-
def __unicode__(self):
return u''
+ if PY3:
+ __str__ = __unicode__
+ del __unicode__
+ else:
+ def __str__(self):
+ return self.__unicode__().encode('utf-8')
+
def __len__(self):
return 0
@@ -535,10 +537,6 @@ class DebugUndefined(Undefined):
"""
__slots__ = ()
- def __str__(self):
- s = self.__unicode__()
- return s if six.PY3 else s.encode('utf-8')
-
def __unicode__(self):
if self._undefined_hint is None:
if self._undefined_obj is missing:
@@ -549,6 +547,10 @@ class DebugUndefined(Undefined):
)
return u'{{ undefined value printed: %s }}' % self._undefined_hint
+ if PY3:
+ __str__ = __unicode__
+ del __unicode__
+
class StrictUndefined(Undefined):
"""An undefined that barks on print and iteration as well as boolean
@@ -570,9 +572,12 @@ class StrictUndefined(Undefined):
UndefinedError: 'foo' is undefined
"""
__slots__ = ()
- __iter__ = __unicode__ = __str__ = __len__ = __nonzero__ = __eq__ = \
+ __iter__ = __str__ = __len__ = __nonzero__ = __eq__ = \
__ne__ = __bool__ = Undefined._fail_with_undefined_error
+ if not PY3:
+ __unicode__ = Undefined._fail_with_undefined_error
+
# remove remaining slots attributes, after the metaclass did the magic they
# are unneeded and irritating as they contain wrong data for the subclasses.
diff --git a/jinja2/sandbox.py b/jinja2/sandbox.py
index ed145d5..68fc599 100644
--- a/jinja2/sandbox.py
+++ b/jinja2/sandbox.py
@@ -13,11 +13,10 @@
:license: BSD.
"""
import operator
-import six
from jinja2.environment import Environment
from jinja2.exceptions import SecurityError
-from jinja2.utils import FunctionType, MethodType, TracebackType, CodeType, \
- FrameType, GeneratorType
+from jinja2._compat import string_types, function_type, method_type, \
+ traceback_type, code_type, frame_type, generator_type
#: maximum number of items a range may produce
@@ -125,19 +124,19 @@ def is_internal_attribute(obj, attr):
>>> is_internal_attribute(str, "upper")
False
"""
- if isinstance(obj, FunctionType):
+ if isinstance(obj, function_type):
if attr in UNSAFE_FUNCTION_ATTRIBUTES:
return True
- elif isinstance(obj, MethodType):
+ elif isinstance(obj, method_type):
if attr in UNSAFE_FUNCTION_ATTRIBUTES or \
attr in UNSAFE_METHOD_ATTRIBUTES:
return True
elif isinstance(obj, type):
if attr == 'mro':
return True
- elif isinstance(obj, (CodeType, TracebackType, FrameType)):
+ elif isinstance(obj, (code_type, traceback_type, frame_type)):
return True
- elif isinstance(obj, GeneratorType):
+ elif isinstance(obj, generator_type):
if attr == 'gi_frame':
return True
return attr.startswith('__')
@@ -300,7 +299,7 @@ class SandboxedEnvironment(Environment):
try:
return obj[argument]
except (TypeError, LookupError):
- if isinstance(argument, six.string_types):
+ if isinstance(argument, string_types):
try:
attr = str(argument)
except Exception:
diff --git a/jinja2/tests.py b/jinja2/tests.py
index 140b5bf..5fff61a 100644
--- a/jinja2/tests.py
+++ b/jinja2/tests.py
@@ -10,16 +10,7 @@
"""
import re
from jinja2.runtime import Undefined
-import six
-
-try:
- from collections import Mapping as MappingType
-except ImportError:
- import UserDict
- MappingType = (UserDict.UserDict, UserDict.DictMixin, dict)
-
-# nose, nothing here to test
-__test__ = False
+from jinja2._compat import text_type, string_types, mapping_types
number_re = re.compile(r'^-?\d+(\.\d+)?$')
@@ -77,17 +68,17 @@ def test_none(value):
def test_lower(value):
"""Return true if the variable is lowercased."""
- return six.text_type(value).islower()
+ return text_type(value).islower()
def test_upper(value):
"""Return true if the variable is uppercased."""
- return six.text_type(value).isupper()
+ return text_type(value).isupper()
def test_string(value):
"""Return true if the object is a string."""
- return isinstance(value, six.string_types)
+ return isinstance(value, string_types)
def test_mapping(value):
@@ -95,7 +86,7 @@ def test_mapping(value):
.. versionadded:: 2.6
"""
- return isinstance(value, MappingType)
+ return isinstance(value, mapping_types)
def test_number(value):
diff --git a/jinja2/utils.py b/jinja2/utils.py
index 164c583..f3cf10e 100644
--- a/jinja2/utils.py
+++ b/jinja2/utils.py
@@ -11,8 +11,6 @@
import re
import sys
import errno
-import six
-from six.moves import map
try:
from urllib.parse import quote_from_bytes as url_quote
except ImportError:
@@ -25,6 +23,8 @@ except ImportError:
except ImportError:
from dummy_thread import allocate_lock
from collections import deque
+from jinja2._compat import text_type, string_types, Iterator
+
_word_split_re = re.compile(r'(\s+)')
_punctuation_re = re.compile(
@@ -67,26 +67,6 @@ else:
from keyword import iskeyword as is_python_keyword
-# common types. These do exist in the special types module too which however
-# does not exist in IronPython out of the box. Also that way we don't have
-# to deal with implementation specific stuff here
-class _C(object):
- def method(self): pass
-def _func():
- yield None
-FunctionType = type(_func)
-GeneratorType = type(_func())
-MethodType = type(_C().method)
-CodeType = type(_C.method.__code__)
-try:
- raise TypeError()
-except TypeError:
- _tb = sys.exc_info()[2]
- TracebackType = type(_tb)
- FrameType = type(_tb.tb_frame)
-del _C, _tb, _func
-
-
def contextfunction(f):
"""This decorator can be used to mark a function or method context callable.
A context callable is passed the active :class:`Context` as first argument when
@@ -247,7 +227,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(six.text_type(escape(text)))
+ words = _word_split_re.split(text_type(escape(text)))
nofollow_attr = nofollow and ' rel="nofollow"' or ''
for i, word in enumerate(words):
match = _punctuation_re.match(word)
@@ -334,11 +314,11 @@ def unicode_urlencode(obj, charset='utf-8'):
If non strings are provided they are converted to their unicode
representation first.
"""
- if not isinstance(obj, six.string_types):
- obj = six.text_type(obj)
- if isinstance(obj, six.text_type):
+ if not isinstance(obj, string_types):
+ obj = text_type(obj)
+ if isinstance(obj, text_type):
obj = obj.encode(charset)
- return six.text_type(url_quote(obj))
+ return text_type(url_quote(obj))
class LRUCache(object):
@@ -526,7 +506,7 @@ except ImportError:
pass
-class Cycler(six.Iterator):
+class Cycler(Iterator):
"""A cycle helper for templates."""
def __init__(self, *items):