Moved all six usages (ignoring testsuite) into jinja2._compat
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 @@
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 @@
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.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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
# 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 @@
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 @@
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 @@
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 @@
"""
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
"""
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 @@
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 @@
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 @@
.. 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 @@
@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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
# 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 @@
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.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 @@
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 @@
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 @@
# 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 @@
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 @@
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 @@
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 @@
"""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 @@
"""
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 @@
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 @@
"""
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 @@
'"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 @@
"""
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 @@
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 @@
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 @@
"""
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 @@
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_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 @@
';': 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 TokenStreamIterator(six.Iterator):
+class TokenStreamIterator(Iterator):
"""The iterator for tokenstreams. Iterate over the stream
until the eof token is reached.
"""
@@ -291,7 +290,7 @@
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 @@
"""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 @@
# 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 @@
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 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 @@
"""
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 @@
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 @@
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 @@
# 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 @@
# 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 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 @@
# 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 @@
# 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 @@
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 LoopContextIterator(six.Iterator):
+class LoopContextIterator(Iterator):
"""The iterator for a loop context."""
__slots__ = ('context',)
@@ -472,7 +471,7 @@
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 @@
__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 @@
"""
__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 @@
)
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 @@
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 @@
>>> 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 @@
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_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 @@
.. 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:
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 @@
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 @@
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 @@
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 @@
pass
-class Cycler(six.Iterator):
+class Cycler(Iterator):
"""A cycle helper for templates."""
def __init__(self, *items):