iqm-client 32.0.0__py3-none-any.whl → 33.0.0__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.
Files changed (45) hide show
  1. iqm/cirq_iqm/devices/iqm_device_metadata.py +2 -1
  2. iqm/cirq_iqm/examples/demo_common.py +1 -1
  3. iqm/cirq_iqm/examples/demo_iqm_execution.py +3 -3
  4. iqm/cirq_iqm/iqm_sampler.py +47 -29
  5. iqm/cirq_iqm/serialize.py +1 -1
  6. iqm/cirq_iqm/transpiler.py +3 -1
  7. iqm/iqm_client/__init__.py +0 -2
  8. iqm/iqm_client/errors.py +6 -17
  9. iqm/iqm_client/iqm_client.py +199 -602
  10. iqm/iqm_client/models.py +20 -611
  11. iqm/iqm_client/transpile.py +11 -8
  12. iqm/iqm_client/validation.py +18 -9
  13. iqm/iqm_server_client/__init__.py +14 -0
  14. iqm/iqm_server_client/errors.py +6 -0
  15. iqm/iqm_server_client/iqm_server_client.py +755 -0
  16. iqm/iqm_server_client/models.py +179 -0
  17. iqm/iqm_server_client/py.typed +0 -0
  18. iqm/qiskit_iqm/__init__.py +8 -0
  19. iqm/qiskit_iqm/examples/bell_measure.py +2 -2
  20. iqm/qiskit_iqm/examples/transpile_example.py +9 -4
  21. iqm/qiskit_iqm/fake_backends/fake_adonis.py +2 -1
  22. iqm/qiskit_iqm/fake_backends/fake_aphrodite.py +2 -1
  23. iqm/qiskit_iqm/fake_backends/fake_apollo.py +2 -1
  24. iqm/qiskit_iqm/fake_backends/fake_deneb.py +2 -1
  25. iqm/qiskit_iqm/fake_backends/iqm_fake_backend.py +8 -7
  26. iqm/qiskit_iqm/iqm_backend.py +3 -4
  27. iqm/qiskit_iqm/iqm_circuit_validation.py +8 -7
  28. iqm/qiskit_iqm/iqm_job.py +106 -88
  29. iqm/qiskit_iqm/iqm_move_layout.py +2 -1
  30. iqm/qiskit_iqm/iqm_naive_move_pass.py +115 -56
  31. iqm/qiskit_iqm/iqm_provider.py +49 -36
  32. iqm/qiskit_iqm/iqm_target.py +12 -8
  33. iqm/qiskit_iqm/iqm_transpilation.py +219 -26
  34. iqm/qiskit_iqm/qiskit_to_iqm.py +150 -41
  35. iqm/qiskit_iqm/transpiler_plugins.py +11 -8
  36. {iqm_client-32.0.0.dist-info → iqm_client-33.0.0.dist-info}/METADATA +4 -14
  37. iqm_client-33.0.0.dist-info/RECORD +63 -0
  38. iqm/iqm_client/api.py +0 -90
  39. iqm/iqm_client/authentication.py +0 -206
  40. iqm_client-32.0.0.dist-info/RECORD +0 -60
  41. {iqm_client-32.0.0.dist-info → iqm_client-33.0.0.dist-info}/AUTHORS.rst +0 -0
  42. {iqm_client-32.0.0.dist-info → iqm_client-33.0.0.dist-info}/LICENSE.txt +0 -0
  43. {iqm_client-32.0.0.dist-info → iqm_client-33.0.0.dist-info}/WHEEL +0 -0
  44. {iqm_client-32.0.0.dist-info → iqm_client-33.0.0.dist-info}/entry_points.txt +0 -0
  45. {iqm_client-32.0.0.dist-info → iqm_client-33.0.0.dist-info}/top_level.txt +0 -0
@@ -1,206 +0,0 @@
1
- # Copyright 2024 IQM client developers
2
- #
3
- # Licensed under the Apache License, Version 2.0 (the "License");
4
- # you may not use this file except in compliance with the License.
5
- # You may obtain a copy of the License at
6
- #
7
- # http://www.apache.org/licenses/LICENSE-2.0
8
- #
9
- # Unless required by applicable law or agreed to in writing, software
10
- # distributed under the License is distributed on an "AS IS" BASIS,
11
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
- # See the License for the specific language governing permissions and
13
- # limitations under the License.
14
- """This module contains user authentication related classes and functions required by IQMClient."""
15
-
16
- from abc import ABC, abstractmethod
17
- from base64 import b64decode
18
- import json
19
- import os
20
- import time
21
- from typing import Any
22
-
23
- from iqm.iqm_client.errors import ClientAuthenticationError, ClientConfigurationError
24
-
25
- REFRESH_MARGIN_SECONDS = 60
26
-
27
-
28
- class TokenManager:
29
- """TokenManager manages the access token required for user authentication.
30
-
31
- Args:
32
- token: Long-lived IQM token in plain text format
33
- tokens_file: Path to a tokens file used for authentication
34
-
35
- The parameters can also be read from the environment variables IQM_TOKEN or IQM_TOKENS_FILE.
36
- Environment variables can not be mixed with initialisation arguments.
37
- All parameters must come from the same source.
38
-
39
- """
40
-
41
- @staticmethod
42
- def time_left_seconds(token: Any) -> int:
43
- """Check how much time is left until the token expires.
44
-
45
- Returns:
46
- Time left on token in seconds.
47
-
48
- """
49
- if not token or not isinstance(token, str):
50
- return 0
51
- parts = token.split(".", 2)
52
- if len(parts) != 3:
53
- return 0
54
- # Add padding to adjust body length to a multiple of 4 chars as required by base64 decoding
55
- try:
56
- body = parts[1] + ("=" * (-len(parts[1]) % 4))
57
- exp_time = int(json.loads(b64decode(body)).get("exp", "0"))
58
- return max(0, exp_time - int(time.time()))
59
- except (UnicodeDecodeError, json.decoder.JSONDecodeError, ValueError, TypeError):
60
- return 0
61
-
62
- def __init__(self, token: str | None = None, tokens_file: str | None = None):
63
- def _format_names(variable_names: list[str]) -> str:
64
- """Format a list of variable names"""
65
- return ", ".join(f'"{name}"' for name in variable_names)
66
-
67
- auth_parameters: dict[str, str] = {}
68
-
69
- init_parameters = {"token": token, "tokens_file": tokens_file}
70
- init_params_given = [key for key, value in init_parameters.items() if value]
71
-
72
- env_variables = {"token": "IQM_TOKEN", "tokens_file": "IQM_TOKENS_FILE"}
73
- env_vars_given = [name for name in env_variables.values() if os.environ.get(name)]
74
-
75
- if init_params_given and env_vars_given:
76
- raise ClientConfigurationError(
77
- "Authentication parameters given both as initialisation args and as environment variables: "
78
- + f"initialisation args {_format_names(init_params_given)}, "
79
- + f"environment variables {_format_names(env_vars_given)}."
80
- + " Parameter sources must not be mixed."
81
- )
82
-
83
- if env_vars_given:
84
- auth_parameters = {key: value for key, name in env_variables.items() if (value := os.environ.get(name))}
85
- else:
86
- auth_parameters = {key: str(value) for key, value in init_parameters.items() if value}
87
-
88
- self._token_provider: TokenProviderInterface | None = None
89
- self._access_token: str | None = None
90
-
91
- if not auth_parameters:
92
- self._token_provider = None
93
- elif set(auth_parameters) == {"token"}:
94
- # This is not necessarily a JWT token
95
- self._token_provider = ExternalToken(auth_parameters["token"])
96
- elif set(auth_parameters) == {"tokens_file"}:
97
- self._token_provider = TokensFileReader(auth_parameters["tokens_file"])
98
- else:
99
- raise ClientConfigurationError(
100
- f"Missing authentication parameters, neither token or tokens_file is available, {list(auth_parameters)}"
101
- )
102
-
103
- def get_bearer_token(self, retries: int = 1) -> str | None:
104
- """Returns a valid bearer token, or None if no user authentication has been configured.
105
-
106
- Raises:
107
- ClientAuthenticationError: getting the token failed
108
-
109
- """
110
- if self._token_provider is None:
111
- return None # Authentication is not used
112
-
113
- # Use the existing access token if it is still valid
114
- if TokenManager.time_left_seconds(self._access_token) > REFRESH_MARGIN_SECONDS:
115
- return f"Bearer {self._access_token}"
116
-
117
- # Otherwise, get a new access token from token provider
118
- try:
119
- self._access_token = self._token_provider.get_token()
120
- return f"Bearer {self._access_token}"
121
- except ClientAuthenticationError:
122
- if retries < 1:
123
- raise
124
-
125
- # Try again
126
- return self.get_bearer_token(retries - 1)
127
-
128
- def close(self) -> bool:
129
- """Close the configured token provider.
130
-
131
- Returns:
132
- True if closing was successful
133
-
134
- Raises:
135
- ClientAuthenticationError: closing failed
136
-
137
- """
138
- if self._token_provider is None:
139
- return False
140
-
141
- self._token_provider.close()
142
- self._token_provider = None
143
- return True
144
-
145
-
146
- class TokenProviderInterface(ABC):
147
- """Interface to token provider"""
148
-
149
- @abstractmethod
150
- def get_token(self) -> str:
151
- """Returns a valid access token.
152
-
153
- Raises:
154
- ClientAuthenticationError: acquiring the token failed
155
-
156
- """
157
-
158
- @abstractmethod
159
- def close(self) -> None:
160
- """Closes authentication session.
161
-
162
- Raises:
163
- ClientAuthenticationError: closing the session failed
164
-
165
- """
166
-
167
-
168
- class ExternalToken(TokenProviderInterface):
169
- """Holds an external token"""
170
-
171
- def __init__(self, token: str):
172
- self._token: str | None = token
173
-
174
- def get_token(self) -> str:
175
- if self._token is None:
176
- raise ClientAuthenticationError("No external token available")
177
- return self._token
178
-
179
- def close(self) -> None:
180
- self._token = None
181
- raise ClientAuthenticationError("Can not close externally managed auth session")
182
-
183
-
184
- class TokensFileReader(TokenProviderInterface):
185
- """Reads token from a file"""
186
-
187
- def __init__(self, tokens_file: str):
188
- self._path: str | None = tokens_file
189
-
190
- def get_token(self) -> str:
191
- try:
192
- if self._path is None:
193
- raise ClientAuthenticationError("No tokens file available")
194
- with open(self._path, encoding="utf-8") as file:
195
- raw_data = file.read()
196
- json_data = json.loads(raw_data)
197
- token = json_data.get("access_token")
198
- if TokenManager.time_left_seconds(token) <= 0:
199
- raise ClientAuthenticationError("Access token in file has expired or is not valid")
200
- except (FileNotFoundError, IsADirectoryError, json.decoder.JSONDecodeError) as e:
201
- raise ClientAuthenticationError(rf"Failed to read access token from file '{self._path}': {e}") from e
202
- return token
203
-
204
- def close(self) -> None:
205
- self._path = None
206
- raise ClientAuthenticationError("Can not close externally managed auth session")
@@ -1,60 +0,0 @@
1
- iqm/cirq_iqm/__init__.py,sha256=1zTyxtF39OD11D00ZujgqciJ_9GBDYe-PVBLqZp4NaA,831
2
- iqm/cirq_iqm/extended_qasm_parser.py,sha256=csDzfHLhy_9maGbappLbnFo2NHQjQeyd-1F8P380Mbk,1917
3
- iqm/cirq_iqm/iqm_gates.py,sha256=xnZex5ZfNOk_WSsFjVCRybc14FlGNbmwOs3mIfOE_F8,2488
4
- iqm/cirq_iqm/iqm_sampler.py,sha256=LSR-2Wa1rGNUtkH8BNZLBVlAoEOwmTy2gziI5Zm6wl8,11454
5
- iqm/cirq_iqm/optimizers.py,sha256=Jcb6W7-M9wYa5mZztq33jQpWuIzD5ulE16ZperIc-wU,8566
6
- iqm/cirq_iqm/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
- iqm/cirq_iqm/serialize.py,sha256=UwW9plc_qHwxa0DOVB8nSEx7wmzSZ4NgtUTlm77joYc,8516
8
- iqm/cirq_iqm/transpiler.py,sha256=c3-KE4c-4WenbdOcBMnCS30Ynm4Wt35i-bl4iG8pKAs,2112
9
- iqm/cirq_iqm/devices/__init__.py,sha256=WxbvNAqmeoV4mNy9M9IpjwmyNDpAP7ec1XFdjN7w_YA,840
10
- iqm/cirq_iqm/devices/adonis.py,sha256=ZWaA4_OfO6fBcrLYHONTjtW8aSlVq2nwy9IiW529gQw,1390
11
- iqm/cirq_iqm/devices/aphrodite.py,sha256=0K8zRo6gVVadQo7LJfs6laUVLzS3fNkrXMrPlwieyJ8,4018
12
- iqm/cirq_iqm/devices/apollo.py,sha256=_k7L45zyHZnpdZWMMXO6zci3XY3UEnBj2RmvxM6D7Mg,2238
13
- iqm/cirq_iqm/devices/iqm_device.py,sha256=CyAP0kU9vfovNWvF4CVX8Wp6_QLxLN8fy9I2YZkHHwM,15425
14
- iqm/cirq_iqm/devices/iqm_device_metadata.py,sha256=MklkPEXfIkp9aTgsvqV9_fAAU6QZgfnYF6eNrUH2bSk,7138
15
- iqm/cirq_iqm/examples/demo_adonis.py,sha256=rPd8VYqccYijG6t92hfvKsk8RAaMGHOmm4JelYjt3rw,1728
16
- iqm/cirq_iqm/examples/demo_apollo.py,sha256=vnDwcEXqEyew0cf4SDDQ2budP-giizSNJU3dgOw15H0,1751
17
- iqm/cirq_iqm/examples/demo_common.py,sha256=l47o574xzIo8Ri5j-RGjY2NRNJN4IU6d6l0dcwDWRtM,8731
18
- iqm/cirq_iqm/examples/demo_iqm_execution.py,sha256=I9hh1DfveBky-ngJlLmuxucIzlGtRPwrI7sMUSro8eM,2463
19
- iqm/cirq_iqm/examples/usage.ipynb,sha256=Kyfyu_MwqzTavHVNjgrWJo1tZPeJwTw7ExcU0MFYNRk,34208
20
- iqm/iqm_client/__init__.py,sha256=D-8W54EcQIxk_1JZo_86GYlR1YitHhPIiFwwLJ2IfGE,1411
21
- iqm/iqm_client/api.py,sha256=_c6OVuv2dyzBF7J2XlK_qxisTSPyOiI4gYokZPsuaJY,3083
22
- iqm/iqm_client/authentication.py,sha256=VtndzZ-nxuaU7q2G8bXYctGThcTuFZW0PqMNE9k4OCA,7447
23
- iqm/iqm_client/errors.py,sha256=ty2P-sg80zlAoL3_kC3PlprgDUv4PI-KFhmmxaaapS0,1429
24
- iqm/iqm_client/iqm_client.py,sha256=oX_wu7aIJCdwc-DZy8iF43n4t7mphtp7ha5Ec38kOkM,41160
25
- iqm/iqm_client/models.py,sha256=0i0jYI8G_mJlNGCbH9W89OBS3JeqbcD2n_kUcM1AqIs,41942
26
- iqm/iqm_client/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
27
- iqm/iqm_client/transpile.py,sha256=2hDxQK8F4eMgpJC06XMIA8YbguFnRVNMlE1iKQNiTZk,37268
28
- iqm/iqm_client/util.py,sha256=obzh1g6PNEXOj7k3gUkiylNUhyqutbWlxlEpfyyU_fk,1505
29
- iqm/iqm_client/validation.py,sha256=GAe5GQAEXyplbmS_ioIRLR4fhCYKSranB0vE06qMfe8,12192
30
- iqm/qiskit_iqm/__init__.py,sha256=Mv9V_r8ZcmGC8Ke5S8-7yLOx02vjZ1qiVx8mtbOpwnY,1420
31
- iqm/qiskit_iqm/iqm_backend.py,sha256=HddizT6yHHq-MOG_U48n6ftE9AqmzaqbXYayEC1ljso,5548
32
- iqm/qiskit_iqm/iqm_circuit.py,sha256=jaPo3zc5FC0vAIumh5d56fr44fDaJXXwcquBzQEy1Yg,1400
33
- iqm/qiskit_iqm/iqm_circuit_validation.py,sha256=9pneZKs-KjBDGeDI6RHj6lB-ACqugbnYr1BqkJwLcXg,1737
34
- iqm/qiskit_iqm/iqm_job.py,sha256=YLkAF4oqQ44dOLWbsqMiYCyj7pd3Rk6NIZ_TI1XtcQ8,11700
35
- iqm/qiskit_iqm/iqm_move_layout.py,sha256=ECf1BcRmXKeClc7AL0lHedvJbqtwV5rEHcOOFR8shKU,10534
36
- iqm/qiskit_iqm/iqm_naive_move_pass.py,sha256=jhTfvhrNDKt6NhhJg_3Y-5x6E1HRNzC_n4A27ZQTuvQ,12962
37
- iqm/qiskit_iqm/iqm_provider.py,sha256=KHF27Qk12-_OA7_UZ8Rd25qDfFq4np2jv11_9f4tchQ,18599
38
- iqm/qiskit_iqm/iqm_target.py,sha256=UyULiGMn6UJsyILBQiriso9KbhlmzP9TZItS2URaXWg,15832
39
- iqm/qiskit_iqm/iqm_transpilation.py,sha256=6_6Mri01_HQBV_GTX94WSvIbu-pDMLMzEU6zVMEt6Gc,9153
40
- iqm/qiskit_iqm/move_gate.py,sha256=UbrQSfrpVV3QKGJ93TelxEfZkl1wY4uWL8IH_QDpGUw,2840
41
- iqm/qiskit_iqm/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
42
- iqm/qiskit_iqm/qiskit_to_iqm.py,sha256=3Sm1gLELFLCLf6QiATZSiPzLzkjvzUakhU2N6KoBXC8,14948
43
- iqm/qiskit_iqm/transpiler_plugins.py,sha256=iuReGL42fCe5aOoH-KMUsb6t7Ok9qmIIj2S4yotJJ-U,8749
44
- iqm/qiskit_iqm/examples/__init__.py,sha256=M4ElQHCo-WxtVXK39bF3QiFT3IGXPtZ1khqexHiTBEc,20
45
- iqm/qiskit_iqm/examples/bell_measure.py,sha256=vlayliApHU70a2zTnN_gs6iKSSdaB4Jip-iQHJNYN5M,3064
46
- iqm/qiskit_iqm/examples/transpile_example.py,sha256=cQmXXx3lqvmhgWYFK_U5HmHzMOKQqXUXPYfQhkyHH14,2135
47
- iqm/qiskit_iqm/fake_backends/__init__.py,sha256=fkw2UHT-3aJbAKvR1WYUN7_4N5Gdwpx9bm6vlWj1tm0,874
48
- iqm/qiskit_iqm/fake_backends/fake_adonis.py,sha256=vdWaVB6Hsa-SYgMWuYBtRQH5x5Y1qVHvdomWT2bh5QQ,2225
49
- iqm/qiskit_iqm/fake_backends/fake_aphrodite.py,sha256=78KL0sONOtYKsWjPFGdc-uIxRUguncBbRQ9CP6bD_FQ,15510
50
- iqm/qiskit_iqm/fake_backends/fake_apollo.py,sha256=6YSaKtUc6zZ4m3iAREbmxL4tRs_DW0ulmZy2Sq7sPUc,6600
51
- iqm/qiskit_iqm/fake_backends/fake_deneb.py,sha256=_xpo_NJdu9t4ER8p5be-xTRmApkFY6kQw1UEGUPizk0,3193
52
- iqm/qiskit_iqm/fake_backends/fake_garnet.py,sha256=GI0xafTCj1Um09qVuccO6GPOGBm6ygul_O40Wu220Ys,5555
53
- iqm/qiskit_iqm/fake_backends/iqm_fake_backend.py,sha256=wJtfsxjPYbDKmzaz5R4AuaXvvPHa21WyPtRgNctL9eY,16785
54
- iqm_client-32.0.0.dist-info/AUTHORS.rst,sha256=qsxeK5A3-B_xK3hNbhFHEIkoHNpo7sdzYyRTs7Bdtm8,795
55
- iqm_client-32.0.0.dist-info/LICENSE.txt,sha256=2DXrmQtVVUV9Fc9RBFJidMiTEaQlG2oAtlC9PMrEwTk,11333
56
- iqm_client-32.0.0.dist-info/METADATA,sha256=TNcHTh2I8F7zKgtU-Lh1QfNWpmUH1WwhO1SY0pJCyDo,17887
57
- iqm_client-32.0.0.dist-info/WHEEL,sha256=y4mX-SOX4fYIkonsAGA5N0Oy-8_gI4FXw5HNI1xqvWg,91
58
- iqm_client-32.0.0.dist-info/entry_points.txt,sha256=Kk2qfRwk8vbIJ7qCAvmaUogfRRn6t92_hBFhe6kqAE4,1317
59
- iqm_client-32.0.0.dist-info/top_level.txt,sha256=NB4XRfyDS6_wG9gMsyX-9LTU7kWnTQxNvkbzIxGv3-c,4
60
- iqm_client-32.0.0.dist-info/RECORD,,