Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/pip/_internal/metadata/__init__.py: 76%

38 statements  

« prev     ^ index     » next       coverage.py v7.2.7, created at 2023-06-07 06:48 +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 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 Distribution: Type[BaseDistribution] 

54 Environment: Type[BaseEnvironment] 

55 

56 

57@functools.lru_cache(maxsize=None) 

58def select_backend() -> Backend: 

59 if _should_use_importlib_metadata(): 

60 from . import importlib 

61 

62 return cast(Backend, importlib) 

63 from . import pkg_resources 

64 

65 return cast(Backend, pkg_resources) 

66 

67 

68def get_default_environment() -> BaseEnvironment: 

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

70 

71 This returns an Environment instance from the chosen backend. The default 

72 Environment instance should be built from ``sys.path`` and may use caching 

73 to share instance state accorss calls. 

74 """ 

75 return select_backend().Environment.default() 

76 

77 

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

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

80 

81 This returns an Environment instance from the chosen backend based on the 

82 given import paths. The backend must build a fresh instance representing 

83 the state of installed distributions when this function is called. 

84 """ 

85 return select_backend().Environment.from_paths(paths) 

86 

87 

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

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

90 

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

92 the given on-disk ``.dist-info`` directory. 

93 """ 

94 return select_backend().Distribution.from_directory(directory) 

95 

96 

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

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

99 

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

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

102 

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

104 """ 

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

106 

107 

108def get_metadata_distribution( 

109 metadata_contents: bytes, 

110 filename: str, 

111 canonical_name: str, 

112) -> BaseDistribution: 

113 """Get the dist representation of the specified METADATA file contents. 

114 

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

116 in `metadata_contents`. 

117 

118 :param metadata_contents: Contents of a METADATA file within a dist, or one served 

119 via PEP 658. 

120 :param filename: Filename for the dist this metadata represents. 

121 :param canonical_name: Normalized project name of the given dist. 

122 """ 

123 return select_backend().Distribution.from_metadata_file_contents( 

124 metadata_contents, 

125 filename, 

126 canonical_name, 

127 )