blob: fc2a744f72353b4e5a64e80e858e7593f49ad918 [file] [log] [blame]
Brett Cannon23cbd8a2009-01-18 00:24:28 +00001"""Core implementation of import.
2
3This module is NOT meant to be directly imported! It has been designed such
4that it can be bootstrapped into Python as the implementation of import. As
5such it requires the injection of specific modules and attributes in order to
6work. One should use importlib as the public-facing version of this module.
7
8"""
9
10# Injected modules are '_warnings', 'imp', 'sys', 'marshal', 'errno', and '_os'
11# (a.k.a. 'posix', 'nt' or 'os2').
12# Injected attribute is path_sep.
13#
14# When editing this code be aware that code executed at import time CANNOT
15# reference any injected objects! This includes not only global code but also
16# anything specified at the class level.
17
18
19# XXX Could also expose Modules/getpath.c:joinpath()
20def _path_join(*args):
21 """Replacement for os.path.join."""
22 return path_sep.join(x[:-len(path_sep)] if x.endswith(path_sep) else x
23 for x in args)
24
25
26def _path_exists(path):
27 """Replacement for os.path.exists."""
28 try:
29 _os.stat(path)
30 except OSError:
31 return False
32 else:
33 return True
34
35
36def _path_is_mode_type(path, mode):
37 """Test whether the path is the specified mode type."""
38 try:
39 stat_info = _os.stat(path)
40 except OSError:
41 return False
42 return (stat_info.st_mode & 0o170000) == mode
43
44
45# XXX Could also expose Modules/getpath.c:isfile()
46def _path_isfile(path):
47 """Replacement for os.path.isfile."""
48 return _path_is_mode_type(path, 0o100000)
49
50
51# XXX Could also expose Modules/getpath.c:isdir()
52def _path_isdir(path):
53 """Replacement for os.path.isdir."""
54 return _path_is_mode_type(path, 0o040000)
55
56
57def _path_without_ext(path, ext_type):
58 """Replacement for os.path.splitext()[0]."""
59 for suffix in suffix_list(ext_type):
60 if path.endswith(suffix):
61 return path[:-len(suffix)]
62 else:
63 raise ValueError("path is not of the specified type")
64
65
66def _path_absolute(path):
67 """Replacement for os.path.abspath."""
68 if not path:
69 path = _os.getcwd()
70 try:
71 return _os._getfullpathname(path)
72 except AttributeError:
73 if path.startswith('/'):
74 return path
75 else:
76 return _path_join(_os.getcwd(), path)
77
78
79class closing:
80
81 """Simple replacement for contextlib.closing."""
82
83 def __init__(self, obj):
84 self.obj = obj
85
86 def __enter__(self):
87 return self.obj
88
89 def __exit__(self, *args):
90 self.obj.close()
91
92
Brett Cannon5abdc932009-01-22 22:43:07 +000093class BuiltinImporter:
Brett Cannon23cbd8a2009-01-18 00:24:28 +000094
Brett Cannon5abdc932009-01-22 22:43:07 +000095 """Meta path loader for built-in modules.
Brett Cannon23cbd8a2009-01-18 00:24:28 +000096
Brett Cannon5abdc932009-01-22 22:43:07 +000097 All methods are either class or static methods, allowing direct use of the
98 class.
Brett Cannon23cbd8a2009-01-18 00:24:28 +000099
100 """
101
Brett Cannon5abdc932009-01-22 22:43:07 +0000102 @classmethod
103 def find_module(cls, fullname, path=None):
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000104 """Try to find the built-in module.
105
106 If 'path' is ever specified then the search is considered a failure.
107
108 """
109 if path is not None:
110 return None
Brett Cannon5abdc932009-01-22 22:43:07 +0000111 return cls if imp.is_builtin(fullname) else None
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000112
Brett Cannon78246b62009-01-25 04:56:30 +0000113 @classmethod
114 def load_module(cls, fullname):
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000115 """Load a built-in module."""
116 if fullname not in sys.builtin_module_names:
117 raise ImportError("{0} is not a built-in module".format(fullname))
Brett Cannon5abdc932009-01-22 22:43:07 +0000118 return imp.init_builtin(fullname)
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000119
120
Brett Cannon5abdc932009-01-22 22:43:07 +0000121class FrozenImporter:
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000122
Brett Cannon5abdc932009-01-22 22:43:07 +0000123 """Meta path class for importing frozen modules.
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000124
Brett Cannon5abdc932009-01-22 22:43:07 +0000125 All methods are either class or static method to allow direct use of the
126 class.
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000127
Brett Cannon5abdc932009-01-22 22:43:07 +0000128 """
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000129
Brett Cannon5abdc932009-01-22 22:43:07 +0000130 @classmethod
131 def find_module(cls, fullname, path=None):
132 """Find a frozen module."""
133 return cls if imp.is_frozen(fullname) else None
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000134
Brett Cannon5abdc932009-01-22 22:43:07 +0000135 @classmethod
136 def load_module(cls, fullname):
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000137 """Load a frozen module."""
Brett Cannon5abdc932009-01-22 22:43:07 +0000138 if cls.find_module(fullname) is None:
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000139 raise ImportError("{0} is not a frozen module".format(fullname))
Brett Cannon223a19d2009-02-01 01:34:13 +0000140 module = imp.init_frozen(fullname)
141 if hasattr(module, '__path__'):
142 module.__package__ = module.__name__
143 elif '.' in module.__name__:
144 module.__package__ = module.__name__.rsplit('.', 1)[0]
145 return module
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000146
147
148class ChainedImporter(object):
149
150 """Finder that sequentially calls other finders."""
151
152 def __init__(self, *importers):
153 self._importers = importers
154
155 def find_module(self, fullname, path=None):
156 for importer in self._importers:
157 result = importer.find_module(fullname, path)
158 if result:
159 return result
160 else:
161 return None
162
163
164# XXX Don't make filesystem-specific and instead make generic for any path
165# hooks.
166def chaining_fs_path_hook(*path_hooks):
167 """Create a closure which calls the path hooks sequentially looking for
168 which path hooks can handle a path entry.
169
170
171 Passed-in path hooks work as any other path hooks, raising ImportError if
172 they cannot handle the path, otherwise returning a finder.
173
174 """
175 def chained_fs_path_hook(path_entry):
176 """Closure which sees which of the captured path hooks can handle the
177 path entry."""
178 absolute_path = _path_absolute(path_entry)
179 if not _path_isdir(absolute_path):
180 raise ImportError("only directories are supported")
181 accepted = []
182 for path_hook in path_hooks:
183 try:
184 accepted.append(path_hook(absolute_path))
185 except ImportError:
186 continue
187 if not accepted:
188 raise ImportError("no path hooks could handle %s" % path_entry)
189 return ChainedImporter(*accepted)
190 return chained_fs_path_hook
191
192
193def check_name(method):
194 """Decorator to verify that the module being requested matches the one the
195 loader can handle.
196
197 The first argument (self) must define _name which the second argument is
198 comapred against. If the comparison fails then ImportError is raised.
199
200 """
201 def inner(self, name, *args, **kwargs):
202 if self._name != name:
203 raise ImportError("loader cannot handle %s" % name)
204 return method(self, name, *args, **kwargs)
205 inner.__name__ = method.__name__
206 inner.__doc__ = method.__doc__
207 inner.__dict__.update(method.__dict__)
208 return inner
209
210
211class _ExtensionFileLoader(object):
212
213 """Loader for extension modules.
214
215 The constructor is designed to work with FileImporter.
216
217 """
218
219 def __init__(self, name, path, is_pkg):
220 """Initialize the loader.
221
222 If is_pkg is True then an exception is raised as extension modules
223 cannot be the __init__ module for an extension module.
224
225 """
226 self._name = name
227 self._path = path
228 if is_pkg:
229 raise ValueError("extension modules cannot be packages")
230
231 @check_name
232 def load_module(self, fullname):
233 """Load an extension module."""
234 assert self._name == fullname
235 try:
236 module = imp.load_dynamic(fullname, self._path)
237 module.__loader__ = self
238 return module
239 except:
240 # If an error occurred, don't leave a partially initialized module.
241 if fullname in sys.modules:
242 del sys.modules[fullname]
243 raise
244
245 @check_name
246 def is_package(self, fullname):
247 """Return False as an extension module can never be a package."""
248 return False
249
250 @check_name
251 def get_code(self, fullname):
252 """Return None as an extension module cannot create a code object."""
253 return None
254
255 @check_name
256 def get_source(self, fullname):
257 """Return None as extension modules have no source code."""
258 return None
259
260
261def suffix_list(suffix_type):
262 """Return a list of file suffixes based on the imp file type."""
263 return [suffix[0] for suffix in imp.get_suffixes()
264 if suffix[2] == suffix_type]
265
266
267# XXX Need a better name.
268def get_module(fxn):
269 """Decorator to handle selecting the proper module for load_module
270 implementations.
271
272 Decorated modules are passed the module to use instead of the module name.
273 The module is either from sys.modules if it already exists (for reloading)
274 or is a new module which has __name__ set. If any exception is raised by
275 the decorated method then __loader__, __name__, __file__, and __path__ are
276 all restored on the module to their original values.
277
278 """
279 def decorated(self, fullname):
280 module = sys.modules.get(fullname)
281 is_reload = bool(module)
282 if not is_reload:
283 # This must be done before open() is called as the 'io' module
284 # implicitly imports 'locale' and would otherwise trigger an
285 # infinite loop.
286 module = imp.new_module(fullname)
287 module.__name__ = fullname
288 sys.modules[fullname] = module
289 else:
290 original_values = {}
291 modified_attrs = ['__loader__', '__name__', '__file__', '__path__']
292 for attr in modified_attrs:
293 try:
294 original_values[attr] = getattr(module, attr)
295 except AttributeError:
296 pass
297 try:
298 return fxn(self, module)
299 except:
300 if not is_reload:
301 del sys.modules[fullname]
302 else:
303 for attr in modified_attrs:
304 if attr in original_values:
305 setattr(module, attr, original_values[attr])
306 elif hasattr(module, attr):
307 delattr(module, attr)
308 raise
309 return decorated
310
311
312class _PyFileLoader(object):
313 # XXX Still smart to have this as a separate class? Or would it work
314 # better to integrate with PyFileImporter? Could cache _is_pkg info.
315 # FileImporter can be changed to return self instead of a specific loader
316 # call. Otherwise _base_path can be calculated on the fly without issue if
317 # it is known whether a module should be treated as a path or package to
318 # minimize stat calls. Could even go as far as to stat the directory the
319 # importer is in to detect changes and then cache all the info about what
320 # files were found (if stating directories is platform-dependent).
321
322 """Load a Python source or bytecode file."""
323
324 def __init__(self, name, path, is_pkg):
325 self._name = name
326 self._is_pkg = is_pkg
327 # Figure out the base path based on whether it was source or bytecode
328 # that was found.
329 try:
330 self._base_path = _path_without_ext(path, imp.PY_SOURCE)
331 except ValueError:
332 self._base_path = _path_without_ext(path, imp.PY_COMPILED)
333
334 def _find_path(self, ext_type):
335 """Find a path from the base path and the specified extension type that
336 exists, returning None if one is not found."""
337 for suffix in suffix_list(ext_type):
338 path = self._base_path + suffix
339 if _path_exists(path):
340 return path
341 else:
342 return None
343
Brett Cannon51c50262009-02-01 05:33:17 +0000344 @check_name
345 def source_path(self, fullname):
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000346 """Return the path to an existing source file for the module, or None
347 if one cannot be found."""
348 # Not a property so that it is easy to override.
349 return self._find_path(imp.PY_SOURCE)
350
Brett Cannon51c50262009-02-01 05:33:17 +0000351 @check_name
352 def bytecode_path(self, fullname):
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000353 """Return the path to a bytecode file, or None if one does not
354 exist."""
355 # Not a property for easy overriding.
356 return self._find_path(imp.PY_COMPILED)
357
358 @check_name
359 @get_module
360 def load_module(self, module):
361 """Load a Python source or bytecode module."""
Brett Cannon51c50262009-02-01 05:33:17 +0000362 name = module.__name__
363 source_path = self.source_path(name)
364 bytecode_path = self.bytecode_path(name)
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000365 code_object = self.get_code(module.__name__)
366 module.__file__ = source_path if source_path else bytecode_path
367 module.__loader__ = self
368 if self._is_pkg:
369 module.__path__ = [module.__file__.rsplit(path_sep, 1)[0]]
370 module.__package__ = module.__name__
371 elif '.' in module.__name__:
372 module.__package__ = module.__name__.rsplit('.', 1)[0]
373 else:
374 module.__package__ = None
375 exec(code_object, module.__dict__)
376 return module
377
378 @check_name
379 def source_mtime(self, name):
380 """Return the modification time of the source for the specified
381 module."""
Brett Cannon51c50262009-02-01 05:33:17 +0000382 source_path = self.source_path(name)
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000383 if not source_path:
384 return None
385 return int(_os.stat(source_path).st_mtime)
386
387 @check_name
388 def get_source(self, fullname):
389 """Return the source for the module as a string.
390
391 Return None if the source is not available. Raise ImportError if the
392 laoder cannot handle the specified module.
393
394 """
Brett Cannon51c50262009-02-01 05:33:17 +0000395 source_path = self._source_path(name)
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000396 if source_path is None:
397 return None
398 import tokenize
Brett Cannonb4a1b8c2009-01-19 06:56:16 +0000399 with closing(_fileio._FileIO(source_path, 'r')) as file:
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000400 encoding, lines = tokenize.detect_encoding(file.readline)
401 # XXX Will fail when passed to compile() if the encoding is
402 # anything other than UTF-8.
403 return open(source_path, encoding=encoding).read()
404
405 @check_name
Brett Cannon776e7012009-02-01 06:07:57 +0000406 def write_bytecode(self, name, data):
407 """Write out 'data' for the specified module, returning a boolean
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000408 signifying if the write-out actually occurred.
409
410 Raises ImportError (just like get_source) if the specified module
411 cannot be handled by the loader.
412
413 """
Brett Cannon51c50262009-02-01 05:33:17 +0000414 bytecode_path = self.bytecode_path(name)
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000415 if not bytecode_path:
416 bytecode_path = self._base_path + suffix_list(imp.PY_COMPILED)[0]
417 file = _fileio._FileIO(bytecode_path, 'w')
418 try:
419 with closing(file) as bytecode_file:
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000420 bytecode_file.write(data)
421 return True
422 except IOError as exc:
423 if exc.errno == errno.EACCES:
424 return False
425 else:
426 raise
427
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000428 @check_name
429 def get_code(self, name):
Brett Cannon776e7012009-02-01 06:07:57 +0000430 """Return the code object for the module."""
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000431 # XXX Care enough to make sure this call does not happen if the magic
432 # number is bad?
433 source_timestamp = self.source_mtime(name)
434 # Try to use bytecode if it is available.
Brett Cannonba96f0f2009-02-01 05:43:31 +0000435 bytecode_path = self.bytecode_path(name)
436 if bytecode_path:
437 data = self.get_data(bytecode_path)
438 magic = data[:4]
439 pyc_timestamp = marshal._r_long(data[4:8])
440 bytecode = data[8:]
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000441 try:
442 # Verify that the magic number is valid.
443 if imp.get_magic() != magic:
444 raise ImportError("bad magic number")
445 # Verify that the bytecode is not stale (only matters when
446 # there is source to fall back on.
447 if source_timestamp:
448 if pyc_timestamp < source_timestamp:
449 raise ImportError("bytcode is stale")
450 except ImportError:
451 # If source is available give it a shot.
452 if source_timestamp is not None:
453 pass
454 else:
455 raise
456 else:
457 # Bytecode seems fine, so try to use it.
458 # XXX If the bytecode is ill-formed, would it be beneficial to
459 # try for using source if available and issue a warning?
460 return marshal.loads(bytecode)
461 elif source_timestamp is None:
462 raise ImportError("no source or bytecode available to create code "
463 "object for {0!r}".format(name))
464 # Use the source.
Brett Cannonba96f0f2009-02-01 05:43:31 +0000465 source_path = self.source_path(name)
466 source = self.get_data(source_path)
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000467 # Convert to universal newlines.
468 line_endings = b'\n'
469 for index, c in enumerate(source):
470 if c == ord(b'\n'):
471 break
472 elif c == ord(b'\r'):
473 line_endings = b'\r'
474 try:
475 if source[index+1] == ord(b'\n'):
476 line_endings += b'\n'
477 except IndexError:
478 pass
479 break
480 if line_endings != b'\n':
481 source = source.replace(line_endings, b'\n')
482 code_object = compile(source, source_path, 'exec', dont_inherit=True)
483 # Generate bytecode and write it out.
484 if not sys.dont_write_bytecode:
Brett Cannon776e7012009-02-01 06:07:57 +0000485 data = bytearray(imp.get_magic())
486 data.extend(marshal._w_long(source_timestamp))
487 data.extend(marshal.dumps(code_object))
488 self.write_bytecode(name, data)
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000489 return code_object
490
491 def get_data(self, path):
492 """Return the data from path as raw bytes."""
493 return _fileio._FileIO(path, 'r').read()
494
495 @check_name
496 def is_package(self, fullname):
497 """Return a boolean based on whether the module is a package.
498
499 Raises ImportError (like get_source) if the loader cannot handle the
500 package.
501
502 """
503 return self._is_pkg
504
505
506class FileImporter(object):
507
508 """Base class for file importers.
509
510 Subclasses are expected to define the following attributes:
511
512 * _suffixes
513 Sequence of file suffixes whose order will be followed.
514
515 * _possible_package
516 True if importer should check for packages.
517
518 * _loader
519 A callable that takes the module name, a file path, and whether
520 the path points to a package and returns a loader for the module
521 found at that path.
522
523 """
524
525 def __init__(self, path_entry):
526 """Initialize an importer for the passed-in sys.path entry (which is
527 assumed to have already been verified as an existing directory).
528
529 Can be used as an entry on sys.path_hook.
530
531 """
532 self._path_entry = path_entry
533
534 def find_module(self, fullname, path=None):
535 tail_module = fullname.rsplit('.', 1)[-1]
536 package_directory = None
537 if self._possible_package:
538 for ext in self._suffixes:
539 package_directory = _path_join(self._path_entry, tail_module)
540 init_filename = '__init__' + ext
541 package_init = _path_join(package_directory, init_filename)
542 if (_path_isfile(package_init) and
543 _case_ok(self._path_entry, tail_module) and
544 _case_ok(package_directory, init_filename)):
545 return self._loader(fullname, package_init, True)
546 for ext in self._suffixes:
547 file_name = tail_module + ext
548 file_path = _path_join(self._path_entry, file_name)
549 if (_path_isfile(file_path) and
550 _case_ok(self._path_entry, file_name)):
551 return self._loader(fullname, file_path, False)
552 else:
553 # Raise a warning if it matches a directory w/o an __init__ file.
554 if (package_directory is not None and
555 _path_isdir(package_directory) and
556 _case_ok(self._path_entry, tail_module)):
557 _warnings.warn("Not importing directory %s: missing __init__"
558 % package_directory, ImportWarning)
559 return None
560
561
562class ExtensionFileImporter(FileImporter):
563
564 """Importer for extension files."""
565
566 _possible_package = False
567 _loader = _ExtensionFileLoader
568
569 def __init__(self, path_entry):
570 # Assigning to _suffixes here instead of at the class level because
571 # imp is not imported at the time of class creation.
572 self._suffixes = suffix_list(imp.C_EXTENSION)
573 super(ExtensionFileImporter, self).__init__(path_entry)
574
575
576class PyFileImporter(FileImporter):
577
578 """Importer for source/bytecode files."""
579
580 _possible_package = True
581 _loader = _PyFileLoader
582
583 def __init__(self, path_entry):
584 # Lack of imp during class creation means _suffixes is set here.
585 # Make sure that Python source files are listed first! Needed for an
586 # optimization by the loader.
587 self._suffixes = suffix_list(imp.PY_SOURCE)
588 self._suffixes += suffix_list(imp.PY_COMPILED)
589 super(PyFileImporter, self).__init__(path_entry)
590
591
Brett Cannonf7e5a8c2009-02-05 02:52:18 +0000592class PathFinder:
Brett Cannon1d376682009-02-02 19:19:36 +0000593
594 """Meta path finder for sys.(path|path_hooks|path_importer_cache)."""
595
Brett Cannonf7e5a8c2009-02-05 02:52:18 +0000596 _default_hook = staticmethod(chaining_fs_path_hook(ExtensionFileImporter,
597 PyFileImporter))
Brett Cannon1d376682009-02-02 19:19:36 +0000598
599 # The list of implicit hooks cannot be a class attribute because of
600 # bootstrapping issues for accessing imp.
Brett Cannonf7e5a8c2009-02-05 02:52:18 +0000601 @classmethod
602 def _implicit_hooks(cls):
Brett Cannon1d376682009-02-02 19:19:36 +0000603 """Return a list of the implicit path hooks."""
Brett Cannon1f9bcd32009-02-05 23:36:02 +0000604 return [cls._default_hook, imp.NullImporter]
Brett Cannon1d376682009-02-02 19:19:36 +0000605
Brett Cannonf7e5a8c2009-02-05 02:52:18 +0000606 @classmethod
607 def _path_hooks(cls, path):
Brett Cannon1d376682009-02-02 19:19:36 +0000608 """Search sys.path_hooks for a finder for 'path'.
609
610 Guaranteed to return a finder for the path as NullImporter is the
611 default importer for any path that does not have an explicit finder.
612
613 """
Brett Cannonf7e5a8c2009-02-05 02:52:18 +0000614 for hook in sys.path_hooks + cls._implicit_hooks():
Brett Cannon1d376682009-02-02 19:19:36 +0000615 try:
616 return hook(path)
617 except ImportError:
618 continue
619 else:
620 # This point should never be reached thanks to NullImporter.
621 raise SystemError("no hook could find an importer for "
622 "{0}".format(path))
623
Brett Cannonf7e5a8c2009-02-05 02:52:18 +0000624 @classmethod
625 def _path_importer_cache(cls, path):
Brett Cannon1d376682009-02-02 19:19:36 +0000626 """Get the finder for the path from sys.path_importer_cache.
627
628 If the path is not in the cache, find the appropriate finder and cache
629 it. If None is cached, get the default finder and cache that
630 (if applicable).
631
632 Because of NullImporter, some finder should be returned. The only
633 explicit fail case is if None is cached but the path cannot be used for
634 the default hook, for which ImportError is raised.
635
636 """
637 try:
Brett Cannonf7e5a8c2009-02-05 02:52:18 +0000638 finder = sys.path_importer_cache[path]
Brett Cannon1d376682009-02-02 19:19:36 +0000639 except KeyError:
Brett Cannonf7e5a8c2009-02-05 02:52:18 +0000640 finder = cls._path_hooks(path)
Brett Cannon1d376682009-02-02 19:19:36 +0000641 sys.path_importer_cache[path] = finder
642 else:
643 if finder is None:
644 # Raises ImportError on failure.
Brett Cannonf7e5a8c2009-02-05 02:52:18 +0000645 finder = cls._default_hook(path)
Brett Cannon1d376682009-02-02 19:19:36 +0000646 sys.path_importer_cache[path] = finder
647 return finder
648
Brett Cannonf7e5a8c2009-02-05 02:52:18 +0000649 @classmethod
650 def find_module(cls, fullname, path=None):
Brett Cannon1d376682009-02-02 19:19:36 +0000651 """Find the module on sys.path or 'path'."""
652 if not path:
653 path = sys.path
654 for entry in path:
655 try:
Brett Cannonf7e5a8c2009-02-05 02:52:18 +0000656 finder = cls._path_importer_cache(entry)
Brett Cannon1d376682009-02-02 19:19:36 +0000657 except ImportError:
658 continue
659 loader = finder.find_module(fullname)
660 if loader:
661 return loader
662 else:
663 return None
664
665
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000666class ImportLockContext(object):
667
668 """Context manager for the import lock."""
669
670 def __enter__(self):
671 """Acquire the import lock."""
672 imp.acquire_lock()
673
674 def __exit__(self, exc_type, exc_value, exc_traceback):
675 """Release the import lock regardless of any raised exceptions."""
676 imp.release_lock()
677
678
Brett Cannon7f9876c2009-02-06 02:47:33 +0000679def _gcd_import(name, package=None, level=0):
680 """Import and return the module based on its name, the package the call is
681 being made from, and the level adjustment.
682
683 This function represents the greatest common denominator of functionality
Brett Cannon2c318a12009-02-07 01:15:27 +0000684 between import_module and __import__. This includes settting __package__ if
685 the loader did not.
686
Brett Cannon7f9876c2009-02-06 02:47:33 +0000687 """
Brett Cannon2c318a12009-02-07 01:15:27 +0000688 if package:
689 if not hasattr(package, 'rindex'):
690 raise ValueError("__package__ not set to a string")
691 elif package not in sys.modules:
692 msg = ("Parent module {0!r} not loaded, cannot perform relative "
693 "import")
694 raise SystemError(msg.format(package))
695 if not name and level == 0:
696 raise ValueError("Empty module name")
Brett Cannon7f9876c2009-02-06 02:47:33 +0000697 if level > 0:
Brett Cannon2c318a12009-02-07 01:15:27 +0000698 dot = len(package)
Brett Cannon7f9876c2009-02-06 02:47:33 +0000699 for x in range(level, 1, -1):
700 try:
701 dot = package.rindex('.', 0, dot)
Brett Cannon7f9876c2009-02-06 02:47:33 +0000702 except ValueError:
Brett Cannon2c318a12009-02-07 01:15:27 +0000703 raise ValueError("attempted relative import beyond "
704 "top-level package")
705 if name:
706 name = "{0}.{1}".format(package[:dot], name)
707 else:
708 name = package[:dot]
Brett Cannon7f9876c2009-02-06 02:47:33 +0000709 with ImportLockContext():
710 try:
711 return sys.modules[name]
712 except KeyError:
713 pass
714 parent = name.rpartition('.')[0]
715 path = None
716 if parent:
717 if parent not in sys.modules:
Brett Cannon2c318a12009-02-07 01:15:27 +0000718 _gcd_import(parent)
719 # Backwards-compatibility; be nicer to skip the dict lookup.
720 parent_module = sys.modules[parent]
Brett Cannon7f9876c2009-02-06 02:47:33 +0000721 path = parent_module.__path__
Brett Cannon2c318a12009-02-07 01:15:27 +0000722 meta_path = (sys.meta_path +
723 [BuiltinImporter, FrozenImporter, PathFinder])
724 for finder in meta_path:
Brett Cannon7f9876c2009-02-06 02:47:33 +0000725 loader = finder.find_module(name, path)
Brett Cannon2c318a12009-02-07 01:15:27 +0000726 if loader is not None:
727 loader.load_module(name)
728 break
Brett Cannon7f9876c2009-02-06 02:47:33 +0000729 else:
730 raise ImportError("No module named {0}".format(name))
Brett Cannon2c318a12009-02-07 01:15:27 +0000731 # Backwards-compatibility; be nicer to skip the dict lookup.
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000732 module = sys.modules[name]
733 if parent:
Brett Cannon2c318a12009-02-07 01:15:27 +0000734 # Set the module as an attribute on its parent.
735 setattr(parent_module, name.rpartition('.')[2], module)
736 # Set __package__ if the loader did not.
737 if not hasattr(module, '__package__') or module.__package__ is None:
738 # Watch out for what comes out of sys.modules to not be a module,
739 # e.g. an int.
740 try:
741 module.__package__ = module.__name__
742 if not hasattr(module, '__path__'):
743 module.__package__ = module.__package__.rpartition('.')[0]
744 except AttributeError:
745 pass
746 return module
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000747
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000748
Brett Cannon2c318a12009-02-07 01:15:27 +0000749def _import(name, globals={}, locals={}, fromlist=[], level=0):
750 """Import a module.
751
752 The 'globals' argument is used to infer where the import is occuring from
753 to handle relative imports. The 'locals' argument is ignored. The
754 'fromlist' argument specifies what should exist as attributes on the module
755 being imported (e.g. ``from module import <fromlist>``). The 'level'
756 argument represents the package location to import from in a relative
757 import (e.g. ``from ..pkg import mod`` would have a 'level' of 2).
758
759 """
760 if level == 0:
761 module = _gcd_import(name)
762 else:
763 # __package__ is not guaranteed to be defined.
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000764 try:
Brett Cannon2c318a12009-02-07 01:15:27 +0000765 package = globals['__package__']
766 except KeyError:
767 package = globals['__name__']
768 if '__path__' not in globals:
769 package = package.rpartition('.')[0]
770 module = _gcd_import(name, package, level)
771 # The hell that is fromlist ...
772 if not fromlist:
773 # Return up to the first dot in 'name'. This is complicated by the fact
774 # that 'name' may be relative.
775 if level == 0:
776 return sys.modules[name.partition('.')[0]]
777 elif not name:
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000778 return module
Brett Cannon2c318a12009-02-07 01:15:27 +0000779 else:
780 cut_off = len(name) - len(name.partition('.')[0])
781 return sys.modules[module.__name__[:-cut_off]]
782 else:
783 # If a package was imported, try to import stuff from fromlist.
784 if hasattr(module, '__path__'):
785 if '*' in fromlist and hasattr(module, '__all__'):
786 fromlist.remove('*')
787 fromlist.extend(module.__all__)
788 for x in (y for y in fromlist if not hasattr(module,y)):
789 try:
790 _gcd_import('{0}.{1}'.format(module.__name__, x))
791 except ImportError:
792 pass
793 return module
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000794
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000795
796# XXX Eventually replace with a proper __all__ value (i.e., don't expose os
797# replacements but do expose _ExtensionFileLoader, etc. for testing).
798__all__ = [obj for obj in globals().keys() if not obj.startswith('__')]