Michael Merickel
2018-10-19 aff6ee3c87a7a3f114e9b611b22c9dd41d79614a
commit | author | age
6c1597 1 import inspect
8064bd 2 import platform
e6c2d2 3 import sys
CM 4 import types
5
2e7c71 6 WIN = platform.system() == 'Windows'
8064bd 7
ce7c06 8 try:  # pragma: no cover
f11a02 9     import __pypy__
0c29cf 10
f11a02 11     PYPY = True
4d838f 12 except BaseException:  # pragma: no cover
f11a02 13     __pypy__ = None
CM 14     PYPY = False
15
e6c2d2 16 try:
CM 17     import cPickle as pickle
ce7c06 18 except ImportError:  # pragma: no cover
e6c2d2 19     import pickle
CM 20
e80491 21 try:
MB 22     from functools import lru_cache
23 except ImportError:
24     from repoze.lru import lru_cache
25
49cd2f 26 # PY3 is left as bw-compat but PY2 should be used for most checks.
bc37a5 27 PY2 = sys.version_info[0] == 2
e6c2d2 28 PY3 = sys.version_info[0] == 3
CM 29
bc37a5 30 if PY2:
0c29cf 31     string_types = (basestring,)
e6c2d2 32     integer_types = (int, long)
CM 33     class_types = (type, types.ClassType)
34     text_type = unicode
35     binary_type = str
16a5d3 36     long = long
bc37a5 37 else:
0c29cf 38     string_types = (str,)
MM 39     integer_types = (int,)
40     class_types = (type,)
bc37a5 41     text_type = str
MM 42     binary_type = bytes
43     long = int
0c29cf 44
e6c2d2 45
CM 46 def text_(s, encoding='latin-1', errors='strict'):
5cf9fc 47     """ If ``s`` is an instance of ``binary_type``, return
5a3ddb 48     ``s.decode(encoding, errors)``, otherwise return ``s``"""
e6c2d2 49     if isinstance(s, binary_type):
CM 50         return s.decode(encoding, errors)
cf4ad5 51     return s
e6c2d2 52
0c29cf 53
e6c2d2 54 def bytes_(s, encoding='latin-1', errors='strict'):
5cf9fc 55     """ If ``s`` is an instance of ``text_type``, return
CM 56     ``s.encode(encoding, errors)``, otherwise return ``s``"""
cf4ad5 57     if isinstance(s, text_type):
e6c2d2 58         return s.encode(encoding, errors)
CM 59     return s
60
0c29cf 61
bc37a5 62 if PY2:
0c29cf 63
f84147 64     def ascii_native_(s):
CM 65         if isinstance(s, text_type):
66             s = s.encode('ascii')
67         return str(s)
0c29cf 68
MM 69
bc37a5 70 else:
0c29cf 71
bc37a5 72     def ascii_native_(s):
MM 73         if isinstance(s, text_type):
74             s = s.encode('ascii')
75         return str(s, 'ascii', 'strict')
0c29cf 76
f84147 77
5cf9fc 78 ascii_native_.__doc__ = """
CM 79 Python 3: If ``s`` is an instance of ``text_type``, return
80 ``s.encode('ascii')``, otherwise return ``str(s, 'ascii', 'strict')``
81
82 Python 2: If ``s`` is an instance of ``text_type``, return
83 ``s.encode('ascii')``, otherwise return ``str(s)``
84 """
85
86
bc37a5 87 if PY2:
0c29cf 88
e6c2d2 89     def native_(s, encoding='latin-1', errors='strict'):
5cf9fc 90         """ If ``s`` is an instance of ``text_type``, return
CM 91         ``s.encode(encoding, errors)``, otherwise return ``str(s)``"""
e6c2d2 92         if isinstance(s, text_type):
CM 93             return s.encode(encoding, errors)
94         return str(s)
0c29cf 95
MM 96
bc37a5 97 else:
0c29cf 98
bc37a5 99     def native_(s, encoding='latin-1', errors='strict'):
MM 100         """ If ``s`` is an instance of ``text_type``, return
101         ``s``, otherwise return ``str(s, encoding, errors)``"""
102         if isinstance(s, text_type):
103             return s
104         return str(s, encoding, errors)
0c29cf 105
5cf9fc 106
CM 107 native_.__doc__ = """
108 Python 3: If ``s`` is an instance of ``text_type``, return ``s``, otherwise
109 return ``str(s, encoding, errors)``
110
111 Python 2: If ``s`` is an instance of ``text_type``, return
112 ``s.encode(encoding, errors)``, otherwise return ``str(s)``
113 """
e6c2d2 114
bc37a5 115 if PY2:
e6c2d2 116     import urlparse
CM 117     from urllib import quote as url_quote
a84e17 118     from urllib import quote_plus as url_quote_plus
e6c2d2 119     from urllib import unquote as url_unquote
CM 120     from urllib import urlencode as url_encode
121     from urllib2 import urlopen as url_open
ce7c06 122
0c29cf 123     def url_unquote_text(
MM 124         v, encoding='utf-8', errors='replace'
125     ):  # pragma: no cover
954999 126         v = url_unquote(v)
CM 127         return v.decode(encoding, errors)
ce7c06 128
0c29cf 129     def url_unquote_native(
MM 130         v, encoding='utf-8', errors='replace'
131     ):  # pragma: no cover
f84147 132         return native_(url_unquote_text(v, encoding, errors))
0c29cf 133
MM 134
bc37a5 135 else:
MM 136     from urllib import parse
0c29cf 137
bc37a5 138     urlparse = parse
MM 139     from urllib.parse import quote as url_quote
140     from urllib.parse import quote_plus as url_quote_plus
141     from urllib.parse import unquote as url_unquote
142     from urllib.parse import urlencode as url_encode
143     from urllib.request import urlopen as url_open
0c29cf 144
bc37a5 145     url_unquote_text = url_unquote
MM 146     url_unquote_native = url_unquote
e6c2d2 147
ce7c06 148
bc37a5 149 if PY2:  # pragma: no cover
0c29cf 150
e6c2d2 151     def exec_(code, globs=None, locs=None):
CM 152         """Execute code in a namespace."""
153         if globs is None:
154             frame = sys._getframe(1)
155             globs = frame.f_globals
156             if locs is None:
157                 locs = frame.f_locals
158             del frame
159         elif locs is None:
160             locs = globs
161         exec("""exec code in globs, locs""")
162
0c29cf 163     exec_(
MM 164         """def reraise(tp, value, tb=None):
e6c2d2 165     raise tp, value, tb
0c29cf 166 """
MM 167     )
e6c2d2 168
ce7c06 169 else:  # pragma: no cover
bc37a5 170     import builtins
0c29cf 171
bc37a5 172     exec_ = getattr(builtins, "exec")
MM 173
174     def reraise(tp, value, tb=None):
175         if value is None:
176             value = tp
177         if value.__traceback__ is not tb:
178             raise value.with_traceback(tb)
179         raise value
180
181     del builtins
182
183
184 if PY2:  # pragma: no cover
0c29cf 185
e6c2d2 186     def iteritems_(d):
CM 187         return d.iteritems()
ce7c06 188
e6c2d2 189     def itervalues_(d):
CM 190         return d.itervalues()
ce7c06 191
8e606d 192     def iterkeys_(d):
CM 193         return d.iterkeys()
0c29cf 194
MM 195
bc37a5 196 else:  # pragma: no cover
0c29cf 197
bc37a5 198     def iteritems_(d):
MM 199         return d.items()
200
201     def itervalues_(d):
202         return d.values()
203
204     def iterkeys_(d):
205         return d.keys()
e6c2d2 206
CM 207
bc37a5 208 if PY2:
MM 209     map_ = map
210 else:
0c29cf 211
e6c2d2 212     def map_(*arg):
CM 213         return list(map(*arg))
ce7c06 214
0c29cf 215
bc37a5 216 if PY2:
0c29cf 217
bc37a5 218     def is_nonstr_iter(v):
MM 219         return hasattr(v, '__iter__')
0c29cf 220
MM 221
bc37a5 222 else:
0c29cf 223
475532 224     def is_nonstr_iter(v):
CM 225         if isinstance(v, str):
226             return False
227         return hasattr(v, '__iter__')
0c29cf 228
ce7c06 229
bc37a5 230 if PY2:
2029b2 231     im_func = 'im_func'
6c1597 232     im_self = 'im_self'
bc37a5 233 else:
MM 234     im_func = '__func__'
235     im_self = '__self__'
8e606d 236
cf4ad5 237 try:
8e606d 238     import configparser
cf4ad5 239 except ImportError:
338cb9 240     import ConfigParser as configparser
45009c 241
CM 242 try:
243     from http.cookies import SimpleCookie
cf4ad5 244 except ImportError:
MM 245     from Cookie import SimpleCookie
10d2f2 246
bc37a5 247 if PY2:
10d2f2 248     from cgi import escape
cf4ad5 249 else:
bc37a5 250     from html import escape
MM 251
252 if PY2:
cf4ad5 253     input_ = raw_input
ce7c06 254 else:
bc37a5 255     input_ = input
MM 256
257 if PY2:
cf4ad5 258     from io import BytesIO as NativeIO
bc37a5 259 else:
MM 260     from io import StringIO as NativeIO
4b4ef7 261
CM 262 # "json" is not an API; it's here to support older pyramid_debugtoolbar
263 # versions which attempt to import it
264 import json
d68f85 265
bc37a5 266 if PY2:
0c29cf 267
bc37a5 268     def decode_path_info(path):
MM 269         return path.decode('utf-8')
0c29cf 270
MM 271
bc37a5 272 else:
5c43d5 273     # see PEP 3333 for why we encode WSGI PATH_INFO to latin-1 before
CM 274     # decoding it to utf-8
275     def decode_path_info(path):
276         return path.encode('latin-1').decode('utf-8')
277
0c29cf 278
bc37a5 279 if PY2:
MM 280     from urlparse import unquote as unquote_to_bytes
281
282     def unquote_bytes_to_wsgi(bytestring):
283         return unquote_to_bytes(bytestring)
0c29cf 284
MM 285
bc37a5 286 else:
0c29cf 287     # see PEP 3333 for why we decode the path to latin-1
5c43d5 288     from urllib.parse import unquote_to_bytes
ce7c06 289
5c43d5 290     def unquote_bytes_to_wsgi(bytestring):
CM 291         return unquote_to_bytes(bytestring).decode('latin-1')
6c1597 292
CM 293
294 def is_bound_method(ob):
295     return inspect.ismethod(ob) and getattr(ob, im_self, None) is not None
0c29cf 296
6c1597 297
31e492 298 # support annotations and keyword-only arguments in PY3
bc37a5 299 if PY2:
31e492 300     from inspect import getargspec
5d2302 301 else:
bc37a5 302     from inspect import getfullargspec as getargspec
MM 303
304 if PY2:
5d2302 305     from itertools import izip_longest as zip_longest
bc37a5 306 else:
MM 307     from itertools import zip_longest
ce7c06 308
0c29cf 309
4a7029 310 def is_unbound_method(fn):
JA 311     """
312     This consistently verifies that the callable is bound to a
313     class.
314     """
315     is_bound = is_bound_method(fn)
316
317     if not is_bound and inspect.isroutine(fn):
6e9e2d 318         spec = getargspec(fn)
4a7029 319         has_self = len(spec.args) > 0 and spec.args[0] == 'self'
JA 320
bc37a5 321         if PY2 and inspect.ismethod(fn):
4a7029 322             return True
bc37a5 323         elif inspect.isfunction(fn) and has_self:
4a7029 324             return True
JA 325
326     return False