baseballcommand 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of baseballcommand might be problematic. Click here for more details.
- baseballcommand-0.1.0/.github/workflows/python-publish.yml +70 -0
- baseballcommand-0.1.0/.gitignore +12 -0
- baseballcommand-0.1.0/CHANGELOG.md +52 -0
- baseballcommand-0.1.0/CONTRIBUTING.md +160 -0
- baseballcommand-0.1.0/LICENSE +21 -0
- baseballcommand-0.1.0/PKG-INFO +359 -0
- baseballcommand-0.1.0/README.md +310 -0
- baseballcommand-0.1.0/docs/commands.md +450 -0
- baseballcommand-0.1.0/docs/data-source.md +132 -0
- baseballcommand-0.1.0/docs/stats-glossary.md +108 -0
- baseballcommand-0.1.0/pyproject.toml +55 -0
- baseballcommand-0.1.0/src/baseballcommand/__init__.py +8 -0
- baseballcommand-0.1.0/src/baseballcommand/__main__.py +8 -0
- baseballcommand-0.1.0/src/baseballcommand/api.py +395 -0
- baseballcommand-0.1.0/src/baseballcommand/cache.py +115 -0
- baseballcommand-0.1.0/src/baseballcommand/cli.py +121 -0
- baseballcommand-0.1.0/src/baseballcommand/commands/__init__.py +38 -0
- baseballcommand-0.1.0/src/baseballcommand/commands/cache.py +65 -0
- baseballcommand-0.1.0/src/baseballcommand/commands/compare.py +149 -0
- baseballcommand-0.1.0/src/baseballcommand/commands/glossary.py +48 -0
- baseballcommand-0.1.0/src/baseballcommand/commands/leaders.py +222 -0
- baseballcommand-0.1.0/src/baseballcommand/commands/player.py +209 -0
- baseballcommand-0.1.0/src/baseballcommand/commands/roster.py +225 -0
- baseballcommand-0.1.0/src/baseballcommand/commands/scores.py +214 -0
- baseballcommand-0.1.0/src/baseballcommand/commands/standings.py +193 -0
- baseballcommand-0.1.0/src/baseballcommand/commands/team.py +165 -0
- baseballcommand-0.1.0/src/baseballcommand/commands/teams.py +83 -0
- baseballcommand-0.1.0/src/baseballcommand/dates.py +96 -0
- baseballcommand-0.1.0/src/baseballcommand/errors.py +39 -0
- baseballcommand-0.1.0/src/baseballcommand/lookup.py +207 -0
- baseballcommand-0.1.0/src/baseballcommand/output.py +193 -0
- baseballcommand-0.1.0/src/baseballcommand/stats.py +171 -0
- baseballcommand-0.1.0/tests/__init__.py +0 -0
- baseballcommand-0.1.0/tests/conftest.py +201 -0
- baseballcommand-0.1.0/tests/test_api.py +152 -0
- baseballcommand-0.1.0/tests/test_cache.py +61 -0
- baseballcommand-0.1.0/tests/test_cli.py +368 -0
- baseballcommand-0.1.0/tests/test_dates.py +58 -0
- baseballcommand-0.1.0/tests/test_lookup.py +97 -0
- baseballcommand-0.1.0/tests/test_output.py +66 -0
- baseballcommand-0.1.0/tests/test_roster.py +204 -0
- baseballcommand-0.1.0/tests/test_stats.py +49 -0
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# This workflow will upload a Python Package to PyPI when a release is created
|
|
2
|
+
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python#publishing-to-package-registries
|
|
3
|
+
|
|
4
|
+
# This workflow uses actions that are not certified by GitHub.
|
|
5
|
+
# They are provided by a third-party and are governed by
|
|
6
|
+
# separate terms of service, privacy policy, and support
|
|
7
|
+
# documentation.
|
|
8
|
+
|
|
9
|
+
name: Upload Python Package
|
|
10
|
+
|
|
11
|
+
on:
|
|
12
|
+
release:
|
|
13
|
+
types: [published]
|
|
14
|
+
|
|
15
|
+
permissions:
|
|
16
|
+
contents: read
|
|
17
|
+
|
|
18
|
+
jobs:
|
|
19
|
+
release-build:
|
|
20
|
+
runs-on: ubuntu-latest
|
|
21
|
+
|
|
22
|
+
steps:
|
|
23
|
+
- uses: actions/checkout@v4
|
|
24
|
+
|
|
25
|
+
- uses: actions/setup-python@v5
|
|
26
|
+
with:
|
|
27
|
+
python-version: "3.x"
|
|
28
|
+
|
|
29
|
+
- name: Build release distributions
|
|
30
|
+
run: |
|
|
31
|
+
# NOTE: put your own distribution build steps here.
|
|
32
|
+
python -m pip install build
|
|
33
|
+
python -m build
|
|
34
|
+
|
|
35
|
+
- name: Upload distributions
|
|
36
|
+
uses: actions/upload-artifact@v4
|
|
37
|
+
with:
|
|
38
|
+
name: release-dists
|
|
39
|
+
path: dist/
|
|
40
|
+
|
|
41
|
+
pypi-publish:
|
|
42
|
+
runs-on: ubuntu-latest
|
|
43
|
+
needs:
|
|
44
|
+
- release-build
|
|
45
|
+
permissions:
|
|
46
|
+
# IMPORTANT: this permission is mandatory for trusted publishing
|
|
47
|
+
id-token: write
|
|
48
|
+
|
|
49
|
+
# Dedicated environments with protections for publishing are strongly recommended.
|
|
50
|
+
# For more information, see: https://docs.github.com/en/actions/deployment/targeting-different-environments/using-environments-for-deployment#deployment-protection-rules
|
|
51
|
+
environment:
|
|
52
|
+
name: pypi
|
|
53
|
+
# OPTIONAL: uncomment and update to include your PyPI project URL in the deployment status:
|
|
54
|
+
# url: https://pypi.org/p/YOURPROJECT
|
|
55
|
+
#
|
|
56
|
+
# ALTERNATIVE: if your GitHub Release name is the PyPI project version string
|
|
57
|
+
# ALTERNATIVE: exactly, uncomment the following line instead:
|
|
58
|
+
# url: https://pypi.org/project/YOURPROJECT/${{ github.event.release.name }}
|
|
59
|
+
|
|
60
|
+
steps:
|
|
61
|
+
- name: Retrieve release distributions
|
|
62
|
+
uses: actions/download-artifact@v4
|
|
63
|
+
with:
|
|
64
|
+
name: release-dists
|
|
65
|
+
path: dist/
|
|
66
|
+
|
|
67
|
+
- name: Publish release distributions to PyPI
|
|
68
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
69
|
+
with:
|
|
70
|
+
packages-dir: dist/
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented here. The format follows
|
|
4
|
+
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project
|
|
5
|
+
adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
|
+
|
|
7
|
+
## [Unreleased]
|
|
8
|
+
|
|
9
|
+
## [0.1.0] — 2026-08-14
|
|
10
|
+
|
|
11
|
+
First release.
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
|
|
15
|
+
- `base scores` — scores and status for a day's games, with `--linescore` for
|
|
16
|
+
inning-by-inning detail, `--team` to filter, and flexible date input
|
|
17
|
+
(`yesterday`, `8/14`, `-3`).
|
|
18
|
+
- `base player` — biographical record plus season, career, or year-by-year stat
|
|
19
|
+
lines. The stat group follows the player's position; two-way players get both
|
|
20
|
+
hitting and pitching. Supports `--postseason` and `--full`.
|
|
21
|
+
- `base team` — a club's record, division standing, and season stat totals.
|
|
22
|
+
- `base standings` — division and wild card standings with L10, streak, and run
|
|
23
|
+
differential.
|
|
24
|
+
- `base leaders` — league leaderboards for any category, with shorthand (`hr`,
|
|
25
|
+
`era`, `whip`) and `--list` to enumerate all categories.
|
|
26
|
+
- `base roster` — a club's roster, with `--stats` to include every player's
|
|
27
|
+
season line in a single request, and `--sort` by any column.
|
|
28
|
+
- `base compare` — two or more players side by side, with the better figure in
|
|
29
|
+
each row highlighted.
|
|
30
|
+
- `base teams` — every club with its abbreviation and id.
|
|
31
|
+
- `base glossary` — what the column headings mean.
|
|
32
|
+
- `base cache` — inspect or clear the on-disk response cache.
|
|
33
|
+
- `--json` on every command, emitting a flat, stable shape rather than the raw
|
|
34
|
+
API envelope.
|
|
35
|
+
- Forgiving lookups: teams by abbreviation, city, nickname, or id; players by
|
|
36
|
+
any part of a name or MLBAM id, including retired players. Genuine ambiguity
|
|
37
|
+
is reported with candidates instead of guessed at.
|
|
38
|
+
- On-disk response cache with lifetimes matched to how fast each kind of data
|
|
39
|
+
changes.
|
|
40
|
+
- Actionable guidance when TLS verification fails, which is the common failure
|
|
41
|
+
on macOS python.org installs. `certifi` is used automatically when present but
|
|
42
|
+
is never required.
|
|
43
|
+
|
|
44
|
+
### Notes
|
|
45
|
+
|
|
46
|
+
- Zero runtime dependencies; standard library only.
|
|
47
|
+
- Requires Python 3.9 or newer.
|
|
48
|
+
- Data comes from the free public MLB Stats API. See
|
|
49
|
+
[docs/data-source.md](docs/data-source.md) for terms of use.
|
|
50
|
+
|
|
51
|
+
[Unreleased]: https://github.com/opowell28/BaseballCommand/compare/v0.1.0...HEAD
|
|
52
|
+
[0.1.0]: https://github.com/opowell28/BaseballCommand/releases/tag/v0.1.0
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
Thanks for taking a look. Bug reports, ideas, and pull requests are all welcome.
|
|
4
|
+
|
|
5
|
+
## Getting set up
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
git clone https://github.com/opowell28/BaseballCommand.git
|
|
9
|
+
cd BaseballCommand
|
|
10
|
+
python -m venv .venv && source .venv/bin/activate
|
|
11
|
+
pip install -e ".[dev]"
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Then:
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
pytest # the full suite — offline, under a second
|
|
18
|
+
ruff check . # lint
|
|
19
|
+
ruff check . --fix
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## How the code is laid out
|
|
23
|
+
|
|
24
|
+
```
|
|
25
|
+
src/baseballcommand/
|
|
26
|
+
├── cli.py argparse setup, global flags, dispatch, error handling
|
|
27
|
+
├── api.py the only module that touches the network
|
|
28
|
+
├── cache.py on-disk TTL cache for API responses
|
|
29
|
+
├── lookup.py "nyy" -> team 147, "judge" -> player 592450
|
|
30
|
+
├── stats.py which stats to show, in what order, under what heading
|
|
31
|
+
├── dates.py date parsing and local-time formatting
|
|
32
|
+
├── output.py tables, color, layout
|
|
33
|
+
├── errors.py the exception types the CLI catches
|
|
34
|
+
└── commands/ one module per subcommand
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Two rules keep this from tangling:
|
|
38
|
+
|
|
39
|
+
1. **Only `api.py` makes requests.** Commands receive a client and call its
|
|
40
|
+
methods. Caching, retries, and error translation live in one place.
|
|
41
|
+
2. **Only `output.py` formats.** Commands assemble rows and hand them over.
|
|
42
|
+
That is what makes `--no-color` and column alignment work everywhere at once.
|
|
43
|
+
|
|
44
|
+
## Adding a command
|
|
45
|
+
|
|
46
|
+
Write a module in `commands/` with two functions:
|
|
47
|
+
|
|
48
|
+
```python
|
|
49
|
+
"""``base thing`` — one line on what it does."""
|
|
50
|
+
|
|
51
|
+
from __future__ import annotations
|
|
52
|
+
|
|
53
|
+
from .. import output
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def register(subparsers) -> None:
|
|
57
|
+
parser = subparsers.add_parser(
|
|
58
|
+
"thing",
|
|
59
|
+
help="short text for `base --help`",
|
|
60
|
+
description="longer text for `base thing -h`",
|
|
61
|
+
)
|
|
62
|
+
parser.add_argument("name", help="what this is")
|
|
63
|
+
parser.set_defaults(func=run)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def run(args, ctx) -> int:
|
|
67
|
+
data = ctx.client.get("some/endpoint", {"param": args.name})
|
|
68
|
+
|
|
69
|
+
if ctx.json:
|
|
70
|
+
output.emit_json({"thing": data})
|
|
71
|
+
return 0
|
|
72
|
+
|
|
73
|
+
print(output.heading("Thing"))
|
|
74
|
+
output.blank()
|
|
75
|
+
print(output.table(["A", "B"], [[1, 2]]))
|
|
76
|
+
return 0
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Then add it to `MODULES` in `commands/__init__.py`. The tuple order is the order
|
|
80
|
+
subcommands appear in `base --help`.
|
|
81
|
+
|
|
82
|
+
`ctx` is a `cli.Context`: `ctx.client` is the API client, `ctx.json` is the
|
|
83
|
+
global `--json` flag.
|
|
84
|
+
|
|
85
|
+
Checklist for a new command:
|
|
86
|
+
|
|
87
|
+
- [ ] Supports `--json` with a flat, stable shape — not the raw API envelope.
|
|
88
|
+
- [ ] Raises `NotFoundError`, `AmbiguousError`, or `UsageError` for expected
|
|
89
|
+
failures, so the user gets a message instead of a traceback.
|
|
90
|
+
- [ ] Fails before printing anything, rather than half-way through a table.
|
|
91
|
+
- [ ] Documented in `docs/commands.md` and listed in the README table.
|
|
92
|
+
- [ ] Covered by a test in `tests/`.
|
|
93
|
+
|
|
94
|
+
## Conventions
|
|
95
|
+
|
|
96
|
+
- **Standard library only** for runtime code. This is deliberate: it keeps
|
|
97
|
+
installation trivial and the tool immune to dependency churn. `certifi` is
|
|
98
|
+
used if it happens to be installed, but is never required. Dev dependencies
|
|
99
|
+
(pytest, ruff) are unconstrained.
|
|
100
|
+
- **Python 3.9+.** Every module starts with `from __future__ import annotations`,
|
|
101
|
+
which is what lets `list[str]` and `str | None` appear in annotations on 3.9.
|
|
102
|
+
- **Line length 100**, enforced by ruff.
|
|
103
|
+
- **Comments explain why, not what.** If a line needs a comment to say what it
|
|
104
|
+
does, rewrite the line.
|
|
105
|
+
- **Missing data renders as `-`.** The API omits stats rather than nulling them;
|
|
106
|
+
never let that raise.
|
|
107
|
+
|
|
108
|
+
## Testing
|
|
109
|
+
|
|
110
|
+
The suite runs entirely offline. `tests/conftest.py` provides `FakeAPI`, a
|
|
111
|
+
stand-in for the real client that serves canned payloads:
|
|
112
|
+
|
|
113
|
+
```python
|
|
114
|
+
def test_something(monkeypatch, capsys):
|
|
115
|
+
from .test_cli import run
|
|
116
|
+
|
|
117
|
+
code, out, err = run(monkeypatch, capsys, ["scores"], schedule=SCHEDULE)
|
|
118
|
+
assert code == 0
|
|
119
|
+
assert "Final" in out
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
`run()` drives `cli.main` exactly as the shell does, so one test covers argument
|
|
123
|
+
parsing, command logic, and rendering together.
|
|
124
|
+
|
|
125
|
+
`FakeAPI` raises on any method a test did not set up. That is intentional — it
|
|
126
|
+
stops a test from silently passing on data it never provided.
|
|
127
|
+
|
|
128
|
+
If you are fixing a bug in how a response is parsed, add the real shape that
|
|
129
|
+
broke it to the fixtures. That is the most useful kind of test in this codebase,
|
|
130
|
+
because the upstream API is undocumented and its shapes are discovered rather
|
|
131
|
+
than specified.
|
|
132
|
+
|
|
133
|
+
## Reporting bugs
|
|
134
|
+
|
|
135
|
+
Please include:
|
|
136
|
+
|
|
137
|
+
- The exact command you ran.
|
|
138
|
+
- What you expected and what happened.
|
|
139
|
+
- `base --version` and your Python version.
|
|
140
|
+
- For a rendering or parsing bug, the output of the same command with `--json`.
|
|
141
|
+
That distinguishes "the API gave us something unexpected" from "we formatted
|
|
142
|
+
it wrong".
|
|
143
|
+
|
|
144
|
+
## Before opening a pull request
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
ruff check . && pytest
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
Keep changes focused, and update `docs/commands.md` and `CHANGELOG.md` when
|
|
151
|
+
behavior changes.
|
|
152
|
+
|
|
153
|
+
## Scope
|
|
154
|
+
|
|
155
|
+
BaseballCommand is a lookup tool: you ask a question, it prints an answer. Things
|
|
156
|
+
that fit well are more stat groups, better splits, more useful output shapes.
|
|
157
|
+
|
|
158
|
+
Things that don't fit: bulk export, a persistent database, or anything that
|
|
159
|
+
implies scraping the API in volume — see
|
|
160
|
+
[docs/data-source.md](docs/data-source.md) for why.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Owen Powell
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,359 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: baseballcommand
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Baseball scores and statistics in your terminal, from the free MLB Stats API.
|
|
5
|
+
Project-URL: Homepage, https://github.com/opowell28/BaseballCommand
|
|
6
|
+
Project-URL: Repository, https://github.com/opowell28/BaseballCommand
|
|
7
|
+
Project-URL: Issues, https://github.com/opowell28/BaseballCommand/issues
|
|
8
|
+
Author: Owen Powell
|
|
9
|
+
License: MIT License
|
|
10
|
+
|
|
11
|
+
Copyright (c) 2026 Owen Powell
|
|
12
|
+
|
|
13
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
14
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
15
|
+
in the Software without restriction, including without limitation the rights
|
|
16
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
17
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
18
|
+
furnished to do so, subject to the following conditions:
|
|
19
|
+
|
|
20
|
+
The above copyright notice and this permission notice shall be included in all
|
|
21
|
+
copies or substantial portions of the Software.
|
|
22
|
+
|
|
23
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
24
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
25
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
26
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
27
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
28
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
29
|
+
SOFTWARE.
|
|
30
|
+
License-File: LICENSE
|
|
31
|
+
Keywords: baseball,cli,mlb,scores,sports,statistics
|
|
32
|
+
Classifier: Development Status :: 4 - Beta
|
|
33
|
+
Classifier: Environment :: Console
|
|
34
|
+
Classifier: Intended Audience :: End Users/Desktop
|
|
35
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
36
|
+
Classifier: Operating System :: OS Independent
|
|
37
|
+
Classifier: Programming Language :: Python :: 3
|
|
38
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
39
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
40
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
41
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
42
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
43
|
+
Classifier: Topic :: Utilities
|
|
44
|
+
Requires-Python: >=3.9
|
|
45
|
+
Provides-Extra: dev
|
|
46
|
+
Requires-Dist: pytest>=7.0; extra == 'dev'
|
|
47
|
+
Requires-Dist: ruff>=0.4; extra == 'dev'
|
|
48
|
+
Description-Content-Type: text/markdown
|
|
49
|
+
|
|
50
|
+
# BaseballCommand
|
|
51
|
+
|
|
52
|
+
Baseball scores and statistics in your terminal.
|
|
53
|
+
|
|
54
|
+
BaseballCommand (`base`) is a command-line tool for looking up player stats, team
|
|
55
|
+
stats, standings, league leaders, and the day's scores. It reads from the public
|
|
56
|
+
MLB Stats API, so there is **no API key, no account, and no signup** — install it
|
|
57
|
+
and run it.
|
|
58
|
+
|
|
59
|
+
```
|
|
60
|
+
$ base scores yesterday
|
|
61
|
+
|
|
62
|
+
Scores — Thursday, August 13, 2026
|
|
63
|
+
9 games
|
|
64
|
+
|
|
65
|
+
Status Away R Home R
|
|
66
|
+
------ --------------------- -- -------------------- -
|
|
67
|
+
Final Cleveland Guardians 0 Detroit Tigers 3
|
|
68
|
+
Final Cincinnati Reds 9 Chicago White Sox 8
|
|
69
|
+
Final Pittsburgh Pirates 13 Miami Marlins 1
|
|
70
|
+
Final Seattle Mariners 1 New York Yankees 0
|
|
71
|
+
Final Boston Red Sox 7 Toronto Blue Jays 0
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
```
|
|
75
|
+
$ base player "Aaron Judge"
|
|
76
|
+
|
|
77
|
+
Aaron Judge
|
|
78
|
+
#99 · Outfielder · New York Yankees
|
|
79
|
+
|
|
80
|
+
Bats/Throws Right/Right
|
|
81
|
+
Height/Weight 6' 7", 282 lb
|
|
82
|
+
Age 34
|
|
83
|
+
Born 1992-04-26 (Linden, CA, USA)
|
|
84
|
+
MLB debut 2016-08-13
|
|
85
|
+
Status Active
|
|
86
|
+
MLBAM id 592450
|
|
87
|
+
|
|
88
|
+
Hitting — 2026
|
|
89
|
+
G PA AB R H 2B 3B HR RBI BB SO SB CS AVG OBP SLG OPS
|
|
90
|
+
-- --- --- -- -- -- -- -- --- -- -- -- -- ---- ---- ---- ----
|
|
91
|
+
59 261 214 43 53 10 0 17 38 42 72 5 3 .248 .375 .533 .908
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## Contents
|
|
97
|
+
|
|
98
|
+
- [Data Sources and Dependencies](#data-sources-and-dependencies)
|
|
99
|
+
- [Install](#install)
|
|
100
|
+
- [Quick start](#quick-start)
|
|
101
|
+
- [Commands](#commands)
|
|
102
|
+
- [Global options](#global-options)
|
|
103
|
+
- [Naming players and teams](#naming-players-and-teams)
|
|
104
|
+
- [JSON output and scripting](#json-output-and-scripting)
|
|
105
|
+
- [Caching](#caching)
|
|
106
|
+
- [Troubleshooting](#troubleshooting)
|
|
107
|
+
- [Data source and terms of use](#data-source-and-terms-of-use)
|
|
108
|
+
- [Development](#development)
|
|
109
|
+
- [License](#license)
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## Data Sources and Dependencies
|
|
114
|
+
|
|
115
|
+
Everything comes from `statsapi.mlb.com`, the same public API that powers
|
|
116
|
+
MLB.com's own scoreboards. It is unauthenticated and free to query. There is no
|
|
117
|
+
paid tier, no rate-limit key, and nothing to configure.
|
|
118
|
+
|
|
119
|
+
BaseballCommand also has **zero runtime dependencies**. It runs on the Python
|
|
120
|
+
standard library alone, so `pip install` pulls in nothing else and the tool keeps
|
|
121
|
+
working regardless of what happens to any third-party package.
|
|
122
|
+
|
|
123
|
+
Please read [Data source and terms of use](#data-source-and-terms-of-use) before
|
|
124
|
+
building anything on top of it — MLBAM permits individual, non-commercial,
|
|
125
|
+
non-bulk use of this data.
|
|
126
|
+
|
|
127
|
+
## Install
|
|
128
|
+
|
|
129
|
+
Requires Python 3.9 or newer.
|
|
130
|
+
|
|
131
|
+
The recommended way is [pipx](https://pipx.pypa.io/), which installs the CLI into
|
|
132
|
+
its own environment and puts `base` on your PATH:
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
pipx install https://github.com/opowell28/BaseballCommand.git
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
Or with pip:
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
pip install https://github.com/opowell28/BaseballCommand.git
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
From a local clone:
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
git clone https://github.com/opowell28/BaseballCommand.git && cd BaseballCommand && pip install -e .
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
Check that it worked:
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
base --version
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
The package installs two identical entry points, `base` and `baseballcommand`, and
|
|
157
|
+
also runs as a module with `python -m baseballcommand`.
|
|
158
|
+
|
|
159
|
+
## Quick start
|
|
160
|
+
|
|
161
|
+
```bash
|
|
162
|
+
base scores # today's games
|
|
163
|
+
base scores yesterday --linescore # yesterday's games, inning by inning
|
|
164
|
+
base player "Aaron Judge" # a player's current season
|
|
165
|
+
base player Ohtani --years # every season a player has played
|
|
166
|
+
base team NYY # a club's record and season totals
|
|
167
|
+
base standings --league al # American League standings
|
|
168
|
+
base leaders hr -n 5 # this season's top five home run hitters
|
|
169
|
+
base roster LAD --stats --sort HR # a full roster, sorted by home runs
|
|
170
|
+
base compare Judge Ohtani # two players side by side
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
## Commands
|
|
174
|
+
|
|
175
|
+
| Command | What it does |
|
|
176
|
+
| --- | --- |
|
|
177
|
+
| [`base scores [DATE]`](docs/commands.md#base-scores) | Scores and status for a day's games |
|
|
178
|
+
| [`base player NAME`](docs/commands.md#base-player) | One player's bio and stat lines |
|
|
179
|
+
| [`base team NAME`](docs/commands.md#base-team) | A club's record and season totals |
|
|
180
|
+
| [`base standings`](docs/commands.md#base-standings) | Division or wild card standings |
|
|
181
|
+
| [`base leaders CATEGORY`](docs/commands.md#base-leaders) | League leaderboards |
|
|
182
|
+
| [`base roster NAME`](docs/commands.md#base-roster) | A club's roster, optionally with everyone's stats |
|
|
183
|
+
| [`base compare A B`](docs/commands.md#base-compare) | Players side by side |
|
|
184
|
+
| [`base teams`](docs/commands.md#base-teams) | Every club and its abbreviation |
|
|
185
|
+
| [`base glossary`](docs/commands.md#base-glossary) | What the column headings mean |
|
|
186
|
+
| [`base cache`](docs/commands.md#base-cache) | Inspect or clear the response cache |
|
|
187
|
+
|
|
188
|
+
Every command takes `-h` for its own options. The full reference, with examples
|
|
189
|
+
and output for each, is in **[docs/commands.md](docs/commands.md)**.
|
|
190
|
+
|
|
191
|
+
## Global options
|
|
192
|
+
|
|
193
|
+
These go before the subcommand — `base --json scores`, not `base scores --json`.
|
|
194
|
+
|
|
195
|
+
| Option | Effect |
|
|
196
|
+
| --- | --- |
|
|
197
|
+
| `--json` | Print raw JSON instead of tables. Implies `--no-color`. |
|
|
198
|
+
| `--no-color` | Disable ANSI color. |
|
|
199
|
+
| `--no-cache` | Bypass the cache; always fetch fresh. |
|
|
200
|
+
| `--timeout SECONDS` | Network timeout per request (default 15). |
|
|
201
|
+
| `-V`, `--version` | Print the version. |
|
|
202
|
+
|
|
203
|
+
Color is enabled only when stdout is a terminal, and is disabled automatically
|
|
204
|
+
when you pipe or redirect output, or when [`NO_COLOR`](https://no-color.org/) is
|
|
205
|
+
set.
|
|
206
|
+
|
|
207
|
+
## Naming players and teams
|
|
208
|
+
|
|
209
|
+
You do not have to be precise. Teams accept an abbreviation, a city, a nickname,
|
|
210
|
+
a club name, a full name, or a numeric id:
|
|
211
|
+
|
|
212
|
+
```bash
|
|
213
|
+
base team NYY
|
|
214
|
+
base team "New York Yankees"
|
|
215
|
+
base team yanks
|
|
216
|
+
base team 147
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
Players accept any part of a name, or an MLBAM id. Retired players work too:
|
|
220
|
+
|
|
221
|
+
```bash
|
|
222
|
+
base player judge
|
|
223
|
+
base player "Ken Griffey Jr."
|
|
224
|
+
base player 592450
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
When a query genuinely matches more than one, BaseballCommand says so and lists
|
|
228
|
+
the candidates rather than guessing:
|
|
229
|
+
|
|
230
|
+
```
|
|
231
|
+
$ base team sox
|
|
232
|
+
base: 'sox' matches more than one team:
|
|
233
|
+
CWS Chicago White Sox
|
|
234
|
+
BOS Boston Red Sox
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
```
|
|
238
|
+
$ base player "ken griffey"
|
|
239
|
+
base: 'ken griffey' matches 2 players — rerun with a fuller name or an id:
|
|
240
|
+
115135 Ken Griffey Jr. (retired) [CF — Seattle Mariners]
|
|
241
|
+
115136 Ken Griffey Sr. (retired) [RF — Seattle Mariners]
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
Run `base teams` for the full list of clubs and abbreviations.
|
|
245
|
+
|
|
246
|
+
## JSON output and scripting
|
|
247
|
+
|
|
248
|
+
Every command supports `--json`, which prints a stable, flattened structure
|
|
249
|
+
rather than the API's raw envelope. This makes `base` usable as a data source in
|
|
250
|
+
scripts:
|
|
251
|
+
|
|
252
|
+
```bash
|
|
253
|
+
# Tonight's matchups
|
|
254
|
+
base --json scores | jq -r '.games[] | "\(.away.name) @ \(.home.name)"'
|
|
255
|
+
|
|
256
|
+
# Every team over .500
|
|
257
|
+
base --json standings | jq -r '.groups[].teams[] | select((.pct|tonumber) > 0.5) | .name'
|
|
258
|
+
|
|
259
|
+
# A player's home run total
|
|
260
|
+
base --json player "Aaron Judge" | jq '.stats.hitting[0].stat.homeRuns'
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
Exit codes are script-friendly:
|
|
264
|
+
|
|
265
|
+
| Code | Meaning |
|
|
266
|
+
| --- | --- |
|
|
267
|
+
| `0` | Success |
|
|
268
|
+
| `1` | Lookup or network failure (unknown player, API unreachable) |
|
|
269
|
+
| `2` | Bad usage (unparseable date, unknown category, ambiguous input) |
|
|
270
|
+
| `130` | Interrupted with Ctrl-C |
|
|
271
|
+
|
|
272
|
+
## Caching
|
|
273
|
+
|
|
274
|
+
Responses are cached on disk so repeated commands are fast and the free public
|
|
275
|
+
API is not hammered. Live scores get a 30-second lifetime; season stats get an
|
|
276
|
+
hour; team lists and biographical data get a day.
|
|
277
|
+
|
|
278
|
+
```bash
|
|
279
|
+
base cache # location, entry count, size on disk
|
|
280
|
+
base cache clear # throw it all away
|
|
281
|
+
base --no-cache … # bypass for one command
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
The cache lives in `~/.cache/baseballcommand` by default, honoring
|
|
285
|
+
`XDG_CACHE_HOME`. Set `BASEBALLCOMMAND_CACHE_DIR` to put it somewhere else. It is
|
|
286
|
+
safe to delete at any time.
|
|
287
|
+
|
|
288
|
+
## Troubleshooting
|
|
289
|
+
|
|
290
|
+
**`TLS certificate verification failed`**
|
|
291
|
+
|
|
292
|
+
Your Python installation has no usable root certificates. This is common with
|
|
293
|
+
the python.org macOS installer, which ships certificates but does not install
|
|
294
|
+
them.
|
|
295
|
+
|
|
296
|
+
- macOS, python.org build: run `/Applications/Python 3.x/Install Certificates.command`
|
|
297
|
+
- Any platform: `pip install certifi` — BaseballCommand uses it automatically
|
|
298
|
+
when it is present.
|
|
299
|
+
|
|
300
|
+
BaseballCommand never disables certificate verification.
|
|
301
|
+
|
|
302
|
+
**Stats are empty for the current season**
|
|
303
|
+
|
|
304
|
+
In January and February the current season has not started, so `base` defaults to
|
|
305
|
+
the season that just finished. During spring training the regular-season stats
|
|
306
|
+
are genuinely empty; pass `--season` for a specific year.
|
|
307
|
+
|
|
308
|
+
**`Could not reach the MLB Stats API`**
|
|
309
|
+
|
|
310
|
+
Check your network. If you are behind a proxy, `urllib` honors the standard
|
|
311
|
+
`HTTP_PROXY` and `HTTPS_PROXY` environment variables.
|
|
312
|
+
|
|
313
|
+
## Data source and terms of use
|
|
314
|
+
|
|
315
|
+
All data comes from the MLB Stats API at `https://statsapi.mlb.com`. That API is
|
|
316
|
+
publicly reachable but **not officially documented or supported for third-party
|
|
317
|
+
use**, and its responses carry this notice from MLB Advanced Media:
|
|
318
|
+
|
|
319
|
+
> Only individual, non-commercial, non-bulk use of the Materials is permitted and
|
|
320
|
+
> any other use of the Materials is prohibited without prior written
|
|
321
|
+
> authorization from MLBAM.
|
|
322
|
+
> — [gdx.mlb.com/components/copyright.txt](http://gdx.mlb.com/components/copyright.txt)
|
|
323
|
+
|
|
324
|
+
BaseballCommand is a personal-use tool and is built to stay inside that: it
|
|
325
|
+
queries only what you ask for, and it caches responses to avoid redundant
|
|
326
|
+
requests. If you intend to use this data commercially or to bulk-download it,
|
|
327
|
+
contact MLBAM for authorization first.
|
|
328
|
+
|
|
329
|
+
BaseballCommand is an independent project. It is **not affiliated with,
|
|
330
|
+
endorsed by, or sponsored by** Major League Baseball, MLB Advanced Media, or any
|
|
331
|
+
club. All trademarks belong to their respective owners.
|
|
332
|
+
|
|
333
|
+
More detail on which endpoints are used and how, in
|
|
334
|
+
**[docs/data-source.md](docs/data-source.md)**.
|
|
335
|
+
|
|
336
|
+
## Development
|
|
337
|
+
|
|
338
|
+
```bash
|
|
339
|
+
git clone https://github.com/opowell28/BaseballCommand.git
|
|
340
|
+
cd BaseballCommand
|
|
341
|
+
python -m venv .venv && source .venv/bin/activate
|
|
342
|
+
pip install -e ".[dev]"
|
|
343
|
+
|
|
344
|
+
pytest # the full suite, entirely offline
|
|
345
|
+
ruff check . # lint
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
The test suite makes no network calls — the API client is replaced with a fake
|
|
349
|
+
serving canned payloads — so it is fast and works offline.
|
|
350
|
+
|
|
351
|
+
See **[CONTRIBUTING.md](CONTRIBUTING.md)** for the layout of the codebase and how
|
|
352
|
+
to add a command.
|
|
353
|
+
|
|
354
|
+
## License
|
|
355
|
+
|
|
356
|
+
[MIT](LICENSE) © Owen Powell.
|
|
357
|
+
|
|
358
|
+
The license covers this software. It does not cover the data, which remains the
|
|
359
|
+
property of MLB Advanced Media under the terms linked above.
|