Skip to content

fix: repoint or retire 8 methods that called unrouted paths (#153) [1.17.0] - #154

Merged
karlwaldman merged 2 commits into
mainfrom
fix/153-dead-routes
Oct 3, 2026
Merged

karlwaldman merged 2 commits into
mainfrom
fix/153-dead-routes

Conversation

@karlwaldman

Copy link
Copy Markdown
Member

Closes #153.

Problem

Eight methods (sync and async) called /v1 paths the API never routed, so every call returned 404. The existing mocked tests did not assert request paths, which is why CI stayed green.

Decisions

Method Was Now Live (2026-10-03, test key)
storage.history /v1/storage/{code}/history /v1/storage/history/{code} with period 200 (4 records, cushing 30d)
bunker_fuels.spreads /v1/bunker-fuels/spreads /v1/bunker-fuels/spreads/ports?from&to[&grade] 200
bunker_fuels.historical /v1/bunker-fuels/historical?port= /v1/bunker-fuels/historical/{port} (+ client-side fuel_type filter) 200
forecasts.accuracy /v1/forecasts/accuracy /v1/forecasts/monthly/accuracy 404 not_available → DataNotFoundError (route exists; forecasts unpublished)
forecasts.archive /v1/forecasts/archive /v1/forecasts/monthly/archive same as above
drilling.trends /v1/drilling-intelligence/trends deprecated: raises before any request → rig_counts.trends() no request
drilling.basin /v1/drilling-intelligence/basin/{name} deprecated → ei.drilling_productivity.by_basin() no request
futures.spreads(c1, c2) /v1/futures/spreads deprecated → new futures.calendar_spreads(contract) on /v1/futures/{slug}/spreads 200 (17 pairs, brent)
  • Deprecated methods emit DeprecationWarning and raise ValidationError(code="ENDPOINT_NOT_AVAILABLE", status_code=None). They are slated for removal in 2.0.
  • Bad storage codes, periods, ports and fuel types are rejected locally before any request.
  • Signature changes. These methods never worked, so no working caller breaks:
    • storage.history drops start_date/end_date, which the route never accepted, and gains period.
    • bunker_fuels.spreads now requires from_port and to_port.
    • bunker_fuels.historical returns the API object instead of a list.

Contract test

  • tests/unit/test_api_path_contract.py checks every /v1 literal in oilpriceapi/ against a vendored route-table snapshot. The snapshot is tests/fixtures/api_paths.json.fixture: 520 routes from rails routes at api b64093719 (oilpriceapi-api origin/main, 2026-10-03), plus the 105 swagger paths.
  • It uses rails routes, not swagger plus openapi_route_policy.yml. The policy excludes paths by prefix (/v1/futures, /v1/storage, /v1/bunker-fuels, /v1/forecasts), which would admit every one of these dead paths.
  • Refresh with scripts/refresh_api_paths.py.
  • Proven red twice. Run against the origin/main SDK source, it reports exactly these 8 paths. Reintroducing /v1/storage/{code}/history fails it. With the fix, it is green.

Also

  • The EXAMPLES.md price-alert loop now polls hourly instead of every 30 minutes, halving its daily requests. The comment is phrased to pass validate_storefront_claims.py, which forbids fixed rate numbers in docs.
  • Version 1.16.1, with a CHANGELOG entry.

Verification (local, Python 3.14)

  • ruff check oilpriceapi/: clean.
  • mypy oilpriceapi/: clean.
  • Unit suite: 2019 passed, 14 skipped. That is 36 more than main's 1983 (new tests in test_dead_route_repoints.py and test_api_path_contract.py, sync and async).
  • validate_storefront_claims.py: passes on source and on the built sdist.
  • Live smoke against production with the test key: results are in the table above.

Not merged, tagged or published.

🤖 Generated with Claude Code

Every call to these methods returned 404 because the API never routed the
path. The mocked tests never asserted paths, so CI stayed green.

- storage.history -> /v1/storage/history/{code} (period, not dates)
- bunker_fuels.spreads -> /v1/bunker-fuels/spreads/ports (from/to required)
- bunker_fuels.historical -> /v1/bunker-fuels/historical/{port}
- forecasts.accuracy/archive -> /v1/forecasts/monthly/{accuracy,archive}
- drilling.trends, drilling.basin, futures.spreads: no route; warn and
  raise ValidationError(ENDPOINT_NOT_AVAILABLE) before any request,
  naming the replacement. Adds futures.calendar_spreads().

Adds a contract test against a vendored route-table snapshot that fails on
any unrouted /v1 path; it reports exactly these 8 against origin/main.
Hourly polling in the EXAMPLES.md price alert. Version 1.16.1.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Oct 3, 2026 •

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration
  • Configuration used: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: f2319e24-85ea-4c42-bc10-8758477e2fdf
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

…atures)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@karlwaldman karlwaldman changed the title fix: repoint or retire 8 methods that called unrouted paths (#153) fix: repoint or retire 8 methods that called unrouted paths (#153) [1.17.0] Oct 3, 2026
@karlwaldman
karlwaldman merged commit ca9df32 into main Oct 3, 2026
7 checks passed
@karlwaldman
karlwaldman deleted the fix/153-dead-routes branch October 3, 2026 21:40
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.

[P2][bug] 8 SDK methods call routes that do not exist (live 404), and the polling example exceeds the free tier 1.9x

1 participant