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/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`). 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_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" 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.