1 """Utilities for writing code that runs on Python 2 and 3"""
3 # Copyright (c) 2010-2014 Benjamin Peterson
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:
12 # The above copyright notice and this permission notice shall be included in all
13 # copies or substantial portions of the Software.
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
27 __author__ = "Benjamin Peterson <benjamin@python.org>"
31 # Useful for very coarse version differentiation.
32 PY2 = sys.version_info[0] == 2
33 PY3 = sys.version_info[0] == 3
44 string_types = basestring,
45 integer_types = (int, long)
46 class_types = (type, types.ClassType)
50 if sys.platform.startswith("java"):
51 # Jython always uses 32 bits.
52 MAXSIZE = int((1 << 31) - 1)
54 # It's possible to have sizeof(long) != sizeof(Py_ssize_t).
62 MAXSIZE = int((1 << 31) - 1)
65 MAXSIZE = int((1 << 63) - 1)
69 def _add_doc(func, doc):
70 """Add documentation to a function."""
74 def _import_module(name):
75 """Import module, returning the module after the last dot."""
77 return sys.modules[name]
80 class _LazyDescr(object):
82 def __init__(self, name):
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)
93 class MovedModule(_LazyDescr):
95 def __init__(self, name, old, new=None):
96 super(MovedModule, self).__init__(name)
105 return _import_module(self.mod)
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
114 if attr in ("__file__", "__name__") and self.mod not in sys.modules:
116 _module = self._resolve()
117 value = getattr(_module, attr)
118 setattr(self, attr, value)
122 class _LazyModule(types.ModuleType):
124 def __init__(self, name):
125 super(_LazyModule, self).__init__(name)
126 self.__doc__ = self.__class__.__doc__
129 attrs = ["__doc__", "__name__"]
130 attrs += [attr.name for attr in self._moved_attributes]
133 # Subclasses should override this
134 _moved_attributes = []
137 class MovedAttribute(_LazyDescr):
139 def __init__(self, name, old_mod, new_mod, old_attr=None, new_attr=None):
140 super(MovedAttribute, self).__init__(name)
158 module = _import_module(self.mod)
159 return getattr(module, self.attr)
162 class _MovedItems(_LazyModule):
163 """Lazy loading of moved objects"""
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"),
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"),
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
233 _MovedItems._moved_attributes = _moved_attributes
235 moves = sys.modules[__name__ + ".moves"] = _MovedItems(__name__ + ".moves")
238 class Module_six_moves_urllib_parse(_LazyModule):
239 """Lazy loading of moved objects in six.moves.urllib_parse"""
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"),
259 for attr in _urllib_parse_moved_attributes:
260 setattr(Module_six_moves_urllib_parse, attr.name, attr)
263 Module_six_moves_urllib_parse._moved_attributes = _urllib_parse_moved_attributes
265 sys.modules[__name__ + ".moves.urllib_parse"] = sys.modules[__name__ + ".moves.urllib.parse"] = Module_six_moves_urllib_parse(__name__ + ".moves.urllib_parse")
268 class Module_six_moves_urllib_error(_LazyModule):
269 """Lazy loading of moved objects in six.moves.urllib_error"""
272 _urllib_error_moved_attributes = [
273 MovedAttribute("URLError", "urllib2", "urllib.error"),
274 MovedAttribute("HTTPError", "urllib2", "urllib.error"),
275 MovedAttribute("ContentTooShortError", "urllib", "urllib.error"),
277 for attr in _urllib_error_moved_attributes:
278 setattr(Module_six_moves_urllib_error, attr.name, attr)
281 Module_six_moves_urllib_error._moved_attributes = _urllib_error_moved_attributes
283 sys.modules[__name__ + ".moves.urllib_error"] = sys.modules[__name__ + ".moves.urllib.error"] = Module_six_moves_urllib_error(__name__ + ".moves.urllib.error")
286 class Module_six_moves_urllib_request(_LazyModule):
287 """Lazy loading of moved objects in six.moves.urllib_request"""
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"),
325 for attr in _urllib_request_moved_attributes:
326 setattr(Module_six_moves_urllib_request, attr.name, attr)
329 Module_six_moves_urllib_request._moved_attributes = _urllib_request_moved_attributes
331 sys.modules[__name__ + ".moves.urllib_request"] = sys.modules[__name__ + ".moves.urllib.request"] = Module_six_moves_urllib_request(__name__ + ".moves.urllib.request")
334 class Module_six_moves_urllib_response(_LazyModule):
335 """Lazy loading of moved objects in six.moves.urllib_response"""
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"),
344 for attr in _urllib_response_moved_attributes:
345 setattr(Module_six_moves_urllib_response, attr.name, attr)
348 Module_six_moves_urllib_response._moved_attributes = _urllib_response_moved_attributes
350 sys.modules[__name__ + ".moves.urllib_response"] = sys.modules[__name__ + ".moves.urllib.response"] = Module_six_moves_urllib_response(__name__ + ".moves.urllib.response")
353 class Module_six_moves_urllib_robotparser(_LazyModule):
354 """Lazy loading of moved objects in six.moves.urllib_robotparser"""
357 _urllib_robotparser_moved_attributes = [
358 MovedAttribute("RobotFileParser", "robotparser", "urllib.robotparser"),
360 for attr in _urllib_robotparser_moved_attributes:
361 setattr(Module_six_moves_urllib_robotparser, attr.name, attr)
364 Module_six_moves_urllib_robotparser._moved_attributes = _urllib_robotparser_moved_attributes
366 sys.modules[__name__ + ".moves.urllib_robotparser"] = sys.modules[__name__ + ".moves.urllib.robotparser"] = Module_six_moves_urllib_robotparser(__name__ + ".moves.urllib.robotparser")
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"]
378 return ['parse', 'error', 'request', 'response', 'robotparser']
381 sys.modules[__name__ + ".moves.urllib"] = Module_six_moves_urllib(__name__ + ".moves.urllib")
385 """Add an item to six.moves."""
386 setattr(_MovedItems, move.name, move)
389 def remove_move(name):
390 """Remove item from six.moves."""
392 delattr(_MovedItems, name)
393 except AttributeError:
395 del moves.__dict__[name]
397 raise AttributeError("no such move, %r" % (name,))
401 _meth_func = "__func__"
402 _meth_self = "__self__"
404 _func_closure = "__closure__"
405 _func_code = "__code__"
406 _func_defaults = "__defaults__"
407 _func_globals = "__globals__"
410 _itervalues = "values"
414 _meth_func = "im_func"
415 _meth_self = "im_self"
417 _func_closure = "func_closure"
418 _func_code = "func_code"
419 _func_defaults = "func_defaults"
420 _func_globals = "func_globals"
422 _iterkeys = "iterkeys"
423 _itervalues = "itervalues"
424 _iteritems = "iteritems"
425 _iterlists = "iterlists"
429 advance_iterator = next
431 def advance_iterator(it):
433 next = advance_iterator
440 return any("__call__" in klass.__dict__ for klass in type(obj).__mro__)
444 def get_unbound_function(unbound):
447 create_bound_method = types.MethodType
451 def get_unbound_function(unbound):
452 return unbound.im_func
454 def create_bound_method(func, obj):
455 return types.MethodType(func, obj, obj.__class__)
457 class Iterator(object):
460 return type(self).__next__(self)
463 _add_doc(get_unbound_function,
464 """Get the function out of a possibly unbound function""")
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)
475 def iterkeys(d, **kw):
476 """Return an iterator over the keys of a dictionary."""
477 return iter(getattr(d, _iterkeys)(**kw))
480 def itervalues(d, **kw):
481 """Return an iterator over the values of a dictionary."""
482 return iter(getattr(d, _itervalues)(**kw))
485 def iteritems(d, **kw):
486 """Return an iterator over the (key, value) pairs of a dictionary."""
487 return iter(getattr(d, _iteritems)(**kw))
490 def iterlists(d, **kw):
491 """Return an iterator over the (key, [values]) pairs of a dictionary."""
492 return iter(getattr(d, _iterlists)(**kw))
497 return s.encode("latin-1")
502 if sys.version_info[1] <= 1:
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
512 StringIO = io.StringIO
517 # Workaround for standalone backslash
520 return unicode(s.replace(r'\\', r'\\\\'), "unicode_escape")
527 def indexbytes(buf, i):
531 return (ord(byte) for byte in buf)
533 StringIO = BytesIO = StringIO.StringIO
534 _add_doc(b, """Byte literal""")
535 _add_doc(u, """Text literal""")
539 exec_ = getattr(moves.builtins, "exec")
541 def reraise(tp, value, tb=None):
542 if value.__traceback__ is not tb:
543 raise value.with_traceback(tb)
547 def exec_(_code_, _globs_=None, _locs_=None):
548 """Execute code in a namespace."""
550 frame = sys._getframe(1)
551 _globs_ = frame.f_globals
553 _locs_ = frame.f_locals
557 exec("""exec _code_ in _globs_, _locs_""")
559 exec_("""def reraise(tp, value, tb=None):
564 print_ = getattr(moves.builtins, "print", 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)
573 if not isinstance(data, basestring):
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)
582 data = data.encode(fp.encoding, errors)
585 sep = kwargs.pop("sep", None)
587 if isinstance(sep, unicode):
589 elif not isinstance(sep, str):
590 raise TypeError("sep must be None or a string")
591 end = kwargs.pop("end", None)
593 if isinstance(end, unicode):
595 elif not isinstance(end, str):
596 raise TypeError("end must be None or a string")
598 raise TypeError("invalid keyword arguments to print()")
601 if isinstance(arg, unicode):
605 newline = unicode("\n")
614 for i, arg in enumerate(args):
620 _add_doc(reraise, """Reraise an exception.""")
623 def with_metaclass(meta, *bases):
624 """Create a base class with a metaclass."""
625 return meta("NewBase", bases, {})
628 def add_metaclass(metaclass):
629 """Class decorator for creating a class with a metaclass."""
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):
638 for slots_var in slots:
639 orig_vars.pop(slots_var)
640 return metaclass(cls.__name__, cls.__bases__, orig_vars)