abc.py 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. """Abstract base classes related to import."""
  2. from . import _bootstrap_external
  3. from . import machinery
  4. try:
  5. import _frozen_importlib
  6. except ImportError as exc:
  7. if exc.name != '_frozen_importlib':
  8. raise
  9. _frozen_importlib = None
  10. try:
  11. import _frozen_importlib_external
  12. except ImportError:
  13. _frozen_importlib_external = _bootstrap_external
  14. from ._abc import Loader
  15. import abc
  16. import warnings
  17. from .resources import abc as _resources_abc
  18. __all__ = [
  19. 'Loader', 'MetaPathFinder', 'PathEntryFinder',
  20. 'ResourceLoader', 'InspectLoader', 'ExecutionLoader',
  21. 'FileLoader', 'SourceLoader',
  22. ]
  23. def __getattr__(name):
  24. """
  25. For backwards compatibility, continue to make names
  26. from _resources_abc available through this module. #93963
  27. """
  28. if name in _resources_abc.__all__:
  29. obj = getattr(_resources_abc, name)
  30. warnings._deprecated(f"{__name__}.{name}", remove=(3, 14))
  31. globals()[name] = obj
  32. return obj
  33. raise AttributeError(f'module {__name__!r} has no attribute {name!r}')
  34. def _register(abstract_cls, *classes):
  35. for cls in classes:
  36. abstract_cls.register(cls)
  37. if _frozen_importlib is not None:
  38. try:
  39. frozen_cls = getattr(_frozen_importlib, cls.__name__)
  40. except AttributeError:
  41. frozen_cls = getattr(_frozen_importlib_external, cls.__name__)
  42. abstract_cls.register(frozen_cls)
  43. class MetaPathFinder(metaclass=abc.ABCMeta):
  44. """Abstract base class for import finders on sys.meta_path."""
  45. # We don't define find_spec() here since that would break
  46. # hasattr checks we do to support backward compatibility.
  47. def invalidate_caches(self):
  48. """An optional method for clearing the finder's cache, if any.
  49. This method is used by importlib.invalidate_caches().
  50. """
  51. _register(MetaPathFinder, machinery.BuiltinImporter, machinery.FrozenImporter,
  52. machinery.PathFinder, machinery.WindowsRegistryFinder)
  53. class PathEntryFinder(metaclass=abc.ABCMeta):
  54. """Abstract base class for path entry finders used by PathFinder."""
  55. def invalidate_caches(self):
  56. """An optional method for clearing the finder's cache, if any.
  57. This method is used by PathFinder.invalidate_caches().
  58. """
  59. _register(PathEntryFinder, machinery.FileFinder)
  60. class ResourceLoader(Loader):
  61. """Abstract base class for loaders which can return data from their
  62. back-end storage.
  63. This ABC represents one of the optional protocols specified by PEP 302.
  64. """
  65. @abc.abstractmethod
  66. def get_data(self, path):
  67. """Abstract method which when implemented should return the bytes for
  68. the specified path. The path must be a str."""
  69. raise OSError
  70. class InspectLoader(Loader):
  71. """Abstract base class for loaders which support inspection about the
  72. modules they can load.
  73. This ABC represents one of the optional protocols specified by PEP 302.
  74. """
  75. def is_package(self, fullname):
  76. """Optional method which when implemented should return whether the
  77. module is a package. The fullname is a str. Returns a bool.
  78. Raises ImportError if the module cannot be found.
  79. """
  80. raise ImportError
  81. def get_code(self, fullname):
  82. """Method which returns the code object for the module.
  83. The fullname is a str. Returns a types.CodeType if possible, else
  84. returns None if a code object does not make sense
  85. (e.g. built-in module). Raises ImportError if the module cannot be
  86. found.
  87. """
  88. source = self.get_source(fullname)
  89. if source is None:
  90. return None
  91. return self.source_to_code(source)
  92. @abc.abstractmethod
  93. def get_source(self, fullname):
  94. """Abstract method which should return the source code for the
  95. module. The fullname is a str. Returns a str.
  96. Raises ImportError if the module cannot be found.
  97. """
  98. raise ImportError
  99. @staticmethod
  100. def source_to_code(data, path='<string>'):
  101. """Compile 'data' into a code object.
  102. The 'data' argument can be anything that compile() can handle. The'path'
  103. argument should be where the data was retrieved (when applicable)."""
  104. return compile(data, path, 'exec', dont_inherit=True)
  105. exec_module = _bootstrap_external._LoaderBasics.exec_module
  106. load_module = _bootstrap_external._LoaderBasics.load_module
  107. _register(InspectLoader, machinery.BuiltinImporter, machinery.FrozenImporter, machinery.NamespaceLoader)
  108. class ExecutionLoader(InspectLoader):
  109. """Abstract base class for loaders that wish to support the execution of
  110. modules as scripts.
  111. This ABC represents one of the optional protocols specified in PEP 302.
  112. """
  113. @abc.abstractmethod
  114. def get_filename(self, fullname):
  115. """Abstract method which should return the value that __file__ is to be
  116. set to.
  117. Raises ImportError if the module cannot be found.
  118. """
  119. raise ImportError
  120. def get_code(self, fullname):
  121. """Method to return the code object for fullname.
  122. Should return None if not applicable (e.g. built-in module).
  123. Raise ImportError if the module cannot be found.
  124. """
  125. source = self.get_source(fullname)
  126. if source is None:
  127. return None
  128. try:
  129. path = self.get_filename(fullname)
  130. except ImportError:
  131. return self.source_to_code(source)
  132. else:
  133. return self.source_to_code(source, path)
  134. _register(ExecutionLoader, machinery.ExtensionFileLoader)
  135. class FileLoader(_bootstrap_external.FileLoader, ResourceLoader, ExecutionLoader):
  136. """Abstract base class partially implementing the ResourceLoader and
  137. ExecutionLoader ABCs."""
  138. _register(FileLoader, machinery.SourceFileLoader,
  139. machinery.SourcelessFileLoader)
  140. class SourceLoader(_bootstrap_external.SourceLoader, ResourceLoader, ExecutionLoader):
  141. """Abstract base class for loading source code (and optionally any
  142. corresponding bytecode).
  143. To support loading from source code, the abstractmethods inherited from
  144. ResourceLoader and ExecutionLoader need to be implemented. To also support
  145. loading from bytecode, the optional methods specified directly by this ABC
  146. is required.
  147. Inherited abstractmethods not implemented in this ABC:
  148. * ResourceLoader.get_data
  149. * ExecutionLoader.get_filename
  150. """
  151. def path_mtime(self, path):
  152. """Return the (int) modification time for the path (str)."""
  153. if self.path_stats.__func__ is SourceLoader.path_stats:
  154. raise OSError
  155. return int(self.path_stats(path)['mtime'])
  156. def path_stats(self, path):
  157. """Return a metadata dict for the source pointed to by the path (str).
  158. Possible keys:
  159. - 'mtime' (mandatory) is the numeric timestamp of last source
  160. code modification;
  161. - 'size' (optional) is the size in bytes of the source code.
  162. """
  163. if self.path_mtime.__func__ is SourceLoader.path_mtime:
  164. raise OSError
  165. return {'mtime': self.path_mtime(path)}
  166. def set_data(self, path, data):
  167. """Write the bytes to the path (if possible).
  168. Accepts a str path and data as bytes.
  169. Any needed intermediary directories are to be created. If for some
  170. reason the file cannot be written because of permissions, fail
  171. silently.
  172. """
  173. _register(SourceLoader, machinery.SourceFileLoader)