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 30# True if we are running on Python 3. 31PY3 = sys.version_info[0] == 3 32 33if PY3: 34 string_types = str, 35 integer_types = int, 36 class_types = type, 37 text_type = str 38 binary_type = bytes 39 40 MAXSIZE = sys.maxsize 41else: 42 string_types = basestring, 43 integer_types = (int, long) 44 class_types = (type, types.ClassType) 45 text_type = unicode 46 binary_type = str 47 48 if sys.platform.startswith("java"): 49 # Jython always uses 32 bits. 50 MAXSIZE = int((1 << 31) - 1) 51 else: 52 # It's possible to have sizeof(long) != sizeof(Py_ssize_t). 53 class X(object): 54 def __len__(self): 55 return 1 << 31 56 try: 57 len(X()) 58 except OverflowError: 59 # 32-bit 60 MAXSIZE = int((1 << 31) - 1) 61 else: 62 # 64-bit 63 MAXSIZE = int((1 << 63) - 1) 64 del X 65 66 67def _add_doc(func, doc): 68 """Add documentation to a function.""" 69 func.__doc__ = doc 70 71 72def _import_module(name): 73 """Import module, returning the module after the last dot.""" 74 __import__(name) 75 return sys.modules[name] 76 77 78# Replacement for lazy loading stuff in upstream six. See gh-2764 79if PY3: 80 import builtins 81 import functools 82 reduce = functools.reduce 83 zip = builtins.zip 84 xrange = builtins.range 85else: 86 import __builtin__ 87 import itertools 88 builtins = __builtin__ 89 reduce = __builtin__.reduce 90 zip = itertools.izip 91 xrange = __builtin__.xrange 92 93 94if PY3: 95 _meth_func = "__func__" 96 _meth_self = "__self__" 97 98 _func_code = "__code__" 99 _func_defaults = "__defaults__" 100 101 _iterkeys = "keys" 102 _itervalues = "values" 103 _iteritems = "items" 104else: 105 _meth_func = "im_func" 106 _meth_self = "im_self" 107 108 _func_code = "func_code" 109 _func_defaults = "func_defaults" 110 111 _iterkeys = "iterkeys" 112 _itervalues = "itervalues" 113 _iteritems = "iteritems" 114 115 116try: 117 advance_iterator = next 118except NameError: 119 def advance_iterator(it): 120 return it.next() 121next = advance_iterator 122 123 124if PY3: 125 def get_unbound_function(unbound): 126 return unbound 127 128 Iterator = object 129 130 def callable(obj): 131 return any("__call__" in klass.__dict__ for klass in type(obj).__mro__) 132else: 133 def get_unbound_function(unbound): 134 return unbound.im_func 135 136 class Iterator(object): 137 138 def next(self): 139 return type(self).__next__(self) 140 141 callable = callable 142_add_doc(get_unbound_function, 143 """Get the function out of a possibly unbound function""") 144 145 146get_method_function = operator.attrgetter(_meth_func) 147get_method_self = operator.attrgetter(_meth_self) 148get_function_code = operator.attrgetter(_func_code) 149get_function_defaults = operator.attrgetter(_func_defaults) 150 151 152def iterkeys(d): 153 """Return an iterator over the keys of a dictionary.""" 154 return iter(getattr(d, _iterkeys)()) 155 156 157def itervalues(d): 158 """Return an iterator over the values of a dictionary.""" 159 return iter(getattr(d, _itervalues)()) 160 161 162def iteritems(d): 163 """Return an iterator over the (key, value) pairs of a dictionary.""" 164 return iter(getattr(d, _iteritems)()) 165 166 167if PY3: 168 def b(s): 169 return s.encode("latin-1") 170 171 def u(s): 172 return s 173 174 if sys.version_info[1] <= 1: 175 def int2byte(i): 176 return bytes((i,)) 177 else: 178 # This is about 2x faster than the implementation above on 3.2+ 179 int2byte = operator.methodcaller("to_bytes", 1, "big") 180 import io 181 StringIO = io.StringIO 182 BytesIO = io.BytesIO 183else: 184 def b(s): 185 return s 186 187 def u(s): 188 return unicode(s, "unicode_escape") 189 int2byte = chr 190 import StringIO 191 StringIO = BytesIO = StringIO.StringIO 192_add_doc(b, """Byte literal""") 193_add_doc(u, """Text literal""") 194 195 196if PY3: 197 import builtins 198 exec_ = getattr(builtins, "exec") 199 200 def reraise(tp, value, tb=None): 201 if value.__traceback__ is not tb: 202 raise value.with_traceback(tb) 203 raise value 204 205 print_ = getattr(builtins, "print") 206 del builtins 207 208else: 209 def exec_(code, globs=None, locs=None): 210 """Execute code in a namespace.""" 211 if globs is None: 212 frame = sys._getframe(1) 213 globs = frame.f_globals 214 if locs is None: 215 locs = frame.f_locals 216 del frame 217 elif locs is None: 218 locs = globs 219 exec("""exec code in globs, locs""") 220 221 exec_("""def reraise(tp, value, tb=None): 222 raise tp, value, tb 223""") 224 225 def print_(*args, **kwargs): 226 """The new-style print function.""" 227 fp = kwargs.pop("file", sys.stdout) 228 if fp is None: 229 return 230 231 def write(data): 232 if not isinstance(data, basestring): 233 data = str(data) 234 fp.write(data) 235 want_unicode = False 236 sep = kwargs.pop("sep", None) 237 if sep is not None: 238 if isinstance(sep, unicode): 239 want_unicode = True 240 elif not isinstance(sep, str): 241 raise TypeError("sep must be None or a string") 242 end = kwargs.pop("end", None) 243 if end is not None: 244 if isinstance(end, unicode): 245 want_unicode = True 246 elif not isinstance(end, str): 247 raise TypeError("end must be None or a string") 248 if kwargs: 249 raise TypeError("invalid keyword arguments to print()") 250 if not want_unicode: 251 for arg in args: 252 if isinstance(arg, unicode): 253 want_unicode = True 254 break 255 if want_unicode: 256 newline = unicode("\n") 257 space = unicode(" ") 258 else: 259 newline = "\n" 260 space = " " 261 if sep is None: 262 sep = space 263 if end is None: 264 end = newline 265 for i, arg in enumerate(args): 266 if i: 267 write(sep) 268 write(arg) 269 write(end) 270 271_add_doc(reraise, """Reraise an exception.""") 272 273 274def with_metaclass(meta, base=object): 275 """Create a base class with a metaclass.""" 276 return meta("NewBase", (base,), {}) 277