Skip to content

fix: futures slug normalization + live CI tests (v1.8.1)#35

Merged
karlwaldman merged 3 commits into
mainfrom
fix/futures-and-live-ci
Jun 21, 2026
Merged

fix: futures slug normalization + live CI tests (v1.8.1)#35
karlwaldman merged 3 commits into
mainfrom
fix/futures-and-live-ci

Conversation

@karlwaldman

Copy link
Copy Markdown
Member

Summary

Hardens the futures path and turns on live CI testing.

Futures endpoints are keyed by slug (ice-brent, ice-wti, ...), not by raw exchange contract code. The previous docstrings advertised "CL.1", which would build /v1/futures/CL.1 and 404. This PR adds contract-code -> slug normalization (callers may pass either form), fixes the misleading examples, and wires up live CI.

Code -> slug handling

New oilpriceapi/resources/_futures_slug.py with normalize_futures_slug(), applied to both the sync (FuturesResource) and async (AsyncFuturesResource) resources:

Friendly code Slug Friendly code Slug
BZ / BRENT ice-brent NG / NATGAS natural-gas
CL / WTI ice-wti TTF ttf-gas
G / QS / GASOIL ice-gasoil JKM / LNG lng-jkm
EUA eua-carbon UKA uk-carbon
  • Canonical slugs (ice-brent, ice-wti, ice-gasoil, natural-gas, ttf-gas, lng-jkm, eua-carbon, uk-carbon, continuous/brent, continuous/wti) pass through unchanged.
  • Tolerant of contract suffixes: CL.1, CL1!, NG-2025-12, BZ_2026_01.
  • Unknown values raise a clear ValueError listing valid slugs/codes.
  • futures.continuous() now correctly targets /v1/futures/continuous/{brent,wti}/historical.
  • Mappings verified against app/controllers/v1/futures_controller.rb + config/routes.rb in the Rails API.

Live CI

  • New live integration test tests/integration/test_live_futures.py (marked live, excluded from the default unit gate) using OILPRICEAPI_TEST_KEY. Hits the real API: futures.latest("ice-brent"), the "BZ" code form (post-normalization), and futures.curve(...). Asserts 200 + sane price. Skips when the key is absent (forks). Calls spaced for the 1 req/sec limit.
  • New workflow .github/workflows/live-tests.yml runs the live suite with OILPRICEAPI_TEST_KEY: ${{ secrets.OILPRICEAPI_TEST_KEY }}, gated so forks/PRs without the secret don't fail.
  • Added unit tests for slug normalization (run in the default gate).

Version

Bumped 1.8.0 -> 1.8.1 (pyproject.toml + oilpriceapi/version.py).

Gate results (local, venv)

  • mypy oilpriceapi/ --ignore-missing-imports -> Success: no issues found in 41 source files
  • ruff check oilpriceapi/ -> All checks passed
  • pytest tests/ --ignore=tests/integration --ignore=tests/contract -m 'not slow' --cov=oilpriceapi -> 272 passed, 9 skipped; coverage 57.57% (>= 50% gate)
  • Live futures test collects + skips cleanly without OILPRICEAPI_TEST_KEY.

🤖 Generated with Claude Code

Futures endpoints are keyed by slug (ice-brent, ice-wti, ...), not raw
exchange contract code. The old docstrings advertised "CL.1" which would
hit /v1/futures/CL.1 and 404. Add contract-code -> slug normalization so
callers can pass either a slug or a friendly code, and fix the misleading
examples across the sync and async futures resources.

- New oilpriceapi/resources/_futures_slug.py: normalize_futures_slug()
  maps BZ->ice-brent, CL->ice-wti, G/QS->ice-gasoil, NG->natural-gas,
  TTF->ttf-gas, JKM->lng-jkm, EUA->eua-carbon, UKA->uk-carbon; passes
  through canonical and continuous/{brent,wti} slugs; tolerates contract
  suffixes (CL.1, CL1!, NG-2025-12). Verified against the Rails API
  controller + routes.
- futures.continuous() now targets /v1/futures/continuous/{brent,wti}/historical.
- Add live integration test (tests/integration/test_live_futures.py, marked
  live, excluded from the unit gate) using OILPRICEAPI_TEST_KEY; skips when
  absent; spaced for the 1 req/sec limit.
- Add unit tests for slug normalization.
- Add live CI workflow (.github/workflows/live-tests.yml) gated on the
  OILPRICEAPI_TEST_KEY secret so forks don't fail.
- Bump version 1.8.0 -> 1.8.1.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jun 21, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@karlwaldman, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 38 minutes and 5 seconds. Learn how PR review limits work.

Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file).

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits.

🚦 How do rate limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan refill rate.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, the refill rate gradually slows as usage increases. The highest same-day bursts are limited more strictly.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 4794e470-e485-408e-ba58-d2ed90f5a04d

📥 Commits

Reviewing files that changed from the base of the PR and between 77f46f9 and 9d80510.

📒 Files selected for processing (9)
  • .github/workflows/live-tests.yml
  • oilpriceapi/async_resources.py
  • oilpriceapi/resources/_futures_slug.py
  • oilpriceapi/resources/futures.py
  • oilpriceapi/streaming/models.py
  • oilpriceapi/version.py
  • pyproject.toml
  • tests/integration/test_live_futures.py
  • tests/unit/test_futures_slug.py
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/futures-and-live-ci

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 and usage tips.

karlwaldman and others added 2 commits June 21, 2026 13:02
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…nd CI envs

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@karlwaldman karlwaldman merged commit ca7a267 into main Jun 21, 2026
6 checks passed
@karlwaldman karlwaldman deleted the fix/futures-and-live-ci branch June 21, 2026 17:09
karlwaldman added a commit that referenced this pull request Jul 3, 2026
* fix: futures slug normalization + live CI tests (v1.8.1)

Futures endpoints are keyed by slug (ice-brent, ice-wti, ...), not raw
exchange contract code. The old docstrings advertised "CL.1" which would
hit /v1/futures/CL.1 and 404. Add contract-code -> slug normalization so
callers can pass either a slug or a friendly code, and fix the misleading
examples across the sync and async futures resources.

- New oilpriceapi/resources/_futures_slug.py: normalize_futures_slug()
  maps BZ->ice-brent, CL->ice-wti, G/QS->ice-gasoil, NG->natural-gas,
  TTF->ttf-gas, JKM->lng-jkm, EUA->eua-carbon, UKA->uk-carbon; passes
  through canonical and continuous/{brent,wti} slugs; tolerates contract
  suffixes (CL.1, CL1!, NG-2025-12). Verified against the Rails API
  controller + routes.
- futures.continuous() now targets /v1/futures/continuous/{brent,wti}/historical.
- Add live integration test (tests/integration/test_live_futures.py, marked
  live, excluded from the unit gate) using OILPRICEAPI_TEST_KEY; skips when
  absent; spaced for the 1 req/sec limit.
- Add unit tests for slug normalization.
- Add live CI workflow (.github/workflows/live-tests.yml) gated on the
  OILPRICEAPI_TEST_KEY secret so forks don't fail.
- Bump version 1.8.0 -> 1.8.1.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix: remove unused type-ignore (CI mypy under --ignore-missing-imports)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix: use unused-ignore so dateutil import passes mypy in both local and CI envs

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (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