blob: 0b4a3f80717502c0dcea57d2aa43edd98c4a2210 [file] [log] [blame]
Brett Cannon2a922ed2009-03-09 03:35:50 +00001"""Abstract base classes related to import."""
Eric Snow32439d62015-05-02 19:15:18 -06002from . import _bootstrap_external
Brett Cannon2a922ed2009-03-09 03:35:50 +00003from . import machinery
Brett Cannon938d44d2012-04-22 19:58:33 -04004try:
5 import _frozen_importlib
Brett Cannoncd171c82013-07-04 17:43:24 -04006except ImportError as exc:
Brett Cannon938d44d2012-04-22 19:58:33 -04007 if exc.name != '_frozen_importlib':
8 raise
9 _frozen_importlib = None
Eric Snow32439d62015-05-02 19:15:18 -060010try:
11 import _frozen_importlib_external
Pablo Galindo293dd232019-11-19 21:34:03 +000012except ImportError:
Eric Snow32439d62015-05-02 19:15:18 -060013 _frozen_importlib_external = _bootstrap_external
Victor Stinner9e098492020-06-17 23:15:59 +020014from ._abc import Loader
Brett Cannon2a922ed2009-03-09 03:35:50 +000015import abc
Matthias Bussonnier1d4601c2017-02-15 18:00:32 -080016import warnings
Jason R. Coombs67148252021-03-04 13:43:00 -050017from typing import BinaryIO, Iterable, Text
Jason R. Coombs7f7e7062020-05-08 19:20:26 -040018from typing import Protocol, runtime_checkable
Brett Cannon2a922ed2009-03-09 03:35:50 +000019
20
Brett Cannon938d44d2012-04-22 19:58:33 -040021def _register(abstract_cls, *classes):
22 for cls in classes:
23 abstract_cls.register(cls)
24 if _frozen_importlib is not None:
Eric Snow32439d62015-05-02 19:15:18 -060025 try:
26 frozen_cls = getattr(_frozen_importlib, cls.__name__)
27 except AttributeError:
28 frozen_cls = getattr(_frozen_importlib_external, cls.__name__)
Brett Cannon938d44d2012-04-22 19:58:33 -040029 abstract_cls.register(frozen_cls)
30
31
Nick Coghlan8a9080f2012-08-02 21:26:03 +100032class Finder(metaclass=abc.ABCMeta):
33
Brett Cannonf4dc9202012-08-10 12:21:12 -040034 """Legacy abstract base class for import finders.
Nick Coghlan8a9080f2012-08-02 21:26:03 +100035
Brett Cannonf4dc9202012-08-10 12:21:12 -040036 It may be subclassed for compatibility with legacy third party
37 reimplementations of the import system. Otherwise, finder
38 implementations should derive from the more specific MetaPathFinder
39 or PathEntryFinder ABCs.
Matthias Bussonnier1d4601c2017-02-15 18:00:32 -080040
41 Deprecated since Python 3.3
Nick Coghlan8a9080f2012-08-02 21:26:03 +100042 """
43
Brett Cannon57c6cb52021-04-06 08:56:57 -070044 def __init__(self):
45 warnings.warn("the Finder ABC is deprecated and "
46 "slated for removal in Python 3.12; use MetaPathFinder "
47 "or PathEntryFinder instead",
48 DeprecationWarning)
49
Brett Cannonf4dc9202012-08-10 12:21:12 -040050 @abc.abstractmethod
Nick Coghlan8a9080f2012-08-02 21:26:03 +100051 def find_module(self, fullname, path=None):
Brett Cannonf4dc9202012-08-10 12:21:12 -040052 """An abstract method that should find a module.
Nick Coghlan8a9080f2012-08-02 21:26:03 +100053 The fullname is a str and the optional path is a str or None.
Brett Cannon100883f2013-04-09 16:59:39 -040054 Returns a Loader object or None.
Nick Coghlan8a9080f2012-08-02 21:26:03 +100055 """
Brett Cannon57c6cb52021-04-06 08:56:57 -070056 warnings.warn("importlib.abc.Finder along with its find_module() "
57 "method are deprecated and "
58 "slated for removal in Python 3.12; use "
59 "MetaPathFinder.find_spec() or "
60 "PathEntryFinder.find_spec() instead",
61 DeprecationWarning)
Nick Coghlan8a9080f2012-08-02 21:26:03 +100062
Nick Coghlan8a9080f2012-08-02 21:26:03 +100063
Brett Cannon57c6cb52021-04-06 08:56:57 -070064class MetaPathFinder(metaclass=abc.ABCMeta):
Nick Coghlan8a9080f2012-08-02 21:26:03 +100065
66 """Abstract base class for import finders on sys.meta_path."""
67
Eric Snowb523f842013-11-22 09:05:39 -070068 # We don't define find_spec() here since that would break
69 # hasattr checks we do to support backward compatibility.
70
Nick Coghlan8a9080f2012-08-02 21:26:03 +100071 def find_module(self, fullname, path):
Eric Snowb523f842013-11-22 09:05:39 -070072 """Return a loader for the module.
73
74 If no module is found, return None. The fullname is a str and
75 the path is a list of strings or None.
76
Matthias Bussonnier1d4601c2017-02-15 18:00:32 -080077 This method is deprecated since Python 3.4 in favor of
78 finder.find_spec(). If find_spec() exists then backwards-compatible
79 functionality is provided for this method.
Eric Snow1500d492014-01-06 20:49:04 -070080
Nick Coghlan8a9080f2012-08-02 21:26:03 +100081 """
Matthias Bussonnier1d4601c2017-02-15 18:00:32 -080082 warnings.warn("MetaPathFinder.find_module() is deprecated since Python "
Brett Cannon57c6cb52021-04-06 08:56:57 -070083 "3.4 in favor of MetaPathFinder.find_spec() and is "
84 "slated for removal in Python 3.12",
Matthias Bussonnier1d4601c2017-02-15 18:00:32 -080085 DeprecationWarning,
86 stacklevel=2)
Brett Cannon8d942292014-01-07 15:52:42 -050087 if not hasattr(self, 'find_spec'):
88 return None
89 found = self.find_spec(fullname, path)
90 return found.loader if found is not None else None
Nick Coghlan8a9080f2012-08-02 21:26:03 +100091
Brett Cannonf4dc9202012-08-10 12:21:12 -040092 def invalidate_caches(self):
93 """An optional method for clearing the finder's cache, if any.
94 This method is used by importlib.invalidate_caches().
95 """
Brett Cannonf4dc9202012-08-10 12:21:12 -040096
Nick Coghlan8a9080f2012-08-02 21:26:03 +100097_register(MetaPathFinder, machinery.BuiltinImporter, machinery.FrozenImporter,
Nick Coghlanff794862012-08-02 21:45:24 +100098 machinery.PathFinder, machinery.WindowsRegistryFinder)
Nick Coghlan8a9080f2012-08-02 21:26:03 +100099
100
Brett Cannon57c6cb52021-04-06 08:56:57 -0700101class PathEntryFinder(metaclass=abc.ABCMeta):
Nick Coghlan8a9080f2012-08-02 21:26:03 +1000102
103 """Abstract base class for path entry finders used by PathFinder."""
104
Eric Snowb523f842013-11-22 09:05:39 -0700105 # We don't define find_spec() here since that would break
106 # hasattr checks we do to support backward compatibility.
107
Nick Coghlan8a9080f2012-08-02 21:26:03 +1000108 def find_loader(self, fullname):
Eric Snowb523f842013-11-22 09:05:39 -0700109 """Return (loader, namespace portion) for the path entry.
110
111 The fullname is a str. The namespace portion is a sequence of
112 path entries contributing to part of a namespace package. The
113 sequence may be empty. If loader is not None, the portion will
114 be ignored.
115
116 The portion will be discarded if another path entry finder
117 locates the module as a normal module or package.
118
Matthias Bussonnier1d4601c2017-02-15 18:00:32 -0800119 This method is deprecated since Python 3.4 in favor of
120 finder.find_spec(). If find_spec() is provided than backwards-compatible
121 functionality is provided.
Nick Coghlan8a9080f2012-08-02 21:26:03 +1000122 """
Matthias Bussonnier1d4601c2017-02-15 18:00:32 -0800123 warnings.warn("PathEntryFinder.find_loader() is deprecated since Python "
124 "3.4 in favor of PathEntryFinder.find_spec() "
125 "(available since 3.4)",
126 DeprecationWarning,
127 stacklevel=2)
Brett Cannon8d942292014-01-07 15:52:42 -0500128 if not hasattr(self, 'find_spec'):
129 return None, []
130 found = self.find_spec(fullname)
131 if found is not None:
132 if not found.submodule_search_locations:
133 portions = []
134 else:
135 portions = found.submodule_search_locations
136 return found.loader, portions
137 else:
138 return None, []
Nick Coghlan8a9080f2012-08-02 21:26:03 +1000139
Eric Snow32439d62015-05-02 19:15:18 -0600140 find_module = _bootstrap_external._find_module_shim
Brett Cannonf4dc9202012-08-10 12:21:12 -0400141
142 def invalidate_caches(self):
143 """An optional method for clearing the finder's cache, if any.
144 This method is used by PathFinder.invalidate_caches().
145 """
Brett Cannonf4dc9202012-08-10 12:21:12 -0400146
Nick Coghlan8a9080f2012-08-02 21:26:03 +1000147_register(PathEntryFinder, machinery.FileFinder)
148
149
Brett Cannon2a922ed2009-03-09 03:35:50 +0000150class ResourceLoader(Loader):
151
Brett Cannon7aa21f72009-03-15 00:53:05 +0000152 """Abstract base class for loaders which can return data from their
153 back-end storage.
Brett Cannon2a922ed2009-03-09 03:35:50 +0000154
155 This ABC represents one of the optional protocols specified by PEP 302.
156
157 """
158
159 @abc.abstractmethod
Raymond Hettingercd92f372011-01-13 02:31:25 +0000160 def get_data(self, path):
Brett Cannon7aa21f72009-03-15 00:53:05 +0000161 """Abstract method which when implemented should return the bytes for
Raymond Hettingerd958ea72011-01-13 19:08:04 +0000162 the specified path. The path must be a str."""
Serhiy Storchaka55fe1ae2017-04-16 10:46:38 +0300163 raise OSError
Brett Cannon2a922ed2009-03-09 03:35:50 +0000164
165
166class InspectLoader(Loader):
167
Brett Cannon7aa21f72009-03-15 00:53:05 +0000168 """Abstract base class for loaders which support inspection about the
169 modules they can load.
Brett Cannon2a922ed2009-03-09 03:35:50 +0000170
171 This ABC represents one of the optional protocols specified by PEP 302.
172
173 """
174
Raymond Hettingercd92f372011-01-13 02:31:25 +0000175 def is_package(self, fullname):
Eric Snowb523f842013-11-22 09:05:39 -0700176 """Optional method which when implemented should return whether the
Brett Cannon100883f2013-04-09 16:59:39 -0400177 module is a package. The fullname is a str. Returns a bool.
178
Eric Snowb523f842013-11-22 09:05:39 -0700179 Raises ImportError if the module cannot be found.
Brett Cannon100883f2013-04-09 16:59:39 -0400180 """
181 raise ImportError
Brett Cannon2a922ed2009-03-09 03:35:50 +0000182
Raymond Hettingercd92f372011-01-13 02:31:25 +0000183 def get_code(self, fullname):
Brett Cannon3b62ca82013-05-27 21:11:04 -0400184 """Method which returns the code object for the module.
Brett Cannon100883f2013-04-09 16:59:39 -0400185
Brett Cannon3b62ca82013-05-27 21:11:04 -0400186 The fullname is a str. Returns a types.CodeType if possible, else
187 returns None if a code object does not make sense
188 (e.g. built-in module). Raises ImportError if the module cannot be
189 found.
Brett Cannon100883f2013-04-09 16:59:39 -0400190 """
Brett Cannon3b62ca82013-05-27 21:11:04 -0400191 source = self.get_source(fullname)
192 if source is None:
193 return None
194 return self.source_to_code(source)
Brett Cannon2a922ed2009-03-09 03:35:50 +0000195
196 @abc.abstractmethod
Raymond Hettingercd92f372011-01-13 02:31:25 +0000197 def get_source(self, fullname):
Brett Cannon7aa21f72009-03-15 00:53:05 +0000198 """Abstract method which should return the source code for the
Brett Cannon100883f2013-04-09 16:59:39 -0400199 module. The fullname is a str. Returns a str.
200
201 Raises ImportError if the module cannot be found.
202 """
203 raise ImportError
Brett Cannon2a922ed2009-03-09 03:35:50 +0000204
Brett Cannon6eaac132014-05-09 12:28:22 -0400205 @staticmethod
206 def source_to_code(data, path='<string>'):
Brett Cannon9ffe85e2013-05-26 16:45:10 -0400207 """Compile 'data' into a code object.
208
209 The 'data' argument can be anything that compile() can handle. The'path'
210 argument should be where the data was retrieved (when applicable)."""
211 return compile(data, path, 'exec', dont_inherit=True)
212
Eric Snow32439d62015-05-02 19:15:18 -0600213 exec_module = _bootstrap_external._LoaderBasics.exec_module
214 load_module = _bootstrap_external._LoaderBasics.load_module
Brett Cannon0dbb4c72013-05-31 18:56:47 -0400215
Eric Snowb523f842013-11-22 09:05:39 -0700216_register(InspectLoader, machinery.BuiltinImporter, machinery.FrozenImporter)
Brett Cannona113ac52009-03-15 01:41:33 +0000217
Brett Cannon2a922ed2009-03-09 03:35:50 +0000218
Brett Cannon69194272009-07-20 04:23:48 +0000219class ExecutionLoader(InspectLoader):
220
221 """Abstract base class for loaders that wish to support the execution of
222 modules as scripts.
223
224 This ABC represents one of the optional protocols specified in PEP 302.
225
226 """
227
228 @abc.abstractmethod
Raymond Hettingercd92f372011-01-13 02:31:25 +0000229 def get_filename(self, fullname):
Brett Cannon69194272009-07-20 04:23:48 +0000230 """Abstract method which should return the value that __file__ is to be
Brett Cannon100883f2013-04-09 16:59:39 -0400231 set to.
232
233 Raises ImportError if the module cannot be found.
234 """
235 raise ImportError
Brett Cannon69194272009-07-20 04:23:48 +0000236
Brett Cannon3b62ca82013-05-27 21:11:04 -0400237 def get_code(self, fullname):
238 """Method to return the code object for fullname.
239
240 Should return None if not applicable (e.g. built-in module).
241 Raise ImportError if the module cannot be found.
242 """
243 source = self.get_source(fullname)
244 if source is None:
245 return None
246 try:
247 path = self.get_filename(fullname)
248 except ImportError:
249 return self.source_to_code(source)
250 else:
251 return self.source_to_code(source, path)
252
Eric Snow7e70fa52013-10-04 20:28:52 -0600253_register(ExecutionLoader, machinery.ExtensionFileLoader)
Eric Snow51794452013-10-03 12:08:55 -0600254
Brett Cannon69194272009-07-20 04:23:48 +0000255
Eric Snow32439d62015-05-02 19:15:18 -0600256class FileLoader(_bootstrap_external.FileLoader, ResourceLoader, ExecutionLoader):
Brett Cannon938d44d2012-04-22 19:58:33 -0400257
258 """Abstract base class partially implementing the ResourceLoader and
259 ExecutionLoader ABCs."""
260
261_register(FileLoader, machinery.SourceFileLoader,
Marc-Andre Lemburg4fe29c92012-04-25 02:31:37 +0200262 machinery.SourcelessFileLoader)
Brett Cannon938d44d2012-04-22 19:58:33 -0400263
264
Eric Snow32439d62015-05-02 19:15:18 -0600265class SourceLoader(_bootstrap_external.SourceLoader, ResourceLoader, ExecutionLoader):
Brett Cannon2a922ed2009-03-09 03:35:50 +0000266
Brett Cannonf23e3742010-06-27 23:57:46 +0000267 """Abstract base class for loading source code (and optionally any
268 corresponding bytecode).
Brett Cannon2a922ed2009-03-09 03:35:50 +0000269
Brett Cannonf23e3742010-06-27 23:57:46 +0000270 To support loading from source code, the abstractmethods inherited from
271 ResourceLoader and ExecutionLoader need to be implemented. To also support
272 loading from bytecode, the optional methods specified directly by this ABC
273 is required.
274
275 Inherited abstractmethods not implemented in this ABC:
276
277 * ResourceLoader.get_data
278 * ExecutionLoader.get_filename
279
280 """
281
Raymond Hettingercd92f372011-01-13 02:31:25 +0000282 def path_mtime(self, path):
Raymond Hettingerd958ea72011-01-13 19:08:04 +0000283 """Return the (int) modification time for the path (str)."""
Antoine Pitrou5136ac02012-01-13 18:52:16 +0100284 if self.path_stats.__func__ is SourceLoader.path_stats:
Serhiy Storchaka55fe1ae2017-04-16 10:46:38 +0300285 raise OSError
Antoine Pitrou5136ac02012-01-13 18:52:16 +0100286 return int(self.path_stats(path)['mtime'])
287
288 def path_stats(self, path):
289 """Return a metadata dict for the source pointed to by the path (str).
290 Possible keys:
291 - 'mtime' (mandatory) is the numeric timestamp of last source
292 code modification;
293 - 'size' (optional) is the size in bytes of the source code.
294 """
295 if self.path_mtime.__func__ is SourceLoader.path_mtime:
Serhiy Storchaka55fe1ae2017-04-16 10:46:38 +0300296 raise OSError
Antoine Pitrou5136ac02012-01-13 18:52:16 +0100297 return {'mtime': self.path_mtime(path)}
Brett Cannon8d189072010-08-22 20:38:47 +0000298
Raymond Hettingercd92f372011-01-13 02:31:25 +0000299 def set_data(self, path, data):
Brett Cannon8d189072010-08-22 20:38:47 +0000300 """Write the bytes to the path (if possible).
301
Raymond Hettingerd958ea72011-01-13 19:08:04 +0000302 Accepts a str path and data as bytes.
303
Brett Cannon8d189072010-08-22 20:38:47 +0000304 Any needed intermediary directories are to be created. If for some
305 reason the file cannot be written because of permissions, fail
306 silently.
Brett Cannon8d189072010-08-22 20:38:47 +0000307 """
Brett Cannon8d189072010-08-22 20:38:47 +0000308
Brett Cannon938d44d2012-04-22 19:58:33 -0400309_register(SourceLoader, machinery.SourceFileLoader)
Brett Cannon4ac51502017-12-15 16:29:35 -0800310
311
Barry Warsaw5ec0fee2018-01-15 15:07:11 -0800312class ResourceReader(metaclass=abc.ABCMeta):
Jason R. Coombs67148252021-03-04 13:43:00 -0500313 """Abstract base class for loaders to provide resource reading support."""
Brett Cannon4ac51502017-12-15 16:29:35 -0800314
315 @abc.abstractmethod
Jason R. Coombs67148252021-03-04 13:43:00 -0500316 def open_resource(self, resource: Text) -> BinaryIO:
Brett Cannon4ac51502017-12-15 16:29:35 -0800317 """Return an opened, file-like object for binary reading.
318
Jason R. Coombs67148252021-03-04 13:43:00 -0500319 The 'resource' argument is expected to represent only a file name.
Brett Cannon4ac51502017-12-15 16:29:35 -0800320 If the resource cannot be found, FileNotFoundError is raised.
321 """
Jason R. Coombs67148252021-03-04 13:43:00 -0500322 # This deliberately raises FileNotFoundError instead of
323 # NotImplementedError so that if this method is accidentally called,
324 # it'll still do the right thing.
Brett Cannon4ac51502017-12-15 16:29:35 -0800325 raise FileNotFoundError
326
327 @abc.abstractmethod
Jason R. Coombs67148252021-03-04 13:43:00 -0500328 def resource_path(self, resource: Text) -> Text:
Brett Cannon4ac51502017-12-15 16:29:35 -0800329 """Return the file system path to the specified resource.
330
Jason R. Coombs67148252021-03-04 13:43:00 -0500331 The 'resource' argument is expected to represent only a file name.
Brett Cannon4ac51502017-12-15 16:29:35 -0800332 If the resource does not exist on the file system, raise
333 FileNotFoundError.
334 """
Jason R. Coombs67148252021-03-04 13:43:00 -0500335 # This deliberately raises FileNotFoundError instead of
336 # NotImplementedError so that if this method is accidentally called,
337 # it'll still do the right thing.
Brett Cannon4ac51502017-12-15 16:29:35 -0800338 raise FileNotFoundError
339
340 @abc.abstractmethod
Jason R. Coombs67148252021-03-04 13:43:00 -0500341 def is_resource(self, path: Text) -> bool:
342 """Return True if the named 'path' is a resource.
343
344 Files are resources, directories are not.
345 """
Brett Cannon4ac51502017-12-15 16:29:35 -0800346 raise FileNotFoundError
347
348 @abc.abstractmethod
Jason R. Coombs67148252021-03-04 13:43:00 -0500349 def contents(self) -> Iterable[str]:
350 """Return an iterable of entries in `package`."""
351 raise FileNotFoundError
Jason R. Coombs7f7e7062020-05-08 19:20:26 -0400352
353
354@runtime_checkable
355class Traversable(Protocol):
356 """
357 An object with a subset of pathlib.Path methods suitable for
358 traversing directories and opening files.
359 """
360
361 @abc.abstractmethod
362 def iterdir(self):
363 """
364 Yield Traversable objects in self
365 """
366
Jason R. Coombs7f7e7062020-05-08 19:20:26 -0400367 def read_bytes(self):
368 """
369 Read contents of self as bytes
370 """
Jason R. Coombs67148252021-03-04 13:43:00 -0500371 with self.open('rb') as strm:
372 return strm.read()
Jason R. Coombs7f7e7062020-05-08 19:20:26 -0400373
Jason R. Coombs7f7e7062020-05-08 19:20:26 -0400374 def read_text(self, encoding=None):
375 """
Jason R. Coombs67148252021-03-04 13:43:00 -0500376 Read contents of self as text
Jason R. Coombs7f7e7062020-05-08 19:20:26 -0400377 """
Jason R. Coombs67148252021-03-04 13:43:00 -0500378 with self.open(encoding=encoding) as strm:
379 return strm.read()
Jason R. Coombs7f7e7062020-05-08 19:20:26 -0400380
381 @abc.abstractmethod
Jason R. Coombs67148252021-03-04 13:43:00 -0500382 def is_dir(self) -> bool:
Jason R. Coombs7f7e7062020-05-08 19:20:26 -0400383 """
384 Return True if self is a dir
385 """
386
387 @abc.abstractmethod
Jason R. Coombs67148252021-03-04 13:43:00 -0500388 def is_file(self) -> bool:
Jason R. Coombs7f7e7062020-05-08 19:20:26 -0400389 """
390 Return True if self is a file
391 """
392
393 @abc.abstractmethod
394 def joinpath(self, child):
395 """
396 Return Traversable child in self
397 """
398
Jason R. Coombs7f7e7062020-05-08 19:20:26 -0400399 def __truediv__(self, child):
400 """
401 Return Traversable child in self
402 """
Jason R. Coombs67148252021-03-04 13:43:00 -0500403 return self.joinpath(child)
Jason R. Coombs7f7e7062020-05-08 19:20:26 -0400404
405 @abc.abstractmethod
406 def open(self, mode='r', *args, **kwargs):
407 """
408 mode may be 'r' or 'rb' to open as text or binary. Return a handle
409 suitable for reading (same as pathlib.Path.open).
410
411 When opening as text, accepts encoding parameters such as those
412 accepted by io.TextIOWrapper.
413 """
414
415 @abc.abstractproperty
Jason R. Coombs67148252021-03-04 13:43:00 -0500416 def name(self) -> str:
Jason R. Coombs7f7e7062020-05-08 19:20:26 -0400417 """
418 The base name of this object without any parent references.
419 """
420
421
422class TraversableResources(ResourceReader):
Jason R. Coombs67148252021-03-04 13:43:00 -0500423 """
424 The required interface for providing traversable
425 resources.
426 """
427
Jason R. Coombs7f7e7062020-05-08 19:20:26 -0400428 @abc.abstractmethod
429 def files(self):
430 """Return a Traversable object for the loaded package."""
431
432 def open_resource(self, resource):
433 return self.files().joinpath(resource).open('rb')
434
435 def resource_path(self, resource):
436 raise FileNotFoundError(resource)
437
438 def is_resource(self, path):
Jason R. Coombs843c2772020-06-07 21:00:51 -0400439 return self.files().joinpath(path).is_file()
Jason R. Coombs7f7e7062020-05-08 19:20:26 -0400440
441 def contents(self):
442 return (item.name for item in self.files().iterdir())