1"""Utilities for writing code that runs on Python 2 and 3""" 2 3# Copyright (c) 2010-2012 Benjamin Peterson 4# 5# Permission is hereby granted, free of charge, to any person obtaining a copy of 6# this software and associated documentation files (the "Software"), to deal in 7# the Software without restriction, including without limitation the rights to 8# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9# the Software, and to permit persons to whom the Software is furnished to do so, 10# 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, FITNESS 17# FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 22import operator 23import sys 24import types 25 26__author__ = "Benjamin Peterson <benjamin@python.org>" 27__version__ = "1.2.0" 28 29 30PY2 = sys.version_info[0] == 2 31 32# True if we are running on Python 3. 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("input", "__builtin__", "builtins", "raw_input", "input"), 142 MovedAttribute("map", "itertools", "builtins", "imap", "map"), 143 MovedAttribute("reload_module", "__builtin__", "imp", "reload"), 144 MovedAttribute("reduce", "__builtin__", "functools"), 145 MovedAttribute("StringIO", "StringIO", "io"), 146 MovedAttribute("xrange", "__builtin__", "builtins", "xrange", "range"), 147 MovedAttribute("zip", "itertools", "builtins", "izip", "zip"), 148 149 MovedModule("builtins", "__builtin__"), 150 MovedModule("configparser", "ConfigParser"), 151 MovedModule("copyreg", "copy_reg"), 152 MovedModule("http_cookiejar", "cookielib", "http.cookiejar"), 153 MovedModule("http_cookies", "Cookie", "http.cookies"), 154 MovedModule("html_entities", "htmlentitydefs", "html.entities"), 155 MovedModule("html_parser", "HTMLParser", "html.parser"), 156 MovedModule("http_client", "httplib", "http.client"), 157 MovedModule("email_mime_multipart", "email.MIMEMultipart", "email.mime.multipart"), 158 MovedModule("email_mime_text", "email.MIMEText", "email.mime.text"), 159 MovedModule("email_mime_base", "email.MIMEBase", "email.mime.base"), 160 MovedModule("BaseHTTPServer", "BaseHTTPServer", "http.server"), 161 MovedModule("CGIHTTPServer", "CGIHTTPServer", "http.server"), 162 MovedModule("SimpleHTTPServer", "SimpleHTTPServer", "http.server"), 163 MovedModule("cPickle", "cPickle", "pickle"), 164 MovedModule("queue", "Queue"), 165 MovedModule("reprlib", "repr"), 166 MovedModule("socketserver", "SocketServer"), 167 MovedModule("tkinter", "Tkinter"), 168 MovedModule("tkinter_dialog", "Dialog", "tkinter.dialog"), 169 MovedModule("tkinter_filedialog", "FileDialog", "tkinter.filedialog"), 170 MovedModule("tkinter_scrolledtext", "ScrolledText", "tkinter.scrolledtext"), 171 MovedModule("tkinter_simpledialog", "SimpleDialog", "tkinter.simpledialog"), 172 MovedModule("tkinter_tix", "Tix", "tkinter.tix"), 173 MovedModule("tkinter_constants", "Tkconstants", "tkinter.constants"), 174 MovedModule("tkinter_dnd", "Tkdnd", "tkinter.dnd"), 175 MovedModule("tkinter_colorchooser", "tkColorChooser", 176 "tkinter.colorchooser"), 177 MovedModule("tkinter_commondialog", "tkCommonDialog", 178 "tkinter.commondialog"), 179 MovedModule("tkinter_tkfiledialog", "tkFileDialog", "tkinter.filedialog"), 180 MovedModule("tkinter_font", "tkFont", "tkinter.font"), 181 MovedModule("tkinter_messagebox", "tkMessageBox", "tkinter.messagebox"), 182 MovedModule("tkinter_tksimpledialog", "tkSimpleDialog", 183 "tkinter.simpledialog"), 184 MovedModule("urllib_robotparser", "robotparser", "urllib.robotparser"), 185 MovedModule("winreg", "_winreg"), 186] 187for attr in _moved_attributes: 188 setattr(_MovedItems, attr.name, attr) 189del attr 190 191moves = sys.modules[__name__ + ".moves"] = _MovedItems("moves") 192 193 194def add_move(move): 195 """Add an item to six.moves.""" 196 setattr(_MovedItems, move.name, move) 197 198 199def remove_move(name): 200 """Remove item from six.moves.""" 201 try: 202 delattr(_MovedItems, name) 203 except AttributeError: 204 try: 205 del moves.__dict__[name] 206 except KeyError: 207 raise AttributeError("no such move, %r" % (name,)) 208 209 210if PY3: 211 _meth_func = "__func__" 212 _meth_self = "__self__" 213 214 _func_code = "__code__" 215 _func_defaults = "__defaults__" 216 217 _iterkeys = "keys" 218 _itervalues = "values" 219 _iteritems = "items" 220else: 221 _meth_func = "im_func" 222 _meth_self = "im_self" 223 224 _func_code = "func_code" 225 _func_defaults = "func_defaults" 226 227 _iterkeys = "iterkeys" 228 _itervalues = "itervalues" 229 _iteritems = "iteritems" 230 231 232try: 233 advance_iterator = next 234except NameError: 235 def advance_iterator(it): 236 return it.next() 237next = advance_iterator 238 239 240try: 241 callable = callable 242except NameError: 243 def callable(obj): 244 return any("__call__" in klass.__dict__ for klass in type(obj).__mro__) 245 246 247if PY3: 248 def get_unbound_function(unbound): 249 return unbound 250 251 Iterator = object 252else: 253 def get_unbound_function(unbound): 254 return unbound.im_func 255 256 class Iterator(object): 257 258 def next(self): 259 return type(self).__next__(self) 260 261 callable = callable 262_add_doc(get_unbound_function, 263 """Get the function out of a possibly unbound function""") 264 265 266get_method_function = operator.attrgetter(_meth_func) 267get_method_self = operator.attrgetter(_meth_self) 268get_function_code = operator.attrgetter(_func_code) 269get_function_defaults = operator.attrgetter(_func_defaults) 270 271 272def iterkeys(d): 273 """Return an iterator over the keys of a dictionary.""" 274 return iter(getattr(d, _iterkeys)()) 275 276def itervalues(d): 277 """Return an iterator over the values of a dictionary.""" 278 return iter(getattr(d, _itervalues)()) 279 280def iteritems(d): 281 """Return an iterator over the (key, value) pairs of a dictionary.""" 282 return iter(getattr(d, _iteritems)()) 283 284 285if PY3: 286 def b(s): 287 return s.encode("latin-1") 288 def u(s): 289 return s 290 if sys.version_info[1] <= 1: 291 def int2byte(i): 292 return bytes((i,)) 293 else: 294 # This is about 2x faster than the implementation above on 3.2+ 295 int2byte = operator.methodcaller("to_bytes", 1, "big") 296 import io 297 StringIO = io.StringIO 298 BytesIO = io.BytesIO 299else: 300 def b(s): 301 return s 302 def u(s): 303 return unicode(s, "unicode_escape") 304 int2byte = chr 305 import StringIO 306 StringIO = BytesIO = StringIO.StringIO 307_add_doc(b, """Byte literal""") 308_add_doc(u, """Text literal""") 309 310 311if PY3: 312 import builtins 313 exec_ = getattr(builtins, "exec") 314 315 316 def reraise(tp, value, tb=None): 317 if value.__traceback__ is not tb: 318 raise value.with_traceback(tb) 319 raise value 320 321 322 print_ = getattr(builtins, "print") 323 del builtins 324 325else: 326 def exec_(_code_, _globs_=None, _locs_=None): 327 """Execute code in a namespace.""" 328 if _globs_ is None: 329 frame = sys._getframe(1) 330 _globs_ = frame.f_globals 331 if _locs_ is None: 332 _locs_ = frame.f_locals 333 del frame 334 elif _locs_ is None: 335 _locs_ = _globs_ 336 exec("""exec _code_ in _globs_, _locs_""") 337 338 339 exec_("""def reraise(tp, value, tb=None): 340 raise tp, value, tb 341""") 342 343 344 def print_(*args, **kwargs): 345 """The new-style print function.""" 346 fp = kwargs.pop("file", sys.stdout) 347 if fp is None: 348 return 349 def write(data): 350 if not isinstance(data, basestring): 351 data = str(data) 352 fp.write(data) 353 want_unicode = False 354 sep = kwargs.pop("sep", None) 355 if sep is not None: 356 if isinstance(sep, unicode): 357 want_unicode = True 358 elif not isinstance(sep, str): 359 raise TypeError("sep must be None or a string") 360 end = kwargs.pop("end", None) 361 if end is not None: 362 if isinstance(end, unicode): 363 want_unicode = True 364 elif not isinstance(end, str): 365 raise TypeError("end must be None or a string") 366 if kwargs: 367 raise TypeError("invalid keyword arguments to print()") 368 if not want_unicode: 369 for arg in args: 370 if isinstance(arg, unicode): 371 want_unicode = True 372 break 373 if want_unicode: 374 newline = unicode("\n") 375 space = unicode(" ") 376 else: 377 newline = "\n" 378 space = " " 379 if sep is None: 380 sep = space 381 if end is None: 382 end = newline 383 for i, arg in enumerate(args): 384 if i: 385 write(sep) 386 write(arg) 387 write(end) 388 389_add_doc(reraise, """Reraise an exception.""") 390 391 392def with_metaclass(meta, base=object): 393 """Create a base class with a metaclass.""" 394 return meta("NewBase", (base,), {}) 395