quapp-common 0.0.11.dev5__tar.gz → 0.0.11.dev7__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 (85) hide show
  1. {quapp_common-0.0.11.dev5/quapp_common.egg-info → quapp_common-0.0.11.dev7}/PKG-INFO +35 -19
  2. quapp_common-0.0.11.dev7/README.md +72 -0
  3. {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/pyproject.toml +3 -2
  4. quapp_common-0.0.11.dev7/quapp_common/async_tasks/async_invocation_task.py +80 -0
  5. {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/async_tasks/export_circuit_task.py +21 -15
  6. {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/component/backend/invocation.py +10 -9
  7. {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/component/backend/job_fetcher.py +4 -4
  8. {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/component/backend/job_fetching.py +2 -2
  9. quapp_common-0.0.11.dev7/quapp_common/component/backend/job_manager.py +302 -0
  10. quapp_common-0.0.11.dev7/quapp_common/component/callback/update_job_metadata.py +77 -0
  11. {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/component/device/device_selection.py +1 -1
  12. {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/data/request/invocation_request.py +2 -2
  13. {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/data/request/job_fetching_request.py +2 -2
  14. {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/data/request/request.py +4 -2
  15. {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/data/response/job_response.py +2 -2
  16. {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/model/device/custom_device.py +1 -1
  17. {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/model/device/device.py +1 -1
  18. quapp_common-0.0.11.dev7/quapp_common/model/invocation.py +54 -0
  19. quapp_common-0.0.11.dev7/quapp_common/util/http_utils.py +141 -0
  20. quapp_common-0.0.11.dev7/quapp_common/util/response_utils.py +200 -0
  21. {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7/quapp_common.egg-info}/PKG-INFO +35 -19
  22. {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common.egg-info/SOURCES.txt +3 -0
  23. {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common.egg-info/requires.txt +1 -0
  24. quapp_common-0.0.11.dev5/README.md +0 -57
  25. quapp_common-0.0.11.dev5/quapp_common/component/callback/update_job_metadata.py +0 -41
  26. quapp_common-0.0.11.dev5/quapp_common/util/http_utils.py +0 -93
  27. quapp_common-0.0.11.dev5/quapp_common/util/response_utils.py +0 -97
  28. {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/LICENSE +0 -0
  29. {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/__init__.py +0 -0
  30. {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/async_tasks/__init__.py +0 -0
  31. {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/async_tasks/async_task.py +0 -0
  32. {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/async_tasks/post_processing_task.py +0 -0
  33. {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/component/__init__.py +0 -0
  34. {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/component/backend/__init__.py +0 -0
  35. {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/component/callback/__init__.py +0 -0
  36. {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/component/device/__init__.py +0 -0
  37. {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/config/__init__.py +0 -0
  38. {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/config/logging_config.py +0 -0
  39. {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/config/thread_config.py +0 -0
  40. {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/data/__init__.py +0 -0
  41. {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/data/async_task/__init__.py +0 -0
  42. {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/data/async_task/circuit_export/__init__.py +0 -0
  43. {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/data/async_task/circuit_export/backend_holder.py +0 -0
  44. {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/data/async_task/circuit_export/circuit_holder.py +0 -0
  45. {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/data/backend/__init__.py +0 -0
  46. {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/data/backend/backend_information.py +0 -0
  47. {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/data/callback/__init__.py +0 -0
  48. {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/data/callback/callback_url.py +0 -0
  49. {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/data/device/__init__.py +0 -0
  50. {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/data/device/circuit_running_option.py +0 -0
  51. {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/data/promise/__init__.py +0 -0
  52. {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/data/promise/post_processing_promise.py +0 -0
  53. {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/data/promise/promise.py +0 -0
  54. {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/data/request/__init__.py +0 -0
  55. {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/data/response/__init__.py +0 -0
  56. {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/data/response/authentication.py +0 -0
  57. {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/data/response/custom_header.py +0 -0
  58. {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/enum/__init__.py +0 -0
  59. {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/enum/base_enum.py +0 -0
  60. {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/enum/http_header.py +0 -0
  61. {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/enum/invocation_step.py +0 -0
  62. {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/enum/media_type.py +0 -0
  63. {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/enum/processing_unit.py +0 -0
  64. {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/enum/provider_tag.py +0 -0
  65. {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/enum/sdk.py +0 -0
  66. {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/enum/status/__init__.py +0 -0
  67. {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/enum/status/job_status.py +0 -0
  68. {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/enum/status/status_code.py +0 -0
  69. {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/enum/token_type.py +0 -0
  70. {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/factory/__init__.py +0 -0
  71. {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/factory/device_factory.py +0 -0
  72. {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/factory/handler_factory.py +0 -0
  73. {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/factory/provider_factory.py +0 -0
  74. {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/handler/__init__.py +0 -0
  75. {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/handler/handler.py +0 -0
  76. {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/model/__init__.py +0 -0
  77. {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/model/device/__init__.py +0 -0
  78. {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/model/provider/__init__.py +0 -0
  79. {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/model/provider/provider.py +0 -0
  80. {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/util/__init__.py +0 -0
  81. {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/util/file_utils.py +0 -0
  82. {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/util/json_parser_utils.py +0 -0
  83. {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common.egg-info/dependency_links.txt +0 -0
  84. {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common.egg-info/top_level.txt +0 -0
  85. {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: quapp-common
3
- Version: 0.0.11.dev5
3
+ Version: 0.0.11.dev7
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)
@@ -24,6 +24,7 @@ Requires-Dist: requests
24
24
  Requires-Dist: numpy
25
25
  Requires-Dist: matplotlib
26
26
  Requires-Dist: pylatexenc
27
+ Requires-Dist: starlette
27
28
  Provides-Extra: dev
28
29
  Requires-Dist: black; extra == "dev"
29
30
  Requires-Dist: bumpver; extra == "dev"
@@ -42,12 +43,11 @@ Quapp common library supporting Quapp Platform for Quantum Computing.
42
43
  Quantum Computing by providing common utilities, configurations, and
43
44
  abstractions for working with
44
45
  quantum providers and devices.
45
-
46
- Recent improvements focus on cleaner and more consistent logging, enhanced error
47
- handling, and
48
- standardizing header management by adding workspace-specific headers instead of
49
- tenant-specific ones,
50
- improving maintainability and clarity.
46
+ Recent improvements add first-class asynchronous job processing with a
47
+ cross-process JobManager,
48
+ background task execution, and standardized result models for immediate client
49
+ responses while work
50
+ continues in the background.
51
51
 
52
52
  ## Features
53
53
 
@@ -61,6 +61,17 @@ improving maintainability and clarity.
61
61
  - Enhanced error handling and job metadata update mechanisms.
62
62
  - Simplified and cleaner HTTP request/response logging and URL parsing
63
63
  utilities.
64
+ - Asynchronous job processing:
65
+ - AsyncInvocationTask to run handlers in a background thread pool and return
66
+ immediate responses.
67
+ - JobManager for cross-process job registry with atomic add/update/get and
68
+ pub-sub updates.
69
+ - Standard Event/Result (Success, Error) models for consistent async
70
+ responses.
71
+ - Scheduler integration via callback URL; local updates are patched to the
72
+ scheduler.
73
+ - Safety: updates to jobs already DONE/FAILED are ignored to prevent
74
+ post-completion mutations.
64
75
 
65
76
  ## Installation
66
77
 
@@ -70,22 +81,27 @@ Install via pip:
70
81
  pip install quapp-common
71
82
  ```
72
83
 
84
+ Notes:
85
+
86
+ - From version 0.0.11.dev7, `starlette` is a direct dependency to support
87
+ background execution helpers.
88
+
73
89
  ## Recently Changes Highlights
74
90
 
75
- - Added workspace-specific classes for request, response, and promise,
76
- consolidating code to unify context handling.
77
- - Refactored logging throughout the codebase, removing redundant debug logs and
78
- adding context-rich log messages.
79
- - Improved URL parsing and job ID extraction, especially in HTTP utilities, to
80
- better track jobs.
81
- - Cleaned up logging configuration files to standardize log formats and levels.
82
- - Added robust error handling in job execution and analysis pipelines, ensuring
83
- detailed failure reporting.
84
- - Simplified header and request body logging, improving performance and
85
- readability.
91
+ - Version bump to 0.0.11.dev7 and dependency update (add `starlette`).
92
+ - Introduce asynchronous job processing primitives:
93
+ - AsyncInvocationTask for background execution with immediate client
94
+ response.
95
+ - Event and standardized Result models (Success, Error).
96
+ - Introduce JobManager for cross-process job management and update publication.
97
+ - Integrate JobManager into Request to register jobs and carry scheduler
98
+ callback URL.
99
+ - Modularize update_job_metadata with clearer helpers; patch scheduler on local
100
+ state changes.
101
+ - Fix: ignore updates for jobs that are already DONE or FAILED.
102
+ - Improve logging and error handling (use full tracebacks, cleaner logs).
86
103
 
87
104
  ---
88
105
 
89
106
  For detailed usage and API references, please refer to the in-code documentation
90
107
  or contact the maintainers.
91
-
@@ -0,0 +1,72 @@
1
+ # quapp-common
2
+
3
+ Quapp common library supporting Quapp Platform for Quantum Computing.
4
+
5
+ ## Overview
6
+
7
+ `quapp-common` is a Python library designed to support the Quapp Platform for
8
+ Quantum Computing by providing common utilities, configurations, and
9
+ abstractions for working with
10
+ quantum providers and devices.
11
+ Recent improvements add first-class asynchronous job processing with a
12
+ cross-process JobManager,
13
+ background task execution, and standardized result models for immediate client
14
+ responses while work
15
+ continues in the background.
16
+
17
+ ## Features
18
+
19
+ - Provider and device factory for quantum computing platforms.
20
+ - Logging and configuration utilities with improved and detailed log messages.
21
+ - Support for AWS Braket, OQC Cloud, Qiskit, PennyLane, DWave Ocean, and Quapp
22
+ quantum simulators.
23
+ - Refactored classes and utilities to remove tenant-specific request, response,
24
+ and promise classes.
25
+ - Standardized naming by renaming `ProjectHeader` to `CustomHeader`.
26
+ - Enhanced error handling and job metadata update mechanisms.
27
+ - Simplified and cleaner HTTP request/response logging and URL parsing
28
+ utilities.
29
+ - Asynchronous job processing:
30
+ - AsyncInvocationTask to run handlers in a background thread pool and return
31
+ immediate responses.
32
+ - JobManager for cross-process job registry with atomic add/update/get and
33
+ pub-sub updates.
34
+ - Standard Event/Result (Success, Error) models for consistent async
35
+ responses.
36
+ - Scheduler integration via callback URL; local updates are patched to the
37
+ scheduler.
38
+ - Safety: updates to jobs already DONE/FAILED are ignored to prevent
39
+ post-completion mutations.
40
+
41
+ ## Installation
42
+
43
+ Install via pip:
44
+
45
+ ```bash
46
+ pip install quapp-common
47
+ ```
48
+
49
+ Notes:
50
+
51
+ - From version 0.0.11.dev7, `starlette` is a direct dependency to support
52
+ background execution helpers.
53
+
54
+ ## Recently Changes Highlights
55
+
56
+ - Version bump to 0.0.11.dev7 and dependency update (add `starlette`).
57
+ - Introduce asynchronous job processing primitives:
58
+ - AsyncInvocationTask for background execution with immediate client
59
+ response.
60
+ - Event and standardized Result models (Success, Error).
61
+ - Introduce JobManager for cross-process job management and update publication.
62
+ - Integrate JobManager into Request to register jobs and carry scheduler
63
+ callback URL.
64
+ - Modularize update_job_metadata with clearer helpers; patch scheduler on local
65
+ state changes.
66
+ - Fix: ignore updates for jobs that are already DONE or FAILED.
67
+ - Improve logging and error handling (use full tracebacks, cleaner logs).
68
+
69
+ ---
70
+
71
+ For detailed usage and API references, please refer to the in-code documentation
72
+ or contact the maintainers.
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "quapp-common"
7
- version = "0.0.11.dev5"
7
+ version = "0.0.11.dev7"
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" }]
@@ -20,7 +20,8 @@ dependencies = [
20
20
  "requests",
21
21
  "numpy",
22
22
  "matplotlib",
23
- "pylatexenc"
23
+ "pylatexenc",
24
+ "starlette"
24
25
  ]
25
26
  requires-python = ">=3.7"
26
27
 
@@ -0,0 +1,80 @@
1
+ # Quapp Platform Project
2
+ # async_invocation_task.py
3
+ # Copyright © CITYNOW Co. Ltd. All rights reserved.
4
+ import asyncio
5
+ import sys
6
+
7
+ from starlette.concurrency import run_in_threadpool
8
+ from starlette.responses import JSONResponse
9
+
10
+ from ..async_tasks.async_task import AsyncTask
11
+ from ..component.backend.job_manager import JobManager
12
+ from ..config.logging_config import logger
13
+ from ..factory.handler_factory import HandlerFactory
14
+ from ..model.invocation import Event, Error, Success
15
+
16
+
17
+ class AsyncInvocationTask(AsyncTask):
18
+ """
19
+ Handles asynchronous invocation tasks, designed to process events with
20
+ specific handlers and generate immediate responses.
21
+
22
+ The class is aimed at enabling tasks to be processed asynchronously, involving
23
+ a handler factory and functions for event processing and post-processing. It
24
+ executes operations in a background thread pool to ensure quick response to
25
+ clients, allowing them to poll for job status updates. Its primary purpose is
26
+ to facilitate efficient asynchronous processing of jobs without blocking the
27
+ main application flow.
28
+
29
+ Attributes:
30
+ handler_factory: Factory instance that produces job handlers.
31
+ event: Event to be processed by the created handler.
32
+ processing_fn: Function to be executed during the job processing stage.
33
+ post_processing_fn: Function to be executed post-job processing.
34
+ """
35
+
36
+ def __init__(self, handler_factory: HandlerFactory, event: Event,
37
+ processing_fn, post_processing_fn):
38
+ super().__init__()
39
+ self.handler_factory = handler_factory
40
+ self.event = event
41
+ self.processing_fn = processing_fn
42
+ self.post_processing_fn = post_processing_fn
43
+
44
+ def do(self) -> JSONResponse:
45
+ """
46
+ Handles executing a job asynchronously and provides an immediate response with the job's ID and
47
+ status. Logging is configured dynamically based on the provided job ID.
48
+
49
+ Returns:
50
+ JSONResponse: A response object with the status and job ID if the job submission succeeds,
51
+ or an error message if there is an issue.
52
+
53
+ Raises:
54
+ Exception: If any error occurs during job processing, it is logged, and an appropriate error
55
+ response is returned.
56
+ """
57
+ try:
58
+ job_id = self.event.json().get('jobId')
59
+ if job_id is None:
60
+ raise Exception("Job ID is missing from event")
61
+ logger.add(sink=sys.stderr,
62
+ format="[ConsoleJobLog][" + job_id + "] " + "{level} : {time} : {message}: {process}",
63
+ level='DEBUG')
64
+
65
+ # Define the blocking work
66
+ def _run_handle():
67
+ return self.handler_factory.create_handler(self.event,
68
+ self.processing_fn,
69
+ self.post_processing_fn).handle()
70
+
71
+ # Run in the background threadpool so this request can return immediately
72
+ asyncio.create_task(run_in_threadpool(_run_handle))
73
+
74
+ # Respond immediately so clients can poll GET /jobs/{job_id}
75
+ return JSONResponse(status_code=200, content=Success(
76
+ JobManager.get_job(job_id)).serialize())
77
+ except Exception as exception:
78
+ logger.exception(f"An error occurred: {exception}")
79
+ return JSONResponse(status_code=400,
80
+ content=Error(exception).serialize())
@@ -11,6 +11,7 @@ from .async_task import AsyncTask
11
11
  from ..config.logging_config import job_logger
12
12
  from ..data.async_task.circuit_export.backend_holder import BackendDataHolder
13
13
  from ..data.async_task.circuit_export.circuit_holder import CircuitDataHolder
14
+ from ..data.response.custom_header import CustomHeader
14
15
  from ..enum.media_type import MediaType
15
16
  from ..util.file_utils import FileUtils
16
17
  from ..util.http_utils import create_bearer_header, get_job_id_from_url
@@ -20,8 +21,11 @@ class CircuitExportTask(AsyncTask):
20
21
  MAX_CIRCUIT_IMAGE_SIZE = 5 * (1024 ** 2)
21
22
 
22
23
  def __init__(self, circuit_data_holder: CircuitDataHolder,
23
- backend_data_holder: BackendDataHolder):
24
+ backend_data_holder: BackendDataHolder,
25
+ project_header: CustomHeader, workspace_header: CustomHeader):
24
26
  super().__init__()
27
+ self.project_header = project_header
28
+ self.workspace_header = workspace_header
25
29
  self.circuit_data_holder = circuit_data_holder
26
30
  self.backend_data_holder = backend_data_holder
27
31
  self.logger = job_logger(
@@ -43,8 +47,8 @@ class CircuitExportTask(AsyncTask):
43
47
  self.logger.debug('Converting circuit to SVG')
44
48
  figure_buffer = self.__convert()
45
49
  except Exception as e:
46
- self.logger.error(f"Error converting circuit to SVG: {e}",
47
- exc_info=True)
50
+ self.logger.exception(f"Error converting circuit to SVG: {e}",
51
+ exc_info=True)
48
52
  return
49
53
 
50
54
  try:
@@ -54,7 +58,7 @@ class CircuitExportTask(AsyncTask):
54
58
  self.logger.debug(f"Content type: {content_type}")
55
59
  self.logger.debug(f"Buffer size: {len(io_buffer_value)} bytes")
56
60
  except Exception as e:
57
- self.logger.error(
61
+ self.logger.exception(
58
62
  f"Error determining if circuit SVG should be zipped: {e}",
59
63
  exc_info=True)
60
64
  return
@@ -64,11 +68,12 @@ class CircuitExportTask(AsyncTask):
64
68
  self.__send(io_buffer_value=io_buffer_value,
65
69
  content_type=content_type)
66
70
  self.logger.debug("Circuit sent to backend successfully.")
71
+ return
67
72
  except Exception as e:
68
- self.logger.error(f"Error sending exported circuit to backend: {e}",
69
- exc_info=True)
70
-
71
- self.logger.info("Circuit export task finished.")
73
+ self.logger.exception(
74
+ f"Error sending exported circuit to backend: {e}",
75
+ exc_info=True)
76
+ return
72
77
 
73
78
  def __convert(self):
74
79
  """
@@ -81,8 +86,8 @@ class CircuitExportTask(AsyncTask):
81
86
  try:
82
87
  circuit_figure = transpiled_circuit.draw(output='mpl', fold=-1)
83
88
  except Exception as exception:
84
- self.logger.error(f"Error drawing circuit: {exception}",
85
- exc_info=True)
89
+ self.logger.exception(f"Error drawing circuit: {exception}",
90
+ exc_info=True)
86
91
  raise exception
87
92
 
88
93
  self.logger.debug("Converting circuit figure to SVG file...")
@@ -93,7 +98,7 @@ class CircuitExportTask(AsyncTask):
93
98
  self.logger.debug(
94
99
  f"SVG export complete. Size: {figure_buffer.getbuffer().nbytes} bytes")
95
100
  except Exception as exception:
96
- self.logger.error(
101
+ self.logger.exception(
97
102
  f"Error saving circuit figure to SVG: {exception}",
98
103
  exc_info=True)
99
104
  raise exception
@@ -135,16 +140,17 @@ class CircuitExportTask(AsyncTask):
135
140
 
136
141
  try:
137
142
  response = requests.post(url=url, headers=create_bearer_header(
138
- self.backend_data_holder.user_token), files=payload)
143
+ self.backend_data_holder.user_token, self.project_header,
144
+ self.workspace_header), files=payload)
139
145
  except Exception as exception:
140
- self.logger.error(f"HTTP request failed: {exception}",
141
- exc_info=True)
146
+ self.logger.exception(f"HTTP request failed: {exception}",
147
+ exc_info=True)
142
148
  raise
143
149
 
144
150
  if response.ok:
145
151
  self.logger.info("Request sent to QuaO backend successfully.")
146
152
  else:
147
- self.logger.error(
153
+ self.logger.exception(
148
154
  f"Sending request to QuaO backend failed with status {response.status_code}! Response: {response.content}")
149
155
 
150
156
  self.logger.debug("HTTP request complete.")
@@ -77,9 +77,9 @@ class Invocation(ABC):
77
77
  circuit = self.__prepare_circuit(circuit_preparation_fn)
78
78
 
79
79
  if circuit is None:
80
- self.logger.error(
80
+ self.logger.exception(
81
81
  "Circuit preparation failed, returning None from pre-execute")
82
- return None
82
+ raise ValueError("Circuit preparation failed")
83
83
 
84
84
  try:
85
85
  self.logger.debug("Preparing backend data")
@@ -88,12 +88,13 @@ class Invocation(ABC):
88
88
  f"Backend data prepared: device {self.backend_information.device_name}, provider {self.backend_information.provider_tag.value}")
89
89
 
90
90
  except Exception as exception:
91
- self.logger.error(f"Error when prepare backend data: {exception}",
92
- exc_info=True)
91
+ self.logger.exception(
92
+ f"Error when prepare backend data: {exception}",
93
+ exc_info=True)
93
94
 
94
95
  job_response = build_error_job_response(exception,
95
96
  message='Error when prepare backend data')
96
-
97
+ job_response.authentication = self.authentication
97
98
  update_job_metadata(job_response, self.callback_dict.get(
98
99
  InvocationStep.PREPARATION).on_error)
99
100
 
@@ -113,7 +114,7 @@ class Invocation(ABC):
113
114
 
114
115
  try:
115
116
  if self.backend_information is None:
116
- self.logger.error(
117
+ self.logger.exception(
117
118
  "Backend information is None before execution")
118
119
  raise ValueError("Backend is not found")
119
120
 
@@ -129,7 +130,7 @@ class Invocation(ABC):
129
130
  device = self._create_device(provider)
130
131
 
131
132
  except Exception as exception:
132
- self.logger.error(
133
+ self.logger.exception(
133
134
  f"Exception when create provider or device: {exception}",
134
135
  exc_info=True)
135
136
 
@@ -182,8 +183,8 @@ class Invocation(ABC):
182
183
  return circuit
183
184
 
184
185
  except Exception as exception:
185
- self.logger.error(f'Error when prepare circuit: {exception}',
186
- exc_info=True)
186
+ self.logger.exception(f'Error when prepare circuit: {exception}',
187
+ exc_info=True)
187
188
 
188
189
  job_response = build_error_job_response(exception, job_response,
189
190
  message='Error when prepare circuit')
@@ -116,7 +116,7 @@ class JobFetcher(ABC):
116
116
  update_job_metadata(job_response, self.callback_urls[
117
117
  InvocationStep.EXECUTION].on_done)
118
118
  elif job_status == JobStatus.ERROR.value:
119
- self.logger.error("Job resulted in error, handling failure")
119
+ self.logger.exception("Job resulted in error, handling failure")
120
120
 
121
121
  self._handle_failed_job(original_job_result, job_response)
122
122
  update_job_metadata(job_response, self.callback_urls[
@@ -127,7 +127,7 @@ class JobFetcher(ABC):
127
127
  job_response.status_code = StatusCode.POLLING
128
128
 
129
129
  except Exception as exception:
130
- self.logger.error(
130
+ self.logger.exception(
131
131
  f"Exception during job fetch for provider_job_id {self.provider_job_id}: {exception}",
132
132
  exc_info=True)
133
133
 
@@ -151,7 +151,7 @@ class JobFetcher(ABC):
151
151
  def _handle_failed_job(self, original_job_result,
152
152
  job_response: JobResponse):
153
153
  """Handles the job result when the job has encountered an error."""
154
- self.logger.error("Parsing job result from failed job")
154
+ self.logger.exception("Parsing job result from failed job")
155
155
  job_response.job_result = parse(original_job_result)
156
156
 
157
157
  def _process_job_result(self, original_job_result,
@@ -205,7 +205,7 @@ class JobFetcher(ABC):
205
205
  return job_response
206
206
 
207
207
  except Exception as exception:
208
- self.logger.error(f"Exception during analysis: {exception}",
208
+ self.logger.exception(f"Exception during analysis: {exception}",
209
209
  exc_info=True)
210
210
  from ...util.response_utils import build_error_job_response
211
211
  job_response = build_error_job_response(exception, job_response,
@@ -75,7 +75,7 @@ class JobFetching(ABC):
75
75
  InvocationStep.EXECUTION).on_done)
76
76
 
77
77
  elif JobStatus.ERROR.value.__eq__(job_response.job_status):
78
- self.logger.error("Job resulted in error, handling failure")
78
+ self.logger.exception("Job resulted in error, handling failure")
79
79
 
80
80
  job_response.job_result = parse(original_job_result)
81
81
 
@@ -152,7 +152,7 @@ class JobFetching(ABC):
152
152
  return job_response
153
153
 
154
154
  except Exception as exception:
155
- self.logger.error(
155
+ self.logger.exception(
156
156
  "Exception when analyst job result with provider_job_id {0}: {1}".format(
157
157
  self.provider_job_id, str(exception)))
158
158