Skip to content

Refactor: reduce sync/async client duplication (~380 lines each) #20

@justin-layerv

Description

@justin-layerv

Context

Flagged in PR #8 review (claude[bot] 2026-04-11):

client.py and async_client.py carry ~380 lines of duplicated business logic each (validation, body construction, docstrings). The module-level comment ("keep both in sync") is honest but brittle. Consider whether a shared mixin or a thin async wrapper pattern could reduce the surface area for drift in a follow-up — not a blocker for this PR since the sync/async mirror tests provide a safety net.

Options

  1. Shared mixin — extract validation, body construction, and docstrings into a base class. Both QURLClient and AsyncQURLClient inherit it and only implement the HTTP plumbing (_raw_request).
  2. Thin async wrapper — keep the sync client as the primary implementation, wrap it with asyncio.to_thread or a similar pattern. Downside: loses native async httpx benefits.
  3. Code generation — generate one client from the other via a build-time script. Keeps native async but adds a build step.

Status quo safety net

The sync/async mirror tests in test_client.py catch drift: every new method/edge case gets both a sync and async test. This is sufficient for now but doesn't scale well as the API surface grows.

Not a blocker for PR #8

Reviewer explicitly labeled this "not a blocker… consider in a follow-up." The mirror tests provide adequate safety for the current scope.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions