openquantum-sdk 0.3.4__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.4 → openquantum_sdk-0.3.7}/PKG-INFO +13 -8
- {openquantum_sdk-0.3.4 → openquantum_sdk-0.3.7}/README.md +8 -7
- {openquantum_sdk-0.3.4 → openquantum_sdk-0.3.7}/openquantum_sdk/__init__.py +1 -1
- {openquantum_sdk-0.3.4 → openquantum_sdk-0.3.7}/openquantum_sdk/__main__.py +3 -1
- {openquantum_sdk-0.3.4 → 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.4 → openquantum_sdk-0.3.7}/openquantum_sdk/clients.py +317 -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.4 → 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.4 → openquantum_sdk-0.3.7}/openquantum_sdk.egg-info/PKG-INFO +13 -8
- {openquantum_sdk-0.3.4 → 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.4 → openquantum_sdk-0.3.7}/pyproject.toml +5 -1
- openquantum_sdk-0.3.7/tests/test_backends.py +240 -0
- {openquantum_sdk-0.3.4 → openquantum_sdk-0.3.7}/tests/test_clients.py +2 -2
- openquantum_sdk-0.3.7/tests/test_clients_plan_priority.py +162 -0
- openquantum_sdk-0.3.4/openquantum_sdk/enums.py +0 -16
- openquantum_sdk-0.3.4/openquantum_sdk/models.py +0 -230
- openquantum_sdk-0.3.4/openquantum_sdk/utils.py +0 -24
- openquantum_sdk-0.3.4/openquantum_sdk.egg-info/requires.txt +0 -1
- openquantum_sdk-0.3.4/tests/conftest.py +0 -40
- {openquantum_sdk-0.3.4 → openquantum_sdk-0.3.7}/MANIFEST.in +0 -0
- {openquantum_sdk-0.3.4 → openquantum_sdk-0.3.7}/openquantum_sdk.egg-info/dependency_links.txt +0 -0
- {openquantum_sdk-0.3.4 → openquantum_sdk-0.3.7}/openquantum_sdk.egg-info/entry_points.txt +0 -0
- {openquantum_sdk-0.3.4 → openquantum_sdk-0.3.7}/openquantum_sdk.egg-info/top_level.txt +0 -0
- {openquantum_sdk-0.3.4 → openquantum_sdk-0.3.7}/requirements-dev.txt +0 -0
- {openquantum_sdk-0.3.4 → openquantum_sdk-0.3.7}/requirements.txt +0 -0
- {openquantum_sdk-0.3.4 → openquantum_sdk-0.3.7}/setup.cfg +0 -0
- {openquantum_sdk-0.3.4 → openquantum_sdk-0.3.7}/tests/__init__.py +0 -0
- {openquantum_sdk-0.3.4 → 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
|
|
|
@@ -100,7 +104,7 @@ try:
|
|
|
100
104
|
# 3. Define config
|
|
101
105
|
config = JobSubmissionConfig(
|
|
102
106
|
organization_id=org_id,
|
|
103
|
-
backend_class_id="
|
|
107
|
+
backend_class_id="iqm:emerald",
|
|
104
108
|
name="Bell State SDK Quickstart",
|
|
105
109
|
job_subcategory_id="fin:port", # Finance Portfolio Optimization
|
|
106
110
|
shots=100,
|
|
@@ -162,7 +166,7 @@ try:
|
|
|
162
166
|
print(f" - {bc.name} [{bc.type}] — {bc.short_code or bc.id}")
|
|
163
167
|
|
|
164
168
|
# 2. Choose IDs
|
|
165
|
-
MY_BACKEND = "
|
|
169
|
+
MY_BACKEND = "iqm:emerald"
|
|
166
170
|
MY_SUBCATEGORY = "fin:port"
|
|
167
171
|
|
|
168
172
|
# 3. Upload
|
|
@@ -353,7 +357,7 @@ from openquantum_sdk.enums import ExecutionPlanType, QueuePriorityType
|
|
|
353
357
|
```bash
|
|
354
358
|
python -m openquantum_sdk --sdk-key ./key.json \
|
|
355
359
|
--input bell.qasm \
|
|
356
|
-
--backend "
|
|
360
|
+
--backend "iqm:emerald" \
|
|
357
361
|
--name "CLI Circuit" \
|
|
358
362
|
--subcategory "mathematics:linear-systems" \
|
|
359
363
|
--shots 100 \
|
|
@@ -367,11 +371,12 @@ Automatically **downloads and pretty-prints JSON output**.
|
|
|
367
371
|
### Backends
|
|
368
372
|
| Provider | Backend | Short Code |
|
|
369
373
|
| ------ | ------ | ------ |
|
|
370
|
-
|
|
|
374
|
+
| AQT | Ibex-Q1 | `aqt:ibex-q1` |
|
|
375
|
+
| IonQ | Forte Enterprise | `ionq:forte-ent` |
|
|
371
376
|
| IonQ | Forte-1 | `ionq:forte-1` |
|
|
372
377
|
| IQM | Emerald | `iqm:emerald` |
|
|
373
378
|
| IQM | Garnet | `iqm:garnet` |
|
|
374
|
-
| Rigetti |
|
|
379
|
+
| Rigetti | Cepheus-1-108Q | `rigetti:cepheus-108q`|
|
|
375
380
|
|
|
376
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:*
|
|
377
382
|
|
|
@@ -439,8 +444,8 @@ for cat in cats:
|
|
|
439
444
|
**Q: How do I get results as JSON?**
|
|
440
445
|
**A:** Use `scheduler.download_job_output(job)` — returns parsed object.
|
|
441
446
|
|
|
442
|
-
**Q: Why does auto mode fail on some QPUs?**
|
|
443
|
-
**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.
|
|
444
449
|
|
|
445
450
|
**Q: Can I hide the public plan citation notice?**
|
|
446
451
|
**A:** Setting `OPENQUANTUM_HIDE_CITATION_NOTICE=true` will omit the citation notice from output.
|
|
@@ -89,7 +89,7 @@ try:
|
|
|
89
89
|
# 3. Define config
|
|
90
90
|
config = JobSubmissionConfig(
|
|
91
91
|
organization_id=org_id,
|
|
92
|
-
backend_class_id="
|
|
92
|
+
backend_class_id="iqm:emerald",
|
|
93
93
|
name="Bell State SDK Quickstart",
|
|
94
94
|
job_subcategory_id="fin:port", # Finance Portfolio Optimization
|
|
95
95
|
shots=100,
|
|
@@ -151,7 +151,7 @@ try:
|
|
|
151
151
|
print(f" - {bc.name} [{bc.type}] — {bc.short_code or bc.id}")
|
|
152
152
|
|
|
153
153
|
# 2. Choose IDs
|
|
154
|
-
MY_BACKEND = "
|
|
154
|
+
MY_BACKEND = "iqm:emerald"
|
|
155
155
|
MY_SUBCATEGORY = "fin:port"
|
|
156
156
|
|
|
157
157
|
# 3. Upload
|
|
@@ -342,7 +342,7 @@ from openquantum_sdk.enums import ExecutionPlanType, QueuePriorityType
|
|
|
342
342
|
```bash
|
|
343
343
|
python -m openquantum_sdk --sdk-key ./key.json \
|
|
344
344
|
--input bell.qasm \
|
|
345
|
-
--backend "
|
|
345
|
+
--backend "iqm:emerald" \
|
|
346
346
|
--name "CLI Circuit" \
|
|
347
347
|
--subcategory "mathematics:linear-systems" \
|
|
348
348
|
--shots 100 \
|
|
@@ -356,11 +356,12 @@ Automatically **downloads and pretty-prints JSON output**.
|
|
|
356
356
|
### Backends
|
|
357
357
|
| Provider | Backend | Short Code |
|
|
358
358
|
| ------ | ------ | ------ |
|
|
359
|
-
|
|
|
359
|
+
| AQT | Ibex-Q1 | `aqt:ibex-q1` |
|
|
360
|
+
| IonQ | Forte Enterprise | `ionq:forte-ent` |
|
|
360
361
|
| IonQ | Forte-1 | `ionq:forte-1` |
|
|
361
362
|
| IQM | Emerald | `iqm:emerald` |
|
|
362
363
|
| IQM | Garnet | `iqm:garnet` |
|
|
363
|
-
| Rigetti |
|
|
364
|
+
| Rigetti | Cepheus-1-108Q | `rigetti:cepheus-108q`|
|
|
364
365
|
|
|
365
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:*
|
|
366
367
|
|
|
@@ -428,8 +429,8 @@ for cat in cats:
|
|
|
428
429
|
**Q: How do I get results as JSON?**
|
|
429
430
|
**A:** Use `scheduler.download_job_output(job)` — returns parsed object.
|
|
430
431
|
|
|
431
|
-
**Q: Why does auto mode fail on some QPUs?**
|
|
432
|
-
**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.
|
|
433
434
|
|
|
434
435
|
**Q: Can I hide the public plan citation notice?**
|
|
435
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}"}
|