claude-configs/skills/major-domo/cli_schedule.py
Cal Corum 6201b4c9af Major Domo CLI: modular refactor + 6 new command modules
Refactored monolithic cli.py into modular architecture:
- cli_common.py: shared state, console, output helpers
- cli_transactions.py: list + simulate (compliance checker)
- cli_injuries.py: injury listing with team/active filters
- cli_stats.py: batting/pitching leaderboards
- cli_results.py: game results
- cli_schedule.py: game schedules

Also: team get now shows salary_cap, SKILL.md fully updated
with CLI docs, flag ordering warning, and compliance workflow.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 11:24:18 -06:00

232 lines
6.4 KiB
Python

#!/usr/bin/env python3
"""
Major Domo CLI - Schedule Operations
Commands for listing and filtering game schedules.
"""
from typing import Annotated, Optional
import typer
from cli_common import (
state,
console,
output_json,
output_table,
handle_error,
get_season,
)
schedule_app = typer.Typer(
help="Schedule operations",
invoke_without_command=True,
no_args_is_help=False,
)
@schedule_app.callback()
def schedule_callback(
ctx: typer.Context,
team: Annotated[
Optional[str], typer.Option("--team", "-t", help="Filter by team abbreviation")
] = None,
week: Annotated[
Optional[int], typer.Option("--week", "-w", help="Filter by specific week")
] = None,
week_start: Annotated[
Optional[int], typer.Option("--week-start", help="Start week for range")
] = None,
week_end: Annotated[
Optional[int], typer.Option("--week-end", help="End week for range")
] = None,
season: Annotated[
Optional[int], typer.Option("--season", "-s", help="Season number")
] = None,
limit: Annotated[
int, typer.Option("--limit", "-n", help="Max results to display")
] = 50,
):
"""
List game schedules with optional filters.
By default, shows recent schedules for the current season.
Use filters to narrow down results.
Examples:
majordomo schedule --team CAR
majordomo schedule --week 5
majordomo schedule --week-start 1 --week-end 4
"""
# Only invoke if no subcommand was called
if ctx.invoked_subcommand is not None:
return
try:
season = get_season(season)
# Handle week vs week_start/week_end
if week is not None:
week_start = week
week_end = week
# Get schedules from API using low-level get method
result = state.api.get(
"schedules",
season=season,
team_abbrev=team,
week_start=week_start,
week_end=week_end,
short_output=False,
)
schedules = result.get("schedules", [])
# Limit results
schedules = schedules[:limit]
if state.json_output:
output_json(schedules)
return
if not schedules:
console.print(
f"[yellow]No schedules found for the given filters (Season {season})[/yellow]"
)
return
# Build table rows
rows = []
for s in schedules:
away_team = s.get("away_team", {})
home_team = s.get("home_team", {})
away_abbrev = (
away_team.get("abbrev", "N/A") if isinstance(away_team, dict) else "N/A"
)
home_abbrev = (
home_team.get("abbrev", "N/A") if isinstance(home_team, dict) else "N/A"
)
rows.append(
[
s.get("week", ""),
s.get("game_num", ""),
away_abbrev,
"@",
home_abbrev,
]
)
# Build title with filters
title_parts = [f"Schedule (Season {season})"]
if team:
title_parts.append(f"Team: {team}")
if week:
title_parts.append(f"Week {week}")
elif week_start and week_end:
title_parts.append(f"Weeks {week_start}-{week_end}")
title = " | ".join(title_parts)
output_table(title, ["Week", "Gm", "Away", "@", "Home"], rows)
except Exception as e:
handle_error(e)
@schedule_app.command("list")
def schedule_list(
team: Annotated[
Optional[str], typer.Option("--team", "-t", help="Filter by team abbreviation")
] = None,
week: Annotated[
Optional[int], typer.Option("--week", "-w", help="Filter by specific week")
] = None,
week_start: Annotated[
Optional[int], typer.Option("--week-start", help="Start week for range")
] = None,
week_end: Annotated[
Optional[int], typer.Option("--week-end", help="End week for range")
] = None,
season: Annotated[
Optional[int], typer.Option("--season", "-s", help="Season number")
] = None,
limit: Annotated[
int, typer.Option("--limit", "-n", help="Max results to display")
] = 50,
):
"""
List game schedules with optional filters (explicit command).
This is the same as calling 'majordomo schedule' without a subcommand.
"""
try:
season = get_season(season)
# Handle week vs week_start/week_end
if week is not None:
week_start = week
week_end = week
# Get schedules from API using low-level get method
result = state.api.get(
"schedules",
season=season,
team_abbrev=team,
week_start=week_start,
week_end=week_end,
short_output=False,
)
schedules = result.get("schedules", [])
# Limit results
schedules = schedules[:limit]
if state.json_output:
output_json(schedules)
return
if not schedules:
console.print(
f"[yellow]No schedules found for the given filters (Season {season})[/yellow]"
)
return
# Build table rows
rows = []
for s in schedules:
away_team = s.get("away_team", {})
home_team = s.get("home_team", {})
away_abbrev = (
away_team.get("abbrev", "N/A") if isinstance(away_team, dict) else "N/A"
)
home_abbrev = (
home_team.get("abbrev", "N/A") if isinstance(home_team, dict) else "N/A"
)
rows.append(
[
s.get("week", ""),
s.get("game_num", ""),
away_abbrev,
"@",
home_abbrev,
]
)
# Build title with filters
title_parts = [f"Schedule (Season {season})"]
if team:
title_parts.append(f"Team: {team}")
if week:
title_parts.append(f"Week {week}")
elif week_start and week_end:
title_parts.append(f"Weeks {week_start}-{week_end}")
title = " | ".join(title_parts)
output_table(title, ["Week", "Gm", "Away", "@", "Home"], rows)
except Exception as e:
handle_error(e)