qctrl-workflow-client 5.1.2__tar.gz → 5.3.0__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.
@@ -1,8 +1,7 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.3
2
2
  Name: qctrl-workflow-client
3
- Version: 5.1.2
3
+ Version: 5.3.0
4
4
  Summary: Q-CTRL Workflow Client
5
- Home-page: https://q-ctrl.com
6
5
  License: https://q-ctrl.com/terms
7
6
  Keywords: black opal,boulder opal,fire opal,nisq,open controls,q control,q ctrl,q-control,q-ctrl,qcontrol,qctrl,quantum,quantum algorithms,quantum circuits,quantum coding,quantum coding software,quantum computing,quantum control,quantum control software,quantum control theory,quantum engineering,quantum error correction,quantum firmware,quantum fundamentals,quantum sensing,qubit,qudit
8
7
  Author: Q-CTRL
@@ -35,10 +34,11 @@ Requires-Dist: qctrl-client (>=10.1.0,<11.0.0)
35
34
  Requires-Dist: qctrl-commons (==23.3.0)
36
35
  Requires-Dist: requests (>=2.32.0,<3.0.0)
37
36
  Requires-Dist: tenacity (>=8.1.0,<9.0.0)
38
- Requires-Dist: tomli (>=2.0.1,<3.0.0)
37
+ Requires-Dist: tomli (>=2.2.1,<3.0.0)
39
38
  Project-URL: Documentation, https://docs.q-ctrl.com
40
39
  Project-URL: Facebook, https://www.facebook.com/qctrl
41
40
  Project-URL: GitHub, https://github.com/qctrl
41
+ Project-URL: Homepage, https://q-ctrl.com
42
42
  Project-URL: LinkedIn, https://www.linkedin.com/company/q-ctrl/
43
43
  Project-URL: X, https://x.com/qctrlHQ
44
44
  Project-URL: YouTube, https://www.youtube.com/qctrl
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "qctrl-workflow-client"
3
- version = "5.1.2"
3
+ version = "5.3.0"
4
4
  description = "Q-CTRL Workflow Client"
5
5
  license = "https://q-ctrl.com/terms"
6
6
  authors = ["Q-CTRL <support@q-ctrl.com>"]
@@ -75,7 +75,7 @@ priority = "supplemental"
75
75
 
76
76
  [tool.poetry.dependencies]
77
77
  python = ">=3.9, <3.13"
78
- tomli = "^2.0.1"
78
+ tomli = "^2.2.1"
79
79
  importlib-metadata = "^6.8.0"
80
80
  gql = "^3.4.0"
81
81
  tenacity = "^8.1.0"
@@ -85,15 +85,15 @@ qctrl-commons = { version = "23.3.0", source = "PyPI" }
85
85
  qctrl-client = { version = "^10.1.0", source = "PyPI" }
86
86
 
87
87
  [tool.poetry.group.dev.dependencies]
88
- black = "^24.3.0"
89
- isort = "^5.12.0"
90
- pre-commit = "^3.3.3"
91
- pylint = "^3.2.2"
92
- pytest = "^7.2.2"
93
- pytest-cov = "^4.0.0"
88
+ black = "^25.1.0"
89
+ isort = "^6.0.0"
90
+ pre-commit = "^4.1.0"
91
+ pylint = "^3.3.4"
92
+ pytest = "^8.3.4"
93
+ pytest-cov = "^6.0.0"
94
94
  pytest-mock = "^3.10.0"
95
95
  pytest-xdist = "^3.2.1"
96
- qctrl-core-workflow-manager = "^4.0.0"
96
+ qctrl-core-workflow-manager = "^5.0.0"
97
97
 
98
98
  [tool.isort]
99
99
  profile = "black"
@@ -1,4 +1,4 @@
1
- # Copyright 2024 Q-CTRL. All rights reserved.
1
+ # Copyright 2025 Q-CTRL. All rights reserved.
2
2
  #
3
3
  # Licensed under the Q-CTRL Terms of service (the "License"). Unauthorized
4
4
  # copying or use of this file, via any medium, is strictly prohibited.
@@ -11,7 +11,7 @@
11
11
  # distributed under the License is distributed on an "AS IS" BASIS. See the
12
12
  # License for the specific language.
13
13
 
14
- __version__ = "5.1.2"
14
+ __version__ = "5.3.0"
15
15
 
16
16
  from .defaults import get_authenticated_client_for_product
17
17
  from .functions import (
@@ -1,4 +1,4 @@
1
- # Copyright 2024 Q-CTRL. All rights reserved.
1
+ # Copyright 2025 Q-CTRL. All rights reserved.
2
2
  #
3
3
  # Licensed under the Q-CTRL Terms of service (the "License"). Unauthorized
4
4
  # copying or use of this file, via any medium, is strictly prohibited.
@@ -1,4 +1,4 @@
1
- # Copyright 2024 Q-CTRL. All rights reserved.
1
+ # Copyright 2025 Q-CTRL. All rights reserved.
2
2
  #
3
3
  # Licensed under the Q-CTRL Terms of service (the "License"). Unauthorized
4
4
  # copying or use of this file, via any medium, is strictly prohibited.
@@ -26,7 +26,10 @@ from qctrlworkflowclient.router.api import ApiRouter
26
26
 
27
27
 
28
28
  def core_workflow(
29
- get_config: Callable, workflow: str, formatter: Optional[Callable] = None
29
+ get_config: Callable,
30
+ workflow: str,
31
+ formatter: Optional[Callable] = None,
32
+ registry_selector: Optional[Callable] = None,
30
33
  ):
31
34
  """
32
35
  Decorator for a function which will execute a workflow.
@@ -55,6 +58,12 @@ def core_workflow(
55
58
  result. The callable should accept exactly one argument
56
59
  which is the raw result fo the workflow. If used, the
57
60
  decorated function will return the result of this callable.
61
+ registry_selector : Callable, optional
62
+ Optional callable which can be used to select the registry
63
+ to be used for the workflow. The callable should accept
64
+ exactly one argument which is the data returned by the
65
+ decorated function. If used, the decorated function will
66
+ return the result of this callable.
58
67
  """
59
68
 
60
69
  def decorator(func: Callable):
@@ -70,7 +79,16 @@ def core_workflow(
70
79
  router.set_async_state(kwargs.pop("is_async", False))
71
80
 
72
81
  data = func(*args, **kwargs)
73
- result = router(workflow, data)
82
+
83
+ # dynamically select the registry to be used if selector provided
84
+ # otherwise the default registry set in the router will be used
85
+ registry = registry_selector(data) if registry_selector else None
86
+
87
+ # if the router is an instance of the ApiRouter, pass the registry
88
+ if isinstance(router, ApiRouter):
89
+ result = router(workflow, data, registry=registry)
90
+ else:
91
+ result = router(workflow, data)
74
92
 
75
93
  if formatter:
76
94
  result = formatter(result)
@@ -83,7 +101,10 @@ def core_workflow(
83
101
 
84
102
 
85
103
  def async_core_workflow(
86
- get_config: Callable, workflow: str, formatter: Optional[Callable] = None
104
+ get_config: Callable,
105
+ workflow: str,
106
+ formatter: Optional[Callable] = None,
107
+ registry_selector: Optional[Callable] = None,
87
108
  ):
88
109
  """
89
110
  Decorator for a function which will execute asynchronously workflow.
@@ -112,6 +133,12 @@ def async_core_workflow(
112
133
  result. The callable should accept exactly one argument
113
134
  which is the raw result fo the workflow. If used, the
114
135
  decorated function will return the result of this callable.
136
+ registry_selector : Callable, optional
137
+ Optional callable which can be used to select the registry
138
+ to be used for the workflow. The callable should accept
139
+ exactly one argument which is the data returned by the
140
+ decorated function. If used, the decorated function will
141
+ return the result of this callable.
115
142
  """
116
143
 
117
144
  def decorator(func: Callable):
@@ -132,7 +159,16 @@ def async_core_workflow(
132
159
  )
133
160
 
134
161
  data = func(*args, **kwargs)
135
- result = router(workflow, data)
162
+
163
+ # dynamically select the registry to be used if selector provided
164
+ # otherwise the default registry set in the router will be used
165
+ registry = registry_selector(data) if registry_selector else None
166
+
167
+ # if the router is an instance of the ApiRouter, pass the registry
168
+ if isinstance(router, ApiRouter):
169
+ result = router(workflow, data, registry=registry)
170
+ else:
171
+ result = router(workflow, data)
136
172
 
137
173
  if formatter:
138
174
  result = formatter(result)
@@ -1,4 +1,4 @@
1
- # Copyright 2024 Q-CTRL. All rights reserved.
1
+ # Copyright 2025 Q-CTRL. All rights reserved.
2
2
  #
3
3
  # Licensed under the Q-CTRL Terms of service (the "License"). Unauthorized
4
4
  # copying or use of this file, via any medium, is strictly prohibited.
@@ -1,4 +1,4 @@
1
- # Copyright 2024 Q-CTRL. All rights reserved.
1
+ # Copyright 2025 Q-CTRL. All rights reserved.
2
2
  #
3
3
  # Licensed under the Q-CTRL Terms of service (the "License"). Unauthorized
4
4
  # copying or use of this file, via any medium, is strictly prohibited.
@@ -1,4 +1,4 @@
1
- # Copyright 2024 Q-CTRL. All rights reserved.
1
+ # Copyright 2025 Q-CTRL. All rights reserved.
2
2
  #
3
3
  # Licensed under the Q-CTRL Terms of service (the "License"). Unauthorized
4
4
  # copying or use of this file, via any medium, is strictly prohibited.
@@ -40,6 +40,7 @@ from tenacity import (
40
40
  wait_fixed,
41
41
  )
42
42
 
43
+ from qctrlworkflowclient.products import Product
43
44
  from qctrlworkflowclient.settings import CoreClientSettings
44
45
  from qctrlworkflowclient.utils import get_installed_version
45
46
 
@@ -340,7 +341,19 @@ class ApiRouter(BaseRouter):
340
341
  self._parallel_task_collector = collector
341
342
  return collector
342
343
 
343
- def __call__(self, workflow, data=None):
344
+ def __call__(self, workflow, data=None, registry=None):
345
+ """
346
+ Executes the workflow through the API.
347
+
348
+ Parameters
349
+ ----------
350
+ workflow : str
351
+ Name of the workflow to be executed.
352
+ data : Dict[str, Any], optional
353
+ Any data required by the workflow for execution.
354
+ registry : str, optional
355
+ The registry to be used for the workflow execution.
356
+ """
344
357
  query = gql.gql(
345
358
  """
346
359
  mutation ($input: StartCoreWorkflowInput!) {
@@ -367,8 +380,13 @@ class ApiRouter(BaseRouter):
367
380
  )
368
381
 
369
382
  client_metadata = self._get_client_metadata()
383
+
384
+ # if registry is not provided, use the default registry
385
+ if registry is None:
386
+ registry = self._settings.product.value.registry
387
+
370
388
  input_ = {
371
- "registry": self._settings.product.value.registry,
389
+ "registry": registry,
372
390
  "workflow": workflow,
373
391
  "data": json.dumps(data, cls=DataTypeEncoder),
374
392
  "clientMetadata": json.dumps(client_metadata),
@@ -501,6 +519,13 @@ class ApiRouter(BaseRouter):
501
519
  action = self._poll_for_completion(action)
502
520
  except KeyboardInterrupt as exc:
503
521
  if revoke_on_interrupt:
522
+ if self._settings.product == Product.BOULDER_OPAL:
523
+ warn(
524
+ "Keyboard interrupts will not cancel remote jobs in the future. "
525
+ "To cancel a job, use the BoulderOpalJob.cancel() method instead.",
526
+ category=FutureWarning,
527
+ stacklevel=2,
528
+ )
504
529
  self._revoke_action(action)
505
530
  action = self._poll_for_completion(action)
506
531
  else:
@@ -1,4 +1,4 @@
1
- # Copyright 2024 Q-CTRL. All rights reserved.
1
+ # Copyright 2025 Q-CTRL. All rights reserved.
2
2
  #
3
3
  # Licensed under the Q-CTRL Terms of service (the "License"). Unauthorized
4
4
  # copying or use of this file, via any medium, is strictly prohibited.
@@ -15,11 +15,7 @@ from abc import (
15
15
  ABC,
16
16
  abstractmethod,
17
17
  )
18
- from typing import (
19
- Any,
20
- Dict,
21
- Optional,
22
- )
18
+ from typing import Any
23
19
 
24
20
 
25
21
  class BaseRouter(ABC):
@@ -28,15 +24,12 @@ class BaseRouter(ABC):
28
24
  """
29
25
 
30
26
  @abstractmethod
31
- def __call__(self, workflow: str, data: Optional[Dict[str, Any]] = None) -> Any:
27
+ def __call__(
28
+ self,
29
+ *args,
30
+ **kwargs,
31
+ ) -> Any:
32
32
  """
33
33
  Given a workflow name and the corresponding data (if any),
34
34
  execute the workflow and returns the raw result.
35
-
36
- Parameters
37
- ----------
38
- workflow : str
39
- Name of the workflow to be executed.
40
- data : Dict[str, Any], optional
41
- Any data required by the workflow for execution.
42
35
  """
@@ -1,4 +1,4 @@
1
- # Copyright 2024 Q-CTRL. All rights reserved.
1
+ # Copyright 2025 Q-CTRL. All rights reserved.
2
2
  #
3
3
  # Licensed under the Q-CTRL Terms of service (the "License"). Unauthorized
4
4
  # copying or use of this file, via any medium, is strictly prohibited.
@@ -30,6 +30,16 @@ class LocalRouter(BaseRouter):
30
30
  self._resolver = resolver
31
31
 
32
32
  def __call__(self, workflow, data=None):
33
+ """
34
+ Executes the workflow locally.
35
+
36
+ Parameters
37
+ ----------
38
+ workflow : str
39
+ Name of the workflow to be executed.
40
+ data : Dict[str, Any], optional
41
+ Any data required by the workflow for execution.
42
+ """
33
43
  data = data or {}
34
44
  task = self._resolver.get_workflow_task_from_signature(workflow, **data)
35
45
  func = self._resolver(task)
@@ -1,4 +1,4 @@
1
- # Copyright 2024 Q-CTRL. All rights reserved.
1
+ # Copyright 2025 Q-CTRL. All rights reserved.
2
2
  #
3
3
  # Licensed under the Q-CTRL Terms of service (the "License"). Unauthorized
4
4
  # copying or use of this file, via any medium, is strictly prohibited.
@@ -1,4 +1,4 @@
1
- # Copyright 2024 Q-CTRL. All rights reserved.
1
+ # Copyright 2025 Q-CTRL. All rights reserved.
2
2
  #
3
3
  # Licensed under the Q-CTRL Terms of service (the "License"). Unauthorized
4
4
  # copying or use of this file, via any medium, is strictly prohibited.