Skip to content

v1.1.0: Add first-class async client support and streamline documentation #297

Description

@Mattsface

v1.1.0: Add first-class async client support and streamline documentation

Goal

Version 1.1.0 will add first-class asynchronous support to python-mlb-statsapi while preserving the existing synchronous Mlb API and the stable 1.x behavioral contract introduced in version 1.0.0.

The async implementation should reuse the existing models, exceptions, endpoint semantics, and response parsing wherever practical rather than creating a separate project or independently maintained implementation.

Version 1.1.0 will also streamline the README so new users can understand and start using the library without working through detailed transport and API documentation first.

Core design

The package should expose two explicit clients:

from mlbstatsapi import Mlb
from mlbstatsapi import AsyncMlb

Synchronous usage remains unchanged:

with Mlb() as mlb:
    team = mlb.get_team(136)

Async usage should follow normal Python async conventions:

async with AsyncMlb() as mlb:
    team = await mlb.get_team(136)

Mlb must never return coroutines or change behavior based on configuration. Sync and async APIs remain separate and explicit.

Compatibility requirement

Upgrading from 1.0.x to 1.1.0 must require zero code changes for existing synchronous users.

The following existing behavior must remain stable:

  • Mlb
  • MlbDataAdapter
  • Existing Pydantic models
  • Existing public exceptions
  • strict_http=True default behavior
  • Explicit strict_http=False compatibility mode
  • Endpoint-specific 404 behavior
  • Timeout and transport semantics
  • Decode-error behavior
  • User-Agent behavior
  • Caller-owned transport lifecycle rules
  • Existing synchronous context-manager behavior

Async support is additive.

Async behavior

The async implementation should provide equivalents for the important existing transport guarantees.

AsyncMlb and AsyncMlbDataAdapter should define and test:

  • Async client ownership
  • async with lifecycle behavior
  • Explicit aclose() behavior
  • Caller-injected async client ownership
  • Timeouts
  • Transport errors
  • HTTP errors
  • JSON decode errors
  • Strict HTTP behavior
  • Compatibility mode
  • Endpoint-specific 404 behavior
  • Retry behavior
  • Cancellation behavior
  • User-Agent behavior
  • Multiple concurrent in-flight requests through one client on the same event loop
  • Independence between unrelated concurrent operations

Where possible, sync and async clients should produce the same models and public exceptions for equivalent responses.

Completed async contract

Issue #298 is the source of truth for the v1.1 async public and behavioral contract.

The downstream implementation issues must enforce the relevant parts of #298 rather than treating it as background documentation:

A downstream implementation issue is not complete if its relevant #298 contract obligations are unimplemented or untested, even if the basic feature appears to work.

Architecture

Avoid maintaining two independent copies of endpoint parsing and model-construction logic.

The preferred direction is:

                 Shared models
                 Shared parsing
                 Shared exceptions
                 Shared semantics
                        |
            +-----------+-----------+
            |                       |
           Mlb                   AsyncMlb
            |                       |
    MlbDataAdapter        AsyncMlbDataAdapter
            |                       |
    requests.Session          async HTTP client

Shared code should be extracted incrementally.

Do not perform a large rewrite of the existing synchronous client solely to support async.

Initial async scope

Start with a small vertical slice rather than immediately porting every public endpoint.

The first implementation should prove:

AsyncMlb
    ↓
AsyncMlbDataAdapter
    ↓
real/fake HTTP response
    ↓
existing MlbResult / parsing
    ↓
existing Pydantic model

The initial endpoint set defined in #298 is:

  • get_team
  • get_person
  • get_schedule

Once the architecture is validated, async endpoint coverage can expand systematically.

Full endpoint parity is not required before the architecture itself has been proven.

Packaging

Async dependencies should preferably be optional so existing users do not receive additional HTTP dependencies simply by upgrading.

Desired installation model:

pip install python-mlb-statsapi

for the synchronous client, and something similar to:

pip install "python-mlb-statsapi[async]"

for async support.

The exact async transport library should be selected as part of #300 according to the requirements established in #298 rather than assumed by this parent issue.

Documentation and README cleanup

The current README contains increasingly detailed HTTP, transport, migration, and API information.

Version 1.1.0 should simplify it around the information most users need first:

  • Installation
  • Python support
  • Basic synchronous usage
  • Basic asynchronous usage
  • Common error handling
  • Links to detailed documentation
  • Contribution/project links

More detailed material should live in dedicated documentation where appropriate, including:

  • HTTP transport behavior
  • Retry policy
  • Timeout behavior
  • Session/client ownership
  • Exception reference
  • Compatibility mode
  • Public API contract
  • Cancellation behavior
  • Concurrent request behavior
  • Advanced usage
  • Migration/release-specific information

The goal is not to remove useful documentation, but to make the README easier to approach.

Testing requirements

The existing synchronous test suite must remain green throughout development.

Async support should gain deterministic offline tests covering at minimum:

2xx
400/403 strict behavior
400/403 compatibility behavior
404
429
5xx
timeout
transport failure
invalid JSON
warnings
client ownership
cleanup
retry behavior
cancellation
same-client concurrency
cancellation independence
non-blocking retry/backoff

#302 is responsible for executable transport-contract coverage. #304 is responsible for sync/async parity coverage.

Live MLB API testing should remain separate from deterministic CI tests.

Release validation

Before version 1.1.0 is released:

  • Existing synchronous CI must remain green across supported Python versions.
  • Async tests must pass across the supported Python matrix where async support is available.
  • Normal installation without async extras must work.
  • Installation with async extras must work.
  • Wheel and source distribution must include the async implementation.
  • Built artifacts must successfully import supported public sync/async APIs.
  • Sync behavior must remain backward compatible with 1.0.x.
  • Async lifecycle and transport behavior must pass deterministic validation.
  • Add deterministic async transport contract tests #302 contract tests must pass.
  • Add sync/async behavioral parity tests #304 parity tests must pass for every supported async endpoint.
  • README and async documentation must describe the final implementation accurately.
  • Relevant live MLB API smoke tests must pass.

Non-goals

Version 1.1.0 should not:

  • Replace the synchronous client
  • Make Mlb conditionally async
  • Return coroutines from existing synchronous methods
  • Rewrite the entire library architecture solely for async support
  • Maintain a separate async package/project
  • Change the established 1.0 HTTP contract without a separate justified proposal
  • Promise full async endpoint parity before it has actually been implemented and tested
  • Add hidden request fan-out, background workers, or automatic batching as part of normal endpoint behavior
  • Promise cross-thread or cross-event-loop client use

Definition of done

Version 1.1.0 is ready when the library has a documented, tested, maintainable async client architecture; existing synchronous users can upgrade without code changes; the initial supported async endpoint set is clearly documented; package installation and release validation cover both modes; the #298 contract is enforced by deterministic tests and downstream acceptance criteria; and the README has been streamlined for new users.

Implementation issues

Suggested implementation order

#298 Define contract ✅
  ├── #299 Extract shared parsing
  └── #300 Add async packaging
          ↓
       #301 Async adapter
          ↓
       #302 Transport contract tests
          ↓
       #303 AsyncMlb vertical slice
          ↓
       #304 Sync/async parity tests
          ↓
       #305 Expand endpoint coverage

#306 README/documentation cleanup should begin after the public async shape is proven in #303 and can proceed alongside parity/coverage work.

#307 release preparation and validation is last.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions