Thanks for your interest in contributing! This repo is a Python client library for the California Energy Commission's MIDAS API. It exposes a two-layer raw/coerced data model with Pydantic v2 entities, pendulum time types, and an httpx-based client. Unlike some sibling libraries it does not bundle an OpenAPI spec — endpoints are hand-written httpx calls, and the spec-level source of truth lives upstream in grid-coordination/midas-api-specs.
Use Discussions for:
- Questions about how to use the library — clients, coercion, raw/coerced layering, time and timezone handling, signal-type helpers
- API and design judgment calls — "should python-midas model X?" / "is this the right shape for Y?"
- MIDAS API behavior gaps that affect python-midas — when the live API exposes something that doesn't fit the current entity shape and you want to scope what the library should do about it
- Coordination with the upstream
midas-api-specsspec repo (whosedoc/notes — RIN structure, datetime/timezone semantics, the v2.0 migration map — this library follows) - Sharing what you're building on top of python-midas
Discussions are open-ended — a good place to think out loud or scope something before it becomes a concrete change. Aligned outcomes from a Discussion often turn into one or more Issues.
Use Issues for actionable changes:
- Bugs in client construction, request building, response parsing, or coercion against the live MIDAS API
- Coercion or schema gaps surfaced by real API responses (a field the library doesn't handle, or a value that breaks the coerced shape)
- New endpoints or request parameters when MIDAS exposes them
- Test failures or unexpected behavior with concrete repro steps
- Documentation errors, unclear explanations, or stale prose in
README.mdor docstrings - Discussion outcomes that have alignment and a clear scope
If you're not sure whether something is an Issue or a Discussion, start with a Discussion — we can convert it later.
Pull requests are welcome.
- For small fixes (typos, broken links, single-test corrections, single-coercion bug fixes), open a PR directly.
- For substantive changes (new endpoints, new entity types, new coerced fields, time-handling changes), open a Discussion or Issue first so we can align on scope before you invest the effort.
- All changes pass
pytest tests/ -m "not integration"andruff check src/ tests//ruff format --check src/ tests/cleanly. - Match the existing tone and structure. The library composes HTTP client → raw response accessors → coerced Pydantic entities as roughly orthogonal layers; patches that fit cleanly into one layer without leaking concerns across them are the easiest to land.
- One commit per logical change is fine; we don't require squash or any particular branch naming.
pip install -e ".[dev]" # install with dev dependencies
pytest tests/ -v -m "not integration" # run the offline unit suite
ruff check src/ tests/ # lint
ruff format --check src/ tests/ # format check (drop --check to apply)This project uses pre-commit to run Ruff lint and format checks automatically on every commit:
pip install pre-commit
pre-commit installThe hooks are configured in .pre-commit-config.yaml (Ruff lint with --fix, then Ruff format). The same Ruff checks are enforced in CI via .github/workflows/ci.yml.
Every coerced datetime is a zone-aware pendulum.DateTime, and the library preserves the honest wire zone rather than normalizing to one display zone: Z-suffixed fields (SystemTime_UTC, SignupCloseDate) stay UTC, as does LastUpdated (a basic-offset +0000 UTC instant in v2.0); ValueData interval boundaries are exposed as a period (start, end) tuple composed from the v2.0 UTC wire and kept in UTC. Convert to a zone of your choice yourself with .in_tz(...). The parsing rules live in src/midas/time.py; the wire-level semantics they encode are documented in midas-api-specs/doc/datetime-and-timezone.md. When changing time handling, keep the "know the zone, convert it yourself" contract intact.
Tests marked integration hit the live MIDAS API and require MIDAS_USERNAME / MIDAS_PASSWORD; they are excluded from CI and from the default offline run above. They target the v2.0 API, which is live only after the CEC cutover on 2026-06-22 — running them before then (or without credentials) will fail or skip. Run them on release day to smoke-test against production:
MIDAS_USERNAME=... MIDAS_PASSWORD=... pytest tests/ -v -m integrationpython-midas is published to PyPI by a GitHub Actions workflow (.github/workflows/publish.yml) using PyPI's Trusted Publisher flow — no API tokens or personal credentials are involved. Pushing a v* tag triggers the workflow, which runs the offline test suite, builds the sdist + wheel, and uploads via OpenID Connect.
To cut a release:
- Bump
versioninpyproject.toml. - Move the
## [Unreleased]entries inCHANGELOG.mdunder a## [<version>] — <date>heading (Added / Changed / Fixed / Removed). Update the reference links at the bottom. - Commit on
main(e.g.Bump version to X.Y.Z). - Tag and push:
git tag vX.Y.Z && git push origin vX.Y.Z. - The
Publish to PyPIworkflow runs the test job, then the publish job in thepypienvironment. Watch it on the Actions tab.
The Trusted Publisher binding is grid-coordination / python-midas / publish.yml / pypi, configured at pypi.org → Manage → Publishing. If a release fails with an OIDC error, verify the binding hasn't drifted (workflow filename, environment name, repo path).
Versioning follows SemVer. The 1.0.0 release tracks MIDAS v2.0 and is a v2-only, breaking release (see CHANGELOG.md).
Be respectful and constructive. We're a small project and appreciate everyone who takes the time to file an issue or send a PR.
This library is provided on an "as-is" basis. Updates and maintenance, including responses to issues filed on GitHub, will take place on an "as time and resources permit" basis. Library output (raw API responses, coerced entities) is best-effort against the live MIDAS API and the upstream midas-api-specs documentation. This library is not authoritative for billing, dispatch, or grid operations — independent verification against the MIDAS API's actual responses is recommended for any consumer relying on these results for operational correctness.