1# -*- coding: utf-8 -*- 2# flake8: noqa 3""" 4 flask_admin._compat 5 ~~~~~~~~~~~~~~~~~~~~~~~ 6 7 Some py2/py3 compatibility support based on a stripped down 8 version of six so we don't have to depend on a specific version 9 of it. 10 11 :copyright: (c) 2013 by Armin Ronacher. 12 :license: BSD, see LICENSE for more details. 13""" 14import sys 15 16PY2 = sys.version_info[0] == 2 17VER = sys.version_info 18 19if not PY2: 20 text_type = str 21 string_types = (str,) 22 integer_types = (int, ) 23 24 iterkeys = lambda d: iter(d.keys()) 25 itervalues = lambda d: iter(d.values()) 26 iteritems = lambda d: iter(d.items()) 27 filter_list = lambda f, l: list(filter(f, l)) 28 29 def as_unicode(s): 30 if isinstance(s, bytes): 31 return s.decode('utf-8') 32 33 return str(s) 34 35 def csv_encode(s): 36 ''' Returns unicode string expected by Python 3's csv module ''' 37 return as_unicode(s) 38 39 # Various tools 40 from functools import reduce 41 from urllib.parse import urljoin, urlparse, quote 42else: 43 text_type = unicode 44 string_types = (str, unicode) 45 integer_types = (int, long) 46 47 iterkeys = lambda d: d.iterkeys() 48 itervalues = lambda d: d.itervalues() 49 iteritems = lambda d: d.iteritems() 50 filter_list = filter 51 52 def as_unicode(s): 53 if isinstance(s, str): 54 return s.decode('utf-8') 55 56 return unicode(s) 57 58 def csv_encode(s): 59 ''' Returns byte string expected by Python 2's csv module ''' 60 return as_unicode(s).encode('utf-8') 61 62 # Helpers 63 reduce = __builtins__['reduce'] if isinstance(__builtins__, dict) else __builtins__.reduce 64 from urlparse import urljoin, urlparse 65 from urllib import quote 66 67 68def with_metaclass(meta, *bases): 69 # This requires a bit of explanation: the basic idea is to make a 70 # dummy metaclass for one level of class instantiation that replaces 71 # itself with the actual metaclass. Because of internal type checks 72 # we also need to make sure that we downgrade the custom metaclass 73 # for one level to something closer to type (that's why __call__ and 74 # __init__ comes back from type etc.). 75 # 76 # This has the advantage over six.with_metaclass in that it does not 77 # introduce dummy classes into the final MRO. 78 class metaclass(meta): 79 __call__ = type.__call__ 80 __init__ = type.__init__ 81 82 def __new__(cls, name, this_bases, d): 83 if this_bases is None: 84 return type.__new__(cls, name, (), d) 85 return meta(name, bases, d) 86 return metaclass('temporary_class', None, {}) 87 88 89try: 90 from collections import OrderedDict 91except ImportError: 92 from ordereddict import OrderedDict 93