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