Home | History | Annotate | Download | only in jinja2
      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 """
     13 import sys
     14 
     15 PY2 = sys.version_info[0] == 2
     16 PYPY = hasattr(sys, 'pypy_translation_info')
     17 _identity = lambda x: x
     18 
     19 
     20 if 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 
     49 else:
     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 
     85 try:
     86     next = next
     87 except NameError:
     88     def next(it):
     89         return it.next()
     90 
     91 
     92 def 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 
    112 try:
    113     from collections import Mapping as mapping_types
    114 except 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
    122 class _C(object):
    123     def method(self): pass
    124 def _func():
    125     yield None
    126 function_type = type(_func)
    127 generator_type = type(_func())
    128 method_type = type(_C().method)
    129 code_type = type(_C.method.__code__)
    130 try:
    131     raise TypeError()
    132 except TypeError:
    133     _tb = sys.exc_info()[2]
    134     traceback_type = type(_tb)
    135     frame_type = type(_tb.tb_frame)
    136 
    137 
    138 try:
    139     from urllib.parse import quote_from_bytes as url_quote
    140 except ImportError:
    141     from urllib import quote as url_quote
    142 
    143 
    144 try:
    145     from thread import allocate_lock
    146 except ImportError:
    147     try:
    148         from threading import Lock as allocate_lock
    149     except ImportError:
    150         from dummy_thread import allocate_lock
    151