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.

255 lines
8.4 KiB

  1. """This module provides the components needed to build your own __import__
  2. function. Undocumented functions are obsolete.
  3. In most cases it is preferred you consider using the importlib module's
  4. functionality over this module.
  5. """
  6. # (Probably) need to stay in _imp
  7. from _imp import (lock_held, acquire_lock, release_lock,
  8. load_dynamic, get_frozen_object, is_frozen_package,
  9. init_builtin, init_frozen, is_builtin, is_frozen,
  10. _fix_co_filename, extension_suffixes)
  11. # Directly exposed by this module
  12. from importlib._bootstrap import new_module
  13. from importlib._bootstrap import cache_from_source, source_from_cache
  14. from importlib import _bootstrap
  15. from importlib import machinery
  16. import os
  17. import sys
  18. import tokenize
  19. import warnings
  20. # DEPRECATED
  21. SEARCH_ERROR = 0
  22. PY_SOURCE = 1
  23. PY_COMPILED = 2
  24. C_EXTENSION = 3
  25. PY_RESOURCE = 4
  26. PKG_DIRECTORY = 5
  27. C_BUILTIN = 6
  28. PY_FROZEN = 7
  29. PY_CODERESOURCE = 8
  30. IMP_HOOK = 9
  31. def get_magic():
  32. """Return the magic number for .pyc or .pyo files."""
  33. return _bootstrap._MAGIC_BYTES
  34. def get_tag():
  35. """Return the magic tag for .pyc or .pyo files."""
  36. return sys.implementation.cache_tag
  37. def get_suffixes():
  38. warnings.warn('imp.get_suffixes() is deprecated; use the constants '
  39. 'defined on importlib.machinery instead',
  40. DeprecationWarning, 2)
  41. extensions = [(s, 'rb', C_EXTENSION) for s in extension_suffixes()]
  42. source = [(s, 'U', PY_SOURCE) for s in machinery.SOURCE_SUFFIXES]
  43. bytecode = [(s, 'rb', PY_COMPILED) for s in machinery.BYTECODE_SUFFIXES]
  44. return extensions + source + bytecode
  45. class NullImporter:
  46. """Null import object."""
  47. def __init__(self, path):
  48. if path == '':
  49. raise ImportError('empty pathname', path='')
  50. elif os.path.isdir(path):
  51. raise ImportError('existing directory', path=path)
  52. def find_module(self, fullname):
  53. """Always returns None."""
  54. return None
  55. class _HackedGetData:
  56. """Compatibiilty support for 'file' arguments of various load_*()
  57. functions."""
  58. def __init__(self, fullname, path, file=None):
  59. super().__init__(fullname, path)
  60. self.file = file
  61. def get_data(self, path):
  62. """Gross hack to contort loader to deal w/ load_*()'s bad API."""
  63. if self.file and path == self.path:
  64. with self.file:
  65. # Technically should be returning bytes, but
  66. # SourceLoader.get_code() just passed what is returned to
  67. # compile() which can handle str. And converting to bytes would
  68. # require figuring out the encoding to decode to and
  69. # tokenize.detect_encoding() only accepts bytes.
  70. return self.file.read()
  71. else:
  72. return super().get_data(path)
  73. class _LoadSourceCompatibility(_HackedGetData, _bootstrap.SourceFileLoader):
  74. """Compatibility support for implementing load_source()."""
  75. def load_source(name, pathname, file=None):
  76. msg = ('imp.load_source() is deprecated; use '
  77. 'importlib.machinery.SourceFileLoader(name, pathname).load_module()'
  78. ' instead')
  79. warnings.warn(msg, DeprecationWarning, 2)
  80. return _LoadSourceCompatibility(name, pathname, file).load_module(name)
  81. class _LoadCompiledCompatibility(_HackedGetData,
  82. _bootstrap.SourcelessFileLoader):
  83. """Compatibility support for implementing load_compiled()."""
  84. def load_compiled(name, pathname, file=None):
  85. msg = ('imp.load_compiled() is deprecated; use '
  86. 'importlib.machinery.SourcelessFileLoader(name, pathname).'
  87. 'load_module() instead ')
  88. warnings.warn(msg, DeprecationWarning, 2)
  89. return _LoadCompiledCompatibility(name, pathname, file).load_module(name)
  90. def load_package(name, path):
  91. msg = ('imp.load_package() is deprecated; use either '
  92. 'importlib.machinery.SourceFileLoader() or '
  93. 'importlib.machinery.SourcelessFileLoader() instead')
  94. warnings.warn(msg, DeprecationWarning, 2)
  95. if os.path.isdir(path):
  96. extensions = (machinery.SOURCE_SUFFIXES[:] +
  97. machinery.BYTECODE_SUFFIXES[:])
  98. for extension in extensions:
  99. path = os.path.join(path, '__init__'+extension)
  100. if os.path.exists(path):
  101. break
  102. else:
  103. raise ValueError('{!r} is not a package'.format(path))
  104. return _bootstrap.SourceFileLoader(name, path).load_module(name)
  105. def load_module(name, file, filename, details):
  106. """**DEPRECATED**
  107. Load a module, given information returned by find_module().
  108. The module name must include the full package name, if any.
  109. """
  110. suffix, mode, type_ = details
  111. with warnings.catch_warnings():
  112. warnings.simplefilter('ignore')
  113. if mode and (not mode.startswith(('r', 'U')) or '+' in mode):
  114. raise ValueError('invalid file open mode {!r}'.format(mode))
  115. elif file is None and type_ in {PY_SOURCE, PY_COMPILED}:
  116. msg = 'file object required for import (type code {})'.format(type_)
  117. raise ValueError(msg)
  118. elif type_ == PY_SOURCE:
  119. return load_source(name, filename, file)
  120. elif type_ == PY_COMPILED:
  121. return load_compiled(name, filename, file)
  122. elif type_ == PKG_DIRECTORY:
  123. return load_package(name, filename)
  124. elif type_ == C_BUILTIN:
  125. return init_builtin(name)
  126. elif type_ == PY_FROZEN:
  127. return init_frozen(name)
  128. else:
  129. msg = "Don't know how to import {} (type code {}".format(name, type_)
  130. raise ImportError(msg, name=name)
  131. def find_module(name, path=None):
  132. """**DEPRECATED**
  133. Search for a module.
  134. If path is omitted or None, search for a built-in, frozen or special
  135. module and continue search in sys.path. The module name cannot
  136. contain '.'; to search for a submodule of a package, pass the
  137. submodule name and the package's __path__.
  138. """
  139. if not isinstance(name, str):
  140. raise TypeError("'name' must be a str, not {}".format(type(name)))
  141. elif not isinstance(path, (type(None), list)):
  142. # Backwards-compatibility
  143. raise RuntimeError("'list' must be None or a list, "
  144. "not {}".format(type(name)))
  145. if path is None:
  146. if is_builtin(name):
  147. return None, None, ('', '', C_BUILTIN)
  148. elif is_frozen(name):
  149. return None, None, ('', '', PY_FROZEN)
  150. else:
  151. path = sys.path
  152. for entry in path:
  153. package_directory = os.path.join(entry, name)
  154. for suffix in ['.py', machinery.BYTECODE_SUFFIXES[0]]:
  155. package_file_name = '__init__' + suffix
  156. file_path = os.path.join(package_directory, package_file_name)
  157. if os.path.isfile(file_path):
  158. return None, package_directory, ('', '', PKG_DIRECTORY)
  159. with warnings.catch_warnings():
  160. warnings.simplefilter('ignore')
  161. for suffix, mode, type_ in get_suffixes():
  162. file_name = name + suffix
  163. file_path = os.path.join(entry, file_name)
  164. if os.path.isfile(file_path):
  165. break
  166. else:
  167. continue
  168. break # Break out of outer loop when breaking out of inner loop.
  169. else:
  170. raise ImportError(_bootstrap._ERR_MSG.format(name), name=name)
  171. encoding = None
  172. if mode == 'U':
  173. with open(file_path, 'rb') as file:
  174. encoding = tokenize.detect_encoding(file.readline)[0]
  175. file = open(file_path, mode, encoding=encoding)
  176. return file, file_path, (suffix, mode, type_)
  177. _RELOADING = {}
  178. def reload(module):
  179. """Reload the module and return it.
  180. The module must have been successfully imported before.
  181. """
  182. if not module or type(module) != type(sys):
  183. raise TypeError("reload() argument must be module")
  184. name = module.__name__
  185. if name not in sys.modules:
  186. msg = "module {} not in sys.modules"
  187. raise ImportError(msg.format(name), name=name)
  188. if name in _RELOADING:
  189. return _RELOADING[name]
  190. _RELOADING[name] = module
  191. try:
  192. parent_name = name.rpartition('.')[0]
  193. if parent_name and parent_name not in sys.modules:
  194. msg = "parent {!r} not in sys.modules"
  195. raise ImportError(msg.format(parentname), name=parent_name)
  196. return module.__loader__.load_module(name)
  197. finally:
  198. try:
  199. del _RELOADING[name]
  200. except KeyError:
  201. pass