1"""Utilities for writing code that runs on Python 2 and 3""" 2 3# Copyright (c) 2010-2013 Benjamin Peterson 4# 5# Permission is hereby granted, free of charge, to any person obtaining a copy 6# of this software and associated documentation files (the "Software"), to deal 7# in the Software without restriction, including without limitation the rights 8# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9# copies of the Software, and to permit persons to whom the Software is 10# furnished to do so, subject to the following conditions: 11# 12# The above copyright notice and this permission notice shall be included in all 13# copies or substantial portions of the Software. 14# 15# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21# SOFTWARE. 22 23import operator 24import sys 25import types 26 27__author__ = "Benjamin Peterson <benjamin@python.org>" 28__version__ = "1.4.1" 29 30 31# Useful for very coarse version differentiation. 32PY2 = sys.version_info[0] == 2 33PY3 = sys.version_info[0] == 3 34 35if PY3: 36 string_types = str, 37 integer_types = int, 38 class_types = type, 39 text_type = str 40 binary_type = bytes 41 42 MAXSIZE = sys.maxsize 43else: 44 string_types = basestring, 45 integer_types = (int, long) 46 class_types = (type, types.ClassType) 47 text_type = unicode 48 binary_type = str 49 50 if sys.platform.startswith("java"): 51 # Jython always uses 32 bits. 52 MAXSIZE = int((1 << 31) - 1) 53 else: 54 # It's possible to have sizeof(long) != sizeof(Py_ssize_t). 55 class X(object): 56 def __len__(self): 57 return 1 << 31 58 try: 59 len(X()) 60 except OverflowError: 61 # 32-bit 62 MAXSIZE = int((1 << 31) - 1) 63 else: 64 # 64-bit 65 MAXSIZE = int((1 << 63) - 1) 66 del X 67 68 69def _add_doc(func, doc): 70 """Add documentation to a function.""" 71 func.__doc__ = doc 72 73 74def _import_module(name): 75 """Import module, returning the module after the last dot.""" 76 __import__(name) 77 return sys.modules[name] 78 79 80class _LazyDescr(object): 81 82 def __init__(self, name): 83 self.name = name 84 85 def __get__(self, obj, tp): 86 result = self._resolve() 87 setattr(obj, self.name, result) 88 # This is a bit ugly, but it avoids running this again. 89 delattr(tp, self.name) 90 return result 91 92 93class MovedModule(_LazyDescr): 94 95 def __init__(self, name, old, new=None): 96 super(MovedModule, self).__init__(name) 97 if PY3: 98 if new is None: 99 new = name 100 self.mod = new 101 else: 102 self.mod = old 103 104 def _resolve(self): 105 return _import_module(self.mod) 106 107 108class MovedAttribute(_LazyDescr): 109 110 def __init__(self, name, old_mod, new_mod, old_attr=None, new_attr=None): 111 super(MovedAttribute, self).__init__(name) 112 if PY3: 113 if new_mod is None: 114 new_mod = name 115 self.mod = new_mod 116 if new_attr is None: 117 if old_attr is None: 118 new_attr = name 119 else: 120 new_attr = old_attr 121 self.attr = new_attr 122 else: 123 self.mod = old_mod 124 if old_attr is None: 125 old_attr = name 126 self.attr = old_attr 127 128 def _resolve(self): 129 module = _import_module(self.mod) 130 return getattr(module, self.attr) 131 132 133 134class _MovedItems(types.ModuleType): 135 """Lazy loading of moved objects""" 136 137 138_moved_attributes = [ 139 MovedAttribute("cStringIO", "cStringIO", "io", "StringIO"), 140 MovedAttribute("filter", "itertools", "builtins", "ifilter", "filter"), 141 MovedAttribute("filterfalse", "itertools", "itertools", "ifilterfalse", "filterfalse"), 142 MovedAttribute("input", "__builtin__", "builtins", "raw_input", "input"), 143 MovedAttribute("map", "itertools", "builtins", "imap", "map"), 144 MovedAttribute("range", "__builtin__", "builtins", "xrange", "range"), 145 MovedAttribute("reload_module", "__builtin__", "imp", "reload"), 146 MovedAttribute("reduce", "__builtin__", "functools"), 147 MovedAttribute("StringIO", "StringIO", "io"), 148 MovedAttribute("UserString", "UserString", "collections"), 149 MovedAttribute("xrange", "__builtin__", "builtins", "xrange", "range"), 150 MovedAttribute("zip", "itertools", "builtins", "izip", "zip"), 151 MovedAttribute("zip_longest", "itertools", "itertools", "izip_longest", "zip_longest"), 152 153 MovedModule("builtins", "__builtin__"), 154 MovedModule("configparser", "ConfigParser"), 155 MovedModule("copyreg", "copy_reg"), 156 MovedModule("http_cookiejar", "cookielib", "http.cookiejar"), 157 MovedModule("http_cookies", "Cookie", "http.cookies"), 158 MovedModule("html_entities", "htmlentitydefs", "html.entities"), 159 MovedModule("html_parser", "HTMLParser", "html.parser"), 160 MovedModule("http_client", "httplib", "http.client"), 161 MovedModule("email_mime_multipart", "email.MIMEMultipart", "email.mime.multipart"), 162 MovedModule("email_mime_text", "email.MIMEText", "email.mime.text"), 163 MovedModule("email_mime_base", "email.MIMEBase", "email.mime.base"), 164 MovedModule("BaseHTTPServer", "BaseHTTPServer", "http.server"), 165 MovedModule("CGIHTTPServer", "CGIHTTPServer", "http.server"), 166 MovedModule("SimpleHTTPServer", "SimpleHTTPServer", "http.server"), 167 MovedModule("cPickle", "cPickle", "pickle"), 168 MovedModule("queue", "Queue"), 169 MovedModule("reprlib", "repr"), 170 MovedModule("socketserver", "SocketServer"), 171 MovedModule("tkinter", "Tkinter"), 172 MovedModule("tkinter_dialog", "Dialog", "tkinter.dialog"), 173 MovedModule("tkinter_filedialog", "FileDialog", "tkinter.filedialog"), 174 MovedModule("tkinter_scrolledtext", "ScrolledText", "tkinter.scrolledtext"), 175 MovedModule("tkinter_simpledialog", "SimpleDialog", "tkinter.simpledialog"), 176 MovedModule("tkinter_tix", "Tix", "tkinter.tix"), 177 MovedModule("tkinter_constants", "Tkconstants", "tkinter.constants"), 178 MovedModule("tkinter_dnd", "Tkdnd", "tkinter.dnd"), 179 MovedModule("tkinter_colorchooser", "tkColorChooser", 180 "tkinter.colorchooser"), 181 MovedModule("tkinter_commondialog", "tkCommonDialog", 182 "tkinter.commondialog"), 183 MovedModule("tkinter_tkfiledialog", "tkFileDialog", "tkinter.filedialog"), 184 MovedModule("tkinter_font", "tkFont", "tkinter.font"), 185 MovedModule("tkinter_messagebox", "tkMessageBox", "tkinter.messagebox"), 186 MovedModule("tkinter_tksimpledialog", "tkSimpleDialog", 187 "tkinter.simpledialog"), 188 MovedModule("urllib_parse", __name__ + ".moves.urllib_parse", "urllib.parse"), 189 MovedModule("urllib_error", __name__ + ".moves.urllib_error", "urllib.error"), 190 MovedModule("urllib", __name__ + ".moves.urllib", __name__ + ".moves.urllib"), 191 MovedModule("urllib_robotparser", "robotparser", "urllib.robotparser"), 192 MovedModule("winreg", "_winreg"), 193] 194for attr in _moved_attributes: 195 setattr(_MovedItems, attr.name, attr) 196del attr 197 198moves = sys.modules[__name__ + ".moves"] = _MovedItems(__name__ + ".moves") 199 200 201 202class Module_six_moves_urllib_parse(types.ModuleType): 203 """Lazy loading of moved objects in six.moves.urllib_parse""" 204 205 206_urllib_parse_moved_attributes = [ 207 MovedAttribute("ParseResult", "urlparse", "urllib.parse"), 208 MovedAttribute("parse_qs", "urlparse", "urllib.parse"), 209 MovedAttribute("parse_qsl", "urlparse", "urllib.parse"), 210 MovedAttribute("urldefrag", "urlparse", "urllib.parse"), 211 MovedAttribute("urljoin", "urlparse", "urllib.parse"), 212 MovedAttribute("urlparse", "urlparse", "urllib.parse"), 213 MovedAttribute("urlsplit", "urlparse", "urllib.parse"), 214 MovedAttribute("urlunparse", "urlparse", "urllib.parse"), 215 MovedAttribute("urlunsplit", "urlparse", "urllib.parse"), 216 MovedAttribute("quote", "urllib", "urllib.parse"), 217 MovedAttribute("quote_plus", "urllib", "urllib.parse"), 218 MovedAttribute("unquote", "urllib", "urllib.parse"), 219 MovedAttribute("unquote_plus", "urllib", "urllib.parse"), 220 MovedAttribute("urlencode", "urllib", "urllib.parse"), 221] 222for attr in _urllib_parse_moved_attributes: 223 setattr(Module_six_moves_urllib_parse, attr.name, attr) 224del attr 225 226sys.modules[__name__ + ".moves.urllib_parse"] = Module_six_moves_urllib_parse(__name__ + ".moves.urllib_parse") 227sys.modules[__name__ + ".moves.urllib.parse"] = Module_six_moves_urllib_parse(__name__ + ".moves.urllib.parse") 228 229 230class Module_six_moves_urllib_error(types.ModuleType): 231 """Lazy loading of moved objects in six.moves.urllib_error""" 232 233 234_urllib_error_moved_attributes = [ 235 MovedAttribute("URLError", "urllib2", "urllib.error"), 236 MovedAttribute("HTTPError", "urllib2", "urllib.error"), 237 MovedAttribute("ContentTooShortError", "urllib", "urllib.error"), 238] 239for attr in _urllib_error_moved_attributes: 240 setattr(Module_six_moves_urllib_error, attr.name, attr) 241del attr 242 243sys.modules[__name__ + ".moves.urllib_error"] = Module_six_moves_urllib_error(__name__ + ".moves.urllib_error") 244sys.modules[__name__ + ".moves.urllib.error"] = Module_six_moves_urllib_error(__name__ + ".moves.urllib.error") 245 246 247class Module_six_moves_urllib_request(types.ModuleType): 248 """Lazy loading of moved objects in six.moves.urllib_request""" 249 250 251_urllib_request_moved_attributes = [ 252 MovedAttribute("urlopen", "urllib2", "urllib.request"), 253 MovedAttribute("install_opener", "urllib2", "urllib.request"), 254 MovedAttribute("build_opener", "urllib2", "urllib.request"), 255 MovedAttribute("pathname2url", "urllib", "urllib.request"), 256 MovedAttribute("url2pathname", "urllib", "urllib.request"), 257 MovedAttribute("getproxies", "urllib", "urllib.request"), 258 MovedAttribute("Request", "urllib2", "urllib.request"), 259 MovedAttribute("OpenerDirector", "urllib2", "urllib.request"), 260 MovedAttribute("HTTPDefaultErrorHandler", "urllib2", "urllib.request"), 261 MovedAttribute("HTTPRedirectHandler", "urllib2", "urllib.request"), 262 MovedAttribute("HTTPCookieProcessor", "urllib2", "urllib.request"), 263 MovedAttribute("ProxyHandler", "urllib2", "urllib.request"), 264 MovedAttribute("BaseHandler", "urllib2", "urllib.request"), 265 MovedAttribute("HTTPPasswordMgr", "urllib2", "urllib.request"), 266 MovedAttribute("HTTPPasswordMgrWithDefaultRealm", "urllib2", "urllib.request"), 267 MovedAttribute("AbstractBasicAuthHandler", "urllib2", "urllib.request"), 268 MovedAttribute("HTTPBasicAuthHandler", "urllib2", "urllib.request"), 269 MovedAttribute("ProxyBasicAuthHandler", "urllib2", "urllib.request"), 270 MovedAttribute("AbstractDigestAuthHandler", "urllib2", "urllib.request"), 271 MovedAttribute("HTTPDigestAuthHandler", "urllib2", "urllib.request"), 272 MovedAttribute("ProxyDigestAuthHandler", "urllib2", "urllib.request"), 273 MovedAttribute("HTTPHandler", "urllib2", "urllib.request"), 274 MovedAttribute("HTTPSHandler", "urllib2", "urllib.request"), 275 MovedAttribute("FileHandler", "urllib2", "urllib.request"), 276 MovedAttribute("FTPHandler", "urllib2", "urllib.request"), 277 MovedAttribute("CacheFTPHandler", "urllib2", "urllib.request"), 278 MovedAttribute("UnknownHandler", "urllib2", "urllib.request"), 279 MovedAttribute("HTTPErrorProcessor", "urllib2", "urllib.request"), 280 MovedAttribute("urlretrieve", "urllib", "urllib.request"), 281 MovedAttribute("urlcleanup", "urllib", "urllib.request"), 282 MovedAttribute("URLopener", "urllib", "urllib.request"), 283 MovedAttribute("FancyURLopener", "urllib", "urllib.request"), 284] 285for attr in _urllib_request_moved_attributes: 286 setattr(Module_six_moves_urllib_request, attr.name, attr) 287del attr 288 289sys.modules[__name__ + ".moves.urllib_request"] = Module_six_moves_urllib_request(__name__ + ".moves.urllib_request") 290sys.modules[__name__ + ".moves.urllib.request"] = Module_six_moves_urllib_request(__name__ + ".moves.urllib.request") 291 292 293class Module_six_moves_urllib_response(types.ModuleType): 294 """Lazy loading of moved objects in six.moves.urllib_response""" 295 296 297_urllib_response_moved_attributes = [ 298 MovedAttribute("addbase", "urllib", "urllib.response"), 299 MovedAttribute("addclosehook", "urllib", "urllib.response"), 300 MovedAttribute("addinfo", "urllib", "urllib.response"), 301 MovedAttribute("addinfourl", "urllib", "urllib.response"), 302] 303for attr in _urllib_response_moved_attributes: 304 setattr(Module_six_moves_urllib_response, attr.name, attr) 305del attr 306 307sys.modules[__name__ + ".moves.urllib_response"] = Module_six_moves_urllib_response(__name__ + ".moves.urllib_response") 308sys.modules[__name__ + ".moves.urllib.response"] = Module_six_moves_urllib_response(__name__ + ".moves.urllib.response") 309 310 311class Module_six_moves_urllib_robotparser(types.ModuleType): 312 """Lazy loading of moved objects in six.moves.urllib_robotparser""" 313 314 315_urllib_robotparser_moved_attributes = [ 316 MovedAttribute("RobotFileParser", "robotparser", "urllib.robotparser"), 317] 318for attr in _urllib_robotparser_moved_attributes: 319 setattr(Module_six_moves_urllib_robotparser, attr.name, attr) 320del attr 321 322sys.modules[__name__ + ".moves.urllib_robotparser"] = Module_six_moves_urllib_robotparser(__name__ + ".moves.urllib_robotparser") 323sys.modules[__name__ + ".moves.urllib.robotparser"] = Module_six_moves_urllib_robotparser(__name__ + ".moves.urllib.robotparser") 324 325 326class Module_six_moves_urllib(types.ModuleType): 327 """Create a six.moves.urllib namespace that resembles the Python 3 namespace""" 328 parse = sys.modules[__name__ + ".moves.urllib_parse"] 329 error = sys.modules[__name__ + ".moves.urllib_error"] 330 request = sys.modules[__name__ + ".moves.urllib_request"] 331 response = sys.modules[__name__ + ".moves.urllib_response"] 332 robotparser = sys.modules[__name__ + ".moves.urllib_robotparser"] 333 334 335sys.modules[__name__ + ".moves.urllib"] = Module_six_moves_urllib(__name__ + ".moves.urllib") 336 337 338def add_move(move): 339 """Add an item to six.moves.""" 340 setattr(_MovedItems, move.name, move) 341 342 343def remove_move(name): 344 """Remove item from six.moves.""" 345 try: 346 delattr(_MovedItems, name) 347 except AttributeError: 348 try: 349 del moves.__dict__[name] 350 except KeyError: 351 raise AttributeError("no such move, %r" % (name,)) 352 353 354if PY3: 355 _meth_func = "__func__" 356 _meth_self = "__self__" 357 358 _func_closure = "__closure__" 359 _func_code = "__code__" 360 _func_defaults = "__defaults__" 361 _func_globals = "__globals__" 362 363 _iterkeys = "keys" 364 _itervalues = "values" 365 _iteritems = "items" 366 _iterlists = "lists" 367else: 368 _meth_func = "im_func" 369 _meth_self = "im_self" 370 371 _func_closure = "func_closure" 372 _func_code = "func_code" 373 _func_defaults = "func_defaults" 374 _func_globals = "func_globals" 375 376 _iterkeys = "iterkeys" 377 _itervalues = "itervalues" 378 _iteritems = "iteritems" 379 _iterlists = "iterlists" 380 381 382try: 383 advance_iterator = next 384except NameError: 385 def advance_iterator(it): 386 return it.next() 387next = advance_iterator 388 389 390try: 391 callable = callable 392except NameError: 393 def callable(obj): 394 return any("__call__" in klass.__dict__ for klass in type(obj).__mro__) 395 396 397if PY3: 398 def get_unbound_function(unbound): 399 return unbound 400 401 create_bound_method = types.MethodType 402 403 Iterator = object 404else: 405 def get_unbound_function(unbound): 406 return unbound.im_func 407 408 def create_bound_method(func, obj): 409 return types.MethodType(func, obj, obj.__class__) 410 411 class Iterator(object): 412 413 def next(self): 414 return type(self).__next__(self) 415 416 callable = callable 417_add_doc(get_unbound_function, 418 """Get the function out of a possibly unbound function""") 419 420 421get_method_function = operator.attrgetter(_meth_func) 422get_method_self = operator.attrgetter(_meth_self) 423get_function_closure = operator.attrgetter(_func_closure) 424get_function_code = operator.attrgetter(_func_code) 425get_function_defaults = operator.attrgetter(_func_defaults) 426get_function_globals = operator.attrgetter(_func_globals) 427 428 429def iterkeys(d, **kw): 430 """Return an iterator over the keys of a dictionary.""" 431 return iter(getattr(d, _iterkeys)(**kw)) 432 433def itervalues(d, **kw): 434 """Return an iterator over the values of a dictionary.""" 435 return iter(getattr(d, _itervalues)(**kw)) 436 437def iteritems(d, **kw): 438 """Return an iterator over the (key, value) pairs of a dictionary.""" 439 return iter(getattr(d, _iteritems)(**kw)) 440 441def iterlists(d, **kw): 442 """Return an iterator over the (key, [values]) pairs of a dictionary.""" 443 return iter(getattr(d, _iterlists)(**kw)) 444 445 446if PY3: 447 def b(s): 448 return s.encode("latin-1") 449 def u(s): 450 return s 451 unichr = chr 452 if sys.version_info[1] <= 1: 453 def int2byte(i): 454 return bytes((i,)) 455 else: 456 # This is about 2x faster than the implementation above on 3.2+ 457 int2byte = operator.methodcaller("to_bytes", 1, "big") 458 byte2int = operator.itemgetter(0) 459 indexbytes = operator.getitem 460 iterbytes = iter 461 import io 462 StringIO = io.StringIO 463 BytesIO = io.BytesIO 464else: 465 def b(s): 466 return s 467 def u(s): 468 return unicode(s, "unicode_escape") 469 unichr = unichr 470 int2byte = chr 471 def byte2int(bs): 472 return ord(bs[0]) 473 def indexbytes(buf, i): 474 return ord(buf[i]) 475 def iterbytes(buf): 476 return (ord(byte) for byte in buf) 477 import StringIO 478 StringIO = BytesIO = StringIO.StringIO 479_add_doc(b, """Byte literal""") 480_add_doc(u, """Text literal""") 481 482 483if PY3: 484 import builtins 485 exec_ = getattr(builtins, "exec") 486 487 488 def reraise(tp, value, tb=None): 489 if value.__traceback__ is not tb: 490 raise value.with_traceback(tb) 491 raise value 492 493 494 print_ = getattr(builtins, "print") 495 del builtins 496 497else: 498 def exec_(_code_, _globs_=None, _locs_=None): 499 """Execute code in a namespace.""" 500 if _globs_ is None: 501 frame = sys._getframe(1) 502 _globs_ = frame.f_globals 503 if _locs_ is None: 504 _locs_ = frame.f_locals 505 del frame 506 elif _locs_ is None: 507 _locs_ = _globs_ 508 exec("""exec _code_ in _globs_, _locs_""") 509 510 511 exec_("""def reraise(tp, value, tb=None): 512 raise tp, value, tb 513""") 514 515 516 def print_(*args, **kwargs): 517 """The new-style print function.""" 518 fp = kwargs.pop("file", sys.stdout) 519 if fp is None: 520 return 521 def write(data): 522 if not isinstance(data, basestring): 523 data = str(data) 524 fp.write(data) 525 want_unicode = False 526 sep = kwargs.pop("sep", None) 527 if sep is not None: 528 if isinstance(sep, unicode): 529 want_unicode = True 530 elif not isinstance(sep, str): 531 raise TypeError("sep must be None or a string") 532 end = kwargs.pop("end", None) 533 if end is not None: 534 if isinstance(end, unicode): 535 want_unicode = True 536 elif not isinstance(end, str): 537 raise TypeError("end must be None or a string") 538 if kwargs: 539 raise TypeError("invalid keyword arguments to print()") 540 if not want_unicode: 541 for arg in args: 542 if isinstance(arg, unicode): 543 want_unicode = True 544 break 545 if want_unicode: 546 newline = unicode("\n") 547 space = unicode(" ") 548 else: 549 newline = "\n" 550 space = " " 551 if sep is None: 552 sep = space 553 if end is None: 554 end = newline 555 for i, arg in enumerate(args): 556 if i: 557 write(sep) 558 write(arg) 559 write(end) 560 561_add_doc(reraise, """Reraise an exception.""") 562 563 564def with_metaclass(meta, *bases): 565 """Create a base class with a metaclass.""" 566 return meta("NewBase", bases, {}) 567 568def add_metaclass(metaclass): 569 """Class decorator for creating a class with a metaclass.""" 570 def wrapper(cls): 571 orig_vars = cls.__dict__.copy() 572 orig_vars.pop('__dict__', None) 573 orig_vars.pop('__weakref__', None) 574 for slots_var in orig_vars.get('__slots__', ()): 575 orig_vars.pop(slots_var) 576 return metaclass(cls.__name__, cls.__bases__, orig_vars) 577 return wrapper 578 579def getexcobj(): 580 return sys.exc_info()[1] 581 582if PY3: 583 xrange = range 584else: 585 xrange = xrange 586 587if PY3: 588 def keys(dictObj): 589 return list(dictObj.keys()) 590 def values(dictObj): 591 return list(dictObj.values()) 592 def nextiter(container): 593 return next(container) 594else: 595 def keys(dictObj): 596 return dictObj.keys() 597 def values(dictObj): 598 return dictObj.values() 599 def nextiter(container): 600 return container.next() 601 602if PY3: 603 def isstring(obj): 604 return isinstance(obj, str) 605else: 606 def isstring(obj): 607 return isinstance(obj, (str, unicode)) 608 609