py3k.py 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. """
  2. Python 3 compatibility tools.
  3. """
  4. from __future__ import division, absolute_import, print_function
  5. __all__ = ['bytes', 'asbytes', 'isfileobj', 'getexception', 'strchar',
  6. 'unicode', 'asunicode', 'asbytes_nested', 'asunicode_nested',
  7. 'asstr', 'open_latin1', 'long', 'basestring', 'sixu',
  8. 'integer_types', 'is_pathlib_path', 'npy_load_module', 'Path',
  9. 'contextlib_nullcontext', 'os_fspath', 'os_PathLike']
  10. import sys
  11. try:
  12. from pathlib import Path, PurePath
  13. except ImportError:
  14. Path = PurePath = None
  15. if sys.version_info[0] >= 3:
  16. import io
  17. long = int
  18. integer_types = (int,)
  19. basestring = str
  20. unicode = str
  21. bytes = bytes
  22. def asunicode(s):
  23. if isinstance(s, bytes):
  24. return s.decode('latin1')
  25. return str(s)
  26. def asbytes(s):
  27. if isinstance(s, bytes):
  28. return s
  29. return str(s).encode('latin1')
  30. def asstr(s):
  31. if isinstance(s, bytes):
  32. return s.decode('latin1')
  33. return str(s)
  34. def isfileobj(f):
  35. return isinstance(f, (io.FileIO, io.BufferedReader, io.BufferedWriter))
  36. def open_latin1(filename, mode='r'):
  37. return open(filename, mode=mode, encoding='iso-8859-1')
  38. def sixu(s):
  39. return s
  40. strchar = 'U'
  41. else:
  42. bytes = str
  43. long = long
  44. basestring = basestring
  45. unicode = unicode
  46. integer_types = (int, long)
  47. asbytes = str
  48. asstr = str
  49. strchar = 'S'
  50. def isfileobj(f):
  51. return isinstance(f, file)
  52. def asunicode(s):
  53. if isinstance(s, unicode):
  54. return s
  55. return str(s).decode('ascii')
  56. def open_latin1(filename, mode='r'):
  57. return open(filename, mode=mode)
  58. def sixu(s):
  59. return unicode(s, 'unicode_escape')
  60. def getexception():
  61. return sys.exc_info()[1]
  62. def asbytes_nested(x):
  63. if hasattr(x, '__iter__') and not isinstance(x, (bytes, unicode)):
  64. return [asbytes_nested(y) for y in x]
  65. else:
  66. return asbytes(x)
  67. def asunicode_nested(x):
  68. if hasattr(x, '__iter__') and not isinstance(x, (bytes, unicode)):
  69. return [asunicode_nested(y) for y in x]
  70. else:
  71. return asunicode(x)
  72. def is_pathlib_path(obj):
  73. """
  74. Check whether obj is a pathlib.Path object.
  75. Prefer using `isinstance(obj, os_PathLike)` instead of this function.
  76. """
  77. return Path is not None and isinstance(obj, Path)
  78. # from Python 3.7
  79. class contextlib_nullcontext(object):
  80. """Context manager that does no additional processing.
  81. Used as a stand-in for a normal context manager, when a particular
  82. block of code is only sometimes used with a normal context manager:
  83. cm = optional_cm if condition else nullcontext()
  84. with cm:
  85. # Perform operation, using optional_cm if condition is True
  86. """
  87. def __init__(self, enter_result=None):
  88. self.enter_result = enter_result
  89. def __enter__(self):
  90. return self.enter_result
  91. def __exit__(self, *excinfo):
  92. pass
  93. if sys.version_info[0] >= 3 and sys.version_info[1] >= 4:
  94. def npy_load_module(name, fn, info=None):
  95. """
  96. Load a module.
  97. .. versionadded:: 1.11.2
  98. Parameters
  99. ----------
  100. name : str
  101. Full module name.
  102. fn : str
  103. Path to module file.
  104. info : tuple, optional
  105. Only here for backward compatibility with Python 2.*.
  106. Returns
  107. -------
  108. mod : module
  109. """
  110. import importlib.machinery
  111. return importlib.machinery.SourceFileLoader(name, fn).load_module()
  112. else:
  113. def npy_load_module(name, fn, info=None):
  114. """
  115. Load a module.
  116. .. versionadded:: 1.11.2
  117. Parameters
  118. ----------
  119. name : str
  120. Full module name.
  121. fn : str
  122. Path to module file.
  123. info : tuple, optional
  124. Information as returned by `imp.find_module`
  125. (suffix, mode, type).
  126. Returns
  127. -------
  128. mod : module
  129. """
  130. import imp
  131. import os
  132. if info is None:
  133. path = os.path.dirname(fn)
  134. fo, fn, info = imp.find_module(name, [path])
  135. else:
  136. fo = open(fn, info[1])
  137. try:
  138. mod = imp.load_module(name, fo, fn, info)
  139. finally:
  140. fo.close()
  141. return mod
  142. # backport abc.ABC
  143. import abc
  144. if sys.version_info[:2] >= (3, 4):
  145. abc_ABC = abc.ABC
  146. else:
  147. abc_ABC = abc.ABCMeta('ABC', (object,), {'__slots__': ()})
  148. # Backport os.fs_path, os.PathLike, and PurePath.__fspath__
  149. if sys.version_info[:2] >= (3, 6):
  150. import os
  151. os_fspath = os.fspath
  152. os_PathLike = os.PathLike
  153. else:
  154. def _PurePath__fspath__(self):
  155. return str(self)
  156. class os_PathLike(abc_ABC):
  157. """Abstract base class for implementing the file system path protocol."""
  158. @abc.abstractmethod
  159. def __fspath__(self):
  160. """Return the file system path representation of the object."""
  161. raise NotImplementedError
  162. @classmethod
  163. def __subclasshook__(cls, subclass):
  164. if PurePath is not None and issubclass(subclass, PurePath):
  165. return True
  166. return hasattr(subclass, '__fspath__')
  167. def os_fspath(path):
  168. """Return the path representation of a path-like object.
  169. If str or bytes is passed in, it is returned unchanged. Otherwise the
  170. os.PathLike interface is used to get the path representation. If the
  171. path representation is not str or bytes, TypeError is raised. If the
  172. provided path is not str, bytes, or os.PathLike, TypeError is raised.
  173. """
  174. if isinstance(path, (unicode, bytes)):
  175. return path
  176. # Work from the object's type to match method resolution of other magic
  177. # methods.
  178. path_type = type(path)
  179. try:
  180. path_repr = path_type.__fspath__(path)
  181. except AttributeError:
  182. if hasattr(path_type, '__fspath__'):
  183. raise
  184. elif PurePath is not None and issubclass(path_type, PurePath):
  185. return _PurePath__fspath__(path)
  186. else:
  187. raise TypeError("expected str, bytes or os.PathLike object, "
  188. "not " + path_type.__name__)
  189. if isinstance(path_repr, (unicode, bytes)):
  190. return path_repr
  191. else:
  192. raise TypeError("expected {}.__fspath__() to return str or bytes, "
  193. "not {}".format(path_type.__name__,
  194. type(path_repr).__name__))