openquantum-sdk 0.3.3__tar.gz → 0.3.7__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {openquantum_sdk-0.3.3/openquantum_sdk.egg-info → openquantum_sdk-0.3.7}/PKG-INFO +24 -8
- openquantum_sdk-0.3.3/PKG-INFO → openquantum_sdk-0.3.7/README.md +19 -18
- {openquantum_sdk-0.3.3 → openquantum_sdk-0.3.7}/openquantum_sdk/__init__.py +1 -1
- {openquantum_sdk-0.3.3 → openquantum_sdk-0.3.7}/openquantum_sdk/__main__.py +3 -1
- {openquantum_sdk-0.3.3 → openquantum_sdk-0.3.7}/openquantum_sdk/auth.py +58 -5
- openquantum_sdk-0.3.7/openquantum_sdk/backends.py +688 -0
- {openquantum_sdk-0.3.3 → openquantum_sdk-0.3.7}/openquantum_sdk/clients.py +337 -26
- openquantum_sdk-0.3.7/openquantum_sdk/enums.py +40 -0
- openquantum_sdk-0.3.7/openquantum_sdk/models.py +469 -0
- {openquantum_sdk-0.3.3 → openquantum_sdk-0.3.7}/openquantum_sdk/qiskit/__init__.py +3 -7
- openquantum_sdk-0.3.7/openquantum_sdk/utils.py +71 -0
- openquantum_sdk-0.3.3/README.md → openquantum_sdk-0.3.7/openquantum_sdk.egg-info/PKG-INFO +34 -7
- {openquantum_sdk-0.3.3 → openquantum_sdk-0.3.7}/openquantum_sdk.egg-info/SOURCES.txt +3 -1
- openquantum_sdk-0.3.7/openquantum_sdk.egg-info/requires.txt +7 -0
- {openquantum_sdk-0.3.3 → openquantum_sdk-0.3.7}/pyproject.toml +5 -1
- openquantum_sdk-0.3.7/tests/test_backends.py +240 -0
- {openquantum_sdk-0.3.3 → openquantum_sdk-0.3.7}/tests/test_clients.py +14 -4
- openquantum_sdk-0.3.7/tests/test_clients_plan_priority.py +162 -0
- openquantum_sdk-0.3.3/openquantum_sdk/enums.py +0 -16
- openquantum_sdk-0.3.3/openquantum_sdk/models.py +0 -223
- openquantum_sdk-0.3.3/openquantum_sdk/utils.py +0 -24
- openquantum_sdk-0.3.3/openquantum_sdk.egg-info/requires.txt +0 -1
- openquantum_sdk-0.3.3/tests/conftest.py +0 -40
- {openquantum_sdk-0.3.3 → openquantum_sdk-0.3.7}/MANIFEST.in +0 -0
- {openquantum_sdk-0.3.3 → openquantum_sdk-0.3.7}/openquantum_sdk.egg-info/dependency_links.txt +0 -0
- {openquantum_sdk-0.3.3 → openquantum_sdk-0.3.7}/openquantum_sdk.egg-info/entry_points.txt +0 -0
- {openquantum_sdk-0.3.3 → openquantum_sdk-0.3.7}/openquantum_sdk.egg-info/top_level.txt +0 -0
- {openquantum_sdk-0.3.3 → openquantum_sdk-0.3.7}/requirements-dev.txt +0 -0
- {openquantum_sdk-0.3.3 → openquantum_sdk-0.3.7}/requirements.txt +0 -0
- {openquantum_sdk-0.3.3 → openquantum_sdk-0.3.7}/setup.cfg +0 -0
- {openquantum_sdk-0.3.3 → openquantum_sdk-0.3.7}/tests/__init__.py +0 -0
- {openquantum_sdk-0.3.3 → openquantum_sdk-0.3.7}/tests/test_qiskit_wrappers.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: openquantum-sdk
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.7
|
|
4
4
|
Summary: Python SDK for Open Quantum
|
|
5
5
|
Classifier: Programming Language :: Python :: 3
|
|
6
6
|
Classifier: License :: OSI Approved :: Apache Software License
|
|
@@ -8,6 +8,10 @@ Classifier: Operating System :: OS Independent
|
|
|
8
8
|
Requires-Python: >=3.8
|
|
9
9
|
Description-Content-Type: text/markdown
|
|
10
10
|
Requires-Dist: requests>=2.25.0
|
|
11
|
+
Provides-Extra: qiskit
|
|
12
|
+
Requires-Dist: openquantum-sdk-qiskit>=0.2.4; extra == "qiskit"
|
|
13
|
+
Provides-Extra: pennylane
|
|
14
|
+
Requires-Dist: openquantum-sdk-pennylane>=0.1.0; extra == "pennylane"
|
|
11
15
|
|
|
12
16
|
# Open Quantum Python SDK
|
|
13
17
|
|
|
@@ -58,6 +62,13 @@ auth = ClientCredentialsAuth(
|
|
|
58
62
|
)
|
|
59
63
|
```
|
|
60
64
|
|
|
65
|
+
### Option 3: Environment Variables
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
export OPENQUANTUM_CLIENT_ID=s_...
|
|
69
|
+
export OPENQUANTUM_CLIENT_SECRET=e460c8...
|
|
70
|
+
```
|
|
71
|
+
|
|
61
72
|
## Quickstart: One-Call Submission (Recommended)
|
|
62
73
|
|
|
63
74
|
```python
|
|
@@ -93,7 +104,7 @@ try:
|
|
|
93
104
|
# 3. Define config
|
|
94
105
|
config = JobSubmissionConfig(
|
|
95
106
|
organization_id=org_id,
|
|
96
|
-
backend_class_id="
|
|
107
|
+
backend_class_id="iqm:emerald",
|
|
97
108
|
name="Bell State SDK Quickstart",
|
|
98
109
|
job_subcategory_id="fin:port", # Finance Portfolio Optimization
|
|
99
110
|
shots=100,
|
|
@@ -155,7 +166,7 @@ try:
|
|
|
155
166
|
print(f" - {bc.name} [{bc.type}] — {bc.short_code or bc.id}")
|
|
156
167
|
|
|
157
168
|
# 2. Choose IDs
|
|
158
|
-
MY_BACKEND = "
|
|
169
|
+
MY_BACKEND = "iqm:emerald"
|
|
159
170
|
MY_SUBCATEGORY = "fin:port"
|
|
160
171
|
|
|
161
172
|
# 3. Upload
|
|
@@ -290,6 +301,7 @@ finally:
|
|
|
290
301
|
| `list_user_organizations(limit=20, cursor=...)` | `PaginatedOrganizations` | Your orgs |
|
|
291
302
|
| `list_providers(limit=20, cursor=...)` | `PaginatedProviders` | All backend providers |
|
|
292
303
|
| `list_backend_classes(provider_id=None, limit=20, cursor=...)` | `PaginatedBackendClasses` | Available backends |
|
|
304
|
+
| `get_credit_balance(organization_id: str)` | `CreditBalanceRead` | Get current credit balance |
|
|
293
305
|
|
|
294
306
|
## Data Models
|
|
295
307
|
|
|
@@ -345,7 +357,7 @@ from openquantum_sdk.enums import ExecutionPlanType, QueuePriorityType
|
|
|
345
357
|
```bash
|
|
346
358
|
python -m openquantum_sdk --sdk-key ./key.json \
|
|
347
359
|
--input bell.qasm \
|
|
348
|
-
--backend "
|
|
360
|
+
--backend "iqm:emerald" \
|
|
349
361
|
--name "CLI Circuit" \
|
|
350
362
|
--subcategory "mathematics:linear-systems" \
|
|
351
363
|
--shots 100 \
|
|
@@ -359,11 +371,12 @@ Automatically **downloads and pretty-prints JSON output**.
|
|
|
359
371
|
### Backends
|
|
360
372
|
| Provider | Backend | Short Code |
|
|
361
373
|
| ------ | ------ | ------ |
|
|
362
|
-
|
|
|
374
|
+
| AQT | Ibex-Q1 | `aqt:ibex-q1` |
|
|
375
|
+
| IonQ | Forte Enterprise | `ionq:forte-ent` |
|
|
363
376
|
| IonQ | Forte-1 | `ionq:forte-1` |
|
|
364
377
|
| IQM | Emerald | `iqm:emerald` |
|
|
365
378
|
| IQM | Garnet | `iqm:garnet` |
|
|
366
|
-
| Rigetti |
|
|
379
|
+
| Rigetti | Cepheus-1-108Q | `rigetti:cepheus-108q`|
|
|
367
380
|
|
|
368
381
|
*Note: This list may be modified as backends are added or removed from the platform. For the most up-to-date list, run the following code:*
|
|
369
382
|
|
|
@@ -431,5 +444,8 @@ for cat in cats:
|
|
|
431
444
|
**Q: How do I get results as JSON?**
|
|
432
445
|
**A:** Use `scheduler.download_job_output(job)` — returns parsed object.
|
|
433
446
|
|
|
434
|
-
**Q: Why does auto mode fail on some QPUs?**
|
|
435
|
-
**A:** `auto`
|
|
447
|
+
**Q: Why does auto mode fail on some QPUs?**
|
|
448
|
+
**A:** `"auto"` selects the cheapest plan and priority (`PUBLIC` + `STANDARD`). If a backend only offers private execution, pass `execution_plan="private"` explicitly. Similarly, use `queue_priority="priority"` or `"instant"` for higher-priority queue access.
|
|
449
|
+
|
|
450
|
+
**Q: Can I hide the public plan citation notice?**
|
|
451
|
+
**A:** Setting `OPENQUANTUM_HIDE_CITATION_NOTICE=true` will omit the citation notice from output.
|
|
@@ -1,14 +1,3 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: openquantum-sdk
|
|
3
|
-
Version: 0.3.3
|
|
4
|
-
Summary: Python SDK for Open Quantum
|
|
5
|
-
Classifier: Programming Language :: Python :: 3
|
|
6
|
-
Classifier: License :: OSI Approved :: Apache Software License
|
|
7
|
-
Classifier: Operating System :: OS Independent
|
|
8
|
-
Requires-Python: >=3.8
|
|
9
|
-
Description-Content-Type: text/markdown
|
|
10
|
-
Requires-Dist: requests>=2.25.0
|
|
11
|
-
|
|
12
1
|
# Open Quantum Python SDK
|
|
13
2
|
|
|
14
3
|
A lightweight, modern Python SDK for the **Open Quantum Platform**.
|
|
@@ -58,6 +47,13 @@ auth = ClientCredentialsAuth(
|
|
|
58
47
|
)
|
|
59
48
|
```
|
|
60
49
|
|
|
50
|
+
### Option 3: Environment Variables
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
export OPENQUANTUM_CLIENT_ID=s_...
|
|
54
|
+
export OPENQUANTUM_CLIENT_SECRET=e460c8...
|
|
55
|
+
```
|
|
56
|
+
|
|
61
57
|
## Quickstart: One-Call Submission (Recommended)
|
|
62
58
|
|
|
63
59
|
```python
|
|
@@ -93,7 +89,7 @@ try:
|
|
|
93
89
|
# 3. Define config
|
|
94
90
|
config = JobSubmissionConfig(
|
|
95
91
|
organization_id=org_id,
|
|
96
|
-
backend_class_id="
|
|
92
|
+
backend_class_id="iqm:emerald",
|
|
97
93
|
name="Bell State SDK Quickstart",
|
|
98
94
|
job_subcategory_id="fin:port", # Finance Portfolio Optimization
|
|
99
95
|
shots=100,
|
|
@@ -155,7 +151,7 @@ try:
|
|
|
155
151
|
print(f" - {bc.name} [{bc.type}] — {bc.short_code or bc.id}")
|
|
156
152
|
|
|
157
153
|
# 2. Choose IDs
|
|
158
|
-
MY_BACKEND = "
|
|
154
|
+
MY_BACKEND = "iqm:emerald"
|
|
159
155
|
MY_SUBCATEGORY = "fin:port"
|
|
160
156
|
|
|
161
157
|
# 3. Upload
|
|
@@ -290,6 +286,7 @@ finally:
|
|
|
290
286
|
| `list_user_organizations(limit=20, cursor=...)` | `PaginatedOrganizations` | Your orgs |
|
|
291
287
|
| `list_providers(limit=20, cursor=...)` | `PaginatedProviders` | All backend providers |
|
|
292
288
|
| `list_backend_classes(provider_id=None, limit=20, cursor=...)` | `PaginatedBackendClasses` | Available backends |
|
|
289
|
+
| `get_credit_balance(organization_id: str)` | `CreditBalanceRead` | Get current credit balance |
|
|
293
290
|
|
|
294
291
|
## Data Models
|
|
295
292
|
|
|
@@ -345,7 +342,7 @@ from openquantum_sdk.enums import ExecutionPlanType, QueuePriorityType
|
|
|
345
342
|
```bash
|
|
346
343
|
python -m openquantum_sdk --sdk-key ./key.json \
|
|
347
344
|
--input bell.qasm \
|
|
348
|
-
--backend "
|
|
345
|
+
--backend "iqm:emerald" \
|
|
349
346
|
--name "CLI Circuit" \
|
|
350
347
|
--subcategory "mathematics:linear-systems" \
|
|
351
348
|
--shots 100 \
|
|
@@ -359,11 +356,12 @@ Automatically **downloads and pretty-prints JSON output**.
|
|
|
359
356
|
### Backends
|
|
360
357
|
| Provider | Backend | Short Code |
|
|
361
358
|
| ------ | ------ | ------ |
|
|
362
|
-
|
|
|
359
|
+
| AQT | Ibex-Q1 | `aqt:ibex-q1` |
|
|
360
|
+
| IonQ | Forte Enterprise | `ionq:forte-ent` |
|
|
363
361
|
| IonQ | Forte-1 | `ionq:forte-1` |
|
|
364
362
|
| IQM | Emerald | `iqm:emerald` |
|
|
365
363
|
| IQM | Garnet | `iqm:garnet` |
|
|
366
|
-
| Rigetti |
|
|
364
|
+
| Rigetti | Cepheus-1-108Q | `rigetti:cepheus-108q`|
|
|
367
365
|
|
|
368
366
|
*Note: This list may be modified as backends are added or removed from the platform. For the most up-to-date list, run the following code:*
|
|
369
367
|
|
|
@@ -431,5 +429,8 @@ for cat in cats:
|
|
|
431
429
|
**Q: How do I get results as JSON?**
|
|
432
430
|
**A:** Use `scheduler.download_job_output(job)` — returns parsed object.
|
|
433
431
|
|
|
434
|
-
**Q: Why does auto mode fail on some QPUs?**
|
|
435
|
-
**A:** `auto`
|
|
432
|
+
**Q: Why does auto mode fail on some QPUs?**
|
|
433
|
+
**A:** `"auto"` selects the cheapest plan and priority (`PUBLIC` + `STANDARD`). If a backend only offers private execution, pass `execution_plan="private"` explicitly. Similarly, use `queue_priority="priority"` or `"instant"` for higher-priority queue access.
|
|
434
|
+
|
|
435
|
+
**Q: Can I hide the public plan citation notice?**
|
|
436
|
+
**A:** Setting `OPENQUANTUM_HIDE_CITATION_NOTICE=true` will omit the citation notice from output.
|
|
@@ -121,8 +121,10 @@ def main():
|
|
|
121
121
|
creds=creds
|
|
122
122
|
)
|
|
123
123
|
|
|
124
|
-
scheduler = SchedulerClient(base_url=args.scheduler_base, auth=auth)
|
|
125
124
|
management = ManagementClient(base_url=args.management_base, auth=auth)
|
|
125
|
+
scheduler = SchedulerClient(
|
|
126
|
+
base_url=args.scheduler_base, auth=auth, management_client=management
|
|
127
|
+
)
|
|
126
128
|
|
|
127
129
|
try:
|
|
128
130
|
print("--- Open Quantum Job Submission CLI ---")
|
|
@@ -9,17 +9,28 @@ from urllib.parse import urljoin
|
|
|
9
9
|
|
|
10
10
|
@dataclass
|
|
11
11
|
class ClientCredentials:
|
|
12
|
+
"""SDK key credentials for machine-to-machine authentication.
|
|
13
|
+
|
|
14
|
+
Attributes:
|
|
15
|
+
client_id: The OAuth2 client ID (SDK key ID).
|
|
16
|
+
client_secret: The OAuth2 client secret (SDK key secret).
|
|
17
|
+
"""
|
|
18
|
+
|
|
12
19
|
client_id: str
|
|
13
20
|
client_secret: str
|
|
14
21
|
|
|
15
22
|
|
|
16
23
|
class ClientCredentialsAuth:
|
|
24
|
+
"""Keycloak client-credentials OAuth2 helper with thread-safe token caching.
|
|
25
|
+
|
|
26
|
+
Manages the full token lifecycle: initial fetch, automatic refresh when
|
|
27
|
+
the token is within ``leeway_seconds`` of expiry, and forced refresh on
|
|
28
|
+
401 retries. All token operations are thread-safe.
|
|
29
|
+
|
|
30
|
+
The token endpoint is constructed as:
|
|
31
|
+
``{keycloak_base}/realms/{realm}/protocol/openid-connect/token``
|
|
17
32
|
"""
|
|
18
|
-
|
|
19
|
-
- Fetches token from: {keycloak_base}/realms/{realm}/protocol/openid-connect/token
|
|
20
|
-
- Auto refreshes when within leeway of expiry
|
|
21
|
-
- Retries once on 401
|
|
22
|
-
"""
|
|
33
|
+
|
|
23
34
|
def __init__(
|
|
24
35
|
self,
|
|
25
36
|
creds: ClientCredentials,
|
|
@@ -29,6 +40,19 @@ class ClientCredentialsAuth:
|
|
|
29
40
|
leeway_seconds: int = 30,
|
|
30
41
|
session: Optional[requests.Session] = None,
|
|
31
42
|
):
|
|
43
|
+
"""Initialize the auth helper.
|
|
44
|
+
|
|
45
|
+
Args:
|
|
46
|
+
creds: Client credentials containing the client ID and secret.
|
|
47
|
+
keycloak_base: Base URL of the Keycloak server.
|
|
48
|
+
Defaults to ``"https://id.openquantum.com"``.
|
|
49
|
+
realm: Keycloak realm name. Defaults to ``"platform"``.
|
|
50
|
+
scope: Optional OAuth2 scope to request.
|
|
51
|
+
leeway_seconds: Seconds before token expiry to trigger a
|
|
52
|
+
proactive refresh. Defaults to 30.
|
|
53
|
+
session: Optional ``requests.Session`` to use for token requests.
|
|
54
|
+
A new session is created if not provided.
|
|
55
|
+
"""
|
|
32
56
|
self.keycloak_base = keycloak_base.rstrip("/")
|
|
33
57
|
self.realm = realm
|
|
34
58
|
self.creds = creds
|
|
@@ -41,6 +65,7 @@ class ClientCredentialsAuth:
|
|
|
41
65
|
|
|
42
66
|
@property
|
|
43
67
|
def token_endpoint(self) -> str:
|
|
68
|
+
"""The full Keycloak token endpoint URL for this realm."""
|
|
44
69
|
return urljoin(
|
|
45
70
|
self.keycloak_base + "/",
|
|
46
71
|
f"realms/{self.realm}/protocol/openid-connect/token",
|
|
@@ -72,6 +97,22 @@ class ClientCredentialsAuth:
|
|
|
72
97
|
self._expires_at = time.time() + int(expires_in)
|
|
73
98
|
|
|
74
99
|
def get_access_token(self, force: bool = False) -> str:
|
|
100
|
+
"""Return a valid access token, refreshing if needed.
|
|
101
|
+
|
|
102
|
+
Uses double-checked locking to ensure only one thread fetches a
|
|
103
|
+
new token at a time.
|
|
104
|
+
|
|
105
|
+
Args:
|
|
106
|
+
force: If ``True``, forces a token refresh regardless of
|
|
107
|
+
expiry status. Defaults to ``False``.
|
|
108
|
+
|
|
109
|
+
Returns:
|
|
110
|
+
A valid OAuth2 access token string.
|
|
111
|
+
|
|
112
|
+
Raises:
|
|
113
|
+
RuntimeError: If the Keycloak response is missing an access token.
|
|
114
|
+
requests.HTTPError: If the token request fails.
|
|
115
|
+
"""
|
|
75
116
|
if force or self._needs_refresh():
|
|
76
117
|
with self._lock:
|
|
77
118
|
if force or self._needs_refresh():
|
|
@@ -79,6 +120,18 @@ class ClientCredentialsAuth:
|
|
|
79
120
|
return self._access_token # type: ignore[str-bytes-safe]
|
|
80
121
|
|
|
81
122
|
def apply_auth_header(self, headers: Dict[str, str]) -> Dict[str, str]:
|
|
123
|
+
"""Add a Bearer authorization header using the current access token.
|
|
124
|
+
|
|
125
|
+
Does not mutate the input dict; returns a new dict with the
|
|
126
|
+
``Authorization`` header added.
|
|
127
|
+
|
|
128
|
+
Args:
|
|
129
|
+
headers: Existing headers to augment.
|
|
130
|
+
|
|
131
|
+
Returns:
|
|
132
|
+
A new headers dict containing all entries from ``headers`` plus
|
|
133
|
+
the ``Authorization: Bearer <token>`` header.
|
|
134
|
+
"""
|
|
82
135
|
token = self.get_access_token()
|
|
83
136
|
# don't mutate caller's header dict
|
|
84
137
|
return {**headers, "Authorization": f"Bearer {token}"}
|