azure-quantum 1.1.1__py3-none-any.whl → 1.1.2.dev0__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.
@@ -0,0 +1,91 @@
1
+ ##
2
+ # Copyright (c) Microsoft Corporation. All rights reserved.
3
+ # Licensed under the MIT License.
4
+ ##
5
+
6
+ from enum import Enum
7
+ from azure.identity._constants import EnvironmentVariables as SdkEnvironmentVariables
8
+ from azure.identity import _internal as AzureIdentityInternals
9
+
10
+
11
+ class EnvironmentVariables:
12
+ USER_AGENT_APPID = "AZURE_QUANTUM_PYTHON_APPID"
13
+ QUANTUM_LOCATION = "AZURE_QUANTUM_WORKSPACE_LOCATION"
14
+ LOCATION = "LOCATION"
15
+ QUANTUM_RESOURCE_GROUP = "AZURE_QUANTUM_WORKSPACE_RG"
16
+ RESOURCE_GROUP = "RESOURCE_GROUP"
17
+ QUANTUM_SUBSCRIPTION_ID = "AZURE_QUANTUM_SUBSCRIPTION_ID"
18
+ SUBSCRIPTION_ID = "SUBSCRIPTION_ID"
19
+ WORKSPACE_NAME = "AZURE_QUANTUM_WORKSPACE_NAME"
20
+ QUANTUM_ENV = "AZURE_QUANTUM_ENV"
21
+ AZURE_CLIENT_ID = SdkEnvironmentVariables.AZURE_CLIENT_ID
22
+ AZURE_CLIENT_SECRET = SdkEnvironmentVariables.AZURE_CLIENT_SECRET
23
+ AZURE_TENANT_ID = SdkEnvironmentVariables.AZURE_TENANT_ID
24
+ QUANTUM_TOKEN_FILE = "AZURE_QUANTUM_TOKEN_FILE"
25
+ CONNECTION_STRING = "AZURE_QUANTUM_CONNECTION_STRING"
26
+ ALL = [
27
+ USER_AGENT_APPID,
28
+ QUANTUM_LOCATION,
29
+ LOCATION,
30
+ QUANTUM_RESOURCE_GROUP,
31
+ RESOURCE_GROUP,
32
+ QUANTUM_SUBSCRIPTION_ID,
33
+ SUBSCRIPTION_ID,
34
+ WORKSPACE_NAME,
35
+ QUANTUM_ENV,
36
+ AZURE_CLIENT_ID,
37
+ AZURE_CLIENT_SECRET,
38
+ AZURE_TENANT_ID,
39
+ QUANTUM_TOKEN_FILE,
40
+ CONNECTION_STRING,
41
+ ]
42
+
43
+
44
+ class EnvironmentKind(Enum):
45
+ PRODUCTION = 1,
46
+ CANARY = 2,
47
+ DOGFOOD = 3
48
+
49
+
50
+ class ConnectionConstants:
51
+ DATA_PLANE_CREDENTIAL_SCOPE = "https://quantum.microsoft.com/.default"
52
+ ARM_CREDENTIAL_SCOPE = "https://management.azure.com/.default"
53
+
54
+ MSA_TENANT_ID = "9188040d-6c67-4c5b-b112-36a304b66dad"
55
+
56
+ AUTHORITY = AzureIdentityInternals.get_default_authority()
57
+ DOGFOOD_AUTHORITY = "login.windows-ppe.net"
58
+
59
+ # pylint: disable=unnecessary-lambda-assignment
60
+ GET_QUANTUM_PRODUCTION_ENDPOINT = \
61
+ lambda location: f"https://{location}.quantum.azure.com/"
62
+ GET_QUANTUM_CANARY_ENDPOINT = \
63
+ lambda location: f"https://{location or 'eastus2euap'}.quantum.azure.com/"
64
+ GET_QUANTUM_DOGFOOD_ENDPOINT = \
65
+ lambda location: f"https://{location}.quantum-test.azure.com/"
66
+
67
+ ARM_PRODUCTION_ENDPOINT = "https://management.azure.com/"
68
+ ARM_DOGFOOD_ENDPOINT = "https://api-dogfood.resources.windows-int.net/"
69
+
70
+ VALID_RESOURCE_ID = (
71
+ lambda subscription_id, resource_group, workspace_name:
72
+ f"/subscriptions/{subscription_id}" +
73
+ f"/resourceGroups/{resource_group}" +
74
+ "/providers/Microsoft.Quantum/" +
75
+ f"Workspaces/{workspace_name}"
76
+ )
77
+
78
+ VALID_CONNECTION_STRING = (
79
+ lambda subscription_id, resource_group, workspace_name, api_key, quantum_endpoint:
80
+ f"SubscriptionId={subscription_id};" +
81
+ f"ResourceGroupName={resource_group};" +
82
+ f"WorkspaceName={workspace_name};" +
83
+ f"ApiKey={api_key};" +
84
+ f"QuantumEndpoint={quantum_endpoint};"
85
+ )
86
+
87
+ QUANTUM_API_KEY_HEADER = "x-ms-quantum-api-key"
88
+
89
+ GUID_REGEX_PATTERN = (
90
+ r"[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}"
91
+ )
@@ -0,0 +1,544 @@
1
+ ##
2
+ # Copyright (c) Microsoft Corporation. All rights reserved.
3
+ # Licensed under the MIT License.
4
+ ##
5
+ from __future__ import annotations
6
+ import re
7
+ import os
8
+ from re import Match
9
+ from typing import (
10
+ Optional,
11
+ Callable,
12
+ Union,
13
+ Any
14
+ )
15
+ from azure.core.credentials import AzureKeyCredential
16
+ from azure.core.pipeline.policies import AzureKeyCredentialPolicy
17
+ from azure.quantum._authentication import _DefaultAzureCredential
18
+ from azure.quantum._constants import (
19
+ EnvironmentKind,
20
+ EnvironmentVariables,
21
+ ConnectionConstants,
22
+ GUID_REGEX_PATTERN,
23
+ )
24
+
25
+ class WorkspaceConnectionParams:
26
+ """
27
+ Internal Azure Quantum Python SDK class to handle logic
28
+ for the parameters needed to connect to a Workspace.
29
+ """
30
+
31
+ RESOURCE_ID_REGEX = re.compile(
32
+ fr"""
33
+ ^
34
+ /subscriptions/(?P<subscription_id>{GUID_REGEX_PATTERN})
35
+ /resourceGroups/(?P<resource_group>[^\s/]+)
36
+ /providers/Microsoft\.Quantum
37
+ /Workspaces/(?P<workspace_name>[^\s/]+)
38
+ $
39
+ """,
40
+ re.VERBOSE | re.IGNORECASE)
41
+
42
+ CONNECTION_STRING_REGEX = re.compile(
43
+ fr"""
44
+ ^
45
+ SubscriptionId=(?P<subscription_id>{GUID_REGEX_PATTERN});
46
+ ResourceGroupName=(?P<resource_group>[^\s;]+);
47
+ WorkspaceName=(?P<workspace_name>[^\s;]+);
48
+ ApiKey=(?P<api_key>[^\s;]+);
49
+ QuantumEndpoint=(?P<quantum_endpoint>https://(?P<location>[^\s\.]+).quantum(?:-test)?.azure.com/);
50
+ """,
51
+ re.VERBOSE | re.IGNORECASE)
52
+
53
+ def __init__(
54
+ self,
55
+ subscription_id: Optional[str] = None,
56
+ resource_group: Optional[str] = None,
57
+ workspace_name: Optional[str] = None,
58
+ location: Optional[str] = None,
59
+ quantum_endpoint: Optional[str] = None,
60
+ arm_endpoint: Optional[str] = None,
61
+ environment: Union[str, EnvironmentKind, None] = None,
62
+ credential: Optional[object] = None,
63
+ resource_id: Optional[str] = None,
64
+ user_agent: Optional[str] = None,
65
+ user_agent_app_id: Optional[str] = None,
66
+ tenant_id: Optional[str] = None,
67
+ client_id: Optional[str] = None,
68
+ api_version: Optional[str] = None,
69
+ connection_string: Optional[str] = None,
70
+ on_new_client_request: Optional[Callable] = None,
71
+ ):
72
+ # fields are used for these properties since
73
+ # they have special getters/setters
74
+ self._location = None
75
+ self._environment = None
76
+ self._quantum_endpoint = None
77
+ self._arm_endpoint = None
78
+ # regular connection properties
79
+ self.subscription_id = None
80
+ self.resource_group = None
81
+ self.workspace_name = None
82
+ self.credential = None
83
+ self.user_agent = None
84
+ self.user_agent_app_id = None
85
+ self.client_id = None
86
+ self.tenant_id = None
87
+ self.api_version = None
88
+ # callback to create a new client if needed
89
+ # for example, when changing the user agent
90
+ self.on_new_client_request = on_new_client_request
91
+ # merge the connection parameters passed
92
+ # connection_string is set first as it
93
+ # should be overridden by other parameters
94
+ self.apply_connection_string(connection_string)
95
+ self.merge(
96
+ api_version=api_version,
97
+ arm_endpoint=arm_endpoint,
98
+ quantum_endpoint=quantum_endpoint,
99
+ client_id=client_id,
100
+ credential=credential,
101
+ environment=environment,
102
+ location=location,
103
+ resource_group=resource_group,
104
+ subscription_id=subscription_id,
105
+ tenant_id=tenant_id,
106
+ user_agent=user_agent,
107
+ user_agent_app_id=user_agent_app_id,
108
+ workspace_name=workspace_name,
109
+ )
110
+ self.apply_resource_id(resource_id=resource_id)
111
+
112
+ @property
113
+ def location(self):
114
+ """
115
+ The Azure location.
116
+ On the setter, we normalize the value removing spaces
117
+ and converting it to lowercase.
118
+ """
119
+ return self._location
120
+
121
+ @location.setter
122
+ def location(self, value: str):
123
+ self._location = (value.replace(" ", "").lower()
124
+ if isinstance(value, str)
125
+ else value)
126
+
127
+ @property
128
+ def environment(self):
129
+ """
130
+ The environment kind, such as dogfood, canary or production.
131
+ Defaults to EnvironmentKind.PRODUCTION
132
+ """
133
+ return self._environment or EnvironmentKind.PRODUCTION
134
+
135
+ @environment.setter
136
+ def environment(self, value: Union[str, EnvironmentKind]):
137
+ self._environment = (EnvironmentKind[value.upper()]
138
+ if isinstance(value, str)
139
+ else value)
140
+
141
+ @property
142
+ def quantum_endpoint(self):
143
+ """
144
+ The Azure Quantum data plane endpoint.
145
+ Defaults to well-known endpoint based on the environment.
146
+ """
147
+ if self._quantum_endpoint:
148
+ return self._quantum_endpoint
149
+ if not self.location:
150
+ raise ValueError("Location not specified")
151
+ if self.environment is EnvironmentKind.PRODUCTION:
152
+ return ConnectionConstants.GET_QUANTUM_PRODUCTION_ENDPOINT(self.location)
153
+ if self.environment is EnvironmentKind.CANARY:
154
+ return ConnectionConstants.GET_QUANTUM_CANARY_ENDPOINT(self.location)
155
+ if self.environment is EnvironmentKind.DOGFOOD:
156
+ return ConnectionConstants.GET_QUANTUM_DOGFOOD_ENDPOINT(self.location)
157
+ raise ValueError(f"Unknown environment `{self.environment}`.")
158
+
159
+ @quantum_endpoint.setter
160
+ def quantum_endpoint(self, value: str):
161
+ self._quantum_endpoint = value
162
+
163
+ @property
164
+ def arm_endpoint(self):
165
+ """
166
+ The control plane endpoint.
167
+ Defaults to well-known arm_endpoint based on the environment.
168
+ """
169
+ if self._arm_endpoint:
170
+ return self._arm_endpoint
171
+ if self.environment is EnvironmentKind.DOGFOOD:
172
+ return ConnectionConstants.ARM_DOGFOOD_ENDPOINT
173
+ if self.environment in [EnvironmentKind.PRODUCTION,
174
+ EnvironmentKind.CANARY]:
175
+ return ConnectionConstants.ARM_PRODUCTION_ENDPOINT
176
+ raise ValueError(f"Unknown environment `{self.environment}`.")
177
+
178
+ @arm_endpoint.setter
179
+ def arm_endpoint(self, value: str):
180
+ self._arm_endpoint = value
181
+
182
+ @property
183
+ def api_key(self):
184
+ """
185
+ The api-key stored in a AzureKeyCredential.
186
+ """
187
+ return (self.credential.key
188
+ if isinstance(self.credential, AzureKeyCredential)
189
+ else None)
190
+
191
+ @api_key.setter
192
+ def api_key(self, value: str):
193
+ if value:
194
+ self.credential = AzureKeyCredential(value)
195
+ self._api_key = value
196
+
197
+ def __repr__(self):
198
+ """
199
+ Print all fields and properties.
200
+ """
201
+ info = []
202
+ for key in vars(self):
203
+ info.append(f" {key}: {self.__dict__[key]}")
204
+ cls = type(self)
205
+ for key in dir(self):
206
+ attr = getattr(cls, key, None)
207
+ if attr and isinstance(attr, property) and attr.fget:
208
+ info.append(f" {key}: {attr.fget(self)}")
209
+ info.sort()
210
+ info.insert(0, super().__repr__())
211
+ return "\n".join(info)
212
+
213
+ def apply_resource_id(self, resource_id: str):
214
+ """
215
+ Parses the resource_id and set the connection
216
+ parameters obtained from it.
217
+ """
218
+ if resource_id:
219
+ match = re.search(
220
+ WorkspaceConnectionParams.RESOURCE_ID_REGEX,
221
+ resource_id)
222
+ if not match:
223
+ raise ValueError("Invalid resource id")
224
+ self._merge_re_match(match)
225
+
226
+ def apply_connection_string(self, connection_string: str):
227
+ """
228
+ Parses the connection_string and set the connection
229
+ parameters obtained from it.
230
+ """
231
+ if connection_string:
232
+ match = re.search(
233
+ WorkspaceConnectionParams.CONNECTION_STRING_REGEX,
234
+ connection_string)
235
+ if not match:
236
+ raise ValueError("Invalid connection string")
237
+ self._merge_re_match(match)
238
+
239
+ def merge(
240
+ self,
241
+ subscription_id: Optional[str] = None,
242
+ resource_group: Optional[str] = None,
243
+ workspace_name: Optional[str] = None,
244
+ location: Optional[str] = None,
245
+ quantum_endpoint: Optional[str] = None,
246
+ arm_endpoint: Optional[str] = None,
247
+ environment: Union[str, EnvironmentKind, None] = None,
248
+ credential: Optional[object] = None,
249
+ user_agent: Optional[str] = None,
250
+ user_agent_app_id: Optional[str] = None,
251
+ tenant_id: Optional[str] = None,
252
+ client_id: Optional[str] = None,
253
+ api_version: Optional[str] = None,
254
+ api_key: Optional[str] = None,
255
+ ):
256
+ """
257
+ Set all fields/properties with `not None` values
258
+ passed in the (named or key-valued) arguments
259
+ into this instance.
260
+ """
261
+ self._merge(
262
+ api_version=api_version,
263
+ arm_endpoint=arm_endpoint,
264
+ quantum_endpoint=quantum_endpoint,
265
+ client_id=client_id,
266
+ credential=credential,
267
+ environment=environment,
268
+ location=location,
269
+ resource_group=resource_group,
270
+ subscription_id=subscription_id,
271
+ tenant_id=tenant_id,
272
+ user_agent=user_agent,
273
+ user_agent_app_id=user_agent_app_id,
274
+ workspace_name=workspace_name,
275
+ api_key=api_key,
276
+ merge_default_mode=False,
277
+ )
278
+ return self
279
+
280
+ def apply_defaults(
281
+ self,
282
+ subscription_id: Optional[str] = None,
283
+ resource_group: Optional[str] = None,
284
+ workspace_name: Optional[str] = None,
285
+ location: Optional[str] = None,
286
+ quantum_endpoint: Optional[str] = None,
287
+ arm_endpoint: Optional[str] = None,
288
+ environment: Union[str, EnvironmentKind, None] = None,
289
+ credential: Optional[object] = None,
290
+ user_agent: Optional[str] = None,
291
+ user_agent_app_id: Optional[str] = None,
292
+ tenant_id: Optional[str] = None,
293
+ client_id: Optional[str] = None,
294
+ api_version: Optional[str] = None,
295
+ api_key: Optional[str] = None,
296
+ ) -> WorkspaceConnectionParams:
297
+ """
298
+ Set all fields/properties with `not None` values
299
+ passed in the (named or key-valued) arguments
300
+ into this instance IF the instance does not have
301
+ the corresponding parameter set yet.
302
+ """
303
+ self._merge(
304
+ api_version=api_version,
305
+ arm_endpoint=arm_endpoint,
306
+ quantum_endpoint=quantum_endpoint,
307
+ client_id=client_id,
308
+ credential=credential,
309
+ environment=environment,
310
+ location=location,
311
+ resource_group=resource_group,
312
+ subscription_id=subscription_id,
313
+ tenant_id=tenant_id,
314
+ user_agent=user_agent,
315
+ user_agent_app_id=user_agent_app_id,
316
+ workspace_name=workspace_name,
317
+ api_key=api_key,
318
+ merge_default_mode=True,
319
+ )
320
+ return self
321
+
322
+ def _merge(
323
+ self,
324
+ merge_default_mode: bool,
325
+ subscription_id: Optional[str] = None,
326
+ resource_group: Optional[str] = None,
327
+ workspace_name: Optional[str] = None,
328
+ location: Optional[str] = None,
329
+ quantum_endpoint: Optional[str] = None,
330
+ arm_endpoint: Optional[str] = None,
331
+ environment: Union[str, EnvironmentKind, None] = None,
332
+ credential: Optional[object] = None,
333
+ user_agent: Optional[str] = None,
334
+ user_agent_app_id: Optional[str] = None,
335
+ tenant_id: Optional[str] = None,
336
+ client_id: Optional[str] = None,
337
+ api_version: Optional[str] = None,
338
+ api_key: Optional[str] = None,
339
+ ):
340
+ """
341
+ Set all fields/properties with `not None` values
342
+ passed in the kwargs arguments
343
+ into this instance.
344
+
345
+ If merge_default_mode is True, skip setting
346
+ the field/property if it already has a value.
347
+ """
348
+ def _get_value_or_default(old_value, new_value):
349
+ if merge_default_mode and old_value:
350
+ return old_value
351
+ if new_value:
352
+ return new_value
353
+ return old_value
354
+
355
+ self.subscription_id = _get_value_or_default(self.subscription_id, subscription_id)
356
+ self.resource_group = _get_value_or_default(self.resource_group, resource_group)
357
+ self.workspace_name = _get_value_or_default(self.workspace_name, workspace_name)
358
+ self.location = _get_value_or_default(self.location, location)
359
+ self.environment = _get_value_or_default(self.environment, environment)
360
+ self.credential = _get_value_or_default(self.credential, credential)
361
+ self.user_agent = _get_value_or_default(self.user_agent, user_agent)
362
+ self.user_agent_app_id = _get_value_or_default(self.user_agent_app_id, user_agent_app_id)
363
+ self.client_id = _get_value_or_default(self.client_id, client_id)
364
+ self.tenant_id = _get_value_or_default(self.tenant_id, tenant_id)
365
+ self.api_version = _get_value_or_default(self.api_version, api_version)
366
+ self.api_key = _get_value_or_default(self.api_key, api_key)
367
+ # for these properties that have a default value in the getter, we use
368
+ # the private field as the old_value
369
+ self.quantum_endpoint = _get_value_or_default(self._quantum_endpoint, quantum_endpoint)
370
+ self.arm_endpoint = _get_value_or_default(self._arm_endpoint, arm_endpoint)
371
+ return self
372
+
373
+ def _merge_connection_params(
374
+ self,
375
+ connection_params: WorkspaceConnectionParams,
376
+ merge_default_mode: bool = False,
377
+ ) -> WorkspaceConnectionParams:
378
+ """
379
+ Set all fields/properties with `not None` values
380
+ from the `connection_params` into this instance.
381
+ """
382
+ self._merge(
383
+ api_version=connection_params.api_version,
384
+ client_id=connection_params.client_id,
385
+ credential=connection_params.credential,
386
+ environment=connection_params.environment,
387
+ location=connection_params.location,
388
+ resource_group=connection_params.resource_group,
389
+ subscription_id=connection_params.subscription_id,
390
+ tenant_id=connection_params.tenant_id,
391
+ user_agent=connection_params.user_agent,
392
+ user_agent_app_id=connection_params.user_agent_app_id,
393
+ workspace_name=connection_params.workspace_name,
394
+ merge_default_mode=merge_default_mode,
395
+ # for these properties that have a default value in the getter,
396
+ # so we use the private field instead
397
+ # pylint: disable=protected-access
398
+ arm_endpoint=connection_params._arm_endpoint,
399
+ quantum_endpoint=connection_params._quantum_endpoint,
400
+ )
401
+ return self
402
+
403
+ def get_credential_or_default(self) -> Any:
404
+ """
405
+ Get the credential if one was set,
406
+ or defaults to a new _DefaultAzureCredential.
407
+ """
408
+ return (self.credential
409
+ or _DefaultAzureCredential(
410
+ subscription_id=self.subscription_id,
411
+ arm_endpoint=self.arm_endpoint,
412
+ tenant_id=self.tenant_id))
413
+
414
+ def get_auth_policy(self) -> Any:
415
+ """
416
+ Returns a AzureKeyCredentialPolicy if using an AzureKeyCredential.
417
+ Defaults to None.
418
+ """
419
+ if isinstance(self.credential, AzureKeyCredential):
420
+ return AzureKeyCredentialPolicy(self.credential,
421
+ ConnectionConstants.QUANTUM_API_KEY_HEADER)
422
+ return None
423
+
424
+ def append_user_agent(self, value: str):
425
+ """
426
+ Append a new value to the Workspace's UserAgent and re-initialize the
427
+ QuantumClient. The values are appended using a dash.
428
+
429
+ :param value: UserAgent value to add, e.g. "azure-quantum-<plugin>"
430
+ """
431
+ new_user_agent = None
432
+
433
+ if (
434
+ value
435
+ and value not in (self.user_agent or "")
436
+ ):
437
+ new_user_agent = (f"{self.user_agent}-{value}"
438
+ if self.user_agent else value)
439
+
440
+ if new_user_agent != self.user_agent:
441
+ self.user_agent = new_user_agent
442
+ if self.on_new_client_request:
443
+ self.on_new_client_request()
444
+
445
+ def get_full_user_agent(self):
446
+ """
447
+ Get the full Azure Quantum Python SDK UserAgent
448
+ that is sent to the service via the header.
449
+ """
450
+ full_user_agent = self.user_agent
451
+ app_id = self.user_agent_app_id
452
+ if self.user_agent_app_id:
453
+ full_user_agent = (f"{app_id} {full_user_agent}"
454
+ if full_user_agent else app_id)
455
+ return full_user_agent
456
+
457
+ def is_complete(self) -> bool:
458
+ """
459
+ Returns true if we have all necessary parameters
460
+ to connect to the Azure Quantum Workspace.
461
+ """
462
+ return (self.location
463
+ and self.subscription_id
464
+ and self.resource_group
465
+ and self.workspace_name
466
+ and self.get_credential_or_default())
467
+
468
+ def assert_complete(self):
469
+ """
470
+ Raises ValueError if we don't have all necessary parameters
471
+ to connect to the Azure Quantum Workspace.
472
+ """
473
+ if not self.is_complete():
474
+ raise ValueError(
475
+ """
476
+ Azure Quantum workspace not fully specified.
477
+ Please specify one of the following:
478
+ 1) A valid combination of location and resource ID.
479
+ 2) A valid combination of location, subscription ID,
480
+ resource group name, and workspace name.
481
+ 3) A valid connection string (via Workspace.from_connection_string()).
482
+ """)
483
+
484
+ def default_from_env_vars(self) -> WorkspaceConnectionParams:
485
+ """
486
+ Apply default values found in the environment variables
487
+ if current parameters are not set.
488
+ """
489
+ self.subscription_id = (self.subscription_id
490
+ or os.environ.get(EnvironmentVariables.QUANTUM_SUBSCRIPTION_ID)
491
+ or os.environ.get(EnvironmentVariables.SUBSCRIPTION_ID))
492
+ self.resource_group = (self.resource_group
493
+ or os.environ.get(EnvironmentVariables.QUANTUM_RESOURCE_GROUP)
494
+ or os.environ.get(EnvironmentVariables.RESOURCE_GROUP))
495
+ self.workspace_name = (self.workspace_name
496
+ or os.environ.get(EnvironmentVariables.WORKSPACE_NAME))
497
+ self.location = (self.location
498
+ or os.environ.get(EnvironmentVariables.QUANTUM_LOCATION)
499
+ or os.environ.get(EnvironmentVariables.LOCATION))
500
+ self.user_agent_app_id = (self.user_agent_app_id
501
+ or os.environ.get(EnvironmentVariables.USER_AGENT_APPID))
502
+ self.tenant_id = (self.tenant_id
503
+ or os.environ.get(EnvironmentVariables.AZURE_TENANT_ID))
504
+ self.client_id = (self.client_id
505
+ or os.environ.get(EnvironmentVariables.AZURE_CLIENT_ID))
506
+ # for these properties we use the private field
507
+ # because the getter return default values
508
+ self.environment = (self._environment
509
+ or os.environ.get(EnvironmentVariables.QUANTUM_ENV))
510
+ # only try to use the connection string from env var if
511
+ # we really need it
512
+ if (not self.location
513
+ or not self.subscription_id
514
+ or not self.resource_group
515
+ or not self.workspace_name
516
+ or not self.credential
517
+ ):
518
+ self._merge_connection_params(
519
+ connection_params=WorkspaceConnectionParams(
520
+ connection_string=os.environ.get(EnvironmentVariables.CONNECTION_STRING)),
521
+ merge_default_mode=True)
522
+ return self
523
+
524
+ @classmethod
525
+ def from_env_vars(
526
+ cls,
527
+ ) -> WorkspaceConnectionParams:
528
+ """
529
+ Initialize the WorkspaceConnectionParams from values found
530
+ in the environment variables.
531
+ """
532
+ return WorkspaceConnectionParams().default_from_env_vars()
533
+
534
+ def _merge_re_match(self, re_match: Match[str]):
535
+ def get_value(group_name):
536
+ return re_match.groupdict().get(group_name)
537
+ self.merge(
538
+ subscription_id=get_value('subscription_id'),
539
+ resource_group=get_value('resource_group'),
540
+ workspace_name=get_value('workspace_name'),
541
+ location=get_value('location'),
542
+ quantum_endpoint=get_value('quantum_endpoint'),
543
+ api_key=get_value('api_key'),
544
+ )
azure/quantum/version.py CHANGED
@@ -5,4 +5,4 @@
5
5
  # Copyright (c) Microsoft Corporation. All rights reserved.
6
6
  # Licensed under the MIT License.
7
7
  ##
8
- __version__ = "1.1.1"
8
+ __version__ = "1.1.2.dev0"