luna-quantum 0.0.16__py3-none-any.whl

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.

Potentially problematic release.


This version of luna-quantum might be problematic. Click here for more details.

Files changed (160) hide show
  1. luna_quantum-0.0.16.dist-info/LICENSE +201 -0
  2. luna_quantum-0.0.16.dist-info/METADATA +46 -0
  3. luna_quantum-0.0.16.dist-info/RECORD +160 -0
  4. luna_quantum-0.0.16.dist-info/WHEEL +4 -0
  5. luna_sdk/__init__.py +2 -0
  6. luna_sdk/constants.py +1 -0
  7. luna_sdk/controllers/__init__.py +2 -0
  8. luna_sdk/controllers/custom_login_client.py +61 -0
  9. luna_sdk/controllers/luna_platform_client.py +62 -0
  10. luna_sdk/controllers/luna_q.py +36 -0
  11. luna_sdk/controllers/luna_solve.py +49 -0
  12. luna_sdk/controllers/luna_transform.py +41 -0
  13. luna_sdk/error/__init__.py +0 -0
  14. luna_sdk/error/http_error_utils.py +100 -0
  15. luna_sdk/exceptions/__init__.py +1 -0
  16. luna_sdk/exceptions/encryption_exception.py +6 -0
  17. luna_sdk/exceptions/luna_exception.py +7 -0
  18. luna_sdk/exceptions/luna_server_exception.py +18 -0
  19. luna_sdk/exceptions/timeout_exception.py +10 -0
  20. luna_sdk/exceptions/transformation.py +11 -0
  21. luna_sdk/interfaces/__init__.py +5 -0
  22. luna_sdk/interfaces/circuit_repo_i.py +62 -0
  23. luna_sdk/interfaces/clients/__init__.py +0 -0
  24. luna_sdk/interfaces/clients/client_i.py +10 -0
  25. luna_sdk/interfaces/clients/luna_q_i.py +39 -0
  26. luna_sdk/interfaces/clients/luna_solve_i.py +37 -0
  27. luna_sdk/interfaces/clients/luna_transform_i.py +33 -0
  28. luna_sdk/interfaces/cplex_repo_i.py +121 -0
  29. luna_sdk/interfaces/info_repo_i.py +40 -0
  30. luna_sdk/interfaces/lp_repo_i.py +106 -0
  31. luna_sdk/interfaces/optimization_repo_i.py +262 -0
  32. luna_sdk/interfaces/qpu_token_repo_i.py +151 -0
  33. luna_sdk/interfaces/repository_i.py +14 -0
  34. luna_sdk/interfaces/solutions_repo_i.py +219 -0
  35. luna_sdk/py.typed +0 -0
  36. luna_sdk/repositories/__init__.py +4 -0
  37. luna_sdk/repositories/circuit_repo.py +104 -0
  38. luna_sdk/repositories/cplex_repo.py +118 -0
  39. luna_sdk/repositories/info_repo.py +45 -0
  40. luna_sdk/repositories/lp_repo.py +105 -0
  41. luna_sdk/repositories/optimization_repo.py +358 -0
  42. luna_sdk/repositories/qpu_token_repo.py +226 -0
  43. luna_sdk/repositories/solutions_repo.py +347 -0
  44. luna_sdk/schemas/__init__.py +4 -0
  45. luna_sdk/schemas/circuit.py +43 -0
  46. luna_sdk/schemas/create/__init__.py +3 -0
  47. luna_sdk/schemas/create/circuit.py +29 -0
  48. luna_sdk/schemas/create/optimization.py +22 -0
  49. luna_sdk/schemas/create/qpu_token.py +26 -0
  50. luna_sdk/schemas/create/qubo.py +19 -0
  51. luna_sdk/schemas/create/solution.py +15 -0
  52. luna_sdk/schemas/enums/__init__.py +0 -0
  53. luna_sdk/schemas/enums/circuit.py +14 -0
  54. luna_sdk/schemas/enums/optimization.py +10 -0
  55. luna_sdk/schemas/enums/problem.py +48 -0
  56. luna_sdk/schemas/enums/qpu_token_type.py +6 -0
  57. luna_sdk/schemas/enums/solution.py +8 -0
  58. luna_sdk/schemas/enums/status.py +10 -0
  59. luna_sdk/schemas/enums/timeframe.py +11 -0
  60. luna_sdk/schemas/error_message.py +12 -0
  61. luna_sdk/schemas/optimization.py +75 -0
  62. luna_sdk/schemas/optimization_formats/__init__.py +0 -0
  63. luna_sdk/schemas/optimization_formats/bqm.py +34 -0
  64. luna_sdk/schemas/optimization_formats/cqm.py +127 -0
  65. luna_sdk/schemas/optimization_formats/lp.py +9 -0
  66. luna_sdk/schemas/optimization_formats/qm.py +30 -0
  67. luna_sdk/schemas/pretty_base.py +49 -0
  68. luna_sdk/schemas/qpu_token.py +60 -0
  69. luna_sdk/schemas/representation.py +19 -0
  70. luna_sdk/schemas/rest/__init__.py +0 -0
  71. luna_sdk/schemas/rest/qpu_token/__init__.py +0 -0
  72. luna_sdk/schemas/rest/qpu_token/token_provider.py +45 -0
  73. luna_sdk/schemas/solution.py +227 -0
  74. luna_sdk/schemas/solver_info.py +11 -0
  75. luna_sdk/schemas/solver_parameters/aws/__init__.py +1 -0
  76. luna_sdk/schemas/solver_parameters/aws/qaoa.py +24 -0
  77. luna_sdk/schemas/solver_parameters/dwave/__init__.py +72 -0
  78. luna_sdk/schemas/solver_parameters/dwave/base.py +409 -0
  79. luna_sdk/schemas/solver_parameters/dwave/dialectic_search.py +31 -0
  80. luna_sdk/schemas/solver_parameters/dwave/kerberos.py +71 -0
  81. luna_sdk/schemas/solver_parameters/dwave/leap_hybrid_bqm.py +19 -0
  82. luna_sdk/schemas/solver_parameters/dwave/leap_hybrid_cqm.py +22 -0
  83. luna_sdk/schemas/solver_parameters/dwave/parallel_tempering.py +30 -0
  84. luna_sdk/schemas/solver_parameters/dwave/parallel_tempering_qpu.py +37 -0
  85. luna_sdk/schemas/solver_parameters/dwave/population_annealing.py +25 -0
  86. luna_sdk/schemas/solver_parameters/dwave/population_annealing_qpu.py +35 -0
  87. luna_sdk/schemas/solver_parameters/dwave/qaga.py +56 -0
  88. luna_sdk/schemas/solver_parameters/dwave/qbsolv_like_qpu.py +19 -0
  89. luna_sdk/schemas/solver_parameters/dwave/qbsolv_like_simulated_annealing.py +22 -0
  90. luna_sdk/schemas/solver_parameters/dwave/qbsolv_like_tabu_search.py +21 -0
  91. luna_sdk/schemas/solver_parameters/dwave/quantum_annealing.py +20 -0
  92. luna_sdk/schemas/solver_parameters/dwave/repeated_reverse_quantum_annealing.py +82 -0
  93. luna_sdk/schemas/solver_parameters/dwave/repeated_reverse_simulated_annealing.py +89 -0
  94. luna_sdk/schemas/solver_parameters/dwave/saga.py +61 -0
  95. luna_sdk/schemas/solver_parameters/dwave/simulated_annealing.py +74 -0
  96. luna_sdk/schemas/solver_parameters/dwave/tabu_search.py +72 -0
  97. luna_sdk/schemas/solver_parameters/fujitsu/__init__.py +20 -0
  98. luna_sdk/schemas/solver_parameters/fujitsu/base.py +47 -0
  99. luna_sdk/schemas/solver_parameters/fujitsu/digital_annealer_cpu.py +129 -0
  100. luna_sdk/schemas/solver_parameters/fujitsu/digital_annealer_v2.py +149 -0
  101. luna_sdk/schemas/solver_parameters/fujitsu/digital_annealer_v3.py +150 -0
  102. luna_sdk/schemas/solver_parameters/fujitsu/partial_config.py +177 -0
  103. luna_sdk/schemas/solver_parameters/ibm/__init__.py +4 -0
  104. luna_sdk/schemas/solver_parameters/ibm/qaoa.py +64 -0
  105. luna_sdk/schemas/solver_parameters/ibm/standard_parameters.py +27 -0
  106. luna_sdk/schemas/solver_parameters/ibm/vqe.py +49 -0
  107. luna_sdk/schemas/solver_parameters/qctrl/__init__.py +1 -0
  108. luna_sdk/schemas/solver_parameters/qctrl/qaoa.py +47 -0
  109. luna_sdk/schemas/transformations/__init__.py +2 -0
  110. luna_sdk/schemas/transformations/bqm.py +33 -0
  111. luna_sdk/schemas/transformations/matrix.py +12 -0
  112. luna_sdk/schemas/use_cases/__init__.py +54 -0
  113. luna_sdk/schemas/use_cases/arbitrage_edge_based.py +49 -0
  114. luna_sdk/schemas/use_cases/arbitrage_node_based.py +54 -0
  115. luna_sdk/schemas/use_cases/base.py +5 -0
  116. luna_sdk/schemas/use_cases/binary_integer_linear_programming.py +53 -0
  117. luna_sdk/schemas/use_cases/binary_paint_shop_problem.py +36 -0
  118. luna_sdk/schemas/use_cases/credit_scoring_feature_selection.py +39 -0
  119. luna_sdk/schemas/use_cases/dynamic_portfolio_optimization.py +63 -0
  120. luna_sdk/schemas/use_cases/exact_cover.py +50 -0
  121. luna_sdk/schemas/use_cases/flight_gate_assignment.py +78 -0
  122. luna_sdk/schemas/use_cases/graph_coloring.py +41 -0
  123. luna_sdk/schemas/use_cases/graph_isomorphism.py +53 -0
  124. luna_sdk/schemas/use_cases/graph_partitioning.py +45 -0
  125. luna_sdk/schemas/use_cases/hamiltonian_cycle.py +48 -0
  126. luna_sdk/schemas/use_cases/induced_subgraph_isomorphism.py +49 -0
  127. luna_sdk/schemas/use_cases/job_shop_scheduling.py +43 -0
  128. luna_sdk/schemas/use_cases/k_medoids_clustering.py +48 -0
  129. luna_sdk/schemas/use_cases/knapsack_integer_weights.py +55 -0
  130. luna_sdk/schemas/use_cases/linear_regression.py +59 -0
  131. luna_sdk/schemas/use_cases/lmwcs.py +80 -0
  132. luna_sdk/schemas/use_cases/longest_path.py +49 -0
  133. luna_sdk/schemas/use_cases/market_graph_clustering.py +60 -0
  134. luna_sdk/schemas/use_cases/max2sat.py +51 -0
  135. luna_sdk/schemas/use_cases/max3sat.py +52 -0
  136. luna_sdk/schemas/use_cases/max_clique.py +59 -0
  137. luna_sdk/schemas/use_cases/max_cut.py +47 -0
  138. luna_sdk/schemas/use_cases/max_independent_set.py +36 -0
  139. luna_sdk/schemas/use_cases/minimal_maximal_matching.py +53 -0
  140. luna_sdk/schemas/use_cases/minimal_spanning_tree.py +87 -0
  141. luna_sdk/schemas/use_cases/minimum_vertex_cover.py +44 -0
  142. luna_sdk/schemas/use_cases/number_partitioning.py +31 -0
  143. luna_sdk/schemas/use_cases/portfolio_optimization.py +45 -0
  144. luna_sdk/schemas/use_cases/portfolio_optimization_ib_tv.py +62 -0
  145. luna_sdk/schemas/use_cases/quadratic_assignment.py +48 -0
  146. luna_sdk/schemas/use_cases/quadratic_knapsack.py +47 -0
  147. luna_sdk/schemas/use_cases/satellite_scheduling.py +72 -0
  148. luna_sdk/schemas/use_cases/sensor_placement.py +57 -0
  149. luna_sdk/schemas/use_cases/set_cover.py +55 -0
  150. luna_sdk/schemas/use_cases/set_packing.py +53 -0
  151. luna_sdk/schemas/use_cases/set_partitioning.py +51 -0
  152. luna_sdk/schemas/use_cases/subgraph_isomorphism.py +56 -0
  153. luna_sdk/schemas/use_cases/subset_sum.py +36 -0
  154. luna_sdk/schemas/use_cases/support_vector_machine.py +63 -0
  155. luna_sdk/schemas/use_cases/traffic_flow.py +34 -0
  156. luna_sdk/schemas/use_cases/travelling_salesman_problem.py +52 -0
  157. luna_sdk/schemas/use_cases/type_aliases.py +11 -0
  158. luna_sdk/schemas/use_cases/weighted_max_cut.py +36 -0
  159. luna_sdk/utils/__init__.py +0 -0
  160. luna_sdk/utils/qpu_tokens.py +52 -0
@@ -0,0 +1,358 @@
1
+ import json
2
+ from io import BufferedReader
3
+ from typing import Any, Dict, List, Optional, Type
4
+
5
+ from dimod import BinaryQuadraticModel, ConstrainedQuadraticModel
6
+ from httpx import Response
7
+
8
+ from luna_sdk.interfaces.optimization_repo_i import IOptimizationRepo
9
+ from luna_sdk.schemas import UseCase
10
+ from luna_sdk.schemas.create import QUBOIn
11
+ from luna_sdk.schemas.create.optimization import OptimizationUseCaseIn
12
+ from luna_sdk.schemas.enums.optimization import InputType
13
+ from luna_sdk.schemas.enums.timeframe import TimeframeEnum
14
+ from luna_sdk.schemas.optimization import (
15
+ Optimization,
16
+ OptimizationBQM,
17
+ OptimizationCQM,
18
+ OptimizationLP,
19
+ OptimizationUseCase,
20
+ )
21
+ from luna_sdk.schemas.optimization_formats.bqm import BQMSchema
22
+ from luna_sdk.schemas.optimization_formats.cqm import CQMSchema
23
+
24
+
25
+ class OptimizationRepo(IOptimizationRepo):
26
+ @property
27
+ def _endpoint(self) -> str:
28
+ return "/optimizations"
29
+
30
+ def get_all(
31
+ self,
32
+ timeframe: Optional[TimeframeEnum] = None,
33
+ input_type: Optional[InputType] = None,
34
+ limit: int = 50,
35
+ offset: int = 0,
36
+ ) -> List[Optimization]:
37
+ """
38
+ Get a list of all available Models.
39
+
40
+ Parameters
41
+ ----------
42
+ timeframe: Optional[TimeframeEnum]
43
+ Only return QUBOs created within a specified timeframe. Default None.
44
+ input_type: Optional[InputType]
45
+ Only return optimizations of a specified input type. Default None.
46
+ limit: int
47
+ Limit the number of Optimizations to be returned. Default value 50.
48
+ offset: int
49
+ Offset the list of optimizations by this amount. Default value 0.
50
+
51
+ Returns
52
+ -------
53
+ List[Model]
54
+ List of Model instances.
55
+ """
56
+ params = {}
57
+ if timeframe and timeframe != TimeframeEnum.all_time: # no value == all_time
58
+ params["timeframe"] = timeframe.value
59
+
60
+ if input_type:
61
+ params["input_type"] = input_type.value
62
+
63
+ if limit < 1:
64
+ # set the minimum limit to 1
65
+ limit = 1
66
+
67
+ params["limit"] = str(limit)
68
+ params["offset"] = str(offset)
69
+ response: Response = self._client.get(self._endpoint, params=params)
70
+ response.raise_for_status()
71
+ return [Optimization.model_validate(item) for item in response.json()]
72
+
73
+ def get(self, optimization_id: str) -> Optimization:
74
+ response: Response = self._client.get(f"{self._endpoint}/{optimization_id}")
75
+ response.raise_for_status()
76
+ response_data = response.json()
77
+
78
+ model: Type[Optimization] = Optimization
79
+
80
+ optimization_data = response_data.pop("optimization_data", None)
81
+ if optimization_data:
82
+ input_type = response_data["input_type"]
83
+
84
+ if input_type in (InputType.bqm_spin, InputType.bqm_binary):
85
+ model = OptimizationBQM
86
+ elif input_type == InputType.cqm:
87
+ model = OptimizationCQM
88
+ elif input_type == InputType.lp:
89
+ model = OptimizationLP
90
+ elif input_type == InputType.qubo:
91
+ if response_data.get("use_case_name"):
92
+ model = OptimizationUseCase
93
+ else:
94
+ model = OptimizationBQM
95
+ else:
96
+ model = OptimizationBQM
97
+
98
+ response_data.update(optimization_data)
99
+
100
+ return model.validate(response_data)
101
+
102
+ def create_from_qubo(
103
+ self,
104
+ name: str,
105
+ matrix: List[List[float]],
106
+ timeout: Optional[float] = 10800.0,
107
+ ) -> Optimization:
108
+ """
109
+ Create an optimization from a QUBO matrix.
110
+
111
+ Parameters
112
+ ----------
113
+ name: str
114
+ Name of the optimization to be created.
115
+ matrix: List[List[float]]
116
+ QUBO matrix.
117
+ timeout: Optional[float]
118
+ Default = 10800. Timeout for the api request. If set to None,
119
+ there won't be any timeout. Increase or disable the timeout if you face
120
+ issues uploading big QUBO matrices.
121
+
122
+ Returns
123
+ -------
124
+ Optimization:
125
+ Created optimization.
126
+ """
127
+ data_in: Dict[str, Any] = QUBOIn(name=name, matrix=matrix).model_dump()
128
+
129
+ response: Response = self._client.post(
130
+ f"{self._endpoint}/qubo",
131
+ json=data_in,
132
+ timeout=timeout,
133
+ )
134
+
135
+ response.raise_for_status()
136
+
137
+ return Optimization.model_validate_json(response.text)
138
+
139
+ def create_from_use_case(
140
+ self,
141
+ name: str,
142
+ use_case: UseCase,
143
+ timeout: Optional[float] = 10800.0,
144
+ ) -> Optimization:
145
+ """
146
+ Create an optimization from a use case.
147
+
148
+ Parameters
149
+ ----------
150
+ name: str
151
+ Name of the optimization to be created.
152
+ use_case: UseCase
153
+ Use case.
154
+ timeout: Optional[float]
155
+ Default = 10800.0. Timeout for the api request. If set to None,
156
+ there won't be any timeout. Increase or disable the timeout if you face
157
+ issues uploading big Problems.
158
+
159
+ Returns
160
+ -------
161
+ Optimization:
162
+ Created optimization.
163
+ """
164
+ optimization_in = OptimizationUseCaseIn(
165
+ name=name, use_case=use_case, params=None
166
+ )
167
+
168
+ response: Response = self._client.post(
169
+ f"{self._endpoint}/use_case",
170
+ content=optimization_in.model_dump_json(),
171
+ timeout=timeout,
172
+ )
173
+
174
+ response.raise_for_status()
175
+
176
+ return Optimization.model_validate_json(response.text)
177
+
178
+ def create_from_bqm(
179
+ self,
180
+ name: str,
181
+ bqm: BinaryQuadraticModel,
182
+ timeout: Optional[float] = 10800.0,
183
+ ) -> Optimization:
184
+ """
185
+ Create an optimization from BQM.
186
+
187
+ Parameters
188
+ ----------
189
+ name: str
190
+ Name of the optimization to be created.
191
+ bqm: BinaryQuadraticModel
192
+ QUBO in dimod BQM format.
193
+ timeout: Optional[float]
194
+
195
+ Returns
196
+ -------
197
+ Optimization:
198
+ Created optimization.
199
+ """
200
+ data_in = {"name": name, **BQMSchema.from_bqm(bqm).model_dump()}
201
+
202
+ response: Response = self._client.post(
203
+ f"{self._endpoint}/bqm",
204
+ json=data_in,
205
+ timeout=timeout,
206
+ )
207
+
208
+ response.raise_for_status()
209
+
210
+ return Optimization.model_validate_json(response.text)
211
+
212
+ def create_from_cqm(
213
+ self,
214
+ name: str,
215
+ cqm: ConstrainedQuadraticModel,
216
+ timeout: Optional[float] = 10800.0,
217
+ ) -> Optimization:
218
+ """
219
+ Create an optimization from CQM.
220
+
221
+ Parameters
222
+ ----------
223
+ name: str
224
+ Name of the optimization to be created.
225
+ cqm: ConstrainedQuadraticModel
226
+ in dimod CQM format.
227
+ timeout: Optional[float]
228
+
229
+ Returns
230
+ -------
231
+ Optimization:
232
+ Created optimization.
233
+ """
234
+
235
+ data_in = {"name": name, **CQMSchema.from_cqm(cqm).model_dump()}
236
+
237
+ response: Response = self._client.post(
238
+ f"{self._endpoint}/cqm",
239
+ json=data_in,
240
+ timeout=timeout,
241
+ )
242
+
243
+ response.raise_for_status()
244
+
245
+ return Optimization.model_validate_json(response.text)
246
+
247
+ def create_from_lp_file(
248
+ self,
249
+ name: str,
250
+ lp_file: BufferedReader,
251
+ timeout: Optional[float] = 10800.0,
252
+ ) -> Optimization:
253
+ """
254
+ Create an optimization from LP file.
255
+
256
+ Parameters
257
+ ----------
258
+ name: str
259
+ Name of the optimization to be created.
260
+ lp_file: buffer reader.
261
+ timeout: Optional[float]
262
+ Default = 10800. Timeout for the api request. If set to None,
263
+ there won't be any timeout. Increase or disable the timeout if you face
264
+ issues uploading big QUBO matrices.
265
+
266
+ Returns
267
+ -------
268
+ Optimization:
269
+ Created optimization.
270
+ """
271
+
272
+ response: Response = self._client.post(
273
+ f"{self._endpoint}/lp-file",
274
+ data={"optimization_in": json.dumps({"name": name})},
275
+ files={"lp_file": lp_file},
276
+ timeout=timeout,
277
+ )
278
+
279
+ response.raise_for_status()
280
+
281
+ return Optimization.model_validate_json(response.text)
282
+
283
+ def create_from_lp_string(
284
+ self,
285
+ name: str,
286
+ lp_string: str,
287
+ timeout: Optional[float] = 10800.0,
288
+ ) -> Optimization:
289
+ """
290
+ Create an optimization from LP string.
291
+
292
+ Parameters
293
+ ----------
294
+ name: str
295
+ Name of the optimization to be created.
296
+ lp_string: string.
297
+ timeout: Optional[float]
298
+ Default = 10800. Timeout for the api request. If set to None,
299
+ there won't be any timeout. Increase or disable the timeout if you face
300
+ issues uploading big QUBO matrices.
301
+
302
+ Returns
303
+ -------
304
+ Optimization:
305
+ Created optimization.
306
+ """
307
+ data_in = {"name": name, "lp_string": lp_string}
308
+
309
+ response: Response = self._client.post(
310
+ f"{self._endpoint}/lp-string",
311
+ json=data_in,
312
+ timeout=timeout,
313
+ )
314
+
315
+ response.raise_for_status()
316
+
317
+ return Optimization.model_validate_json(response.text)
318
+
319
+ def rename(self, optimization_id: str, name: str) -> Optimization:
320
+ """
321
+ Update the name of the optimization
322
+
323
+ Parameters
324
+ ----------
325
+ optimization_id: str
326
+ Id of the optimization to be updated.
327
+ name: str
328
+ New name of the optimization
329
+
330
+ Returns
331
+ -------
332
+ Optimization:
333
+ Updated optimization.
334
+ """
335
+ data: Dict[str, str] = {"name": name}
336
+
337
+ response: Response = self._client.put(
338
+ f"{self._endpoint}/{optimization_id}",
339
+ content=json.dumps(data),
340
+ )
341
+ response.raise_for_status()
342
+
343
+ return Optimization.model_validate_json(response.text)
344
+
345
+ def delete(self, optimization_id: str) -> None:
346
+ """
347
+ Delete one QUBO by id.
348
+
349
+ Parameters
350
+ ----------
351
+ optimization_id: str
352
+ Id of the Model that should be deleted
353
+
354
+ Returns
355
+ -------
356
+ """
357
+ response: Response = self._client.delete(f"{self._endpoint}/{optimization_id}")
358
+ response.raise_for_status()
@@ -0,0 +1,226 @@
1
+ import json
2
+ import os
3
+ from typing import Dict, List, Optional
4
+
5
+ from httpx import Response
6
+
7
+ from luna_sdk.exceptions.encryption_exception import EncryptionNotSetException
8
+ from luna_sdk.interfaces.qpu_token_repo_i import IQpuTokenRepo
9
+ from luna_sdk.schemas import QpuTokenOut
10
+ from luna_sdk.schemas.create import QpuTokenIn
11
+ from luna_sdk.schemas.enums.qpu_token_type import QpuTokenTypeEnum
12
+
13
+
14
+ class QpuTokenRepo(IQpuTokenRepo):
15
+ @property
16
+ def _endpoint(self) -> str:
17
+ return "/qpu-tokens"
18
+
19
+ def _get_endpoint_by_type(
20
+ self, token_type: Optional[QpuTokenTypeEnum] = None
21
+ ) -> str:
22
+ if token_type is None:
23
+ return f"{self._endpoint}"
24
+ elif token_type == QpuTokenTypeEnum.PERSONAL:
25
+ return f"{self._endpoint}/users"
26
+ else:
27
+ return f"{self._endpoint}/organization"
28
+
29
+ def _get_by_name(self, name: str, token_type: QpuTokenTypeEnum) -> QpuTokenOut:
30
+ response: Response = self._client.get(
31
+ f"{self._get_endpoint_by_type(token_type)}/by_name/{name}"
32
+ )
33
+ response.raise_for_status()
34
+
35
+ qpu_token_data = response.json()
36
+ return QpuTokenOut.model_validate(qpu_token_data)
37
+
38
+ def create(
39
+ self,
40
+ name: str,
41
+ provider: str,
42
+ token: str,
43
+ token_type: QpuTokenTypeEnum = QpuTokenTypeEnum.PERSONAL,
44
+ encryption_key: Optional[str] = None,
45
+ ) -> QpuTokenOut:
46
+ """
47
+ Create user QPU token
48
+
49
+ Parameters
50
+ ----------
51
+ name: str
52
+ Name of the QPU token
53
+ provider: str
54
+ Name of provider
55
+ token: str
56
+ Token
57
+ token_type: QpuTokenTypeEnum
58
+ There are two types of QPU tokens: PERSONAL and ORGANIZATION.
59
+ The default value is PERSONAL.
60
+ All users of an organization can use organization QPU tokens.
61
+ User QPU tokens can only be used by the user who created them.
62
+ encryption_key: Optional[str]
63
+ Encryption key to be used for encryption of QPU tokens.
64
+ Returns
65
+ -------
66
+ QpuTokenOut
67
+ QpuTokenOut instances.
68
+ """
69
+ encryption_key = encryption_key or os.environ.get("LUNA_ENCRYPTION_KEY")
70
+ if encryption_key is None:
71
+ raise EncryptionNotSetException
72
+ qpu_token = QpuTokenIn(
73
+ name=name,
74
+ provider=provider,
75
+ token=token,
76
+ encryption_key=encryption_key,
77
+ )
78
+
79
+ response: Response = self._client.post(
80
+ self._get_endpoint_by_type(token_type), content=qpu_token.model_dump_json()
81
+ )
82
+ response.raise_for_status()
83
+ qpu_token_data = response.json()
84
+ return QpuTokenOut.model_validate(qpu_token_data)
85
+
86
+ def get_all(
87
+ self,
88
+ filter_provider: Optional[str] = None,
89
+ name: Optional[str] = None,
90
+ token_type: Optional[QpuTokenTypeEnum] = None,
91
+ ) -> Dict[QpuTokenTypeEnum, List[QpuTokenOut]]:
92
+ """
93
+ Retrieve list of user QPU tokens.
94
+
95
+ Parameters
96
+ ----------
97
+ filter_provider: Optional[str]
98
+ The provider for which qpu tokens should be retrieved
99
+ name: Optional[str]
100
+ Name of the QPU token that should be retrieved
101
+ token_type: Optional[QpuTokenTypeEnum]
102
+ If you want to retrieve only user or organization QPU tokens
103
+ otherwise all QPU tokens will be retrieved
104
+ token_type: QpuTokenTypeEnum
105
+ There are two types of QPU tokens: PERSONAL and ORGANIZATION.
106
+ The default value is PERSONAL.
107
+ All users of an organization can use organization QPU tokens.
108
+ User QPU tokens can only be used by the user who created them.
109
+
110
+ Returns
111
+ -------
112
+ Dict[QpuTokenTypeEnum, List[QpuTokenOut]]
113
+ List of QpuTokenOut instances.
114
+ """
115
+ params = {}
116
+ if filter_provider:
117
+ params["filter_provider"] = filter_provider
118
+
119
+ if name:
120
+ params["name"] = name
121
+
122
+ response = self._client.get(self._get_endpoint_by_type(), params=params)
123
+ response.raise_for_status()
124
+
125
+ to_return: Dict[QpuTokenTypeEnum, List[QpuTokenOut]] = {}
126
+ for key, value in response.json().items():
127
+ to_return[QpuTokenTypeEnum(key)] = [
128
+ QpuTokenOut.model_validate(item) for item in value
129
+ ]
130
+
131
+ return to_return
132
+
133
+ def get(
134
+ self,
135
+ name: str,
136
+ token_type: QpuTokenTypeEnum = QpuTokenTypeEnum.PERSONAL,
137
+ ) -> QpuTokenOut:
138
+ """
139
+ Retrieve user QPU token by id
140
+
141
+ Parameters
142
+ ----------
143
+ name: str
144
+ Name of the QPU token that should be retrieved
145
+ token_type: QpuTokenTypeEnum
146
+ There are two types of QPU tokens: PERSONAL and ORGANIZATION.
147
+ The default value is PERSONAL.
148
+ All users of an organization can use organization QPU tokens.
149
+ User QPU tokens can only be used by the user who created them.
150
+
151
+ Returns
152
+ -------
153
+ QpuTokenOut
154
+ QpuTokenOut instance.
155
+ """
156
+
157
+ qpu_token: QpuTokenOut = self._get_by_name(name, token_type)
158
+
159
+ return qpu_token
160
+
161
+ def rename(
162
+ self,
163
+ name: str,
164
+ new_name: str,
165
+ token_type: QpuTokenTypeEnum = QpuTokenTypeEnum.PERSONAL,
166
+ ) -> QpuTokenOut:
167
+ """
168
+ Update user QPU token by id
169
+
170
+ Parameters
171
+ ----------
172
+ name: str
173
+ Name of the QPU token that should be updated
174
+ new_name: str
175
+ The new name
176
+ token_type: QpuTokenTypeEnum
177
+ There are two types of QPU tokens: PERSONAL and ORGANIZATION.
178
+ The default value is PERSONAL.
179
+ All users of an organization can use organization QPU tokens.
180
+ User QPU tokens can only be used by the user who created them.
181
+
182
+ Returns
183
+ -------
184
+ QpuTokenOut
185
+ QpuTokenOut instance.
186
+ """
187
+ qpu_token_update_data = {"name": new_name}
188
+
189
+ token: QpuTokenOut = self.get(name, token_type)
190
+
191
+ response = self._client.put(
192
+ f"{self._get_endpoint_by_type(token_type)}/{token.id}",
193
+ content=json.dumps(qpu_token_update_data),
194
+ )
195
+ response.raise_for_status()
196
+
197
+ qpu_token_data = response.json()
198
+ return QpuTokenOut.model_validate(qpu_token_data)
199
+
200
+ def delete(
201
+ self,
202
+ name: str,
203
+ token_type: QpuTokenTypeEnum = QpuTokenTypeEnum.PERSONAL,
204
+ ) -> None:
205
+ """
206
+ Delete organization QPU token by name
207
+
208
+ Parameters
209
+ ----------
210
+ name: str
211
+ Name of the QPU token that should be deleted
212
+ token_type: QpuTokenTypeEnum
213
+ There are two types of QPU tokens: PERSONAL and ORGANIZATION.
214
+ The default value is PERSONAL.
215
+ All users of an organization can use organization QPU tokens.
216
+ User QPU tokens can only be used by the user who created them.
217
+
218
+ Returns
219
+ -------
220
+ """
221
+ token: QpuTokenOut = self.get(name, token_type)
222
+
223
+ response = self._client.delete(
224
+ f"{self._get_endpoint_by_type(token_type)}/{token.id}"
225
+ )
226
+ response.raise_for_status()