quapp-common 0.0.12.dev15__tar.gz → 0.0.13.dev2__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 (89) hide show
  1. {quapp_common-0.0.12.dev15/quapp_common.egg-info → quapp_common-0.0.13.dev2}/PKG-INFO +53 -10
  2. {quapp_common-0.0.12.dev15 → quapp_common-0.0.13.dev2}/README.md +52 -9
  3. {quapp_common-0.0.12.dev15 → quapp_common-0.0.13.dev2}/pyproject.toml +1 -1
  4. {quapp_common-0.0.12.dev15 → quapp_common-0.0.13.dev2}/quapp_common/component/circuit_adapter.py +23 -5
  5. {quapp_common-0.0.12.dev15 → quapp_common-0.0.13.dev2}/quapp_common/component/dispatcher.py +6 -3
  6. {quapp_common-0.0.12.dev15 → quapp_common-0.0.13.dev2/quapp_common.egg-info}/PKG-INFO +53 -10
  7. {quapp_common-0.0.12.dev15 → quapp_common-0.0.13.dev2}/LICENSE +0 -0
  8. {quapp_common-0.0.12.dev15 → quapp_common-0.0.13.dev2}/quapp_common/__init__.py +0 -0
  9. {quapp_common-0.0.12.dev15 → quapp_common-0.0.13.dev2}/quapp_common/async_tasks/__init__.py +0 -0
  10. {quapp_common-0.0.12.dev15 → quapp_common-0.0.13.dev2}/quapp_common/async_tasks/async_invocation_task.py +0 -0
  11. {quapp_common-0.0.12.dev15 → quapp_common-0.0.13.dev2}/quapp_common/async_tasks/async_task.py +0 -0
  12. {quapp_common-0.0.12.dev15 → quapp_common-0.0.13.dev2}/quapp_common/async_tasks/export_circuit_task.py +0 -0
  13. {quapp_common-0.0.12.dev15 → quapp_common-0.0.13.dev2}/quapp_common/async_tasks/post_processing_task.py +0 -0
  14. {quapp_common-0.0.12.dev15 → quapp_common-0.0.13.dev2}/quapp_common/component/__init__.py +0 -0
  15. {quapp_common-0.0.12.dev15 → quapp_common-0.0.13.dev2}/quapp_common/component/backend/__init__.py +0 -0
  16. {quapp_common-0.0.12.dev15 → quapp_common-0.0.13.dev2}/quapp_common/component/backend/invocation.py +0 -0
  17. {quapp_common-0.0.12.dev15 → quapp_common-0.0.13.dev2}/quapp_common/component/backend/job_fetcher.py +0 -0
  18. {quapp_common-0.0.12.dev15 → quapp_common-0.0.13.dev2}/quapp_common/component/backend/job_fetching.py +0 -0
  19. {quapp_common-0.0.12.dev15 → quapp_common-0.0.13.dev2}/quapp_common/component/backend/job_manager.py +0 -0
  20. {quapp_common-0.0.12.dev15 → quapp_common-0.0.13.dev2}/quapp_common/component/bridge.py +0 -0
  21. {quapp_common-0.0.12.dev15 → quapp_common-0.0.13.dev2}/quapp_common/component/callback/__init__.py +0 -0
  22. {quapp_common-0.0.12.dev15 → quapp_common-0.0.13.dev2}/quapp_common/component/callback/update_job_metadata.py +0 -0
  23. {quapp_common-0.0.12.dev15 → quapp_common-0.0.13.dev2}/quapp_common/component/device/__init__.py +0 -0
  24. {quapp_common-0.0.12.dev15 → quapp_common-0.0.13.dev2}/quapp_common/component/device/device_selection.py +0 -0
  25. {quapp_common-0.0.12.dev15 → quapp_common-0.0.13.dev2}/quapp_common/component/result_serializer.py +0 -0
  26. {quapp_common-0.0.12.dev15 → quapp_common-0.0.13.dev2}/quapp_common/config/__init__.py +0 -0
  27. {quapp_common-0.0.12.dev15 → quapp_common-0.0.13.dev2}/quapp_common/config/logging_config.py +0 -0
  28. {quapp_common-0.0.12.dev15 → quapp_common-0.0.13.dev2}/quapp_common/config/thread_config.py +0 -0
  29. {quapp_common-0.0.12.dev15 → quapp_common-0.0.13.dev2}/quapp_common/data/__init__.py +0 -0
  30. {quapp_common-0.0.12.dev15 → quapp_common-0.0.13.dev2}/quapp_common/data/async_task/__init__.py +0 -0
  31. {quapp_common-0.0.12.dev15 → quapp_common-0.0.13.dev2}/quapp_common/data/async_task/circuit_export/__init__.py +0 -0
  32. {quapp_common-0.0.12.dev15 → quapp_common-0.0.13.dev2}/quapp_common/data/async_task/circuit_export/backend_holder.py +0 -0
  33. {quapp_common-0.0.12.dev15 → quapp_common-0.0.13.dev2}/quapp_common/data/async_task/circuit_export/circuit_holder.py +0 -0
  34. {quapp_common-0.0.12.dev15 → quapp_common-0.0.13.dev2}/quapp_common/data/backend/__init__.py +0 -0
  35. {quapp_common-0.0.12.dev15 → quapp_common-0.0.13.dev2}/quapp_common/data/backend/backend_information.py +0 -0
  36. {quapp_common-0.0.12.dev15 → quapp_common-0.0.13.dev2}/quapp_common/data/callback/__init__.py +0 -0
  37. {quapp_common-0.0.12.dev15 → quapp_common-0.0.13.dev2}/quapp_common/data/callback/callback_url.py +0 -0
  38. {quapp_common-0.0.12.dev15 → quapp_common-0.0.13.dev2}/quapp_common/data/device/__init__.py +0 -0
  39. {quapp_common-0.0.12.dev15 → quapp_common-0.0.13.dev2}/quapp_common/data/device/circuit_running_option.py +0 -0
  40. {quapp_common-0.0.12.dev15 → quapp_common-0.0.13.dev2}/quapp_common/data/promise/__init__.py +0 -0
  41. {quapp_common-0.0.12.dev15 → quapp_common-0.0.13.dev2}/quapp_common/data/promise/post_processing_promise.py +0 -0
  42. {quapp_common-0.0.12.dev15 → quapp_common-0.0.13.dev2}/quapp_common/data/promise/promise.py +0 -0
  43. {quapp_common-0.0.12.dev15 → quapp_common-0.0.13.dev2}/quapp_common/data/request/__init__.py +0 -0
  44. {quapp_common-0.0.12.dev15 → quapp_common-0.0.13.dev2}/quapp_common/data/request/invocation_request.py +0 -0
  45. {quapp_common-0.0.12.dev15 → quapp_common-0.0.13.dev2}/quapp_common/data/request/job_fetching_request.py +0 -0
  46. {quapp_common-0.0.12.dev15 → quapp_common-0.0.13.dev2}/quapp_common/data/request/request.py +0 -0
  47. {quapp_common-0.0.12.dev15 → quapp_common-0.0.13.dev2}/quapp_common/data/response/__init__.py +0 -0
  48. {quapp_common-0.0.12.dev15 → quapp_common-0.0.13.dev2}/quapp_common/data/response/authentication.py +0 -0
  49. {quapp_common-0.0.12.dev15 → quapp_common-0.0.13.dev2}/quapp_common/data/response/custom_header.py +0 -0
  50. {quapp_common-0.0.12.dev15 → quapp_common-0.0.13.dev2}/quapp_common/data/response/job_response.py +0 -0
  51. {quapp_common-0.0.12.dev15 → quapp_common-0.0.13.dev2}/quapp_common/enum/__init__.py +0 -0
  52. {quapp_common-0.0.12.dev15 → quapp_common-0.0.13.dev2}/quapp_common/enum/base_enum.py +0 -0
  53. {quapp_common-0.0.12.dev15 → quapp_common-0.0.13.dev2}/quapp_common/enum/http_header.py +0 -0
  54. {quapp_common-0.0.12.dev15 → quapp_common-0.0.13.dev2}/quapp_common/enum/invocation_step.py +0 -0
  55. {quapp_common-0.0.12.dev15 → quapp_common-0.0.13.dev2}/quapp_common/enum/language.py +0 -0
  56. {quapp_common-0.0.12.dev15 → quapp_common-0.0.13.dev2}/quapp_common/enum/media_type.py +0 -0
  57. {quapp_common-0.0.12.dev15 → quapp_common-0.0.13.dev2}/quapp_common/enum/processing_unit.py +0 -0
  58. {quapp_common-0.0.12.dev15 → quapp_common-0.0.13.dev2}/quapp_common/enum/provider_tag.py +0 -0
  59. {quapp_common-0.0.12.dev15 → quapp_common-0.0.13.dev2}/quapp_common/enum/sdk.py +0 -0
  60. {quapp_common-0.0.12.dev15 → quapp_common-0.0.13.dev2}/quapp_common/enum/status/__init__.py +0 -0
  61. {quapp_common-0.0.12.dev15 → quapp_common-0.0.13.dev2}/quapp_common/enum/status/job_status.py +0 -0
  62. {quapp_common-0.0.12.dev15 → quapp_common-0.0.13.dev2}/quapp_common/enum/status/status_code.py +0 -0
  63. {quapp_common-0.0.12.dev15 → quapp_common-0.0.13.dev2}/quapp_common/enum/token_type.py +0 -0
  64. {quapp_common-0.0.12.dev15 → quapp_common-0.0.13.dev2}/quapp_common/factory/__init__.py +0 -0
  65. {quapp_common-0.0.12.dev15 → quapp_common-0.0.13.dev2}/quapp_common/factory/device_factory.py +0 -0
  66. {quapp_common-0.0.12.dev15 → quapp_common-0.0.13.dev2}/quapp_common/factory/handler_factory.py +0 -0
  67. {quapp_common-0.0.12.dev15 → quapp_common-0.0.13.dev2}/quapp_common/factory/provider_factory.py +0 -0
  68. {quapp_common-0.0.12.dev15 → quapp_common-0.0.13.dev2}/quapp_common/handler/__init__.py +0 -0
  69. {quapp_common-0.0.12.dev15 → quapp_common-0.0.13.dev2}/quapp_common/handler/handler.py +0 -0
  70. {quapp_common-0.0.12.dev15 → quapp_common-0.0.13.dev2}/quapp_common/model/__init__.py +0 -0
  71. {quapp_common-0.0.12.dev15 → quapp_common-0.0.13.dev2}/quapp_common/model/device/__init__.py +0 -0
  72. {quapp_common-0.0.12.dev15 → quapp_common-0.0.13.dev2}/quapp_common/model/device/custom_device.py +0 -0
  73. {quapp_common-0.0.12.dev15 → quapp_common-0.0.13.dev2}/quapp_common/model/device/device.py +0 -0
  74. {quapp_common-0.0.12.dev15 → quapp_common-0.0.13.dev2}/quapp_common/model/invocation.py +0 -0
  75. {quapp_common-0.0.12.dev15 → quapp_common-0.0.13.dev2}/quapp_common/model/provider/__init__.py +0 -0
  76. {quapp_common-0.0.12.dev15 → quapp_common-0.0.13.dev2}/quapp_common/model/provider/provider.py +0 -0
  77. {quapp_common-0.0.12.dev15 → quapp_common-0.0.13.dev2}/quapp_common/util/__init__.py +0 -0
  78. {quapp_common-0.0.12.dev15 → quapp_common-0.0.13.dev2}/quapp_common/util/file_utils.py +0 -0
  79. {quapp_common-0.0.12.dev15 → quapp_common-0.0.13.dev2}/quapp_common/util/http_utils.py +0 -0
  80. {quapp_common-0.0.12.dev15 → quapp_common-0.0.13.dev2}/quapp_common/util/json_parser_utils.py +0 -0
  81. {quapp_common-0.0.12.dev15 → quapp_common-0.0.13.dev2}/quapp_common/util/response_utils.py +0 -0
  82. {quapp_common-0.0.12.dev15 → quapp_common-0.0.13.dev2}/quapp_common.egg-info/SOURCES.txt +0 -0
  83. {quapp_common-0.0.12.dev15 → quapp_common-0.0.13.dev2}/quapp_common.egg-info/dependency_links.txt +0 -0
  84. {quapp_common-0.0.12.dev15 → quapp_common-0.0.13.dev2}/quapp_common.egg-info/requires.txt +0 -0
  85. {quapp_common-0.0.12.dev15 → quapp_common-0.0.13.dev2}/quapp_common.egg-info/top_level.txt +0 -0
  86. {quapp_common-0.0.12.dev15 → quapp_common-0.0.13.dev2}/setup.cfg +0 -0
  87. {quapp_common-0.0.12.dev15 → quapp_common-0.0.13.dev2}/tests/test_circuit_adapter.py +0 -0
  88. {quapp_common-0.0.12.dev15 → quapp_common-0.0.13.dev2}/tests/test_json_parser_utils.py +0 -0
  89. {quapp_common-0.0.12.dev15 → quapp_common-0.0.13.dev2}/tests/test_result_serializer.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: quapp-common
3
- Version: 0.0.12.dev15
3
+ Version: 0.0.13.dev2
4
4
  Summary: Quapp common library supporting Quapp Platform for Quantum Computing
5
5
  Author-email: "CITYNOW Co. Ltd. " <corp@citynow.vn>
6
6
  License: The MIT License (MIT)
@@ -80,15 +80,22 @@ responses while work continues in the background.
80
80
  - Multi-language SDK support:
81
81
  - Language enum for validating and resolving Python, JavaScript, and Q#
82
82
  runtimes.
83
- - SubprocessDispatcher to delegate tasks to non-Python runtimes via
84
- subprocess with timeout management and JSON payload processing; supports
85
- Node.js and `dotnet run` (Q#) runners.
86
- - SubprocessBridge integrating dispatcher, circuit adapter, and result
87
- serializer for seamless JS-Python handler interaction.
88
- - CircuitAdapter for converting JS subprocess circuit outputs into native
89
- SDK formats (OpenQASM, QUBO, JSON) across Qiskit, Braket, PennyLane, etc.
90
- - ResultSerializer for converting complex job results into JSON-serializable
91
- dictionaries for subprocess communication.
83
+ - Standalone `dispatch()` function (formerly `SubprocessDispatcher` class)
84
+ to delegate tasks to non-Python runtimes via subprocess with timeout
85
+ management and JSON payload processing; supports Node.js and precompiled
86
+ Q# binary (`./handler_runner_bin/Function[.exe]`) runners.
87
+ - Working directory configurable via `QUAPP_WORKING_DIR` environment
88
+ variable; falls back to `os.getcwd()` when unset.
89
+ - `SubprocessBridge` class integrating standalone dispatcher, circuit
90
+ adapter, and result serializer for seamless JS/Q#-Python handler
91
+ interaction.
92
+ - Standalone `adapt()` function (formerly `CircuitAdapter` class) for
93
+ converting subprocess circuit outputs into native SDK formats (OpenQASM,
94
+ QUBO, JSON) across Qiskit, Braket, PennyLane, PyQuil, Qibo, Qulacs, and
95
+ CUDA Quantum.
96
+ - Standalone `serialize()` function (formerly `ResultSerializer` class) for
97
+ converting complex job results into JSON-serializable dictionaries for
98
+ subprocess communication.
92
99
 
93
100
  ## Installation
94
101
 
@@ -107,6 +114,42 @@ Notes:
107
114
 
108
115
  ## Recently Changes Highlights
109
116
 
117
+ ### v0.0.13.dev2
118
+ - Fix: `_openqasm_to_braket` in `circuit_adapter.py` now injects a default
119
+ `Probability` result type when the Braket circuit produced by `tk_to_braket`
120
+ has no result types. OpenQASM circuits submitted from non-Python runtimes (e.g.
121
+ Q#) do not carry explicit measurement annotations, so the converted Braket
122
+ circuit would have an empty `result_types` list and fail at execution time. The
123
+ fix adds `circuit.probability(target=list(range(circuit.qubit_count)))` before
124
+ returning, ensuring every Braket job has at least one result type.
125
+
126
+ ### v0.0.13.dev1
127
+ - Refactor: Replace class-based subprocess components with standalone
128
+ module-level functions for simpler imports and testability:
129
+ - `SubprocessDispatcher` class → `dispatch()` and `is_subprocess_language()`
130
+ in `dispatcher.py`.
131
+ - `CircuitAdapter` class → `adapt()` and private helper functions in
132
+ `circuit_adapter.py`.
133
+ - `ResultSerializer` class → `serialize()` in `result_serializer.py`.
134
+ - `SubprocessBridge` retains its class form but delegates internally to the
135
+ new standalone functions.
136
+ - Refactor `dispatcher.py`: `WORKING_DIR` is now read from the
137
+ `QUAPP_WORKING_DIR` environment variable (previously hardcoded `None`);
138
+ falls back to `os.getcwd()` when the variable is unset.
139
+ - Refactor `dispatcher.py`: Q# runner command changed from
140
+ `dotnet run --project HandlerRunner.csproj` to a precompiled
141
+ platform-specific binary — `./handler_runner_bin/Function.exe` on Windows
142
+ and `./handler_runner_bin/Function` on other platforms — eliminating the
143
+ `dotnet` toolchain requirement at runtime.
144
+ - Refactor `circuit_adapter.py`: Extract `_load_qasm_circuit(qasm_str)` private
145
+ utility that centralises OpenQASM 2.0 string parsing with Qiskit version
146
+ compatibility — uses `qiskit.qasm2.loads` (Qiskit >= 1.0) and falls back to
147
+ `QiskitCircuit.from_qasm_str` (Qiskit < 1.0).
148
+ - Fix: `subprocess.run` now passes `check=True` so a non-zero exit code raises
149
+ `CalledProcessError` before the manual return-code branch is reached.
150
+ - Add unit tests: `tests/test_circuit_adapter.py`,
151
+ `tests/test_json_parser_utils.py`, `tests/test_result_serializer.py`.
152
+
110
153
  ### v0.0.12.dev15
111
154
  - Extend multi-language SDK support with Q# (QSharp) runtime:
112
155
  - Add `QSHARP` to `Language` enum.
@@ -39,15 +39,22 @@ responses while work continues in the background.
39
39
  - Multi-language SDK support:
40
40
  - Language enum for validating and resolving Python, JavaScript, and Q#
41
41
  runtimes.
42
- - SubprocessDispatcher to delegate tasks to non-Python runtimes via
43
- subprocess with timeout management and JSON payload processing; supports
44
- Node.js and `dotnet run` (Q#) runners.
45
- - SubprocessBridge integrating dispatcher, circuit adapter, and result
46
- serializer for seamless JS-Python handler interaction.
47
- - CircuitAdapter for converting JS subprocess circuit outputs into native
48
- SDK formats (OpenQASM, QUBO, JSON) across Qiskit, Braket, PennyLane, etc.
49
- - ResultSerializer for converting complex job results into JSON-serializable
50
- dictionaries for subprocess communication.
42
+ - Standalone `dispatch()` function (formerly `SubprocessDispatcher` class)
43
+ to delegate tasks to non-Python runtimes via subprocess with timeout
44
+ management and JSON payload processing; supports Node.js and precompiled
45
+ Q# binary (`./handler_runner_bin/Function[.exe]`) runners.
46
+ - Working directory configurable via `QUAPP_WORKING_DIR` environment
47
+ variable; falls back to `os.getcwd()` when unset.
48
+ - `SubprocessBridge` class integrating standalone dispatcher, circuit
49
+ adapter, and result serializer for seamless JS/Q#-Python handler
50
+ interaction.
51
+ - Standalone `adapt()` function (formerly `CircuitAdapter` class) for
52
+ converting subprocess circuit outputs into native SDK formats (OpenQASM,
53
+ QUBO, JSON) across Qiskit, Braket, PennyLane, PyQuil, Qibo, Qulacs, and
54
+ CUDA Quantum.
55
+ - Standalone `serialize()` function (formerly `ResultSerializer` class) for
56
+ converting complex job results into JSON-serializable dictionaries for
57
+ subprocess communication.
51
58
 
52
59
  ## Installation
53
60
 
@@ -66,6 +73,42 @@ Notes:
66
73
 
67
74
  ## Recently Changes Highlights
68
75
 
76
+ ### v0.0.13.dev2
77
+ - Fix: `_openqasm_to_braket` in `circuit_adapter.py` now injects a default
78
+ `Probability` result type when the Braket circuit produced by `tk_to_braket`
79
+ has no result types. OpenQASM circuits submitted from non-Python runtimes (e.g.
80
+ Q#) do not carry explicit measurement annotations, so the converted Braket
81
+ circuit would have an empty `result_types` list and fail at execution time. The
82
+ fix adds `circuit.probability(target=list(range(circuit.qubit_count)))` before
83
+ returning, ensuring every Braket job has at least one result type.
84
+
85
+ ### v0.0.13.dev1
86
+ - Refactor: Replace class-based subprocess components with standalone
87
+ module-level functions for simpler imports and testability:
88
+ - `SubprocessDispatcher` class → `dispatch()` and `is_subprocess_language()`
89
+ in `dispatcher.py`.
90
+ - `CircuitAdapter` class → `adapt()` and private helper functions in
91
+ `circuit_adapter.py`.
92
+ - `ResultSerializer` class → `serialize()` in `result_serializer.py`.
93
+ - `SubprocessBridge` retains its class form but delegates internally to the
94
+ new standalone functions.
95
+ - Refactor `dispatcher.py`: `WORKING_DIR` is now read from the
96
+ `QUAPP_WORKING_DIR` environment variable (previously hardcoded `None`);
97
+ falls back to `os.getcwd()` when the variable is unset.
98
+ - Refactor `dispatcher.py`: Q# runner command changed from
99
+ `dotnet run --project HandlerRunner.csproj` to a precompiled
100
+ platform-specific binary — `./handler_runner_bin/Function.exe` on Windows
101
+ and `./handler_runner_bin/Function` on other platforms — eliminating the
102
+ `dotnet` toolchain requirement at runtime.
103
+ - Refactor `circuit_adapter.py`: Extract `_load_qasm_circuit(qasm_str)` private
104
+ utility that centralises OpenQASM 2.0 string parsing with Qiskit version
105
+ compatibility — uses `qiskit.qasm2.loads` (Qiskit >= 1.0) and falls back to
106
+ `QiskitCircuit.from_qasm_str` (Qiskit < 1.0).
107
+ - Fix: `subprocess.run` now passes `check=True` so a non-zero exit code raises
108
+ `CalledProcessError` before the manual return-code branch is reached.
109
+ - Add unit tests: `tests/test_circuit_adapter.py`,
110
+ `tests/test_json_parser_utils.py`, `tests/test_result_serializer.py`.
111
+
69
112
  ### v0.0.12.dev15
70
113
  - Extend multi-language SDK support with Q# (QSharp) runtime:
71
114
  - Add `QSHARP` to `Language` enum.
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "quapp-common"
7
- version = "0.0.12.dev15"
7
+ version = "0.0.13.dev2"
8
8
  description = "Quapp common library supporting Quapp Platform for Quantum Computing"
9
9
  readme = "README.md"
10
10
  authors = [{ name = "CITYNOW Co. Ltd. ", email = "corp@citynow.vn" }]
@@ -9,6 +9,10 @@ from typing import Any, Dict
9
9
  import numpy as np
10
10
  import pennylane as qml
11
11
  import pennylane.measurements as _plm
12
+ try:
13
+ import qiskit.qasm2 as _qasm2
14
+ except ImportError:
15
+ _qasm2 = None
12
16
  from dimod import BinaryQuadraticModel
13
17
  from pytket.qasm import circuit_from_qasm_str
14
18
  from qibo.models import Circuit
@@ -22,6 +26,16 @@ from ..enum.sdk import Sdk
22
26
  logger = logger.bind(context=__name__)
23
27
 
24
28
 
29
+ def _load_qasm_circuit(qasm_str: str) -> QiskitCircuit:
30
+ """Parse OpenQASM 2.0 string into a Qiskit QuantumCircuit.
31
+
32
+ Compatible with Qiskit >= 1.0 (qiskit.qasm2.loads) and < 1.0 (from_qasm_str).
33
+ """
34
+ if _qasm2 is not None:
35
+ return _qasm2.loads(qasm_str)
36
+ return QiskitCircuit.from_qasm_str(qasm_str)
37
+
38
+
25
39
  def adapt(sdk: Sdk, result: dict):
26
40
  """Route to the appropriate adapter based on the 'format' field."""
27
41
  fmt = result.get("format")
@@ -93,7 +107,11 @@ def _openqasm_to_braket(qasm_str):
93
107
  is_tuple = isinstance(result, tuple)
94
108
  logger.debug(
95
109
  f"tk_to_braket returned tuple={is_tuple}; unpacking index 0" if is_tuple else "tk_to_braket returned Circuit directly")
96
- return result[0] if is_tuple else result
110
+ circuit = result[0] if is_tuple else result
111
+ if not circuit.result_types:
112
+ circuit.probability(target=list(range(circuit.qubit_count)))
113
+ logger.debug(f"No result types found; added Probability over {circuit.qubit_count} qubits")
114
+ return circuit
97
115
 
98
116
 
99
117
  def _openqasm_to_cuda_quantum(qasm_str):
@@ -142,8 +160,8 @@ def _openqasm_to_qibo(qasm_str):
142
160
 
143
161
 
144
162
  def _openqasm_to_qiskit(qasm_str):
145
- logger.debug("Converting OpenQASM via Qiskit QuantumCircuit.from_qasm_str")
146
- return QiskitCircuit.from_qasm_str(qasm_str)
163
+ logger.debug("Converting OpenQASM via Qiskit QuantumCircuit")
164
+ return _load_qasm_circuit(qasm_str)
147
165
 
148
166
 
149
167
  def _openqasm_to_qulacs(qasm_str):
@@ -151,7 +169,7 @@ def _openqasm_to_qulacs(qasm_str):
151
169
  # Try the Qiskit bridge first; fall back to raw pass-through if
152
170
  # qiskit is not installed or the conversion fails.
153
171
  try:
154
- qiskit_circ = QiskitCircuit.from_qasm_str(qasm_str)
172
+ qiskit_circ = _load_qasm_circuit(qasm_str)
155
173
  logger.debug(
156
174
  f"Qiskit parsed circuit: num_qubits={qiskit_circ.num_qubits} num_gates={len(qiskit_circ.data)}")
157
175
  return _qiskit_to_qulacs(qiskit_circ)
@@ -166,7 +184,7 @@ def _qiskit_to_pennylane(qasm_str, num_wires):
166
184
  Fallback for environments where qml.from_qasm is unavailable because
167
185
  pennylane-qiskit is not installed (PennyLane < 0.36).
168
186
  """
169
- qiskit_circ = QiskitCircuit.from_qasm_str(qasm_str)
187
+ qiskit_circ = _load_qasm_circuit(qasm_str)
170
188
  qubit_map = {bit: idx for idx, bit in enumerate(qiskit_circ.qubits)}
171
189
  logger.debug(
172
190
  f"_qiskit_to_pennylane: num_qubits={qiskit_circ.num_qubits} "
@@ -5,21 +5,24 @@
5
5
  import json
6
6
  import os
7
7
  import subprocess
8
+ import sys
8
9
 
9
10
  from ..config.logging_config import logger
10
11
  from ..enum.language import Language
11
12
 
12
13
  logger = logger.bind(context=__name__)
13
14
 
14
- WORKING_DIR: str = None
15
+ WORKING_DIR: str = os.environ.get('QUAPP_WORKING_DIR')
16
+
17
+ _QSHARP_BINARY = './handler_runner_bin/Function.exe' if sys.platform == 'win32' else './handler_runner_bin/Function'
15
18
 
16
19
  RUNNER_MAP = {
17
20
  Language.JAVASCRIPT: {
18
21
  'command': ['node', 'handler_runner.js'],
19
22
  'timeout': 300,
20
23
  },
21
- Language.QSHARP: {
22
- 'command': ['dotnet', 'run', '--project', 'HandlerRunner.csproj'],
24
+ Language.QSHARP: {
25
+ 'command': [_QSHARP_BINARY],
23
26
  'timeout': 300,
24
27
  },
25
28
  }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: quapp-common
3
- Version: 0.0.12.dev15
3
+ Version: 0.0.13.dev2
4
4
  Summary: Quapp common library supporting Quapp Platform for Quantum Computing
5
5
  Author-email: "CITYNOW Co. Ltd. " <corp@citynow.vn>
6
6
  License: The MIT License (MIT)
@@ -80,15 +80,22 @@ responses while work continues in the background.
80
80
  - Multi-language SDK support:
81
81
  - Language enum for validating and resolving Python, JavaScript, and Q#
82
82
  runtimes.
83
- - SubprocessDispatcher to delegate tasks to non-Python runtimes via
84
- subprocess with timeout management and JSON payload processing; supports
85
- Node.js and `dotnet run` (Q#) runners.
86
- - SubprocessBridge integrating dispatcher, circuit adapter, and result
87
- serializer for seamless JS-Python handler interaction.
88
- - CircuitAdapter for converting JS subprocess circuit outputs into native
89
- SDK formats (OpenQASM, QUBO, JSON) across Qiskit, Braket, PennyLane, etc.
90
- - ResultSerializer for converting complex job results into JSON-serializable
91
- dictionaries for subprocess communication.
83
+ - Standalone `dispatch()` function (formerly `SubprocessDispatcher` class)
84
+ to delegate tasks to non-Python runtimes via subprocess with timeout
85
+ management and JSON payload processing; supports Node.js and precompiled
86
+ Q# binary (`./handler_runner_bin/Function[.exe]`) runners.
87
+ - Working directory configurable via `QUAPP_WORKING_DIR` environment
88
+ variable; falls back to `os.getcwd()` when unset.
89
+ - `SubprocessBridge` class integrating standalone dispatcher, circuit
90
+ adapter, and result serializer for seamless JS/Q#-Python handler
91
+ interaction.
92
+ - Standalone `adapt()` function (formerly `CircuitAdapter` class) for
93
+ converting subprocess circuit outputs into native SDK formats (OpenQASM,
94
+ QUBO, JSON) across Qiskit, Braket, PennyLane, PyQuil, Qibo, Qulacs, and
95
+ CUDA Quantum.
96
+ - Standalone `serialize()` function (formerly `ResultSerializer` class) for
97
+ converting complex job results into JSON-serializable dictionaries for
98
+ subprocess communication.
92
99
 
93
100
  ## Installation
94
101
 
@@ -107,6 +114,42 @@ Notes:
107
114
 
108
115
  ## Recently Changes Highlights
109
116
 
117
+ ### v0.0.13.dev2
118
+ - Fix: `_openqasm_to_braket` in `circuit_adapter.py` now injects a default
119
+ `Probability` result type when the Braket circuit produced by `tk_to_braket`
120
+ has no result types. OpenQASM circuits submitted from non-Python runtimes (e.g.
121
+ Q#) do not carry explicit measurement annotations, so the converted Braket
122
+ circuit would have an empty `result_types` list and fail at execution time. The
123
+ fix adds `circuit.probability(target=list(range(circuit.qubit_count)))` before
124
+ returning, ensuring every Braket job has at least one result type.
125
+
126
+ ### v0.0.13.dev1
127
+ - Refactor: Replace class-based subprocess components with standalone
128
+ module-level functions for simpler imports and testability:
129
+ - `SubprocessDispatcher` class → `dispatch()` and `is_subprocess_language()`
130
+ in `dispatcher.py`.
131
+ - `CircuitAdapter` class → `adapt()` and private helper functions in
132
+ `circuit_adapter.py`.
133
+ - `ResultSerializer` class → `serialize()` in `result_serializer.py`.
134
+ - `SubprocessBridge` retains its class form but delegates internally to the
135
+ new standalone functions.
136
+ - Refactor `dispatcher.py`: `WORKING_DIR` is now read from the
137
+ `QUAPP_WORKING_DIR` environment variable (previously hardcoded `None`);
138
+ falls back to `os.getcwd()` when the variable is unset.
139
+ - Refactor `dispatcher.py`: Q# runner command changed from
140
+ `dotnet run --project HandlerRunner.csproj` to a precompiled
141
+ platform-specific binary — `./handler_runner_bin/Function.exe` on Windows
142
+ and `./handler_runner_bin/Function` on other platforms — eliminating the
143
+ `dotnet` toolchain requirement at runtime.
144
+ - Refactor `circuit_adapter.py`: Extract `_load_qasm_circuit(qasm_str)` private
145
+ utility that centralises OpenQASM 2.0 string parsing with Qiskit version
146
+ compatibility — uses `qiskit.qasm2.loads` (Qiskit >= 1.0) and falls back to
147
+ `QiskitCircuit.from_qasm_str` (Qiskit < 1.0).
148
+ - Fix: `subprocess.run` now passes `check=True` so a non-zero exit code raises
149
+ `CalledProcessError` before the manual return-code branch is reached.
150
+ - Add unit tests: `tests/test_circuit_adapter.py`,
151
+ `tests/test_json_parser_utils.py`, `tests/test_result_serializer.py`.
152
+
110
153
  ### v0.0.12.dev15
111
154
  - Extend multi-language SDK support with Q# (QSharp) runtime:
112
155
  - Add `QSHARP` to `Language` enum.