Skip to content

Core Deprecator API

Deprecator

Deprecator(
    name: PackageName | str,
    current_version: Version,
    *,
    pending: type[PerPackagePendingDeprecationWarning],
    deprecation: type[PerPackageDeprecationWarning],
    expired_warning: type[
        PerPackageExpiredDeprecationWarning
    ],
    registry: DeprecatorRegistry | None = None,
)
Source code in deprecator/_deprecator.py
def __init__(
    self,
    name: PackageName | str,
    current_version: Version,
    *,
    pending: type[PerPackagePendingDeprecationWarning],
    deprecation: type[PerPackageDeprecationWarning],
    expired_warning: type[PerPackageExpiredDeprecationWarning],
    registry: DeprecatorRegistry | None = None,
) -> None:
    self.name = PackageName(name)
    self.current_version = current_version
    self.PendingDeprecationWarning = pending
    self.DeprecationWarning = deprecation
    self.ExpiredDeprecationWarning = expired_warning
    self._registry = registry
    # Track deprecations in the deprecator itself
    self._tracked_deprecations: list[DeprecatorWarningMixing] = []

define

define(
    message: str,
    gone_in: Version | str | None = None,
    warn_in: Version | str | None = None,
    replace_with: object | None = None,
    *,
    importable_name: str | None = None,
) -> WarningInstance
Source code in deprecator/_deprecator.py
def define(
    self,
    message: str,
    gone_in: Version | str | None = None,
    warn_in: Version | str | None = None,
    replace_with: object | None = None,
    *,
    importable_name: str | None = None,
) -> WarningInstance:
    # gone_in defaults to current_version
    gone_in = self._parse_version(gone_in, fallback=self.current_version)
    # warn_in defaults to min(gone_in, current_version) to ensure warn_in <= gone_in
    warn_in = self._parse_version(
        warn_in, fallback=min(gone_in, self.current_version)
    )

    if replace_with is not None:
        message = f"{message}\n\na replacement might be: {replace_with}"

    if gone_in < warn_in:
        raise ValueError("gone_in must be greater than or equal to warn_in")

    base_category = self._get_warning_class(gone_in, warn_in)

    # Create a specific warning class for this deprecation with its own ClassVars
    # Use the base category name to maintain expected class names
    class_name = base_category.__name__
    SpecificWarning = type(
        class_name,
        (base_category,),
        {
            "gone_in": gone_in,
            "warn_in": warn_in,
            # current_version is already set by the base class
        },
    )

    tracked_warning = SpecificWarning(message)
    assert isinstance(tracked_warning, DeprecatorWarningMixing)

    # If an explicit importable name was provided, set it directly
    if importable_name is not None:
        tracked_warning.importable_name = importable_name

    # Track the deprecation locally
    self._tracked_deprecations.append(tracked_warning)

    return cast(WarningInstance, tracked_warning)

__iter__

__iter__() -> Iterator[DeprecatorWarningMixing]

Iterate over the tracked deprecation warnings.

Source code in deprecator/_deprecator.py
def __iter__(self) -> Iterator[DeprecatorWarningMixing]:
    """Iterate over the tracked deprecation warnings."""
    return iter(self._tracked_deprecations)

__len__

__len__() -> int

Get the number of tracked deprecations.

Source code in deprecator/_deprecator.py
def __len__(self) -> int:
    """Get the number of tracked deprecations."""
    return len(self._tracked_deprecations)

Usage Examples

Basic Usage

from deprecator import for_package

# Create a deprecator for your package
deprecator = for_package("mypackage")

# Define a deprecation
OLD_FEATURE = deprecator.define(
    "old_feature is deprecated, use new_feature instead",
    warn_in="2.0.0",
    gone_in="3.0.0"
)

With Custom Version

from packaging.version import Version
from deprecator import for_package

# Use a specific version for testing
deprecator = for_package("mypackage", Version("1.5.0"))

# Define deprecations based on that version
warning = deprecator.define(
    "This will be deprecated",
    warn_in="2.0.0",
    gone_in="3.0.0"
)
# This will be a PendingDeprecationWarning at version 1.5.0

Accessing Deprecation Details

# Iterate over all defined deprecations (Deprecator is iterable)
for deprecation in deprecator:
    print(f"Message: {deprecation.message}")
    print(f"Warning type: {type(deprecation).__name__}")

# Get the count of defined deprecations
print(f"Total deprecations: {len(deprecator)}")

Version-Based Behavior

The Deprecator automatically determines the warning category based on version comparison:

Condition Warning Type Description
current < warn_in PendingDeprecationWarning Future deprecation (usually hidden)
warn_in <= current < gone_in DeprecationWarning Active deprecation
gone_in <= current ExpiredDeprecationWarning Should be removed

Integration with Package Metadata

The Deprecator can automatically detect your package version:

# Automatically uses the installed version of 'mypackage'
deprecator = for_package("mypackage")
print(f"Package version: {deprecator.current_version}")

Custom Warning Classes

Deprecator creates package-specific warning classes that inherit from the standard Python warning hierarchy:

  • PerPackagePendingDeprecationWarning
  • PerPackageDeprecationWarning
  • PerPackageExpiredDeprecationWarning

These classes include the package name in their structure for better filtering and identification.