From 2512c5a814be8e561ee667ec18034a6d574423ae Mon Sep 17 00:00:00 2001 From: Angela Burton Date: Wed, 28 Sep 2022 14:13:47 -0700 Subject: [PATCH 1/4] Updates to enable resource estimation in the CLI --- src/quantum/azext_quantum/_params.py | 18 ++++++++++++------ src/quantum/azext_quantum/commands.py | 15 +++++++++++++++ src/quantum/azext_quantum/operations/job.py | 9 +++++++-- 3 files changed, 34 insertions(+), 8 deletions(-) diff --git a/src/quantum/azext_quantum/_params.py b/src/quantum/azext_quantum/_params.py index 5f662e0c7ca..9e473afd3bd 100644 --- a/src/quantum/azext_quantum/_params.py +++ b/src/quantum/azext_quantum/_params.py @@ -6,8 +6,10 @@ # pylint: disable=line-too-long,protected-access,no-self-use,too-many-statements import argparse +import json from knack.arguments import CLIArgumentType -from azure.cli.core.azclierror import InvalidArgumentValueError +from azure.cli.core.azclierror import InvalidArgumentValueError, CLIError +from azure.cli.core.util import shell_safe_json_parse class JobParamsAction(argparse._AppendAction): @@ -19,10 +21,14 @@ def get_action(self, values, option_string): params = {} for item in values: try: - key, value = item.split('=', 1) - params[key] = value - except ValueError as e: - raise InvalidArgumentValueError('Usage error: {} KEY=VALUE [KEY=VALUE ...]'.format(option_string)) from e + json_obj = shell_safe_json_parse(item) + params.update(json_obj) + except CLIError as e: + try: + 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 return params @@ -34,7 +40,7 @@ def load_arguments(self, _): project_type = CLIArgumentType(help='The location of the Q# project to submit. Defaults to current folder.') job_name_type = CLIArgumentType(help='A friendly name to give to this run of the program.') job_id_type = CLIArgumentType(options_list=['--job-id', '-j'], help='Job unique identifier in GUID format.') - job_params_type = CLIArgumentType(options_list=['--job-params'], help='Job parameters passed to the target as a list of key=value pairs.', action=JobParamsAction, nargs='+') + job_params_type = CLIArgumentType(options_list=['--job-params'], help='Job parameters passed to the target as a list of key=value pairs, json string, or `@{file}` with json content.', action=JobParamsAction, nargs='+') target_capability_type = CLIArgumentType(options_list=['--target-capability'], help='Target-capability parameter passed to the compiler.') shots_type = CLIArgumentType(help='The number of times to run the Q# program on the given target.') no_build_type = CLIArgumentType(help='If specified, the Q# program is not built before submitting.') diff --git a/src/quantum/azext_quantum/commands.py b/src/quantum/azext_quantum/commands.py index 8b076a1b457..4d876457609 100644 --- a/src/quantum/azext_quantum/commands.py +++ b/src/quantum/azext_quantum/commands.py @@ -97,6 +97,21 @@ def one(key, value): elif 'histogram' in results: histogram = results['histogram'] return [one(key, histogram[key]) for key in histogram] + + elif 'reportData' in results: + table = [] + for group in results['reportData']['groups']: + table.append(OrderedDict([("Label", (f"---{group['title']}---")), + ('Value', '---'), + ('Description', '---') ])) + for entry in group['entries']: + val = results + for key in entry['path'].split("/"): + val = val[key] + table.append(OrderedDict([("Label", entry['label']), + ('Value', val), + ('Description', entry['description']) ]) ) + return table elif 'errorData' in results: notFound = 'Not found' diff --git a/src/quantum/azext_quantum/operations/job.py b/src/quantum/azext_quantum/operations/job.py index 1ca7b84dd6c..dc0e8a051a8 100644 --- a/src/quantum/azext_quantum/operations/job.py +++ b/src/quantum/azext_quantum/operations/job.py @@ -6,6 +6,7 @@ # pylint: disable=redefined-builtin,bare-except,inconsistent-return-statements import logging +import json import knack.log from azure.cli.core.azclierror import (FileOperationError, AzureInternalError, @@ -142,7 +143,11 @@ def _generate_submit_args(program_args, ws, target, token, project, job_name, sh if job_params: args.append("--job-params") for k, v in job_params.items(): - args.append(f"{k}={v}") + if isinstance(v, str): + # If value is string type already, do not use json.dumps(), since it will add extra escapes to the string + args.append(f"{k}={v}") + else: + args.append(f"{k}={json.dumps(v)}") args.extend(program_args) @@ -265,7 +270,7 @@ def output(cmd, job_id, resource_group_name=None, workspace_name=None, location= if len(lines) == 0: return - if job.target.startswith("microsoft.simulator"): + if job.target.startswith("microsoft.simulator") and job.target != "microsoft.simulator.resources-estimator": result_start_line = len(lines) - 1 is_result_string = lines[-1].endswith('"') if is_result_string: From ad5e487f35e5fe4689d1f87eca180c2b161b5a47 Mon Sep 17 00:00:00 2001 From: Angela Burton Date: Tue, 11 Oct 2022 10:35:15 -0700 Subject: [PATCH 2/4] empty commit for CI From 657da8fe0c320ce014726c6e2f17ef10a3fec8ea Mon Sep 17 00:00:00 2001 From: Angela Burton Date: Tue, 11 Oct 2022 11:09:39 -0700 Subject: [PATCH 3/4] formatting fix --- src/quantum/azext_quantum/commands.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/quantum/azext_quantum/commands.py b/src/quantum/azext_quantum/commands.py index 4d876457609..c330d41ef06 100644 --- a/src/quantum/azext_quantum/commands.py +++ b/src/quantum/azext_quantum/commands.py @@ -97,20 +97,20 @@ def one(key, value): elif 'histogram' in results: histogram = results['histogram'] return [one(key, histogram[key]) for key in histogram] - + elif 'reportData' in results: table = [] for group in results['reportData']['groups']: table.append(OrderedDict([("Label", (f"---{group['title']}---")), - ('Value', '---'), - ('Description', '---') ])) + ('Value', '---'), + ('Description', '---')])) for entry in group['entries']: val = results for key in entry['path'].split("/"): val = val[key] - table.append(OrderedDict([("Label", entry['label']), + table.append(OrderedDict([("Label", entry['label']), ('Value', val), - ('Description', entry['description']) ]) ) + ('Description', entry['description'])])) return table elif 'errorData' in results: From a9b293913692c887289fed56df34290aa9ee2eb9 Mon Sep 17 00:00:00 2001 From: Angela Burton Date: Tue, 11 Oct 2022 11:35:27 -0700 Subject: [PATCH 4/4] update formatting --- src/quantum/azext_quantum/commands.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/quantum/azext_quantum/commands.py b/src/quantum/azext_quantum/commands.py index c330d41ef06..abcb7116e23 100644 --- a/src/quantum/azext_quantum/commands.py +++ b/src/quantum/azext_quantum/commands.py @@ -101,16 +101,20 @@ def one(key, value): elif 'reportData' in results: table = [] for group in results['reportData']['groups']: - table.append(OrderedDict([("Label", (f"---{group['title']}---")), + table.append(OrderedDict([ + ("Label", (f"---{group['title']}---")), ('Value', '---'), - ('Description', '---')])) + ('Description', '---') + ])) for entry in group['entries']: val = results for key in entry['path'].split("/"): val = val[key] - table.append(OrderedDict([("Label", entry['label']), - ('Value', val), - ('Description', entry['description'])])) + table.append(OrderedDict([ + ("Label", entry['label']), + ('Value', val), + ('Description', entry['description']) + ])) return table elif 'errorData' in results: