Brett Cannon | b46a179 | 2012-02-27 18:15:42 -0500 | [diff] [blame] | 1 | """A pure Python implementation of import.""" |
Antoine Pitrou | c541f8e | 2012-02-20 01:48:16 +0100 | [diff] [blame] | 2 | __all__ = ['__import__', 'import_module', 'invalidate_caches'] |
Brett Cannon | 9495f18 | 2009-03-12 22:01:40 +0000 | [diff] [blame] | 3 | |
Brett Cannon | 7f400e1 | 2009-01-22 22:44:04 +0000 | [diff] [blame] | 4 | # Bootstrap help ##################################################### |
Nick Coghlan | be7e49f | 2012-07-20 23:40:09 +1000 | [diff] [blame] | 5 | |
| 6 | # Until bootstrapping is complete, DO NOT import any modules that attempt |
| 7 | # to import importlib._bootstrap (directly or indirectly). Since this |
| 8 | # partially initialised package would be present in sys.modules, those |
| 9 | # modules would get an uninitialised copy of the source version, instead |
| 10 | # of a fully initialised version (either the frozen one or the one |
| 11 | # initialised below if the frozen one is not available). |
| 12 | import _imp # Just the builtin component, NOT the full Python module |
Brett Cannon | 354c26e | 2012-02-08 18:50:22 -0500 | [diff] [blame] | 13 | import sys |
Brett Cannon | 7f400e1 | 2009-01-22 22:44:04 +0000 | [diff] [blame] | 14 | |
Antoine Pitrou | 48114b9 | 2012-06-17 22:33:38 +0200 | [diff] [blame] | 15 | try: |
Brett Cannon | 53089c6 | 2012-07-04 14:03:40 -0400 | [diff] [blame] | 16 | import _frozen_importlib as _bootstrap |
| 17 | except ImportError: |
Antoine Pitrou | 48114b9 | 2012-06-17 22:33:38 +0200 | [diff] [blame] | 18 | from . import _bootstrap |
Nick Coghlan | be7e49f | 2012-07-20 23:40:09 +1000 | [diff] [blame] | 19 | _bootstrap._setup(sys, _imp) |
Antoine Pitrou | 48114b9 | 2012-06-17 22:33:38 +0200 | [diff] [blame] | 20 | else: |
| 21 | # importlib._bootstrap is the built-in import, ensure we don't create |
| 22 | # a second copy of the module. |
| 23 | _bootstrap.__name__ = 'importlib._bootstrap' |
| 24 | _bootstrap.__package__ = 'importlib' |
| 25 | _bootstrap.__file__ = __file__.replace('__init__.py', '_bootstrap.py') |
| 26 | sys.modules['importlib._bootstrap'] = _bootstrap |
| 27 | |
| 28 | # To simplify imports in test code |
| 29 | _w_long = _bootstrap._w_long |
| 30 | _r_long = _bootstrap._r_long |
Brett Cannon | 23cbd8a | 2009-01-18 00:24:28 +0000 | [diff] [blame] | 31 | |
Nick Coghlan | be7e49f | 2012-07-20 23:40:09 +1000 | [diff] [blame] | 32 | # Fully bootstrapped at this point, import whatever you like, circular |
| 33 | # dependencies and startup overhead minimisation permitting :) |
Brett Cannon | afccd63 | 2009-01-20 02:21:27 +0000 | [diff] [blame] | 34 | |
Brett Cannon | 7f400e1 | 2009-01-22 22:44:04 +0000 | [diff] [blame] | 35 | # Public API ######################################################### |
| 36 | |
Brett Cannon | b46a179 | 2012-02-27 18:15:42 -0500 | [diff] [blame] | 37 | from ._bootstrap import __import__ |
| 38 | |
| 39 | |
| 40 | def invalidate_caches(): |
Brett Cannon | f4dc920 | 2012-08-10 12:21:12 -0400 | [diff] [blame] | 41 | """Call the invalidate_caches() method on all meta path finders stored in |
| 42 | sys.meta_path (where implemented).""" |
| 43 | for finder in sys.meta_path: |
Brett Cannon | b46a179 | 2012-02-27 18:15:42 -0500 | [diff] [blame] | 44 | if hasattr(finder, 'invalidate_caches'): |
| 45 | finder.invalidate_caches() |
Brett Cannon | afccd63 | 2009-01-20 02:21:27 +0000 | [diff] [blame] | 46 | |
| 47 | |
Brett Cannon | ee78a2b | 2012-05-12 17:43:17 -0400 | [diff] [blame] | 48 | def find_loader(name, path=None): |
| 49 | """Find the loader for the specified module. |
| 50 | |
| 51 | First, sys.modules is checked to see if the module was already imported. If |
| 52 | so, then sys.modules[name].__loader__ is returned. If that happens to be |
| 53 | set to None, then ValueError is raised. If the module is not in |
| 54 | sys.modules, then sys.meta_path is searched for a suitable loader with the |
| 55 | value of 'path' given to the finders. None is returned if no loader could |
| 56 | be found. |
| 57 | |
Brett Cannon | 56b4ca7 | 2012-11-17 09:30:55 -0500 | [diff] [blame] | 58 | Dotted names do not have their parent packages implicitly imported. You will |
| 59 | most likely need to explicitly import all parent packages in the proper |
| 60 | order for a submodule to get the correct loader. |
Brett Cannon | ee78a2b | 2012-05-12 17:43:17 -0400 | [diff] [blame] | 61 | |
| 62 | """ |
| 63 | try: |
| 64 | loader = sys.modules[name].__loader__ |
| 65 | if loader is None: |
| 66 | raise ValueError('{}.__loader__ is None'.format(name)) |
| 67 | else: |
| 68 | return loader |
| 69 | except KeyError: |
| 70 | pass |
| 71 | return _bootstrap._find_module(name, path) |
| 72 | |
| 73 | |
Brett Cannon | afccd63 | 2009-01-20 02:21:27 +0000 | [diff] [blame] | 74 | def import_module(name, package=None): |
| 75 | """Import a module. |
| 76 | |
| 77 | The 'package' argument is required when performing a relative import. It |
| 78 | specifies the package to use as the anchor point from which to resolve the |
| 79 | relative import to an absolute import. |
| 80 | |
| 81 | """ |
Brett Cannon | 2c318a1 | 2009-02-07 01:15:27 +0000 | [diff] [blame] | 82 | level = 0 |
Brett Cannon | afccd63 | 2009-01-20 02:21:27 +0000 | [diff] [blame] | 83 | if name.startswith('.'): |
| 84 | if not package: |
| 85 | raise TypeError("relative imports require the 'package' argument") |
Brett Cannon | afccd63 | 2009-01-20 02:21:27 +0000 | [diff] [blame] | 86 | for character in name: |
| 87 | if character != '.': |
| 88 | break |
| 89 | level += 1 |
Brett Cannon | 2c318a1 | 2009-02-07 01:15:27 +0000 | [diff] [blame] | 90 | return _bootstrap._gcd_import(name[level:], package, level) |