1"""Utilities for writing code that runs on Python 2 and 3""" 2 3# Copyright (c) 2010-2014 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.6.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 try: 87 result = self._resolve() 88 except ImportError: 89 # See the nice big comment in MovedModule.__getattr__. 90 raise AttributeError("%s could not be imported " % self.name) 91 setattr(obj, self.name, result) # Invokes __set__. 92 # This is a bit ugly, but it avoids running this again. 93 delattr(obj.__class__, self.name) 94 return result 95 96 97class MovedModule(_LazyDescr): 98 99 def __init__(self, name, old, new=None): 100 super(MovedModule, self).__init__(name) 101 if PY3: 102 if new is None: 103 new = name 104 self.mod = new 105 else: 106 self.mod = old 107 108 def _resolve(self): 109 return _import_module(self.mod) 110 111 def __getattr__(self, attr): 112 # It turns out many Python frameworks like to traverse sys.modules and 113 # try to load various attributes. This causes problems if this is a 114 # platform-specific module on the wrong platform, like _winreg on 115 # Unixes. Therefore, we silently pretend unimportable modules do not 116 # have any attributes. See issues #51, #53, #56, and #63 for the full 117 # tales of woe. 118 # 119 # First, if possible, avoid loading the module just to look at __file__, 120 # __name__, or __path__. 121 if (attr in ("__file__", "__name__", "__path__") and 122 self.mod not in sys.modules): 123 raise AttributeError(attr) 124 try: 125 _module = self._resolve() 126 except ImportError: 127 raise AttributeError(attr) 128 value = getattr(_module, attr) 129 setattr(self, attr, value) 130 return value 131 132 133class _LazyModule(types.ModuleType): 134 135 def __init__(self, name): 136 super(_LazyModule, self).__init__(name) 137 self.__doc__ = self.__class__.__doc__ 138 139 def __dir__(self): 140 attrs = ["__doc__", "__name__"] 141 attrs += [attr.name for attr in self._moved_attributes] 142 return attrs 143 144 # Subclasses should override this 145 _moved_attributes = [] 146 147 148class MovedAttribute(_LazyDescr): 149 150 def __init__(self, name, old_mod, new_mod, old_attr=None, new_attr=None): 151 super(MovedAttribute, self).__init__(name) 152 if PY3: 153 if new_mod is None: 154 new_mod = name 155 self.mod = new_mod 156 if new_attr is None: 157 if old_attr is None: 158 new_attr = name 159 else: 160 new_attr = old_attr 161 self.attr = new_attr 162 else: 163 self.mod = old_mod 164 if old_attr is None: 165 old_attr = name 166 self.attr = old_attr 167 168 def _resolve(self): 169 module = _import_module(self.mod) 170 return getattr(module, self.attr) 171 172 173 174class _MovedItems(_LazyModule): 175 """Lazy loading of moved objects""" 176 177 178_moved_attributes = [ 179 MovedAttribute("cStringIO", "cStringIO", "io", "StringIO"), 180 MovedAttribute("filter", "itertools", "builtins", "ifilter", "filter"), 181 MovedAttribute("filterfalse", "itertools", "itertools", "ifilterfalse", "filterfalse"), 182 MovedAttribute("input", "__builtin__", "builtins", "raw_input", "input"), 183 MovedAttribute("map", "itertools", "builtins", "imap", "map"), 184 MovedAttribute("range", "__builtin__", "builtins", "xrange", "range"), 185 MovedAttribute("reload_module", "__builtin__", "imp", "reload"), 186 MovedAttribute("reduce", "__builtin__", "functools"), 187 MovedAttribute("StringIO", "StringIO", "io"), 188 MovedAttribute("UserString", "UserString", "collections"), 189 MovedAttribute("xrange", "__builtin__", "builtins", "xrange", "range"), 190 MovedAttribute("zip", "itertools", "builtins", "izip", "zip"), 191 MovedAttribute("zip_longest", "itertools", "itertools", "izip_longest", "zip_longest"), 192 193 MovedModule("builtins", "__builtin__"), 194 MovedModule("configparser", "ConfigParser"), 195 MovedModule("copyreg", "copy_reg"), 196 MovedModule("dbm_gnu", "gdbm", "dbm.gnu"), 197 MovedModule("http_cookiejar", "cookielib", "http.cookiejar"), 198 MovedModule("http_cookies", "Cookie", "http.cookies"), 199 MovedModule("html_entities", "htmlentitydefs", "html.entities"), 200 MovedModule("html_parser", "HTMLParser", "html.parser"), 201 MovedModule("http_client", "httplib", "http.client"), 202 MovedModule("email_mime_multipart", "email.MIMEMultipart", "email.mime.multipart"), 203 MovedModule("email_mime_text", "email.MIMEText", "email.mime.text"), 204 MovedModule("email_mime_base", "email.MIMEBase", "email.mime.base"), 205 MovedModule("BaseHTTPServer", "BaseHTTPServer", "http.server"), 206 MovedModule("CGIHTTPServer", "CGIHTTPServer", "http.server"), 207 MovedModule("SimpleHTTPServer", "SimpleHTTPServer", "http.server"), 208 MovedModule("cPickle", "cPickle", "pickle"), 209 MovedModule("queue", "Queue"), 210 MovedModule("reprlib", "repr"), 211 MovedModule("socketserver", "SocketServer"), 212 MovedModule("_thread", "thread", "_thread"), 213 MovedModule("tkinter", "Tkinter"), 214 MovedModule("tkinter_dialog", "Dialog", "tkinter.dialog"), 215 MovedModule("tkinter_filedialog", "FileDialog", "tkinter.filedialog"), 216 MovedModule("tkinter_scrolledtext", "ScrolledText", "tkinter.scrolledtext"), 217 MovedModule("tkinter_simpledialog", "SimpleDialog", "tkinter.simpledialog"), 218 MovedModule("tkinter_tix", "Tix", "tkinter.tix"), 219 MovedModule("tkinter_ttk", "ttk", "tkinter.ttk"), 220 MovedModule("tkinter_constants", "Tkconstants", "tkinter.constants"), 221 MovedModule("tkinter_dnd", "Tkdnd", "tkinter.dnd"), 222 MovedModule("tkinter_colorchooser", "tkColorChooser", 223 "tkinter.colorchooser"), 224 MovedModule("tkinter_commondialog", "tkCommonDialog", 225 "tkinter.commondialog"), 226 MovedModule("tkinter_tkfiledialog", "tkFileDialog", "tkinter.filedialog"), 227 MovedModule("tkinter_font", "tkFont", "tkinter.font"), 228 MovedModule("tkinter_messagebox", "tkMessageBox", "tkinter.messagebox"), 229 MovedModule("tkinter_tksimpledialog", "tkSimpleDialog", 230 "tkinter.simpledialog"), 231 MovedModule("urllib_parse", __name__ + ".moves.urllib_parse", "urllib.parse"), 232 MovedModule("urllib_error", __name__ + ".moves.urllib_error", "urllib.error"), 233 MovedModule("urllib", __name__ + ".moves.urllib", __name__ + ".moves.urllib"), 234 MovedModule("urllib_robotparser", "robotparser", "urllib.robotparser"), 235 MovedModule("xmlrpc_client", "xmlrpclib", "xmlrpc.client"), 236 MovedModule("xmlrpc_server", "xmlrpclib", "xmlrpc.server"), 237 MovedModule("winreg", "_winreg"), 238] 239for attr in _moved_attributes: 240 setattr(_MovedItems, attr.name, attr) 241 if isinstance(attr, MovedModule): 242 sys.modules[__name__ + ".moves." + attr.name] = attr 243del attr 244 245_MovedItems._moved_attributes = _moved_attributes 246 247moves = sys.modules[__name__ + ".moves"] = _MovedItems(__name__ + ".moves") 248 249 250class Module_six_moves_urllib_parse(_LazyModule): 251 """Lazy loading of moved objects in six.moves.urllib_parse""" 252 253 254_urllib_parse_moved_attributes = [ 255 MovedAttribute("ParseResult", "urlparse", "urllib.parse"), 256 MovedAttribute("SplitResult", "urlparse", "urllib.parse"), 257 MovedAttribute("parse_qs", "urlparse", "urllib.parse"), 258 MovedAttribute("parse_qsl", "urlparse", "urllib.parse"), 259 MovedAttribute("urldefrag", "urlparse", "urllib.parse"), 260 MovedAttribute("urljoin", "urlparse", "urllib.parse"), 261 MovedAttribute("urlparse", "urlparse", "urllib.parse"), 262 MovedAttribute("urlsplit", "urlparse", "urllib.parse"), 263 MovedAttribute("urlunparse", "urlparse", "urllib.parse"), 264 MovedAttribute("urlunsplit", "urlparse", "urllib.parse"), 265 MovedAttribute("quote", "urllib", "urllib.parse"), 266 MovedAttribute("quote_plus", "urllib", "urllib.parse"), 267 MovedAttribute("unquote", "urllib", "urllib.parse"), 268 MovedAttribute("unquote_plus", "urllib", "urllib.parse"), 269 MovedAttribute("urlencode", "urllib", "urllib.parse"), 270 MovedAttribute("splitquery", "urllib", "urllib.parse"), 271] 272for attr in _urllib_parse_moved_attributes: 273 setattr(Module_six_moves_urllib_parse, attr.name, attr) 274del attr 275 276Module_six_moves_urllib_parse._moved_attributes = _urllib_parse_moved_attributes 277 278sys.modules[__name__ + ".moves.urllib_parse"] = sys.modules[__name__ + ".moves.urllib.parse"] = Module_six_moves_urllib_parse(__name__ + ".moves.urllib_parse") 279 280 281class Module_six_moves_urllib_error(_LazyModule): 282 """Lazy loading of moved objects in six.moves.urllib_error""" 283 284 285_urllib_error_moved_attributes = [ 286 MovedAttribute("URLError", "urllib2", "urllib.error"), 287 MovedAttribute("HTTPError", "urllib2", "urllib.error"), 288 MovedAttribute("ContentTooShortError", "urllib", "urllib.error"), 289] 290for attr in _urllib_error_moved_attributes: 291 setattr(Module_six_moves_urllib_error, attr.name, attr) 292del attr 293 294Module_six_moves_urllib_error._moved_attributes = _urllib_error_moved_attributes 295 296sys.modules[__name__ + ".moves.urllib_error"] = sys.modules[__name__ + ".moves.urllib.error"] = Module_six_moves_urllib_error(__name__ + ".moves.urllib.error") 297 298 299class Module_six_moves_urllib_request(_LazyModule): 300 """Lazy loading of moved objects in six.moves.urllib_request""" 301 302 303_urllib_request_moved_attributes = [ 304 MovedAttribute("urlopen", "urllib2", "urllib.request"), 305 MovedAttribute("install_opener", "urllib2", "urllib.request"), 306 MovedAttribute("build_opener", "urllib2", "urllib.request"), 307 MovedAttribute("pathname2url", "urllib", "urllib.request"), 308 MovedAttribute("url2pathname", "urllib", "urllib.request"), 309 MovedAttribute("getproxies", "urllib", "urllib.request"), 310 MovedAttribute("Request", "urllib2", "urllib.request"), 311 MovedAttribute("OpenerDirector", "urllib2", "urllib.request"), 312 MovedAttribute("HTTPDefaultErrorHandler", "urllib2", "urllib.request"), 313 MovedAttribute("HTTPRedirectHandler", "urllib2", "urllib.request"), 314 MovedAttribute("HTTPCookieProcessor", "urllib2", "urllib.request"), 315 MovedAttribute("ProxyHandler", "urllib2", "urllib.request"), 316 MovedAttribute("BaseHandler", "urllib2", "urllib.request"), 317 MovedAttribute("HTTPPasswordMgr", "urllib2", "urllib.request"), 318 MovedAttribute("HTTPPasswordMgrWithDefaultRealm", "urllib2", "urllib.request"), 319 MovedAttribute("AbstractBasicAuthHandler", "urllib2", "urllib.request"), 320 MovedAttribute("HTTPBasicAuthHandler", "urllib2", "urllib.request"), 321 MovedAttribute("ProxyBasicAuthHandler", "urllib2", "urllib.request"), 322 MovedAttribute("AbstractDigestAuthHandler", "urllib2", "urllib.request"), 323 MovedAttribute("HTTPDigestAuthHandler", "urllib2", "urllib.request"), 324 MovedAttribute("ProxyDigestAuthHandler", "urllib2", "urllib.request"), 325 MovedAttribute("HTTPHandler", "urllib2", "urllib.request"), 326 MovedAttribute("HTTPSHandler", "urllib2", "urllib.request"), 327 MovedAttribute("FileHandler", "urllib2", "urllib.request"), 328 MovedAttribute("FTPHandler", "urllib2", "urllib.request"), 329 MovedAttribute("CacheFTPHandler", "urllib2", "urllib.request"), 330 MovedAttribute("UnknownHandler", "urllib2", "urllib.request"), 331 MovedAttribute("HTTPErrorProcessor", "urllib2", "urllib.request"), 332 MovedAttribute("urlretrieve", "urllib", "urllib.request"), 333 MovedAttribute("urlcleanup", "urllib", "urllib.request"), 334 MovedAttribute("URLopener", "urllib", "urllib.request"), 335 MovedAttribute("FancyURLopener", "urllib", "urllib.request"), 336 MovedAttribute("proxy_bypass", "urllib", "urllib.request"), 337] 338for attr in _urllib_request_moved_attributes: 339 setattr(Module_six_moves_urllib_request, attr.name, attr) 340del attr 341 342Module_six_moves_urllib_request._moved_attributes = _urllib_request_moved_attributes 343 344sys.modules[__name__ + ".moves.urllib_request"] = sys.modules[__name__ + ".moves.urllib.request"] = Module_six_moves_urllib_request(__name__ + ".moves.urllib.request") 345 346 347class Module_six_moves_urllib_response(_LazyModule): 348 """Lazy loading of moved objects in six.moves.urllib_response""" 349 350 351_urllib_response_moved_attributes = [ 352 MovedAttribute("addbase", "urllib", "urllib.response"), 353 MovedAttribute("addclosehook", "urllib", "urllib.response"), 354 MovedAttribute("addinfo", "urllib", "urllib.response"), 355 MovedAttribute("addinfourl", "urllib", "urllib.response"), 356] 357for attr in _urllib_response_moved_attributes: 358 setattr(Module_six_moves_urllib_response, attr.name, attr) 359del attr 360 361Module_six_moves_urllib_response._moved_attributes = _urllib_response_moved_attributes 362 363sys.modules[__name__ + ".moves.urllib_response"] = sys.modules[__name__ + ".moves.urllib.response"] = Module_six_moves_urllib_response(__name__ + ".moves.urllib.response") 364 365 366class Module_six_moves_urllib_robotparser(_LazyModule): 367 """Lazy loading of moved objects in six.moves.urllib_robotparser""" 368 369 370_urllib_robotparser_moved_attributes = [ 371 MovedAttribute("RobotFileParser", "robotparser", "urllib.robotparser"), 372] 373for attr in _urllib_robotparser_moved_attributes: 374 setattr(Module_six_moves_urllib_robotparser, attr.name, attr) 375del attr 376 377Module_six_moves_urllib_robotparser._moved_attributes = _urllib_robotparser_moved_attributes 378 379sys.modules[__name__ + ".moves.urllib_robotparser"] = sys.modules[__name__ + ".moves.urllib.robotparser"] = Module_six_moves_urllib_robotparser(__name__ + ".moves.urllib.robotparser") 380 381 382class Module_six_moves_urllib(types.ModuleType): 383 """Create a six.moves.urllib namespace that resembles the Python 3 namespace""" 384 parse = sys.modules[__name__ + ".moves.urllib_parse"] 385 error = sys.modules[__name__ + ".moves.urllib_error"] 386 request = sys.modules[__name__ + ".moves.urllib_request"] 387 response = sys.modules[__name__ + ".moves.urllib_response"] 388 robotparser = sys.modules[__name__ + ".moves.urllib_robotparser"] 389 390 def __dir__(self): 391 return ['parse', 'error', 'request', 'response', 'robotparser'] 392 393 394sys.modules[__name__ + ".moves.urllib"] = Module_six_moves_urllib(__name__ + ".moves.urllib") 395 396 397def add_move(move): 398 """Add an item to six.moves.""" 399 setattr(_MovedItems, move.name, move) 400 401 402def remove_move(name): 403 """Remove item from six.moves.""" 404 try: 405 delattr(_MovedItems, name) 406 except AttributeError: 407 try: 408 del moves.__dict__[name] 409 except KeyError: 410 raise AttributeError("no such move, %r" % (name,)) 411 412 413if PY3: 414 _meth_func = "__func__" 415 _meth_self = "__self__" 416 417 _func_closure = "__closure__" 418 _func_code = "__code__" 419 _func_defaults = "__defaults__" 420 _func_globals = "__globals__" 421 422 _iterkeys = "keys" 423 _itervalues = "values" 424 _iteritems = "items" 425 _iterlists = "lists" 426else: 427 _meth_func = "im_func" 428 _meth_self = "im_self" 429 430 _func_closure = "func_closure" 431 _func_code = "func_code" 432 _func_defaults = "func_defaults" 433 _func_globals = "func_globals" 434 435 _iterkeys = "iterkeys" 436 _itervalues = "itervalues" 437 _iteritems = "iteritems" 438 _iterlists = "iterlists" 439 440 441try: 442 advance_iterator = next 443except NameError: 444 def advance_iterator(it): 445 return it.next() 446next = advance_iterator 447 448 449try: 450 callable = callable 451except NameError: 452 def callable(obj): 453 return any("__call__" in klass.__dict__ for klass in type(obj).__mro__) 454 455 456if PY3: 457 def get_unbound_function(unbound): 458 return unbound 459 460 create_bound_method = types.MethodType 461 462 Iterator = object 463else: 464 def get_unbound_function(unbound): 465 return unbound.im_func 466 467 def create_bound_method(func, obj): 468 return types.MethodType(func, obj, obj.__class__) 469 470 class Iterator(object): 471 472 def next(self): 473 return type(self).__next__(self) 474 475 callable = callable 476_add_doc(get_unbound_function, 477 """Get the function out of a possibly unbound function""") 478 479 480get_method_function = operator.attrgetter(_meth_func) 481get_method_self = operator.attrgetter(_meth_self) 482get_function_closure = operator.attrgetter(_func_closure) 483get_function_code = operator.attrgetter(_func_code) 484get_function_defaults = operator.attrgetter(_func_defaults) 485get_function_globals = operator.attrgetter(_func_globals) 486 487 488def iterkeys(d, **kw): 489 """Return an iterator over the keys of a dictionary.""" 490 return iter(getattr(d, _iterkeys)(**kw)) 491 492def itervalues(d, **kw): 493 """Return an iterator over the values of a dictionary.""" 494 return iter(getattr(d, _itervalues)(**kw)) 495 496def iteritems(d, **kw): 497 """Return an iterator over the (key, value) pairs of a dictionary.""" 498 return iter(getattr(d, _iteritems)(**kw)) 499 500def iterlists(d, **kw): 501 """Return an iterator over the (key, [values]) pairs of a dictionary.""" 502 return iter(getattr(d, _iterlists)(**kw)) 503 504 505if PY3: 506 def b(s): 507 return s.encode("latin-1") 508 def u(s): 509 return s 510 unichr = chr 511 if sys.version_info[1] <= 1: 512 def int2byte(i): 513 return bytes((i,)) 514 else: 515 # This is about 2x faster than the implementation above on 3.2+ 516 int2byte = operator.methodcaller("to_bytes", 1, "big") 517 byte2int = operator.itemgetter(0) 518 indexbytes = operator.getitem 519 iterbytes = iter 520 import io 521 StringIO = io.StringIO 522 BytesIO = io.BytesIO 523else: 524 def b(s): 525 return s 526 # Workaround for standalone backslash 527 def u(s): 528 return unicode(s.replace(r'\\', r'\\\\'), "unicode_escape") 529 unichr = unichr 530 int2byte = chr 531 def byte2int(bs): 532 return ord(bs[0]) 533 def indexbytes(buf, i): 534 return ord(buf[i]) 535 def iterbytes(buf): 536 return (ord(byte) for byte in buf) 537 import StringIO 538 StringIO = BytesIO = StringIO.StringIO 539_add_doc(b, """Byte literal""") 540_add_doc(u, """Text literal""") 541 542 543if PY3: 544 exec_ = getattr(moves.builtins, "exec") 545 546 547 def reraise(tp, value, tb=None): 548 if value.__traceback__ is not tb: 549 raise value.with_traceback(tb) 550 raise value 551 552else: 553 def exec_(_code_, _globs_=None, _locs_=None): 554 """Execute code in a namespace.""" 555 if _globs_ is None: 556 frame = sys._getframe(1) 557 _globs_ = frame.f_globals 558 if _locs_ is None: 559 _locs_ = frame.f_locals 560 del frame 561 elif _locs_ is None: 562 _locs_ = _globs_ 563 exec("""exec _code_ in _globs_, _locs_""") 564 565 566 exec_("""def reraise(tp, value, tb=None): 567 raise tp, value, tb 568""") 569 570 571print_ = getattr(moves.builtins, "print", None) 572if print_ is None: 573 def print_(*args, **kwargs): 574 """The new-style print function for Python 2.4 and 2.5.""" 575 fp = kwargs.pop("file", sys.stdout) 576 if fp is None: 577 return 578 def write(data): 579 if not isinstance(data, basestring): 580 data = str(data) 581 # If the file has an encoding, encode unicode with it. 582 if (isinstance(fp, file) and 583 isinstance(data, unicode) and 584 fp.encoding is not None): 585 errors = getattr(fp, "errors", None) 586 if errors is None: 587 errors = "strict" 588 data = data.encode(fp.encoding, errors) 589 fp.write(data) 590 want_unicode = False 591 sep = kwargs.pop("sep", None) 592 if sep is not None: 593 if isinstance(sep, unicode): 594 want_unicode = True 595 elif not isinstance(sep, str): 596 raise TypeError("sep must be None or a string") 597 end = kwargs.pop("end", None) 598 if end is not None: 599 if isinstance(end, unicode): 600 want_unicode = True 601 elif not isinstance(end, str): 602 raise TypeError("end must be None or a string") 603 if kwargs: 604 raise TypeError("invalid keyword arguments to print()") 605 if not want_unicode: 606 for arg in args: 607 if isinstance(arg, unicode): 608 want_unicode = True 609 break 610 if want_unicode: 611 newline = unicode("\n") 612 space = unicode(" ") 613 else: 614 newline = "\n" 615 space = " " 616 if sep is None: 617 sep = space 618 if end is None: 619 end = newline 620 for i, arg in enumerate(args): 621 if i: 622 write(sep) 623 write(arg) 624 write(end) 625 626_add_doc(reraise, """Reraise an exception.""") 627 628 629def with_metaclass(meta, *bases): 630 """Create a base class with a metaclass.""" 631 return meta("NewBase", bases, {}) 632 633def add_metaclass(metaclass): 634 """Class decorator for creating a class with a metaclass.""" 635 def wrapper(cls): 636 orig_vars = cls.__dict__.copy() 637 orig_vars.pop('__dict__', None) 638 orig_vars.pop('__weakref__', None) 639 slots = orig_vars.get('__slots__') 640 if slots is not None: 641 if isinstance(slots, str): 642 slots = [slots] 643 for slots_var in slots: 644 orig_vars.pop(slots_var) 645 return metaclass(cls.__name__, cls.__bases__, orig_vars) 646 return wrapper 647