diff options
author | Jason R. Coombs <jaraco@jaraco.com> | 2016-01-02 14:02:35 -0500 |
---|---|---|
committer | Jason R. Coombs <jaraco@jaraco.com> | 2016-01-02 14:02:35 -0500 |
commit | 1aafa9ca06881c5c90577fc4449c41ef692c5220 (patch) | |
tree | f3e4b02d3457fce478effbb496f862c0968ab759 | |
parent | fdcd02418087259b71bf7753cf1c528d34e638e6 (diff) | |
download | python-setuptools-bitbucket-1aafa9ca06881c5c90577fc4449c41ef692c5220.tar.gz |
Create a PEP 302 importer for managing conditional import of vendored packages from the 'extern' namespace. This technique avoids the use of 'imp' and works even when setuptools is installed as a zipped egg. Ref #229.
-rw-r--r-- | pkg_resources/extern/__init__.py | 42 | ||||
-rw-r--r-- | pkg_resources/extern/packaging/__init__.py | 45 | ||||
-rw-r--r-- | setuptools/extern/__init__.py | 42 | ||||
-rw-r--r-- | setuptools/extern/six.py | 45 |
4 files changed, 84 insertions, 90 deletions
diff --git a/pkg_resources/extern/__init__.py b/pkg_resources/extern/__init__.py index e69de29b..3b3076c0 100644 --- a/pkg_resources/extern/__init__.py +++ b/pkg_resources/extern/__init__.py @@ -0,0 +1,42 @@ +import sys + +_VENDORED_NAMES = 'packaging', +_SEARCH_PATH = 'pkg_resources._vendor.', '' + +class VendorImporter: + """ + A PEP 302 meta path importer for finding optionally-vendored + or otherwise naturally-installed packages from __name__. + """ + def find_module(self, fullname, path=None): + root, base, target = fullname.partition(__name__ + '.') + if root: + return + if not any(map(target.startswith, _VENDORED_NAMES)): + return + return self + + def load_module(self, fullname): + root, base, target = fullname.partition(__name__ + '.') + for prefix in _SEARCH_PATH: + try: + __import__(prefix + target) + mod = sys.modules[prefix + target] + sys.modules[fullname] = mod + return mod + except ImportError: + pass + else: + raise ImportError( + "The '{target}' package is required; " + "normally this is bundled with this package so if you get " + "this warning, consult the packager of your " + "distribution.".format(**locals()) + ) + + @classmethod + def install(cls): + if not any(isinstance(imp, cls) for imp in sys.meta_path): + sys.meta_path.append(cls()) + +VendorImporter.install() diff --git a/pkg_resources/extern/packaging/__init__.py b/pkg_resources/extern/packaging/__init__.py deleted file mode 100644 index 47f58eab..00000000 --- a/pkg_resources/extern/packaging/__init__.py +++ /dev/null @@ -1,45 +0,0 @@ -""" -Handle loading a package from system or from the bundled copy -""" - -import imp - - -_SEARCH_PATH = ['pkg_resources._vendor.packaging', 'packaging'] - - -def _find_module(name, path=None): - """ - Alternative to `imp.find_module` that can also search in subpackages. - """ - - parts = name.split('.') - - for part in parts: - if path is not None: - path = [path] - - fh, path, descr = imp.find_module(part, path) - - return fh, path, descr - - -def _import_in_place(search_path=_SEARCH_PATH): - for mod_name in search_path: - try: - mod_info = _find_module(mod_name) - except ImportError: - continue - - imp.load_module(__name__, *mod_info) - break - - else: - raise ImportError( - "The '{name}' package is required; " - "normally this is bundled with this package so if you get " - "this warning, consult the packager of your " - "distribution.".format(name=_SEARCH_PATH[-1])) - - -_import_in_place() diff --git a/setuptools/extern/__init__.py b/setuptools/extern/__init__.py index e69de29b..803d9e9a 100644 --- a/setuptools/extern/__init__.py +++ b/setuptools/extern/__init__.py @@ -0,0 +1,42 @@ +import sys + +_VENDORED_NAMES = 'six', +_SEARCH_PATH = 'setuptools._vendor.', '' + +class VendorImporter: + """ + A PEP 302 meta path importer for finding optionally-vendored + or otherwise naturally-installed packages from __name__. + """ + def find_module(self, fullname, path=None): + root, base, target = fullname.partition(__name__ + '.') + if root: + return + if not any(map(target.startswith, _VENDORED_NAMES)): + return + return self + + def load_module(self, fullname): + root, base, target = fullname.partition(__name__ + '.') + for prefix in _SEARCH_PATH: + try: + __import__(prefix + target) + mod = sys.modules[prefix + target] + sys.modules[fullname] = mod + return mod + except ImportError: + pass + else: + raise ImportError( + "The '{target}' package is required; " + "normally this is bundled with this package so if you get " + "this warning, consult the packager of your " + "distribution.".format(**locals()) + ) + + @classmethod + def install(cls): + if not any(isinstance(imp, cls) for imp in sys.meta_path): + sys.meta_path.append(cls()) + +VendorImporter.install() diff --git a/setuptools/extern/six.py b/setuptools/extern/six.py deleted file mode 100644 index 6076c208..00000000 --- a/setuptools/extern/six.py +++ /dev/null @@ -1,45 +0,0 @@ -""" -Handle loading a package from system or from the bundled copy -""" - -import imp - - -_SEARCH_PATH = ['setuptools._vendor.six', 'six'] - - -def _find_module(name, path=None): - """ - Alternative to `imp.find_module` that can also search in subpackages. - """ - - parts = name.split('.') - - for part in parts: - if path is not None: - path = [path] - - fh, path, descr = imp.find_module(part, path) - - return fh, path, descr - - -def _import_in_place(search_path=_SEARCH_PATH): - for mod_name in search_path: - try: - mod_info = _find_module(mod_name) - except ImportError: - continue - - imp.load_module(__name__, *mod_info) - break - - else: - raise ImportError( - "The '{name}' package is required; " - "normally this is bundled with this package so if you get " - "this warning, consult the packager of your " - "distribution.".format(name=_SEARCH_PATH[-1])) - - -_import_in_place() |