You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

394 lines
12 KiB

4 years ago
  1. """Utilities for writing code that runs on Python 2 and 3"""
  2. # Copyright (c) 2010-2012 Benjamin Peterson
  3. #
  4. # Permission is hereby granted, free of charge, to any person obtaining a copy of
  5. # this software and associated documentation files (the "Software"), to deal in
  6. # the Software without restriction, including without limitation the rights to
  7. # use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
  8. # the Software, and to permit persons to whom the Software is furnished to do so,
  9. # subject to the following conditions:
  10. #
  11. # The above copyright notice and this permission notice shall be included in all
  12. # copies or substantial portions of the Software.
  13. #
  14. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
  16. # FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
  17. # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
  18. # IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  19. # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  20. import operator
  21. import sys
  22. import types
  23. __author__ = "Benjamin Peterson <benjamin@python.org>"
  24. __version__ = "1.2.0"
  25. # True if we are running on Python 3.
  26. PY3 = sys.version_info[0] == 3
  27. if PY3:
  28. string_types = str,
  29. integer_types = int,
  30. class_types = type,
  31. text_type = str
  32. binary_type = bytes
  33. MAXSIZE = sys.maxsize
  34. else:
  35. string_types = basestring,
  36. integer_types = (int, long)
  37. class_types = (type, types.ClassType)
  38. text_type = unicode
  39. binary_type = str
  40. if sys.platform.startswith("java"):
  41. # Jython always uses 32 bits.
  42. MAXSIZE = int((1 << 31) - 1)
  43. else:
  44. # It's possible to have sizeof(long) != sizeof(Py_ssize_t).
  45. class X(object):
  46. def __len__(self):
  47. return 1 << 31
  48. try:
  49. len(X())
  50. except OverflowError:
  51. # 32-bit
  52. MAXSIZE = int((1 << 31) - 1)
  53. else:
  54. # 64-bit
  55. MAXSIZE = int((1 << 63) - 1)
  56. del X
  57. def _add_doc(func, doc):
  58. """Add documentation to a function."""
  59. func.__doc__ = doc
  60. def _import_module(name):
  61. """Import module, returning the module after the last dot."""
  62. __import__(name)
  63. return sys.modules[name]
  64. class _LazyDescr(object):
  65. def __init__(self, name):
  66. self.name = name
  67. def __get__(self, obj, tp):
  68. result = self._resolve()
  69. setattr(obj, self.name, result)
  70. # This is a bit ugly, but it avoids running this again.
  71. delattr(tp, self.name)
  72. return result
  73. class MovedModule(_LazyDescr):
  74. def __init__(self, name, old, new=None):
  75. super(MovedModule, self).__init__(name)
  76. if PY3:
  77. if new is None:
  78. new = name
  79. self.mod = new
  80. else:
  81. self.mod = old
  82. def _resolve(self):
  83. return _import_module(self.mod)
  84. class MovedAttribute(_LazyDescr):
  85. def __init__(self, name, old_mod, new_mod, old_attr=None, new_attr=None):
  86. super(MovedAttribute, self).__init__(name)
  87. if PY3:
  88. if new_mod is None:
  89. new_mod = name
  90. self.mod = new_mod
  91. if new_attr is None:
  92. if old_attr is None:
  93. new_attr = name
  94. else:
  95. new_attr = old_attr
  96. self.attr = new_attr
  97. else:
  98. self.mod = old_mod
  99. if old_attr is None:
  100. old_attr = name
  101. self.attr = old_attr
  102. def _resolve(self):
  103. module = _import_module(self.mod)
  104. return getattr(module, self.attr)
  105. class _MovedItems(types.ModuleType):
  106. """Lazy loading of moved objects"""
  107. _moved_attributes = [
  108. MovedAttribute("cStringIO", "cStringIO", "io", "StringIO"),
  109. MovedAttribute("filter", "itertools", "builtins", "ifilter", "filter"),
  110. MovedAttribute("input", "__builtin__", "builtins", "raw_input", "input"),
  111. MovedAttribute("map", "itertools", "builtins", "imap", "map"),
  112. MovedAttribute("reload_module", "__builtin__", "imp", "reload"),
  113. MovedAttribute("reduce", "__builtin__", "functools"),
  114. MovedAttribute("StringIO", "StringIO", "io"),
  115. MovedAttribute("xrange", "__builtin__", "builtins", "xrange", "range"),
  116. MovedAttribute("zip", "itertools", "builtins", "izip", "zip"),
  117. MovedModule("builtins", "__builtin__"),
  118. MovedModule("configparser", "ConfigParser"),
  119. MovedModule("copyreg", "copy_reg"),
  120. MovedModule("http_cookiejar", "cookielib", "http.cookiejar"),
  121. MovedModule("http_cookies", "Cookie", "http.cookies"),
  122. MovedModule("html_entities", "htmlentitydefs", "html.entities"),
  123. MovedModule("html_parser", "HTMLParser", "html.parser"),
  124. MovedModule("http_client", "httplib", "http.client"),
  125. MovedModule("email_mime_multipart", "email.MIMEMultipart", "email.mime.multipart"),
  126. MovedModule("email_mime_text", "email.MIMEText", "email.mime.text"),
  127. MovedModule("email_mime_base", "email.MIMEBase", "email.mime.base"),
  128. MovedModule("BaseHTTPServer", "BaseHTTPServer", "http.server"),
  129. MovedModule("CGIHTTPServer", "CGIHTTPServer", "http.server"),
  130. MovedModule("SimpleHTTPServer", "SimpleHTTPServer", "http.server"),
  131. MovedModule("cPickle", "cPickle", "pickle"),
  132. MovedModule("queue", "Queue"),
  133. MovedModule("reprlib", "repr"),
  134. MovedModule("socketserver", "SocketServer"),
  135. MovedModule("tkinter", "Tkinter"),
  136. MovedModule("tkinter_dialog", "Dialog", "tkinter.dialog"),
  137. MovedModule("tkinter_filedialog", "FileDialog", "tkinter.filedialog"),
  138. MovedModule("tkinter_scrolledtext", "ScrolledText", "tkinter.scrolledtext"),
  139. MovedModule("tkinter_simpledialog", "SimpleDialog", "tkinter.simpledialog"),
  140. MovedModule("tkinter_tix", "Tix", "tkinter.tix"),
  141. MovedModule("tkinter_constants", "Tkconstants", "tkinter.constants"),
  142. MovedModule("tkinter_dnd", "Tkdnd", "tkinter.dnd"),
  143. MovedModule("tkinter_colorchooser", "tkColorChooser",
  144. "tkinter.colorchooser"),
  145. MovedModule("tkinter_commondialog", "tkCommonDialog",
  146. "tkinter.commondialog"),
  147. MovedModule("tkinter_tkfiledialog", "tkFileDialog", "tkinter.filedialog"),
  148. MovedModule("tkinter_font", "tkFont", "tkinter.font"),
  149. MovedModule("tkinter_messagebox", "tkMessageBox", "tkinter.messagebox"),
  150. MovedModule("tkinter_tksimpledialog", "tkSimpleDialog",
  151. "tkinter.simpledialog"),
  152. MovedModule("urllib_robotparser", "robotparser", "urllib.robotparser"),
  153. MovedModule("winreg", "_winreg"),
  154. ]
  155. for attr in _moved_attributes:
  156. setattr(_MovedItems, attr.name, attr)
  157. del attr
  158. moves = sys.modules[__name__ + ".moves"] = _MovedItems("moves")
  159. def add_move(move):
  160. """Add an item to six.moves."""
  161. setattr(_MovedItems, move.name, move)
  162. def remove_move(name):
  163. """Remove item from six.moves."""
  164. try:
  165. delattr(_MovedItems, name)
  166. except AttributeError:
  167. try:
  168. del moves.__dict__[name]
  169. except KeyError:
  170. raise AttributeError("no such move, %r" % (name,))
  171. if PY3:
  172. _meth_func = "__func__"
  173. _meth_self = "__self__"
  174. _func_code = "__code__"
  175. _func_defaults = "__defaults__"
  176. _iterkeys = "keys"
  177. _itervalues = "values"
  178. _iteritems = "items"
  179. else:
  180. _meth_func = "im_func"
  181. _meth_self = "im_self"
  182. _func_code = "func_code"
  183. _func_defaults = "func_defaults"
  184. _iterkeys = "iterkeys"
  185. _itervalues = "itervalues"
  186. _iteritems = "iteritems"
  187. try:
  188. advance_iterator = next
  189. except NameError:
  190. def advance_iterator(it):
  191. return it.next()
  192. next = advance_iterator
  193. try:
  194. callable = callable
  195. except NameError:
  196. def callable(obj):
  197. return any("__call__" in klass.__dict__ for klass in type(obj).__mro__)
  198. if PY3:
  199. def get_unbound_function(unbound):
  200. return unbound
  201. Iterator = object
  202. else:
  203. def get_unbound_function(unbound):
  204. return unbound.im_func
  205. class Iterator(object):
  206. def next(self):
  207. return type(self).__next__(self)
  208. callable = callable
  209. _add_doc(get_unbound_function,
  210. """Get the function out of a possibly unbound function""")
  211. get_method_function = operator.attrgetter(_meth_func)
  212. get_method_self = operator.attrgetter(_meth_self)
  213. get_function_code = operator.attrgetter(_func_code)
  214. get_function_defaults = operator.attrgetter(_func_defaults)
  215. def iterkeys(d):
  216. """Return an iterator over the keys of a dictionary."""
  217. return iter(getattr(d, _iterkeys)())
  218. def itervalues(d):
  219. """Return an iterator over the values of a dictionary."""
  220. return iter(getattr(d, _itervalues)())
  221. def iteritems(d):
  222. """Return an iterator over the (key, value) pairs of a dictionary."""
  223. return iter(getattr(d, _iteritems)())
  224. if PY3:
  225. def b(s):
  226. return s.encode("latin-1")
  227. def u(s):
  228. return s
  229. if sys.version_info[1] <= 1:
  230. def int2byte(i):
  231. return bytes((i,))
  232. else:
  233. # This is about 2x faster than the implementation above on 3.2+
  234. int2byte = operator.methodcaller("to_bytes", 1, "big")
  235. import io
  236. StringIO = io.StringIO
  237. BytesIO = io.BytesIO
  238. else:
  239. def b(s):
  240. return s
  241. def u(s):
  242. if isinstance(s, unicode):
  243. return s
  244. return unicode(s, "unicode_escape")
  245. int2byte = chr
  246. import StringIO
  247. StringIO = BytesIO = StringIO.StringIO
  248. _add_doc(b, """Byte literal""")
  249. _add_doc(u, """Text literal""")
  250. if PY3:
  251. import builtins
  252. exec_ = getattr(builtins, "exec")
  253. def reraise(tp, value, tb=None):
  254. if value.__traceback__ is not tb:
  255. raise value.with_traceback(tb)
  256. raise value
  257. print_ = getattr(builtins, "print")
  258. del builtins
  259. else:
  260. def exec_(_code_, _globs_=None, _locs_=None):
  261. """Execute code in a namespace."""
  262. if _globs_ is None:
  263. frame = sys._getframe(1)
  264. _globs_ = frame.f_globals
  265. if _locs_ is None:
  266. _locs_ = frame.f_locals
  267. del frame
  268. elif _locs_ is None:
  269. _locs_ = _globs_
  270. exec("""exec _code_ in _globs_, _locs_""")
  271. exec_("""def reraise(tp, value, tb=None):
  272. raise tp, value, tb
  273. """)
  274. def print_(*args, **kwargs):
  275. """The new-style print function."""
  276. fp = kwargs.pop("file", sys.stdout)
  277. if fp is None:
  278. return
  279. def write(data):
  280. if not isinstance(data, basestring):
  281. data = str(data)
  282. fp.write(data)
  283. want_unicode = False
  284. sep = kwargs.pop("sep", None)
  285. if sep is not None:
  286. if isinstance(sep, unicode):
  287. want_unicode = True
  288. elif not isinstance(sep, str):
  289. raise TypeError("sep must be None or a string")
  290. end = kwargs.pop("end", None)
  291. if end is not None:
  292. if isinstance(end, unicode):
  293. want_unicode = True
  294. elif not isinstance(end, str):
  295. raise TypeError("end must be None or a string")
  296. if kwargs:
  297. raise TypeError("invalid keyword arguments to print()")
  298. if not want_unicode:
  299. for arg in args:
  300. if isinstance(arg, unicode):
  301. want_unicode = True
  302. break
  303. if want_unicode:
  304. newline = unicode("\n")
  305. space = unicode(" ")
  306. else:
  307. newline = "\n"
  308. space = " "
  309. if sep is None:
  310. sep = space
  311. if end is None:
  312. end = newline
  313. for i, arg in enumerate(args):
  314. if i:
  315. write(sep)
  316. write(arg)
  317. write(end)
  318. _add_doc(reraise, """Reraise an exception.""")
  319. def with_metaclass(meta, base=object):
  320. """Create a base class with a metaclass."""
  321. return meta("NewBase", (base,), {})