Skip to content

pippen.cli

The command-line entry point. Run pippen --help for usage.

pippen.cli

Command-line interface for pippen.

version

version()

Print the installed package version.

Source code in src/pippen/cli.py
@app.command()
def version() -> None:
    """Print the installed package version."""
    console.print(__version__)

paths

paths()

Show where pippen reads and writes data on this machine.

Source code in src/pippen/cli.py
@app.command()
def paths() -> None:
    """Show where pippen reads and writes data on this machine."""
    table = Table(title="pippen data layout")
    table.add_column("Stage", style="bold")
    table.add_column("Path")
    table.add_column("Exists", justify="center")

    table.add_row("root", str(data_root()), "yes" if data_root().is_dir() else "no")
    for stage in ("raw", "interim", "processed", "sources"):
        path = stage_dir(stage)
        table.add_row(stage, str(path), "yes" if path.is_dir() else "no")

    console.print(table)
    console.print(f"\nOverride the root by setting [bold]{ENV_VAR}[/bold].")

fetch

fetch(seasons, dataset='play_by_play', force=False)

Download one hoopR table for a range of seasons.

Files already present and readable are skipped unless --force is given, so re-running after an interruption costs only the seasons that are missing.

Source code in src/pippen/cli.py
@app.command()
def fetch(
    seasons: Annotated[
        str,
        typer.Option(help="A season, 2024, or an inclusive range, 2015-2024."),
    ],
    dataset: Annotated[
        str,
        typer.Option(help="Which hoopR table to download."),
    ] = "play_by_play",
    force: Annotated[
        bool,
        typer.Option(help="Re-download even when a valid file is already present."),
    ] = False,
) -> None:
    """Download one hoopR table for a range of seasons.

    Files already present and readable are skipped unless --force is given, so
    re-running after an interruption costs only the seasons that are missing.
    """
    wanted = _parse_seasons(seasons)
    if dataset not in hoopr.DATASETS:
        known = ", ".join(sorted(hoopr.DATASETS))
        console.print(f"[red]unknown dataset[/red] {dataset!r}. Known datasets: {known}")
        raise typer.Exit(code=2)

    if hoopr.is_master_dataset(dataset):
        # Published as one file covering every season, so the requested range
        # selects nothing. Downloading it once per season would store the same
        # file repeatedly.
        console.print(f"{dataset} is published as one file covering every season")
        results = [hoopr.download_master(dataset, force=force)]
        console.print(f"{results[0].status} {dataset}")
    else:
        results = hoopr.download_seasons(dataset, wanted, force=force, console=console)

    failed = [r for r in results if r.status == "failed"]
    downloaded = sum(1 for r in results if r.status == "downloaded")
    skipped = sum(1 for r in results if r.status == "skipped")
    console.print(
        f"\n{len(results)} season(s): {downloaded} downloaded, "
        f"{skipped} already present, {len(failed)} failed"
    )
    if failed:
        raise typer.Exit(code=1)

rapm

rapm(seasons, window=3)

Compute regularized adjusted plus-minus over a rolling multi-season window.

Source code in src/pippen/cli.py
@app.command()
def rapm(
    seasons: Annotated[str, typer.Option(help="Season range, for example 2015-2024.")],
    window: Annotated[int, typer.Option(help="Number of seasons per RAPM window.")] = 3,
) -> None:
    """Compute regularized adjusted plus-minus over a rolling multi-season window."""
    del seasons, window
    raise typer.Exit(_not_yet("rapm", "week 3-4 of the implementation plan"))

train

train()

Fit the reliability-weighted measurement model.

Source code in src/pippen/cli.py
@app.command()
def train() -> None:
    """Fit the reliability-weighted measurement model."""
    raise typer.Exit(_not_yet("train", "week 5-7 of the implementation plan"))

evaluate

evaluate()

Compare PIPPEN against every input metric on next-season team net rating.

Source code in src/pippen/cli.py
@app.command()
def evaluate() -> None:
    """Compare PIPPEN against every input metric on next-season team net rating."""
    raise typer.Exit(_not_yet("evaluate", "week 5-7 of the implementation plan"))