luna-quantum 0.0.37__py3-none-any.whl → 0.10.1__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.

@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: luna-quantum
3
- Version: 0.0.37
3
+ Version: 0.10.1
4
4
  Summary: Python SDK for Aqarios' Luna Platform
5
5
  Home-page: https://aqarios.com/
6
6
  License: Apache-2.0
@@ -1,7 +1,7 @@
1
1
  luna_sdk/__init__.py,sha256=9s6JkcSeRF4WtFo80TelzXXHFhX8w7fXiaJr59V9ScM,100
2
2
  luna_sdk/controllers/__init__.py,sha256=ivTapH8np5mQeVEevxwsWawCtVSG4Wep72rNp7nEZXw,60
3
3
  luna_sdk/controllers/luna_http_client.py,sha256=_q3_o-bjC61uQMnNTfbbGei0eNR_AoIv-2R1cYRfEgU,819
4
- luna_sdk/controllers/luna_platform_client.py,sha256=EH1jxruuRKwaJ1Vos79PGT4-hwp7jdoSaRFKqjUMbZA,2406
4
+ luna_sdk/controllers/luna_platform_client.py,sha256=TUeK9hlbY3LdYkl0UO2FJtCzGFuU8lshA-kdutkDZlM,2406
5
5
  luna_sdk/controllers/luna_q.py,sha256=cv28o2fYDSaI8iAsfMYWtR68mfuUDxY3jmBWY2KnkRk,1199
6
6
  luna_sdk/controllers/luna_solve.py,sha256=ioMdB7Rlx-1-XB5WE5OT8oVlO_T1l5T64R-ccaNUCAA,1797
7
7
  luna_sdk/controllers/luna_transform.py,sha256=7kdIp5oRMG1NQZ1hBSkcNrj-z6g_2dWvQZ4j8BK3M0A,1337
@@ -24,9 +24,9 @@ luna_sdk/interfaces/cplex_repo_i.py,sha256=a2CWG1m4YmQAlcM022Xfk09BHVmcd3y2H-GMr
24
24
  luna_sdk/interfaces/info_repo_i.py,sha256=hCUYNoqjAKwz6l-61XtymX-UboosDX1RaTTiX64EXXc,1345
25
25
  luna_sdk/interfaces/lp_repo_i.py,sha256=hixIKvJ8jz9VOUi33B3K2VvFLcR7eKfeooJwktquyhc,3052
26
26
  luna_sdk/interfaces/optimization_repo_i.py,sha256=4JZikxWTJZTX4tG85ydSP711WROQ5B8RtbvOp1EDvxE,6202
27
- luna_sdk/interfaces/qpu_token_repo_i.py,sha256=OeF9PRcGBjHzNwrllt266M2ELJ7h03c7gt_16FPh4yg,4351
27
+ luna_sdk/interfaces/qpu_token_repo_i.py,sha256=oTxYxoeMOPJUV4-U1Fd1kD76EVPGmi1Sp9C1J4cvffY,11418
28
28
  luna_sdk/interfaces/repository_i.py,sha256=vJz8pbggkuLLC333qzjepj3TMPh49LUnyh3pJDlcGi0,287
29
- luna_sdk/interfaces/solutions_repo_i.py,sha256=Xu-8qQkPoedIp47Uc0ogv5HS45Plsi6zRBEQouxRws0,7463
29
+ luna_sdk/interfaces/solutions_repo_i.py,sha256=uSAClqt_zfg-k9VvVn8DfkG2vE2NXyCqaxRlaK8mCb4,8012
30
30
  luna_sdk/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
31
31
  luna_sdk/repositories/__init__.py,sha256=HxD02fpzlcIt5YkBHd7LwIp_eE6eFuAz2VDnlrakwJQ,169
32
32
  luna_sdk/repositories/circuit_repo.py,sha256=gpjEmCRrl8UghJrelOt6VOULIJmM-thJAhf8oaA5Ckg,1964
@@ -34,14 +34,15 @@ luna_sdk/repositories/cplex_repo.py,sha256=6vlx6YTJoDSWFSZDDNrPk3E7pa5WWGqG25bhT
34
34
  luna_sdk/repositories/info_repo.py,sha256=GzRW5RwhRJrNjujw8Y7vJY8vV_tHzbfwXo0viHuxqUM,1270
35
35
  luna_sdk/repositories/lp_repo.py,sha256=T44XMbdbW7k9a4z6JgIj1kb0bBZxepn-93vxdZOQa80,4370
36
36
  luna_sdk/repositories/optimization_repo.py,sha256=xHjMdXhzdwt9DtZG7AvGtUgOqWH142veOpAzaNe-nxk,6078
37
- luna_sdk/repositories/qpu_token_repo.py,sha256=Mn3ojxXhLIC-zbjBzEJis6WKNHUYUVkex_qTcuXeQ3Y,4685
38
- luna_sdk/repositories/solutions_repo.py,sha256=xI1KQ1JeleBJrBRFxfuxdusb_pgjBLeLhdpFi7nqdXY,8825
37
+ luna_sdk/repositories/qpu_token_repo.py,sha256=_qM9dJB23AR1-Kblx_yJcovYmuYwGcZMjH2va19F8yg,8840
38
+ luna_sdk/repositories/solutions_repo.py,sha256=W-VHmhN6wkL3jSg4FE0IyVLydatLE7LjqI-RhP21XFs,9073
39
39
  luna_sdk/schemas/__init__.py,sha256=lTix3zUl2Z8ZLA2BTF4pls5S-kqlVZ3cIdAZwGxPSUI,248
40
40
  luna_sdk/schemas/circuit.py,sha256=r3Bv0lyhrvFoI3Gf8eq-PS3kyivTWY3IJmRH0X2LoCk,1067
41
- luna_sdk/schemas/create/__init__.py,sha256=7G2yflImpZJxHn3l4Op5CsQAxwKGmvWJSttq9kmiHq0,90
41
+ luna_sdk/schemas/create/__init__.py,sha256=WTthzwyS0PI2zSENoHp7EWLciLz_DyFebCzSCFVensU,144
42
42
  luna_sdk/schemas/create/circuit.py,sha256=zYtM6SV1QH4JzjYaAhrGNjdNn8EDYsdG1QKwayTqkEY,643
43
43
  luna_sdk/schemas/create/optimization.py,sha256=Z9pKoD0y6BjKvl8gQ6XK76bdvq8etvcoNU4RwxnUvHA,759
44
44
  luna_sdk/schemas/create/qpu_token.py,sha256=_D_QtYOeZQ6b0lG5ALTDmyr4bU42bUZ8OJ0VdwadMNA,380
45
+ luna_sdk/schemas/create/qpu_token_time_quota.py,sha256=5HyfYuXGZmpqB-j4yuStFc7V3b7niPYHYb0KIuvJAzQ,650
45
46
  luna_sdk/schemas/create/qubo.py,sha256=5Y_jWicEnoV82Ubc-f0a_qy9hCuPBumhsGWY8wzMIuA,293
46
47
  luna_sdk/schemas/create/solution.py,sha256=zPPgm0wGwfn23ccgBoYs6SMTZNmbT_uO1po_je15WjA,386
47
48
  luna_sdk/schemas/enums/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -50,10 +51,10 @@ luna_sdk/schemas/enums/optimization.py,sha256=XtFdcfLxGe-MAL64itjxszhRkTcUzUf83t
50
51
  luna_sdk/schemas/enums/problem.py,sha256=HWL6Lc1pqPtJ0J-rXkUTL6WHe2fiBY1ctuZvDnx1hmM,754
51
52
  luna_sdk/schemas/enums/qpu_token_type.py,sha256=KBRrB8ExuTTmpp48obxdJGWwWEHb7xgq9Ajjwptl1VY,105
52
53
  luna_sdk/schemas/enums/solution.py,sha256=Vax6MX62UDwApbwzf1nrhuFWw1Iiq77gUch7_1roCYo,114
53
- luna_sdk/schemas/enums/status.py,sha256=KHaOgePqB3GNhFYLo2Sp-JAEXBPN_ZVDmj2WobrT5N4,204
54
+ luna_sdk/schemas/enums/status.py,sha256=D0ZEu6Bg0GspDrjujwrtRAmkF50m2cUT-b0MOiAi4sg,227
54
55
  luna_sdk/schemas/enums/timeframe.py,sha256=vwoZsgAYGvqF67qdcXMEnHkqbiRcVY5uK-4-ZTFcurI,238
55
56
  luna_sdk/schemas/error_message.py,sha256=svCs-mWQsp3BMEhzZFqskbyP6iS78eVUOPaiWFc4sEQ,307
56
- luna_sdk/schemas/optimization.py,sha256=X7Eb7K7ximWpmtIItn2sJEgxgN8dmlvuioQV-Q71BrY,3174
57
+ luna_sdk/schemas/optimization.py,sha256=juFzE7UUAnLoLvZneOwpXzzhsSUQ2dpXIX48Bm0Sdzg,3172
57
58
  luna_sdk/schemas/optimization_formats/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
58
59
  luna_sdk/schemas/optimization_formats/bqm.py,sha256=rrmiZYe_iEdgBFusJeJfY8PVSxgf1Wv79FgMQUm2YVs,910
59
60
  luna_sdk/schemas/optimization_formats/cqm.py,sha256=VZiNJy4yc-8o3gHoH0E-uaNOHj7UfAGCqznTzKBv0NQ,4257
@@ -62,12 +63,13 @@ luna_sdk/schemas/optimization_formats/qm.py,sha256=yUEZF7FOvXv1Mb5FMiX1q0Rk5w2lt
62
63
  luna_sdk/schemas/optimization_formats/qubo.py,sha256=YN-VbPGTgqOKJuJ7t_TT8H_WIWr1ifU974K98W9Blao,135
63
64
  luna_sdk/schemas/pretty_base.py,sha256=ZyVdwdY5JfmNlfqZDm6MdTs5roNGtv0Pe805r4N25Z4,1845
64
65
  luna_sdk/schemas/qpu_token.py,sha256=CFKbAhFgo0G-LO_lameHH4-iOFUJWx9hmMWi3xQwURw,1508
66
+ luna_sdk/schemas/qpu_token_time_quota.py,sha256=tIlYU2i43m93BOaCUrv62baY3RSIScWBqbD0BBlwES4,656
65
67
  luna_sdk/schemas/representation.py,sha256=0RKVV0XxHOJZ1o9grxTq5ri3cGLziyCFObDwQuXIOEY,364
66
68
  luna_sdk/schemas/rest/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
67
69
  luna_sdk/schemas/rest/qpu_token/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
68
70
  luna_sdk/schemas/rest/qpu_token/qpu_token_source.py,sha256=EPMXHpgxqsQ4uJ1hlwe5gPdSsjuHEuKKAIMtBFgPJ1A,583
69
71
  luna_sdk/schemas/rest/qpu_token/token_provider.py,sha256=3Gecn2AmN7E_wAPUac_c55Fg-LwdDKsgbwAN2-0msJU,2985
70
- luna_sdk/schemas/solution.py,sha256=3I4J-7UXNV95kpK0yjB4iPdq2lx3KB_cZ81m4WNbWwg,8684
72
+ luna_sdk/schemas/solution.py,sha256=bNgd0UpsaQM_TrgTB-CJJiXuTg1ubMJP33y813yd5WY,8818
71
73
  luna_sdk/schemas/solver_info.py,sha256=ZUCdTI8zpPZ8EquLYyrLU35pZ4VkzcPUSYeQWkdijHM,799
72
74
  luna_sdk/schemas/solver_parameters/aws/__init__.py,sha256=CXjKWzgnP_d1_RvQUfWyaaWvsZ1FxLJN5K61QmRa-uw,33
73
75
  luna_sdk/schemas/solver_parameters/aws/optimizer_params.py,sha256=w0eg1SnTpKnuq48YG8JAC1LY0bxsTlZIJ2XbT2ySTHw,1374
@@ -160,7 +162,7 @@ luna_sdk/schemas/wrappers/datetime_wrapper.py,sha256=6usmPJNRYA4Fe_-0NGwe7RYams4
160
162
  luna_sdk/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
161
163
  luna_sdk/utils/parameter_finder.py,sha256=LKkd1upH3Djd6eqkcSQ2feNwPUiKi8soYkx6JT1_VSg,2937
162
164
  luna_sdk/utils/qpu_tokens.py,sha256=xrh5KSoWzbul-6eRa0ELH9iwEENanE7PIms7jlCt3NY,1641
163
- luna_quantum-0.0.37.dist-info/LICENSE,sha256=rwwuFPLz36oRvjWu2oEeX42Qtn9gmbh7zRC2OqCFNaI,11342
164
- luna_quantum-0.0.37.dist-info/METADATA,sha256=199H7vfTIgzdGHF0Bz6eFhCtJnhHMiQuxl93YicnhYk,2311
165
- luna_quantum-0.0.37.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
166
- luna_quantum-0.0.37.dist-info/RECORD,,
165
+ luna_quantum-0.10.1.dist-info/LICENSE,sha256=rwwuFPLz36oRvjWu2oEeX42Qtn9gmbh7zRC2OqCFNaI,11342
166
+ luna_quantum-0.10.1.dist-info/METADATA,sha256=BD5AD8c3uY615XODFmYbFvnf9_WsLt4P_e5K457-KsM,2311
167
+ luna_quantum-0.10.1.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
168
+ luna_quantum-0.10.1.dist-info/RECORD,,
@@ -1,6 +1,6 @@
1
1
  import os
2
2
  from enum import Enum
3
- from typing import Optional, Literal
3
+ from typing import Literal, Optional
4
4
 
5
5
  import httpx
6
6
 
@@ -1,9 +1,11 @@
1
1
  from abc import ABC, abstractmethod
2
+ from datetime import datetime
2
3
  from typing import Dict, List, Optional
3
4
 
4
5
  from luna_sdk.interfaces.repository_i import IRepository
5
6
  from luna_sdk.schemas import QpuTokenOut
6
7
  from luna_sdk.schemas.enums.qpu_token_type import QpuTokenTypeEnum
8
+ from luna_sdk.schemas.qpu_token_time_quota import QpuTokenTimeQuotaOut
7
9
 
8
10
 
9
11
  class IQpuTokenRepo(IRepository, ABC):
@@ -145,3 +147,201 @@ class IQpuTokenRepo(IRepository, ABC):
145
147
  Parameters to pass to `httpx.request`.
146
148
  """
147
149
  raise NotImplementedError
150
+
151
+ @abstractmethod
152
+ def create_group_time_quota(
153
+ self,
154
+ qpu_token_name: str,
155
+ quota: int,
156
+ start: Optional[datetime] = None,
157
+ end: Optional[datetime] = None,
158
+ **kwargs,
159
+ ) -> None:
160
+ """Create a time quota policy for a shared QPU token that affects every user of
161
+ the group.
162
+
163
+ Parameters
164
+ ----------
165
+ qpu_token_name : str
166
+ The name of the qpu token. Currently, only DWave tokens are supported.
167
+ quota : int
168
+ quota : int
169
+ The amount of quota to add. For DWave Quantum Annealing, which is currently
170
+ the only algorithm that supports time quota, this is the qpu access time in
171
+ nanoseconds.
172
+ start : Optional[datetime], optional
173
+ The date and time from which the policy is active. If None, the current date
174
+ and time will be used. If the policy is currently not effective, the token
175
+ cannot be used at all.
176
+ Default: None
177
+ end : Optional[datetime], optional
178
+ The date and time until which the policy is active. If None, the policy if
179
+ effective until 265 days after the start date. If the policy is currently
180
+ not effective, the token cannot be used at all.
181
+ Default: None
182
+ """
183
+ raise NotImplementedError
184
+
185
+ @abstractmethod
186
+ def get_group_time_quota(
187
+ self, qpu_token_name: str, **kwargs
188
+ ) -> Optional[QpuTokenTimeQuotaOut]:
189
+ """Get the group time quota policy for a qpu token.
190
+
191
+ Parameters
192
+ ----------
193
+ qpu_token_name : str
194
+ The name of the qpu token.
195
+
196
+ Returns
197
+ -------
198
+ Optional[QpuTokenTimeQuotaOut]
199
+ The token policy. None, if no group policy is set on this token.
200
+ """
201
+ raise NotImplementedError
202
+
203
+ @abstractmethod
204
+ def update_group_time_quota(
205
+ self,
206
+ qpu_token_name: str,
207
+ quota: Optional[int] = None,
208
+ start: Optional[datetime] = None,
209
+ end: Optional[datetime] = None,
210
+ **kwargs,
211
+ ) -> None:
212
+ """Update the details on a group qpu time quota policy.
213
+
214
+ Parameters
215
+ ----------
216
+ qpu_token_name : str
217
+ The name of the qpu token.
218
+ quota : Optional[int], optional
219
+ The amount of quota. For DWave Quantum Annealing, which is currently the
220
+ only supported solver, this is the qpu access time in nanoseconds. If None,
221
+ the available quota won't be updated.
222
+ Default: None
223
+ start : Optional[datetime], optional
224
+ The date and time from which the policy is active. If None, the start date
225
+ won't be updated.
226
+ Default: None
227
+ end : Optional[datetime], optional
228
+ The date and time until which the policy is active. If None, the end date
229
+ won't be updated.
230
+ Default: None
231
+ """
232
+ raise NotImplementedError
233
+
234
+ @abstractmethod
235
+ def delete_group_time_quota(self, qpu_token_name: str, **kwargs) -> None:
236
+ """Delete the group policy set on a qpu token.
237
+
238
+ Parameters
239
+ ----------
240
+ qpu_token_name : str
241
+ The name of the qpu token.
242
+ """
243
+ raise NotImplementedError
244
+
245
+ @abstractmethod
246
+ def create_user_time_quota(
247
+ self,
248
+ qpu_token_name: str,
249
+ user_email: str,
250
+ quota: int,
251
+ start: Optional[datetime] = None,
252
+ end: Optional[datetime] = None,
253
+ **kwargs,
254
+ ) -> None:
255
+ """Create a time quota policy for a shared QPU token that affects a single user
256
+ of the group.
257
+
258
+ Parameters
259
+ ----------
260
+ qpu_token_name : str
261
+ The name of the qpu token. Currently, only DWave tokens are supported.
262
+ user_email : str
263
+ Email of the user for whom to add the policy.
264
+ quota : int
265
+ The amount of quota to add. For DWave Quantum Annealing, which is currently
266
+ the only algorithm that supports time quota, this is the qpu access time in
267
+ nanoseconds.
268
+ start : Optional[datetime], optional
269
+ The date and time from which the policy is active. If None, the current date
270
+ and time will be used. If the policy is currently not effective, the token
271
+ cannot be used at all.
272
+ Default: None
273
+ end : Optional[datetime], optional
274
+ The date and time until which the policy is active. If None, the policy if
275
+ effective until 265 days after the start date. If the policy is currently
276
+ not effective, the token cannot be used at all.
277
+ Default: None
278
+ """
279
+ raise NotImplementedError
280
+
281
+ @abstractmethod
282
+ def get_user_time_quota(
283
+ self, qpu_token_name: str, user_email: str, **kwargs
284
+ ) -> Optional[QpuTokenTimeQuotaOut]:
285
+ """Get a user-specific time quota policy for a qpu token.
286
+
287
+ Parameters
288
+ ----------
289
+ qpu_token_name : str
290
+ The name of the qpu token.
291
+ user_email : str
292
+ Email of the user for whom to get the policy.
293
+
294
+ Returns
295
+ -------
296
+ Optional[QpuTokenTimeQuotaOut]
297
+ The token policy. None, if no policy is set on this token for the specified
298
+ user.
299
+ """
300
+ raise NotImplementedError
301
+
302
+ @abstractmethod
303
+ def update_user_time_quota(
304
+ self,
305
+ qpu_token_name: str,
306
+ user_email: str,
307
+ quota: Optional[int] = None,
308
+ start: Optional[datetime] = None,
309
+ end: Optional[datetime] = None,
310
+ **kwargs,
311
+ ) -> None:
312
+ """Update the details on a user-specific qpu time quota policy.
313
+
314
+ Parameters
315
+ ----------
316
+ qpu_token_name : str
317
+ The name of the qpu token.
318
+ user_email : str
319
+ Email of the user for whom to update the policy.
320
+ quota : Optional[int], optional
321
+ The amount of quota. For DWave Quantum Annealing, which is currently the
322
+ only supported solver, this is the qpu access time in nanoseconds. If None,
323
+ the available quota won't be updated.
324
+ Default: None
325
+ start : Optional[datetime], optional
326
+ The date and time from which the policy is active. If None, the start date
327
+ won't be updated.
328
+ Default: None
329
+ end : Optional[datetime], optional
330
+ The date and time until which the policy is active. If None, the end date
331
+ won't be updated.
332
+ Default: None
333
+ """
334
+ raise NotImplementedError
335
+
336
+ @abstractmethod
337
+ def delete_user_time_quota(
338
+ self, qpu_token_name: str, user_email: str, **kwargs
339
+ ) -> None:
340
+ """Delete a user-specific policy set on a qpu token.
341
+
342
+ Parameters
343
+ ----------
344
+ qpu_token_name : str
345
+ The name of the qpu token.
346
+ """
347
+ raise NotImplementedError
@@ -231,3 +231,26 @@ class ISolutionsRepo(IRepository, ABC):
231
231
  not (yet) available or the solution sense is `None`, `None` is returned.
232
232
  """
233
233
  raise NotImplementedError
234
+
235
+ @abstractmethod
236
+ def cancel(
237
+ self,
238
+ solution_id: str,
239
+ **kwargs,
240
+ ) -> Solution:
241
+ """
242
+ Cancel a solve job for an optimization.
243
+
244
+ Parameters
245
+ ----------
246
+ solution_id: str
247
+ The id of the solution which should be canceled.
248
+ **kwargs
249
+ Parameters to pass to `httpx.request`.
250
+
251
+ Returns
252
+ -------
253
+ SolutionOut
254
+ The location where the solution can be found once solving is complete.
255
+ """
256
+ raise NotImplementedError
@@ -1,5 +1,5 @@
1
1
  import json
2
- import os
2
+ from datetime import datetime
3
3
  from typing import Dict, List, Optional
4
4
 
5
5
  from httpx import Response
@@ -7,9 +7,9 @@ from pydantic import TypeAdapter
7
7
 
8
8
  from luna_sdk.interfaces.qpu_token_repo_i import IQpuTokenRepo
9
9
  from luna_sdk.schemas import QpuTokenOut
10
- from luna_sdk.schemas.create import QpuTokenIn
10
+ from luna_sdk.schemas.create import QpuTokenIn, QpuTokenTimeQuotaIn
11
11
  from luna_sdk.schemas.enums.qpu_token_type import QpuTokenTypeEnum
12
-
12
+ from luna_sdk.schemas.qpu_token_time_quota import QpuTokenTimeQuotaOut
13
13
 
14
14
  _ORGANIZATION_QPU_TOKENS_BACKEND = "shared"
15
15
  _PERSONAL_QPU_TOKENS_BACKEND = "private"
@@ -141,3 +141,125 @@ class QpuTokenRepo(IQpuTokenRepo):
141
141
  f"{self._get_endpoint_by_type(token_type)}/{name}", **kwargs
142
142
  )
143
143
  response.raise_for_status()
144
+
145
+ def create_group_time_quota(
146
+ self,
147
+ qpu_token_name: str,
148
+ quota: int,
149
+ start: Optional[datetime] = None,
150
+ end: Optional[datetime] = None,
151
+ **kwargs,
152
+ ) -> None:
153
+ time_quota = QpuTokenTimeQuotaIn(quota=quota, start=start, end=end)
154
+
155
+ endpoint = self._get_endpoint_by_type(QpuTokenTypeEnum.GROUP)
156
+ response = self._client.post(
157
+ f"{endpoint}/quota/group/{qpu_token_name}",
158
+ content=time_quota.model_dump_json(),
159
+ **kwargs,
160
+ )
161
+ response.raise_for_status()
162
+
163
+ def get_group_time_quota(
164
+ self, qpu_token_name: str, **kwargs
165
+ ) -> Optional[QpuTokenTimeQuotaOut]:
166
+ endpoint = self._get_endpoint_by_type(QpuTokenTypeEnum.GROUP)
167
+ response = self._client.get(
168
+ f"{endpoint}/quota/group/{qpu_token_name}", **kwargs
169
+ )
170
+ response.raise_for_status()
171
+
172
+ time_quota_data = response.json()
173
+
174
+ if time_quota_data is None:
175
+ return None
176
+ return QpuTokenTimeQuotaOut.model_validate(time_quota_data)
177
+
178
+ def update_group_time_quota(
179
+ self,
180
+ qpu_token_name: str,
181
+ quota: Optional[int] = None,
182
+ start: Optional[datetime] = None,
183
+ end: Optional[datetime] = None,
184
+ **kwargs,
185
+ ) -> None:
186
+ data = {"quota": quota, "start": start, "end": end}
187
+
188
+ endpoint = self._get_endpoint_by_type(QpuTokenTypeEnum.GROUP)
189
+ response = self._client.patch(
190
+ f"{endpoint}/quota/group/{qpu_token_name}",
191
+ content=json.dumps(data),
192
+ **kwargs,
193
+ )
194
+ response.raise_for_status()
195
+
196
+ def delete_group_time_quota(self, qpu_token_name: str, **kwargs) -> None:
197
+ endpoint = self._get_endpoint_by_type(QpuTokenTypeEnum.GROUP)
198
+ response = self._client.delete(
199
+ f"{endpoint}/quota/group/{qpu_token_name}",
200
+ **kwargs,
201
+ )
202
+ response.raise_for_status()
203
+
204
+ def create_user_time_quota(
205
+ self,
206
+ qpu_token_name: str,
207
+ user_email: str,
208
+ quota: int,
209
+ start: Optional[datetime] = None,
210
+ end: Optional[datetime] = None,
211
+ **kwargs,
212
+ ) -> None:
213
+ time_quota = QpuTokenTimeQuotaIn(quota=quota, start=start, end=end)
214
+
215
+ endpoint = self._get_endpoint_by_type(QpuTokenTypeEnum.GROUP)
216
+ response = self._client.post(
217
+ f"{endpoint}/quota/user/{qpu_token_name}/{user_email}",
218
+ content=time_quota.model_dump_json(),
219
+ **kwargs,
220
+ )
221
+ response.raise_for_status()
222
+
223
+ def get_user_time_quota(
224
+ self, qpu_token_name: str, user_email: str, **kwargs
225
+ ) -> Optional[QpuTokenTimeQuotaOut]:
226
+ endpoint = self._get_endpoint_by_type(QpuTokenTypeEnum.GROUP)
227
+ response = self._client.get(
228
+ f"{endpoint}/quota/user/{qpu_token_name}/{user_email}", **kwargs
229
+ )
230
+ response.raise_for_status()
231
+
232
+ time_quota_data = response.json()
233
+
234
+ if time_quota_data is None:
235
+ return None
236
+ return QpuTokenTimeQuotaOut.model_validate(time_quota_data)
237
+
238
+ def update_user_time_quota(
239
+ self,
240
+ qpu_token_name: str,
241
+ user_email: str,
242
+ quota: Optional[int] = None,
243
+ start: Optional[datetime] = None,
244
+ end: Optional[datetime] = None,
245
+ **kwargs,
246
+ ) -> None:
247
+ data = {"quota": quota, "start": start, "end": end}
248
+
249
+ endpoint = self._get_endpoint_by_type(QpuTokenTypeEnum.GROUP)
250
+ response = self._client.patch(
251
+ f"{endpoint}/quota/user/{qpu_token_name}/{user_email}",
252
+ content=json.dumps(data),
253
+ **kwargs,
254
+ )
255
+ response.raise_for_status()
256
+
257
+ def delete_user_time_quota(
258
+ self, qpu_token_name: str, user_email: str, **kwargs
259
+ ) -> None:
260
+ endpoint = self._get_endpoint_by_type(QpuTokenTypeEnum.GROUP)
261
+ response = self._client.delete(
262
+ f"{endpoint}/quota/user/{qpu_token_name}/{user_email}",
263
+ **kwargs,
264
+ )
265
+ response.raise_for_status()
@@ -265,3 +265,9 @@ class SolutionsRepo(ISolutionsRepo):
265
265
  "Solving with Luna can still fail due to the parameters."
266
266
  )
267
267
  return params
268
+
269
+ def cancel(self, solution_id: str, **kwargs) -> Solution:
270
+ response = self._client.post(f"{self._endpoint}/{solution_id}/cancel", **kwargs)
271
+
272
+ response.raise_for_status()
273
+ return Solution.model_validate_json(response.text)
@@ -1,3 +1,4 @@
1
1
  from .circuit import CircuitIn
2
2
  from .qpu_token import QpuTokenIn
3
+ from .qpu_token_time_quota import QpuTokenTimeQuotaIn
3
4
  from .qubo import QUBOIn
@@ -0,0 +1,25 @@
1
+ from datetime import datetime
2
+ from typing import Optional
3
+
4
+ from pydantic import BaseModel
5
+
6
+
7
+ class QpuTokenTimeQuotaIn(BaseModel):
8
+ """
9
+ Pydantic model for creating a time quota on a qpu token.
10
+
11
+ Attributes
12
+ ----------
13
+ quota: int
14
+ The amount of quota.
15
+ start: datetime | None
16
+ Effective start date of the time quota policy.
17
+ If None, policy will be in effect immediately.
18
+ end: datetime | None
19
+ Effective end date of the time quota policy.
20
+ If None, policy will be in effect until 365 days after the start date.
21
+ """
22
+
23
+ quota: int
24
+ start: Optional[datetime]
25
+ end: Optional[datetime]
@@ -7,4 +7,5 @@ class StatusEnum(str, Enum):
7
7
  IN_PROGRESS = "IN_PROGRESS"
8
8
  DONE = "DONE"
9
9
  FAILED = "FAILED"
10
- CANCELLED = "CANCELED"
10
+ CANCELED = "CANCELED"
11
+ TIMEOUT = "TIMEOUT"
@@ -56,6 +56,7 @@ class Optimization(PrettyBase):
56
56
  "id": data_subset.pop("id"),
57
57
  "name": data_subset.pop("name"),
58
58
  "original_format": data_subset.pop("original_format"),
59
+ "created_date": data_subset.pop("created_date"),
59
60
  **data_subset,
60
61
  }
61
62
  output += self._pretty_print(ordered_subset)
@@ -63,16 +64,14 @@ class Optimization(PrettyBase):
63
64
 
64
65
  def subset(self):
65
66
  trimmed_keys = [
66
- "created_by",
67
- "modified_date",
68
- "modified_by",
69
- "use_case_name",
70
- "params",
71
- "verbose",
67
+ "id",
68
+ "name",
69
+ "original_format",
70
+ "created_date",
72
71
  ]
73
72
  data = self.model_dump()
74
73
  output = ""
75
- data_subset = {key: data[key] for key in data if key not in trimmed_keys}
74
+ data_subset = {key: data[key] for key in data if key in trimmed_keys}
76
75
 
77
76
  ordered_subset = {
78
77
  "id": data_subset.pop("id"),
@@ -0,0 +1,26 @@
1
+ from datetime import datetime
2
+
3
+ from pydantic import BaseModel
4
+
5
+
6
+ class QpuTokenTimeQuotaOut(BaseModel):
7
+ """
8
+ Pydantic model for QPU token time quota OUT.
9
+ It contains the data received from the API call.
10
+
11
+ Attributes
12
+ ----------
13
+ quota: int
14
+ The total amount of quota available on a qpu token.
15
+ start: datetime
16
+ Effective start date of the time quota policy.
17
+ end: datetime
18
+ Effective end date of the time quota policy.
19
+ quota_used: int
20
+ How much quota has already been used from the totally available amount of quota.
21
+ """
22
+
23
+ quota: int
24
+ start: datetime
25
+ end: datetime
26
+ quota_used: int
@@ -99,7 +99,7 @@ class Solution(PrettyBase):
99
99
  error_message: Optional[str] = None
100
100
  solver_job_info: Optional[str] = None
101
101
 
102
- results: Optional[List[Result]]
102
+ results: Optional[List[Result]] = None
103
103
  params: Dict[str, Any]
104
104
  runtime: Optional[Runtime]
105
105
  sense: Optional[SenseEnum]
@@ -114,6 +114,9 @@ class Solution(PrettyBase):
114
114
 
115
115
  verbose: bool = False
116
116
 
117
+ is_cancelable: bool = True
118
+ is_cancellation_requested: bool = False
119
+
117
120
  def __str__(self):
118
121
  if self.verbose:
119
122
  return self.details()
@@ -196,6 +199,7 @@ class Solution(PrettyBase):
196
199
  results = data.pop("results") # Extract and remove results from data
197
200
  metadata = data.pop("metadata") # Extract and remove metadata from data
198
201
  provider = data["provider"]
202
+ data.pop("verbose") # Remove verbose field from data
199
203
 
200
204
  divider = "--------------------------------------------------------------------------------\n"
201
205
 
@@ -239,7 +243,7 @@ class Solution(PrettyBase):
239
243
  "created_date",
240
244
  ]
241
245
  data = self.model_dump()
242
- data["optimization_name"] = data["optimization"]["original_format"]
246
+ data["optimization_name"] = data["optimization"]["name"]
243
247
  output = ""
244
248
  data_subset = {key: data.get(key) for key in subset_keys if key in data}
245
249
  output += self._pretty_print(data_subset)