blob: b8a9bb1a21ef775946cde305bb5a0f19f90be1e8 [file] [log] [blame]
Brett Cannon2a922ed2009-03-09 03:35:50 +00001"""Abstract base classes related to import."""
Eric Snow183a9412015-05-15 21:54:59 -06002from . import _bootstrap
Eric Snow32439d62015-05-02 19:15:18 -06003from . import _bootstrap_external
Brett Cannon2a922ed2009-03-09 03:35:50 +00004from . import machinery
Brett Cannon938d44d2012-04-22 19:58:33 -04005try:
6 import _frozen_importlib
Brett Cannoncd171c82013-07-04 17:43:24 -04007except ImportError as exc:
Brett Cannon938d44d2012-04-22 19:58:33 -04008 if exc.name != '_frozen_importlib':
9 raise
10 _frozen_importlib = None
Eric Snow32439d62015-05-02 19:15:18 -060011try:
12 import _frozen_importlib_external
Pablo Galindo293dd232019-11-19 21:34:03 +000013except ImportError:
Eric Snow32439d62015-05-02 19:15:18 -060014 _frozen_importlib_external = _bootstrap_external
Brett Cannon2a922ed2009-03-09 03:35:50 +000015import abc
Matthias Bussonnier1d4601c2017-02-15 18:00:32 -080016import warnings
Jason R. Coombs7f7e7062020-05-08 19:20:26 -040017from typing import Protocol, runtime_checkable
Brett Cannon2a922ed2009-03-09 03:35:50 +000018
19
Brett Cannon938d44d2012-04-22 19:58:33 -040020def _register(abstract_cls, *classes):
21 for cls in classes:
22 abstract_cls.register(cls)
23 if _frozen_importlib is not None:
Eric Snow32439d62015-05-02 19:15:18 -060024 try:
25 frozen_cls = getattr(_frozen_importlib, cls.__name__)
26 except AttributeError:
27 frozen_cls = getattr(_frozen_importlib_external, cls.__name__)
Brett Cannon938d44d2012-04-22 19:58:33 -040028 abstract_cls.register(frozen_cls)
29
30
Nick Coghlan8a9080f2012-08-02 21:26:03 +100031class Finder(metaclass=abc.ABCMeta):
32
Brett Cannonf4dc9202012-08-10 12:21:12 -040033 """Legacy abstract base class for import finders.
Nick Coghlan8a9080f2012-08-02 21:26:03 +100034
Brett Cannonf4dc9202012-08-10 12:21:12 -040035 It may be subclassed for compatibility with legacy third party
36 reimplementations of the import system. Otherwise, finder
37 implementations should derive from the more specific MetaPathFinder
38 or PathEntryFinder ABCs.
Matthias Bussonnier1d4601c2017-02-15 18:00:32 -080039
40 Deprecated since Python 3.3
Nick Coghlan8a9080f2012-08-02 21:26:03 +100041 """
42
Brett Cannonf4dc9202012-08-10 12:21:12 -040043 @abc.abstractmethod
Nick Coghlan8a9080f2012-08-02 21:26:03 +100044 def find_module(self, fullname, path=None):
Brett Cannonf4dc9202012-08-10 12:21:12 -040045 """An abstract method that should find a module.
Nick Coghlan8a9080f2012-08-02 21:26:03 +100046 The fullname is a str and the optional path is a str or None.
Brett Cannon100883f2013-04-09 16:59:39 -040047 Returns a Loader object or None.
Nick Coghlan8a9080f2012-08-02 21:26:03 +100048 """
Nick Coghlan8a9080f2012-08-02 21:26:03 +100049
Nick Coghlan8a9080f2012-08-02 21:26:03 +100050
51class MetaPathFinder(Finder):
52
53 """Abstract base class for import finders on sys.meta_path."""
54
Eric Snowb523f842013-11-22 09:05:39 -070055 # We don't define find_spec() here since that would break
56 # hasattr checks we do to support backward compatibility.
57
Nick Coghlan8a9080f2012-08-02 21:26:03 +100058 def find_module(self, fullname, path):
Eric Snowb523f842013-11-22 09:05:39 -070059 """Return a loader for the module.
60
61 If no module is found, return None. The fullname is a str and
62 the path is a list of strings or None.
63
Matthias Bussonnier1d4601c2017-02-15 18:00:32 -080064 This method is deprecated since Python 3.4 in favor of
65 finder.find_spec(). If find_spec() exists then backwards-compatible
66 functionality is provided for this method.
Eric Snow1500d492014-01-06 20:49:04 -070067
Nick Coghlan8a9080f2012-08-02 21:26:03 +100068 """
Matthias Bussonnier1d4601c2017-02-15 18:00:32 -080069 warnings.warn("MetaPathFinder.find_module() is deprecated since Python "
Serhiy Storchaka34fd4c22018-11-05 16:20:25 +020070 "3.4 in favor of MetaPathFinder.find_spec() "
Matthias Bussonnier1d4601c2017-02-15 18:00:32 -080071 "(available since 3.4)",
72 DeprecationWarning,
73 stacklevel=2)
Brett Cannon8d942292014-01-07 15:52:42 -050074 if not hasattr(self, 'find_spec'):
75 return None
76 found = self.find_spec(fullname, path)
77 return found.loader if found is not None else None
Nick Coghlan8a9080f2012-08-02 21:26:03 +100078
Brett Cannonf4dc9202012-08-10 12:21:12 -040079 def invalidate_caches(self):
80 """An optional method for clearing the finder's cache, if any.
81 This method is used by importlib.invalidate_caches().
82 """
Brett Cannonf4dc9202012-08-10 12:21:12 -040083
Nick Coghlan8a9080f2012-08-02 21:26:03 +100084_register(MetaPathFinder, machinery.BuiltinImporter, machinery.FrozenImporter,
Nick Coghlanff794862012-08-02 21:45:24 +100085 machinery.PathFinder, machinery.WindowsRegistryFinder)
Nick Coghlan8a9080f2012-08-02 21:26:03 +100086
87
88class PathEntryFinder(Finder):
89
90 """Abstract base class for path entry finders used by PathFinder."""
91
Eric Snowb523f842013-11-22 09:05:39 -070092 # We don't define find_spec() here since that would break
93 # hasattr checks we do to support backward compatibility.
94
Nick Coghlan8a9080f2012-08-02 21:26:03 +100095 def find_loader(self, fullname):
Eric Snowb523f842013-11-22 09:05:39 -070096 """Return (loader, namespace portion) for the path entry.
97
98 The fullname is a str. The namespace portion is a sequence of
99 path entries contributing to part of a namespace package. The
100 sequence may be empty. If loader is not None, the portion will
101 be ignored.
102
103 The portion will be discarded if another path entry finder
104 locates the module as a normal module or package.
105
Matthias Bussonnier1d4601c2017-02-15 18:00:32 -0800106 This method is deprecated since Python 3.4 in favor of
107 finder.find_spec(). If find_spec() is provided than backwards-compatible
108 functionality is provided.
Nick Coghlan8a9080f2012-08-02 21:26:03 +1000109 """
Matthias Bussonnier1d4601c2017-02-15 18:00:32 -0800110 warnings.warn("PathEntryFinder.find_loader() is deprecated since Python "
111 "3.4 in favor of PathEntryFinder.find_spec() "
112 "(available since 3.4)",
113 DeprecationWarning,
114 stacklevel=2)
Brett Cannon8d942292014-01-07 15:52:42 -0500115 if not hasattr(self, 'find_spec'):
116 return None, []
117 found = self.find_spec(fullname)
118 if found is not None:
119 if not found.submodule_search_locations:
120 portions = []
121 else:
122 portions = found.submodule_search_locations
123 return found.loader, portions
124 else:
125 return None, []
Nick Coghlan8a9080f2012-08-02 21:26:03 +1000126
Eric Snow32439d62015-05-02 19:15:18 -0600127 find_module = _bootstrap_external._find_module_shim
Brett Cannonf4dc9202012-08-10 12:21:12 -0400128
129 def invalidate_caches(self):
130 """An optional method for clearing the finder's cache, if any.
131 This method is used by PathFinder.invalidate_caches().
132 """
Brett Cannonf4dc9202012-08-10 12:21:12 -0400133
Nick Coghlan8a9080f2012-08-02 21:26:03 +1000134_register(PathEntryFinder, machinery.FileFinder)
135
136
Brett Cannon2a922ed2009-03-09 03:35:50 +0000137class Loader(metaclass=abc.ABCMeta):
138
Eric Snowb523f842013-11-22 09:05:39 -0700139 """Abstract base class for import loaders."""
Brett Cannon100883f2013-04-09 16:59:39 -0400140
Eric Snowb523f842013-11-22 09:05:39 -0700141 def create_module(self, spec):
142 """Return a module to initialize and into which to load.
Brett Cannon100883f2013-04-09 16:59:39 -0400143
Eric Snowb523f842013-11-22 09:05:39 -0700144 This method should raise ImportError if anything prevents it
145 from creating a new module. It may return None to indicate
146 that the spec should create the new module.
Eric Snowb523f842013-11-22 09:05:39 -0700147 """
Brett Cannon2a17bde2014-05-30 14:55:29 -0400148 # By default, defer to default semantics for the new module.
Eric Snowb523f842013-11-22 09:05:39 -0700149 return None
150
151 # We don't define exec_module() here since that would break
152 # hasattr checks we do to support backward compatibility.
153
Raymond Hettingercd92f372011-01-13 02:31:25 +0000154 def load_module(self, fullname):
Eric Snowb523f842013-11-22 09:05:39 -0700155 """Return the loaded module.
156
157 The module must be added to sys.modules and have import-related
158 attributes set properly. The fullname is a str.
Brett Cannon2a922ed2009-03-09 03:35:50 +0000159
Brett Cannon100883f2013-04-09 16:59:39 -0400160 ImportError is raised on failure.
Eric Snowb523f842013-11-22 09:05:39 -0700161
Brett Cannon8d942292014-01-07 15:52:42 -0500162 This method is deprecated in favor of loader.exec_module(). If
163 exec_module() exists then it is used to provide a backwards-compatible
164 functionality for this method.
Eric Snow1500d492014-01-06 20:49:04 -0700165
Brett Cannon100883f2013-04-09 16:59:39 -0400166 """
Brett Cannon8d942292014-01-07 15:52:42 -0500167 if not hasattr(self, 'exec_module'):
168 raise ImportError
Eric Snow183a9412015-05-15 21:54:59 -0600169 return _bootstrap._load_module_shim(self, fullname)
Brett Cannon100883f2013-04-09 16:59:39 -0400170
Barry Warsawd7d21942012-07-29 16:36:17 -0400171 def module_repr(self, module):
Brett Cannon100883f2013-04-09 16:59:39 -0400172 """Return a module's repr.
173
Brett Cannonf1d7b112013-05-31 18:39:07 -0400174 Used by the module type when the method does not raise
175 NotImplementedError.
Barry Warsawd7d21942012-07-29 16:36:17 -0400176
Eric Snow1500d492014-01-06 20:49:04 -0700177 This method is deprecated.
178
Eric Snowb523f842013-11-22 09:05:39 -0700179 """
180 # The exception will cause ModuleType.__repr__ to ignore this method.
181 raise NotImplementedError
Brett Cannon0dbb4c72013-05-31 18:56:47 -0400182
Brett Cannon2a922ed2009-03-09 03:35:50 +0000183
Brett Cannon2a922ed2009-03-09 03:35:50 +0000184class ResourceLoader(Loader):
185
Brett Cannon7aa21f72009-03-15 00:53:05 +0000186 """Abstract base class for loaders which can return data from their
187 back-end storage.
Brett Cannon2a922ed2009-03-09 03:35:50 +0000188
189 This ABC represents one of the optional protocols specified by PEP 302.
190
191 """
192
193 @abc.abstractmethod
Raymond Hettingercd92f372011-01-13 02:31:25 +0000194 def get_data(self, path):
Brett Cannon7aa21f72009-03-15 00:53:05 +0000195 """Abstract method which when implemented should return the bytes for
Raymond Hettingerd958ea72011-01-13 19:08:04 +0000196 the specified path. The path must be a str."""
Serhiy Storchaka55fe1ae2017-04-16 10:46:38 +0300197 raise OSError
Brett Cannon2a922ed2009-03-09 03:35:50 +0000198
199
200class InspectLoader(Loader):
201
Brett Cannon7aa21f72009-03-15 00:53:05 +0000202 """Abstract base class for loaders which support inspection about the
203 modules they can load.
Brett Cannon2a922ed2009-03-09 03:35:50 +0000204
205 This ABC represents one of the optional protocols specified by PEP 302.
206
207 """
208
Raymond Hettingercd92f372011-01-13 02:31:25 +0000209 def is_package(self, fullname):
Eric Snowb523f842013-11-22 09:05:39 -0700210 """Optional method which when implemented should return whether the
Brett Cannon100883f2013-04-09 16:59:39 -0400211 module is a package. The fullname is a str. Returns a bool.
212
Eric Snowb523f842013-11-22 09:05:39 -0700213 Raises ImportError if the module cannot be found.
Brett Cannon100883f2013-04-09 16:59:39 -0400214 """
215 raise ImportError
Brett Cannon2a922ed2009-03-09 03:35:50 +0000216
Raymond Hettingercd92f372011-01-13 02:31:25 +0000217 def get_code(self, fullname):
Brett Cannon3b62ca82013-05-27 21:11:04 -0400218 """Method which returns the code object for the module.
Brett Cannon100883f2013-04-09 16:59:39 -0400219
Brett Cannon3b62ca82013-05-27 21:11:04 -0400220 The fullname is a str. Returns a types.CodeType if possible, else
221 returns None if a code object does not make sense
222 (e.g. built-in module). Raises ImportError if the module cannot be
223 found.
Brett Cannon100883f2013-04-09 16:59:39 -0400224 """
Brett Cannon3b62ca82013-05-27 21:11:04 -0400225 source = self.get_source(fullname)
226 if source is None:
227 return None
228 return self.source_to_code(source)
Brett Cannon2a922ed2009-03-09 03:35:50 +0000229
230 @abc.abstractmethod
Raymond Hettingercd92f372011-01-13 02:31:25 +0000231 def get_source(self, fullname):
Brett Cannon7aa21f72009-03-15 00:53:05 +0000232 """Abstract method which should return the source code for the
Brett Cannon100883f2013-04-09 16:59:39 -0400233 module. The fullname is a str. Returns a str.
234
235 Raises ImportError if the module cannot be found.
236 """
237 raise ImportError
Brett Cannon2a922ed2009-03-09 03:35:50 +0000238
Brett Cannon6eaac132014-05-09 12:28:22 -0400239 @staticmethod
240 def source_to_code(data, path='<string>'):
Brett Cannon9ffe85e2013-05-26 16:45:10 -0400241 """Compile 'data' into a code object.
242
243 The 'data' argument can be anything that compile() can handle. The'path'
244 argument should be where the data was retrieved (when applicable)."""
245 return compile(data, path, 'exec', dont_inherit=True)
246
Eric Snow32439d62015-05-02 19:15:18 -0600247 exec_module = _bootstrap_external._LoaderBasics.exec_module
248 load_module = _bootstrap_external._LoaderBasics.load_module
Brett Cannon0dbb4c72013-05-31 18:56:47 -0400249
Eric Snowb523f842013-11-22 09:05:39 -0700250_register(InspectLoader, machinery.BuiltinImporter, machinery.FrozenImporter)
Brett Cannona113ac52009-03-15 01:41:33 +0000251
Brett Cannon2a922ed2009-03-09 03:35:50 +0000252
Brett Cannon69194272009-07-20 04:23:48 +0000253class ExecutionLoader(InspectLoader):
254
255 """Abstract base class for loaders that wish to support the execution of
256 modules as scripts.
257
258 This ABC represents one of the optional protocols specified in PEP 302.
259
260 """
261
262 @abc.abstractmethod
Raymond Hettingercd92f372011-01-13 02:31:25 +0000263 def get_filename(self, fullname):
Brett Cannon69194272009-07-20 04:23:48 +0000264 """Abstract method which should return the value that __file__ is to be
Brett Cannon100883f2013-04-09 16:59:39 -0400265 set to.
266
267 Raises ImportError if the module cannot be found.
268 """
269 raise ImportError
Brett Cannon69194272009-07-20 04:23:48 +0000270
Brett Cannon3b62ca82013-05-27 21:11:04 -0400271 def get_code(self, fullname):
272 """Method to return the code object for fullname.
273
274 Should return None if not applicable (e.g. built-in module).
275 Raise ImportError if the module cannot be found.
276 """
277 source = self.get_source(fullname)
278 if source is None:
279 return None
280 try:
281 path = self.get_filename(fullname)
282 except ImportError:
283 return self.source_to_code(source)
284 else:
285 return self.source_to_code(source, path)
286
Eric Snow7e70fa52013-10-04 20:28:52 -0600287_register(ExecutionLoader, machinery.ExtensionFileLoader)
Eric Snow51794452013-10-03 12:08:55 -0600288
Brett Cannon69194272009-07-20 04:23:48 +0000289
Eric Snow32439d62015-05-02 19:15:18 -0600290class FileLoader(_bootstrap_external.FileLoader, ResourceLoader, ExecutionLoader):
Brett Cannon938d44d2012-04-22 19:58:33 -0400291
292 """Abstract base class partially implementing the ResourceLoader and
293 ExecutionLoader ABCs."""
294
295_register(FileLoader, machinery.SourceFileLoader,
Marc-Andre Lemburg4fe29c92012-04-25 02:31:37 +0200296 machinery.SourcelessFileLoader)
Brett Cannon938d44d2012-04-22 19:58:33 -0400297
298
Eric Snow32439d62015-05-02 19:15:18 -0600299class SourceLoader(_bootstrap_external.SourceLoader, ResourceLoader, ExecutionLoader):
Brett Cannon2a922ed2009-03-09 03:35:50 +0000300
Brett Cannonf23e3742010-06-27 23:57:46 +0000301 """Abstract base class for loading source code (and optionally any
302 corresponding bytecode).
Brett Cannon2a922ed2009-03-09 03:35:50 +0000303
Brett Cannonf23e3742010-06-27 23:57:46 +0000304 To support loading from source code, the abstractmethods inherited from
305 ResourceLoader and ExecutionLoader need to be implemented. To also support
306 loading from bytecode, the optional methods specified directly by this ABC
307 is required.
308
309 Inherited abstractmethods not implemented in this ABC:
310
311 * ResourceLoader.get_data
312 * ExecutionLoader.get_filename
313
314 """
315
Raymond Hettingercd92f372011-01-13 02:31:25 +0000316 def path_mtime(self, path):
Raymond Hettingerd958ea72011-01-13 19:08:04 +0000317 """Return the (int) modification time for the path (str)."""
Antoine Pitrou5136ac02012-01-13 18:52:16 +0100318 if self.path_stats.__func__ is SourceLoader.path_stats:
Serhiy Storchaka55fe1ae2017-04-16 10:46:38 +0300319 raise OSError
Antoine Pitrou5136ac02012-01-13 18:52:16 +0100320 return int(self.path_stats(path)['mtime'])
321
322 def path_stats(self, path):
323 """Return a metadata dict for the source pointed to by the path (str).
324 Possible keys:
325 - 'mtime' (mandatory) is the numeric timestamp of last source
326 code modification;
327 - 'size' (optional) is the size in bytes of the source code.
328 """
329 if self.path_mtime.__func__ is SourceLoader.path_mtime:
Serhiy Storchaka55fe1ae2017-04-16 10:46:38 +0300330 raise OSError
Antoine Pitrou5136ac02012-01-13 18:52:16 +0100331 return {'mtime': self.path_mtime(path)}
Brett Cannon8d189072010-08-22 20:38:47 +0000332
Raymond Hettingercd92f372011-01-13 02:31:25 +0000333 def set_data(self, path, data):
Brett Cannon8d189072010-08-22 20:38:47 +0000334 """Write the bytes to the path (if possible).
335
Raymond Hettingerd958ea72011-01-13 19:08:04 +0000336 Accepts a str path and data as bytes.
337
Brett Cannon8d189072010-08-22 20:38:47 +0000338 Any needed intermediary directories are to be created. If for some
339 reason the file cannot be written because of permissions, fail
340 silently.
Brett Cannon8d189072010-08-22 20:38:47 +0000341 """
Brett Cannon8d189072010-08-22 20:38:47 +0000342
Brett Cannon938d44d2012-04-22 19:58:33 -0400343_register(SourceLoader, machinery.SourceFileLoader)
Brett Cannon4ac51502017-12-15 16:29:35 -0800344
345
Barry Warsaw5ec0fee2018-01-15 15:07:11 -0800346class ResourceReader(metaclass=abc.ABCMeta):
Brett Cannon4ac51502017-12-15 16:29:35 -0800347
Brett Cannonbca42182018-01-12 15:08:59 -0800348 """Abstract base class to provide resource-reading support.
349
350 Loaders that support resource reading are expected to implement
351 the ``get_resource_reader(fullname)`` method and have it either return None
352 or an object compatible with this ABC.
353 """
Brett Cannon4ac51502017-12-15 16:29:35 -0800354
355 @abc.abstractmethod
356 def open_resource(self, resource):
357 """Return an opened, file-like object for binary reading.
358
359 The 'resource' argument is expected to represent only a file name
360 and thus not contain any subdirectory components.
361
362 If the resource cannot be found, FileNotFoundError is raised.
363 """
364 raise FileNotFoundError
365
366 @abc.abstractmethod
367 def resource_path(self, resource):
368 """Return the file system path to the specified resource.
369
370 The 'resource' argument is expected to represent only a file name
371 and thus not contain any subdirectory components.
372
373 If the resource does not exist on the file system, raise
374 FileNotFoundError.
375 """
376 raise FileNotFoundError
377
378 @abc.abstractmethod
379 def is_resource(self, name):
380 """Return True if the named 'name' is consider a resource."""
381 raise FileNotFoundError
382
383 @abc.abstractmethod
384 def contents(self):
Brett Cannon3ab93652018-04-30 11:31:45 -0700385 """Return an iterable of strings over the contents of the package."""
386 return []
Barry Warsaw5ec0fee2018-01-15 15:07:11 -0800387
388
389_register(ResourceReader, machinery.SourceFileLoader)
Jason R. Coombs7f7e7062020-05-08 19:20:26 -0400390
391
392@runtime_checkable
393class Traversable(Protocol):
394 """
395 An object with a subset of pathlib.Path methods suitable for
396 traversing directories and opening files.
397 """
398
399 @abc.abstractmethod
400 def iterdir(self):
401 """
402 Yield Traversable objects in self
403 """
404
405 @abc.abstractmethod
406 def read_bytes(self):
407 """
408 Read contents of self as bytes
409 """
410
411 @abc.abstractmethod
412 def read_text(self, encoding=None):
413 """
414 Read contents of self as bytes
415 """
416
417 @abc.abstractmethod
418 def is_dir(self):
419 """
420 Return True if self is a dir
421 """
422
423 @abc.abstractmethod
424 def is_file(self):
425 """
426 Return True if self is a file
427 """
428
429 @abc.abstractmethod
430 def joinpath(self, child):
431 """
432 Return Traversable child in self
433 """
434
435 @abc.abstractmethod
436 def __truediv__(self, child):
437 """
438 Return Traversable child in self
439 """
440
441 @abc.abstractmethod
442 def open(self, mode='r', *args, **kwargs):
443 """
444 mode may be 'r' or 'rb' to open as text or binary. Return a handle
445 suitable for reading (same as pathlib.Path.open).
446
447 When opening as text, accepts encoding parameters such as those
448 accepted by io.TextIOWrapper.
449 """
450
451 @abc.abstractproperty
452 def name(self):
453 # type: () -> str
454 """
455 The base name of this object without any parent references.
456 """
457
458
459class TraversableResources(ResourceReader):
460 @abc.abstractmethod
461 def files(self):
462 """Return a Traversable object for the loaded package."""
463
464 def open_resource(self, resource):
465 return self.files().joinpath(resource).open('rb')
466
467 def resource_path(self, resource):
468 raise FileNotFoundError(resource)
469
470 def is_resource(self, path):
471 return self.files().joinpath(path).isfile()
472
473 def contents(self):
474 return (item.name for item in self.files().iterdir())