Prep 0.1.0 release: docs, drift pins, and CI hygiene#30
Conversation
The placeholder entry described features at a high level and predated the final API surface. Replace it with bullets that match what 0.1.0 actually ships: the exported helpers, exception hierarchy, retry behavior, extension API, and supported Python versions. Bumps the release date to 2026-04-28.
Replaces the prior README with a from-scratch rewrite tailored to an autogenerated Python SDK against a versioned REST API. Structured per the conventions of openai-python, cloudflare-python, kubernetes-client, qiskit, and cirq: tagline, badges, codegen disclosure, alternative high-level SDKs, install, quickstart (Bell circuit), auth, async, errors, retries, pagination, polling, sessions, advanced (hooks / custom transport / error mapping / native gates), SDK-vs-API version table, SemVer carve-outs, requirements, contributing, support, license.
CODEOWNERS now points at @ionq/developer-tools, matching the team's current name. The README's CUDA-Q bullet now links directly to the IonQServerHelper backend in NVIDIA/cuda-quantum so users can see how the integration is wired.
Replaces the brief stub with a comprehensive contributor guide tailored to a generated Python SDK. Sections cover code of conduct, where to ask questions, bug reporting, scope guidance, the generated-vs-hand-written code structure (with the table of paths, the # @generated marker, and the PR-time staleness check), uv-based development setup, local check commands, integration tests, the exact regeneration command, the PR workflow, SemVer carve-outs, release process, security disclosure, and the CLA contact.
Add an affected-area dropdown that mirrors CONTRIBUTING.md's generated/hand-written taxonomy, split bug description into what-happened and expected-behavior, require the reproduction field, add a search-confirmation checkbox to both templates, and route security reports through SECURITY.md instead of public issues.
The generated/hand-written file boundary was restated in five places (README, CONTRIBUTING table, PR template, bug-report dropdown, and pyproject exclusions) with subtle drift, including __init__.py listed inconsistently. CONTRIBUTING.md is now the single source of truth; the other surfaces link to it. The bug-area classification keys off the @generated marker rather than enumerated paths so new generated files don't require doc updates. Other duplications removed: - README "Requirements" section (duplicated pyproject.toml dep pins) - One-row SDK<->API version table (kept the prose that was useful) - Hard-coded "Python 3.12, 3.13, or 3.14" lists (canonical: pyproject + ci.yml) - Standalone "Security" section in CONTRIBUTING (duplicated the Getting help bullet) - @mjk personal handle for the CLA (now opensource@ionq.co) Adds an [Unreleased] section to CHANGELOG so the contribution instruction to "add to the next release section" works.
Replace hard-wrapped prose (~80 cols) with one-paragraph-per-line so future edits don't reflow whole paragraphs. Word counts unchanged; rendered output is identical.
- Rewrite README relative links as absolute GitHub URLs so they resolve on PyPI (the renderer does not follow relative paths). - Add a Safe Harbor clause to SECURITY.md committing to no legal action against good-faith researchers. - Add `[Unreleased]` / `[0.1.0]` link reference footers to CHANGELOG.md so the version tokens resolve. - Replace the abbreviated CODE_OF_CONDUCT.md with the verbatim Contributor Covenant 2.1 and route reports to <conduct@ionq.co>; sync the same address in CONTRIBUTING.md. - Make the "What did you expect?" field optional in the bug-report template - tracebacks usually make it redundant.
- Bump pre-commit ruff to v0.15.12 so it matches the dev dep. - Drop "Quantum" from the README one-liner to align with pyproject and the auto-generated package docstring. - Match LoggingHook arrow style between README and extensions.py. - Reword CONTRIBUTING.md to describe the ty config accurately (rule override for api/ + models/, not a path exclusion). - Fill in 1.5x growth and default total wait in the polling module docstring. - Extract _DEFAULT_BASE_URL so the integration test can import the production URL once instead of redeclaring it. - Decouple unit-test placeholder URLs from the production base. - Add tests/test_docs_consistency.py to pin README copy to the retry, timeout, and polling constants so future drift fails CI.
Extends the docs-consistency gate to cover the retry backoff trio, default base URL, auth prefix, exception classes, Python floor across pyproject/CI/.python-version/ruff/ty, generated-paths exclusions, the SessionManager example backend, and the package description across pyproject/README/__init__.py/template. Adds a setup-uv composite action so the pinned SHA and Python default live in one file; routes all five setup-using workflows through it. Names polling's growth factor, hoists the test BASE_URL into conftest, switches the SPDX post-hook to stamp \$(date +%Y), and unifies the package description on "A client library for accessing IonQ Cloud Platform API".
The template's only output is ionq_core/__init__.py, which CI regenerates and then asserts against the canonical text via test_init_module_docstring. A separate template-content test was redundant - the output check catches the same drift. Also trim a parenthetical from the bug-reporting copy.
Add eight new test classes to test_docs_consistency.py covering generator tool versions, ClientExtension docstring defaults, polling docstring constants, polling.__all__ in README, pyproject classifiers vs CI matrix, _DEFAULT_BASE_URL vs openapi.json servers[0].url, SPDX year consistency across hand-written and generated files, and resolution of cross-doc anchor links. Pin spec-drift.yml's curl URL to _DEFAULT_BASE_URL so a future v0.4 -> v0.5 bump can't silently keep curl'ing the stale endpoint. Derive the API path in tests/conftest.py and tests/test_session.py from _DEFAULT_BASE_URL via urlparse instead of hardcoding /v0.4.
Flatten tests/test_docs_consistency.py from 13 classes to module-level parametrized tests; same coverage in 217 lines instead of 291. Drop the markdown-anchor resolver test (GitHub already renders broken anchors visibly) and the backoff_factor pin (numbers live in _transport.py and won't drift independently of the README). Merge README's "SDK version vs API spec version" into "Versioning" - the SemVer carve-outs already imply API/SDK independence. Drop the duplicated higher-level-interface paragraph from CONTRIBUTING (already linked in "Getting help"). Tighten the post-generation hook paragraph to a one-liner; the config file is right above. Collapse the three-line max_retries fallback ladder in IonQClient into a single next() expression.
Trim README, CONTRIBUTING, and SECURITY to single-source content; drop the README pin tests for the removed copy. Module docstrings (rendered into the published API reference) now own behavioral detail; the README is the entry point only. - README: drop Authentication detail, Async usage, exception ASCII tree, retry/timeout values, full pagination/polling/sessions snippets, the Advanced section, and versioning carve-outs - all duplicated in module docstrings or drift-prone constants. - CONTRIBUTING: drop the hand-maintained generated-file list (now .gitattributes is the single source), the Versioning section (duplicate of README), and the Releasing section (maintainer-only). - SECURITY: drop the Supported Versions table - it would lie the moment 0.2 ships; the prose policy above already covers it. - test_docs_consistency: drop test_readme_mentions_runtime_constant, test_readme_lists_exception_class, test_readme_lists_polling_name, and the README half of the session-backend pin. Internal-consistency checks (Python floor, classifiers, ruff/coverage/.gitattributes paths, generated-tool versions, base URL, SPDX year, ClientExtension and polling docstring pins) are unchanged.
openapi-python-client checks `cmd.split(" ")[0]` against PATH before
running each post_hook. The `YEAR=$(date +%Y) perl ...` prefix made the
"command" `YEAR=$(date`, which fails the `shutil.which` check; the hook
was skipped, regeneration dropped SPDX headers, and CI's staleness gate
fired. Move the year computation into Perl's BEGIN block so the leading
token is `perl` and the env-prefix trick is no longer needed.
(localtime)[5]+1900 is the canonical short form; with -p the wrapper's once-per-run benefit is moot (one assignment per file, microseconds).
SummaryThe runtime changes are narrow and well covered: the extracted default URL/backoff constants are exercised by the new docs-consistency tests, and the CI action consolidation appears to preserve the old setup behavior. I would request changes before merging because the contributor-facing template links now point at removed anchors, and the new reusable local action should be included in the workflow-audit trigger surface. Findings🟡 Should fix
Test coverageGood coverage for the code/config drift pins. I ran Final verdictrequest changes — the code and tests look sound, but the broken contributor links and missing audit trigger coverage for |
guenp
left a comment
There was a problem hiding this comment.
Codex found some broken links, and a missing reference to the new .github/actions folder, otherwise looks great. loving the 100% UT coverage!
|
great findings thank you!! and 100% coverage for hand-written code is so satisfying haha |
- Switch SPDX post-hook from localtime to gmtime so the stamped year is deterministic across CI runner timezones. - Drop the leading underscore on _DEFAULT_BASE_URL and _DEFAULT_TIMEOUT in ionq_client.py; both are load-bearing for the drift-pin tests (and tests/conftest.py), so the private-by-convention naming was misleading. Not added to __all__ - kept off the wildcard surface. - Retarget dead CONTRIBUTING.md#reporting-bugs and #code-structure links in bug_report.yml and pull_request_template.md to the existing #proposing-changes heading; drop the redundant reporting-guide link since the template fields already prompt for what to include. - Add .github/actions/** to zizmor.yml path filters so the new setup-uv composite action gets the same audit coverage as workflow files.
Tighten test_session_example_backend_consistent so a non-qpu example backend (e.g. "simulator") in session.py would still be caught; pass enable-cache to the composite setup-uv action as a YAML boolean instead of a quoted string.
Summary
Polish for the
0.1.0cut. Three threads of work:Docs and policy. Rewrite
README.mdto point at the published pdoc reference instead of duplicating it; rewriteCONTRIBUTING.mdaround the generated-vs-hand-written boundary; expandSECURITY.mdwith private vulnerability reporting, response SLAs, and safe-harbor scope; switchCODE_OF_CONDUCT.mdto the full Contributor Covenant 2.1; strengthen issue templates (area dropdown, pre-submit checks, security link); rewrite the0.1.0CHANGELOG.mdentry to match the actual shipped surface and date it2026-04-28.Drift pins. New
tests/test_docs_consistency.pypins doc and config against runtime constants (retry status codes, polling backoff, default base URL, default timeout) and against each other (pyproject floor vs. CI matrix vs. ruff/ty/coverage settings,openapi-python-client/oas-patchversions inCONTRIBUTING.mdvs.generated.yml,.gitattributesvs. ruff excludes, single SPDX year across the package). RefactorIonQClientto expose_DEFAULT_BASE_URL, decouple existing tests from the hard-coded/v0.4path, and renamedeveloper-toolsinCODEOWNERS.CI and codegen. Extract a composite
.github/actions/setup-uvaction and switch all workflows to it instead of repeating theastral-sh/setup-uvpin. Compute the SPDX copyright year dynamically in theopenapi-python-clientpost-hook so future regenerations don't get stuck on2026.Test plan
pip-audit, generated-code staleness, new doc-consistency tests).README.md,CONTRIBUTING.md,SECURITY.md, andCHANGELOG.mdlooks right on GitHub.pyproject.tomlversion andCHANGELOG.mddate match what we plan to tag.setup-uvcomposite action works in each workflow that consumes it.🤖 Generated with Claude Code