backcaster 0.3.2__tar.gz → 0.3.3__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.
Files changed (30) hide show
  1. {backcaster-0.3.2/src/backcaster.egg-info → backcaster-0.3.3}/PKG-INFO +26 -32
  2. {backcaster-0.3.2 → backcaster-0.3.3}/README.md +24 -29
  3. {backcaster-0.3.2 → backcaster-0.3.3}/pyproject.toml +2 -3
  4. {backcaster-0.3.2 → backcaster-0.3.3}/src/backcaster/__init__.py +1 -1
  5. backcaster-0.3.3/src/backcaster/cli.py +86 -0
  6. backcaster-0.3.3/src/backcaster/data.py +9 -0
  7. {backcaster-0.3.2 → backcaster-0.3.3}/src/backcaster/lahman.py +4 -1
  8. {backcaster-0.3.2 → backcaster-0.3.3}/src/backcaster/marcel.py +7 -2
  9. {backcaster-0.3.2 → backcaster-0.3.3}/src/backcaster/schemas.py +0 -1
  10. {backcaster-0.3.2 → backcaster-0.3.3/src/backcaster.egg-info}/PKG-INFO +26 -32
  11. {backcaster-0.3.2 → backcaster-0.3.3}/src/backcaster.egg-info/SOURCES.txt +1 -4
  12. {backcaster-0.3.2 → backcaster-0.3.3}/src/backcaster.egg-info/requires.txt +0 -1
  13. backcaster-0.3.3/tests/test_cli.py +102 -0
  14. {backcaster-0.3.2 → backcaster-0.3.3}/tests/test_lahman.py +27 -2
  15. {backcaster-0.3.2 → backcaster-0.3.3}/tests/test_marcel_math.py +49 -0
  16. backcaster-0.3.2/src/backcaster/cli.py +0 -176
  17. backcaster-0.3.2/src/backcaster/data.py +0 -246
  18. backcaster-0.3.2/tests/test_cli.py +0 -259
  19. backcaster-0.3.2/tests/test_cli_player_lookup.py +0 -60
  20. backcaster-0.3.2/tests/test_data.py +0 -412
  21. backcaster-0.3.2/tests/test_player_lookup.py +0 -89
  22. {backcaster-0.3.2 → backcaster-0.3.3}/LICENSE +0 -0
  23. {backcaster-0.3.2 → backcaster-0.3.3}/setup.cfg +0 -0
  24. {backcaster-0.3.2 → backcaster-0.3.3}/src/backcaster/normalize.py +0 -0
  25. {backcaster-0.3.2 → backcaster-0.3.3}/src/backcaster/outputs.py +0 -0
  26. {backcaster-0.3.2 → backcaster-0.3.3}/src/backcaster.egg-info/dependency_links.txt +0 -0
  27. {backcaster-0.3.2 → backcaster-0.3.3}/src/backcaster.egg-info/entry_points.txt +0 -0
  28. {backcaster-0.3.2 → backcaster-0.3.3}/src/backcaster.egg-info/top_level.txt +0 -0
  29. {backcaster-0.3.2 → backcaster-0.3.3}/tests/test_normalize.py +0 -0
  30. {backcaster-0.3.2 → backcaster-0.3.3}/tests/test_outputs.py +0 -0
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: backcaster
3
- Version: 0.3.2
4
- Summary: Marcel-style MLB projection CLI built on pybaseball
3
+ Version: 0.3.3
4
+ Summary: Marcel-style MLB projection CLI using local Lahman CSV data
5
5
  License-Expression: MIT
6
6
  Project-URL: Homepage, https://github.com/jeffreywevans/backcaster
7
7
  Project-URL: Repository, https://github.com/jeffreywevans/backcaster
@@ -18,7 +18,6 @@ Requires-Python: >=3.13
18
18
  Description-Content-Type: text/markdown
19
19
  License-File: LICENSE
20
20
  Requires-Dist: pandas>=2.0
21
- Requires-Dist: pybaseball>=2.2
22
21
  Provides-Extra: dev
23
22
  Requires-Dist: pytest>=8.0; extra == "dev"
24
23
  Requires-Dist: pytest-cov>=5.0; extra == "dev"
@@ -30,7 +29,7 @@ Dynamic: license-file
30
29
 
31
30
  # Backcaster
32
31
 
33
- Backcaster is a Python CLI that produces **Marcel-style MLB projections** from the prior three seasons of data using [`pybaseball`](https://github.com/jldbc/pybaseball) and `pandas`.
32
+ Backcaster is a Python CLI that produces **Marcel-style MLB projections** from the prior three seasons of data using local Lahman CSV files and `pandas`.
34
33
 
35
34
  It supports:
36
35
  - **Single player projections** (`player`)
@@ -44,7 +43,8 @@ It supports:
44
43
 
45
44
  ### Requirements
46
45
  - Python **3.13+**
47
- - Internet access for first-time stat fetches (data is cached locally afterward)
46
+ - An extracted Lahman CSV database covering the three prior seasons
47
+ - Internet access for package installation only; projections run offline
48
48
 
49
49
  ### Update an installed package
50
50
 
@@ -54,10 +54,10 @@ Upgrade to the latest release available on PyPI:
54
54
  python -m pip install --upgrade backcaster
55
55
  ```
56
56
 
57
- To install a specific release, such as 0.3.2:
57
+ To install a specific release, such as 0.3.3:
58
58
 
59
59
  ```powershell
60
- python -m pip install --upgrade backcaster==0.3.2
60
+ python -m pip install --upgrade backcaster==0.3.3
61
61
  ```
62
62
 
63
63
  Run the command using the same Python environment where you run Backcaster.
@@ -116,12 +116,20 @@ backcaster player --name "Mookie Betts" --year 2026 --kind batting
116
116
 
117
117
  ### Offline projections with Lahman CSVs
118
118
 
119
- Extract your Lahman CSV distribution into a local directory. Pass `--data-dir`
120
- to use it without any network requests, player-register downloads, or FanGraphs
121
- cache reads. The directory must contain `People.csv`, `Teams.csv`, and
119
+ All projections use local Lahman CSVs. On Windows, the default directory is
120
+ `C:\Baseball\lahman`; on other systems it is `~/Baseball/lahman`.
121
+ Set the `LAHMAN_DATA_DIR` environment variable to change the default, or pass
122
+ `--data-dir` to override it for one command. No network requests or online
123
+ fallbacks are made. The directory must contain `People.csv`, `Teams.csv`, and
122
124
  `Batting.csv` or `Pitching.csv` for the selected kind. Filenames are matched
123
125
  without regard to case. The database is not bundled with Backcaster.
124
126
 
127
+ For the default Windows directory, no additional flag is needed:
128
+
129
+ ```powershell
130
+ backcaster player --name "Mookie Betts" --year 2024 --kind batting
131
+ ```
132
+
125
133
  See [Lahman database notes](docs/LAHMAN.md) for the supplied 1871–2025 edition's
126
134
  coverage, attribution, license, and historical-data caveats, with its original README.
127
135
 
@@ -134,8 +142,8 @@ backcaster batch --year 2022 --kind pitching --data-dir "C:\Baseball\lahman" --f
134
142
  Use Lahman's `teamID` values, such as `LAN` for the Dodgers (rather than the
135
143
  FanGraphs abbreviation `LAD`). A projection year needs the preceding three seasons:
136
144
  2022 requires 2019–2021. Missing seasons produce an error explaining which year
137
- is unavailable. Without `--data-dir`, the existing pybaseball source is used;
138
- FanGraphs may reject its automated requests with HTTP 403.
145
+ is unavailable. If the directory or required files are missing, the command
146
+ reports the missing file and directory; it never attempts an online fetch.
139
147
 
140
148
  Offline qualification uses a consistent modern rule across historical seasons:
141
149
  at least **3.1 PA per game** for hitters and **one inning per game** for pitchers.
@@ -162,7 +170,7 @@ to the team in their latest stint for that season; this is not a current-roster
162
170
  ### 2) Team projection
163
171
 
164
172
  ```bash
165
- backcaster team --team LAD --year 2026 --kind pitching
173
+ backcaster team --team LAN --year 2026 --kind pitching
166
174
  ```
167
175
 
168
176
  ### 3) Batch projection (all players returned by source data)
@@ -175,7 +183,7 @@ backcaster batch --year 2026 --kind batting
175
183
 
176
184
  ```bash
177
185
  backcaster player --name "Mookie Betts" --year 2026 --kind batting --format csv --out ./out/mookie_2026.csv
178
- backcaster team --team LAD --year 2026 --kind pitching --format html --out ./out/lad_pitching_2026.html
186
+ backcaster team --team LAN --year 2026 --kind pitching --format html --out ./out/lan_pitching_2026.html
179
187
  ```
180
188
 
181
189
  > `--out` is required for `csv` and `html` formats.
@@ -201,24 +209,11 @@ A basic HTML table (no custom CSS) suitable for quick sharing or embedding.
201
209
 
202
210
  ---
203
211
 
204
- ## Cache behavior
205
-
206
- Backcaster caches season stat pulls under:
207
-
208
- ```text
209
- ~/.cache/backcaster/
210
- ```
211
-
212
- Cache details:
213
- - Key pattern: `<kind>_<year>.parquet` (preferred) or `<kind>_<year>.csv` (fallback)
214
- - Read order: Parquet first, then CSV
215
- - Write behavior: atomic temp-file write + rename to reduce corruption risk
216
- - Parquet write failures automatically fall back to CSV
212
+ ## Local data updates
217
213
 
218
- Practical implications:
219
- - First run for a season may be slower (network fetch).
220
- - Re-runs are typically faster (local cache hit).
221
- - If upstream data changes and you need a refresh, delete the relevant cache file(s) and rerun.
214
+ Backcaster reads the local CSV files for each command and does not use the old
215
+ FanGraphs season cache. To refresh the data, replace the CSVs with a complete
216
+ Lahman distribution from the same edition. Existing online caches are ignored.
222
217
 
223
218
  ---
224
219
 
@@ -226,7 +221,6 @@ Practical implications:
226
221
 
227
222
  Runtime dependencies are intentionally minimal:
228
223
  - `pandas` for tabular data processing and projection output
229
- - `pybaseball` for MLB player/team seasonal stat retrieval and player ID lookup
230
224
 
231
225
  Development dependencies (`--extra dev`) include:
232
226
  - `pytest`, `pytest-cov`
@@ -1,6 +1,6 @@
1
1
  # Backcaster
2
2
 
3
- Backcaster is a Python CLI that produces **Marcel-style MLB projections** from the prior three seasons of data using [`pybaseball`](https://github.com/jldbc/pybaseball) and `pandas`.
3
+ Backcaster is a Python CLI that produces **Marcel-style MLB projections** from the prior three seasons of data using local Lahman CSV files and `pandas`.
4
4
 
5
5
  It supports:
6
6
  - **Single player projections** (`player`)
@@ -14,7 +14,8 @@ It supports:
14
14
 
15
15
  ### Requirements
16
16
  - Python **3.13+**
17
- - Internet access for first-time stat fetches (data is cached locally afterward)
17
+ - An extracted Lahman CSV database covering the three prior seasons
18
+ - Internet access for package installation only; projections run offline
18
19
 
19
20
  ### Update an installed package
20
21
 
@@ -24,10 +25,10 @@ Upgrade to the latest release available on PyPI:
24
25
  python -m pip install --upgrade backcaster
25
26
  ```
26
27
 
27
- To install a specific release, such as 0.3.2:
28
+ To install a specific release, such as 0.3.3:
28
29
 
29
30
  ```powershell
30
- python -m pip install --upgrade backcaster==0.3.2
31
+ python -m pip install --upgrade backcaster==0.3.3
31
32
  ```
32
33
 
33
34
  Run the command using the same Python environment where you run Backcaster.
@@ -86,12 +87,20 @@ backcaster player --name "Mookie Betts" --year 2026 --kind batting
86
87
 
87
88
  ### Offline projections with Lahman CSVs
88
89
 
89
- Extract your Lahman CSV distribution into a local directory. Pass `--data-dir`
90
- to use it without any network requests, player-register downloads, or FanGraphs
91
- cache reads. The directory must contain `People.csv`, `Teams.csv`, and
90
+ All projections use local Lahman CSVs. On Windows, the default directory is
91
+ `C:\Baseball\lahman`; on other systems it is `~/Baseball/lahman`.
92
+ Set the `LAHMAN_DATA_DIR` environment variable to change the default, or pass
93
+ `--data-dir` to override it for one command. No network requests or online
94
+ fallbacks are made. The directory must contain `People.csv`, `Teams.csv`, and
92
95
  `Batting.csv` or `Pitching.csv` for the selected kind. Filenames are matched
93
96
  without regard to case. The database is not bundled with Backcaster.
94
97
 
98
+ For the default Windows directory, no additional flag is needed:
99
+
100
+ ```powershell
101
+ backcaster player --name "Mookie Betts" --year 2024 --kind batting
102
+ ```
103
+
95
104
  See [Lahman database notes](docs/LAHMAN.md) for the supplied 1871–2025 edition's
96
105
  coverage, attribution, license, and historical-data caveats, with its original README.
97
106
 
@@ -104,8 +113,8 @@ backcaster batch --year 2022 --kind pitching --data-dir "C:\Baseball\lahman" --f
104
113
  Use Lahman's `teamID` values, such as `LAN` for the Dodgers (rather than the
105
114
  FanGraphs abbreviation `LAD`). A projection year needs the preceding three seasons:
106
115
  2022 requires 2019–2021. Missing seasons produce an error explaining which year
107
- is unavailable. Without `--data-dir`, the existing pybaseball source is used;
108
- FanGraphs may reject its automated requests with HTTP 403.
116
+ is unavailable. If the directory or required files are missing, the command
117
+ reports the missing file and directory; it never attempts an online fetch.
109
118
 
110
119
  Offline qualification uses a consistent modern rule across historical seasons:
111
120
  at least **3.1 PA per game** for hitters and **one inning per game** for pitchers.
@@ -132,7 +141,7 @@ to the team in their latest stint for that season; this is not a current-roster
132
141
  ### 2) Team projection
133
142
 
134
143
  ```bash
135
- backcaster team --team LAD --year 2026 --kind pitching
144
+ backcaster team --team LAN --year 2026 --kind pitching
136
145
  ```
137
146
 
138
147
  ### 3) Batch projection (all players returned by source data)
@@ -145,7 +154,7 @@ backcaster batch --year 2026 --kind batting
145
154
 
146
155
  ```bash
147
156
  backcaster player --name "Mookie Betts" --year 2026 --kind batting --format csv --out ./out/mookie_2026.csv
148
- backcaster team --team LAD --year 2026 --kind pitching --format html --out ./out/lad_pitching_2026.html
157
+ backcaster team --team LAN --year 2026 --kind pitching --format html --out ./out/lan_pitching_2026.html
149
158
  ```
150
159
 
151
160
  > `--out` is required for `csv` and `html` formats.
@@ -171,24 +180,11 @@ A basic HTML table (no custom CSS) suitable for quick sharing or embedding.
171
180
 
172
181
  ---
173
182
 
174
- ## Cache behavior
175
-
176
- Backcaster caches season stat pulls under:
177
-
178
- ```text
179
- ~/.cache/backcaster/
180
- ```
181
-
182
- Cache details:
183
- - Key pattern: `<kind>_<year>.parquet` (preferred) or `<kind>_<year>.csv` (fallback)
184
- - Read order: Parquet first, then CSV
185
- - Write behavior: atomic temp-file write + rename to reduce corruption risk
186
- - Parquet write failures automatically fall back to CSV
183
+ ## Local data updates
187
184
 
188
- Practical implications:
189
- - First run for a season may be slower (network fetch).
190
- - Re-runs are typically faster (local cache hit).
191
- - If upstream data changes and you need a refresh, delete the relevant cache file(s) and rerun.
185
+ Backcaster reads the local CSV files for each command and does not use the old
186
+ FanGraphs season cache. To refresh the data, replace the CSVs with a complete
187
+ Lahman distribution from the same edition. Existing online caches are ignored.
192
188
 
193
189
  ---
194
190
 
@@ -196,7 +192,6 @@ Practical implications:
196
192
 
197
193
  Runtime dependencies are intentionally minimal:
198
194
  - `pandas` for tabular data processing and projection output
199
- - `pybaseball` for MLB player/team seasonal stat retrieval and player ID lookup
200
195
 
201
196
  Development dependencies (`--extra dev`) include:
202
197
  - `pytest`, `pytest-cov`
@@ -5,7 +5,7 @@ build-backend = "setuptools.build_meta"
5
5
  [project]
6
6
  name = "backcaster"
7
7
  dynamic = ["version"]
8
- description = "Marcel-style MLB projection CLI built on pybaseball"
8
+ description = "Marcel-style MLB projection CLI using local Lahman CSV data"
9
9
  readme = "README.md"
10
10
  license = "MIT"
11
11
  license-files = ["LICENSE"]
@@ -22,7 +22,6 @@ classifiers = [
22
22
  requires-python = ">=3.13"
23
23
  dependencies = [
24
24
  "pandas>=2.0",
25
- "pybaseball>=2.2",
26
25
  ]
27
26
 
28
27
  [project.urls]
@@ -85,5 +84,5 @@ no_implicit_optional = true
85
84
  check_untyped_defs = true
86
85
 
87
86
  [[tool.mypy.overrides]]
88
- module = ["pandas", "pandas.*", "pybaseball", "pybaseball.*"]
87
+ module = ["pandas", "pandas.*"]
89
88
  ignore_missing_imports = true
@@ -1,4 +1,4 @@
1
1
  """backcaster package."""
2
2
 
3
3
  __all__ = ["__version__"]
4
- __version__ = "0.3.2"
4
+ __version__ = "0.3.3"
@@ -0,0 +1,86 @@
1
+ from __future__ import annotations
2
+
3
+ import argparse
4
+ import os
5
+ import sys
6
+ from pathlib import Path
7
+
8
+ import pandas as pd
9
+
10
+ from backcaster.data import DataFetchError, PlayerLookupError
11
+ from backcaster.lahman import LahmanSource
12
+ from backcaster.marcel import ProjectionError
13
+ from backcaster.outputs import to_cli_table, to_csv, to_html
14
+
15
+ _FILE_RENDERERS = {"csv": to_csv, "html": to_html}
16
+ _OUTPUT_FORMAT_CHOICES = ("cli", *_FILE_RENDERERS.keys())
17
+
18
+
19
+ def _default_data_dir() -> str:
20
+ default = (
21
+ "C:/Baseball/lahman"
22
+ if sys.platform == "win32"
23
+ else str(Path.home() / "Baseball" / "lahman")
24
+ )
25
+ return os.environ.get("LAHMAN_DATA_DIR", default)
26
+
27
+
28
+ def _render(df: pd.DataFrame, output_format: str, out: str | None) -> None:
29
+ if output_format == "cli":
30
+ print(to_cli_table(df))
31
+ elif output_format in _FILE_RENDERERS:
32
+ if not out:
33
+ raise ValueError(f"--out is required for {output_format} output")
34
+ _FILE_RENDERERS[output_format](df, out)
35
+ else:
36
+ raise ValueError(f"Unsupported format: {output_format}")
37
+
38
+
39
+ def build_parser() -> argparse.ArgumentParser:
40
+ p = argparse.ArgumentParser(prog="backcaster")
41
+ sub = p.add_subparsers(dest="command", required=True)
42
+
43
+ def add_common(sp: argparse.ArgumentParser) -> None:
44
+ sp.add_argument("--year", type=int, required=True)
45
+ sp.add_argument("--kind", choices=["batting", "pitching"], required=True)
46
+ sp.add_argument("--format", choices=_OUTPUT_FORMAT_CHOICES, default="cli")
47
+ sp.add_argument("--out")
48
+ sp.add_argument(
49
+ "--data-dir",
50
+ default=_default_data_dir(),
51
+ help="Lahman CSV directory (default: LAHMAN_DATA_DIR, C:/Baseball/lahman on Windows, or ~/Baseball/lahman)",
52
+ )
53
+
54
+ pp = sub.add_parser("player")
55
+ add_common(pp)
56
+ pp.add_argument("--name", required=True)
57
+
58
+ tp = sub.add_parser("team")
59
+ add_common(tp)
60
+ tp.add_argument("--team", required=True)
61
+
62
+ bp = sub.add_parser("batch")
63
+ add_common(bp)
64
+ return p
65
+
66
+
67
+ def main(argv: list[str] | None = None) -> int:
68
+ parser = build_parser()
69
+ args = parser.parse_args(argv)
70
+ try:
71
+ result = LahmanSource(args.data_dir).project(
72
+ args.command,
73
+ args.year,
74
+ args.kind,
75
+ name=getattr(args, "name", None),
76
+ team=getattr(args, "team", None),
77
+ )
78
+ _render(result, args.format, args.out)
79
+ return 0
80
+ except (DataFetchError, PlayerLookupError, ProjectionError, ValueError) as exc:
81
+ print(f"Error: {exc}", file=sys.stderr)
82
+ return 2
83
+
84
+
85
+ if __name__ == "__main__":
86
+ raise SystemExit(main())
@@ -0,0 +1,9 @@
1
+ """Errors reported when local source data cannot be loaded or resolved."""
2
+
3
+
4
+ class DataFetchError(RuntimeError):
5
+ pass
6
+
7
+
8
+ class PlayerLookupError(RuntimeError):
9
+ pass
@@ -21,7 +21,10 @@ class LahmanSource:
21
21
  p for p in self.directory.glob("*") if p.name.casefold() == f"{name}.csv".casefold()
22
22
  ]
23
23
  if len(paths) != 1:
24
- raise DataFetchError(f"Expected {name}.csv in Lahman directory '{self.directory}'.")
24
+ raise DataFetchError(
25
+ f"Expected {name}.csv in Lahman directory '{self.directory}'. "
26
+ "Extract the Lahman CSVs there or select their directory with --data-dir."
27
+ )
25
28
  try:
26
29
  self.tables[name] = pd.read_csv(paths[0], encoding="utf-8-sig", low_memory=False)
27
30
  except (OSError, ValueError) as exc:
@@ -128,7 +128,12 @@ def project_player(
128
128
 
129
129
  pt_col = comps[0]
130
130
  weighted_pt = float(weighted[pt_col])
131
- reliability = min(1.0, safe_divide(weighted_pt, config.reliability_scale))
131
+ # Regression uses weighted evidence, not the per-season average used for
132
+ # playing time. Averaging first would multiply regression strength by the
133
+ # sum of the season weights (12 for three seasons with weights 5/4/3).
134
+ evidence = weighted * sum(config.season_weights[: len(rows)])
135
+ evidence_pt = float(evidence[pt_col])
136
+ reliability = safe_divide(evidence_pt, evidence_pt + reg_pt)
132
137
 
133
138
  if league_rates is None:
134
139
  baseline_df = league_df if league_df is not None else prior_df
@@ -138,7 +143,7 @@ def project_player(
138
143
  regressed[pt_col] = weighted_pt
139
144
  for c in comps[1:]:
140
145
  regressed_rate = safe_divide(
141
- float(weighted[c]) + league_rates[c] * reg_pt, weighted_pt + reg_pt
146
+ float(evidence[c]) + league_rates[c] * reg_pt, evidence_pt + reg_pt
142
147
  )
143
148
  regressed[c] = regressed_rate * weighted_pt
144
149
 
@@ -18,7 +18,6 @@ class MarcelConfig:
18
18
  regression_pa: float = 1200.0
19
19
  regression_ip: float = 200.0
20
20
  age_adjustment_fn: Callable[[float], float] = lambda age: 1.0 + (0.006 if age <= 29 else -0.003)
21
- reliability_scale: float = 1200.0
22
21
  default_pa_growth: float = 1.0
23
22
  default_ip_growth: float = 1.0
24
23
 
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: backcaster
3
- Version: 0.3.2
4
- Summary: Marcel-style MLB projection CLI built on pybaseball
3
+ Version: 0.3.3
4
+ Summary: Marcel-style MLB projection CLI using local Lahman CSV data
5
5
  License-Expression: MIT
6
6
  Project-URL: Homepage, https://github.com/jeffreywevans/backcaster
7
7
  Project-URL: Repository, https://github.com/jeffreywevans/backcaster
@@ -18,7 +18,6 @@ Requires-Python: >=3.13
18
18
  Description-Content-Type: text/markdown
19
19
  License-File: LICENSE
20
20
  Requires-Dist: pandas>=2.0
21
- Requires-Dist: pybaseball>=2.2
22
21
  Provides-Extra: dev
23
22
  Requires-Dist: pytest>=8.0; extra == "dev"
24
23
  Requires-Dist: pytest-cov>=5.0; extra == "dev"
@@ -30,7 +29,7 @@ Dynamic: license-file
30
29
 
31
30
  # Backcaster
32
31
 
33
- Backcaster is a Python CLI that produces **Marcel-style MLB projections** from the prior three seasons of data using [`pybaseball`](https://github.com/jldbc/pybaseball) and `pandas`.
32
+ Backcaster is a Python CLI that produces **Marcel-style MLB projections** from the prior three seasons of data using local Lahman CSV files and `pandas`.
34
33
 
35
34
  It supports:
36
35
  - **Single player projections** (`player`)
@@ -44,7 +43,8 @@ It supports:
44
43
 
45
44
  ### Requirements
46
45
  - Python **3.13+**
47
- - Internet access for first-time stat fetches (data is cached locally afterward)
46
+ - An extracted Lahman CSV database covering the three prior seasons
47
+ - Internet access for package installation only; projections run offline
48
48
 
49
49
  ### Update an installed package
50
50
 
@@ -54,10 +54,10 @@ Upgrade to the latest release available on PyPI:
54
54
  python -m pip install --upgrade backcaster
55
55
  ```
56
56
 
57
- To install a specific release, such as 0.3.2:
57
+ To install a specific release, such as 0.3.3:
58
58
 
59
59
  ```powershell
60
- python -m pip install --upgrade backcaster==0.3.2
60
+ python -m pip install --upgrade backcaster==0.3.3
61
61
  ```
62
62
 
63
63
  Run the command using the same Python environment where you run Backcaster.
@@ -116,12 +116,20 @@ backcaster player --name "Mookie Betts" --year 2026 --kind batting
116
116
 
117
117
  ### Offline projections with Lahman CSVs
118
118
 
119
- Extract your Lahman CSV distribution into a local directory. Pass `--data-dir`
120
- to use it without any network requests, player-register downloads, or FanGraphs
121
- cache reads. The directory must contain `People.csv`, `Teams.csv`, and
119
+ All projections use local Lahman CSVs. On Windows, the default directory is
120
+ `C:\Baseball\lahman`; on other systems it is `~/Baseball/lahman`.
121
+ Set the `LAHMAN_DATA_DIR` environment variable to change the default, or pass
122
+ `--data-dir` to override it for one command. No network requests or online
123
+ fallbacks are made. The directory must contain `People.csv`, `Teams.csv`, and
122
124
  `Batting.csv` or `Pitching.csv` for the selected kind. Filenames are matched
123
125
  without regard to case. The database is not bundled with Backcaster.
124
126
 
127
+ For the default Windows directory, no additional flag is needed:
128
+
129
+ ```powershell
130
+ backcaster player --name "Mookie Betts" --year 2024 --kind batting
131
+ ```
132
+
125
133
  See [Lahman database notes](docs/LAHMAN.md) for the supplied 1871–2025 edition's
126
134
  coverage, attribution, license, and historical-data caveats, with its original README.
127
135
 
@@ -134,8 +142,8 @@ backcaster batch --year 2022 --kind pitching --data-dir "C:\Baseball\lahman" --f
134
142
  Use Lahman's `teamID` values, such as `LAN` for the Dodgers (rather than the
135
143
  FanGraphs abbreviation `LAD`). A projection year needs the preceding three seasons:
136
144
  2022 requires 2019–2021. Missing seasons produce an error explaining which year
137
- is unavailable. Without `--data-dir`, the existing pybaseball source is used;
138
- FanGraphs may reject its automated requests with HTTP 403.
145
+ is unavailable. If the directory or required files are missing, the command
146
+ reports the missing file and directory; it never attempts an online fetch.
139
147
 
140
148
  Offline qualification uses a consistent modern rule across historical seasons:
141
149
  at least **3.1 PA per game** for hitters and **one inning per game** for pitchers.
@@ -162,7 +170,7 @@ to the team in their latest stint for that season; this is not a current-roster
162
170
  ### 2) Team projection
163
171
 
164
172
  ```bash
165
- backcaster team --team LAD --year 2026 --kind pitching
173
+ backcaster team --team LAN --year 2026 --kind pitching
166
174
  ```
167
175
 
168
176
  ### 3) Batch projection (all players returned by source data)
@@ -175,7 +183,7 @@ backcaster batch --year 2026 --kind batting
175
183
 
176
184
  ```bash
177
185
  backcaster player --name "Mookie Betts" --year 2026 --kind batting --format csv --out ./out/mookie_2026.csv
178
- backcaster team --team LAD --year 2026 --kind pitching --format html --out ./out/lad_pitching_2026.html
186
+ backcaster team --team LAN --year 2026 --kind pitching --format html --out ./out/lan_pitching_2026.html
179
187
  ```
180
188
 
181
189
  > `--out` is required for `csv` and `html` formats.
@@ -201,24 +209,11 @@ A basic HTML table (no custom CSS) suitable for quick sharing or embedding.
201
209
 
202
210
  ---
203
211
 
204
- ## Cache behavior
205
-
206
- Backcaster caches season stat pulls under:
207
-
208
- ```text
209
- ~/.cache/backcaster/
210
- ```
211
-
212
- Cache details:
213
- - Key pattern: `<kind>_<year>.parquet` (preferred) or `<kind>_<year>.csv` (fallback)
214
- - Read order: Parquet first, then CSV
215
- - Write behavior: atomic temp-file write + rename to reduce corruption risk
216
- - Parquet write failures automatically fall back to CSV
212
+ ## Local data updates
217
213
 
218
- Practical implications:
219
- - First run for a season may be slower (network fetch).
220
- - Re-runs are typically faster (local cache hit).
221
- - If upstream data changes and you need a refresh, delete the relevant cache file(s) and rerun.
214
+ Backcaster reads the local CSV files for each command and does not use the old
215
+ FanGraphs season cache. To refresh the data, replace the CSVs with a complete
216
+ Lahman distribution from the same edition. Existing online caches are ignored.
222
217
 
223
218
  ---
224
219
 
@@ -226,7 +221,6 @@ Practical implications:
226
221
 
227
222
  Runtime dependencies are intentionally minimal:
228
223
  - `pandas` for tabular data processing and projection output
229
- - `pybaseball` for MLB player/team seasonal stat retrieval and player ID lookup
230
224
 
231
225
  Development dependencies (`--extra dev`) include:
232
226
  - `pytest`, `pytest-cov`
@@ -16,10 +16,7 @@ src/backcaster.egg-info/entry_points.txt
16
16
  src/backcaster.egg-info/requires.txt
17
17
  src/backcaster.egg-info/top_level.txt
18
18
  tests/test_cli.py
19
- tests/test_cli_player_lookup.py
20
- tests/test_data.py
21
19
  tests/test_lahman.py
22
20
  tests/test_marcel_math.py
23
21
  tests/test_normalize.py
24
- tests/test_outputs.py
25
- tests/test_player_lookup.py
22
+ tests/test_outputs.py
@@ -1,5 +1,4 @@
1
1
  pandas>=2.0
2
- pybaseball>=2.2
3
2
 
4
3
  [dev]
5
4
  pytest>=8.0