Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,7 @@ explicit = true
# uv-secure
# --------------------------------------------------------------------------- #
[tool.uv-secure.vulnerability_criteria]
# Pygments 2.19.2 ReDoS in AdlLexer (GHSA low severity, local-only). No fix available.
ignore_vulnerabilities = ["GHSA-5239-wwwm-4pmq"]
ignore_vulnerabilities = []
allow_unused_ignores = false

# --------------------------------------------------------------------------- #
Expand Down
78 changes: 56 additions & 22 deletions src/docvet/cli/_runners.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
module, and returns findings. The ``_run_fix`` runner additionally
writes scaffolded sections back to files (or collects diffs in dry-run
mode). Git helpers (``_get_git_diff``, ``_get_git_blame``) provide
raw VCS data for the freshness runner.
raw VCS data for the freshness runner. Progress display is handled
by ``_maybe_progressbar``, which avoids the ``click >= 8.2``
``hidden`` kwarg requirement.

See Also:
[`docvet.cli`][]: CLI application and subcommands.
Expand All @@ -22,7 +24,10 @@

import importlib.util
import sys
from collections.abc import Iterator, Sequence
from contextlib import contextmanager
from pathlib import Path
from typing import TypeVar

import typer

Expand All @@ -33,6 +38,35 @@

from . import DiscoveryMode, FreshnessMode

V = TypeVar("V")


@contextmanager
def _maybe_progressbar(
items: Sequence[V],
*,
label: str,
show: bool,
) -> Iterator[Iterator[V]]:
"""Wrap items in a typer progress bar, or iterate directly.

Avoids passing ``hidden`` to ``typer.progressbar`` which relies
on a ``click >= 8.2`` parameter not available in all environments.

Args:
items: Items to iterate over.
label: Progress bar label.
show: When ``True``, display a progress bar on stderr.

Yields:
An iterator over *items*.
"""
if show:
with typer.progressbar(items, label=label, file=sys.stderr) as progress:
yield progress
else:
yield iter(items)


def _get_git_diff(
file_path: Path,
Expand Down Expand Up @@ -138,22 +172,22 @@ def _run_enrichment(
Reads each file, parses its AST, and runs all enabled enrichment
rules. Passes ``config.docstring_style`` to the enrichment checker
for style-aware section detection and rule gating. Files that fail
to parse are skipped with a warning.
to parse are skipped with a warning. Uses ``_maybe_progressbar``
for click-compatible progress display.

Args:
files: Discovered Python file paths.
config: Loaded docvet configuration.
show_progress: Display a progress bar on stderr.
show_progress: Display a progress bar on stderr via
``_maybe_progressbar``.

Returns:
A tuple of ``(findings, symbol_count)`` where *symbol_count*
is the total documented symbols analyzed across all files.
"""
all_findings: list[Finding] = []
symbol_count = 0
with typer.progressbar(
files, label="enrichment", file=sys.stderr, hidden=not show_progress
) as progress:
with _maybe_progressbar(files, label="enrichment", show=show_progress) as progress:
for file_path in progress:
source = file_path.read_text(encoding="utf-8")
try:
Expand Down Expand Up @@ -184,11 +218,13 @@ def _run_presence(
Reads each file, parses its AST, and checks for missing docstrings.
Files that fail to parse are skipped with a warning. Aggregates
per-file coverage statistics into a single :class:`PresenceStats`.
Uses ``_maybe_progressbar`` for click-compatible progress display.

Args:
files: Discovered Python file paths.
config: Loaded docvet configuration.
show_progress: Display a progress bar on stderr.
show_progress: Display a progress bar on stderr via
``_maybe_progressbar``.

Returns:
A tuple of ``(findings, stats)`` where *findings* is a list of
Expand All @@ -198,9 +234,7 @@ def _run_presence(
all_findings: list[Finding] = []
total_documented = 0
total_total = 0
with typer.progressbar(
files, label="presence", file=sys.stderr, hidden=not show_progress
) as progress:
with _maybe_progressbar(files, label="presence", show=show_progress) as progress:
for file_path in progress:
source = file_path.read_text(encoding="utf-8")
try:
Expand Down Expand Up @@ -230,14 +264,16 @@ def _run_freshness(
For diff mode, reads each file, parses the AST, obtains its git
diff, and calls ``check_freshness_diff``. For drift mode, reads
each file, parses the AST, runs ``git blame --line-porcelain``,
and calls ``check_freshness_drift``.
and calls ``check_freshness_drift``. Uses ``_maybe_progressbar``
for click-compatible progress display.

Args:
files: Discovered Python file paths.
config: Loaded docvet configuration.
freshness_mode: The freshness check strategy (diff or drift).
discovery_mode: Controls which git diff variant to run.
show_progress: Display a progress bar on stderr.
show_progress: Display a progress bar on stderr via
``_maybe_progressbar``.

Returns:
A tuple of ``(findings, symbol_count)`` where *symbol_count*
Expand All @@ -246,8 +282,8 @@ def _run_freshness(
if freshness_mode is not FreshnessMode.DIFF:
all_findings: list[Finding] = []
symbol_count = 0
with typer.progressbar(
files, label="freshness", file=sys.stderr, hidden=not show_progress
with _maybe_progressbar(
files, label="freshness", show=show_progress
) as progress:
for file_path in progress:
source = file_path.read_text(encoding="utf-8")
Expand All @@ -268,9 +304,7 @@ def _run_freshness(

all_findings: list[Finding] = []
symbol_count = 0
with typer.progressbar(
files, label="freshness", file=sys.stderr, hidden=not show_progress
) as progress:
with _maybe_progressbar(files, label="freshness", show=show_progress) as progress:
for file_path in progress:
source = file_path.read_text(encoding="utf-8")
try:
Expand Down Expand Up @@ -358,14 +392,16 @@ def _run_fix(
them via ``scaffold_missing_sections``, and either writes the result
or collects diffs. In write mode, re-runs enrichment to collect
scaffold-incomplete findings. In dry-run mode, collects diffs
without writing or re-checking.
without writing or re-checking. Uses ``_maybe_progressbar`` for
click-compatible progress display.

Args:
files: Discovered Python file paths.
config: Loaded docvet configuration.
dry_run: When ``True``, collect diffs without writing files
or re-running enrichment.
show_progress: Display a progress bar on stderr.
show_progress: Display a progress bar on stderr via
``_maybe_progressbar``.

Returns:
A tuple of ``(scaffold_findings, files_modified, sections_scaffolded,
Expand All @@ -380,9 +416,7 @@ def _run_fix(
sections_scaffolded = 0
diffs: list[tuple[str, str, str]] = []

with typer.progressbar(
files, label="fix", file=sys.stderr, hidden=not show_progress
) as progress:
with _maybe_progressbar(files, label="fix", show=show_progress) as progress:
for file_path in progress:
source = file_path.read_text(encoding="utf-8")
try:
Expand Down
Loading
Loading