quapp-common 0.0.14.dev2__tar.gz → 0.0.14.dev4__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 (105) hide show
  1. {quapp_common-0.0.14.dev2/quapp_common.egg-info → quapp_common-0.0.14.dev4}/PKG-INFO +1 -1
  2. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/pyproject.toml +1 -1
  3. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/quapp_common/component/backend/invocation.py +12 -4
  4. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/quapp_common/component/callback/update_job_metadata.py +11 -1
  5. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/quapp_common/data/response/job_response.py +11 -2
  6. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/quapp_common/enum/language.py +1 -0
  7. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/quapp_common/util/response_utils.py +31 -9
  8. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4/quapp_common.egg-info}/PKG-INFO +1 -1
  9. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/tests/test_language_dispatcher.py +15 -0
  10. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/LICENSE +0 -0
  11. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/README.md +0 -0
  12. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/quapp_common/__init__.py +0 -0
  13. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/quapp_common/async_tasks/__init__.py +0 -0
  14. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/quapp_common/async_tasks/async_invocation_task.py +0 -0
  15. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/quapp_common/async_tasks/async_task.py +0 -0
  16. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/quapp_common/async_tasks/export_circuit_task.py +0 -0
  17. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/quapp_common/async_tasks/post_processing_task.py +0 -0
  18. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/quapp_common/component/__init__.py +0 -0
  19. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/quapp_common/component/backend/__init__.py +0 -0
  20. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/quapp_common/component/backend/job_fetcher.py +0 -0
  21. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/quapp_common/component/backend/job_fetching.py +0 -0
  22. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/quapp_common/component/backend/job_heartbeat.py +0 -0
  23. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/quapp_common/component/backend/job_manager.py +0 -0
  24. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/quapp_common/component/bridge.py +0 -0
  25. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/quapp_common/component/callback/__init__.py +0 -0
  26. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/quapp_common/component/circuit_adapter.py +0 -0
  27. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/quapp_common/component/device/__init__.py +0 -0
  28. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/quapp_common/component/device/device_selection.py +0 -0
  29. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/quapp_common/component/dispatcher.py +0 -0
  30. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/quapp_common/component/result_serializer.py +0 -0
  31. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/quapp_common/config/__init__.py +0 -0
  32. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/quapp_common/config/log_context.py +0 -0
  33. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/quapp_common/config/logging_config.py +0 -0
  34. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/quapp_common/config/thread_config.py +0 -0
  35. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/quapp_common/data/__init__.py +0 -0
  36. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/quapp_common/data/async_task/__init__.py +0 -0
  37. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/quapp_common/data/async_task/circuit_export/__init__.py +0 -0
  38. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/quapp_common/data/async_task/circuit_export/backend_holder.py +0 -0
  39. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/quapp_common/data/async_task/circuit_export/circuit_holder.py +0 -0
  40. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/quapp_common/data/backend/__init__.py +0 -0
  41. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/quapp_common/data/backend/backend_information.py +0 -0
  42. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/quapp_common/data/callback/__init__.py +0 -0
  43. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/quapp_common/data/callback/callback_url.py +0 -0
  44. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/quapp_common/data/device/__init__.py +0 -0
  45. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/quapp_common/data/device/circuit_running_option.py +0 -0
  46. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/quapp_common/data/promise/__init__.py +0 -0
  47. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/quapp_common/data/promise/post_processing_promise.py +0 -0
  48. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/quapp_common/data/promise/promise.py +0 -0
  49. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/quapp_common/data/request/__init__.py +0 -0
  50. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/quapp_common/data/request/invocation_request.py +0 -0
  51. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/quapp_common/data/request/job_fetching_request.py +0 -0
  52. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/quapp_common/data/request/request.py +0 -0
  53. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/quapp_common/data/response/__init__.py +0 -0
  54. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/quapp_common/data/response/authentication.py +0 -0
  55. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/quapp_common/data/response/custom_header.py +0 -0
  56. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/quapp_common/data/response/error_report.py +0 -0
  57. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/quapp_common/enum/__init__.py +0 -0
  58. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/quapp_common/enum/base_enum.py +0 -0
  59. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/quapp_common/enum/error_category.py +0 -0
  60. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/quapp_common/enum/http_header.py +0 -0
  61. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/quapp_common/enum/invocation_step.py +0 -0
  62. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/quapp_common/enum/media_type.py +0 -0
  63. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/quapp_common/enum/processing_unit.py +0 -0
  64. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/quapp_common/enum/provider_tag.py +0 -0
  65. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/quapp_common/enum/runtime_phase.py +0 -0
  66. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/quapp_common/enum/sdk.py +0 -0
  67. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/quapp_common/enum/status/__init__.py +0 -0
  68. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/quapp_common/enum/status/job_status.py +0 -0
  69. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/quapp_common/enum/status/status_code.py +0 -0
  70. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/quapp_common/enum/token_type.py +0 -0
  71. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/quapp_common/factory/__init__.py +0 -0
  72. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/quapp_common/factory/device_factory.py +0 -0
  73. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/quapp_common/factory/handler_factory.py +0 -0
  74. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/quapp_common/factory/provider_factory.py +0 -0
  75. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/quapp_common/handler/__init__.py +0 -0
  76. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/quapp_common/handler/handler.py +0 -0
  77. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/quapp_common/model/__init__.py +0 -0
  78. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/quapp_common/model/device/__init__.py +0 -0
  79. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/quapp_common/model/device/custom_device.py +0 -0
  80. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/quapp_common/model/device/device.py +0 -0
  81. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/quapp_common/model/invocation.py +0 -0
  82. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/quapp_common/model/provider/__init__.py +0 -0
  83. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/quapp_common/model/provider/provider.py +0 -0
  84. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/quapp_common/util/__init__.py +0 -0
  85. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/quapp_common/util/error_classifier.py +0 -0
  86. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/quapp_common/util/file_utils.py +0 -0
  87. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/quapp_common/util/http_utils.py +0 -0
  88. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/quapp_common/util/invocation_failure.py +0 -0
  89. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/quapp_common/util/json_parser_utils.py +0 -0
  90. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/quapp_common.egg-info/SOURCES.txt +0 -0
  91. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/quapp_common.egg-info/dependency_links.txt +0 -0
  92. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/quapp_common.egg-info/requires.txt +0 -0
  93. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/quapp_common.egg-info/top_level.txt +0 -0
  94. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/setup.cfg +0 -0
  95. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/tests/test_circuit_adapter.py +0 -0
  96. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/tests/test_dispatcher_runner_error.py +0 -0
  97. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/tests/test_error_classifier.py +0 -0
  98. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/tests/test_error_log_dedupe.py +0 -0
  99. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/tests/test_error_report.py +0 -0
  100. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/tests/test_invocation_failure.py +0 -0
  101. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/tests/test_job_heartbeat.py +0 -0
  102. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/tests/test_json_parser_utils.py +0 -0
  103. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/tests/test_log_secret_leak.py +0 -0
  104. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/tests/test_logging_config.py +0 -0
  105. {quapp_common-0.0.14.dev2 → quapp_common-0.0.14.dev4}/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.14.dev2
3
+ Version: 0.0.14.dev4
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.14.dev2"
7
+ version = "0.0.14.dev4"
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" }]
@@ -97,8 +97,10 @@ class Invocation(ABC):
97
97
  job_response = build_error_job_response(exception,
98
98
  message='Error when prepare backend data',
99
99
  stage='while preparing the backend',
100
- phase=RuntimePhase.DEVICE_SELECTION)
101
- job_response.authentication = self.authentication
100
+ phase=RuntimePhase.DEVICE_SELECTION,
101
+ authentication=self.authentication,
102
+ project_header=self.project_header,
103
+ workspace_header=self.workspace_header)
102
104
  update_job_metadata(job_response, self.callback_dict.get(
103
105
  InvocationStep.PREPARATION).on_error)
104
106
 
@@ -142,7 +144,10 @@ class Invocation(ABC):
142
144
  job_response = build_error_job_response(exception,
143
145
  message='Error when create provider or device',
144
146
  stage='while running the circuit on the device',
145
- phase=RuntimePhase.PROVIDER_INVOCATION)
147
+ phase=RuntimePhase.PROVIDER_INVOCATION,
148
+ authentication=self.authentication,
149
+ project_header=self.project_header,
150
+ workspace_header=self.workspace_header)
146
151
  update_job_metadata(job_response, self.callback_dict.get(
147
152
  InvocationStep.EXECUTION).on_error, )
148
153
 
@@ -194,7 +199,10 @@ class Invocation(ABC):
194
199
  job_response = build_error_job_response(exception, job_response,
195
200
  message='Error when prepare circuit',
196
201
  stage='while preparing the circuit',
197
- phase=RuntimePhase.PREPROCESSING)
202
+ phase=RuntimePhase.PREPROCESSING,
203
+ authentication=self.authentication,
204
+ project_header=self.project_header,
205
+ workspace_header=self.workspace_header)
198
206
 
199
207
  update_job_metadata(job_response, self.callback_dict.get(
200
208
  InvocationStep.PREPARATION).on_error)
@@ -17,7 +17,12 @@ def update_job_metadata(job_response: JobResponse, callback_url: str):
17
17
  def _log_http_result(tag: str, resp):
18
18
  logger.info(
19
19
  f"Request to {tag} completed with status code: {resp.status_code}")
20
- if not resp.ok:
20
+ if resp.status_code in (401, 403):
21
+ logger.error(
22
+ f"Request to {tag} was rejected with status code {resp.status_code}. "
23
+ f"The job update is lost, so the platform will not see this state change. "
24
+ f"Check that the response carries the user token and the project header.")
25
+ elif not resp.ok:
21
26
  logger.warning(
22
27
  f"Unexpected status code received from {tag}: {resp.status_code}, response content: {resp.content}")
23
28
 
@@ -60,6 +65,11 @@ def update_job_metadata(job_response: JobResponse, callback_url: str):
60
65
  logger.info(
61
66
  f'Calling backend to update job metadata at URL: {callback_url}')
62
67
 
68
+ if not getattr(job_response, 'user_token', None):
69
+ logger.error(
70
+ 'Job update is being sent without a user token, the backend will reject it. '
71
+ 'The response was built without the invocation credentials.')
72
+
63
73
  request_body = generate_response(job_response)
64
74
 
65
75
  try:
@@ -23,9 +23,18 @@ class JobResponse(object):
23
23
  self.job_result = job_result
24
24
  self.content_type = content_type
25
25
  self.job_histogram = job_histogram
26
- self.user_identity = getattr(authentication, 'user_identity', None)
27
- self.user_token = getattr(authentication, 'user_token', None)
26
+ self.authentication = authentication
28
27
  self.execution_time = execution_time
29
28
  self.status_code = status_code
30
29
  self.project_header = project_header
31
30
  self.workspace_header = workspace_header
31
+
32
+ @property
33
+ def authentication(self) -> Authentication:
34
+ return self._authentication
35
+
36
+ @authentication.setter
37
+ def authentication(self, authentication: Authentication) -> None:
38
+ self._authentication = authentication
39
+ self.user_identity = getattr(authentication, 'user_identity', None)
40
+ self.user_token = getattr(authentication, 'user_token', None)
@@ -14,6 +14,7 @@ class Language(BaseEnum):
14
14
  JAVASCRIPT = 'javascript'
15
15
  QSHARP = 'qsharp'
16
16
  C = 'c'
17
+ CPP = 'cpp'
17
18
 
18
19
  @staticmethod
19
20
  def resolve(language: str):
@@ -11,6 +11,8 @@ from .http_utils import CUSTOM_HEADER_VALUE
11
11
  from ..component.backend.job_fetcher import JobFetcher
12
12
  from ..config.logging_config import job_logger, redact
13
13
  from ..data.promise.post_processing_promise import PostProcessingPromise
14
+ from ..data.response.authentication import Authentication
15
+ from ..data.response.custom_header import CustomHeader
14
16
  from ..data.response.job_response import JobResponse
15
17
  from ..enum.runtime_phase import en_phrase_of
16
18
  from ..enum.status.job_status import JobStatus
@@ -195,7 +197,10 @@ def build_error_job_response(exception: Exception,
195
197
  message: str = None,
196
198
  stage: str = None,
197
199
  phase=None,
198
- context: dict = None) -> JobResponse:
200
+ context: dict = None,
201
+ authentication: Authentication = None,
202
+ project_header: CustomHeader = None,
203
+ workspace_header: CustomHeader = None) -> JobResponse:
199
204
  """
200
205
  Builds and returns a JobResponse object populated with error-related information.
201
206
 
@@ -232,14 +237,18 @@ def build_error_job_response(exception: Exception,
232
237
  """
233
238
  if job_response is None:
234
239
  job_response = JobResponse()
235
- job_response.provider_job_id = __extract_value(PROVIDER_JOB_ID, fetcher,
236
- post_promise)
237
- job_response.authentication = __extract_authentication(fetcher,
238
- post_promise)
239
- job_response.project_header = __extract_value(PROJECT_HEADER, fetcher,
240
- post_promise)
241
- job_response.tenant_header = __extract_value(WORKSPACE_HEADER, fetcher,
242
- post_promise)
240
+
241
+ __apply_if_present(job_response, 'provider_job_id',
242
+ __extract_value(PROVIDER_JOB_ID, fetcher, post_promise))
243
+ __apply_if_present(job_response, 'authentication',
244
+ authentication
245
+ or __extract_authentication(fetcher, post_promise))
246
+ __apply_if_present(job_response, 'project_header',
247
+ project_header
248
+ or __extract_value(PROJECT_HEADER, fetcher, post_promise))
249
+ __apply_if_present(job_response, 'workspace_header',
250
+ workspace_header
251
+ or __extract_value(WORKSPACE_HEADER, fetcher, post_promise))
243
252
  job_response.status_code = StatusCode.ERROR
244
253
  job_response.job_status = JobStatus.ERROR.value
245
254
 
@@ -281,6 +290,19 @@ def build_error_job_response(exception: Exception,
281
290
  return job_response
282
291
 
283
292
 
293
+
294
+ def __apply_if_present(job_response: JobResponse, property_name: str, value):
295
+ """Only overwrite when a value is actually available.
296
+
297
+ The error path is often called without a fetcher or a post promise, so the
298
+ extracted value is None. Overwriting blindly used to wipe the credentials
299
+ already carried by the response, which made the resulting event reach the
300
+ backend without a token and get rejected with 401.
301
+ """
302
+ if value is not None:
303
+ setattr(job_response, property_name, value)
304
+
305
+
284
306
  def __extract_authentication(fetcher: JobFetcher,
285
307
  post_promise: PostProcessingPromise):
286
308
  """
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: quapp-common
3
- Version: 0.0.14.dev2
3
+ Version: 0.0.14.dev4
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)
@@ -18,3 +18,18 @@ class TestRunnerMapLanguageC(unittest.TestCase):
18
18
 
19
19
  def test_timeout(self):
20
20
  self.assertEqual(RUNNER_MAP[Language.C]['timeout'], 300)
21
+
22
+
23
+ class TestLanguageCppEnum(unittest.TestCase):
24
+ def test_value_is_cpp(self):
25
+ self.assertEqual(Language.CPP.value, 'cpp')
26
+
27
+ def test_resolve(self):
28
+ self.assertEqual(Language.resolve('cpp'), Language.CPP)
29
+
30
+
31
+ class TestRunnerMapLanguageCpp(unittest.TestCase):
32
+ def test_language_cpp_not_registered(self):
33
+ """C++ handlers run in-process through NativeQiskitBridge, never as a subprocess, so
34
+ having no runner is the correct state rather than a missing entry."""
35
+ self.assertNotIn(Language.CPP, RUNNER_MAP)