Skip to content

Commit 829f234

Browse files
authored
Sync OpenAPI spec with upstream (April 15, 2026) (#7)
* Sync OpenAPI spec with upstream (April 15, 2026) Fetch latest spec from api-staging.ionq.co and regenerate the client. Adds new GET /jobs/{UUID}/circuits/{lang} endpoint for retrieving compiled circuit files in native or qasm3 format. Closes #6 * Add tests for GET /jobs/{UUID}/circuits/{lang} endpoint * Add code coverage enforcement at 90% for hand-written code Adds pytest-cov with a 90% fail-under threshold, measuring only hand-written ionq_core modules (excludes generated api/, models/, client.py, errors.py, types.py). Current coverage: 93%. * Achieve 100% test coverage on hand-written code Add tests for all previously uncovered paths: transport close/aclose, pagination None responses, async polling (timeout, sleep, None job), session error paths, retry-after date parsing, and version fallback. Bump coverage threshold from 90% to 100%. * Simplify coverage tests: drop version reload, unit-test retry-after Replace importlib.reload-based version fallback test with a coverage exclusion for PackageNotFoundError (defensive pattern, same as TYPE_CHECKING). Simplify retry-after date test to call _parse_retry_after directly with a far-future date, eliminating all monkeypatching. * Fix lint: move _real_sleep after imports, reformat test file * Harden coverage config: branch coverage, skip non-primary versions Enable branch coverage (already at 100% with 112 branches). Add show_missing and skip_covered for cleaner reports. Add standard exclude_also patterns (@overload, NotImplementedError, __main__). Only run coverage on Python 3.12; other versions run tests without coverage instrumentation overhead. * Fix docs, export UNSET/Unset, flesh out changelog - Fix CONTRIBUTING.md: add missing --custom-template-path flag - Add CI badge and API docs link to README - Fix Documentation URL in pyproject.toml to point to GitHub Pages - Export UNSET and Unset from __init__.py (needed by all model consumers) - Flesh out CHANGELOG.md with all 0.1.0 features * Add CODEOWNERS, issue templates, and GitHub Release job - CODEOWNERS: @ionq/sdk-team owns all files - Issue templates: bug report and feature request YAML forms - config.yml: directs account/billing questions to IonQ support - Release workflow: create GitHub Release with auto-generated notes after successful PyPI publish * Add pip-audit dependency vulnerability scanning to CI * Fix pip-audit: use uvx instead of GH action (uv venvs lack pip) * Address code review: fix template ordering, trim redundancies - Fix __all__ ordering in Jinja template to match generator output - Remove redundant CODEOWNERS lines (wildcard already covers all) - Add get_compiled_file to README endpoint table - Remove unnecessary uv sync from audit job - Remove unused raise NotImplementedError coverage exclusion
1 parent 7e09448 commit 829f234

23 files changed

Lines changed: 629 additions & 11 deletions

.github/CODEOWNERS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Default owners for everything in the repo.
2+
* @ionq/sdk-team
3+
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
name: Bug Report
2+
description: Report a bug in ionq-core
3+
labels: [bug]
4+
5+
body:
6+
- type: textarea
7+
id: description
8+
attributes:
9+
label: Description
10+
description: What happened, and what did you expect to happen?
11+
validations:
12+
required: true
13+
14+
- type: textarea
15+
id: reproduction
16+
attributes:
17+
label: Reproduction
18+
description: Minimal code or steps to reproduce the bug.
19+
render: Python
20+
21+
- type: textarea
22+
id: version
23+
attributes:
24+
label: Version Information
25+
description: |
26+
Paste the output of:
27+
```bash
28+
python -c "import ionq_core; print(ionq_core.__version__); import platform; print(platform.python_version()); print(platform.platform())"
29+
```
30+
render: Text
31+
validations:
32+
required: true

.github/ISSUE_TEMPLATE/config.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
blank_issues_enabled: false
2+
contact_links:
3+
- name: IonQ Support
4+
url: https://ionq.com/contact
5+
about: For account, billing, or platform questions, contact IonQ support directly.
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
name: Feature Request
2+
description: Suggest a feature for ionq-core
3+
labels: [enhancement]
4+
5+
body:
6+
- type: textarea
7+
id: description
8+
attributes:
9+
label: Description
10+
description: What problem would this solve, and how would you like it to work?
11+
validations:
12+
required: true

.github/workflows/ci.yml

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,4 +48,17 @@ jobs:
4848
python-version: ${{ matrix.python-version }}
4949
enable-cache: ${{ github.event_name == 'push' }}
5050
- run: uv sync
51-
- run: uv run pytest
51+
- run: uv run pytest ${{ matrix.python-version != '3.12' && '--no-cov' || '' }}
52+
53+
audit:
54+
runs-on: ubuntu-latest
55+
timeout-minutes: 10
56+
steps:
57+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
58+
with:
59+
persist-credentials: false
60+
- uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
61+
with:
62+
python-version: "3.12"
63+
enable-cache: ${{ github.event_name == 'push' }}
64+
- run: uvx pip-audit --require-hashes --strict -r <(uv pip compile pyproject.toml --generate-hashes)

.github/workflows/release.yml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,3 +67,18 @@ jobs:
6767
name: dist
6868
path: dist/
6969
- uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # v1.14.0
70+
71+
github-release:
72+
needs: publish
73+
runs-on: ubuntu-latest
74+
timeout-minutes: 5
75+
permissions:
76+
contents: write
77+
steps:
78+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
79+
with:
80+
persist-credentials: false
81+
- name: Create GitHub Release
82+
env:
83+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
84+
run: gh release create "$GITHUB_REF_NAME" --generate-notes

CHANGELOG.md

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
99

1010
### Added
1111

12-
- Auto-generated Python client from OpenAPI spec
13-
- IonQClient convenience wrapper
14-
- Sync and async support
15-
- OpenAPI Overlay for spec workarounds
16-
- CI/CD workflows
12+
- Auto-generated Python client from the IonQ OpenAPI v0.4 spec (endpoints, typed models, sync + async)
13+
- `IonQClient` convenience wrapper with API key handling, configurable base URL, and User-Agent
14+
- Retry transport with exponential backoff, idempotency-aware retry, and Retry-After support
15+
- Structured exception hierarchy (`IonQError` -> `APIError` -> `AuthenticationError`, `RateLimitError`, etc.)
16+
- Pagination helpers (`iter_jobs`, `aiter_jobs`, `iter_session_jobs`, `aiter_session_jobs`)
17+
- Job polling helpers (`wait_for_job`, `async_wait_for_job`) with timeout and failure detection
18+
- `SessionManager` for QPU session lifecycle (create, end, status, context manager)
19+
- `ClientExtension` API for downstream SDKs to inject hooks, headers, timeouts, and transport wrappers
20+
- Native gate unitary matrices (`gpi_matrix`, `gpi2_matrix`, `ms_matrix`, `zz_matrix`)
21+
- OpenAPI Overlay for spec workarounds (nullable schemas, missing endpoints, gate fixes)
22+
- 100% test coverage on hand-written code (line + branch) enforced in CI
23+
- CI/CD: lint, type check, tests on Python 3.12-3.14, generated code staleness check, weekly spec drift detection

CONTRIBUTING.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ uvx openapi-python-client==0.28.3 generate \
5353
--path /tmp/patched-spec.json \
5454
--meta none \
5555
--config openapi-python-client-config.yaml \
56+
--custom-template-path custom-templates \
5657
--output-path ionq_core \
5758
--overwrite
5859
```

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
[![PyPI version](https://img.shields.io/pypi/v/ionq-core.svg)](https://pypi.org/project/ionq-core/)
44
[![Python 3.12+](https://img.shields.io/badge/python-3.12+-blue.svg)](https://www.python.org/downloads/)
5+
[![CI](https://github.com/ionq/ionq-core-python/actions/workflows/ci.yml/badge.svg)](https://github.com/ionq/ionq-core-python/actions/workflows/ci.yml)
6+
[![API Docs](https://img.shields.io/badge/docs-API%20reference-blue)](https://ionq.github.io/ionq-core-python/)
57

68
A Python client library for the [IonQ Cloud Platform API](https://docs.ionq.com/), providing full access to IonQ's quantum computing services. Supports both synchronous and asynchronous usage, with typed models for all request and response objects.
79

@@ -249,6 +251,7 @@ session = SessionManager.from_id(client, "existing-session-id")
249251
| Cancel a job | `ionq_core.api.default.cancel_job` | Yes |
250252
| Cancel jobs (bulk) | `ionq_core.api.default.cancel_jobs` | Yes |
251253
| Get job cost | `ionq_core.api.default.get_job_cost` | Yes |
254+
| Get compiled circuit | `ionq_core.api.default.get_compiled_file` | Yes |
252255
| Estimate job cost | `ionq_core.api.default.estimate_job_cost` | Yes |
253256

254257
### Sessions

custom-templates/package_init.py.jinja

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,10 @@ from ._polling import (
2525
from ._session import SessionManager
2626
from .client import AuthenticatedClient, Client
2727
from .ionq_client import IonQClient, __version__
28+
from .types import UNSET, Unset
2829

2930
__all__ = (
31+
"UNSET",
3032
"APIConnectionError",
3133
"APIError",
3234
"APITimeoutError",
@@ -46,6 +48,7 @@ __all__ = (
4648
"RateLimitError",
4749
"ServerError",
4850
"SessionManager",
51+
"Unset",
4952
"__version__",
5053
"aiter_jobs",
5154
"aiter_session_jobs",

0 commit comments

Comments
 (0)