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__" 421else: 422 _meth_func = "im_func" 423 _meth_self = "im_self" 424 425 _func_closure = "func_closure" 426 _func_code = "func_code" 427 _func_defaults = "func_defaults" 428 _func_globals = "func_globals" 429 430 431try: 432 advance_iterator = next 433except NameError: 434 def advance_iterator(it): 435 return it.next() 436next = advance_iterator 437 438 439try: 440 callable = callable 441except NameError: 442 def callable(obj): 443 return any("__call__" in klass.__dict__ for klass in type(obj).__mro__) 444 445 446if PY3: 447 def get_unbound_function(unbound): 448 return unbound 449 450 create_bound_method = types.MethodType 451 452 Iterator = object 453else: 454 def get_unbound_function(unbound): 455 return unbound.im_func 456 457 def create_bound_method(func, obj): 458 return types.MethodType(func, obj, obj.__class__) 459 460 class Iterator(object): 461 462 def next(self): 463 return type(self).__next__(self) 464 465 callable = callable 466_add_doc(get_unbound_function, 467 """Get the function out of a possibly unbound function""") 468 469 470get_method_function = operator.attrgetter(_meth_func) 471get_method_self = operator.attrgetter(_meth_self) 472get_function_closure = operator.attrgetter(_func_closure) 473get_function_code = operator.attrgetter(_func_code) 474get_function_defaults = operator.attrgetter(_func_defaults) 475get_function_globals = operator.attrgetter(_func_globals) 476 477 478if PY3: 479 def iterkeys(d, **kw): 480 return iter(d.keys(**kw)) 481 482 def itervalues(d, **kw): 483 return iter(d.values(**kw)) 484 485 def iteritems(d, **kw): 486 return iter(d.items(**kw)) 487 488 def iterlists(d, **kw): 489 return iter(d.lists(**kw)) 490else: 491 def iterkeys(d, **kw): 492 return iter(d.iterkeys(**kw)) 493 494 def itervalues(d, **kw): 495 return iter(d.itervalues(**kw)) 496 497 def iteritems(d, **kw): 498 return iter(d.iteritems(**kw)) 499 500 def iterlists(d, **kw): 501 return iter(d.iterlists(**kw)) 502 503_add_doc(iterkeys, "Return an iterator over the keys of a dictionary.") 504_add_doc(itervalues, "Return an iterator over the values of a dictionary.") 505_add_doc(iteritems, 506 "Return an iterator over the (key, value) pairs of a dictionary.") 507_add_doc(iterlists, 508 "Return an iterator over the (key, [values]) pairs of a dictionary.") 509 510 511if PY3: 512 def b(s): 513 return s.encode("latin-1") 514 def u(s): 515 return s 516 unichr = chr 517 if sys.version_info[1] <= 1: 518 def int2byte(i): 519 return bytes((i,)) 520 else: 521 # This is about 2x faster than the implementation above on 3.2+ 522 int2byte = operator.methodcaller("to_bytes", 1, "big") 523 byte2int = operator.itemgetter(0) 524 indexbytes = operator.getitem 525 iterbytes = iter 526 import io 527 StringIO = io.StringIO 528 BytesIO = io.BytesIO 529else: 530 def b(s): 531 return s 532 # Workaround for standalone backslash 533 def u(s): 534 return unicode(s.replace(r'\\', r'\\\\'), "unicode_escape") 535 unichr = unichr 536 int2byte = chr 537 def byte2int(bs): 538 return ord(bs[0]) 539 def indexbytes(buf, i): 540 return ord(buf[i]) 541 def iterbytes(buf): 542 return (ord(byte) for byte in buf) 543 import StringIO 544 StringIO = BytesIO = StringIO.StringIO 545_add_doc(b, """Byte literal""") 546_add_doc(u, """Text literal""") 547 548 549if PY3: 550 exec_ = getattr(moves.builtins, "exec") 551 552 553 def reraise(tp, value, tb=None): 554 if value.__traceback__ is not tb: 555 raise value.with_traceback(tb) 556 raise value 557 558else: 559 def exec_(_code_, _globs_=None, _locs_=None): 560 """Execute code in a namespace.""" 561 if _globs_ is None: 562 frame = sys._getframe(1) 563 _globs_ = frame.f_globals 564 if _locs_ is None: 565 _locs_ = frame.f_locals 566 del frame 567 elif _locs_ is None: 568 _locs_ = _globs_ 569 exec("""exec _code_ in _globs_, _locs_""") 570 571 572 exec_("""def reraise(tp, value, tb=None): 573 raise tp, value, tb 574""") 575 576 577print_ = getattr(moves.builtins, "print", None) 578if print_ is None: 579 def print_(*args, **kwargs): 580 """The new-style print function for Python 2.4 and 2.5.""" 581 fp = kwargs.pop("file", sys.stdout) 582 if fp is None: 583 return 584 def write(data): 585 if not isinstance(data, basestring): 586 data = str(data) 587 # If the file has an encoding, encode unicode with it. 588 if (isinstance(fp, file) and 589 isinstance(data, unicode) and 590 fp.encoding is not None): 591 errors = getattr(fp, "errors", None) 592 if errors is None: 593 errors = "strict" 594 data = data.encode(fp.encoding, errors) 595 fp.write(data) 596 want_unicode = False 597 sep = kwargs.pop("sep", None) 598 if sep is not None: 599 if isinstance(sep, unicode): 600 want_unicode = True 601 elif not isinstance(sep, str): 602 raise TypeError("sep must be None or a string") 603 end = kwargs.pop("end", None) 604 if end is not None: 605 if isinstance(end, unicode): 606 want_unicode = True 607 elif not isinstance(end, str): 608 raise TypeError("end must be None or a string") 609 if kwargs: 610 raise TypeError("invalid keyword arguments to print()") 611 if not want_unicode: 612 for arg in args: 613 if isinstance(arg, unicode): 614 want_unicode = True 615 break 616 if want_unicode: 617 newline = unicode("\n") 618 space = unicode(" ") 619 else: 620 newline = "\n" 621 space = " " 622 if sep is None: 623 sep = space 624 if end is None: 625 end = newline 626 for i, arg in enumerate(args): 627 if i: 628 write(sep) 629 write(arg) 630 write(end) 631 632_add_doc(reraise, """Reraise an exception.""") 633 634 635def with_metaclass(meta, *bases): 636 """Create a base class with a metaclass.""" 637 return meta("NewBase", bases, {}) 638 639def add_metaclass(metaclass): 640 """Class decorator for creating a class with a metaclass.""" 641 def wrapper(cls): 642 orig_vars = cls.__dict__.copy() 643 orig_vars.pop('__dict__', None) 644 orig_vars.pop('__weakref__', None) 645 slots = orig_vars.get('__slots__') 646 if slots is not None: 647 if isinstance(slots, str): 648 slots = [slots] 649 for slots_var in slots: 650 orig_vars.pop(slots_var) 651 return metaclass(cls.__name__, cls.__bases__, orig_vars) 652 return wrapper 653