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.
⚠️ 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
- Requirements
- Installation
- Quick start
- Configuration
- CLI usage
- Documentation
- Project layout
- Development
- Contributing
- Security
- License
Features
loginflow — authenticates against the GameSheet dashboard with Playwright, persists the auth cookie and Playwright storage state so subsequent commands run without a browser.AuthenticatedSession— arequests-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-headlessfor debugging).associations list— read-only command to list associations (resource-oriented CLI;lsalias and a baregamesheet-sdk-py associationsshortcut both run the same action).leagues list— read-only command to list leagues within a specified association (resource-oriented CLI;lsalias works the same as associations).- Pluggable output —
render()produces JSON, YAML, CSV, TSV, or any of 13 human-readable tabulate formats (simple,grid,fancy_grid,rst,html,latex, …). - Shell completion —
gamesheet-sdk-py completion {bash,zsh,fish}prints a sourceable script that tab-completes sub-commands (including aliases), option names, and--formatchoices. - Typed (PEP 561) — ships a
py.typedmarker and passesmypy --strict. - Config from env or kwargs —
pydantic-settingsresolvesGAMESHEET_*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
loginflow and any other browser-driven workflow. Install once per machine withpython -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`
Or from Python:
from gamesheet_sdk import (
AuthenticatedSession,
Config,
list_associations,
list_leagues,
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}")
Configuration
Config is a pydantic-settings model. Values resolve in this order:
- Keyword arguments passed to
Config(...)(or CLI flags like--base-url). GAMESHEET_-prefixed environment variables.- 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(orpre-commit run --all-files) andmake test(orpytest). To cover the full lint/type/security/docs matrix in isolated envs, runtox— or scope it with the labelstox -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) — thexenonpre-commit hook enforces this on every commit. Runmake metricsto see the numbers before you push. - New documentation pages belong in one of the four Diátaxis quadrants under
docs/— seedocs/explanation/diataxis.mdfor 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
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file gamesheet_sdk_py-0.0.4.tar.gz.
File metadata
- Download URL: gamesheet_sdk_py-0.0.4.tar.gz
- Upload date:
- Size: 82.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
78e93c4a3f2977c095cc28626d53cbec5f399d9164a8a230dfb8a90e044e9176
|
|
| MD5 |
b54538f61c3006556eafb81d2907d899
|
|
| BLAKE2b-256 |
cb2eb38309613bca0921830ecb95805a266d7f34e895882776637439e45308ee
|
Provenance
The following attestation bundles were made for gamesheet_sdk_py-0.0.4.tar.gz:
Publisher:
release.yml on bdperkin/gamesheet-sdk-py
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
gamesheet_sdk_py-0.0.4.tar.gz -
Subject digest:
78e93c4a3f2977c095cc28626d53cbec5f399d9164a8a230dfb8a90e044e9176 - Sigstore transparency entry: 1711982923
- Sigstore integration time:
-
Permalink:
bdperkin/gamesheet-sdk-py@eeb775cf16e3e4accc7b17b5f62d9aeafbc6e64b -
Branch / Tag:
refs/tags/v0.0.4 - Owner: https://github.com/bdperkin
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@eeb775cf16e3e4accc7b17b5f62d9aeafbc6e64b -
Trigger Event:
push
-
Statement type:
File details
Details for the file gamesheet_sdk_py-0.0.4-py3-none-any.whl.
File metadata
- Download URL: gamesheet_sdk_py-0.0.4-py3-none-any.whl
- Upload date:
- Size: 41.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9f4add1e3f4f61b36d5ae5e8ac29e2b78f794bd1f35037278cacfc3196edb421
|
|
| MD5 |
7efe54608abb859bcddd559b9acb196a
|
|
| BLAKE2b-256 |
bdbc5a152d3a126cf8ca5eb7392471735fca7a8a7e83a1b97f823f143afd4b86
|
Provenance
The following attestation bundles were made for gamesheet_sdk_py-0.0.4-py3-none-any.whl:
Publisher:
release.yml on bdperkin/gamesheet-sdk-py
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
gamesheet_sdk_py-0.0.4-py3-none-any.whl -
Subject digest:
9f4add1e3f4f61b36d5ae5e8ac29e2b78f794bd1f35037278cacfc3196edb421 - Sigstore transparency entry: 1711982965
- Sigstore integration time:
-
Permalink:
bdperkin/gamesheet-sdk-py@eeb775cf16e3e4accc7b17b5f62d9aeafbc6e64b -
Branch / Tag:
refs/tags/v0.0.4 - Owner: https://github.com/bdperkin
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@eeb775cf16e3e4accc7b17b5f62d9aeafbc6e64b -
Trigger Event:
push
-
Statement type: