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