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).
  • 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`

Or from Python:

from gamesheet_sdk import (
    AuthenticatedSession,
    Config,
    list_associations,
    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}")

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.
  login         Authenticate and persist a GameSheet session.

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
│   ├── auth.py                # login, token persistence, AuthenticatedSession
│   ├── browser.py             # Playwright BrowserSession wrapper
│   ├── cli.py                 # click entry point — `gamesheet-sdk-py` (resource groups)
│   ├── 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

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.5.tar.gz (84.3 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.5-py3-none-any.whl (43.1 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: gamesheet_sdk_py-0.0.5.tar.gz
  • Upload date:
  • Size: 84.3 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.5.tar.gz
Algorithm Hash digest
SHA256 5f1d2625301669e502e8e4ea48b2e5ed9865b75f46a901a1bf431448676f8623
MD5 ff32d14c3519a61be83c1d7e2a4b77be
BLAKE2b-256 71b8c275c502e9af6001036d8b6600a8724171ecf666bfdc1e72f7b8fdfc8d3a

See more details on using hashes here.

Provenance

The following attestation bundles were made for gamesheet_sdk_py-0.0.5.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.5-py3-none-any.whl.

File metadata

File hashes

Hashes for gamesheet_sdk_py-0.0.5-py3-none-any.whl
Algorithm Hash digest
SHA256 90e2c20c6f27dfa43a2b55eaf19eff9f29316aff495a3cc03c31789f0511abee
MD5 e62a2257e54ec1a1b1a222478102872f
BLAKE2b-256 28728ff4075c2533fca43e72bb18cbca8d3dce0ff77ea049e2368a1a04d2098f

See more details on using hashes here.

Provenance

The following attestation bundles were made for gamesheet_sdk_py-0.0.5-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