quapp-common 0.0.13.dev3__tar.gz → 0.0.13.dev5__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.13.dev3/quapp_common.egg-info → quapp_common-0.0.13.dev5}/PKG-INFO +1 -1
  2. {quapp_common-0.0.13.dev3 → quapp_common-0.0.13.dev5}/pyproject.toml +1 -1
  3. {quapp_common-0.0.13.dev3 → quapp_common-0.0.13.dev5}/quapp_common/component/backend/invocation.py +6 -3
  4. {quapp_common-0.0.13.dev3 → quapp_common-0.0.13.dev5}/quapp_common/util/response_utils.py +75 -3
  5. {quapp_common-0.0.13.dev3 → quapp_common-0.0.13.dev5/quapp_common.egg-info}/PKG-INFO +1 -1
  6. {quapp_common-0.0.13.dev3 → quapp_common-0.0.13.dev5}/LICENSE +0 -0
  7. {quapp_common-0.0.13.dev3 → quapp_common-0.0.13.dev5}/README.md +0 -0
  8. {quapp_common-0.0.13.dev3 → quapp_common-0.0.13.dev5}/quapp_common/__init__.py +0 -0
  9. {quapp_common-0.0.13.dev3 → quapp_common-0.0.13.dev5}/quapp_common/async_tasks/__init__.py +0 -0
  10. {quapp_common-0.0.13.dev3 → quapp_common-0.0.13.dev5}/quapp_common/async_tasks/async_invocation_task.py +0 -0
  11. {quapp_common-0.0.13.dev3 → quapp_common-0.0.13.dev5}/quapp_common/async_tasks/async_task.py +0 -0
  12. {quapp_common-0.0.13.dev3 → quapp_common-0.0.13.dev5}/quapp_common/async_tasks/export_circuit_task.py +0 -0
  13. {quapp_common-0.0.13.dev3 → quapp_common-0.0.13.dev5}/quapp_common/async_tasks/post_processing_task.py +0 -0
  14. {quapp_common-0.0.13.dev3 → quapp_common-0.0.13.dev5}/quapp_common/component/__init__.py +0 -0
  15. {quapp_common-0.0.13.dev3 → quapp_common-0.0.13.dev5}/quapp_common/component/backend/__init__.py +0 -0
  16. {quapp_common-0.0.13.dev3 → quapp_common-0.0.13.dev5}/quapp_common/component/backend/job_fetcher.py +0 -0
  17. {quapp_common-0.0.13.dev3 → quapp_common-0.0.13.dev5}/quapp_common/component/backend/job_fetching.py +0 -0
  18. {quapp_common-0.0.13.dev3 → quapp_common-0.0.13.dev5}/quapp_common/component/backend/job_manager.py +0 -0
  19. {quapp_common-0.0.13.dev3 → quapp_common-0.0.13.dev5}/quapp_common/component/bridge.py +0 -0
  20. {quapp_common-0.0.13.dev3 → quapp_common-0.0.13.dev5}/quapp_common/component/callback/__init__.py +0 -0
  21. {quapp_common-0.0.13.dev3 → quapp_common-0.0.13.dev5}/quapp_common/component/callback/update_job_metadata.py +0 -0
  22. {quapp_common-0.0.13.dev3 → quapp_common-0.0.13.dev5}/quapp_common/component/circuit_adapter.py +0 -0
  23. {quapp_common-0.0.13.dev3 → quapp_common-0.0.13.dev5}/quapp_common/component/device/__init__.py +0 -0
  24. {quapp_common-0.0.13.dev3 → quapp_common-0.0.13.dev5}/quapp_common/component/device/device_selection.py +0 -0
  25. {quapp_common-0.0.13.dev3 → quapp_common-0.0.13.dev5}/quapp_common/component/dispatcher.py +0 -0
  26. {quapp_common-0.0.13.dev3 → quapp_common-0.0.13.dev5}/quapp_common/component/result_serializer.py +0 -0
  27. {quapp_common-0.0.13.dev3 → quapp_common-0.0.13.dev5}/quapp_common/config/__init__.py +0 -0
  28. {quapp_common-0.0.13.dev3 → quapp_common-0.0.13.dev5}/quapp_common/config/logging_config.py +0 -0
  29. {quapp_common-0.0.13.dev3 → quapp_common-0.0.13.dev5}/quapp_common/config/thread_config.py +0 -0
  30. {quapp_common-0.0.13.dev3 → quapp_common-0.0.13.dev5}/quapp_common/data/__init__.py +0 -0
  31. {quapp_common-0.0.13.dev3 → quapp_common-0.0.13.dev5}/quapp_common/data/async_task/__init__.py +0 -0
  32. {quapp_common-0.0.13.dev3 → quapp_common-0.0.13.dev5}/quapp_common/data/async_task/circuit_export/__init__.py +0 -0
  33. {quapp_common-0.0.13.dev3 → quapp_common-0.0.13.dev5}/quapp_common/data/async_task/circuit_export/backend_holder.py +0 -0
  34. {quapp_common-0.0.13.dev3 → quapp_common-0.0.13.dev5}/quapp_common/data/async_task/circuit_export/circuit_holder.py +0 -0
  35. {quapp_common-0.0.13.dev3 → quapp_common-0.0.13.dev5}/quapp_common/data/backend/__init__.py +0 -0
  36. {quapp_common-0.0.13.dev3 → quapp_common-0.0.13.dev5}/quapp_common/data/backend/backend_information.py +0 -0
  37. {quapp_common-0.0.13.dev3 → quapp_common-0.0.13.dev5}/quapp_common/data/callback/__init__.py +0 -0
  38. {quapp_common-0.0.13.dev3 → quapp_common-0.0.13.dev5}/quapp_common/data/callback/callback_url.py +0 -0
  39. {quapp_common-0.0.13.dev3 → quapp_common-0.0.13.dev5}/quapp_common/data/device/__init__.py +0 -0
  40. {quapp_common-0.0.13.dev3 → quapp_common-0.0.13.dev5}/quapp_common/data/device/circuit_running_option.py +0 -0
  41. {quapp_common-0.0.13.dev3 → quapp_common-0.0.13.dev5}/quapp_common/data/promise/__init__.py +0 -0
  42. {quapp_common-0.0.13.dev3 → quapp_common-0.0.13.dev5}/quapp_common/data/promise/post_processing_promise.py +0 -0
  43. {quapp_common-0.0.13.dev3 → quapp_common-0.0.13.dev5}/quapp_common/data/promise/promise.py +0 -0
  44. {quapp_common-0.0.13.dev3 → quapp_common-0.0.13.dev5}/quapp_common/data/request/__init__.py +0 -0
  45. {quapp_common-0.0.13.dev3 → quapp_common-0.0.13.dev5}/quapp_common/data/request/invocation_request.py +0 -0
  46. {quapp_common-0.0.13.dev3 → quapp_common-0.0.13.dev5}/quapp_common/data/request/job_fetching_request.py +0 -0
  47. {quapp_common-0.0.13.dev3 → quapp_common-0.0.13.dev5}/quapp_common/data/request/request.py +0 -0
  48. {quapp_common-0.0.13.dev3 → quapp_common-0.0.13.dev5}/quapp_common/data/response/__init__.py +0 -0
  49. {quapp_common-0.0.13.dev3 → quapp_common-0.0.13.dev5}/quapp_common/data/response/authentication.py +0 -0
  50. {quapp_common-0.0.13.dev3 → quapp_common-0.0.13.dev5}/quapp_common/data/response/custom_header.py +0 -0
  51. {quapp_common-0.0.13.dev3 → quapp_common-0.0.13.dev5}/quapp_common/data/response/job_response.py +0 -0
  52. {quapp_common-0.0.13.dev3 → quapp_common-0.0.13.dev5}/quapp_common/enum/__init__.py +0 -0
  53. {quapp_common-0.0.13.dev3 → quapp_common-0.0.13.dev5}/quapp_common/enum/base_enum.py +0 -0
  54. {quapp_common-0.0.13.dev3 → quapp_common-0.0.13.dev5}/quapp_common/enum/http_header.py +0 -0
  55. {quapp_common-0.0.13.dev3 → quapp_common-0.0.13.dev5}/quapp_common/enum/invocation_step.py +0 -0
  56. {quapp_common-0.0.13.dev3 → quapp_common-0.0.13.dev5}/quapp_common/enum/language.py +0 -0
  57. {quapp_common-0.0.13.dev3 → quapp_common-0.0.13.dev5}/quapp_common/enum/media_type.py +0 -0
  58. {quapp_common-0.0.13.dev3 → quapp_common-0.0.13.dev5}/quapp_common/enum/processing_unit.py +0 -0
  59. {quapp_common-0.0.13.dev3 → quapp_common-0.0.13.dev5}/quapp_common/enum/provider_tag.py +0 -0
  60. {quapp_common-0.0.13.dev3 → quapp_common-0.0.13.dev5}/quapp_common/enum/sdk.py +0 -0
  61. {quapp_common-0.0.13.dev3 → quapp_common-0.0.13.dev5}/quapp_common/enum/status/__init__.py +0 -0
  62. {quapp_common-0.0.13.dev3 → quapp_common-0.0.13.dev5}/quapp_common/enum/status/job_status.py +0 -0
  63. {quapp_common-0.0.13.dev3 → quapp_common-0.0.13.dev5}/quapp_common/enum/status/status_code.py +0 -0
  64. {quapp_common-0.0.13.dev3 → quapp_common-0.0.13.dev5}/quapp_common/enum/token_type.py +0 -0
  65. {quapp_common-0.0.13.dev3 → quapp_common-0.0.13.dev5}/quapp_common/factory/__init__.py +0 -0
  66. {quapp_common-0.0.13.dev3 → quapp_common-0.0.13.dev5}/quapp_common/factory/device_factory.py +0 -0
  67. {quapp_common-0.0.13.dev3 → quapp_common-0.0.13.dev5}/quapp_common/factory/handler_factory.py +0 -0
  68. {quapp_common-0.0.13.dev3 → quapp_common-0.0.13.dev5}/quapp_common/factory/provider_factory.py +0 -0
  69. {quapp_common-0.0.13.dev3 → quapp_common-0.0.13.dev5}/quapp_common/handler/__init__.py +0 -0
  70. {quapp_common-0.0.13.dev3 → quapp_common-0.0.13.dev5}/quapp_common/handler/handler.py +0 -0
  71. {quapp_common-0.0.13.dev3 → quapp_common-0.0.13.dev5}/quapp_common/model/__init__.py +0 -0
  72. {quapp_common-0.0.13.dev3 → quapp_common-0.0.13.dev5}/quapp_common/model/device/__init__.py +0 -0
  73. {quapp_common-0.0.13.dev3 → quapp_common-0.0.13.dev5}/quapp_common/model/device/custom_device.py +0 -0
  74. {quapp_common-0.0.13.dev3 → quapp_common-0.0.13.dev5}/quapp_common/model/device/device.py +0 -0
  75. {quapp_common-0.0.13.dev3 → quapp_common-0.0.13.dev5}/quapp_common/model/invocation.py +0 -0
  76. {quapp_common-0.0.13.dev3 → quapp_common-0.0.13.dev5}/quapp_common/model/provider/__init__.py +0 -0
  77. {quapp_common-0.0.13.dev3 → quapp_common-0.0.13.dev5}/quapp_common/model/provider/provider.py +0 -0
  78. {quapp_common-0.0.13.dev3 → quapp_common-0.0.13.dev5}/quapp_common/util/__init__.py +0 -0
  79. {quapp_common-0.0.13.dev3 → quapp_common-0.0.13.dev5}/quapp_common/util/file_utils.py +0 -0
  80. {quapp_common-0.0.13.dev3 → quapp_common-0.0.13.dev5}/quapp_common/util/http_utils.py +0 -0
  81. {quapp_common-0.0.13.dev3 → quapp_common-0.0.13.dev5}/quapp_common/util/json_parser_utils.py +0 -0
  82. {quapp_common-0.0.13.dev3 → quapp_common-0.0.13.dev5}/quapp_common.egg-info/SOURCES.txt +0 -0
  83. {quapp_common-0.0.13.dev3 → quapp_common-0.0.13.dev5}/quapp_common.egg-info/dependency_links.txt +0 -0
  84. {quapp_common-0.0.13.dev3 → quapp_common-0.0.13.dev5}/quapp_common.egg-info/requires.txt +0 -0
  85. {quapp_common-0.0.13.dev3 → quapp_common-0.0.13.dev5}/quapp_common.egg-info/top_level.txt +0 -0
  86. {quapp_common-0.0.13.dev3 → quapp_common-0.0.13.dev5}/setup.cfg +0 -0
  87. {quapp_common-0.0.13.dev3 → quapp_common-0.0.13.dev5}/tests/test_circuit_adapter.py +0 -0
  88. {quapp_common-0.0.13.dev3 → quapp_common-0.0.13.dev5}/tests/test_json_parser_utils.py +0 -0
  89. {quapp_common-0.0.13.dev3 → quapp_common-0.0.13.dev5}/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.13.dev3
3
+ Version: 0.0.13.dev5
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)
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "quapp-common"
7
- version = "0.0.13.dev3"
7
+ version = "0.0.13.dev5"
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" }]
@@ -93,7 +93,8 @@ class Invocation(ABC):
93
93
  exc_info=True)
94
94
 
95
95
  job_response = build_error_job_response(exception,
96
- message='Error when prepare backend data')
96
+ message='Error when prepare backend data',
97
+ stage='while preparing the backend')
97
98
  job_response.authentication = self.authentication
98
99
  update_job_metadata(job_response, self.callback_dict.get(
99
100
  InvocationStep.PREPARATION).on_error)
@@ -135,7 +136,8 @@ class Invocation(ABC):
135
136
  exc_info=True)
136
137
 
137
138
  job_response = build_error_job_response(exception,
138
- message='Error when create provider or device')
139
+ message='Error when create provider or device',
140
+ stage='while running the circuit on the device')
139
141
  update_job_metadata(job_response, self.callback_dict.get(
140
142
  InvocationStep.EXECUTION).on_error, )
141
143
 
@@ -187,7 +189,8 @@ class Invocation(ABC):
187
189
  exc_info=True)
188
190
 
189
191
  job_response = build_error_job_response(exception, job_response,
190
- message='Error when prepare circuit')
192
+ message='Error when prepare circuit',
193
+ stage='while preparing the circuit')
191
194
 
192
195
  update_job_metadata(job_response, self.callback_dict.get(
193
196
  InvocationStep.PREPARATION).on_error)
@@ -2,6 +2,11 @@
2
2
  # response_utils.py
3
3
  # Copyright © CITYNOW Co. Ltd. All rights reserved.
4
4
 
5
+ import json
6
+ import os
7
+ import traceback
8
+ from typing import Optional
9
+
5
10
  from .http_utils import CUSTOM_HEADER_VALUE
6
11
  from ..component.backend.job_fetcher import JobFetcher
7
12
  from ..data.promise.post_processing_promise import PostProcessingPromise
@@ -97,11 +102,63 @@ def build_done_job_response(fetcher: JobFetcher = None,
97
102
  status_code=StatusCode.DONE)
98
103
 
99
104
 
105
+ def _humanize_exception(exception: Exception) -> Optional[str]:
106
+ """
107
+ Return a short, user-friendly explanation for common input-related
108
+ exceptions raised by a function handler, or None when there is no
109
+ friendlier form.
110
+
111
+ Rationale: the raw ``str`` of some exceptions is cryptic for end users --
112
+ most notably ``KeyError``, whose ``str`` is just the repr of the missing
113
+ key (e.g. ``str(KeyError('Q'))`` -> ``"'Q'"``). Classifying the common
114
+ cases lets us surface an actionable, plain-language message instead. Full
115
+ technical detail (traceback, step, exception type) stays in the function
116
+ logs -- it is not surfaced to the end user here.
117
+ """
118
+ if isinstance(exception, KeyError):
119
+ # KeyError.args[0] is the missing key itself (not quoted).
120
+ key = exception.args[0] if exception.args else exception
121
+ return f"Missing required input field: '{key}'."
122
+
123
+ if isinstance(exception, json.JSONDecodeError):
124
+ return "Input is not valid JSON."
125
+
126
+ if isinstance(exception, IndexError):
127
+ return "An input field has fewer items than expected."
128
+
129
+ return None
130
+
131
+
132
+ def _format_exception(exception: Exception) -> dict:
133
+ """
134
+ Return a compact, structured description of an exception for the user-facing
135
+ response: the exception type, a one-line detail, and the deepest source
136
+ location (file:line in function).
137
+
138
+ The full multi-frame traceback is intentionally NOT included here -- it is
139
+ emitted to the function logs via logger.exception(exc_info=True). The
140
+ frontend renders job_result as pretty JSON, so this nested object displays
141
+ cleanly with no frontend change required.
142
+ """
143
+ at = None
144
+ tb = traceback.extract_tb(exception.__traceback__)
145
+ if tb:
146
+ frame = tb[-1] # deepest frame = where the error actually occurred
147
+ at = f"{os.path.basename(frame.filename)}:{frame.lineno} in {frame.name}()"
148
+
149
+ return {
150
+ "type": type(exception).__name__,
151
+ "detail": str(exception),
152
+ "at": at,
153
+ }
154
+
155
+
100
156
  def build_error_job_response(exception: Exception,
101
157
  job_response: JobResponse = None,
102
158
  fetcher: JobFetcher = None,
103
159
  post_promise: PostProcessingPromise = None,
104
- message: str = None) -> JobResponse:
160
+ message: str = None,
161
+ stage: str = None) -> JobResponse:
105
162
  """
106
163
  Builds and returns a JobResponse object populated with error-related information.
107
164
 
@@ -148,8 +205,23 @@ def build_error_job_response(exception: Exception,
148
205
  post_promise)
149
206
  job_response.status_code = StatusCode.ERROR
150
207
  job_response.job_status = JobStatus.ERROR.value
151
- job_response.job_result = {'message' : message or 'Unknown error occurred.',
152
- 'exception': str(exception)}
208
+
209
+ # User-facing message: plain language + which stage failed (in human terms,
210
+ # from `stage`), never internal jargon. `message` (old internal step label)
211
+ # is kept for backward compatibility but is no longer surfaced to the user.
212
+ # Full multi-frame traceback stays in the logs via logger.exception().
213
+ phrase = stage or 'while running your job'
214
+ hint = _humanize_exception(exception)
215
+ if hint:
216
+ user_message = f'Your job failed {phrase}. {hint}'
217
+ else:
218
+ user_message = (f'Your job failed {phrase}. '
219
+ 'See the exception below or the job logs for details.')
220
+
221
+ job_response.job_result = {
222
+ 'message' : user_message,
223
+ 'exception': _format_exception(exception),
224
+ }
153
225
  return job_response
154
226
 
155
227
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: quapp-common
3
- Version: 0.0.13.dev3
3
+ Version: 0.0.13.dev5
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)