Merged in #115 (fcc4edf). Verified by execution against main on 2026-09-13 — confirmed live.
What changed
oilpriceapi/retry.py:23-42 (validated_max_retries) now rejects max_retries=0, negatives, and non-ints with ConfigurationError, raised from OilPriceAPI.__init__ / AsyncOilPriceAPI.__init__.
Repro
from oilpriceapi import OilPriceAPI
FIXTURE_KEY = "fixture-not-a-real-credential"
OilPriceAPI(api_key=FIXTURE_KEY, max_retries=0) # ConfigurationError
OilPriceAPI(api_key=FIXTURE_KEY, max_retries=3.0) # ConfigurationError
Measured:
{'max_retries': 0} -> ConfigurationError: max_retries counts total attempts and must be at least 1, got 0.
{'max_retries': -1} -> ConfigurationError
{'max_retries': True} -> ConfigurationError: ... got bool
{'max_retries': 3.0} -> ConfigurationError: ... got float
All four constructed successfully before this merge.
Why it matters
The validation itself is correct and worth keeping — silently turning an explicit 0 into 3 was the bug. But this is a breaking change to a public constructor argument, and:
oilpriceapi/version.py:8 is still __version__ = "1.13.0" — no bump.
max_retries=0 is the natural spelling of "do not retry" and is exactly what an env-driven config produces: int(os.getenv("OPA_MAX_RETRIES", "0")).
max_retries=3.0 is what a JSON/YAML config round-trip produces for an integer in many stacks.
- The failure is at client construction, so it takes the whole process down at startup rather than degrading one call.
A caller upgrading within 1.13.x gets an unannounced crash at import-time-adjacent code.
Suggested fix
Pick one:
- Deprecate rather than break. Map
0 -> 1 with a DeprecationWarning naming the new meaning ("max_retries counts total attempts; 0 is being treated as 1"), keep raising for negatives and non-numerics, and accept an integral float (3.0) by coercing. Remove the shim in the next major.
- Keep the hard error and bump the version to 2.0.0 (or at minimum 1.14.0 with a prominent CHANGELOG "breaking" entry and a migration line), so the break is visible before it is hit.
Either way this needs a CHANGELOG entry — there is currently nothing telling an upgrading caller that a previously-valid argument is now fatal.
Merged in #115 (
fcc4edf). Verified by execution againstmainon 2026-09-13 — confirmed live.What changed
oilpriceapi/retry.py:23-42(validated_max_retries) now rejectsmax_retries=0, negatives, and non-ints withConfigurationError, raised fromOilPriceAPI.__init__/AsyncOilPriceAPI.__init__.Repro
Measured:
All four constructed successfully before this merge.
Why it matters
The validation itself is correct and worth keeping — silently turning an explicit
0into3was the bug. But this is a breaking change to a public constructor argument, and:oilpriceapi/version.py:8is still__version__ = "1.13.0"— no bump.max_retries=0is the natural spelling of "do not retry" and is exactly what an env-driven config produces:int(os.getenv("OPA_MAX_RETRIES", "0")).max_retries=3.0is what a JSON/YAML config round-trip produces for an integer in many stacks.A caller upgrading within 1.13.x gets an unannounced crash at import-time-adjacent code.
Suggested fix
Pick one:
0 -> 1with aDeprecationWarningnaming the new meaning ("max_retries counts total attempts; 0 is being treated as 1"), keep raising for negatives and non-numerics, and accept an integral float (3.0) by coercing. Remove the shim in the next major.Either way this needs a CHANGELOG entry — there is currently nothing telling an upgrading caller that a previously-valid argument is now fatal.