|
11 | 11 | from pip import __version__ as current_version
|
12 | 12 |
|
13 | 13 | DEPRECATION_MSG_PREFIX = "DEPRECATION: "
|
| 14 | +DEPRECATION_MESSAGE = DEPRECATION_MSG_PREFIX + "{reason}" |
| 15 | +GONE_IN_MESSAGE_FUTURE = "pip {gone_in} will enforce this behavior change." |
| 16 | +GONE_IN_MESSAGE_PAST = "This behavior change has been enforced since pip {gone_in}." |
| 17 | +REPLACEMENT_MESSAGE = "A possible replacement is {replacement}." |
| 18 | +FEATURE_FLAG_MESSAGE = ( |
| 19 | + "You can temporarily use the flag --use-feature={feature_flag} " |
| 20 | + "to test the upcoming behavior." |
| 21 | +) |
| 22 | +ISSUE_MESSAGE = "Discussion can be found at https://github.com/pypa/pip/issues/{issue}." |
14 | 23 |
|
15 | 24 |
|
16 | 25 | class PipDeprecationWarning(Warning):
|
@@ -56,49 +65,63 @@ def deprecated(
|
56 | 65 | reason: str,
|
57 | 66 | replacement: Optional[str],
|
58 | 67 | gone_in: Optional[str],
|
| 68 | + feature_flag: Optional[str] = None, |
59 | 69 | issue: Optional[int] = None,
|
60 | 70 | ) -> None:
|
61 | 71 | """Helper to deprecate existing functionality.
|
62 | 72 |
|
63 | 73 | reason:
|
64 | 74 | Textual reason shown to the user about why this functionality has
|
65 |
| - been deprecated. |
| 75 | + been deprecated. Should be a complete sentence. |
66 | 76 | replacement:
|
67 | 77 | Textual suggestion shown to the user about what alternative
|
68 | 78 | functionality they can use.
|
69 | 79 | gone_in:
|
70 | 80 | The version of pip does this functionality should get removed in.
|
71 |
| - Raises errors if pip's current version is greater than or equal to |
| 81 | + Raises an error if pip's current version is greater than or equal to |
72 | 82 | this.
|
| 83 | + feature_flag: |
| 84 | + Command-line flag of the form --use-feature={feature_flag} for testing |
| 85 | + upcoming functionality. |
73 | 86 | issue:
|
74 | 87 | Issue number on the tracker that would serve as a useful place for
|
75 | 88 | users to find related discussion and provide feedback.
|
76 | 89 |
|
77 | 90 | Always pass replacement, gone_in and issue as keyword arguments for clarity
|
78 | 91 | at the call site.
|
79 | 92 | """
|
80 |
| - |
| 93 | + # Determine whether or not the feature is already gone in this version. |
| 94 | + is_gone = gone_in is not None and parse(current_version) >= parse(gone_in) |
| 95 | + # Allow variable substitutions within the "reason" variable. |
| 96 | + formatted_reason = reason.format(gone_in=gone_in) |
81 | 97 | # Construct a nice message.
|
82 | 98 | # This is eagerly formatted as we want it to get logged as if someone
|
83 | 99 | # typed this entire message out.
|
| 100 | + formatted_deprecation_message = DEPRECATION_MESSAGE.format(reason=formatted_reason) |
| 101 | + gone_in_message = GONE_IN_MESSAGE_PAST if is_gone else GONE_IN_MESSAGE_FUTURE |
| 102 | + formatted_gone_in_message = ( |
| 103 | + gone_in_message.format(gone_in=gone_in) if gone_in else None |
| 104 | + ) |
| 105 | + formatted_replacement_message = ( |
| 106 | + REPLACEMENT_MESSAGE.format(replacement=replacement) if replacement else None |
| 107 | + ) |
| 108 | + formatted_feature_flag_message = ( |
| 109 | + None |
| 110 | + if is_gone or not feature_flag |
| 111 | + else FEATURE_FLAG_MESSAGE.format(feature_flag=feature_flag) |
| 112 | + ) |
| 113 | + formatted_issue_message = ISSUE_MESSAGE.format(issue=issue) if issue else None |
84 | 114 | sentences = [
|
85 |
| - (reason, DEPRECATION_MSG_PREFIX + "{}"), |
86 |
| - (gone_in, "pip {} will remove support for this functionality."), |
87 |
| - (replacement, "A possible replacement is {}."), |
88 |
| - ( |
89 |
| - issue, |
90 |
| - ( |
91 |
| - "You can find discussion regarding this at " |
92 |
| - "https://github.com/pypa/pip/issues/{}." |
93 |
| - ), |
94 |
| - ), |
| 115 | + formatted_deprecation_message, |
| 116 | + formatted_gone_in_message, |
| 117 | + formatted_replacement_message, |
| 118 | + formatted_feature_flag_message, |
| 119 | + formatted_issue_message, |
95 | 120 | ]
|
96 |
| - message = " ".join( |
97 |
| - template.format(val) for val, template in sentences if val is not None |
98 |
| - ) |
| 121 | + message = " ".join(sentence for sentence in sentences if sentence) |
99 | 122 |
|
100 |
| - # Raise as an error if it has to be removed. |
101 |
| - if gone_in is not None and parse(current_version) >= parse(gone_in): |
| 123 | + # Raise as an error if the functionality is gone. |
| 124 | + if is_gone: |
102 | 125 | raise PipDeprecationWarning(message)
|
103 |
| - |
104 |
| - warnings.warn(message, category=PipDeprecationWarning, stacklevel=2) |
| 126 | + else: |
| 127 | + warnings.warn(message, category=PipDeprecationWarning, stacklevel=2) |
0 commit comments