Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/pip/_internal/metadata/__init__.py: 77%
39 statements
« prev ^ index » next coverage.py v7.4.3, created at 2024-02-26 06:33 +0000
« prev ^ index » next coverage.py v7.4.3, created at 2024-02-26 06:33 +0000
1import contextlib
2import functools
3import os
4import sys
5from typing import TYPE_CHECKING, List, Optional, Type, cast
7from pip._internal.utils.misc import strtobool
9from .base import BaseDistribution, BaseEnvironment, FilesystemWheel, MemoryWheel, Wheel
11if TYPE_CHECKING:
12 from typing import Literal, Protocol
13else:
14 Protocol = object
16__all__ = [
17 "BaseDistribution",
18 "BaseEnvironment",
19 "FilesystemWheel",
20 "MemoryWheel",
21 "Wheel",
22 "get_default_environment",
23 "get_environment",
24 "get_wheel_distribution",
25 "select_backend",
26]
29def _should_use_importlib_metadata() -> bool:
30 """Whether to use the ``importlib.metadata`` or ``pkg_resources`` backend.
32 By default, pip uses ``importlib.metadata`` on Python 3.11+, and
33 ``pkg_resourcess`` otherwise. This can be overridden by a couple of ways:
35 * If environment variable ``_PIP_USE_IMPORTLIB_METADATA`` is set, it
36 dictates whether ``importlib.metadata`` is used, regardless of Python
37 version.
38 * On Python 3.11+, Python distributors can patch ``importlib.metadata``
39 to add a global constant ``_PIP_USE_IMPORTLIB_METADATA = False``. This
40 makes pip use ``pkg_resources`` (unless the user set the aforementioned
41 environment variable to *True*).
42 """
43 with contextlib.suppress(KeyError, ValueError):
44 return bool(strtobool(os.environ["_PIP_USE_IMPORTLIB_METADATA"]))
45 if sys.version_info < (3, 11):
46 return False
47 import importlib.metadata
49 return bool(getattr(importlib.metadata, "_PIP_USE_IMPORTLIB_METADATA", True))
52class Backend(Protocol):
53 NAME: 'Literal["importlib", "pkg_resources"]'
54 Distribution: Type[BaseDistribution]
55 Environment: Type[BaseEnvironment]
58@functools.lru_cache(maxsize=None)
59def select_backend() -> Backend:
60 if _should_use_importlib_metadata():
61 from . import importlib
63 return cast(Backend, importlib)
64 from . import pkg_resources
66 return cast(Backend, pkg_resources)
69def get_default_environment() -> BaseEnvironment:
70 """Get the default representation for the current environment.
72 This returns an Environment instance from the chosen backend. The default
73 Environment instance should be built from ``sys.path`` and may use caching
74 to share instance state accorss calls.
75 """
76 return select_backend().Environment.default()
79def get_environment(paths: Optional[List[str]]) -> BaseEnvironment:
80 """Get a representation of the environment specified by ``paths``.
82 This returns an Environment instance from the chosen backend based on the
83 given import paths. The backend must build a fresh instance representing
84 the state of installed distributions when this function is called.
85 """
86 return select_backend().Environment.from_paths(paths)
89def get_directory_distribution(directory: str) -> BaseDistribution:
90 """Get the distribution metadata representation in the specified directory.
92 This returns a Distribution instance from the chosen backend based on
93 the given on-disk ``.dist-info`` directory.
94 """
95 return select_backend().Distribution.from_directory(directory)
98def get_wheel_distribution(wheel: Wheel, canonical_name: str) -> BaseDistribution:
99 """Get the representation of the specified wheel's distribution metadata.
101 This returns a Distribution instance from the chosen backend based on
102 the given wheel's ``.dist-info`` directory.
104 :param canonical_name: Normalized project name of the given wheel.
105 """
106 return select_backend().Distribution.from_wheel(wheel, canonical_name)
109def get_metadata_distribution(
110 metadata_contents: bytes,
111 filename: str,
112 canonical_name: str,
113) -> BaseDistribution:
114 """Get the dist representation of the specified METADATA file contents.
116 This returns a Distribution instance from the chosen backend sourced from the data
117 in `metadata_contents`.
119 :param metadata_contents: Contents of a METADATA file within a dist, or one served
120 via PEP 658.
121 :param filename: Filename for the dist this metadata represents.
122 :param canonical_name: Normalized project name of the given dist.
123 """
124 return select_backend().Distribution.from_metadata_file_contents(
125 metadata_contents,
126 filename,
127 canonical_name,
128 )