qbraid-core 0.2.2__tar.gz → 0.2.3__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 (73) hide show
  1. {qbraid_core-0.2.2/qbraid_core.egg-info → qbraid_core-0.2.3}/PKG-INFO +1 -1
  2. {qbraid_core-0.2.2 → qbraid_core-0.2.3}/pyproject.toml +1 -1
  3. {qbraid_core-0.2.2 → qbraid_core-0.2.3}/qbraid_core/services/runtime/client.py +122 -0
  4. {qbraid_core-0.2.2 → qbraid_core-0.2.3}/qbraid_core/services/runtime/schemas/__init__.py +3 -0
  5. qbraid_core-0.2.3/qbraid_core/services/runtime/schemas/group.py +91 -0
  6. {qbraid_core-0.2.2 → qbraid_core-0.2.3}/qbraid_core/services/runtime/schemas/job.py +8 -2
  7. {qbraid_core-0.2.2 → qbraid_core-0.2.3/qbraid_core.egg-info}/PKG-INFO +1 -1
  8. {qbraid_core-0.2.2 → qbraid_core-0.2.3}/qbraid_core.egg-info/SOURCES.txt +1 -0
  9. {qbraid_core-0.2.2 → qbraid_core-0.2.3}/LICENSE +0 -0
  10. {qbraid_core-0.2.2 → qbraid_core-0.2.3}/MANIFEST.in +0 -0
  11. {qbraid_core-0.2.2 → qbraid_core-0.2.3}/README.md +0 -0
  12. {qbraid_core-0.2.2 → qbraid_core-0.2.3}/docs/_static/favicon.ico +0 -0
  13. {qbraid_core-0.2.2 → qbraid_core-0.2.3}/docs/_static/logo.png +0 -0
  14. {qbraid_core-0.2.2 → qbraid_core-0.2.3}/docs/api/qbraid_core.rst +0 -0
  15. {qbraid_core-0.2.2 → qbraid_core-0.2.3}/docs/api/qbraid_core.services.rst +0 -0
  16. {qbraid_core-0.2.2 → qbraid_core-0.2.3}/docs/conf.py +0 -0
  17. {qbraid_core-0.2.2 → qbraid_core-0.2.3}/docs/index.rst +0 -0
  18. {qbraid_core-0.2.2 → qbraid_core-0.2.3}/qbraid_core/__init__.py +0 -0
  19. {qbraid_core-0.2.2 → qbraid_core-0.2.3}/qbraid_core/_compat.py +0 -0
  20. {qbraid_core-0.2.2 → qbraid_core-0.2.3}/qbraid_core/_import.py +0 -0
  21. {qbraid_core-0.2.2 → qbraid_core-0.2.3}/qbraid_core/_version.py +0 -0
  22. {qbraid_core-0.2.2 → qbraid_core-0.2.3}/qbraid_core/annotations.py +0 -0
  23. {qbraid_core-0.2.2 → qbraid_core-0.2.3}/qbraid_core/client.py +0 -0
  24. {qbraid_core-0.2.2 → qbraid_core-0.2.3}/qbraid_core/config.py +0 -0
  25. {qbraid_core-0.2.2 → qbraid_core-0.2.3}/qbraid_core/context.py +0 -0
  26. {qbraid_core-0.2.2 → qbraid_core-0.2.3}/qbraid_core/decimal.py +0 -0
  27. {qbraid_core-0.2.2 → qbraid_core-0.2.3}/qbraid_core/exceptions.py +0 -0
  28. {qbraid_core-0.2.2 → qbraid_core-0.2.3}/qbraid_core/py.typed +0 -0
  29. {qbraid_core-0.2.2 → qbraid_core-0.2.3}/qbraid_core/registry.py +0 -0
  30. {qbraid_core-0.2.2 → qbraid_core-0.2.3}/qbraid_core/retry.py +0 -0
  31. {qbraid_core-0.2.2 → qbraid_core-0.2.3}/qbraid_core/services/__init__.py +0 -0
  32. {qbraid_core-0.2.2 → qbraid_core-0.2.3}/qbraid_core/services/environments/__init__.py +0 -0
  33. {qbraid_core-0.2.2 → qbraid_core-0.2.3}/qbraid_core/services/environments/client.py +0 -0
  34. {qbraid_core-0.2.2 → qbraid_core-0.2.3}/qbraid_core/services/environments/create.py +0 -0
  35. {qbraid_core-0.2.2 → qbraid_core-0.2.3}/qbraid_core/services/environments/exceptions.py +0 -0
  36. {qbraid_core-0.2.2 → qbraid_core-0.2.3}/qbraid_core/services/environments/kernels.py +0 -0
  37. {qbraid_core-0.2.2 → qbraid_core-0.2.3}/qbraid_core/services/environments/magic.py +0 -0
  38. {qbraid_core-0.2.2 → qbraid_core-0.2.3}/qbraid_core/services/environments/packages.py +0 -0
  39. {qbraid_core-0.2.2 → qbraid_core-0.2.3}/qbraid_core/services/environments/paths.py +0 -0
  40. {qbraid_core-0.2.2 → qbraid_core-0.2.3}/qbraid_core/services/environments/registry.py +0 -0
  41. {qbraid_core-0.2.2 → qbraid_core-0.2.3}/qbraid_core/services/environments/schema.py +0 -0
  42. {qbraid_core-0.2.2 → qbraid_core-0.2.3}/qbraid_core/services/environments/state.py +0 -0
  43. {qbraid_core-0.2.2 → qbraid_core-0.2.3}/qbraid_core/services/environments/validate.py +0 -0
  44. {qbraid_core-0.2.2 → qbraid_core-0.2.3}/qbraid_core/services/mcp/__init__.py +0 -0
  45. {qbraid_core-0.2.2 → qbraid_core-0.2.3}/qbraid_core/services/mcp/client.py +0 -0
  46. {qbraid_core-0.2.2 → qbraid_core-0.2.3}/qbraid_core/services/mcp/discovery.py +0 -0
  47. {qbraid_core-0.2.2 → qbraid_core-0.2.3}/qbraid_core/services/mcp/router.py +0 -0
  48. {qbraid_core-0.2.2 → qbraid_core-0.2.3}/qbraid_core/services/quantum/__init__.py +0 -0
  49. {qbraid_core-0.2.2 → qbraid_core-0.2.3}/qbraid_core/services/quantum/runner.py +0 -0
  50. {qbraid_core-0.2.2 → qbraid_core-0.2.3}/qbraid_core/services/runtime/__init__.py +0 -0
  51. {qbraid_core-0.2.2 → qbraid_core-0.2.3}/qbraid_core/services/runtime/exceptions.py +0 -0
  52. {qbraid_core-0.2.2 → qbraid_core-0.2.3}/qbraid_core/services/runtime/schemas/device.py +0 -0
  53. {qbraid_core-0.2.2 → qbraid_core-0.2.3}/qbraid_core/services/runtime/schemas/enums.py +0 -0
  54. {qbraid_core-0.2.2 → qbraid_core-0.2.3}/qbraid_core/services/runtime/schemas/result.py +0 -0
  55. {qbraid_core-0.2.2 → qbraid_core-0.2.3}/qbraid_core/services/storage/__init__.py +0 -0
  56. {qbraid_core-0.2.2 → qbraid_core-0.2.3}/qbraid_core/services/storage/disk_usage_client.py +0 -0
  57. {qbraid_core-0.2.2 → qbraid_core-0.2.3}/qbraid_core/services/storage/exceptions.py +0 -0
  58. {qbraid_core-0.2.2 → qbraid_core-0.2.3}/qbraid_core/services/storage/types.py +0 -0
  59. {qbraid_core-0.2.2 → qbraid_core-0.2.3}/qbraid_core/sessions.py +0 -0
  60. {qbraid_core-0.2.2 → qbraid_core-0.2.3}/qbraid_core/system/__init__.py +0 -0
  61. {qbraid_core-0.2.2 → qbraid_core-0.2.3}/qbraid_core/system/exceptions.py +0 -0
  62. {qbraid_core-0.2.2 → qbraid_core-0.2.3}/qbraid_core/system/executables.py +0 -0
  63. {qbraid_core-0.2.2 → qbraid_core-0.2.3}/qbraid_core/system/filemanager.py +0 -0
  64. {qbraid_core-0.2.2 → qbraid_core-0.2.3}/qbraid_core/system/generic.py +0 -0
  65. {qbraid_core-0.2.2 → qbraid_core-0.2.3}/qbraid_core/system/magic/__init__.py +0 -0
  66. {qbraid_core-0.2.2 → qbraid_core-0.2.3}/qbraid_core/system/magic/manager.py +0 -0
  67. {qbraid_core-0.2.2 → qbraid_core-0.2.3}/qbraid_core/system/magic/qbraid_magic.py +0 -0
  68. {qbraid_core-0.2.2 → qbraid_core-0.2.3}/qbraid_core/system/packages.py +0 -0
  69. {qbraid_core-0.2.2 → qbraid_core-0.2.3}/qbraid_core/system/versions.py +0 -0
  70. {qbraid_core-0.2.2 → qbraid_core-0.2.3}/qbraid_core.egg-info/dependency_links.txt +0 -0
  71. {qbraid_core-0.2.2 → qbraid_core-0.2.3}/qbraid_core.egg-info/requires.txt +0 -0
  72. {qbraid_core-0.2.2 → qbraid_core-0.2.3}/qbraid_core.egg-info/top_level.txt +0 -0
  73. {qbraid_core-0.2.2 → qbraid_core-0.2.3}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: qbraid-core
3
- Version: 0.2.2
3
+ Version: 0.2.3
4
4
  Summary: Python library with core abstractions for software development in the qBraid ecosystem.
5
5
  Author: qBraid Development Team
6
6
  Author-email: contact@qbraid.com
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "qbraid-core"
7
- version = "0.2.2"
7
+ version = "0.2.3"
8
8
  authors = [{name = "qBraid Development Team"}, {email = "contact@qbraid.com"}]
9
9
  description = "Python library with core abstractions for software development in the qBraid ecosystem."
10
10
  readme = "README.md"
@@ -15,6 +15,7 @@ from qbraid_core.registry import register_client
15
15
 
16
16
  from .exceptions import QuantumRuntimeServiceRequestError
17
17
  from .schemas.device import RuntimeDevice
18
+ from .schemas.group import GroupJob
18
19
  from .schemas.job import JobRequest, Program, RuntimeJob
19
20
  from .schemas.result import Result
20
21
 
@@ -183,3 +184,124 @@ class QuantumRuntimeClient(QbraidClientV1):
183
184
  raise QuantumRuntimeServiceRequestError(
184
185
  f"Failed to retrieve program for job '{job_qrn}': {err}"
185
186
  ) from err
187
+
188
+ def create_group(
189
+ self,
190
+ name: Optional[str] = None,
191
+ tags: Optional[dict[str, Any]] = None,
192
+ metadata: Optional[dict[str, Any]] = None,
193
+ max_ttl: Optional[int] = None,
194
+ ) -> GroupJob:
195
+ """Create a new group job session.
196
+
197
+ Args:
198
+ name: Optional human-readable name for the group.
199
+ tags: Optional tags for filtering/grouping.
200
+ metadata: Optional metadata dict.
201
+ max_ttl: Optional max time-to-live in seconds (1–86400).
202
+ The backend defaults to 3600 (1 hour) if not provided.
203
+
204
+ Returns:
205
+ GroupJob with status OPEN and a generated groupJobQrn.
206
+ """
207
+ body: dict[str, Any] = {}
208
+ if name is not None:
209
+ body["name"] = name
210
+ if tags is not None:
211
+ body["tags"] = tags
212
+ if metadata is not None:
213
+ body["metadata"] = metadata
214
+ if max_ttl is not None:
215
+ body["maxTTL"] = max_ttl
216
+
217
+ try:
218
+ response = self.session.post("/jobs/group", json=body)
219
+ resp_data: dict[str, Any] = response.json()["data"]
220
+ return GroupJob.model_validate(resp_data)
221
+ except RequestsApiError as err:
222
+ raise QuantumRuntimeServiceRequestError(f"Failed to create group: {err}") from err
223
+
224
+ def get_group(self, group_qrn: str) -> GroupJob:
225
+ """Retrieve group details by QRN.
226
+
227
+ Args:
228
+ group_qrn: The group job QRN.
229
+
230
+ Returns:
231
+ GroupJob with current status, counters, and job list.
232
+ """
233
+ try:
234
+ response = self.session.get(f"/jobs/group/{group_qrn}")
235
+ resp_data: dict[str, Any] = response.json()["data"]
236
+ return GroupJob.model_validate(resp_data)
237
+ except RequestsApiError as err:
238
+ raise QuantumRuntimeServiceRequestError(
239
+ f"Failed to retrieve group '{group_qrn}': {err}"
240
+ ) from err
241
+
242
+ def close_group(self, group_qrn: str) -> GroupJob:
243
+ """Close a group (no new jobs accepted, existing jobs continue).
244
+
245
+ Args:
246
+ group_qrn: The group job QRN.
247
+
248
+ Returns:
249
+ Updated GroupJob with status CLOSED.
250
+ """
251
+ try:
252
+ response = self.session.post(f"/jobs/group/{group_qrn}/close")
253
+ resp_data: dict[str, Any] = response.json()["data"]
254
+ return GroupJob.model_validate(resp_data)
255
+ except RequestsApiError as err:
256
+ raise QuantumRuntimeServiceRequestError(
257
+ f"Failed to close group '{group_qrn}': {err}"
258
+ ) from err
259
+
260
+ def cancel_group(self, group_qrn: str) -> GroupJob:
261
+ """Cancel a group and all its non-terminal jobs.
262
+
263
+ Args:
264
+ group_qrn: The group job QRN.
265
+
266
+ Returns:
267
+ Updated GroupJob with status CANCELLED.
268
+ """
269
+ try:
270
+ response = self.session.post(f"/jobs/group/{group_qrn}/cancel")
271
+ resp_data: dict[str, Any] = response.json()["data"]
272
+ return GroupJob.model_validate(resp_data)
273
+ except RequestsApiError as err:
274
+ raise QuantumRuntimeServiceRequestError(
275
+ f"Failed to cancel group '{group_qrn}': {err}"
276
+ ) from err
277
+
278
+ def list_groups(
279
+ self,
280
+ status: Optional[str] = None,
281
+ page: Optional[int] = None,
282
+ limit: Optional[int] = None,
283
+ ) -> list[GroupJob]:
284
+ """List group jobs for the current user.
285
+
286
+ Args:
287
+ status: Filter by group status (OPEN, CLOSED, COMPLETED, FAILED, CANCELLED).
288
+ page: Page number for pagination.
289
+ limit: Number of results per page.
290
+
291
+ Returns:
292
+ List of GroupJob objects.
293
+ """
294
+ params: dict[str, Any] = {}
295
+ if status is not None:
296
+ params["status"] = status
297
+ if page is not None:
298
+ params["page"] = page
299
+ if limit is not None:
300
+ params["limit"] = limit
301
+
302
+ try:
303
+ response = self.session.get("/jobs/group", params=params if params else None)
304
+ resp_data: list[dict[str, Any]] = response.json()["data"]
305
+ return [GroupJob.model_validate(group) for group in resp_data]
306
+ except RequestsApiError as err:
307
+ raise QuantumRuntimeServiceRequestError(f"Failed to list groups: {err}") from err
@@ -7,10 +7,13 @@ Pydantic schemas for the qBraid Runtime API.
7
7
 
8
8
  from .device import DevicePricing, RuntimeDevice
9
9
  from .enums import DeviceStatus, ExperimentType, JobStatus
10
+ from .group import GroupJob, GroupStatus
10
11
  from .job import JobBase, JobRequest, Program, RuntimeJob, TimeStamps
11
12
  from .result import Result
12
13
 
13
14
  __all__ = [
15
+ "GroupJob",
16
+ "GroupStatus",
14
17
  "DevicePricing",
15
18
  "RuntimeDevice",
16
19
  "DeviceStatus",
@@ -0,0 +1,91 @@
1
+ # Copyright (c) 2025, qBraid Development Team
2
+ # All rights reserved.
3
+
4
+ """
5
+ Pydantic schemas for group job API requests and responses.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ from enum import Enum
11
+ from typing import Any, Optional
12
+
13
+ from pydantic import BaseModel, Field, field_serializer
14
+
15
+ from qbraid_core.decimal import Credits
16
+
17
+ from .job import TimeStamps
18
+
19
+
20
+ class GroupStatus(str, Enum):
21
+ """Status of a group job session.
22
+
23
+ Attributes:
24
+ OPEN: Group is accepting new job submissions.
25
+ CLOSED: Group is closed for new submissions; jobs still executing.
26
+ COMPLETED: All jobs reached COMPLETED state.
27
+ FAILED: All jobs in terminal state, and at least 1 failed.
28
+ CANCELLED: Group was explicitly cancelled by the user.
29
+ """
30
+
31
+ OPEN = "OPEN"
32
+ CLOSED = "CLOSED"
33
+ COMPLETED = "COMPLETED"
34
+ FAILED = "FAILED"
35
+ CANCELLED = "CANCELLED"
36
+
37
+ @classmethod
38
+ def terminal_states(cls) -> set[GroupStatus]:
39
+ """Returns the set of terminal group statuses."""
40
+ return {cls.COMPLETED, cls.FAILED, cls.CANCELLED}
41
+
42
+
43
+ class GroupJob(BaseModel):
44
+ """Schema for group job response model.
45
+
46
+ Returned by the runtime API when creating, retrieving, or listing groups.
47
+ The SDK's GroupJobSession wraps this model.
48
+ """
49
+
50
+ groupJobQrn: str = Field(..., description="Group job resource name")
51
+ name: Optional[str] = Field(None, description="User-assigned group name")
52
+ status: GroupStatus = Field(..., description="Group status")
53
+ organizationUserId: str = Field(..., description="Organization user ID")
54
+
55
+ # Job tracking
56
+ jobCount: int = Field(0, ge=0, description="Total number of jobs in the group")
57
+ completedCount: int = Field(0, ge=0, description="Number of completed jobs")
58
+ failedCount: int = Field(0, ge=0, description="Number of failed jobs")
59
+ cancelledCount: int = Field(0, ge=0, description="Number of cancelled jobs")
60
+
61
+ # Cost aggregation
62
+ totalEstimatedCost: Optional[Credits] = Field(
63
+ None, ge=0, description="Sum of estimated costs for all jobs"
64
+ )
65
+ totalCost: Optional[Credits] = Field(
66
+ None, ge=0, description="Sum of actual costs for completed jobs"
67
+ )
68
+
69
+ # Timestamps
70
+ timeStamps: Optional[TimeStamps] = Field(None, description="Group timestamps")
71
+
72
+ # TTL
73
+ maxTTL: Optional[int] = Field(
74
+ None, ge=1, le=86400, description="Max time-to-live in seconds (1s – 86400s / 24h)"
75
+ )
76
+
77
+ # User metadata
78
+ tags: dict[str, Any] = Field(default_factory=dict, description="User-defined tags")
79
+ metadata: dict[str, Any] = Field(default_factory=dict, description="Additional metadata")
80
+
81
+ @field_serializer("totalEstimatedCost", "totalCost")
82
+ def serialize_credits(self, value: Optional[Credits]) -> Optional[float]:
83
+ """Serialize Credits to float for JSON response."""
84
+ if value is None:
85
+ return None
86
+ return float(value)
87
+
88
+ @field_serializer("status")
89
+ def serialize_status(self, value: GroupStatus) -> str:
90
+ """Serialize GroupStatus enum to its string value."""
91
+ return value.value
@@ -11,7 +11,13 @@ import sys
11
11
  from datetime import datetime
12
12
  from typing import Any, Literal, Optional, Union
13
13
 
14
- from pydantic import BaseModel, Field, field_serializer, field_validator, model_validator
14
+ from pydantic import (
15
+ BaseModel,
16
+ Field,
17
+ field_serializer,
18
+ field_validator,
19
+ model_validator,
20
+ )
15
21
 
16
22
  from qbraid_core.decimal import Credits
17
23
 
@@ -78,6 +84,7 @@ class JobBase(BaseModel):
78
84
  deviceQrn: str = Field(..., description="qBraid device resource name")
79
85
  tags: dict[str, Union[str, int, bool]] = Field(default_factory=dict, description="Job tags")
80
86
  runtimeOptions: dict[str, Any] = Field(default_factory=dict, description="Runtime options")
87
+ groupJobQrn: Optional[str] = Field(None, description="Group job resource name")
81
88
 
82
89
 
83
90
  class JobRequest(JobBase):
@@ -90,7 +97,6 @@ class RuntimeJob(JobBase):
90
97
  """Schema for runtime job model"""
91
98
 
92
99
  jobQrn: str = Field(..., description="qBraid job resource name")
93
- batchJobQrn: Optional[str] = Field(None, description="Batch job resource name")
94
100
  vendor: Literal["aws", "azure", "ibm", "ionq", "rigetti", "qbraid"] = Field(
95
101
  ..., description="Vendor name"
96
102
  )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: qbraid-core
3
- Version: 0.2.2
3
+ Version: 0.2.3
4
4
  Summary: Python library with core abstractions for software development in the qBraid ecosystem.
5
5
  Author: qBraid Development Team
6
6
  Author-email: contact@qbraid.com
@@ -52,6 +52,7 @@ qbraid_core/services/runtime/exceptions.py
52
52
  qbraid_core/services/runtime/schemas/__init__.py
53
53
  qbraid_core/services/runtime/schemas/device.py
54
54
  qbraid_core/services/runtime/schemas/enums.py
55
+ qbraid_core/services/runtime/schemas/group.py
55
56
  qbraid_core/services/runtime/schemas/job.py
56
57
  qbraid_core/services/runtime/schemas/result.py
57
58
  qbraid_core/services/storage/__init__.py
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes