diff --git a/pex/pex_builder.py b/pex/pex_builder.py index 0663950d9..54b089aa9 100644 --- a/pex/pex_builder.py +++ b/pex/pex_builder.py @@ -119,10 +119,12 @@ def __entry_point_from_filename__(filename): if '__file__' in locals() and __file__ is not None and os.path.exists(__file__): __entry_point__ = __entry_point_from_filename__(__file__) elif '__loader__' in locals(): - from pkgutil import ImpLoader if hasattr(__loader__, 'archive'): __entry_point__ = __loader__.archive - elif isinstance(__loader__, ImpLoader): + elif hasattr(__loader__, 'get_filename'): + # The source of the loader interface has changed over the course of Python history from + # `pkgutil.ImpLoader` to `importlib.abc.Loader`, but the existence and semantics of + # `get_filename` has remained constant; so we just check for the method. __entry_point__ = __entry_point_from_filename__(__loader__.get_filename()) if __entry_point__ is None: diff --git a/pex/third_party/__init__.py b/pex/third_party/__init__.py index 05d4fa1a6..b6140454a 100644 --- a/pex/third_party/__init__.py +++ b/pex/third_party/__init__.py @@ -364,7 +364,16 @@ def uninstall(self): loader.unload() _tracer().log("Uninstalled {}".format(self), V=3) - # The PEP-302 finder API. + def find_spec(self, fullname, path, target=None): + # Python 2.7 does not know about this API and does not use it. + from importlib.util import spec_from_loader # type: ignore[import] + + loader = self.find_module(fullname, path) + if loader: + return spec_from_loader(fullname, loader) + return None + + # The Legacy PEP-302 finder API. # See: https://www.python.org/dev/peps/pep-0302/#specification-part-1-the-importer-protocol def find_module(self, fullname, path=None): for importable in self._importables: