Allow use of importlib.metadata for finding entrypoints#1102
Conversation
055e115 to
6017ad0
Compare
6017ad0 to
6395653
Compare
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #1102 +/- ##
==========================================
- Coverage 91.29% 91.21% -0.08%
==========================================
Files 26 27 +1
Lines 4479 4496 +17
==========================================
+ Hits 4089 4101 +12
- Misses 390 395 +5
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. |
babel/messages/_compat.py
Outdated
| try: | ||
| from importlib.metadata import entry_points | ||
| except ImportError: | ||
| pass | ||
| else: | ||
| eps = entry_points() | ||
| if isinstance(eps, dict): # Old structure before Python 3.10 | ||
| group_eps = eps.get(group_name, []) | ||
| else: # New structure in Python 3.10+ | ||
| group_eps = (ep for ep in eps if ep.group == group_name) | ||
| for entry_point in group_eps: | ||
| yield (entry_point.name, entry_point.load) | ||
| return | ||
|
|
||
| try: | ||
| from pkg_resources import working_set | ||
| except ImportError: | ||
| pass | ||
| else: | ||
| for entry_point in working_set.iter_entry_points(group_name): | ||
| yield (entry_point.name, partial(entry_point.load, require=True)) |
There was a problem hiding this comment.
As my colleague @j123b567 rightly noted, for versions before 3.10, it is better to use pkg_resources, as the importlib.metadata API is still unstable.
You can use pkg_resources as the first handler, and in the second try block, ensure to verify that the eps object is not a dictionary before processing entry points. Otherwise, simply continue the function execution.
Consider this option as well.
There was a problem hiding this comment.
Could you post this as a code suggestion so it's easier to see what you mean?
There was a problem hiding this comment.
| try: | |
| from importlib.metadata import entry_points | |
| except ImportError: | |
| pass | |
| else: | |
| eps = entry_points() | |
| if isinstance(eps, dict): # Old structure before Python 3.10 | |
| group_eps = eps.get(group_name, []) | |
| else: # New structure in Python 3.10+ | |
| group_eps = (ep for ep in eps if ep.group == group_name) | |
| for entry_point in group_eps: | |
| yield (entry_point.name, entry_point.load) | |
| return | |
| try: | |
| from pkg_resources import working_set | |
| except ImportError: | |
| pass | |
| else: | |
| for entry_point in working_set.iter_entry_points(group_name): | |
| yield (entry_point.name, partial(entry_point.load, require=True)) | |
| try: | |
| from pkg_resources import working_set | |
| except ImportError: | |
| pass | |
| else: | |
| for entry_point in working_set.iter_entry_points(group_name): | |
| yield (entry_point.name, partial(entry_point.load, require=True)) | |
| return | |
| try: | |
| from importlib.metadata import entry_points | |
| except ImportError: | |
| pass | |
| else: | |
| eps = entry_points() | |
| if not isinstance(eps, dict): # New structure in Python 3.10+ | |
| group_eps = (ep for ep in eps if ep.group == group_name) | |
| for entry_point in group_eps: | |
| yield (entry_point.name, entry_point.load) |
There was a problem hiding this comment.
Good idea – I pushed a commit with a variation on this idea, namely to only even try importlib.metadata on Python 3.10+, when we know it will be stable.
There was a problem hiding this comment.
In my initial local implementation, there was a strict check for the Python version, but we decided @j123b567 to abandon this approach since various Python interpreters (e.g., PyPy) and, consequently, different standard modules can be used. My proposed version is universal and not tied to a specific version, but only to the availability of the library if pkg_resources is missing
| # "Changed in version 3.10: importlib.metadata is no longer provisional." | ||
| try: | ||
| from importlib.metadata import entry_points | ||
| except ImportError: |
There was a problem hiding this comment.
Is the try/except block needed if we have an explicit version check? importlib.metadata should always be available on 3.10+
There was a problem hiding this comment.
Is the try/except block needed if we have an explicit version check?
importlib.metadatashould always be available on 3.10+
There was a problem hiding this comment.
As @podgorniy94 mentioned, I think it's a good thing to double-check, for supporting some more esoteric environments.
There was a problem hiding this comment.
As @podgorniy94 mentioned, I think it's a good thing to double-check, for supporting some more esoteric environments.
Actually, there's no need to check the Python version. We simply try pkg_resources, and if the library isn't available, then we attempt importlib.metadata. To avoid strict version checking for, as you said, esoteric environments where there might be different version labeling :) What do you think?
There was a problem hiding this comment.
Yes and no – using pkg_resources where it's deprecated will raise a DeprecationWarning, which in some (in e.g. my work-work) environments deprecation warnings are hard errors in tests.
e012487 to
c5434d4
Compare
For Python 3.12 compatibility! Co-authored-by: podgorniy94 <podgorniy.inc@gmail.com>
c5434d4 to
7a029e0
Compare
Closes #1093 (supersedes it, based on it).
Refs #861.
This PR makes Babel attempt to use
importlib.metadatainstead ofpkg_resourceswhere available.It also adds a test that proves the Jinja2 extractor also works on Python 3.12; this is ran in CI as well.