1# -*- coding: utf-8 -*-
2"""
3    jinja2._compat
4    ~~~~~~~~~~~~~~
5
6    Some py2/py3 compatibility support based on a stripped down
7    version of six so we don't have to depend on a specific version
8    of it.
9
10    :copyright: Copyright 2013 by the Jinja team, see AUTHORS.
11    :license: BSD, see LICENSE for details.
12"""
13import sys
14
15PY2 = sys.version_info[0] == 2
16PYPY = hasattr(sys, 'pypy_translation_info')
17_identity = lambda x: x
18
19
20if not PY2:
21    unichr = chr
22    range_type = range
23    text_type = str
24    string_types = (str,)
25
26    iterkeys = lambda d: iter(d.keys())
27    itervalues = lambda d: iter(d.values())
28    iteritems = lambda d: iter(d.items())
29
30    import pickle
31    from io import BytesIO, StringIO
32    NativeStringIO = StringIO
33
34    def reraise(tp, value, tb=None):
35        if value.__traceback__ is not tb:
36            raise value.with_traceback(tb)
37        raise value
38
39    ifilter = filter
40    imap = map
41    izip = zip
42    intern = sys.intern
43
44    implements_iterator = _identity
45    implements_to_string = _identity
46    encode_filename = _identity
47    get_next = lambda x: x.__next__
48
49else:
50    unichr = unichr
51    text_type = unicode
52    range_type = xrange
53    string_types = (str, unicode)
54
55    iterkeys = lambda d: d.iterkeys()
56    itervalues = lambda d: d.itervalues()
57    iteritems = lambda d: d.iteritems()
58
59    import cPickle as pickle
60    from cStringIO import StringIO as BytesIO, StringIO
61    NativeStringIO = BytesIO
62
63    exec('def reraise(tp, value, tb=None):\n raise tp, value, tb')
64
65    from itertools import imap, izip, ifilter
66    intern = intern
67
68    def implements_iterator(cls):
69        cls.next = cls.__next__
70        del cls.__next__
71        return cls
72
73    def implements_to_string(cls):
74        cls.__unicode__ = cls.__str__
75        cls.__str__ = lambda x: x.__unicode__().encode('utf-8')
76        return cls
77
78    get_next = lambda x: x.next
79
80    def encode_filename(filename):
81        if isinstance(filename, unicode):
82            return filename.encode('utf-8')
83        return filename
84
85try:
86    next = next
87except NameError:
88    def next(it):
89        return it.next()
90
91
92def with_metaclass(meta, *bases):
93    # This requires a bit of explanation: the basic idea is to make a
94    # dummy metaclass for one level of class instanciation that replaces
95    # itself with the actual metaclass.  Because of internal type checks
96    # we also need to make sure that we downgrade the custom metaclass
97    # for one level to something closer to type (that's why __call__ and
98    # __init__ comes back from type etc.).
99    #
100    # This has the advantage over six.with_metaclass in that it does not
101    # introduce dummy classes into the final MRO.
102    class metaclass(meta):
103        __call__ = type.__call__
104        __init__ = type.__init__
105        def __new__(cls, name, this_bases, d):
106            if this_bases is None:
107                return type.__new__(cls, name, (), d)
108            return meta(name, bases, d)
109    return metaclass('temporary_class', None, {})
110
111
112try:
113    from collections import Mapping as mapping_types
114except ImportError:
115    import UserDict
116    mapping_types = (UserDict.UserDict, UserDict.DictMixin, dict)
117
118
119# common types.  These do exist in the special types module too which however
120# does not exist in IronPython out of the box.  Also that way we don't have
121# to deal with implementation specific stuff here
122class _C(object):
123    def method(self): pass
124def _func():
125    yield None
126function_type = type(_func)
127generator_type = type(_func())
128method_type = type(_C().method)
129code_type = type(_C.method.__code__)
130try:
131    raise TypeError()
132except TypeError:
133    _tb = sys.exc_info()[2]
134    traceback_type = type(_tb)
135    frame_type = type(_tb.tb_frame)
136
137
138try:
139    from urllib.parse import quote_from_bytes as url_quote
140except ImportError:
141    from urllib import quote as url_quote
142
143
144try:
145    from thread import allocate_lock
146except ImportError:
147    try:
148        from threading import Lock as allocate_lock
149    except ImportError:
150        from dummy_thread import allocate_lock
151