From bd9bcef8b3262c513a0dd614731cfe8db8d64125 Mon Sep 17 00:00:00 2001 From: Tzu-ping Chung Date: Tue, 19 Apr 2022 17:08:57 +0800 Subject: [PATCH] Enable importlib.metadata backend on Python 3.11 --- .github/workflows/ci.yml | 4 ++-- news/11044.process.rst | 4 ++++ src/pip/_internal/metadata/__init__.py | 29 +++++++++++++++++++++++++- 3 files changed, 34 insertions(+), 3 deletions(-) create mode 100644 news/11044.process.rst diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f0b8ba644..e467b3e50 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -219,11 +219,12 @@ jobs: env: TEMP: "R:\\Temp" + # TODO: Remove this when we add Python 3.11 to CI. tests-importlib-metadata: name: tests for importlib.metadata backend runs-on: ubuntu-latest env: - _PIP_METADATA_BACKEND_IMPORTLIB: egg-compat + _PIP_USE_IMPORTLIB_METADATA: 'true' needs: [pre-commit, packaging, determine-changes] if: >- @@ -241,7 +242,6 @@ jobs: - run: pip install nox 'virtualenv<20' - # Main check - name: Run unit tests run: >- nox -s test-3.10 -- diff --git a/news/11044.process.rst b/news/11044.process.rst new file mode 100644 index 000000000..d33fc74d8 --- /dev/null +++ b/news/11044.process.rst @@ -0,0 +1,4 @@ +Enable the ``importlib.metadata`` metadata implementation by default on +Python 3.11 (or later). The environment variable ``_PIP_USE_IMPORTLIB_METADATA`` +can still be used to enable the implementation on 3.10 and earlier, or disable +it on 3.11 (by setting it to ``0`` or ``false``). diff --git a/src/pip/_internal/metadata/__init__.py b/src/pip/_internal/metadata/__init__.py index aa9a80822..01c35f94b 100644 --- a/src/pip/_internal/metadata/__init__.py +++ b/src/pip/_internal/metadata/__init__.py @@ -1,7 +1,11 @@ +import contextlib import functools import os +import sys from typing import TYPE_CHECKING, List, Optional, Type, cast +from pip._internal.utils.misc import strtobool + from .base import BaseDistribution, BaseEnvironment, FilesystemWheel, MemoryWheel, Wheel if TYPE_CHECKING: @@ -22,6 +26,29 @@ __all__ = [ ] +def _should_use_importlib_metadata() -> bool: + """Whether to use the ``importlib.metadata`` or ``pkg_resources`` backend. + + By default, pip uses ``importlib.metadata`` on Python 3.11+, and + ``pkg_resourcess`` otherwise. This can be overriden by a couple of ways: + + * If environment variable ``_PIP_USE_IMPORTLIB_METADATA`` is set, it + dictates whether ``importlib.metadata`` is used, regardless of Python + version. + * On Python 3.11+, Python distributors can patch ``importlib.metadata`` + to add a global constant ``_PIP_USE_IMPORTLIB_METADATA = False``. This + makes pip use ``pkg_resources`` (unless the user set the aforementioned + environment variable to *True*). + """ + with contextlib.suppress(KeyError, ValueError): + return bool(strtobool(os.environ["_PIP_USE_IMPORTLIB_METADATA"])) + if sys.version_info < (3, 11): + return False + import importlib.metadata + + return bool(getattr(importlib.metadata, "_PIP_USE_IMPORTLIB_METADATA", True)) + + class Backend(Protocol): Distribution: Type[BaseDistribution] Environment: Type[BaseEnvironment] @@ -29,7 +56,7 @@ class Backend(Protocol): @functools.lru_cache(maxsize=None) def select_backend() -> Backend: - if os.environ.get("_PIP_METADATA_BACKEND_IMPORTLIB"): + if _should_use_importlib_metadata(): from . import importlib return cast(Backend, importlib)