Skip to main content

Unofficial Python SDK and CLI for the GameSheet Inc. platform — automates WebUI procedures where a native API is absent.

Project description

gamesheet-sdk-py

Unofficial Python SDK and command-line interface for the GameSheet Inc. platform.

CI Tests CodeQL Docs Dependency review pre-commit pre-commit.ci status codecov

Code style: black Imports: isort Linting: flake8 Linting: pylint Checked with mypy Security: bandit pre-commit

PyPI version PyPI - Python Version PyPI - Wheel PyPI - Status PyPI - Downloads License: MIT Typed Hatch project

GitHub release GitHub stars GitHub forks GitHub issues GitHub pull requests GitHub contributors GitHub commit activity

GitHub last commit Maintenance Dependabot GitHub repo size GitHub code size

⚠️ Disclaimer

This project is not affiliated with, endorsed by, or sponsored by GameSheet Inc. GameSheet Inc. does not publish a public REST/GraphQL API for the operations this SDK covers. Where a native API is absent, this library automates the GameSheet WebUI (using a combination of HTTP requests, HTML parsing, and headless-browser automation) in order to perform routine tasks programmatically.

Because this approach depends on the structure of a third-party web interface, it may break without warning whenever GameSheet ships UI changes. Check the GitHub Releases page for release notes before upgrading in production.

Use of this software must comply with the GameSheet Inc. Terms of Service. You are responsible for any automation you perform against accounts you control.

Table of contents

Features

  • login flow — authenticates against the GameSheet dashboard with Playwright, persists the auth cookie and Playwright storage state so subsequent commands run without a browser.
  • AuthenticatedSession — a requests-backed HTTP layer that attaches the saved bearer token, transparently refreshes it on 401, and re-persists rotated tokens via a user-supplied callback.
  • BrowserSession — a Playwright wrapper that opens Chromium with the saved storage state for any flow that genuinely needs a real browser (headed mode available via --no-headless for debugging).
  • associations list — read-only command to list associations (resource-oriented CLI; ls alias and a bare gamesheet-sdk-py associations shortcut both run the same action).
  • leagues list — read-only command to list leagues within a specified association (resource-oriented CLI; ls alias works the same as associations).
  • seasons list — read-only command to list seasons within a specified league (resource-oriented CLI; ls alias works the same as associations/leagues).
  • season get — read-only command to get detailed information about a specific season, including settings, penalty codes, flagging criteria, and more (resource-oriented CLI; show and view aliases available, with get as the default).
  • ipad-keys get — read-only command to retrieve iPad / Scoring Access Keys for a specific season (resource-oriented CLI; show and view aliases available, with get as the default).
  • Pluggable outputrender() produces JSON, YAML, CSV, TSV, or any of 13 human-readable tabulate formats (simple, grid, fancy_grid, rst, html, latex, …).
  • Shell completiongamesheet-sdk-py completion {bash,zsh,fish} prints a sourceable script that tab-completes sub-commands (including aliases), option names, and --format choices.
  • Typed (PEP 561) — ships a py.typed marker and passes mypy --strict.
  • Config from env or kwargspydantic-settings resolves GAMESHEET_* environment variables with CLI overrides taking precedence.

Requirements

  • Python 3.11, 3.12, 3.13, or 3.14 (declared in pyproject.toml)
  • Chromium binary managed by Playwright — required for the login flow and any other browser-driven workflow. Install once per machine with python -m playwright install chromium.
  • Any modern Linux, macOS, or Windows host on which Python and Playwright Chromium run.

Installation

pip install gamesheet-sdk-py

# Playwright browser binaries are required for headless WebUI flows:
python -m playwright install chromium

From source

git clone https://github.com/bdperkin/gamesheet-sdk-py.git
cd gamesheet-sdk-py
pip install -e ".[all]"   # everything: pytest, mypy, lint suite, docs, pre-commit
python -m playwright install chromium

The [all] extra pulls every per-tool dependency declared in pyproject.toml. For a leaner setup pick the extras you need explicitly — e.g. pip install -e ".[dev,pytest,docs]" for tests + docs without the full lint matrix.

Quick start

Authenticate once, then list the associations on your account:

# Credentials can also be supplied via GAMESHEET_USERNAME / GAMESHEET_PASSWORD;
# omit the flags to be prompted interactively.
gamesheet-sdk-py login --email you@example.com

# Subsequent commands reuse the saved session — no browser, no re-prompt.
gamesheet-sdk-py associations list --format json   # also: `associations ls`, or bare `associations`

# List leagues within a specific association (replace 38 with your association ID)
gamesheet-sdk-py leagues list 38 --format json     # also: `leagues ls 38`

# List seasons within a specific league (replace 1148580 with your league ID)
gamesheet-sdk-py seasons list 1148580 --format json     # also: `seasons ls 1148580`

# Get detailed information about a specific season (replace 15020 with your season ID)
gamesheet-sdk-py season get 15020 --format json          # also: `season show 15020` or `season view 15020`
gamesheet-sdk-py season get 15020 --fields id,title,sport,start_date,end_date  # Filter to specific fields

# Get iPad / Scoring Access Keys for a specific season (replace 15020 with your season ID)
gamesheet-sdk-py ipad-keys get 15020 --format json       # also: `ipad-keys show 15020` or `ipad-keys view 15020`
gamesheet-sdk-py ipad-keys get 15020 --columns id,value,description  # Filter to specific columns

Or from Python:

from gamesheet_sdk import (
    AuthenticatedSession,
    Config,
    get_season,
    list_associations,
    list_ipad_keys,
    list_leagues,
    list_seasons,
    load_access_token,
    load_refresh_token,
    save_tokens,
)

config = Config()  # reads GAMESHEET_* env vars; CLI args > env > defaults
access = load_access_token(config)
refresh = load_refresh_token(config)

with AuthenticatedSession(
    config,
    access_token=access or "",
    refresh_token=refresh or "",
    on_refresh=lambda tokens: save_tokens(config, **tokens),
) as session:
    # List all associations
    for assoc in list_associations(session):
        print(f"Association: {assoc.title}")

        # List leagues for each association
        for league in list_leagues(session, assoc.id):
            print(f"  League: {league.title}")

            # List seasons for each league
            for season in list_seasons(session, league.id):
                print(f"    Season: {season.title}")

                # Get detailed information about a specific season
                season_detail = get_season(session, season.id)
                print(
                    f"      Sport: {season_detail.sport}, Dates: {season_detail.start_date} to {season_detail.end_date}"
                )

                # Get iPad / Scoring Access Keys for the season
                ipad_keys = list_ipad_keys(session, season.id)
                for key in ipad_keys:
                    print(f"        iPad Key: {key.value} - {key.description}")

Configuration

Config is a pydantic-settings model. Values resolve in this order:

  1. Keyword arguments passed to Config(...) (or CLI flags like --base-url).
  2. GAMESHEET_-prefixed environment variables.
  3. Built-in defaults.
Environment variable Purpose Default
GAMESHEET_BASE_URL Root URL of the GameSheet WebUI https://gamesheet.app
GAMESHEET_USERNAME Account email (CLI --email overrides) unset
GAMESHEET_PASSWORD Account password (CLI --password overrides) unset
GAMESHEET_TIMEOUT Default per-request HTTP timeout in seconds 30
GAMESHEET_REQUEST_RETRIES Auto-retries on 5xx and connection errors 3
GAMESHEET_USER_AGENT Override the HTTP User-Agent header requests default
GAMESHEET_VERIFY_SSL TLS certificate verification true
GAMESHEET_SESSION_PATH Where to persist cookie state $XDG_CACHE_HOME/gamesheet-sdk-py/session.json
GAMESHEET_BROWSER_STATE_PATH Where to persist Playwright storage state $XDG_CACHE_HOME/gamesheet-sdk-py/browser-state.json
GAMESHEET_BROWSER_HEADLESS Launch Playwright in headless mode (--no-headless) true

CLI usage

$ gamesheet-sdk-py --help
Usage: gamesheet-sdk-py [OPTIONS] COMMAND [ARGS]...

  Unofficial CLI for the GameSheet Inc. platform.

Options:
  --version       Show the version and exit.
  -v, --verbose   Increase logging verbosity. -v sets INFO; -vv sets DEBUG.
  --base-url URL  Override Config.base_url for this invocation.
  --no-headless   Run browser-driven flows with a visible window (for
                  debugging).
  -h, --help      Show this message and exit.

Commands:
  associations  Manage GameSheet associations.
  completion    Print a SHELL completion script to stdout.
  ipad-keys     Manage iPad / Scoring Access Keys.
  leagues       Manage GameSheet leagues.
  login         Authenticate and persist a GameSheet session.
  season        Manage a specific GameSheet season.
  seasons       Manage GameSheet seasons.

The CLI is resource-oriented (noun-first): each resource gets a nested group whose canonical verbs are create / get / list / update / delete, with the aliases add|new / show|view / ls / set|edit / rm|remove. A bare gamesheet-sdk-py <resource> implicitly runs list.

$ gamesheet-sdk-py associations --help
Commands:
  list (ls)  List the associations the signed-in user can see.

Render formats accepted by associations list --format:

  • Data: json, yaml, csv, tsv
  • Tables (via tabulate): plain, simple (default), grid, fancy_grid, pipe, orgtbl, rst, mediawiki, html, latex, latex_raw, latex_booktabs, latex_longtable

Tab completion

# Bash, current shell:
eval "$(gamesheet-sdk-py completion bash)"

# Bash, persistent:
gamesheet-sdk-py completion bash >> ~/.bashrc

# Zsh, persistent:
gamesheet-sdk-py completion zsh >> ~/.zshrc

# Fish, persistent (fish auto-loads ~/.config/fish/completions/):
gamesheet-sdk-py completion fish > ~/.config/fish/completions/gamesheet-sdk-py.fish

Documentation

Full documentation is published on GitHub Pages: https://bdperkin.github.io/gamesheet-sdk-py/

The docs are organized following the Diátaxis framework into tutorials, how-to guides, reference, and explanation. The reference section (API + CLI) is generated from source, so it cannot drift from the shipped package.

Project layout

gamesheet-sdk-py/
├── src/gamesheet_sdk/
│   ├── __init__.py            # public re-exports + __version__
│   ├── associations.py        # list_associations action + Association model
│   ├── leagues.py             # list_leagues action + League model
│   ├── seasons.py             # list_seasons + get_season actions + Season/SeasonDetail models
│   ├── ipad_keys.py           # list_ipad_keys action + IPadKey model
│   ├── auth/                  # authentication package (modular structure)
│   │   ├── __init__.py        # public auth API exports
│   │   ├── login.py           # login flow implementation
│   │   ├── session.py         # AuthenticatedSession HTTP layer
│   │   ├── storage.py         # token persistence (load/save)
│   │   ├── tokens.py          # token refresh logic
│   │   └── constants.py       # auth-related constants
│   ├── cli/                   # CLI framework package (modular structure)
│   │   ├── __init__.py        # CLI entry point exports
│   │   ├── main.py            # root click group + main() wrapper
│   │   ├── core.py            # ResourceGroup, confirm_destructive, logging setup
│   │   ├── helpers.py         # CLI utility functions
│   │   └── commands/          # individual command modules
│   │       ├── __init__.py    # command exports
│   │       ├── login.py       # login command
│   │       ├── associations.py # associations resource group
│   │       ├── leagues.py     # leagues resource group
│   │       ├── seasons.py     # seasons resource group
│   │       ├── season.py      # season (singular) resource group
│   │       ├── ipad_keys.py   # ipad-keys resource group
│   │       └── completion.py  # shell completion command
│   ├── browser.py             # Playwright BrowserSession wrapper
│   ├── config.py              # pydantic-settings Config (GAMESHEET_*)
│   ├── exceptions.py          # GameSheetError, AuthenticationError
│   ├── output.py              # render() — json/yaml/csv/tsv + tabulate
│   ├── session.py             # base requests.Session subclass
│   └── py.typed               # PEP 561 marker
├── tests/                     # pytest suite (VCR cassettes + Playwright)
├── docs/                      # Sphinx (Diátaxis) — published to GH Pages
├── .github/workflows/         # per-category fan-out: ci, tests, codeql, docs,
│                              #   pre-commit, dependency-review, release, plus
│                              #   one file per tool category (type checkers,
│                              #   formatters, linters, doc tools, …)
├── Makefile                   # unified dev shortcuts (`make help`)
├── pyproject.toml             # PEP 621 metadata + Hatch + tool config + extras
├── tox.ini                    # ~45 per-tool envs + labels (tests / docs / pre-commit)
├── .pre-commit-config.yaml    # local hooks + pre-commit.ci settings (inline `ci:` block)
├── .codecov.yml               # Codecov targets (project 100% / patch 100%) + analytics
├── SECURITY.md                # vulnerability reporting policy
└── LICENSE                    # MIT

Modular architecture

The codebase is organized into focused packages to improve maintainability and separation of concerns:

  • auth/ package — Authentication logic is split across multiple modules:

    • login.py — Playwright-driven login flow
    • session.pyAuthenticatedSession with automatic token refresh
    • storage.py — Token persistence to disk (load_access_token, load_refresh_token, save_tokens)
    • tokens.py — Token refresh logic
    • constants.py — Auth-related constants (endpoints, timeouts)
  • cli/ package — CLI framework is modularized:

    • main.py — Root click group and main() entry point
    • core.pyResourceGroup class, confirm_destructive decorator, logging setup
    • helpers.py — Shared CLI utility functions
    • commands/ — Each resource gets its own command module (associations, leagues, seasons, season, ipad_keys, login, completion)
  • Resource modules — Each domain resource (associations, leagues, seasons, ipad_keys) is a standalone module with pydantic models and action functions.

This structure allows each concern to evolve independently while maintaining a simple public API through __init__.py re-exports.

Development

# 1. Create an isolated environment and install everything
python -m venv .venv && source .venv/bin/activate
pip install -e ".[all]"            # all per-tool extras: pytest, mypy, lint suite, docs, …
python -m playwright install chromium

# 2. Install pre-commit hooks (runs on every `git commit`)
pre-commit install

# 3. Run the test suite (network is blocked unless replayed via VCR)
pytest                              # everything
pytest -m "not browser"             # skip slow real-Chromium tests
pytest --cov                        # with coverage (local floor: fail_under = 100)

# 4. Run quality gates
pre-commit run --all-files          # every hook (mypy, pylint, pyright, bandit, xenon, …)
mypy src                            # strict mode only

Makefile shortcuts

The Makefile wraps the most common workflows so you don't have to memorize tox env names. Run make help for the full list.

make install       # editable install with [dev] extras + Playwright Chromium
make test          # full pytest suite
make test-fast     # pytest -m "not browser"
make test-cov      # pytest --cov
make lint          # pre-commit across the whole repo
make type          # mypy --strict against src/
make fix           # apply formatters in place (isort, black, mdformat)
make metrics       # radon + xenon complexity gates
make docs          # Sphinx HTML build
make docs-serve    # live-reload preview
make clean         # caches + build artifacts

Coverage

Local pytest runs enforce fail_under = 100 (see [tool.coverage.report]). On every push, the codecov.yml workflow uploads coverage.xml and JUnit XML to Codecov, which gates PRs against .codecov.yml targets — project coverage = 100% (0% drop tolerated) and patch coverage = 100% on newly-introduced lines. Codecov test-analytics tracks flaky tests and a >10% performance regression alert.

Tox

Tox orchestrates ~45 per-tool envs (one per linter / formatter / type checker / doc builder), a single pytest env, and a fix-everything fix env. Selected envs and label groups:

tox -l                # list every available env
tox -m tests          # all test envs (sanity build/install + pytest)
tox -m docs           # docs, docs-lint, docs-linkcheck, docs-doctest, docs-epub, docs-man, docs-pdf, docs-serve
tox -m pre-commit     # run pre-commit hooks
tox -e pytest         # the runtime pytest env (Python matrix lives in tests.yml on CI)
tox -e mypy           # mypy --strict
tox -e pylint         # pylint
tox -e bandit         # bandit security scan
tox -e metrics        # radon cc + radon mi (complexity)
tox -e fix            # apply isort, black, mdformat in place
tox -e pytest -- -k test_name  # pass args to pytest after `--`

Every pyproject.toml optional-dependencies.* group has a matching tox env that pulls only that extra — so tox -e mypy runs in an isolated venv with just mypy + project imports, tox -e pyright with just pyright, etc.

Releases

The package version is derived from git describe via hatch-vcs — never edit a version literal. To cut a release, tag the commit (git tag -a vX.Y.Z then git push origin vX.Y.Z); the release.yml workflow builds, publishes to PyPI via Trusted Publishing (OIDC), and creates a GitHub Release.

Contributing

Issues and pull requests are welcome.

Before opening a PR:

  • Run make lint (or pre-commit run --all-files) and make test (or pytest). To cover the full lint/type/security/docs matrix in isolated envs, run tox — or scope it with the labels tox -m tests, tox -m docs, tox -m pre-commit.
  • New code must be fully annotated and pass mypy --strict. Every block must stay at cyclomatic-complexity grade A (cc ≤ 5) — the xenon pre-commit hook enforces this on every commit. Run make metrics to see the numbers before you push.
  • New documentation pages belong in one of the four Diátaxis quadrants under docs/ — see docs/explanation/diataxis.md for guidance.

Security

To report a vulnerability, see SECURITY.md. Please do not open public issues for security reports — use the private reporting channel documented there.

License

Distributed under the terms of the MIT License. © 2026 bdperkin.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

gamesheet_sdk_py-0.0.6.tar.gz (123.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

gamesheet_sdk_py-0.0.6-py3-none-any.whl (82.5 kB view details)

Uploaded Python 3

File details

Details for the file gamesheet_sdk_py-0.0.6.tar.gz.

File metadata

  • Download URL: gamesheet_sdk_py-0.0.6.tar.gz
  • Upload date:
  • Size: 123.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for gamesheet_sdk_py-0.0.6.tar.gz
Algorithm Hash digest
SHA256 aa17a52943b56fe62591363c3911652cf307c93086710b735e4913cb5cb09b41
MD5 c95a8610e79b34a71520d81ce502f2a6
BLAKE2b-256 7766b9ae8a7ed3dbb47d701a4ca7bd85ee6905a857fb7d3732cebdc09a33d6bc

See more details on using hashes here.

Provenance

The following attestation bundles were made for gamesheet_sdk_py-0.0.6.tar.gz:

Publisher: release.yml on bdperkin/gamesheet-sdk-py

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file gamesheet_sdk_py-0.0.6-py3-none-any.whl.

File metadata

File hashes

Hashes for gamesheet_sdk_py-0.0.6-py3-none-any.whl
Algorithm Hash digest
SHA256 1275b32541dc0c0ca19d8a5a2a3534ee56544d4b238843b38b75a8df4a5b572d
MD5 0eb05ba4c23fd7a6aa8ab3470e71bde1
BLAKE2b-256 e0cd71075a836c0e5ec6bae2e9349a9812811e03f1173d4413e8a570add4223c

See more details on using hashes here.

Provenance

The following attestation bundles were made for gamesheet_sdk_py-0.0.6-py3-none-any.whl:

Publisher: release.yml on bdperkin/gamesheet-sdk-py

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page