blob: c171da37aee307b0d34d52d5e61384079f922f47 [file] [log] [blame]
Brett Cannon2a922ed2009-03-09 03:35:50 +00001"""Abstract base classes related to import."""
2from . import _bootstrap
3from . import machinery
Brett Cannon938d44d2012-04-22 19:58:33 -04004try:
5 import _frozen_importlib
6except ImportError as exc:
7 if exc.name != '_frozen_importlib':
8 raise
9 _frozen_importlib = None
Brett Cannon2a922ed2009-03-09 03:35:50 +000010import abc
Brett Cannonf23e3742010-06-27 23:57:46 +000011import imp
Brett Cannonf23e3742010-06-27 23:57:46 +000012import marshal
Brett Cannonf23e3742010-06-27 23:57:46 +000013import sys
14import tokenize
Brett Cannonf23e3742010-06-27 23:57:46 +000015import warnings
Brett Cannon2a922ed2009-03-09 03:35:50 +000016
17
Brett Cannon938d44d2012-04-22 19:58:33 -040018def _register(abstract_cls, *classes):
19 for cls in classes:
20 abstract_cls.register(cls)
21 if _frozen_importlib is not None:
22 frozen_cls = getattr(_frozen_importlib, cls.__name__)
23 abstract_cls.register(frozen_cls)
24
25
Brett Cannon2a922ed2009-03-09 03:35:50 +000026class Loader(metaclass=abc.ABCMeta):
27
Brett Cannon7aa21f72009-03-15 00:53:05 +000028 """Abstract base class for import loaders."""
Brett Cannon2a922ed2009-03-09 03:35:50 +000029
Brett Cannon7aa21f72009-03-15 00:53:05 +000030 @abc.abstractmethod
Raymond Hettingercd92f372011-01-13 02:31:25 +000031 def load_module(self, fullname):
Raymond Hettingerd958ea72011-01-13 19:08:04 +000032 """Abstract method which when implemented should load a module.
33 The fullname is a str."""
Brett Cannon2a922ed2009-03-09 03:35:50 +000034 raise NotImplementedError
35
Brett Cannon2a922ed2009-03-09 03:35:50 +000036
37class Finder(metaclass=abc.ABCMeta):
38
Brett Cannon7aa21f72009-03-15 00:53:05 +000039 """Abstract base class for import finders."""
Brett Cannon2a922ed2009-03-09 03:35:50 +000040
41 @abc.abstractmethod
Raymond Hettingercd92f372011-01-13 02:31:25 +000042 def find_module(self, fullname, path=None):
Raymond Hettingerd958ea72011-01-13 19:08:04 +000043 """Abstract method which when implemented should find a module.
44 The fullname is a str and the optional path is a str or None.
45 Returns a Loader object.
46 """
Brett Cannon2a922ed2009-03-09 03:35:50 +000047 raise NotImplementedError
48
Brett Cannon938d44d2012-04-22 19:58:33 -040049_register(Finder, machinery.BuiltinImporter, machinery.FrozenImporter,
50 machinery.PathFinder, machinery.FileFinder)
Brett Cannon2a922ed2009-03-09 03:35:50 +000051
52
Brett Cannon2a922ed2009-03-09 03:35:50 +000053class ResourceLoader(Loader):
54
Brett Cannon7aa21f72009-03-15 00:53:05 +000055 """Abstract base class for loaders which can return data from their
56 back-end storage.
Brett Cannon2a922ed2009-03-09 03:35:50 +000057
58 This ABC represents one of the optional protocols specified by PEP 302.
59
60 """
61
62 @abc.abstractmethod
Raymond Hettingercd92f372011-01-13 02:31:25 +000063 def get_data(self, path):
Brett Cannon7aa21f72009-03-15 00:53:05 +000064 """Abstract method which when implemented should return the bytes for
Raymond Hettingerd958ea72011-01-13 19:08:04 +000065 the specified path. The path must be a str."""
Brett Cannon2a922ed2009-03-09 03:35:50 +000066 raise NotImplementedError
67
68
69class InspectLoader(Loader):
70
Brett Cannon7aa21f72009-03-15 00:53:05 +000071 """Abstract base class for loaders which support inspection about the
72 modules they can load.
Brett Cannon2a922ed2009-03-09 03:35:50 +000073
74 This ABC represents one of the optional protocols specified by PEP 302.
75
76 """
77
78 @abc.abstractmethod
Raymond Hettingercd92f372011-01-13 02:31:25 +000079 def is_package(self, fullname):
Brett Cannon7aa21f72009-03-15 00:53:05 +000080 """Abstract method which when implemented should return whether the
Raymond Hettingerd958ea72011-01-13 19:08:04 +000081 module is a package. The fullname is a str. Returns a bool."""
Brett Cannonf23e3742010-06-27 23:57:46 +000082 raise NotImplementedError
Brett Cannon2a922ed2009-03-09 03:35:50 +000083
84 @abc.abstractmethod
Raymond Hettingercd92f372011-01-13 02:31:25 +000085 def get_code(self, fullname):
Brett Cannon7aa21f72009-03-15 00:53:05 +000086 """Abstract method which when implemented should return the code object
Raymond Hettingerd958ea72011-01-13 19:08:04 +000087 for the module. The fullname is a str. Returns a types.CodeType."""
Brett Cannonf23e3742010-06-27 23:57:46 +000088 raise NotImplementedError
Brett Cannon2a922ed2009-03-09 03:35:50 +000089
90 @abc.abstractmethod
Raymond Hettingercd92f372011-01-13 02:31:25 +000091 def get_source(self, fullname):
Brett Cannon7aa21f72009-03-15 00:53:05 +000092 """Abstract method which should return the source code for the
Raymond Hettingerd958ea72011-01-13 19:08:04 +000093 module. The fullname is a str. Returns a str."""
Brett Cannonf23e3742010-06-27 23:57:46 +000094 raise NotImplementedError
Brett Cannon2a922ed2009-03-09 03:35:50 +000095
Brett Cannon938d44d2012-04-22 19:58:33 -040096_register(InspectLoader, machinery.BuiltinImporter, machinery.FrozenImporter,
97 machinery.ExtensionFileLoader)
Brett Cannona113ac52009-03-15 01:41:33 +000098
Brett Cannon2a922ed2009-03-09 03:35:50 +000099
Brett Cannon69194272009-07-20 04:23:48 +0000100class ExecutionLoader(InspectLoader):
101
102 """Abstract base class for loaders that wish to support the execution of
103 modules as scripts.
104
105 This ABC represents one of the optional protocols specified in PEP 302.
106
107 """
108
109 @abc.abstractmethod
Raymond Hettingercd92f372011-01-13 02:31:25 +0000110 def get_filename(self, fullname):
Brett Cannon69194272009-07-20 04:23:48 +0000111 """Abstract method which should return the value that __file__ is to be
112 set to."""
113 raise NotImplementedError
114
115
Brett Cannon938d44d2012-04-22 19:58:33 -0400116class FileLoader(_bootstrap.FileLoader, ResourceLoader, ExecutionLoader):
117
118 """Abstract base class partially implementing the ResourceLoader and
119 ExecutionLoader ABCs."""
120
121_register(FileLoader, machinery.SourceFileLoader,
Marc-Andre Lemburg4fe29c92012-04-25 02:31:37 +0200122 machinery.SourcelessFileLoader)
Brett Cannon938d44d2012-04-22 19:58:33 -0400123
124
Brett Cannon0cf9e6a2010-06-28 04:57:24 +0000125class SourceLoader(_bootstrap.SourceLoader, ResourceLoader, ExecutionLoader):
Brett Cannon2a922ed2009-03-09 03:35:50 +0000126
Brett Cannonf23e3742010-06-27 23:57:46 +0000127 """Abstract base class for loading source code (and optionally any
128 corresponding bytecode).
Brett Cannon2a922ed2009-03-09 03:35:50 +0000129
Brett Cannonf23e3742010-06-27 23:57:46 +0000130 To support loading from source code, the abstractmethods inherited from
131 ResourceLoader and ExecutionLoader need to be implemented. To also support
132 loading from bytecode, the optional methods specified directly by this ABC
133 is required.
134
135 Inherited abstractmethods not implemented in this ABC:
136
137 * ResourceLoader.get_data
138 * ExecutionLoader.get_filename
139
140 """
141
Raymond Hettingercd92f372011-01-13 02:31:25 +0000142 def path_mtime(self, path):
Raymond Hettingerd958ea72011-01-13 19:08:04 +0000143 """Return the (int) modification time for the path (str)."""
Antoine Pitrou5136ac02012-01-13 18:52:16 +0100144 if self.path_stats.__func__ is SourceLoader.path_stats:
145 raise NotImplementedError
146 return int(self.path_stats(path)['mtime'])
147
148 def path_stats(self, path):
149 """Return a metadata dict for the source pointed to by the path (str).
150 Possible keys:
151 - 'mtime' (mandatory) is the numeric timestamp of last source
152 code modification;
153 - 'size' (optional) is the size in bytes of the source code.
154 """
155 if self.path_mtime.__func__ is SourceLoader.path_mtime:
156 raise NotImplementedError
157 return {'mtime': self.path_mtime(path)}
Brett Cannon8d189072010-08-22 20:38:47 +0000158
Raymond Hettingercd92f372011-01-13 02:31:25 +0000159 def set_data(self, path, data):
Brett Cannon8d189072010-08-22 20:38:47 +0000160 """Write the bytes to the path (if possible).
161
Raymond Hettingerd958ea72011-01-13 19:08:04 +0000162 Accepts a str path and data as bytes.
163
Brett Cannon8d189072010-08-22 20:38:47 +0000164 Any needed intermediary directories are to be created. If for some
165 reason the file cannot be written because of permissions, fail
166 silently.
167
168 """
169 raise NotImplementedError
170
Brett Cannon938d44d2012-04-22 19:58:33 -0400171_register(SourceLoader, machinery.SourceFileLoader)
Brett Cannonf23e3742010-06-27 23:57:46 +0000172
173class PyLoader(SourceLoader):
174
175 """Implement the deprecated PyLoader ABC in terms of SourceLoader.
176
177 This class has been deprecated! It is slated for removal in Python 3.4.
178 If compatibility with Python 3.1 is not needed then implement the
179 SourceLoader ABC instead of this class. If Python 3.1 compatibility is
180 needed, then use the following idiom to have a single class that is
181 compatible with Python 3.1 onwards::
182
183 try:
184 from importlib.abc import SourceLoader
185 except ImportError:
186 from importlib.abc import PyLoader as SourceLoader
187
188
189 class CustomLoader(SourceLoader):
190 def get_filename(self, fullname):
191 # Implement ...
192
193 def source_path(self, fullname):
194 '''Implement source_path in terms of get_filename.'''
195 try:
196 return self.get_filename(fullname)
197 except ImportError:
198 return None
199
200 def is_package(self, fullname):
201 filename = os.path.basename(self.get_filename(fullname))
202 return os.path.splitext(filename)[0] == '__init__'
Brett Cannon7aa21f72009-03-15 00:53:05 +0000203
204 """
Brett Cannon2a922ed2009-03-09 03:35:50 +0000205
206 @abc.abstractmethod
Brett Cannonf23e3742010-06-27 23:57:46 +0000207 def is_package(self, fullname):
Brett Cannon2a922ed2009-03-09 03:35:50 +0000208 raise NotImplementedError
209
Brett Cannonf23e3742010-06-27 23:57:46 +0000210 @abc.abstractmethod
Raymond Hettingercd92f372011-01-13 02:31:25 +0000211 def source_path(self, fullname):
Raymond Hettingerd958ea72011-01-13 19:08:04 +0000212 """Abstract method. Accepts a str module name and returns the path to
213 the source code for the module."""
Brett Cannonf23e3742010-06-27 23:57:46 +0000214 raise NotImplementedError
Brett Cannon2a922ed2009-03-09 03:35:50 +0000215
Brett Cannonf23e3742010-06-27 23:57:46 +0000216 def get_filename(self, fullname):
217 """Implement get_filename in terms of source_path.
218
219 As get_filename should only return a source file path there is no
220 chance of the path not existing but loading still being possible, so
221 ImportError should propagate instead of being turned into returning
222 None.
223
224 """
225 warnings.warn("importlib.abc.PyLoader is deprecated and is "
226 "slated for removal in Python 3.4; "
227 "use SourceLoader instead. "
228 "See the importlib documentation on how to be "
229 "compatible with Python 3.1 onwards.",
Florent Xicluna67317752011-12-10 11:07:42 +0100230 DeprecationWarning)
Brett Cannonf23e3742010-06-27 23:57:46 +0000231 path = self.source_path(fullname)
232 if path is None:
Brett Cannonbbb66802012-04-12 21:09:01 -0400233 raise ImportError(name=fullname)
Brett Cannonf23e3742010-06-27 23:57:46 +0000234 else:
235 return path
236
Brett Cannonf23e3742010-06-27 23:57:46 +0000237
238class PyPycLoader(PyLoader):
Brett Cannon2a922ed2009-03-09 03:35:50 +0000239
Brett Cannon7aa21f72009-03-15 00:53:05 +0000240 """Abstract base class to assist in loading source and bytecode by
241 requiring only back-end storage methods to be implemented.
Brett Cannon2a922ed2009-03-09 03:35:50 +0000242
Brett Cannonf23e3742010-06-27 23:57:46 +0000243 This class has been deprecated! Removal is slated for Python 3.4. Implement
244 the SourceLoader ABC instead. If Python 3.1 compatibility is needed, see
245 PyLoader.
246
Brett Cannon7aa21f72009-03-15 00:53:05 +0000247 The methods get_code, get_source, and load_module are implemented for the
248 user.
249
250 """
Brett Cannon2a922ed2009-03-09 03:35:50 +0000251
Brett Cannonf23e3742010-06-27 23:57:46 +0000252 def get_filename(self, fullname):
253 """Return the source or bytecode file path."""
254 path = self.source_path(fullname)
255 if path is not None:
256 return path
257 path = self.bytecode_path(fullname)
258 if path is not None:
259 return path
260 raise ImportError("no source or bytecode path available for "
Brett Cannonbbb66802012-04-12 21:09:01 -0400261 "{0!r}".format(fullname), name=fullname)
Brett Cannonf23e3742010-06-27 23:57:46 +0000262
263 def get_code(self, fullname):
264 """Get a code object from source or bytecode."""
265 warnings.warn("importlib.abc.PyPycLoader is deprecated and slated for "
266 "removal in Python 3.4; use SourceLoader instead. "
267 "If Python 3.1 compatibility is required, see the "
268 "latest documentation for PyLoader.",
Florent Xicluna67317752011-12-10 11:07:42 +0100269 DeprecationWarning)
Brett Cannonf23e3742010-06-27 23:57:46 +0000270 source_timestamp = self.source_mtime(fullname)
271 # Try to use bytecode if it is available.
272 bytecode_path = self.bytecode_path(fullname)
273 if bytecode_path:
274 data = self.get_data(bytecode_path)
275 try:
276 magic = data[:4]
277 if len(magic) < 4:
Philip Jenvey4b42ff62012-02-24 21:48:17 -0800278 raise ImportError(
Brett Cannonbbb66802012-04-12 21:09:01 -0400279 "bad magic number in {}".format(fullname),
280 name=fullname, path=bytecode_path)
Brett Cannonf23e3742010-06-27 23:57:46 +0000281 raw_timestamp = data[4:8]
282 if len(raw_timestamp) < 4:
283 raise EOFError("bad timestamp in {}".format(fullname))
Brett Cannonc264e3e2012-01-25 18:58:03 -0500284 pyc_timestamp = _bootstrap._r_long(raw_timestamp)
Brett Cannonf23e3742010-06-27 23:57:46 +0000285 bytecode = data[8:]
286 # Verify that the magic number is valid.
287 if imp.get_magic() != magic:
Philip Jenvey4b42ff62012-02-24 21:48:17 -0800288 raise ImportError(
Brett Cannonbbb66802012-04-12 21:09:01 -0400289 "bad magic number in {}".format(fullname),
290 name=fullname, path=bytecode_path)
Brett Cannonf23e3742010-06-27 23:57:46 +0000291 # Verify that the bytecode is not stale (only matters when
292 # there is source to fall back on.
293 if source_timestamp:
294 if pyc_timestamp < source_timestamp:
Brett Cannonbbb66802012-04-12 21:09:01 -0400295 raise ImportError("bytecode is stale", name=fullname,
296 path=bytecode_path)
Brett Cannonf23e3742010-06-27 23:57:46 +0000297 except (ImportError, EOFError):
298 # If source is available give it a shot.
299 if source_timestamp is not None:
300 pass
301 else:
302 raise
303 else:
304 # Bytecode seems fine, so try to use it.
305 return marshal.loads(bytecode)
306 elif source_timestamp is None:
307 raise ImportError("no source or bytecode available to create code "
Brett Cannonbbb66802012-04-12 21:09:01 -0400308 "object for {0!r}".format(fullname),
309 name=fullname)
Brett Cannonf23e3742010-06-27 23:57:46 +0000310 # Use the source.
311 source_path = self.source_path(fullname)
312 if source_path is None:
313 message = "a source path must exist to load {0}".format(fullname)
Brett Cannonbbb66802012-04-12 21:09:01 -0400314 raise ImportError(message, name=fullname)
Brett Cannonf23e3742010-06-27 23:57:46 +0000315 source = self.get_data(source_path)
316 code_object = compile(source, source_path, 'exec', dont_inherit=True)
317 # Generate bytecode and write it out.
318 if not sys.dont_write_bytecode:
319 data = bytearray(imp.get_magic())
Brett Cannonc264e3e2012-01-25 18:58:03 -0500320 data.extend(_bootstrap._w_long(source_timestamp))
Brett Cannonf23e3742010-06-27 23:57:46 +0000321 data.extend(marshal.dumps(code_object))
322 self.write_bytecode(fullname, data)
323 return code_object
324
Brett Cannon2a922ed2009-03-09 03:35:50 +0000325 @abc.abstractmethod
Raymond Hettingercd92f372011-01-13 02:31:25 +0000326 def source_mtime(self, fullname):
Raymond Hettingerd958ea72011-01-13 19:08:04 +0000327 """Abstract method. Accepts a str filename and returns an int
Brett Cannon7aa21f72009-03-15 00:53:05 +0000328 modification time for the source of the module."""
Brett Cannon2a922ed2009-03-09 03:35:50 +0000329 raise NotImplementedError
330
331 @abc.abstractmethod
Raymond Hettingercd92f372011-01-13 02:31:25 +0000332 def bytecode_path(self, fullname):
Raymond Hettingerd958ea72011-01-13 19:08:04 +0000333 """Abstract method. Accepts a str filename and returns the str pathname
334 to the bytecode for the module."""
Brett Cannon2a922ed2009-03-09 03:35:50 +0000335 raise NotImplementedError
336
337 @abc.abstractmethod
Raymond Hettingercd92f372011-01-13 02:31:25 +0000338 def write_bytecode(self, fullname, bytecode):
Raymond Hettingerd958ea72011-01-13 19:08:04 +0000339 """Abstract method. Accepts a str filename and bytes object
340 representing the bytecode for the module. Returns a boolean
341 representing whether the bytecode was written or not."""
Brett Cannon2a922ed2009-03-09 03:35:50 +0000342 raise NotImplementedError