Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:

Expand Down
6 changes: 3 additions & 3 deletions docs/http-transport.md
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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).

Expand Down Expand Up @@ -206,7 +206,7 @@ python-mlb-statsapi/<installed-version>
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
Expand Down
2 changes: 1 addition & 1 deletion docs/releases.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ 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
- [1.0.0](releases/1.0.0.md) — strict HTTP behavior by default and a stable public API contract
- [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

30 changes: 30 additions & 0 deletions docs/releases/1.1.2.md
Original file line number Diff line number Diff line change
@@ -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`).
1 change: 1 addition & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -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 <spahmatthew@gmail.com>",
Expand Down
33 changes: 33 additions & 0 deletions tests/test_codedesc_regressions.py
Original file line number Diff line number Diff line change
@@ -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"
3 changes: 2 additions & 1 deletion tests/test_release_validation.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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.
Expand Down
Loading