You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							121 lines
						
					
					
						
							3.5 KiB
						
					
					
				
			
		
		
	
	
							121 lines
						
					
					
						
							3.5 KiB
						
					
					
				"""
 | 
						|
A module that implements tooling to enable easy warnings about deprecations.
 | 
						|
"""
 | 
						|
 | 
						|
import logging
 | 
						|
import warnings
 | 
						|
from typing import Any, Optional, TextIO, Type, Union
 | 
						|
 | 
						|
from pip._vendor.packaging.version import parse
 | 
						|
 | 
						|
from pip import __version__ as current_version  # NOTE: tests patch this name.
 | 
						|
 | 
						|
DEPRECATION_MSG_PREFIX = "DEPRECATION: "
 | 
						|
 | 
						|
 | 
						|
class PipDeprecationWarning(Warning):
 | 
						|
    pass
 | 
						|
 | 
						|
 | 
						|
_original_showwarning: Any = None
 | 
						|
 | 
						|
 | 
						|
# Warnings <-> Logging Integration
 | 
						|
def _showwarning(
 | 
						|
    message: Union[Warning, str],
 | 
						|
    category: Type[Warning],
 | 
						|
    filename: str,
 | 
						|
    lineno: int,
 | 
						|
    file: Optional[TextIO] = None,
 | 
						|
    line: Optional[str] = None,
 | 
						|
) -> None:
 | 
						|
    if file is not None:
 | 
						|
        if _original_showwarning is not None:
 | 
						|
            _original_showwarning(message, category, filename, lineno, file, line)
 | 
						|
    elif issubclass(category, PipDeprecationWarning):
 | 
						|
        # We use a specially named logger which will handle all of the
 | 
						|
        # deprecation messages for pip.
 | 
						|
        logger = logging.getLogger("pip._internal.deprecations")
 | 
						|
        logger.warning(message)
 | 
						|
    else:
 | 
						|
        _original_showwarning(message, category, filename, lineno, file, line)
 | 
						|
 | 
						|
 | 
						|
def install_warning_logger() -> None:
 | 
						|
    # Enable our Deprecation Warnings
 | 
						|
    warnings.simplefilter("default", PipDeprecationWarning, append=True)
 | 
						|
 | 
						|
    global _original_showwarning
 | 
						|
 | 
						|
    if _original_showwarning is None:
 | 
						|
        _original_showwarning = warnings.showwarning
 | 
						|
        warnings.showwarning = _showwarning
 | 
						|
 | 
						|
 | 
						|
def deprecated(
 | 
						|
    *,
 | 
						|
    reason: str,
 | 
						|
    replacement: Optional[str],
 | 
						|
    gone_in: Optional[str],
 | 
						|
    feature_flag: Optional[str] = None,
 | 
						|
    issue: Optional[int] = None,
 | 
						|
) -> None:
 | 
						|
    """Helper to deprecate existing functionality.
 | 
						|
 | 
						|
    reason:
 | 
						|
        Textual reason shown to the user about why this functionality has
 | 
						|
        been deprecated. Should be a complete sentence.
 | 
						|
    replacement:
 | 
						|
        Textual suggestion shown to the user about what alternative
 | 
						|
        functionality they can use.
 | 
						|
    gone_in:
 | 
						|
        The version of pip does this functionality should get removed in.
 | 
						|
        Raises an error if pip's current version is greater than or equal to
 | 
						|
        this.
 | 
						|
    feature_flag:
 | 
						|
        Command-line flag of the form --use-feature={feature_flag} for testing
 | 
						|
        upcoming functionality.
 | 
						|
    issue:
 | 
						|
        Issue number on the tracker that would serve as a useful place for
 | 
						|
        users to find related discussion and provide feedback.
 | 
						|
    """
 | 
						|
 | 
						|
    # Determine whether or not the feature is already gone in this version.
 | 
						|
    is_gone = gone_in is not None and parse(current_version) >= parse(gone_in)
 | 
						|
 | 
						|
    message_parts = [
 | 
						|
        (reason, f"{DEPRECATION_MSG_PREFIX}{{}}"),
 | 
						|
        (
 | 
						|
            gone_in,
 | 
						|
            "pip {} will enforce this behaviour change."
 | 
						|
            if not is_gone
 | 
						|
            else "Since pip {}, this is no longer supported.",
 | 
						|
        ),
 | 
						|
        (
 | 
						|
            replacement,
 | 
						|
            "A possible replacement is {}.",
 | 
						|
        ),
 | 
						|
        (
 | 
						|
            feature_flag,
 | 
						|
            "You can use the flag --use-feature={} to test the upcoming behaviour."
 | 
						|
            if not is_gone
 | 
						|
            else None,
 | 
						|
        ),
 | 
						|
        (
 | 
						|
            issue,
 | 
						|
            "Discussion can be found at https://github.com/pypa/pip/issues/{}",
 | 
						|
        ),
 | 
						|
    ]
 | 
						|
 | 
						|
    message = " ".join(
 | 
						|
        format_str.format(value)
 | 
						|
        for value, format_str in message_parts
 | 
						|
        if format_str is not None and value is not None
 | 
						|
    )
 | 
						|
 | 
						|
    # Raise as an error if this behaviour is deprecated.
 | 
						|
    if is_gone:
 | 
						|
        raise PipDeprecationWarning(message)
 | 
						|
 | 
						|
    warnings.warn(message, category=PipDeprecationWarning, stacklevel=2)
 |