diff --git a/src/quantum/azext_quantum/__init__.py b/src/quantum/azext_quantum/__init__.py index ed4d2bdbbf6..1024a39efb3 100644 --- a/src/quantum/azext_quantum/__init__.py +++ b/src/quantum/azext_quantum/__init__.py @@ -3,6 +3,8 @@ # Licensed under the MIT License. See License.txt in the project root for license information. # -------------------------------------------------------------------------------------------- +# pylint: disable=line-too-long + from azure.cli.core import AzCommandsLoader import azext_quantum._help # pylint: disable=unused-import @@ -35,7 +37,7 @@ def load_arguments(self, command): from ._version_check_helper import check_version from .operations.workspace import _show_tip from datetime import datetime - message = check_version(self.cli_ctx_config, CLI_REPORTED_VERSION, str(datetime.today()).split(' ')[0]) + message = check_version(self.cli_ctx_config, CLI_REPORTED_VERSION, str(datetime.today()).split(' ', maxsplit=1)[0]) if message is not None: _show_tip(message) diff --git a/src/quantum/azext_quantum/_params.py b/src/quantum/azext_quantum/_params.py index e1d92e53856..e5503284708 100644 --- a/src/quantum/azext_quantum/_params.py +++ b/src/quantum/azext_quantum/_params.py @@ -3,7 +3,7 @@ # Licensed under the MIT License. See License.txt in the project root for license information. # -------------------------------------------------------------------------------------------- -# pylint: disable=line-too-long,protected-access,no-self-use,too-many-statements +# pylint: disable=line-too-long,protected-access,too-many-statements import argparse from knack.arguments import CLIArgumentType @@ -27,11 +27,11 @@ def get_action(self, values, option_string): key, value = item.split('=', 1) params[key] = value except ValueError as e: - raise InvalidArgumentValueError('Usage error: {} KEY=VALUE [KEY=VALUE ...], json string, or @file expected'.format(option_string)) from e + raise InvalidArgumentValueError(f'Usage error: {option_string} KEY=VALUE [KEY=VALUE ...], json string, or @file expected') from e return params -def load_arguments(self, _): +def load_arguments(self, _): # pylint: disable=too-many-locals workspace_name_type = CLIArgumentType(options_list=['--workspace-name', '-w'], help='Name of the Quantum Workspace. You can configure the default workspace using `az quantum workspace set`.', configured_default='workspace', id_part=None) storage_account_name_type = CLIArgumentType(options_list=['--storage-account', '-a'], help='Name of the storage account to be used by a quantum workspace.') program_args_type = CLIArgumentType(nargs='*', help='List of arguments expected by the Q# operation specified as --name=value after `--`.') diff --git a/src/quantum/azext_quantum/_storage.py b/src/quantum/azext_quantum/_storage.py index bb372186112..d3f4a57607d 100644 --- a/src/quantum/azext_quantum/_storage.py +++ b/src/quantum/azext_quantum/_storage.py @@ -48,8 +48,8 @@ def create_container_using_client(container_client: ContainerClient): """ if not container_client.exists(): logger.debug( - f'{" - uploading to **new** container:"}' - f"{container_client.container_name}" + " - uploading to **new** container: %s", + container_client.container_name ) container_client.create_container() @@ -82,13 +82,13 @@ def upload_blob( blob = container.get_blob_client(blob_name) blob.upload_blob(data, content_settings=content_settings) - logger.debug(f" - blob '{blob_name}' uploaded. generating sas token.") + logger.debug(" - blob '%s' uploaded. generating sas token.", blob_name) if return_sas_token: uri = get_blob_uri_with_sas_token(blob) else: uri = remove_sas_token(blob.url) - logger.debug(f" - blob access url: '{uri}'.") + logger.debug(" - blob access url: '%s'.", uri) return uri diff --git a/src/quantum/azext_quantum/commands.py b/src/quantum/azext_quantum/commands.py index 4e929989ce5..eab7efbc96d 100644 --- a/src/quantum/azext_quantum/commands.py +++ b/src/quantum/azext_quantum/commands.py @@ -117,7 +117,7 @@ def one(key, value): ])) return table - elif isinstance(results, list) and len(results) > 0 and 'reportData' in results[0]: + elif isinstance(results, list) and len(results) > 0 and 'reportData' in results[0]: # pylint: disable=too-many-nested-blocks table = [] indices = range(len(results)) diff --git a/src/quantum/azext_quantum/operations/job.py b/src/quantum/azext_quantum/operations/job.py index 65e9e6b4599..a246aa20d75 100644 --- a/src/quantum/azext_quantum/operations/job.py +++ b/src/quantum/azext_quantum/operations/job.py @@ -44,6 +44,7 @@ _targets_with_allowed_failure_output = {"microsoft.dft"} + def _show_warning(msg): import colorama colorama.init() @@ -269,7 +270,7 @@ def _submit_directly_to_service(cmd, resource_group_name, workspace_name, locati raise RequiredArgumentMissingError(ERROR_MSG_MISSING_OUTPUT_FORMAT, JOB_SUBMIT_DOC_LINK_MSG) # An entry point is required on QIR jobs - if job_type == QIR_JOB: + if job_type == QIR_JOB: # pylint: disable=too-many-nested-blocks # An entry point is required for a QIR job, but there are four ways to specify it in a CLI command: # - Use the --entry-point parameter # - Include it in --job-params as entryPoint=MyEntryPoint @@ -413,8 +414,8 @@ def _submit_directly_to_service(cmd, resource_group_name, workspace_name, locati if shots is not None: try: job_params["shots"] = int(shots) - except: - raise InvalidArgumentValueError("Invalid --shots value. Shots must be an integer.") + except Exception as exc: + raise InvalidArgumentValueError("Invalid --shots value. Shots must be an integer.") from exc if target_capability is not None: job_params["targetCapability"] = target_capability if entry_point is not None: @@ -424,8 +425,8 @@ def _submit_directly_to_service(cmd, resource_group_name, workspace_name, locati if "count" in job_params.keys(): try: job_params["count"] = int(job_params["count"]) - except: - raise InvalidArgumentValueError("Invalid count value. Count must be an integer.") + except Exception as exc: + raise InvalidArgumentValueError("Invalid count value. Count must be an integer.") from exc # Convert all other numeric parameter values from string to int or float _convert_numeric_params(job_params) @@ -663,7 +664,7 @@ def _get_job_output(cmd, job, item=None): blob_service.get_blob_to_path(containerName, blobName, path) - with open(path) as json_file: + with open(path, encoding="utf-8") as json_file: lines = [line.strip() for line in json_file.readlines()] # Receiving an empty response is valid. diff --git a/src/quantum/azext_quantum/operations/workspace.py b/src/quantum/azext_quantum/operations/workspace.py index c6d3df4b8b6..5f0f933f0cf 100644 --- a/src/quantum/azext_quantum/operations/workspace.py +++ b/src/quantum/azext_quantum/operations/workspace.py @@ -156,7 +156,7 @@ def _add_quantum_providers(cmd, workspace, providers, auto_accept, skip_autoadd) _autoadd_providers(cmd, providers_in_region, providers_selected, workspace.location, auto_accept) # If there weren't any autoAdd providers and none were specified with the -r parameter, we have a problem... - if providers_selected == []: + if not providers_selected: raise RequiredArgumentMissingError("A list of Azure Quantum providers and SKUs (plans) is required.", "Supply the missing -r parameter. For example:\n" "\t-r \"Microsoft/Basic, Microsoft.FleetManagement/Basic\"\n" @@ -202,12 +202,10 @@ def _create_role_assignment(cmd, quantum_workspace): def _validate_storage_account(tier_or_kind_msg_text, tier_or_kind, supported_tiers_or_kinds): if tier_or_kind not in supported_tiers_or_kinds: - tier_or_kind_list = '' - for item in supported_tiers_or_kinds: - tier_or_kind_list += f"{item}, " + tier_or_kind_list = ', '.join(supported_tiers_or_kinds) plural = 's' if len(supported_tiers_or_kinds) != 1 else '' raise InvalidArgumentValueError(f"Storage account {tier_or_kind_msg_text} '{tier_or_kind}' is not supported.\n" - f"Storage account {tier_or_kind_msg_text}{plural} currently supported: {tier_or_kind_list[:-2]}") + f"Storage account {tier_or_kind_msg_text}{plural} currently supported: {tier_or_kind_list}") def create(cmd, resource_group_name, workspace_name, location, storage_account, skip_role_assignment=False, diff --git a/src/quantum/azext_quantum/tests/latest/test_quantum_jobs.py b/src/quantum/azext_quantum/tests/latest/test_quantum_jobs.py index 896078164ef..4e504e5ddfa 100644 --- a/src/quantum/azext_quantum/tests/latest/test_quantum_jobs.py +++ b/src/quantum/azext_quantum/tests/latest/test_quantum_jobs.py @@ -12,7 +12,7 @@ from azure.cli.testsdk import ScenarioTest from azure.cli.core.azclierror import InvalidArgumentValueError, AzureInternalError -from .utils import get_test_subscription_id, get_test_resource_group, get_test_workspace, get_test_workspace_location, issue_cmd_with_param_missing, get_test_workspace_storage, get_test_workspace_random_name +from .utils import get_test_subscription_id, get_test_resource_group, get_test_workspace, get_test_workspace_location, get_test_workspace_location_for_dft, issue_cmd_with_param_missing, get_test_workspace_storage, get_test_workspace_random_name from ..._client_factory import _get_data_credentials from ...commands import transform_output from ...operations.workspace import WorkspaceInfo, DEPLOYMENT_NAME_PREFIX @@ -126,7 +126,7 @@ def test_transform_output(self): table_row = table[0] hist_row = table_row[''] second_char = hist_row[1] - self.assertEquals(second_char, "\u2588") # Expecting a "Full Block" character here + self.assertEquals(second_char, "\u2588") # Expecting a "Full Block" character here # Give it a malformed histogram test_job_results = '{"Histogram":["[0,0,0]",0.125,"[1,0,0]",0.125,"[0,1,0]",0.125,"[1,1,0]"]}' @@ -135,36 +135,36 @@ def test_transform_output(self): # Call with output from a failed job test_job_results = \ - '{\ - "beginExecutionTime": "2022-02-25T18:57:26.093000+00:00",\ - "cancellationTime": null,\ - "containerUri": "https://foo...",\ - "costEstimate": null,\ - "creationTime": "2022-02-25T18:56:53.275035+00:00",\ - "endExecutionTime": "2022-02-25T18:57:26.093000+00:00",\ - "errorData": {\ - "code": "InsufficientResources",\ - "message": "Too many qubits requested"\ - },\ - "id": "11111111-2222-3333-4444-555555555555",\ - "inputDataFormat": "microsoft.ionq-ir.v2",\ - "inputDataUri": "https://bar...",\ - "inputParams": {\ - "shots": "500"\ - },\ - "isCancelling": false,\ - "metadata": {\ - "entryPointInput": {\"Qubits\":null},\ - "outputMappingBlobUri": "https://baz..."\ - },\ - "name": "",\ - "outputDataFormat": "microsoft.quantum-results.v1",\ - "outputDataUri": "https://quux...",\ - "providerId": "ionq",\ - "status": "Failed",\ - "tags": [],\ - "target": "ionq.simulator"\ - }' + '{\ + "beginExecutionTime": "2022-02-25T18:57:26.093000+00:00",\ + "cancellationTime": null,\ + "containerUri": "https://foo...",\ + "costEstimate": null,\ + "creationTime": "2022-02-25T18:56:53.275035+00:00",\ + "endExecutionTime": "2022-02-25T18:57:26.093000+00:00",\ + "errorData": {\ + "code": "InsufficientResources",\ + "message": "Too many qubits requested"\ + },\ + "id": "11111111-2222-3333-4444-555555555555",\ + "inputDataFormat": "microsoft.ionq-ir.v2",\ + "inputDataUri": "https://bar...",\ + "inputParams": {\ + "shots": "500"\ + },\ + "isCancelling": false,\ + "metadata": {\ + "entryPointInput": {\"Qubits\":null},\ + "outputMappingBlobUri": "https://baz..."\ + },\ + "name": "",\ + "outputDataFormat": "microsoft.quantum-results.v1",\ + "outputDataUri": "https://quux...",\ + "providerId": "ionq",\ + "status": "Failed",\ + "tags": [],\ + "target": "ionq.simulator"\ + }' table = transform_output(json.loads(test_job_results)) self.assertEquals(table['Status'], "Failed") @@ -176,30 +176,30 @@ def test_transform_output(self): # Call with missing "status", "code", "message", "target", "id", and "creationTime" test_job_results = \ - '{\ - "beginExecutionTime": "2022-02-25T18:57:26.093000+00:00",\ - "cancellationTime": null,\ - "containerUri": "https://foo...",\ - "costEstimate": null,\ - "endExecutionTime": "2022-02-25T18:57:26.093000+00:00",\ - "errorData": {\ - },\ - "inputDataFormat": "microsoft.ionq-ir.v2",\ - "inputDataUri": "https://bar...",\ - "inputParams": {\ - "shots": "500"\ - },\ - "isCancelling": false,\ - "metadata": {\ - "entryPointInput": {\"Qubits\":null},\ - "outputMappingBlobUri": "https://baz..."\ - },\ - "name": "",\ - "outputDataFormat": "microsoft.quantum-results.v1",\ - "outputDataUri": "https://quux...",\ - "providerId": "ionq",\ - "tags": []\ - }' + '{\ + "beginExecutionTime": "2022-02-25T18:57:26.093000+00:00",\ + "cancellationTime": null,\ + "containerUri": "https://foo...",\ + "costEstimate": null,\ + "endExecutionTime": "2022-02-25T18:57:26.093000+00:00",\ + "errorData": {\ + },\ + "inputDataFormat": "microsoft.ionq-ir.v2",\ + "inputDataUri": "https://bar...",\ + "inputParams": {\ + "shots": "500"\ + },\ + "isCancelling": false,\ + "metadata": {\ + "entryPointInput": {\"Qubits\":null},\ + "outputMappingBlobUri": "https://baz..."\ + },\ + "name": "",\ + "outputDataFormat": "microsoft.quantum-results.v1",\ + "outputDataUri": "https://quux...",\ + "providerId": "ionq",\ + "tags": []\ + }' table = transform_output(json.loads(test_job_results)) notFound = "Not found" @@ -282,7 +282,7 @@ def test_submit(self): @live_only() def test_submit_dft(self): - test_location = "westus" # DFT is not enabled in WestUS2 + test_location = get_test_workspace_location_for_dft() test_resource_group = get_test_resource_group() test_workspace_temp = get_test_workspace_random_name() test_provider_sku_list = "microsoft-elements/elements-internal-testing" @@ -291,7 +291,7 @@ def test_submit_dft(self): self.cmd(f"az quantum workspace create -g {test_resource_group} -w {test_workspace_temp} -l {test_location} -a {test_storage} -r \"{test_provider_sku_list}\" --skip-autoadd") self.cmd(f"az quantum workspace set -g {test_resource_group} -w {test_workspace_temp} -l {test_location}") - # Run a "microsoft.dft" job to test that successful job returns proper output + # Run a "microsoft.dft" job to test that successful job returns proper output results = self.cmd("az quantum run -t microsoft.dft --job-input-format microsoft.xyz.v1 --job-output-format microsoft.dft-results.v1 --job-input-file src/quantum/azext_quantum/tests/latest/input_data/dft_molecule_success.xyz --job-params {{\\\"tasks\\\":[{{\\\"taskType\\\":\\\"spe\\\",\\\"basisSet\\\":{{\\\"name\\\":\\\"def2-svp\\\",\\\"cartesian\\\":false}},\\\"xcFunctional\\\":{{\\\"name\\\":\\\"m06-2x\\\",\\\"gridLevel\\\":4}},\\\"scf\\\":{{\\\"method\\\":\\\"rks\\\",\\\"maxSteps\\\":100,\\\"convergeThreshold\\\":1e-8}}}}]}} -o json").get_output_in_json() self.assertIsNotNone(results["results"]) self.assertTrue(len(results["results"]) == 1) @@ -314,4 +314,4 @@ def test_submit_dft(self): self.assertTrue(len(results["results"]) == 1) self.assertFalse(results["results"][0]["success"]) - self.cmd(f'az quantum workspace delete -g {test_resource_group} -w {test_workspace_temp}') \ No newline at end of file + self.cmd(f'az quantum workspace delete -g {test_resource_group} -w {test_workspace_temp}') diff --git a/src/quantum/azext_quantum/tests/latest/test_quantum_targets.py b/src/quantum/azext_quantum/tests/latest/test_quantum_targets.py index 95296b64d7d..424536974e2 100644 --- a/src/quantum/azext_quantum/tests/latest/test_quantum_targets.py +++ b/src/quantum/azext_quantum/tests/latest/test_quantum_targets.py @@ -25,32 +25,32 @@ def test_targets(self): self.cmd(f'az quantum workspace set -g {get_test_resource_group()} -w {get_test_workspace()} -l {get_test_workspace_location()}') # clear current target - self.cmd(f'az quantum target clear') + self.cmd('az quantum target clear') # list targets = self.cmd('az quantum target list -o json').get_output_in_json() assert len(targets) > 0 # set - self.cmd(f'az quantum target set -t microsoft.estimator -o json', checks=[ + self.cmd('az quantum target set -t microsoft.estimator -o json', checks=[ self.check("targetId", "microsoft.estimator") ]) # show - self.cmd(f'az quantum target show -o json', checks=[ + self.cmd('az quantum target show -o json', checks=[ self.check("targetId", "microsoft.estimator") ]) # clear - self.cmd(f'az quantum target clear') + self.cmd('az quantum target clear') # show - self.cmd(f'az quantum target show -t microsoft.estimator -o json', checks=[ + self.cmd('az quantum target show -t microsoft.estimator -o json', checks=[ self.check("targetId", "microsoft.estimator") ]) def test_target_errors(self): - self.cmd(f'az quantum target clear') + self.cmd('az quantum target clear') issue_cmd_with_param_missing(self, "az quantum target set", "az quantum target set -t target-id\nSelect a default when submitting jobs to Azure Quantum.") @live_only() diff --git a/src/quantum/azext_quantum/tests/latest/test_quantum_workspace.py b/src/quantum/azext_quantum/tests/latest/test_quantum_workspace.py index c3e288ce995..1b16121e334 100644 --- a/src/quantum/azext_quantum/tests/latest/test_quantum_workspace.py +++ b/src/quantum/azext_quantum/tests/latest/test_quantum_workspace.py @@ -28,6 +28,7 @@ def __init__(self, id, auto_add): __test__ = False + class TestManagedApplicationDescription(object): def __init__(self, offer_id, publisher_id): self.offer_id = offer_id @@ -35,17 +36,18 @@ def __init__(self, offer_id, publisher_id): __test__ = False + class TestPropertyDescription(object): def __init__(self, managed_application, skus): self.managed_application = TestManagedApplicationDescription(None, None) self.skus = [TestSkuDescription(None, False)] __test__ = False - + + class TestProviderDescription: def __init__(self, id, properties): - id = str() - properties = TestPropertyDescription(TestManagedApplicationDescription(None, None), [TestSkuDescription(None, None)]) + return __test__ = False id = None @@ -58,7 +60,7 @@ class QuantumWorkspacesScenarioTest(ScenarioTest): @AllowLargeResponse() def test_workspace(self): # clear - self.cmd(f'az quantum workspace clear') + self.cmd('az quantum workspace clear') # initialize values test_location = get_test_workspace_location() @@ -78,12 +80,12 @@ def test_workspace(self): ]) # show - self.cmd(f'az quantum workspace show -o json', checks=[ + self.cmd('az quantum workspace show -o json', checks=[ self.check("name", test_workspace) ]) # clear - self.cmd(f'az quantum workspace clear') + self.cmd('az quantum workspace clear') @live_only() def test_workspace_create_destroy(self): @@ -98,75 +100,75 @@ def test_workspace_create_destroy(self): if all_providers_are_in_capabilities(test_provider_sku_list, get_test_capabilities()): # create self.cmd(f'az quantum workspace create -g {test_resource_group} -w {test_workspace_temp} -l {test_location} -a {test_storage_account} -r {test_provider_sku_list} -o json --skip-role-assignment', checks=[ - self.check("name", test_workspace_temp), - self.check("provisioningState", "Accepted") # Status is accepted since we're not linking the storage account. + self.check("name", test_workspace_temp), + self.check("provisioningState", "Accepted") # Status is accepted since we're not linking the storage account. ]) # delete self.cmd(f'az quantum workspace delete -g {test_resource_group} -w {test_workspace_temp} -o json', checks=[ - self.check("name", test_workspace_temp), - self.check("provisioningState", "Deleting") + self.check("name", test_workspace_temp), + self.check("provisioningState", "Deleting") ]) # Create workspace with "--skip-role-assignment" and "--skip-autoadd" parameters test_workspace_temp = get_test_workspace_random_name() self.cmd(f'az quantum workspace create --skip-autoadd -g {test_resource_group} -w {test_workspace_temp} -l {test_location} -a {test_storage_account} -r {test_provider_sku_list} -o json --skip-role-assignment', checks=[ - self.check("name", test_workspace_temp), - self.check("provisioningState", "Accepted") # Status is accepted since we're not linking the storage account. + self.check("name", test_workspace_temp), + self.check("provisioningState", "Accepted") # Status is accepted since we're not linking the storage account. ]) # delete self.cmd(f'az quantum workspace delete -g {test_resource_group} -w {test_workspace_temp} -o json', checks=[ - self.check("name", test_workspace_temp), - self.check("provisioningState", "Deleting") + self.check("name", test_workspace_temp), + self.check("provisioningState", "Deleting") ]) # Repeat without the "--skip-role-assignment" or "--skip-autoadd" parameters (Uses ARM template and adds C4A plans) test_workspace_temp = get_test_workspace_random_name() self.cmd(f'az quantum workspace create -g {test_resource_group} -w {test_workspace_temp} -l {test_location} -a {test_storage_account} -r {test_provider_sku_list} -o json', checks=[ - self.check("name", DEPLOYMENT_NAME_PREFIX + test_workspace_temp), + self.check("name", DEPLOYMENT_NAME_PREFIX + test_workspace_temp), ]) # delete self.cmd(f'az quantum workspace delete -g {test_resource_group} -w {test_workspace_temp} -o json', checks=[ - self.check("name", test_workspace_temp), - self.check("provisioningState", "Deleting") + self.check("name", test_workspace_temp), + self.check("provisioningState", "Deleting") ]) # Create a workspace specifying "--skip-autoadd" test_workspace_temp = get_test_workspace_random_name() self.cmd(f'az quantum workspace create --skip-autoadd -g {test_resource_group} -w {test_workspace_temp} -l {test_location} -a {test_storage_account} -r {test_provider_sku_list} -o json', checks=[ - self.check("name", DEPLOYMENT_NAME_PREFIX + test_workspace_temp), + self.check("name", DEPLOYMENT_NAME_PREFIX + test_workspace_temp), ]) # delete self.cmd(f'az quantum workspace delete -g {test_resource_group} -w {test_workspace_temp} -o json', checks=[ - self.check("name", test_workspace_temp), - self.check("provisioningState", "Deleting") + self.check("name", test_workspace_temp), + self.check("provisioningState", "Deleting") ]) # Create a workspace specifying a storage account that is not Standard_LRS test_workspace_temp = get_test_workspace_random_name() self.cmd(f'az quantum workspace create --skip-autoadd -g {test_resource_group} -w {test_workspace_temp} -l {test_location} -a {test_storage_account_grs} -r {test_provider_sku_list} -o json', checks=[ - self.check("name", DEPLOYMENT_NAME_PREFIX + test_workspace_temp), + self.check("name", DEPLOYMENT_NAME_PREFIX + test_workspace_temp), ]) # delete self.cmd(f'az quantum workspace delete -g {test_resource_group} -w {test_workspace_temp} -o json', checks=[ - self.check("name", test_workspace_temp), - self.check("provisioningState", "Deleting") + self.check("name", test_workspace_temp), + self.check("provisioningState", "Deleting") ]) # Create a workspace with a maximum length name, but make sure the deployment name was truncated to a valid length test_workspace_temp = get_test_workspace_random_long_name() self.cmd(f'az quantum workspace create --skip-autoadd -g {test_resource_group} -w {test_workspace_temp} -l {test_location} -a {test_storage_account_grs} -r {test_provider_sku_list} -o json', checks=[ - self.check("name", (DEPLOYMENT_NAME_PREFIX + test_workspace_temp)[:64]), + self.check("name", (DEPLOYMENT_NAME_PREFIX + test_workspace_temp)[:64]), ]) # delete self.cmd(f'az quantum workspace delete -g {test_resource_group} -w {test_workspace_temp} -o json', checks=[ - self.check("name", test_workspace_temp), - self.check("provisioningState", "Deleting") + self.check("name", test_workspace_temp), + self.check("provisioningState", "Deleting") ]) else: self.skipTest(f"Skipping test_workspace_create_destroy: One or more providers in '{test_provider_sku_list}' not found in AZURE_QUANTUM_CAPABILITIES") @@ -184,15 +186,13 @@ def test_workspace_errors(self): test_workspace_temp = get_test_workspace_random_name() # Attempt to create workspace, but omit the storage account parameter - issue_cmd_with_param_missing(self, f'az quantum workspace create -w {test_workspace_temp} -l {test_location} -g {test_resource_group} -r "microsoft-qc/learn-and-develop"', - 'az quantum workspace create -g MyResourceGroup -w MyWorkspace -l MyLocation -r "MyProvider1 / MySKU1, MyProvider2 / MySKU2" -a MyStorageAccountName To display a list of available providers and their SKUs, use the following command: az quantum offerings list -l MyLocation -o table\nCreate a new Azure Quantum workspace with a specific list of providers.') - + issue_cmd_with_param_missing(self, f'az quantum workspace create -w {test_workspace_temp} -l {test_location} -g {test_resource_group} -r "microsoft-qc/learn-and-develop"', 'az quantum workspace create -g MyResourceGroup -w MyWorkspace -l MyLocation -r "MyProvider1 / MySKU1, MyProvider2 / MySKU2" -a MyStorageAccountName To display a list of available providers and their SKUs, use the following command: az quantum offerings list -l MyLocation -o table\nCreate a new Azure Quantum workspace with a specific list of providers.') @live_only() def test_version_check(self): # initialize values test_old_date = "2021-04-01" - test_today = str(datetime.today()).split(' ')[0] + test_today = str(datetime.today()).split(' ')[0] test_old_reported_version = "0.1.0" test_current_reported_version = CLI_REPORTED_VERSION test_none_version = None @@ -207,7 +207,7 @@ def test_version_check(self): # Temporary fix was: # assert message == f"\nVersion {test_old_reported_version} of the quantum extension is installed locally, but version {test_current_reported_version} is now available.\nYou can use 'az extension update -n quantum' to upgrade.\n" - # No message is generated if either version number is unavailable. + # No message is generated if either version number is unavailable. message = check_version(test_config, test_none_version, test_today) assert message is None @@ -219,21 +219,21 @@ def test_validate_storage_account(self): # Invalid parameters should raise errors try: - _validate_storage_account('tier', 'Premium', SUPPORTED_STORAGE_SKU_TIERS) - assert False + _validate_storage_account('tier', 'Premium', SUPPORTED_STORAGE_SKU_TIERS) + assert False except InvalidArgumentValueError as e: assert str(e) == "Storage account tier 'Premium' is not supported.\nStorage account tier currently supported: Standard" try: - _validate_storage_account('kind', 'BlobStorage', SUPPORTED_STORAGE_KINDS) - assert False + _validate_storage_account('kind', 'BlobStorage', SUPPORTED_STORAGE_KINDS) + assert False except InvalidArgumentValueError as e: assert str(e) == "Storage account kind 'BlobStorage' is not supported.\nStorage account kinds currently supported: Storage, StorageV2" def test_autoadd_providers(self): test_managed_application = TestManagedApplicationDescription(None, None) test_skus = [TestSkuDescription(None, False)] - test_provider_properties = TestPropertyDescription(test_managed_application, test_skus) + test_provider_properties = TestPropertyDescription(test_managed_application, test_skus) test_provider = TestProviderDescription("", test_provider_properties) # Populate providers_in_region with an auto_add provider: diff --git a/src/quantum/azext_quantum/tests/latest/utils.py b/src/quantum/azext_quantum/tests/latest/utils.py index 789eeccf208..a4431cd9f67 100644 --- a/src/quantum/azext_quantum/tests/latest/utils.py +++ b/src/quantum/azext_quantum/tests/latest/utils.py @@ -16,50 +16,76 @@ TEST_TARGET_DEFAULT_PROVIDER = "microsoft-qc" TEST_TARGET_DEFAULT_TARGET = "microsoft.estimator" + def get_from_os_environment(env_name, default): import os return os.environ[env_name] if env_name in os.environ and os.environ[env_name] != "" else default + def get_test_subscription_id(): return get_from_os_environment("AZURE_QUANTUM_SUBSCRIPTION_ID", TEST_SUBS_DEFAULT) + def get_test_resource_group(): return get_from_os_environment("AZURE_QUANTUM_WORKSPACE_RG", TEST_RG_DEFAULT) + def get_test_workspace(): return get_from_os_environment("AZURE_QUANTUM_WORKSPACE_NAME", TEST_WORKSPACE_DEFAULT) + def get_test_workspace_location(): return get_from_os_environment("AZURE_QUANTUM_WORKSPACE_LOCATION", TEST_WORKSPACE_DEFAULT_LOCATION) + +def get_test_workspace_location_for_dft(): + """ TODO: Currently, "microsoft.dft" target is not available in WestUS2 region, + therefore we need to specify the region to WestUS. At the same time, + we need to preserve functionality of setting the region via environment variable + so that we could override it in E2E tests. + + Remove this method once/if "microsoft.dft" target is available in WestUS2. + """ + return get_from_os_environment("AZURE_QUANTUM_WORKSPACE_LOCATION", "westus") + + def get_test_workspace_storage(): return get_from_os_environment("AZURE_QUANTUM_WORKSPACE_STORAGE", TEST_WORKSPACE_DEFAULT_STORAGE) + def get_test_workspace_storage_grs(): return get_from_os_environment("AZURE_QUANTUM_WORKSPACE_STORAGE_GRS", TEST_WORKSPACE_DEFAULT_STORAGE_GRS) + def get_test_workspace_provider_sku_list(): return get_from_os_environment("AZURE_QUANTUM_WORKSPACE_PROVIDER_SKU_LIST", TEST_WORKSPACE_DEFAULT_PROVIDER_SKU_LIST) + def get_test_capabilities(): return get_from_os_environment("AZURE_QUANTUM_CAPABILITIES", TEST_CAPABILITIES_DEFAULT).lower() + def get_test_target_provider_sku_list(): return get_from_os_environment("AZURE_QUANTUM_TARGET_PROVIDER_SKU_LIST", TEST_TARGET_DEFAULT_PROVIDER_SKU_LIST) + def get_test_target_provider(): return get_from_os_environment("AZURE_QUANTUM_PROVIDER", TEST_TARGET_DEFAULT_PROVIDER) + def get_test_target_target(): return get_from_os_environment("AZURE_QUANTUM_TARGET", TEST_TARGET_DEFAULT_TARGET) + def get_test_workspace_random_name(): import random return "e2e-test-w" + str(random.randint(1000000, 9999999)) + def get_test_workspace_random_long_name(): return get_test_workspace_random_name() + "-53-char-name12345678901234567890123" + def all_providers_are_in_capabilities(provider_sku_string, capabilities_string): for provide_sku_pair in provider_sku_string.split(';'): provider = "new." + provide_sku_pair.split('/')[0].lower() @@ -74,6 +100,7 @@ def all_providers_are_in_capabilities(provider_sku_string, capabilities_string): # TEST_ERROR_MESSAGE_PREAMBLE = "the following arguments are required: " + def issue_cmd_with_param_missing(calling_object, command, help_example): try: calling_object.cmd(command)