-
-
Notifications
You must be signed in to change notification settings - Fork 292
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix pex force local to handle PEP-420.
Previously, pex would blow up trying to adjust import paths if a PEP-420 implicit namespace package was encountered. Add a test of the path adjustment functionality both to confirm it was needed (it was) and that the fix technique works with all forms of namespace packages by only assuming they support `append`. Fixes #598
- Loading branch information
Showing
7 changed files
with
437 additions
and
113 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
# coding=utf-8 | ||
# Copyright 2018 Pants project contributors (see CONTRIBUTORS.md). | ||
# Licensed under the Apache License, Version 2.0 (see LICENSE). | ||
|
||
import os | ||
|
||
|
||
class Bootstrap(object): | ||
"""Supports introspection of the PEX bootstrap code.""" | ||
|
||
_INSTANCE = None | ||
|
||
@classmethod | ||
def locate(cls): | ||
"""Locates the active PEX bootstrap. | ||
:rtype: :class:`Bootstrap` | ||
""" | ||
if cls._INSTANCE is None: | ||
bootstrap_path = __file__ | ||
module_import_path = __name__.split('.') | ||
|
||
# For example, our __file__ might be requests.pex/.bootstrap/pex/bootstrap.pyc and our import | ||
# path pex.bootstrap; so we walk back through all the module components of our import path to | ||
# find the base sys.path entry where we were found (requests.pex/.bootstrap in this example). | ||
for _ in module_import_path: | ||
bootstrap_path = os.path.dirname(bootstrap_path) | ||
|
||
cls._INSTANCE = cls(path_entry=bootstrap_path) | ||
return cls._INSTANCE | ||
|
||
def __init__(self, path_entry): | ||
self._path_entry = path_entry | ||
|
||
def demote(self, log): | ||
"""Demote the bootstrap code to the end of the `sys.path` so it is found last.""" | ||
import sys # Grab a hold of `sys` early since we'll be unimporting our module in this process. | ||
|
||
log('Demoting bootstrap code %s' % self._path_entry, V=2) | ||
for name, module in reversed(sorted(sys.modules.items())): | ||
if self.imported_from_bootstrap(module): | ||
sys.modules.pop(name) | ||
log('un-imported {}'.format(name), V=9) | ||
|
||
sys.path.remove(self._path_entry) | ||
sys.path.append(self._path_entry) | ||
|
||
def imported_from_bootstrap(self, module): | ||
"""Return ``True`` if the given ``module_name`` was imported from bootstrap code. | ||
:rtype: bool | ||
""" | ||
# Otherwise we may have an exposed vendored module whose name is not in the root set, but whose | ||
# import comes from our path entry. EG: `pkg_resources` imported from | ||
# `.bootstrap/pex/vendor/_vendored/setuptools/pkg_resources/__init__.py` | ||
|
||
# A vendored module. | ||
path = getattr(module, '__file__', None) | ||
if path and path.startswith(self._path_entry): | ||
return True | ||
|
||
# A vendored package. | ||
path = getattr(module, '__path__', None) | ||
if path: | ||
for path in path: | ||
if path.startswith(self._path_entry): | ||
return True | ||
|
||
return False |
Oops, something went wrong.