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 |