luna-quantum 0.0.29__py3-none-any.whl → 0.0.33__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.29
3
+ Version: 0.0.33
4
4
  Summary: Python SDK for Aqarios' Luna Platform
5
5
  Home-page: https://aqarios.com/
6
6
  License: Apache-2.0
@@ -1,12 +1,12 @@
1
1
  luna_sdk/__init__.py,sha256=9s6JkcSeRF4WtFo80TelzXXHFhX8w7fXiaJr59V9ScM,100
2
2
  luna_sdk/controllers/__init__.py,sha256=ivTapH8np5mQeVEevxwsWawCtVSG4Wep72rNp7nEZXw,60
3
- luna_sdk/controllers/custom_login_client.py,sha256=1sc1h0vLoDEWhMIm3zWp03Ff54C3-9CK84KIM2t57a4,2240
4
- luna_sdk/controllers/luna_platform_client.py,sha256=1IRspVMkwcEaKYJhr1NDQ0kWXu7DnQ1tqQZunDOmVXo,1877
5
- luna_sdk/controllers/luna_q.py,sha256=IVaclfTQKPSY28rucssWsLSsmXHA5pS-CB_kmPLbchg,1230
6
- luna_sdk/controllers/luna_solve.py,sha256=nFSqgB0UEC8VLvfDl3Iinm8cfos08vWlEg8lVgzsMX0,1777
7
- luna_sdk/controllers/luna_transform.py,sha256=eFUU1RafYMUPZ-E_QZNQfYD-zMkcZOvwYtwgmvKHsXQ,1286
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
5
+ luna_sdk/controllers/luna_q.py,sha256=cv28o2fYDSaI8iAsfMYWtR68mfuUDxY3jmBWY2KnkRk,1199
6
+ luna_sdk/controllers/luna_solve.py,sha256=ioMdB7Rlx-1-XB5WE5OT8oVlO_T1l5T64R-ccaNUCAA,1797
7
+ luna_sdk/controllers/luna_transform.py,sha256=7kdIp5oRMG1NQZ1hBSkcNrj-z6g_2dWvQZ4j8BK3M0A,1337
8
8
  luna_sdk/error/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
- luna_sdk/error/http_error_utils.py,sha256=1-Q-W-_RaHKlA2zOXJLLaZamBWNQpf9Oc4SAX4hJdEk,3317
9
+ luna_sdk/error/http_error_utils.py,sha256=qZ4a43GVR35-bn3QTVmGZBJzEjieo43r36M2G5rfIyw,3509
10
10
  luna_sdk/exceptions/__init__.py,sha256=DSKaPN374rR2zccmpLvlqntxDsjFwgSexXtva795ae0,52
11
11
  luna_sdk/exceptions/encryption_exception.py,sha256=qe38EPRen4c63ti6bbA3jXl4PK48Ommi_cb2Lvhn8tg,264
12
12
  luna_sdk/exceptions/luna_exception.py,sha256=m7U3qFpP9Sc77Z3RG9I4bQXsJSQuVeBLvfHQWziC9sQ,114
@@ -23,8 +23,8 @@ luna_sdk/interfaces/clients/luna_transform_i.py,sha256=xpS2ODs83rICbA3oAKzf80rpB
23
23
  luna_sdk/interfaces/cplex_repo_i.py,sha256=a2CWG1m4YmQAlcM022Xfk09BHVmcd3y2H-GMr1N4vx8,3786
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
- luna_sdk/interfaces/optimization_repo_i.py,sha256=jaq6YXmFtUb6BbsLJos6B9VSzBUJ6YxgscNm6DyIl3M,6154
27
- luna_sdk/interfaces/qpu_token_repo_i.py,sha256=kokPGQj7k1E2UzG1W1ZycjET5ZPvjdQl1kqBT2vGTNM,4505
26
+ luna_sdk/interfaces/optimization_repo_i.py,sha256=4JZikxWTJZTX4tG85ydSP711WROQ5B8RtbvOp1EDvxE,6202
27
+ luna_sdk/interfaces/qpu_token_repo_i.py,sha256=q5aWiGxFnuRSasgHcceRAjQ0NvMPRoBfkeJHCByBy_0,4626
28
28
  luna_sdk/interfaces/repository_i.py,sha256=vJz8pbggkuLLC333qzjepj3TMPh49LUnyh3pJDlcGi0,287
29
29
  luna_sdk/interfaces/solutions_repo_i.py,sha256=YmQxgDGSLZNQ-P7jzlw1zTnut5Q1KVeRbcJEuocB3VQ,7767
30
30
  luna_sdk/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -33,8 +33,8 @@ luna_sdk/repositories/circuit_repo.py,sha256=h3Moypl-pba8J-sNTBsOxnbKtu6RCmmX5c_
33
33
  luna_sdk/repositories/cplex_repo.py,sha256=6vlx6YTJoDSWFSZDDNrPk3E7pa5WWGqG25bhTwQdqHQ,5098
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
- luna_sdk/repositories/optimization_repo.py,sha256=UHqJ_dZ9jyQF205naREyk10FUCuC6HfJ1dAxjMBS39M,6025
37
- luna_sdk/repositories/qpu_token_repo.py,sha256=_9r418j-wHksZ-cSNHeQb_slz7yn5WniovjV7qv2e0E,4343
36
+ luna_sdk/repositories/optimization_repo.py,sha256=xHjMdXhzdwt9DtZG7AvGtUgOqWH142veOpAzaNe-nxk,6078
37
+ luna_sdk/repositories/qpu_token_repo.py,sha256=6V3PH2YLMoWx6Dv6hxDoe2ohXH2mRN37nfvzVS6bHDA,5063
38
38
  luna_sdk/repositories/solutions_repo.py,sha256=Q5Q30oRyUnayXkp4z_jPcjDpxYRoPjzWBWUqg2EAFWQ,9242
39
39
  luna_sdk/schemas/__init__.py,sha256=lTix3zUl2Z8ZLA2BTF4pls5S-kqlVZ3cIdAZwGxPSUI,248
40
40
  luna_sdk/schemas/circuit.py,sha256=r3Bv0lyhrvFoI3Gf8eq-PS3kyivTWY3IJmRH0X2LoCk,1067
@@ -46,25 +46,27 @@ luna_sdk/schemas/create/qubo.py,sha256=5Y_jWicEnoV82Ubc-f0a_qy9hCuPBumhsGWY8wzMI
46
46
  luna_sdk/schemas/create/solution.py,sha256=K97JHH-p5z0P_niTVX6YBPoDc0rgIpJG5O4uaUhcs48,410
47
47
  luna_sdk/schemas/enums/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
48
48
  luna_sdk/schemas/enums/circuit.py,sha256=smz_DouDo_K8rs4N5aIOj2PS9w6DX1CFYX0bv6f6JFw,252
49
- luna_sdk/schemas/enums/optimization.py,sha256=K-lv6PLJ4qo4vNVEKHsLU1rEv-QnFfl_FlN1xqZOXUc,170
49
+ luna_sdk/schemas/enums/optimization.py,sha256=XtFdcfLxGe-MAL64itjxszhRkTcUzUf83tO-5DBVLeY,198
50
50
  luna_sdk/schemas/enums/problem.py,sha256=HWL6Lc1pqPtJ0J-rXkUTL6WHe2fiBY1ctuZvDnx1hmM,754
51
- luna_sdk/schemas/enums/qpu_token_type.py,sha256=UwaZoaCRAc2x_sLszRP55RwuU03u5GlJ-oK0u84Tbgo,119
51
+ luna_sdk/schemas/enums/qpu_token_type.py,sha256=KBRrB8ExuTTmpp48obxdJGWwWEHb7xgq9Ajjwptl1VY,105
52
52
  luna_sdk/schemas/enums/solution.py,sha256=Vax6MX62UDwApbwzf1nrhuFWw1Iiq77gUch7_1roCYo,114
53
53
  luna_sdk/schemas/enums/status.py,sha256=KHaOgePqB3GNhFYLo2Sp-JAEXBPN_ZVDmj2WobrT5N4,204
54
54
  luna_sdk/schemas/enums/timeframe.py,sha256=vwoZsgAYGvqF67qdcXMEnHkqbiRcVY5uK-4-ZTFcurI,238
55
55
  luna_sdk/schemas/error_message.py,sha256=svCs-mWQsp3BMEhzZFqskbyP6iS78eVUOPaiWFc4sEQ,307
56
- luna_sdk/schemas/optimization.py,sha256=cB57hs_7VsE8h4YQGj3XuX4Mqp3SZmnu2Y90s4jl1jw,2033
56
+ luna_sdk/schemas/optimization.py,sha256=pCbDL93PFGf7IOGz-0PHFrrpOwQdszm78WnS0oo2xqU,1884
57
57
  luna_sdk/schemas/optimization_formats/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
58
58
  luna_sdk/schemas/optimization_formats/bqm.py,sha256=rrmiZYe_iEdgBFusJeJfY8PVSxgf1Wv79FgMQUm2YVs,910
59
59
  luna_sdk/schemas/optimization_formats/cqm.py,sha256=VZiNJy4yc-8o3gHoH0E-uaNOHj7UfAGCqznTzKBv0NQ,4257
60
60
  luna_sdk/schemas/optimization_formats/lp.py,sha256=iXFDBmHktHsYc79ngSraylCpa-EVMFwN01788fnjFzY,175
61
61
  luna_sdk/schemas/optimization_formats/qm.py,sha256=yUEZF7FOvXv1Mb5FMiX1q0Rk5w2ltrh7HInfFEiVSXU,912
62
+ luna_sdk/schemas/optimization_formats/qubo.py,sha256=YN-VbPGTgqOKJuJ7t_TT8H_WIWr1ifU974K98W9Blao,135
62
63
  luna_sdk/schemas/pretty_base.py,sha256=ZyVdwdY5JfmNlfqZDm6MdTs5roNGtv0Pe805r4N25Z4,1845
63
- luna_sdk/schemas/qpu_token.py,sha256=SRpqMynft7GwiOlEQCYkVQyfcbtm9szuXIHQRtgRU_s,1575
64
+ luna_sdk/schemas/qpu_token.py,sha256=CFKbAhFgo0G-LO_lameHH4-iOFUJWx9hmMWi3xQwURw,1508
64
65
  luna_sdk/schemas/representation.py,sha256=0RKVV0XxHOJZ1o9grxTq5ri3cGLziyCFObDwQuXIOEY,364
65
66
  luna_sdk/schemas/rest/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
66
67
  luna_sdk/schemas/rest/qpu_token/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
67
- luna_sdk/schemas/rest/qpu_token/token_provider.py,sha256=yDD17uIuio5FisarDBiGQwMpl-_QXRYttuFAZ9w-V00,1430
68
+ luna_sdk/schemas/rest/qpu_token/qpu_token_source.py,sha256=EPMXHpgxqsQ4uJ1hlwe5gPdSsjuHEuKKAIMtBFgPJ1A,583
69
+ luna_sdk/schemas/rest/qpu_token/token_provider.py,sha256=3Gecn2AmN7E_wAPUac_c55Fg-LwdDKsgbwAN2-0msJU,2985
68
70
  luna_sdk/schemas/solution.py,sha256=IRtZneNRN5IbSEMHKHc0NYJ7lf74RxZTHoYJI7z2QoY,6871
69
71
  luna_sdk/schemas/solver_info.py,sha256=ZUCdTI8zpPZ8EquLYyrLU35pZ4VkzcPUSYeQWkdijHM,799
70
72
  luna_sdk/schemas/solver_parameters/aws/__init__.py,sha256=CXjKWzgnP_d1_RvQUfWyaaWvsZ1FxLJN5K61QmRa-uw,33
@@ -157,8 +159,8 @@ luna_sdk/schemas/wrappers/__init__.py,sha256=1zq5BWRjDidbRJ346JOCSbP6Q9rhf4NiLhZ
157
159
  luna_sdk/schemas/wrappers/datetime_wrapper.py,sha256=6usmPJNRYA4Fe_-0NGwe7RYams46CCAXpJs8YULu_yc,794
158
160
  luna_sdk/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
159
161
  luna_sdk/utils/parameter_finder.py,sha256=LKkd1upH3Djd6eqkcSQ2feNwPUiKi8soYkx6JT1_VSg,2937
160
- luna_sdk/utils/qpu_tokens.py,sha256=XpUNI102TLshfR85ZxvSFmXmH1fb1JAI8NKlIiuWEqc,1535
161
- luna_quantum-0.0.29.dist-info/LICENSE,sha256=rwwuFPLz36oRvjWu2oEeX42Qtn9gmbh7zRC2OqCFNaI,11342
162
- luna_quantum-0.0.29.dist-info/METADATA,sha256=STnBLAwQav1LezmFuJqjCyUepQIDFnYcRl2eS7kIb0w,2311
163
- luna_quantum-0.0.29.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
164
- luna_quantum-0.0.29.dist-info/RECORD,,
162
+ luna_sdk/utils/qpu_tokens.py,sha256=xrh5KSoWzbul-6eRa0ELH9iwEENanE7PIms7jlCt3NY,1641
163
+ luna_quantum-0.0.33.dist-info/LICENSE,sha256=rwwuFPLz36oRvjWu2oEeX42Qtn9gmbh7zRC2OqCFNaI,11342
164
+ luna_quantum-0.0.33.dist-info/METADATA,sha256=5ojTfod6BKHtIKnRn_utUm3CVd9OifvhK8Lk2xqhD8o,2311
165
+ luna_quantum-0.0.33.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
166
+ luna_quantum-0.0.33.dist-info/RECORD,,
@@ -0,0 +1,27 @@
1
+ from importlib.metadata import version
2
+
3
+ import httpx
4
+ from httpx import Client, Response
5
+
6
+ from luna_sdk.error.http_error_utils import HttpErrorUtils
7
+ from luna_sdk.exceptions.timeout_exception import TimeoutException
8
+
9
+
10
+ class LunaHTTPClient(Client):
11
+ _version: str = version("luna-quantum")
12
+
13
+ _user_agent: str = f"LunaSDK/{_version}"
14
+
15
+ def __init__(self, *args, **kwargs):
16
+ super().__init__(*args, **kwargs)
17
+
18
+ self.headers["User-Agent"] = self._user_agent
19
+
20
+ def request(self, *args, **kwargs) -> Response:
21
+ try:
22
+ response: Response = super().request(*args, **kwargs)
23
+ except httpx.TimeoutException:
24
+ # Handle all possible in httpx timeout exceptions
25
+ raise TimeoutException()
26
+ HttpErrorUtils.check_for_error(response)
27
+ return response
@@ -1,21 +1,41 @@
1
1
  import os
2
- from typing import Optional
2
+ from enum import Enum
3
+ from typing import Optional, Literal
3
4
 
4
- from httpx import Client
5
+ import httpx
5
6
 
6
- from luna_sdk.controllers.custom_login_client import CustomLoginClient
7
+ from luna_sdk.controllers.luna_http_client import LunaHTTPClient
8
+ from luna_sdk.error.http_error_utils import HttpErrorUtils
7
9
  from luna_sdk.interfaces.clients.client_i import IClient
8
10
 
9
11
 
12
+ class LunaPrefixEnum(str, Enum):
13
+ LUNA_SOLVE = "luna-solve"
14
+ LUNA_Q = "luna-q"
15
+
16
+
17
+ def check_httpx_exceptions(response):
18
+ HttpErrorUtils.check_for_error(response)
19
+
20
+
21
+ class APIKeyAuth(httpx.Auth):
22
+ def __init__(self, token):
23
+ self.token = token
24
+
25
+ def auth_flow(self, request):
26
+ request.headers["Luna-API-Key"] = self.token
27
+ yield request
28
+
29
+
10
30
  class LunaPlatformClient(IClient):
11
31
  _base_url: str = ""
12
32
 
13
- _client: Client = None # type: ignore
33
+ _client: httpx.Client = None # type: ignore
14
34
 
15
35
  def __init__(
16
36
  self,
17
- email: str,
18
- password: str,
37
+ api_key: str,
38
+ api: LunaPrefixEnum,
19
39
  base_url: str = os.getenv("LUNA_BASE_URL", "https://api.aqarios.com"),
20
40
  timeout: Optional[float] = 240.0,
21
41
  ):
@@ -26,10 +46,10 @@ class LunaPlatformClient(IClient):
26
46
 
27
47
  Parameters
28
48
  ----------
29
- email:
30
- User's email
31
- password:
32
- User's password
49
+ api_key:
50
+ User's API key
51
+ api: str
52
+ Current API with which luna client is working. Can be luna-solve or luna-q.
33
53
  base_url:
34
54
  Base API URL.
35
55
  If you want to use API not on your local PC then change it.
@@ -41,17 +61,15 @@ class LunaPlatformClient(IClient):
41
61
  itself will time out after 240 seconds.
42
62
  Default: 240.0
43
63
  """
44
- self._base_url = f"{base_url}/api"
64
+ self._base_url = f"{base_url}/{api.value}/api/v1"
45
65
 
46
66
  # setup client
47
-
48
- self._client = CustomLoginClient(
49
- email=email,
50
- password=password,
51
- login_url=f"{base_url}/accessToken",
67
+ self._client = LunaHTTPClient(
68
+ auth=APIKeyAuth(api_key),
52
69
  base_url=self._base_url,
53
70
  follow_redirects=True,
54
71
  timeout=timeout,
72
+ event_hooks={"response": [check_httpx_exceptions]},
55
73
  )
56
74
 
57
75
  def __del__(self):
@@ -1,6 +1,6 @@
1
1
  from typing import Optional
2
2
 
3
- from luna_sdk.controllers.luna_platform_client import LunaPlatformClient
3
+ from luna_sdk.controllers.luna_platform_client import LunaPlatformClient, LunaPrefixEnum
4
4
  from luna_sdk.interfaces import ICircuitRepo
5
5
  from luna_sdk.interfaces.clients.luna_q_i import ILunaQ
6
6
  from luna_sdk.interfaces.qpu_token_repo_i import IQpuTokenRepo
@@ -11,23 +11,21 @@ class LunaQ(LunaPlatformClient, ILunaQ):
11
11
  qpu_token: IQpuTokenRepo = None # type: ignore
12
12
  circuit: ICircuitRepo = None # type: ignore
13
13
 
14
- def __init__(self, email: str, password: str, timeout: Optional[float] = 240.0):
14
+ def __init__(self, api_key: str, timeout: Optional[float] = 240.0):
15
15
  """
16
16
  LunaQ is the main entrypoint for all LunaQ related tasks.
17
17
 
18
18
  Parameters
19
19
  ----------
20
- email: str
21
- User's email
22
- password: str
23
- User's password
20
+ api_key: str
21
+ User's API key
24
22
  timeout: float
25
23
  Default timeout in seconds for the requests via the LunaQ client. `None`
26
24
  means that the SDK uses no timeouts. Note that either way the Luna platform
27
25
  itself will time out after 240 seconds.
28
26
  Default: 240.0
29
27
  """
30
- super().__init__(email=email, password=password, timeout=timeout)
28
+ super().__init__(api_key=api_key, api=LunaPrefixEnum.LUNA_Q, timeout=timeout)
31
29
 
32
30
  self.circuit = CircuitRepo(self._client)
33
31
  self.qpu_token = QpuTokenRepo(self._client)
@@ -1,6 +1,6 @@
1
1
  from typing import Optional
2
2
 
3
- from luna_sdk.controllers.luna_platform_client import LunaPlatformClient
3
+ from luna_sdk.controllers.luna_platform_client import LunaPlatformClient, LunaPrefixEnum
4
4
  from luna_sdk.interfaces import ISolutionsRepo
5
5
  from luna_sdk.interfaces.clients.luna_solve_i import ILunaSolve
6
6
  from luna_sdk.interfaces.info_repo_i import IInfoRepo
@@ -18,23 +18,25 @@ class LunaSolve(LunaPlatformClient, ILunaSolve):
18
18
  qpu_token: IQpuTokenRepo = None # type: ignore
19
19
  info: IInfoRepo = None # type: ignore
20
20
 
21
- def __init__(self, email: str, password: str, timeout: Optional[float] = 240.0):
21
+ def __init__(self, api_key: str, timeout: Optional[float] = 240.0):
22
22
  """
23
23
  LunaSolve is the main entrypoint for all LunaSolve related tasks.
24
24
 
25
25
  Parameters
26
26
  ----------
27
- email: str
28
- User's email
29
- password: str
30
- User's password
27
+ api_key: str
28
+ User's API key
31
29
  timeout: float
32
30
  Default timeout in seconds for the requests via the LunaQ client. `None`
33
31
  means that the SDK uses no timeouts. Note that either way the Luna platform
34
32
  itself will time out after 240 seconds.
35
33
  Default: 240.0
36
34
  """
37
- super().__init__(email=email, password=password, timeout=timeout)
35
+ super().__init__(
36
+ api_key=api_key,
37
+ api=LunaPrefixEnum.LUNA_SOLVE,
38
+ timeout=timeout,
39
+ )
38
40
 
39
41
  self.optimization = OptimizationRepo(self._client)
40
42
  self.solution = SolutionsRepo(self._client)
@@ -1,6 +1,6 @@
1
1
  from typing import Optional
2
2
 
3
- from luna_sdk.controllers.luna_platform_client import LunaPlatformClient
3
+ from luna_sdk.controllers.luna_platform_client import LunaPlatformClient, LunaPrefixEnum
4
4
  from luna_sdk.interfaces.clients.luna_transform_i import ILunaTransform
5
5
  from luna_sdk.interfaces.cplex_repo_i import ICplexRepo
6
6
  from luna_sdk.interfaces.lp_repo_i import ILPRepo
@@ -12,23 +12,29 @@ class LunaTransform(LunaPlatformClient, ILunaTransform):
12
12
  cplex: ICplexRepo = None # type: ignore
13
13
  lp: ILPRepo = None # type: ignore
14
14
 
15
- def __init__(self, email: str, password: str, timeout: Optional[float] = 240.0):
15
+ def __init__(
16
+ self,
17
+ api_key: str,
18
+ timeout: Optional[float] = 240.0,
19
+ ):
16
20
  """
17
21
  LunaTransform is the main entrypoint for all LunaTransform related tasks.
18
22
 
19
23
  Parameters
20
24
  ----------
21
- email: str
22
- User's email
23
- password: str
24
- User's password
25
+ api_key: str
26
+ User's API key
25
27
  timeout: float
26
28
  Default timeout in seconds for the requests via the LunaQ client. `None`
27
29
  means that the SDK uses no timeouts. Note that either way the Luna platform
28
30
  itself will time out after 240 seconds.
29
31
  Default: 240.0
30
32
  """
31
- super().__init__(email=email, password=password, timeout=timeout)
33
+ super().__init__(
34
+ api_key=api_key,
35
+ api=LunaPrefixEnum.LUNA_SOLVE,
36
+ timeout=timeout,
37
+ )
32
38
 
33
39
  self.cplex = CplexRepo(self._client)
34
40
  self.lp = LPRepo(self._client)
@@ -1,7 +1,8 @@
1
1
  import logging
2
2
  from typing import Optional
3
3
 
4
- from httpx import HTTPStatusError, RequestError, Response
4
+ import httpx
5
+ from httpx import RequestError, Response
5
6
 
6
7
  from luna_sdk.exceptions.luna_server_exception import LunaServerException
7
8
  from luna_sdk.schemas.error_message import ErrorMessage
@@ -50,6 +51,12 @@ class HttpErrorUtils:
50
51
  " leading to a timeout. Try reducing the size of the optimization.",
51
52
  )
52
53
 
54
+ elif response.status_code == 403:
55
+ exception = create_error_message(
56
+ "FORBIDDEN",
57
+ response.text,
58
+ )
59
+
53
60
  return exception
54
61
 
55
62
  @staticmethod
@@ -70,15 +77,15 @@ class HttpErrorUtils:
70
77
  If an error occurred with the request outside the http status codes 4xx and 5xx.
71
78
  """
72
79
  try:
80
+ response.read()
73
81
  response.raise_for_status()
74
- except HTTPStatusError as e:
82
+ except httpx.HTTPStatusError as e:
75
83
  exception: Optional[LunaServerException]
76
84
 
77
85
  try:
78
86
  error_msg: ErrorMessage = ErrorMessage.model_validate_json(
79
87
  response.text
80
88
  )
81
-
82
89
  # Convert the error message to the correct exception
83
90
  exception = LunaServerException(response.status_code, error_msg)
84
91
 
@@ -5,9 +5,10 @@ from typing import List, Optional
5
5
  from dimod import BinaryQuadraticModel, ConstrainedQuadraticModel
6
6
 
7
7
  from luna_sdk.interfaces.repository_i import IRepository
8
- from luna_sdk.schemas.enums.optimization import InputType
8
+ from luna_sdk.schemas.enums.optimization import OptFormat
9
9
  from luna_sdk.schemas.enums.timeframe import TimeframeEnum
10
10
  from luna_sdk.schemas.optimization import Optimization
11
+ from luna_sdk.schemas.solution import Numeric
11
12
  from luna_sdk.schemas.use_cases import UseCase
12
13
 
13
14
 
@@ -35,7 +36,7 @@ class IOptimizationRepo(IRepository, ABC):
35
36
  def get_all(
36
37
  self,
37
38
  timeframe: Optional[TimeframeEnum] = None,
38
- input_type: Optional[InputType] = None,
39
+ input_type: Optional[OptFormat] = None,
39
40
  limit: int = 50,
40
41
  offset: int = 0,
41
42
  **kwargs,
@@ -48,7 +49,7 @@ class IOptimizationRepo(IRepository, ABC):
48
49
  timeframe: Optional[TimeframeEnum]
49
50
  Only return optimizations created within a specified timeframe.
50
51
  Default None.
51
- input_type: Optional[InputType]
52
+ input_type: Optional[OptFormat]
52
53
  Only return optimizations of a specified input type. Default None.
53
54
  limit:
54
55
  Limit the number of optimizations to be returned. Default value 50.
@@ -66,7 +67,7 @@ class IOptimizationRepo(IRepository, ABC):
66
67
 
67
68
  @abstractmethod
68
69
  def create_from_qubo(
69
- self, name: str, matrix: List[List[float]], **kwargs
70
+ self, name: str, matrix: List[List[Numeric]], **kwargs
70
71
  ) -> Optimization:
71
72
  """
72
73
  Create an optimization from a QUBO matrix.
@@ -18,7 +18,7 @@ class IQpuTokenRepo(IRepository, ABC):
18
18
  **kwargs,
19
19
  ) -> QpuTokenOut:
20
20
  """
21
- Create organization QPU token
21
+ Create QPU token
22
22
 
23
23
  Parameters
24
24
  ----------
@@ -29,8 +29,8 @@ class IQpuTokenRepo(IRepository, ABC):
29
29
  token: str
30
30
  Token
31
31
  token_type: QpuTokenTypeEnum
32
- There are two types of QPU tokens: PERSONAL and ORGANIZATION.
33
- All users of an organization can use organization QPU tokens.
32
+ There are two types of QPU tokens: PERSONAL and GROUP.
33
+ All users of a group can use group QPU tokens.
34
34
  User QPU tokens can only be used by the user who created them.
35
35
  encryption_key: Optional[str]
36
36
  Encryption key to be used for encryption of QPU tokens.
@@ -50,6 +50,8 @@ class IQpuTokenRepo(IRepository, ABC):
50
50
  filter_provider: Optional[str] = None,
51
51
  name: Optional[str] = None,
52
52
  token_type: Optional[QpuTokenTypeEnum] = None,
53
+ limit: Optional[int] = None,
54
+ offset: Optional[int] = None,
53
55
  **kwargs,
54
56
  ) -> Dict[QpuTokenTypeEnum, List[QpuTokenOut]]:
55
57
  """
@@ -62,8 +64,12 @@ class IQpuTokenRepo(IRepository, ABC):
62
64
  name: Optional[str]
63
65
  Name of the QPU token that should be retrieved
64
66
  token_type: Optional[QpuTokenTypeEnum]
65
- If you want to retrieve only user or organization QPU tokens
67
+ If you want to retrieve only user or group QPU tokens
66
68
  otherwise all QPU tokens will be retrieved
69
+ limit: Optional[int]
70
+ Number of items to fetch. Default is 10.
71
+ offset: Optional[int]
72
+ Optional. Number of items to skip. Default is 0.
67
73
  **kwargs
68
74
  Parameters to pass to `httpx.request`.
69
75
 
@@ -84,8 +90,8 @@ class IQpuTokenRepo(IRepository, ABC):
84
90
  name: str
85
91
  Name of the QPU token that should be retrieved
86
92
  token_type: QpuTokenTypeEnum
87
- There are two types of QPU tokens: PERSONAL and ORGANIZATION.
88
- All users of an organization can use organization QPU tokens.
93
+ There are two types of QPU tokens: PERSONAL and GROUP.
94
+ All users of a group can use group QPU tokens.
89
95
  User QPU tokens can only be used by the user who created them.
90
96
  **kwargs
91
97
  Parameters to pass to `httpx.request`.
@@ -106,7 +112,7 @@ class IQpuTokenRepo(IRepository, ABC):
106
112
  **kwargs,
107
113
  ) -> QpuTokenOut:
108
114
  """
109
- Update organization QPU token by id.
115
+ Update QPU token by id.
110
116
 
111
117
  Parameters
112
118
  ----------
@@ -115,8 +121,8 @@ class IQpuTokenRepo(IRepository, ABC):
115
121
  new_name: str
116
122
  The new name
117
123
  token_type: QpuTokenTypeEnum
118
- There are two types of QPU tokens: PERSONAL and ORGANIZATION.
119
- All users of an organization can use organization QPU tokens.
124
+ There are two types of QPU tokens: PERSONAL and GROUP.
125
+ All users of a group can use group QPU tokens.
120
126
  User QPU tokens can only be used by the user who created them.
121
127
  **kwargs
122
128
  Parameters to pass to `httpx.request`.
@@ -131,15 +137,15 @@ class IQpuTokenRepo(IRepository, ABC):
131
137
  @abstractmethod
132
138
  def delete(self, name: str, token_type: QpuTokenTypeEnum, **kwargs) -> None:
133
139
  """
134
- Delete organization QPU token by name.
140
+ Delete QPU token by name.
135
141
 
136
142
  Parameters
137
143
  ----------
138
144
  name: str
139
145
  Name of the QPU token that should be deleted
140
146
  token_type: QpuTokenTypeEnum
141
- There are two types of QPU tokens: PERSONAL and ORGANIZATION.
142
- All users of an organization can use organization QPU tokens.
147
+ There are two types of QPU tokens: PERSONAL and GROUP.
148
+ All users of a group can use organization QPU tokens.
143
149
  User QPU tokens can only be used by the user who created them.
144
150
  **kwargs
145
151
  Parameters to pass to `httpx.request`.
@@ -9,7 +9,7 @@ from luna_sdk.interfaces.optimization_repo_i import IOptimizationRepo
9
9
  from luna_sdk.schemas import UseCase
10
10
  from luna_sdk.schemas.create import QUBOIn
11
11
  from luna_sdk.schemas.create.optimization import OptimizationUseCaseIn
12
- from luna_sdk.schemas.enums.optimization import InputType
12
+ from luna_sdk.schemas.enums.optimization import OptFormat
13
13
  from luna_sdk.schemas.enums.timeframe import TimeframeEnum
14
14
  from luna_sdk.schemas.optimization import (
15
15
  Optimization,
@@ -17,6 +17,7 @@ from luna_sdk.schemas.optimization import (
17
17
  OptimizationCQM,
18
18
  OptimizationLP,
19
19
  OptimizationUseCase,
20
+ OptimizationQubo,
20
21
  )
21
22
  from luna_sdk.schemas.optimization_formats.bqm import BQMSchema
22
23
  from luna_sdk.schemas.optimization_formats.cqm import CQMSchema
@@ -30,7 +31,7 @@ class OptimizationRepo(IOptimizationRepo):
30
31
  def get_all(
31
32
  self,
32
33
  timeframe: Optional[TimeframeEnum] = None,
33
- input_type: Optional[InputType] = None,
34
+ input_type: Optional[OptFormat] = None,
34
35
  limit: int = 50,
35
36
  offset: int = 0,
36
37
  **kwargs,
@@ -40,7 +41,7 @@ class OptimizationRepo(IOptimizationRepo):
40
41
  params["timeframe"] = timeframe.value
41
42
 
42
43
  if input_type:
43
- params["input_type"] = input_type.value
44
+ params["original_format"] = input_type.value
44
45
 
45
46
  if limit < 1:
46
47
  # set the minimum limit to 1
@@ -63,21 +64,21 @@ class OptimizationRepo(IOptimizationRepo):
63
64
 
64
65
  optimization_data = response_data.pop("optimization_data", None)
65
66
  if optimization_data:
66
- input_type = response_data["input_type"]
67
+ original_format = response_data["original_format"]
67
68
 
68
- if input_type in (InputType.bqm_spin, InputType.bqm_binary):
69
+ if original_format == OptFormat.BQM:
69
70
  model = OptimizationBQM
70
- elif input_type == InputType.cqm:
71
+ elif original_format == OptFormat.CQM:
71
72
  model = OptimizationCQM
72
- elif input_type == InputType.lp:
73
+ elif original_format == OptFormat.LP:
73
74
  model = OptimizationLP
74
- elif input_type == InputType.qubo:
75
+ elif original_format == OptFormat.QUBO:
75
76
  if response_data.get("use_case_name"):
76
77
  model = OptimizationUseCase
77
78
  else:
78
- model = OptimizationBQM
79
+ model = OptimizationQubo
79
80
  else:
80
- model = OptimizationBQM
81
+ raise ValueError("Unknown optimization format")
81
82
 
82
83
  response_data.update(optimization_data)
83
84
 
@@ -22,15 +22,15 @@ class QpuTokenRepo(IQpuTokenRepo):
22
22
  if token_type is None:
23
23
  return f"{self._endpoint}"
24
24
  elif token_type == QpuTokenTypeEnum.PERSONAL:
25
- return f"{self._endpoint}/users"
25
+ return f"{self._endpoint}/private"
26
26
  else:
27
- return f"{self._endpoint}/organization"
27
+ return f"{self._endpoint}/shared"
28
28
 
29
29
  def _get_by_name(
30
30
  self, name: str, token_type: QpuTokenTypeEnum, **kwargs
31
31
  ) -> QpuTokenOut:
32
32
  response: Response = self._client.get(
33
- f"{self._get_endpoint_by_type(token_type)}/by_name/{name}", **kwargs
33
+ f"{self._get_endpoint_by_type(token_type)}/{name}", **kwargs
34
34
  )
35
35
  response.raise_for_status()
36
36
 
@@ -72,6 +72,8 @@ class QpuTokenRepo(IQpuTokenRepo):
72
72
  filter_provider: Optional[str] = None,
73
73
  name: Optional[str] = None,
74
74
  token_type: Optional[QpuTokenTypeEnum] = None,
75
+ limit: Optional[int] = None,
76
+ offset: Optional[int] = None,
75
77
  **kwargs,
76
78
  ) -> Dict[QpuTokenTypeEnum, List[QpuTokenOut]]:
77
79
  params = {}
@@ -80,20 +82,36 @@ class QpuTokenRepo(IQpuTokenRepo):
80
82
 
81
83
  if name:
82
84
  params["name"] = name
83
-
84
- response = self._client.get(
85
- self._get_endpoint_by_type(), params=params, **kwargs
86
- )
87
- response.raise_for_status()
85
+ if limit is not None:
86
+ params["limit"] = str(limit)
87
+ if offset is not None:
88
+ params["offset"] = str(offset)
88
89
 
89
90
  to_return: Dict[QpuTokenTypeEnum, List[QpuTokenOut]] = {}
90
- for key, value in response.json().items():
91
- tokens = []
92
- for item in value:
93
- if token_type is None or token_type.value == key:
94
- item["token_type"] = QpuTokenTypeEnum(key)
95
- tokens.append(QpuTokenOut.model_validate(item))
96
- to_return[QpuTokenTypeEnum(key)] = tokens
91
+ if token_type is None or token_type == QpuTokenTypeEnum.PERSONAL:
92
+ response = self._client.get(
93
+ self._get_endpoint_by_type(QpuTokenTypeEnum.PERSONAL),
94
+ params=params,
95
+ **kwargs,
96
+ )
97
+ response.raise_for_status()
98
+ personal_qpu_tokens = response.json()
99
+ to_return[QpuTokenTypeEnum.PERSONAL] = [
100
+ QpuTokenOut(**qpu_token, token_type=QpuTokenTypeEnum.PERSONAL)
101
+ for qpu_token in personal_qpu_tokens
102
+ ]
103
+ if token_type is None or token_type == QpuTokenTypeEnum.GROUP:
104
+ response = self._client.get(
105
+ self._get_endpoint_by_type(QpuTokenTypeEnum.GROUP),
106
+ params=params,
107
+ **kwargs,
108
+ )
109
+ response.raise_for_status()
110
+ shared_qpu_tokens = response.json()
111
+ to_return[QpuTokenTypeEnum.GROUP] = [
112
+ QpuTokenOut(**qpu_token, token_type=QpuTokenTypeEnum.GROUP)
113
+ for qpu_token in shared_qpu_tokens
114
+ ]
97
115
 
98
116
  return to_return
99
117
 
@@ -114,8 +132,8 @@ class QpuTokenRepo(IQpuTokenRepo):
114
132
 
115
133
  token: QpuTokenOut = self.get(name, token_type)
116
134
 
117
- response = self._client.put(
118
- f"{self._get_endpoint_by_type(token_type)}/{token.id}",
135
+ response = self._client.patch(
136
+ f"{self._get_endpoint_by_type(token_type)}/{token.name}",
119
137
  content=json.dumps(qpu_token_update_data),
120
138
  **kwargs,
121
139
  )
@@ -126,9 +144,7 @@ class QpuTokenRepo(IQpuTokenRepo):
126
144
  return QpuTokenOut.model_validate(qpu_token_data)
127
145
 
128
146
  def delete(self, name: str, token_type: QpuTokenTypeEnum, **kwargs) -> None:
129
- token: QpuTokenOut = self.get(name, token_type)
130
-
131
147
  response = self._client.delete(
132
- f"{self._get_endpoint_by_type(token_type)}/{token.id}", **kwargs
148
+ f"{self._get_endpoint_by_type(token_type)}/{name}", **kwargs
133
149
  )
134
150
  response.raise_for_status()
@@ -1,10 +1,11 @@
1
1
  from enum import Enum
2
2
 
3
3
 
4
- class InputType(str, Enum):
5
- bqm_spin = "bqm_spin"
6
- bqm_binary = "bqm_binary"
7
- cqm = "cqm"
8
- lp = "lp"
9
- aq = "aq"
10
- qubo = "qubo"
4
+ class OptFormat(str, Enum):
5
+ """Enumeration of all supported formats."""
6
+
7
+ AQ_MODEL = "AQ_MODEL"
8
+ LP = "LP"
9
+ QUBO = "QUBO_MATRIX"
10
+ CQM = "CQM"
11
+ BQM = "BQM"
@@ -2,5 +2,5 @@ from enum import Enum
2
2
 
3
3
 
4
4
  class QpuTokenTypeEnum(str, Enum):
5
- ORGANIZATION = "organization"
5
+ GROUP = "group"
6
6
  PERSONAL = "personal"
@@ -1,11 +1,12 @@
1
- from typing import Any, Dict, Generic, List, Optional, TypeVar
1
+ from typing import Any, Dict, Generic, Optional, TypeVar
2
2
 
3
3
  from pydantic import BaseModel, ConfigDict
4
4
 
5
- from luna_sdk.schemas.enums.optimization import InputType
5
+ from luna_sdk.schemas.enums.optimization import OptFormat
6
6
  from luna_sdk.schemas.optimization_formats.bqm import BQMSchema
7
7
  from luna_sdk.schemas.optimization_formats.cqm import CQMSchema
8
8
  from luna_sdk.schemas.optimization_formats.lp import LPSchema
9
+ from luna_sdk.schemas.optimization_formats.qubo import QuboSchema
9
10
  from luna_sdk.schemas.pretty_base import PrettyBase
10
11
  from luna_sdk.schemas.wrappers import PydanticDatetimeWrapper
11
12
 
@@ -33,24 +34,13 @@ class Optimization(PrettyBase):
33
34
  created_by: str
34
35
  modified_date: Optional[PydanticDatetimeWrapper] = None
35
36
  modified_by: Optional[str] = None
36
- input_type: Optional[InputType] = None
37
+ original_format: Optional[OptFormat] = None
37
38
  use_case_name: Optional[str] = None
38
39
  params: Optional[Dict[str, Any]] = None
39
40
 
40
41
  model_config = ConfigDict(extra="ignore", from_attributes=False)
41
42
 
42
43
 
43
- class OptimizationQubo(BaseModel):
44
- id: str
45
- name: Optional[str] = None
46
- created_date: PydanticDatetimeWrapper
47
- created_by: str
48
- modified_date: Optional[PydanticDatetimeWrapper] = None
49
- modified_by: Optional[str] = None
50
-
51
- matrix: List[List[float]]
52
-
53
-
54
44
  class OptimizationBQM(Optimization, BQMSchema): ...
55
45
 
56
46
 
@@ -60,10 +50,13 @@ class OptimizationCQM(Optimization, CQMSchema): ...
60
50
  class OptimizationLP(Optimization, LPSchema): ...
61
51
 
62
52
 
63
- class OptimizationUseCase(Optimization, BQMSchema):
53
+ class OptimizationUseCase(Optimization, QuboSchema):
64
54
  use_case: Dict[str, Any]
65
55
 
66
56
 
57
+ class OptimizationQubo(Optimization, QuboSchema): ...
58
+
59
+
67
60
  T = TypeVar("T")
68
61
 
69
62
 
@@ -0,0 +1,8 @@
1
+ from typing import List
2
+
3
+ from pydantic import BaseModel
4
+
5
+
6
+ class QuboSchema(BaseModel):
7
+ matrix: List[List[float]]
8
+ offset: float
@@ -12,7 +12,7 @@ class QpuTokenSource(str, Enum):
12
12
  # stored token in user account
13
13
  PERSONAL = "personal"
14
14
  # stored token in group account
15
- ORGANIZATION = "organization"
15
+ GROUP = "group"
16
16
 
17
17
 
18
18
  class QpuToken(BaseModel):
@@ -44,16 +44,12 @@ class QpuTokenOut(BaseModel):
44
44
 
45
45
  Attributes
46
46
  ----------
47
- id: str
48
- Id of the QPU token
49
47
  name: Optional[str]
50
48
  Name of the QPU token
51
49
  provider: ProviderEnum
52
50
  Name of provider: dwave | ibm
53
51
  """
54
52
 
55
- id: str
56
-
57
53
  name: str
58
54
  provider: str
59
55
  token_type: QpuTokenTypeEnum
@@ -0,0 +1,18 @@
1
+ from enum import Enum
2
+
3
+
4
+ class _RESTQpuTokenSource(str, Enum):
5
+ """
6
+ This schema allow us not to change entire backend,
7
+ but just sync SDK and everything else in terms of qpu token source.
8
+ Currently, the difference is that
9
+ SDK has group qpu token source
10
+ and backend has organization qpu token source which are mapped to each other.
11
+ """
12
+
13
+ # token currently passed in from the API call (not stored by us)
14
+ INLINE = "inline"
15
+ # stored token in user account
16
+ PERSONAL = "personal"
17
+ # stored token in group account
18
+ ORGANIZATION = "organization"
@@ -1,20 +1,48 @@
1
- from typing import Optional
1
+ from typing import Optional, Union
2
2
 
3
3
  from pydantic import BaseModel, Extra
4
4
 
5
- from luna_sdk.schemas import QpuToken, TokenProvider
5
+ from luna_sdk.schemas import QpuToken, TokenProvider, QpuTokenSource
6
+ from luna_sdk.schemas.rest.qpu_token.qpu_token_source import _RESTQpuTokenSource
7
+
8
+
9
+ class _RestQpuToken(BaseModel):
10
+ source: _RESTQpuTokenSource
11
+ # A unique name for a stored token
12
+ name: Optional[str] = None
13
+ # This could be a QPU token, an API key or any token key for a QPU provider.
14
+ # If the token is not passed from this API call, one stored in the user's
15
+ # account will be used.
16
+ token: Optional[str] = None
17
+
18
+ @classmethod
19
+ def from_qpu_token(cls, qpu_token: Optional[QpuToken]) -> Optional["_RestQpuToken"]:
20
+ if qpu_token is None:
21
+ return None
22
+ # Organizational tokens were renamed to group in #1851
23
+ # For smoother transition we only change naming in the SDK,
24
+ # and therefore we need a mapping between Group and Organization here.
25
+ # However, in backend for now QPU tokens still has source organization
26
+ # TODO: Remove it when backend I/O schema is changed
27
+ if qpu_token.source == QpuTokenSource.GROUP:
28
+ return cls(
29
+ source=_RESTQpuTokenSource.ORGANIZATION,
30
+ name=qpu_token.name,
31
+ token=qpu_token.token,
32
+ )
33
+ return cls.model_validate(qpu_token, from_attributes=True)
6
34
 
7
35
 
8
36
  class AWSQpuTokens(BaseModel):
9
- aws_access_key: QpuToken
10
- aws_secret_access_key: QpuToken
37
+ aws_access_key: _RestQpuToken
38
+ aws_secret_access_key: _RestQpuToken
11
39
 
12
40
 
13
41
  class RestAPITokenProvider(BaseModel):
14
- dwave: Optional[QpuToken] = None
15
- ibm: Optional[QpuToken] = None
16
- fujitsu: Optional[QpuToken] = None
17
- qctrl: Optional[QpuToken] = None
42
+ dwave: Optional[_RestQpuToken] = None
43
+ ibm: Optional[_RestQpuToken] = None
44
+ fujitsu: Optional[_RestQpuToken] = None
45
+ qctrl: Optional[_RestQpuToken] = None
18
46
  aws: Optional[AWSQpuTokens] = None
19
47
 
20
48
  @classmethod
@@ -28,16 +56,20 @@ class RestAPITokenProvider(BaseModel):
28
56
  ):
29
57
  # Ignoring mypy here to receive validation error, because we always need 2 tokens for aws
30
58
  aws = AWSQpuTokens(
31
- aws_access_key=getattr(token_provider, "aws_access_key", None), # type: ignore[arg-type]
32
- aws_secret_access_key=getattr( # type: ignore[arg-type]
33
- token_provider, "aws_secret_access_key", None
59
+ aws_access_key=_RestQpuToken.from_qpu_token(
60
+ getattr(token_provider, "aws_access_key", None)
61
+ ), # type: ignore[arg-type]
62
+ aws_secret_access_key=_RestQpuToken.from_qpu_token(
63
+ getattr( # type: ignore[arg-type]
64
+ token_provider, "aws_secret_access_key", None
65
+ )
34
66
  ),
35
67
  )
36
68
  return cls(
37
- dwave=token_provider.dwave,
38
- ibm=token_provider.ibm,
39
- fujitsu=token_provider.fujitsu,
40
- qctrl=token_provider.qctrl,
69
+ dwave=_RestQpuToken.from_qpu_token(token_provider.dwave),
70
+ ibm=_RestQpuToken.from_qpu_token(token_provider.ibm),
71
+ fujitsu=_RestQpuToken.from_qpu_token(token_provider.fujitsu),
72
+ qctrl=_RestQpuToken.from_qpu_token(token_provider.qctrl),
41
73
  aws=aws,
42
74
  )
43
75
 
@@ -1,9 +1,10 @@
1
1
  import os
2
2
 
3
- from luna_sdk.schemas import QpuToken, QpuTokenSource
3
+ from luna_sdk.schemas.rest.qpu_token.qpu_token_source import _RESTQpuTokenSource
4
4
  from luna_sdk.schemas.rest.qpu_token.token_provider import (
5
5
  RestAPITokenProvider,
6
6
  AWSQpuTokens,
7
+ _RestQpuToken,
7
8
  )
8
9
 
9
10
 
@@ -15,37 +16,37 @@ def extract_qpu_tokens_from_env() -> RestAPITokenProvider:
15
16
  aws_access_key = os.environ.get("LUNA_AWS_ACCESS_KEY")
16
17
  aws_access_secret_key = os.environ.get("LUNA_AWS_SECRET_ACCESS_KEY")
17
18
  return RestAPITokenProvider(
18
- ibm=QpuToken(
19
- source=QpuTokenSource.INLINE,
19
+ ibm=_RestQpuToken(
20
+ source=_RESTQpuTokenSource.INLINE,
20
21
  token=ibm_token,
21
22
  )
22
23
  if ibm_token
23
24
  else None,
24
- dwave=QpuToken(
25
- source=QpuTokenSource.INLINE,
25
+ dwave=_RestQpuToken(
26
+ source=_RESTQpuTokenSource.INLINE,
26
27
  token=dwave_token,
27
28
  )
28
29
  if dwave_token
29
30
  else None,
30
- qctrl=QpuToken(
31
- source=QpuTokenSource.INLINE,
31
+ qctrl=_RestQpuToken(
32
+ source=_RESTQpuTokenSource.INLINE,
32
33
  token=qctrl_token,
33
34
  )
34
35
  if qctrl_token
35
36
  else None,
36
- fujitsu=QpuToken(
37
- source=QpuTokenSource.INLINE,
37
+ fujitsu=_RestQpuToken(
38
+ source=_RESTQpuTokenSource.INLINE,
38
39
  token=fujitsu_token,
39
40
  )
40
41
  if fujitsu_token
41
42
  else None,
42
43
  aws=AWSQpuTokens(
43
- aws_access_key=QpuToken(
44
- source=QpuTokenSource.INLINE,
44
+ aws_access_key=_RestQpuToken(
45
+ source=_RESTQpuTokenSource.INLINE,
45
46
  token=aws_access_key,
46
47
  ),
47
- aws_secret_access_key=QpuToken(
48
- source=QpuTokenSource.INLINE,
48
+ aws_secret_access_key=_RestQpuToken(
49
+ source=_RESTQpuTokenSource.INLINE,
49
50
  token=aws_access_secret_key,
50
51
  ),
51
52
  ),
@@ -1,66 +0,0 @@
1
- import logging
2
- from http.client import UNAUTHORIZED
3
- from importlib.metadata import version
4
-
5
- from httpx import Client, ReadTimeout, Response
6
-
7
- from luna_sdk.error.http_error_utils import HttpErrorUtils
8
- from luna_sdk.exceptions.timeout_exception import TimeoutException
9
-
10
-
11
- class CustomLoginClient(Client):
12
- _login_url: str
13
- _email: str
14
- _password: str
15
- _bearer_token: str
16
-
17
- _version: str = version("luna-quantum")
18
-
19
- _user_agent: str = f"LunaSDK/{_version}"
20
-
21
- def __init__(self, email: str, password: str, login_url: str, *args, **kwargs):
22
- super().__init__(*args, **kwargs)
23
- self._email = email
24
- self._password = password
25
- self._login_url = login_url
26
-
27
- self.headers["User-Agent"] = self._user_agent
28
-
29
- def login(self, email: str, password: str):
30
- with Client() as client:
31
- headers = {
32
- "accept": "application/json",
33
- "Content-Type": "application/x-www-form-urlencoded",
34
- "User-Agent": self._user_agent,
35
- }
36
-
37
- response: Response = client.post(
38
- self._login_url,
39
- data={"username": email, "password": password},
40
- headers=headers,
41
- # Ensure timeout is high enough. CustomLoginClient will be deleted in
42
- # near future anyway.
43
- timeout=None,
44
- )
45
- HttpErrorUtils.check_for_error(response)
46
-
47
- self._bearer_token = response.json()["access_token"]
48
-
49
- def request(self, *args, **kwargs) -> Response:
50
- try:
51
- response: Response = super().request(*args, **kwargs)
52
- if response.status_code == UNAUTHORIZED:
53
- logging.info("Unauthorized - trying to login")
54
-
55
- self.login(self._email, self._password)
56
-
57
- logging.info("Re-login successful")
58
- self.headers.update(
59
- headers={"authorization": f"Bearer {self._bearer_token}"}
60
- )
61
- logging.info("Trying request again")
62
- response = super().request(*args, **kwargs)
63
- except ReadTimeout:
64
- raise TimeoutException()
65
- HttpErrorUtils.check_for_error(response)
66
- return response