From 2ae99b572092d02985f118d13fe51f76ba033e8f Mon Sep 17 00:00:00 2001 From: Peter Shen Date: Thu, 4 Jan 2024 15:46:45 -0800 Subject: [PATCH 1/8] Fix quantum lint --- src/quantum/azext_quantum/_storage.py | 8 +- src/quantum/azext_quantum/operations/job.py | 9 +- .../tests/latest/test_quantum_jobs.py | 114 +++++++++--------- .../tests/latest/test_quantum_targets.py | 12 +- .../tests/latest/test_quantum_workspace.py | 72 +++++------ .../azext_quantum/tests/latest/utils.py | 16 +++ 6 files changed, 124 insertions(+), 107 deletions(-) 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/operations/job.py b/src/quantum/azext_quantum/operations/job.py index 65e9e6b4599..a4367e1496f 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() @@ -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) 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..0750f2e085c 100644 --- a/src/quantum/azext_quantum/tests/latest/test_quantum_jobs.py +++ b/src/quantum/azext_quantum/tests/latest/test_quantum_jobs.py @@ -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" @@ -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..241463ad83f 100644 --- a/src/quantum/azext_quantum/tests/latest/utils.py +++ b/src/quantum/azext_quantum/tests/latest/utils.py @@ -16,50 +16,65 @@ 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_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 +89,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) From 9cacd77a2ceacefc42e6d66edac206d0c54c51a6 Mon Sep 17 00:00:00 2001 From: Peter Shen Date: Fri, 5 Jan 2024 09:37:39 -0800 Subject: [PATCH 2/8] fix lint --- src/quantum/azext_quantum/operations/job.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/quantum/azext_quantum/operations/job.py b/src/quantum/azext_quantum/operations/job.py index a4367e1496f..f791ccbe698 100644 --- a/src/quantum/azext_quantum/operations/job.py +++ b/src/quantum/azext_quantum/operations/job.py @@ -664,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. From 4ed40506c7c32ff95ca1441b762e7171846df062 Mon Sep 17 00:00:00 2001 From: Kirill Komissarov Date: Fri, 5 Jan 2024 12:37:21 -0800 Subject: [PATCH 3/8] fix: use WestUS location for DFT tests --- .../azext_quantum/tests/latest/test_quantum_jobs.py | 4 ++-- src/quantum/azext_quantum/tests/latest/utils.py | 11 +++++++++++ 2 files changed, 13 insertions(+), 2 deletions(-) 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 0750f2e085c..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 @@ -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" diff --git a/src/quantum/azext_quantum/tests/latest/utils.py b/src/quantum/azext_quantum/tests/latest/utils.py index 241463ad83f..fc264fb4c07 100644 --- a/src/quantum/azext_quantum/tests/latest/utils.py +++ b/src/quantum/azext_quantum/tests/latest/utils.py @@ -38,6 +38,17 @@ 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 the region 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) From 4dd3a235ff7dd59ae3159b00d364c680db79964c Mon Sep 17 00:00:00 2001 From: Kirill Komissarov Date: Fri, 5 Jan 2024 15:21:36 -0800 Subject: [PATCH 4/8] chore: minor fix to retrigger PR pipeline --- src/quantum/azext_quantum/tests/latest/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/quantum/azext_quantum/tests/latest/utils.py b/src/quantum/azext_quantum/tests/latest/utils.py index fc264fb4c07..2ceb8e1ba57 100644 --- a/src/quantum/azext_quantum/tests/latest/utils.py +++ b/src/quantum/azext_quantum/tests/latest/utils.py @@ -44,7 +44,7 @@ def get_test_workspace_location_for_dft(): we need to preserve functionality of setting the region via environment variable so that we could override the region in E2E tests. - Remove, this method once/if "microsoft.dft" target is available in WestUS2. + Remove this method once/if "microsoft.dft" target is available in WestUS2. """ return get_from_os_environment("AZURE_QUANTUM_WORKSPACE_LOCATION", "westus") From 1c799e7c749e5a693b3365897b813d86aee79d05 Mon Sep 17 00:00:00 2001 From: Kirill Komissarov Date: Fri, 5 Jan 2024 16:42:50 -0800 Subject: [PATCH 5/8] chore: retriggering PR pipeline --- src/quantum/azext_quantum/tests/latest/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/quantum/azext_quantum/tests/latest/utils.py b/src/quantum/azext_quantum/tests/latest/utils.py index 2ceb8e1ba57..55cb1eb3e38 100644 --- a/src/quantum/azext_quantum/tests/latest/utils.py +++ b/src/quantum/azext_quantum/tests/latest/utils.py @@ -42,7 +42,7 @@ 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 the region in E2E tests. + so that we could override it in E2E tests. Remove this method once/if "microsoft.dft" target is available in WestUS2. """ From 97000e956811206dd20497c2a41de64f08d35b12 Mon Sep 17 00:00:00 2001 From: Peter Shen Date: Mon, 8 Jan 2024 14:16:34 -0800 Subject: [PATCH 6/8] Fix other lint --- src/quantum/azext_quantum/_params.py | 2 +- src/quantum/azext_quantum/commands.py | 2 +- src/quantum/azext_quantum/operations/job.py | 2 +- src/quantum/azext_quantum/operations/workspace.py | 8 +++----- 4 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/quantum/azext_quantum/_params.py b/src/quantum/azext_quantum/_params.py index e1d92e53856..7549adaf49c 100644 --- a/src/quantum/azext_quantum/_params.py +++ b/src/quantum/azext_quantum/_params.py @@ -31,7 +31,7 @@ def get_action(self, values, option_string): 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/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 f791ccbe698..a246aa20d75 100644 --- a/src/quantum/azext_quantum/operations/job.py +++ b/src/quantum/azext_quantum/operations/job.py @@ -270,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 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, From 54c1834b1f84dd086836c8f7c04c4cb0d0e69665 Mon Sep 17 00:00:00 2001 From: Peter Shen Date: Mon, 8 Jan 2024 14:38:22 -0800 Subject: [PATCH 7/8] fix lint --- src/quantum/azext_quantum/__init__.py | 2 +- src/quantum/azext_quantum/_params.py | 4 ++-- src/quantum/azext_quantum/tests/latest/utils.py | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/quantum/azext_quantum/__init__.py b/src/quantum/azext_quantum/__init__.py index ed4d2bdbbf6..b0adba4216e 100644 --- a/src/quantum/azext_quantum/__init__.py +++ b/src/quantum/azext_quantum/__init__.py @@ -35,7 +35,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 7549adaf49c..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,7 +27,7 @@ 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 diff --git a/src/quantum/azext_quantum/tests/latest/utils.py b/src/quantum/azext_quantum/tests/latest/utils.py index 55cb1eb3e38..a4431cd9f67 100644 --- a/src/quantum/azext_quantum/tests/latest/utils.py +++ b/src/quantum/azext_quantum/tests/latest/utils.py @@ -39,8 +39,8 @@ def get_test_workspace_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, + """ 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. From 5a5ebccddb6ced6cf3514913e2c706ea2a5af76a Mon Sep 17 00:00:00 2001 From: Peter Shen Date: Mon, 8 Jan 2024 14:51:32 -0800 Subject: [PATCH 8/8] lint --- src/quantum/azext_quantum/__init__.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/quantum/azext_quantum/__init__.py b/src/quantum/azext_quantum/__init__.py index b0adba4216e..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