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

1import contextlib 

2import functools 

3import os 

4import sys 

5from typing import TYPE_CHECKING, List, Optional, Type, cast 

6 

7from pip._internal.utils.misc import strtobool 

8 

9from .base import BaseDistribution, BaseEnvironment, FilesystemWheel, MemoryWheel, Wheel 

10 

11if TYPE_CHECKING: 

12 from typing import Literal, Protocol 

13else: 

14 Protocol = object 

15 

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] 

27 

28 

29def _should_use_importlib_metadata() -> bool: 

30 """Whether to use the ``importlib.metadata`` or ``pkg_resources`` backend. 

31 

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: 

34 

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 

48 

49 return bool(getattr(importlib.metadata, "_PIP_USE_IMPORTLIB_METADATA", True)) 

50 

51 

52class Backend(Protocol): 

53 NAME: 'Literal["importlib", "pkg_resources"]' 

54 Distribution: Type[BaseDistribution] 

55 Environment: Type[BaseEnvironment] 

56 

57 

58@functools.lru_cache(maxsize=None) 

59def select_backend() -> Backend: 

60 if _should_use_importlib_metadata(): 

61 from . import importlib 

62 

63 return cast(Backend, importlib) 

64 from . import pkg_resources 

65 

66 return cast(Backend, pkg_resources) 

67 

68 

69def get_default_environment() -> BaseEnvironment: 

70 """Get the default representation for the current environment. 

71 

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() 

77 

78 

79def get_environment(paths: Optional[List[str]]) -> BaseEnvironment: 

80 """Get a representation of the environment specified by ``paths``. 

81 

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) 

87 

88 

89def get_directory_distribution(directory: str) -> BaseDistribution: 

90 """Get the distribution metadata representation in the specified directory. 

91 

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) 

96 

97 

98def get_wheel_distribution(wheel: Wheel, canonical_name: str) -> BaseDistribution: 

99 """Get the representation of the specified wheel's distribution metadata. 

100 

101 This returns a Distribution instance from the chosen backend based on 

102 the given wheel's ``.dist-info`` directory. 

103 

104 :param canonical_name: Normalized project name of the given wheel. 

105 """ 

106 return select_backend().Distribution.from_wheel(wheel, canonical_name) 

107 

108 

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. 

115 

116 This returns a Distribution instance from the chosen backend sourced from the data 

117 in `metadata_contents`. 

118 

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 )