Skip to content

Feature: missing-deprecation enrichment rule #323

@Alberto-Codes

Description

@Alberto-Codes

Problem Statement

Deprecation is a critical part of a library's API contract. When a function is marked deprecated in code but the docstring doesn't mention it, users reading the docs won't know to migrate away. This is especially important for libraries consumed via documentation sites (ReadTheDocs, MkDocs, Sphinx).

docvet already detects warnings.warn(...) for missing-warns. This narrows that to the specific case of deprecation warnings and checks for a deprecation notice rather than a Warns: section.

Current Behavior

Functions that emit DeprecationWarning or use @deprecated but lack a deprecation notice in their docstring produce no finding.

Proposed Solution

Detection: code side

Detect any of these deprecation patterns in the function body:

  1. warnings.warn(..., DeprecationWarning) — explicit deprecation warning
  2. warnings.warn(..., PendingDeprecationWarning) — pending deprecation
  3. warnings.warn(..., FutureWarning) — future behavior change
  4. @deprecated decoratortyping_extensions.deprecated (Python 3.13+ / PEP 702) or warnings.deprecated

Detection: docstring side

Intentionally loose — if the word "deprecated" appears anywhere in the docstring, the function is considered documented. Avoids false positives for projects that mention deprecation in prose rather than formal directives.

Example

def old_method(self, data):
    """Process data using the legacy algorithm.

    Args:
        data: Input data to process.

    Returns:
        Processed result dict.
    """
    # missing-deprecation: Function 'old_method' emits DeprecationWarning
    # but docstring has no deprecation notice
    warnings.warn(
        "old_method is deprecated, use new_method instead",
        DeprecationWarning,
        stacklevel=2,
    )
    return self._legacy_process(data)

Fixed:

def old_method(self, data):
    """Process data using the legacy algorithm.

    .. deprecated:: 2.0
        Use :func:`new_method` instead.

    Args:
        data: Input data to process.

    Returns:
        Processed result dict.
    """

Configuration

[tool.docvet.enrichment]
require-deprecation = true  # default

Acceptance Criteria

  • Functions with warnings.warn(..., DeprecationWarning) but no "deprecated" in docstring produce a finding
  • PendingDeprecationWarning and FutureWarning also detected
  • @deprecated decorator detected
  • Word "deprecated" anywhere in docstring satisfies the check
  • Scope-aware (nested functions don't leak)
  • Config key require-deprecation added

Technical Notes

Files changed: config.py (~3 lines), enrichment.py (~40 lines), tests (~30 lines)

Category: required — deprecation is an API contract that must be visible in documentation

Relationship to missing-warns: missing-warns checks for a Warns: section. missing-deprecation checks specifically for a deprecation notice. A function could satisfy both, but in practice most projects use .. deprecated:: directive, not a Warns: section.


BMAD Workflow

When ready to implement:

  • /bmad-bmm-quick-spec -> /bmad-bmm-quick-dev

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions