Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/pip/_internal/utils/deprecation.py: 41%

29 statements  

« prev     ^ index     » next       coverage.py v7.2.7, created at 2023-06-07 06:48 +0000

1""" 

2A module that implements tooling to enable easy warnings about deprecations. 

3""" 

4 

5import logging 

6import warnings 

7from typing import Any, Optional, TextIO, Type, Union 

8 

9from pip._vendor.packaging.version import parse 

10 

11from pip import __version__ as current_version # NOTE: tests patch this name. 

12 

13DEPRECATION_MSG_PREFIX = "DEPRECATION: " 

14 

15 

16class PipDeprecationWarning(Warning): 

17 pass 

18 

19 

20_original_showwarning: Any = None 

21 

22 

23# Warnings <-> Logging Integration 

24def _showwarning( 

25 message: Union[Warning, str], 

26 category: Type[Warning], 

27 filename: str, 

28 lineno: int, 

29 file: Optional[TextIO] = None, 

30 line: Optional[str] = None, 

31) -> None: 

32 if file is not None: 

33 if _original_showwarning is not None: 

34 _original_showwarning(message, category, filename, lineno, file, line) 

35 elif issubclass(category, PipDeprecationWarning): 

36 # We use a specially named logger which will handle all of the 

37 # deprecation messages for pip. 

38 logger = logging.getLogger("pip._internal.deprecations") 

39 logger.warning(message) 

40 else: 

41 _original_showwarning(message, category, filename, lineno, file, line) 

42 

43 

44def install_warning_logger() -> None: 

45 # Enable our Deprecation Warnings 

46 warnings.simplefilter("default", PipDeprecationWarning, append=True) 

47 

48 global _original_showwarning 

49 

50 if _original_showwarning is None: 

51 _original_showwarning = warnings.showwarning 

52 warnings.showwarning = _showwarning 

53 

54 

55def deprecated( 

56 *, 

57 reason: str, 

58 replacement: Optional[str], 

59 gone_in: Optional[str], 

60 feature_flag: Optional[str] = None, 

61 issue: Optional[int] = None, 

62) -> None: 

63 """Helper to deprecate existing functionality. 

64 

65 reason: 

66 Textual reason shown to the user about why this functionality has 

67 been deprecated. Should be a complete sentence. 

68 replacement: 

69 Textual suggestion shown to the user about what alternative 

70 functionality they can use. 

71 gone_in: 

72 The version of pip does this functionality should get removed in. 

73 Raises an error if pip's current version is greater than or equal to 

74 this. 

75 feature_flag: 

76 Command-line flag of the form --use-feature={feature_flag} for testing 

77 upcoming functionality. 

78 issue: 

79 Issue number on the tracker that would serve as a useful place for 

80 users to find related discussion and provide feedback. 

81 """ 

82 

83 # Determine whether or not the feature is already gone in this version. 

84 is_gone = gone_in is not None and parse(current_version) >= parse(gone_in) 

85 

86 message_parts = [ 

87 (reason, f"{DEPRECATION_MSG_PREFIX}{{}}"), 

88 ( 

89 gone_in, 

90 "pip {} will enforce this behaviour change." 

91 if not is_gone 

92 else "Since pip {}, this is no longer supported.", 

93 ), 

94 ( 

95 replacement, 

96 "A possible replacement is {}.", 

97 ), 

98 ( 

99 feature_flag, 

100 "You can use the flag --use-feature={} to test the upcoming behaviour." 

101 if not is_gone 

102 else None, 

103 ), 

104 ( 

105 issue, 

106 "Discussion can be found at https://github.com/pypa/pip/issues/{}", 

107 ), 

108 ] 

109 

110 message = " ".join( 

111 format_str.format(value) 

112 for value, format_str in message_parts 

113 if format_str is not None and value is not None 

114 ) 

115 

116 # Raise as an error if this behaviour is deprecated. 

117 if is_gone: 

118 raise PipDeprecationWarning(message) 

119 

120 warnings.warn(message, category=PipDeprecationWarning, stacklevel=2)