Skip to content

feat: add configurable request timeout to the Creators API - #151

Open
YPCrumble wants to merge 1 commit into
sergioteula:masterfrom
YPCrumble:feature/configurable-request-timeout
Open

feat: add configurable request timeout to the Creators API#151
YPCrumble wants to merge 1 commit into
sergioteula:masterfrom
YPCrumble:feature/configurable-request-timeout

Conversation

@YPCrumble

Copy link
Copy Markdown
Contributor

Summary

The sync AmazonCreatorsApi calls self._api.<method>(...) without _request_timeout at all four call sites (get_items, search_items, get_variations, get_browse_nodes). The bundled SDK's rest.py then takes its timeout = None branch and hands that explicit None to urllib3, so no timeout is applied at all and a stalled endpoint hangs the caller indefinitely.

The async layer already gets this right: aio/client.py defines DEFAULT_TIMEOUT = 30.0 and passes it to httpx. Same library, opposite safety default — and neither one is configurable today.

This adds a timeout parameter, in seconds, to both classes, and reuses the existing 30 second default for the sync layer rather than introducing a new number.

Behavior change

Sync requests now time out after 30 seconds instead of waiting forever. That is a real change, and it is the point of the PR — but it is a change, so timeout=None is supported and restores the old behavior exactly, for anyone who wants it.

I went with a real default rather than an opt-in None because "no timeout" is not a defensible default for a network client, and because 30 seconds is not a new opinion — it is the value this library already ships and has been using in the async layer since 6.1.0. If you would rather keep this strictly non-breaking, I am happy to flip the sync default to None (opt-in only, zero behavior change); it is a one-line change plus a changelog note. Your call, since it is your semver contract.

What changed

  • AmazonCreatorsApi.__init__ takes timeout: float | None = DEFAULT_TIMEOUT and forwards _request_timeout=self.timeout at all four SDK call sites.
  • AsyncAmazonCreatorsApi.__init__ takes the same parameter and passes it to both AsyncHttpClient construction sites (the context-manager client and the per-request one). Async callers were previously stuck with 30 seconds and no way to change it.
  • DEFAULT_TIMEOUT moves from aio/client.py to core/constants.py, next to DEFAULT_THROTTLING, so both layers can share one value. It has to live there rather than in aio/client.py, because that module imports httpx at module scope and httpx is an optional extra — importing it from the sync path would make every sync-only install require httpx. It is still importable from aio.client as before, so nothing downstream breaks.
  • AsyncHttpClient's timeout annotation widens to float | None, since None is how both httpx and the SDK spell "wait indefinitely".
  • Tests for both layers covering the default, an explicit value, and None.

Seconds and float throughout, matching urllib3, httpx, Amazon's _request_timeout, and the existing throttling parameter next to it. Ints work fine (timeout=10); the SDK normalizes them.

No files under creatorsapi_python_sdk/ were touched. Amazon's SDK already accepts _request_timeout on every DefaultApi method — the wrapper simply never set it. This is plumbing, not a design change.

The async half is separable. If you would rather keep this to the sync fix, I will drop it and leave AsyncAmazonCreatorsApi as is.

Checks

ruff format, ruff check, mypy, and the full test suite pass locally on Python 3.9 through 3.14. Verified in a clean environment without httpx installed that the sync API still imports and picks up the default. CHANGELOG.md, pyproject.toml, and docs/conf.py are bumped to 6.4.0 and pass scripts/check_version.py.

Unrelated to #86 / #76, despite the similar title — that issue was a script not exiting on Windows in the legacy amazon_paapi module, not a network timeout.

The sync AmazonCreatorsApi called the bundled SDK without _request_timeout,
so urllib3 received an explicit None and requests could hang forever. The
async layer already applied a 30 second timeout, but did not let callers
change it.

Both classes now accept a timeout parameter in seconds, sharing the
existing DEFAULT_TIMEOUT of 30 seconds. That constant moves to
core.constants so the sync layer can use it without pulling in the
optional httpx dependency, and is re-exported from aio.client for
compatibility. Passing None restores the previous behavior of waiting
indefinitely.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant