Skip to content

API Reference

This page is auto-generated from Python docstrings.

pup_clean

pup-clean package.

__main__

Run as a module.

base

Base package.

types

Typed records.

CleanupTarget dataclass

A known disposable repository target.

Source code in src/pup_clean/base/types.py
@dataclass(frozen=True)
class CleanupTarget:
    """A known disposable repository target."""

    path: Path
    kind: CleanupKind

cli

Command-line interface.

This module parses arguments and dispatches repository cleanup behavior.

Commands: uv run pup-clean uv run pup-clean --delete

Equivalent uvx usage after release: uvx pup-clean uvx pup-clean@latest uvx pup-clean --delete

build_parser

build_parser() -> argparse.ArgumentParser

Build the argument parser.

Source code in src/pup_clean/cli.py
def build_parser() -> argparse.ArgumentParser:
    """Build the argument parser."""
    parser = argparse.ArgumentParser(
        prog="pup-clean",
        description=(
            "Identify and remove known generated and disposable repository artifacts."
        ),
    )

    parser.add_argument(
        "--root",
        type=Path,
        default=None,
        help=(
            "Repository root to clean. Defaults to the nearest parent "
            "directory containing .git, or the current directory."
        ),
    )

    parser.add_argument(
        "--delete",
        action="store_true",
        help=(
            "Delete detected cleanup targets. Without this flag, "
            "pup-clean performs a dry run only."
        ),
    )

    parser.add_argument(
        "paths",
        nargs="*",
        type=Path,
        help=(
            "Optional repository-relative cleanup targets. "
            "When provided, operate only on detected targets matching these paths."
        ),
    )

    return parser

main

main(argv: Sequence[str] | None = None) -> int

Run the command-line interface.

Parameters:

Name Type Description Default
argv Sequence[str] | None

Optional command-line arguments. If None, uses sys.argv.

None

Returns:

Type Description
int

Exit code from the clean command.

Source code in src/pup_clean/cli.py
def main(argv: Sequence[str] | None = None) -> int:
    """Run the command-line interface.

    Args:
        argv: Optional command-line arguments. If None, uses sys.argv.

    Returns:
        Exit code from the clean command.
    """
    parser = build_parser()
    args = parser.parse_args(argv)

    return clean.run(
        root=args.root,
        delete=args.delete,
        paths=tuple(args.paths),
    )

commands

Command modules.

Each command module exposes a stable run(...) -> int entry point.

The CLI parser lives in pup_clean.cli. Behavior lives here.

clean

Clean known disposable and source-generated repository artifacts.

run
run(
    *,
    root: Path | None = None,
    delete: bool = False,
    paths: tuple[Path, ...] = (),
) -> int

Preview or remove known disposable and generated repository artifacts.

Parameters:

Name Type Description Default
root Path | None

Repository root. If None, detect the current repository root.

None
delete bool

Whether to delete detected cleanup targets. False means dry-run only.

False
paths tuple[Path, ...]

Optional repository-relative cleanup targets. When provided, operate only on detected targets matching these paths.

()

Returns:

Type Description
int

Process exit code.

Source code in src/pup_clean/commands/clean.py
def run(
    *,
    root: Path | None = None,
    delete: bool = False,
    paths: tuple[Path, ...] = (),
) -> int:
    """Preview or remove known disposable and generated repository artifacts.

    Args:
        root: Repository root. If None, detect the current repository root.
        delete: Whether to delete detected cleanup targets.
            False means dry-run only.
        paths: Optional repository-relative cleanup targets.
            When provided, operate only on detected targets matching these paths.

    Returns:
        Process exit code.
    """
    repository = detect_repository(root)
    targets = _detect_cleanup_targets(repository.root)

    if paths:
        selected_paths = set(paths)
        targets = tuple(target for target in targets if target.path in selected_paths)

    if delete:
        _delete_cleanup_targets(repository.root, targets)

    print_cleanup_plan(
        repository,
        targets,
        delete=delete,
    )

    return 0

delete

Write package.

terminal

Terminal reporting.

print_cleanup_plan
print_cleanup_plan(
    context: RepositoryContext,
    targets: Sequence[CleanupTarget],
    *,
    delete: bool,
) -> None

Print the repository cleanup plan.

Source code in src/pup_clean/delete/terminal.py
def print_cleanup_plan(
    context: RepositoryContext,
    targets: Sequence[CleanupTarget],
    *,
    delete: bool,
) -> None:
    """Print the repository cleanup plan."""
    mode = "DELETE" if delete else "DRY RUN"

    print(f"[pup-clean] {mode}")  # noqa: T201
    print(f"[pup-clean] repo: {context.repo_name}")  # noqa: T201
    print(f"[pup-clean] root: {context.root}")  # noqa: T201
    print("")  # noqa: T201

    if not targets:
        print("[pup-clean] no cleanup targets found")  # noqa: T201
        return

    label = "DELETED" if delete else "WOULD DELETE"

    for target in targets:
        suffix = "/" if target.kind == "directory" else ""
        print(f"{label:13} {target.path.as_posix()}{suffix}")  # noqa: T201

    print("")  # noqa: T201
    print(f"[pup-clean] summary: {len(targets)} cleanup target(s)")  # noqa: T201

    if not delete:
        print(  # noqa: T201
            "[pup-clean] nothing deleted; rerun with --delete to apply cleanup"
        )

inspect

Inspect package.

generated

Discover generated artifacts by inspecting Python source code.

This module statically inspects Python source files under src/ and finds paths passed to known data-writing, database-creation, and image-writing operations.

The purpose is to identify artifacts created by running a project so that pup-clean can remove instructor-generated outputs before a repository is published.

Only statically resolvable generated file paths are returned. Containing directories are not cleanup targets.

discover_generated_paths
discover_generated_paths(root: Path) -> tuple[Path, ...]

Discover generated data artifacts referenced by project source code.

Python files under src/ are parsed using the AST. Known data-writing operations are inspected and statically resolvable output paths are returned.

A path is returned only when it can be resolved from source code with sufficient confidence. Dynamic or ambiguous paths are ignored.

Image files are explicitly excluded.

Parameters:

Name Type Description Default
root Path

Repository root.

required

Returns:

Type Description
tuple[Path, ...]

Repository-relative paths for discovered generated artifacts.

Source code in src/pup_clean/inspect/generated.py
def discover_generated_paths(root: Path) -> tuple[Path, ...]:
    """Discover generated data artifacts referenced by project source code.

    Python files under ``src/`` are parsed using the AST. Known data-writing
    operations are inspected and statically resolvable output paths are
    returned.

    A path is returned only when it can be resolved from source code with
    sufficient confidence. Dynamic or ambiguous paths are ignored.

    Image files are explicitly excluded.

    Args:
        root: Repository root.

    Returns:
        Repository-relative paths for discovered generated artifacts.
    """
    src_root = root / "src"

    if not src_root.is_dir():
        return ()

    discovered: set[Path] = set()

    for source_path in sorted(src_root.rglob("*.py")):
        discovered.update(
            _discover_generated_paths_in_file(
                root=root,
                source_path=source_path,
            )
        )

    return tuple(sorted(discovered, key=lambda path: path.as_posix()))