From 553fa553539c5ead530413bb614019de6191d7d4 Mon Sep 17 00:00:00 2001 From: John Sirois Date: Tue, 4 Jul 2023 17:05:54 -0700 Subject: [PATCH 1/3] Adapt to removed stdlib APIs in Python 3.12. --- pex/pex_builder.py | 12 +++++++++--- pex/third_party/__init__.py | 11 ++++++++++- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/pex/pex_builder.py b/pex/pex_builder.py index 0663950d9..3b3f1f1fa 100644 --- a/pex/pex_builder.py +++ b/pex/pex_builder.py @@ -119,11 +119,17 @@ 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): - __entry_point__ = __entry_point_from_filename__(__loader__.get_filename()) + else: + try: + from pkgutil import ImpLoader + if isinstance(__loader__, ImpLoader): + __entry_point__ = __entry_point_from_filename__(__loader__.get_filename()) + except ImportError: + from importlib.abc import Loader + if isinstance(__loader__, Loader): + __entry_point__ = __entry_point_from_filename__(__loader__.get_filename()) if __entry_point__ is None: sys.stderr.write('Could not launch python executable!\\n') 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: From 8644bdc39ae0a1fb9fe54e6069dbcfe87b27998a Mon Sep 17 00:00:00 2001 From: John Sirois Date: Tue, 4 Jul 2023 17:20:38 -0700 Subject: [PATCH 2/3] Flip the import order to favor Python 3.4+. --- pex/pex_builder.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pex/pex_builder.py b/pex/pex_builder.py index 3b3f1f1fa..96486586b 100644 --- a/pex/pex_builder.py +++ b/pex/pex_builder.py @@ -123,13 +123,13 @@ def __entry_point_from_filename__(filename): __entry_point__ = __loader__.archive else: try: - from pkgutil import ImpLoader - if isinstance(__loader__, ImpLoader): - __entry_point__ = __entry_point_from_filename__(__loader__.get_filename()) - except ImportError: from importlib.abc import Loader if isinstance(__loader__, Loader): __entry_point__ = __entry_point_from_filename__(__loader__.get_filename()) + except ImportError: + from pkgutil import ImpLoader + if isinstance(__loader__, ImpLoader): + __entry_point__ = __entry_point_from_filename__(__loader__.get_filename()) if __entry_point__ is None: sys.stderr.write('Could not launch python executable!\\n') From b733fd229f8ed66b004d3ae672d005c26f90fef7 Mon Sep 17 00:00:00 2001 From: John Sirois Date: Wed, 5 Jul 2023 08:43:32 -0700 Subject: [PATCH 3/3] Feedback prompted simplification. --- pex/pex_builder.py | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/pex/pex_builder.py b/pex/pex_builder.py index 96486586b..54b089aa9 100644 --- a/pex/pex_builder.py +++ b/pex/pex_builder.py @@ -121,15 +121,11 @@ def __entry_point_from_filename__(filename): elif '__loader__' in locals(): if hasattr(__loader__, 'archive'): __entry_point__ = __loader__.archive - else: - try: - from importlib.abc import Loader - if isinstance(__loader__, Loader): - __entry_point__ = __entry_point_from_filename__(__loader__.get_filename()) - except ImportError: - from pkgutil import ImpLoader - if isinstance(__loader__, ImpLoader): - __entry_point__ = __entry_point_from_filename__(__loader__.get_filename()) + 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: sys.stderr.write('Could not launch python executable!\\n')