From f2333956861d66e9b388645dfbf46047288c71b7 Mon Sep 17 00:00:00 2001 From: Zulfat Nutfullin Date: Wed, 19 Nov 2025 16:37:12 -0800 Subject: [PATCH] Support v2 endpoints when creating workspace from connection string --- azure-quantum/azure/quantum/_constants.py | 4 ++ .../quantum/_workspace_connection_params.py | 2 +- azure-quantum/tests/unit/test_workspace.py | 72 +++++++++++++++++++ 3 files changed, 77 insertions(+), 1 deletion(-) diff --git a/azure-quantum/azure/quantum/_constants.py b/azure-quantum/azure/quantum/_constants.py index 2c7ca17ae..231288adc 100644 --- a/azure-quantum/azure/quantum/_constants.py +++ b/azure-quantum/azure/quantum/_constants.py @@ -63,10 +63,14 @@ class ConnectionConstants: # pylint: disable=unnecessary-lambda-assignment GET_QUANTUM_PRODUCTION_ENDPOINT = \ lambda location: f"https://{location}.quantum.azure.com/" + GET_QUANTUM_PRODUCTION_ENDPOINT_v2 = \ + lambda location: f"https://{location}-v2.quantum.azure.com/" GET_QUANTUM_CANARY_ENDPOINT = \ lambda location: f"https://{location or 'eastus2euap'}.quantum.azure.com/" GET_QUANTUM_DOGFOOD_ENDPOINT = \ lambda location: f"https://{location}.quantum-test.azure.com/" + GET_QUANTUM_DOGFOOD_ENDPOINT_v2 = \ + lambda location: f"https://{location}-v2.quantum-test.azure.com/" ARM_PRODUCTION_ENDPOINT = "https://management.azure.com/" ARM_DOGFOOD_ENDPOINT = "https://api-dogfood.resources.windows-int.net/" diff --git a/azure-quantum/azure/quantum/_workspace_connection_params.py b/azure-quantum/azure/quantum/_workspace_connection_params.py index 8411fde23..c9ebc779b 100644 --- a/azure-quantum/azure/quantum/_workspace_connection_params.py +++ b/azure-quantum/azure/quantum/_workspace_connection_params.py @@ -46,7 +46,7 @@ class WorkspaceConnectionParams: ResourceGroupName=(?P[^\s;]+); WorkspaceName=(?P[^\s;]+); ApiKey=(?P[^\s;]+); - QuantumEndpoint=(?Phttps://(?P[^\s\.]+).quantum(?:-test)?.azure.com/); + QuantumEndpoint=(?Phttps://(?P[^\s\.]+?)(?:-v2)?.quantum(?:-test)?.azure.com/); """, re.VERBOSE | re.IGNORECASE) diff --git a/azure-quantum/tests/unit/test_workspace.py b/azure-quantum/tests/unit/test_workspace.py index 9c424c73e..76bab7467 100644 --- a/azure-quantum/tests/unit/test_workspace.py +++ b/azure-quantum/tests/unit/test_workspace.py @@ -38,6 +38,14 @@ quantum_endpoint=ConnectionConstants.GET_QUANTUM_PRODUCTION_ENDPOINT(LOCATION) ) +SIMPLE_CONNECTION_STRING_V2 = ConnectionConstants.VALID_CONNECTION_STRING( + subscription_id=SUBSCRIPTION_ID, + resource_group=RESOURCE_GROUP, + workspace_name=WORKSPACE, + api_key=API_KEY, + quantum_endpoint=ConnectionConstants.GET_QUANTUM_PRODUCTION_ENDPOINT_v2(LOCATION) +) + class TestWorkspace(QuantumTestBase): def test_create_workspace_instance_valid(self): @@ -204,6 +212,70 @@ def test_workspace_from_connection_string(self): self.assertEqual(workspace.subscription_id, SUBSCRIPTION_ID) self.assertEqual(workspace.resource_group, RESOURCE_GROUP) self.assertEqual(workspace.name, WORKSPACE) + + def test_workspace_from_connection_string_v2(self): + """Test that v2 QuantumEndpoint format is correctly parsed.""" + with mock.patch.dict( + os.environ, + clear=True + ): + workspace = Workspace.from_connection_string(SIMPLE_CONNECTION_STRING_V2) + self.assertEqual(workspace.location, LOCATION) + self.assertEqual(workspace.subscription_id, SUBSCRIPTION_ID) + self.assertEqual(workspace.resource_group, RESOURCE_GROUP) + self.assertEqual(workspace.name, WORKSPACE) + self.assertIsInstance(workspace.credential, AzureKeyCredential) + self.assertEqual(workspace.credential.key, API_KEY) + # pylint: disable=protected-access + self.assertIsInstance( + workspace._client._config.authentication_policy, + AzureKeyCredentialPolicy) + auth_policy = workspace._client._config.authentication_policy + self.assertEqual(auth_policy._name, ConnectionConstants.QUANTUM_API_KEY_HEADER) + self.assertEqual(id(auth_policy._credential), + id(workspace.credential)) + + def test_workspace_from_connection_string_v2_dogfood(self): + """Test v2 QuantumEndpoint with dogfood environment.""" + canary_location = "eastus2euap" + dogfood_connection_string_v2 = ConnectionConstants.VALID_CONNECTION_STRING( + subscription_id=SUBSCRIPTION_ID, + resource_group=RESOURCE_GROUP, + workspace_name=WORKSPACE, + api_key=API_KEY, + quantum_endpoint=ConnectionConstants.GET_QUANTUM_DOGFOOD_ENDPOINT_v2(canary_location) + ) + + with mock.patch.dict(os.environ, clear=True): + workspace = Workspace.from_connection_string(dogfood_connection_string_v2) + self.assertEqual(workspace.location, canary_location) + self.assertEqual(workspace.subscription_id, SUBSCRIPTION_ID) + self.assertEqual(workspace.resource_group, RESOURCE_GROUP) + self.assertEqual(workspace.name, WORKSPACE) + self.assertIsInstance(workspace.credential, AzureKeyCredential) + self.assertEqual(workspace.credential.key, API_KEY) + + def test_env_connection_string_v2(self): + """Test v2 QuantumEndpoint from environment variable.""" + with mock.patch.dict(os.environ): + self.clear_env_vars(os.environ) + os.environ[EnvironmentVariables.CONNECTION_STRING] = SIMPLE_CONNECTION_STRING_V2 + + workspace = Workspace() + self.assertEqual(workspace.location, LOCATION) + self.assertEqual(workspace.subscription_id, SUBSCRIPTION_ID) + self.assertEqual(workspace.name, WORKSPACE) + self.assertEqual(workspace.resource_group, RESOURCE_GROUP) + self.assertIsInstance(workspace.credential, AzureKeyCredential) + self.assertEqual(workspace.credential.key, API_KEY) + # pylint: disable=protected-access + self.assertIsInstance( + workspace._client._config.authentication_policy, + AzureKeyCredentialPolicy) + auth_policy = workspace._client._config.authentication_policy + self.assertEqual(auth_policy._name, ConnectionConstants.QUANTUM_API_KEY_HEADER) + self.assertEqual(id(auth_policy._credential), + id(workspace.credential)) def test_create_workspace_instance_invalid(self): def assert_value_error(exception):