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