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.
Files changed (32) hide show
  1. {openquantum_sdk-0.3.4 → openquantum_sdk-0.3.7}/PKG-INFO +13 -8
  2. {openquantum_sdk-0.3.4 → openquantum_sdk-0.3.7}/README.md +8 -7
  3. {openquantum_sdk-0.3.4 → openquantum_sdk-0.3.7}/openquantum_sdk/__init__.py +1 -1
  4. {openquantum_sdk-0.3.4 → openquantum_sdk-0.3.7}/openquantum_sdk/__main__.py +3 -1
  5. {openquantum_sdk-0.3.4 → openquantum_sdk-0.3.7}/openquantum_sdk/auth.py +58 -5
  6. openquantum_sdk-0.3.7/openquantum_sdk/backends.py +688 -0
  7. {openquantum_sdk-0.3.4 → openquantum_sdk-0.3.7}/openquantum_sdk/clients.py +317 -26
  8. openquantum_sdk-0.3.7/openquantum_sdk/enums.py +40 -0
  9. openquantum_sdk-0.3.7/openquantum_sdk/models.py +469 -0
  10. {openquantum_sdk-0.3.4 → openquantum_sdk-0.3.7}/openquantum_sdk/qiskit/__init__.py +3 -7
  11. openquantum_sdk-0.3.7/openquantum_sdk/utils.py +71 -0
  12. {openquantum_sdk-0.3.4 → openquantum_sdk-0.3.7}/openquantum_sdk.egg-info/PKG-INFO +13 -8
  13. {openquantum_sdk-0.3.4 → openquantum_sdk-0.3.7}/openquantum_sdk.egg-info/SOURCES.txt +3 -1
  14. openquantum_sdk-0.3.7/openquantum_sdk.egg-info/requires.txt +7 -0
  15. {openquantum_sdk-0.3.4 → openquantum_sdk-0.3.7}/pyproject.toml +5 -1
  16. openquantum_sdk-0.3.7/tests/test_backends.py +240 -0
  17. {openquantum_sdk-0.3.4 → openquantum_sdk-0.3.7}/tests/test_clients.py +2 -2
  18. openquantum_sdk-0.3.7/tests/test_clients_plan_priority.py +162 -0
  19. openquantum_sdk-0.3.4/openquantum_sdk/enums.py +0 -16
  20. openquantum_sdk-0.3.4/openquantum_sdk/models.py +0 -230
  21. openquantum_sdk-0.3.4/openquantum_sdk/utils.py +0 -24
  22. openquantum_sdk-0.3.4/openquantum_sdk.egg-info/requires.txt +0 -1
  23. openquantum_sdk-0.3.4/tests/conftest.py +0 -40
  24. {openquantum_sdk-0.3.4 → openquantum_sdk-0.3.7}/MANIFEST.in +0 -0
  25. {openquantum_sdk-0.3.4 → openquantum_sdk-0.3.7}/openquantum_sdk.egg-info/dependency_links.txt +0 -0
  26. {openquantum_sdk-0.3.4 → openquantum_sdk-0.3.7}/openquantum_sdk.egg-info/entry_points.txt +0 -0
  27. {openquantum_sdk-0.3.4 → openquantum_sdk-0.3.7}/openquantum_sdk.egg-info/top_level.txt +0 -0
  28. {openquantum_sdk-0.3.4 → openquantum_sdk-0.3.7}/requirements-dev.txt +0 -0
  29. {openquantum_sdk-0.3.4 → openquantum_sdk-0.3.7}/requirements.txt +0 -0
  30. {openquantum_sdk-0.3.4 → openquantum_sdk-0.3.7}/setup.cfg +0 -0
  31. {openquantum_sdk-0.3.4 → openquantum_sdk-0.3.7}/tests/__init__.py +0 -0
  32. {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.4
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="rigetti:ankaa-3",
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 = "rigetti:ankaa-3"
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 "ionq:aria-1" \
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
- | IonQ | Aria-1 | `ionq:aria-1` |
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 | Ankaa-3 | `rigetti:ankaa-3` |
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` only allows `PUBLIC` + `STANDARD`. Use explicit enums for private/instant access.
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="rigetti:ankaa-3",
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 = "rigetti:ankaa-3"
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 "ionq:aria-1" \
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
- | IonQ | Aria-1 | `ionq:aria-1` |
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 | Ankaa-3 | `rigetti:ankaa-3` |
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` only allows `PUBLIC` + `STANDARD`. Use explicit enums for private/instant access.
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.
@@ -1,5 +1,5 @@
1
1
  from .clients import SchedulerClient, ManagementClient
2
2
  from .utils import poll_for_status
3
3
 
4
- __version__ = "0.3.4"
4
+ __version__ = "0.3.7"
5
5
  __all__ = ["SchedulerClient", "ManagementClient", "poll_for_status"]
@@ -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
- Keycloak client-credentials OAuth2 helper with local, thread-safe token cache.
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}"}