From 7a69bb703c713b861ed838a372d0d9f5362477ea Mon Sep 17 00:00:00 2001 From: Matthew Spah Date: Tue, 29 Sep 2026 12:21:19 -0700 Subject: [PATCH 1/3] Prepare release 1.1.2 Bump the package version to 1.1.2 and add release notes for the CodeDesc.code fix from #343. - Bump version in pyproject.toml - Update the User-Agent version in README.md and docs/http-transport.md - Replace the 1.1.1 release notes pointer in docs/http-transport.md - Add docs/releases/1.1.2.md and link it from docs/releases.md and mkdocs.yml - Point release validation at the 1.1.2 notes and move 1.1.1 to the historical list - Add offline regression tests for #342 so a CodeDesc without a code parses, including inside PlayDetails --- README.md | 2 +- docs/http-transport.md | 6 +++--- docs/releases.md | 2 +- mkdocs.yml | 1 + pyproject.toml | 2 +- tests/test_release_validation.py | 3 ++- 6 files changed, 9 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index a25731c..6cedb78 100644 --- a/README.md +++ b/README.md @@ -202,7 +202,7 @@ See the [method reference](https://zero-sum-seattle.github.io/python-mlb-statsap Both clients use explicit timeouts, structured exceptions, and pooled HTTP connections. `strict_http=True` is the default. Final non-404 4xx responses raise `MlbHttpError`, while existing endpoint-specific 404 behavior is preserved. -Library-created clients send a versioned User-Agent. The current package version sends `python-mlb-statsapi/1.1.1`. See the [HTTP transport documentation](https://zero-sum-seattle.github.io/python-mlb-statsapi/http-transport/) for the full transport contract. +Library-created clients send a versioned User-Agent. The current package version sends `python-mlb-statsapi/1.1.2`. See the [HTTP transport documentation](https://zero-sum-seattle.github.io/python-mlb-statsapi/http-transport/) for the full transport contract. The main transport exceptions are: diff --git a/docs/http-transport.md b/docs/http-transport.md index 2e9c04a..15ecfe1 100644 --- a/docs/http-transport.md +++ b/docs/http-transport.md @@ -1,7 +1,7 @@ # HTTP Transport This document describes the HTTP transport behavior of the current release, -version 1.1.1. +version 1.1.2. Version 0.8.0 introduced shared Sessions, explicit timeouts, bounded retries, and structured exceptions. Version 0.9.0 introduced configurable strict @@ -12,7 +12,7 @@ Version 1.1.0 adds the optional asynchronous `AsyncMlb` and `AsyncMlbDataAdapter` clients while preserving the existing synchronous API. Ordinary usage does not need to configure sessions, clients, or retries. -See [the 1.1.1 release notes](releases/1.1.1.md) for a shorter summary of what +See [the 1.1.2 release notes](releases/1.1.2.md) for a shorter summary of what changed in the current release. For the authoritative public API boundary see [the public API contract](public-api.md). @@ -206,7 +206,7 @@ python-mlb-statsapi/ With the package version currently declared in project metadata that resolves to: ```text -python-mlb-statsapi/1.1.1 +python-mlb-statsapi/1.1.2 ``` The version comes from the installed package metadata, so it always matches diff --git a/docs/releases.md b/docs/releases.md index c7333ca..c542543 100644 --- a/docs/releases.md +++ b/docs/releases.md @@ -4,6 +4,7 @@ Release notes describe user-visible changes, compatibility guidance, and validat ## Releases +- [1.1.2](releases/1.1.2.md) — tolerate missing codes in MLB code-description payloads - [1.1.1](releases/1.1.1.md) — numeric stat field and MLB sentinel handling corrections - [1.1.0](releases/1.1.0.md) — first-class asynchronous client support - [1.0.1](releases/1.0.1.md) — packaging and Python support corrections @@ -11,4 +12,3 @@ Release notes describe user-visible changes, compatibility guidance, and validat - [0.9.0](releases/0.9.0.md) — public retry policy, richer HTTP errors, and compatibility warnings - [0.8.0](releases/0.8.0.md) — shared sessions, explicit timeouts, retries, and structured exceptions - [0.7.1](releases/0.7.1.md) — Pydantic v2 migration and Pythonic model fields - diff --git a/mkdocs.yml b/mkdocs.yml index ed33bdc..bef8b85 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -47,6 +47,7 @@ nav: - Public API Contract: public-api.md - Release Notes: - Overview: releases.md + - 1.1.2: releases/1.1.2.md - 1.1.1: releases/1.1.1.md - 1.1.0: releases/1.1.0.md - 1.0.1: releases/1.0.1.md diff --git a/pyproject.toml b/pyproject.toml index b4523aa..f832101 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "python-mlb-statsapi" -version = "1.1.1" +version = "1.1.2" description = "mlbstatsapi python wrapper" authors = [ "Matthew Spah ", diff --git a/tests/test_release_validation.py b/tests/test_release_validation.py index c35e06c..708c6e9 100644 --- a/tests/test_release_validation.py +++ b/tests/test_release_validation.py @@ -40,7 +40,7 @@ # Release notes for the version this branch is preparing. Kept explicit so the # current-document checks cannot silently classify an unreviewed notes file as # the current release merely because the declared version changed. -CURRENT_RELEASE_NOTES = RELEASE_NOTES_DIR / "1.1.1.md" +CURRENT_RELEASE_NOTES = RELEASE_NOTES_DIR / "1.1.2.md" # Historical notes keep their own version-specific statements and must not be # rewritten to match the current release. @@ -52,6 +52,7 @@ RELEASE_NOTES_DIR / "1.0.0.md", RELEASE_NOTES_DIR / "1.0.1.md", RELEASE_NOTES_DIR / "1.1.0.md", + RELEASE_NOTES_DIR / "1.1.1.md", ) # Deterministic CI contract for maintained release branches. From 316f223a69d18e327ad14f8fb5d3b3f76e21f4b2 Mon Sep 17 00:00:00 2001 From: Matthew Spah Date: Tue, 29 Sep 2026 12:24:55 -0700 Subject: [PATCH 2/3] docs: adding release notes for 1.1.2.md --- docs/releases/1.1.2.md | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 docs/releases/1.1.2.md diff --git a/docs/releases/1.1.2.md b/docs/releases/1.1.2.md new file mode 100644 index 0000000..33162fa --- /dev/null +++ b/docs/releases/1.1.2.md @@ -0,0 +1,30 @@ +# python-mlb-statsapi 1.1.2 + +Version 1.1.2 fixes parsing of MLB data objects when the API omits an expected code value. + +## Data model fix + +`CodeDesc.code` is now optional. + +Some MLB Stats API responses contain a code-description object with a description but no `code`. For example, play-by-play data may contain a type with a description of `"Unknown"` while omitting the corresponding code entirely. + +Previous versions treated `code` as required, causing Pydantic validation to reject the response. Version 1.1.2 accepts these payloads and represents the missing code as `None`. + +Normal API usage is unchanged: + +```python +from mlbstatsapi import Mlb + +with Mlb() as mlb: + game = mlb.get_game(777961) +``` + +This is a backward-compatible model correction and requires no application changes. + +The fix was introduced in [#343](https://github.com/zero-sum-seattle/python-mlb-statsapi/pull/343). + +## Python support + +python-mlb-statsapi requires Python >=3.10. + +CI validates Python 3.10 through 3.14 (`3.10`, `3.11`, `3.12`, `3.13`, and `3.14`). From 681a422c6fd04bef8d86dca0ff5977e365613540 Mon Sep 17 00:00:00 2001 From: Matthew Spah Date: Tue, 29 Sep 2026 12:37:02 -0700 Subject: [PATCH 3/3] test: add test_codedesc_regressions.py --- tests/test_codedesc_regressions.py | 33 ++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 tests/test_codedesc_regressions.py diff --git a/tests/test_codedesc_regressions.py b/tests/test_codedesc_regressions.py new file mode 100644 index 0000000..54755e6 --- /dev/null +++ b/tests/test_codedesc_regressions.py @@ -0,0 +1,33 @@ +from mlbstatsapi.models.data import CodeDesc, PlayDetails + + +def test_codedesc_accepts_missing_code(): + """ + Regression test for #342. + + Game 777961 returns a play event whose details.type has a description of + "Unknown" and no code. Validation used to fail because code was required. + """ + code_desc = CodeDesc(description="Unknown") + + assert code_desc.code is None + assert code_desc.description == "Unknown" + + +def test_play_details_accepts_type_without_code(): + """The missing code must not break parsing of the enclosing play details.""" + details = PlayDetails.model_validate( + {"description": "Status Change - Pre-Game", "type": {"description": "Unknown"}} + ) + + assert details.type is not None + assert details.type.code is None + assert details.type.description == "Unknown" + + +def test_codedesc_still_populates_code_when_present(): + """Making code optional must not stop a present code from populating the field.""" + code_desc = CodeDesc.model_validate({"code": "R", "description": "Right"}) + + assert code_desc.code == "R" + assert code_desc.description == "Right"