From 9a63c66e7970d5c934426a9cd8d120bc88ea626d Mon Sep 17 00:00:00 2001 From: Sanjana Gupta <42555338+sanjgupt@users.noreply.github.com> Date: Mon, 3 May 2021 11:37:28 -0700 Subject: [PATCH 01/21] add online problem plus testing for it. Download method in problme --- .../azure/quantum/optimization/__init__.py | 2 +- .../azure/quantum/optimization/problem.py | 13 +- azure-quantum/tests/unit/quantum_test_base.py | 198 ------------------ azure-quantum/tests/unit/test_job.py | 2 +- azure-quantum/tests/unit/test_optimization.py | 2 +- azure-quantum/tests/unit/test_workspace.py | 2 +- 6 files changed, 15 insertions(+), 204 deletions(-) delete mode 100644 azure-quantum/tests/unit/quantum_test_base.py diff --git a/azure-quantum/azure/quantum/optimization/__init__.py b/azure-quantum/azure/quantum/optimization/__init__.py index e7975d7a9..0d4e46b44 100644 --- a/azure-quantum/azure/quantum/optimization/__init__.py +++ b/azure-quantum/azure/quantum/optimization/__init__.py @@ -8,4 +8,4 @@ from .problem import * from .solvers import * from .streaming_problem import * - +from .online_problem import * diff --git a/azure-quantum/azure/quantum/optimization/problem.py b/azure-quantum/azure/quantum/optimization/problem.py index 22cd63577..597dfdbef 100644 --- a/azure-quantum/azure/quantum/optimization/problem.py +++ b/azure-quantum/azure/quantum/optimization/problem.py @@ -14,8 +14,8 @@ from typing import List, Union, Dict, Optional, TYPE_CHECKING from enum import Enum from azure.quantum.optimization import Term -from azure.quantum.storage import upload_blob, ContainerClient - +from azure.quantum.storage import upload_blob, ContainerClient, BlobClient, download_blob +#import azure.quantum.storage logger = logging.getLogger(__name__) @@ -230,3 +230,12 @@ def is_large(self) -> bool: set_vars.update(term.ids) return (len(set_vars) >= Problem.NUM_VARIABLES_LARGE and len(self.terms) >= Problem.NUM_TERMS_LARGE) + + def download(self): + """Dowloads an uploaded problem as an instance of 'Problem' + """ + if not self.uploaded_blob_uri: + raise Exception("Problem must be uploaded before it can be downloaded") + contents = download_blob(self.uploaded_blob_uri) + return Problem.deserialize(contents, self.name) + diff --git a/azure-quantum/tests/unit/quantum_test_base.py b/azure-quantum/tests/unit/quantum_test_base.py deleted file mode 100644 index 931a81727..000000000 --- a/azure-quantum/tests/unit/quantum_test_base.py +++ /dev/null @@ -1,198 +0,0 @@ -#!/bin/env python -# -*- coding: utf-8 -*- -## -# recording_updater.py: Updates test recordings with dummy values -## -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. -## - -## IMPORTS ## - -import os -import re -import unittest.mock -from azure.quantum import Workspace -from azure.common.credentials import ServicePrincipalCredentials -from msrest.authentication import BasicTokenAuthentication -from azure_devtools.scenario_tests.base import ReplayableTest -from azure_devtools.scenario_tests.recording_processors import RecordingProcessor, is_text_payload, AccessTokenReplacer -from azure_devtools.scenario_tests.utilities import _get_content_type - -class QuantumTestBase(ReplayableTest): - """QuantumTestBase - - During init, gets Azure Credentials and Azure Quantum Workspace parameters from OS environment variables. - """ - - dummy_uid = "00000000-0000-0000-0000-000000000000" - dummy_rg = "dummy-rg" - dummy_ws = "dummy-ws" - dummy_clientsecret = "sanitized" - dummy_auth_token = {'access_token': 'eyJ1eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJidWQiOiJodHRwczovL3F1YW50dW0ubWljcm9zb2Z0LmNvbSIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTE2ODMwNjAsIm5iZiI6MTYxMTY4MzA2MCwiZXhwIjoxNjExNjg2OTYwLCJfY2xhaW1fbmFtZXMiOnsiZ3JvdXBzIjoic3JjMSJ9LCJfY2xhaW1fc291cmNlcyI6eyJzcmMxIjp7ImVuZHBvaW50IjoiaHR0cHM6Ly9ncmFwaC53aW5kb3dzLm5ldC83MmY5ODhiZi04NmYxLTQxYWYtOTFhYi0yZDdjZDAxMWRiNDcvdXNlcnMvZTlhNGE5ZTEtODcxNS00Yjc1LTk2NWQtYzBkZDQxMTIzODY4L2dldE1lbWJlck9iamVjdHMifX0sImFjciI6IjEiLCJhaW8iOiJBVlFBcS84U0FBQUFXMnNsMlRORXd5eXA2OGdvejM2RnRoSXFZSlJDdmRibDF0WVJPanUrUzNCZDV5MGsyeWMyOFdKUk9IQ283a0VuNGRpaDh1dkpLQm00TFNoTHRUQ3FsMHMwNkp6N3NYclNpNTFJOEljZThZcz0iLCJhbXIiOlsid2lhIiwibWZhIl0sImFwcGlkIjoiODRiYTA5NDctNmM1My00ZGQyLTljYTktYjM2OTQ3NjE1MjFiIiwiYXBwaWRhY3IiOiIwIiwiZmFtaWx5X25hbWUiOiJCcm93biIsImdpdmVuX25hbWUiOiJUb20iLCJpbl9jb3JwIjoidHJ1ZSIsImlwYWRkciI6IjczLjgzLjM5LjEwIiwibmFtZSI6IlRvbSBCcm93biIsIm9pZCI6ImU5YTRhOWUxLTg3MTUtNGI3NS05NjVkLWMwZGQ0MTEyMzg2OCIsIm9ucHJlbV9zaWQiOiJTLTEtNS0yMS0yMTI3NTIxMTg0LTE2MDQwMTI5MjAtMTg4NzkyNzUyNy0xNzc1MDU1MSIsInB1aWQiOiIxMDAzN0ZGRTkyREI4MzEyIiwicmgiOiIwLkFSb0F2NGo1Y3ZHR3IwR1JxeTE4MEJIYlIwY0p1b1JUYk5KTm5LbXphVWRoVWhzYUFPOC4iLCJzY3AiOiJKb2JzLlJlYWRXcml0ZSIsInN1YiI6IjNxVk1XZ3cxRWozYVRlTEdTenE0bmVsMms1UHFVS1BBY2ZVNDBSUl9JZ3MiLCJ0aWQiOiI3MmY5ODhiZi04NmYxLTQxYWYtOTFhYi0yZDdjZDAxMWRiNDciLCJ1bmlxdWVfbmFtZSI6InRoYnJvQG1pY3Jvc29mdC5jb20iLCJ1cG4iOiJ0aGJyb0BtaWNyb3NvZnQuY29tIiwidXRpIjoiUzMxNVVqbk9JVWUzeDdRR3ZaVWFBQSIsInZlciI6IjEuMCIsIndpZHMiOlsiYjc5ZmJmNGQtM2VmOS00Njg5LTgxNDMtNzZiMTk0ZTg1NTA5Il19.PCWEtCdso3_jehm3Ppg9lCSy_VgwY96IG0_Lqji5tN3yEmBmsP4Du-6MA2IHlz7pbKfQ8Qdw4aeobWZkuDW71Zo9PCkBSLQewng5EMbDvZO3jPJfCOd0IepaPVdtvtaCL2KnPEZicEM4kIO_9f8hCC4Ik8MAem788HuutNhN_YExJDWtM-aNoXIBLtDm39u3bCr2WFk4he3xpISLD3ZqAk2UPKagMwuwO-tArtcoQvA1_n_owv-I5P8vEk1wOmUh6LTB6pUAIS4wFIMgINUE1dBSuQmyimEfc7rRuWl-YJrMH0WRdbgFutwbBv_5dKs6VcYGgrvA3nIGU_Xz5vuJMA', 'token_type': 'Bearer', 'expires_in': 485} - - def __init__(self, method_name): - self._client_id = os.environ.get("AZURE_CLIENT_ID", self.dummy_uid) - self._client_secret = os.environ.get("AZURE_CLIENT_SECRET", self.dummy_clientsecret) - self._tenant_id = os.environ.get("AZURE_TENANT_ID", self.dummy_uid) - self._resource_group = os.environ.get("RESOURCE_GROUP", self.dummy_rg) - self._subscription_id = os.environ.get("SUBSCRIPTION_ID", self.dummy_uid) - self._workspace_name = os.environ.get("WORKSPACE_NAME", self.dummy_ws) - - regex_replacer = CustomRecordingProcessor() - recording_processors = [] - recording_processors.append(regex_replacer) - recording_processors.append(AccessTokenReplacer()) - replay_processors = [] - - super(QuantumTestBase, self).__init__(method_name, recording_processors=recording_processors, replay_processors=replay_processors) - - if not (self.in_recording or self.is_live): - self._client_id = self.dummy_uid - self._client_secret = self.dummy_clientsecret - self._tenant_id = self.dummy_uid - self._resource_group = self.dummy_rg - self._subscription_id = self.dummy_uid - self._workspace_name = self.dummy_ws - - regex_replacer.register_regex(self.client_id, self.dummy_uid) - regex_replacer.register_regex(self.client_secret, self.dummy_clientsecret) - regex_replacer.register_regex(self.tenant_id, self.dummy_uid) - regex_replacer.register_regex(self.subscription_id, self.dummy_uid) - regex_replacer.register_regex(self.workspace_name, self.dummy_ws) - regex_replacer.register_regex(self.resource_group, self.dummy_rg) - regex_replacer.register_regex(r'/subscriptions/([a-f0-9]+[-]){4}[a-f0-9]+', "/subscriptions/" + self.dummy_uid) - regex_replacer.register_regex(r'job-([a-f0-9]+[-]){4}[a-f0-9]+', "job-" + self.dummy_uid) - regex_replacer.register_regex(r'jobs/([a-f0-9]+[-]){4}[a-f0-9]+', "jobs/" + self.dummy_uid) - regex_replacer.register_regex(r'"id":\s*"([a-f0-9]+[-]){4}[a-f0-9]+"', '"id": "{}"'. format(self.dummy_uid)) - regex_replacer.register_regex(r'/resourceGroups/[a-z0-9-]+/', "/resourceGroups/dummy-rg/") - regex_replacer.register_regex(r'/workspaces/[a-z0-9-]+/', "/workspaces/dummy-ws/") - regex_replacer.register_regex(r'sig=[0-9a-zA-Z%]+\&', "sig=sanitized&") - regex_replacer.register_regex(r'sv=[^&]+\&', "sv=sanitized&") - regex_replacer.register_regex(r'se=[^&]+\&', "se=sanitized&") - - def setUp(self): - super(QuantumTestBase, self).setUp() - # mitigation for issue https://github.com/kevin1024/vcrpy/issues/533 - self.cassette.allow_playback_repeats = True - - @property - def client_id(self): - return self._client_id - - @property - def client_secret(self): - return self._client_secret - - @property - def tenant_id(self): - return self._tenant_id - - @property - def resource_group(self): - return self._resource_group - - @property - def subscription_id(self): - return self._subscription_id - - @property - def workspace_name(self): - return self._workspace_name - - def create_workspace(self) -> Workspace: - """Create workspace using credentials stored in config file - - :return: Workspace - :rtype: Workspace - """ - - workspace = Workspace( - - subscription_id=self.subscription_id, - resource_group=self.resource_group, - name=self.workspace_name, - ) - - if self.is_live or self.in_recording: - workspace.credentials = ServicePrincipalCredentials( - tenant=self.tenant_id, - client_id=self.client_id, - secret=self.client_secret, - resource = "https://quantum.microsoft.com" - ) - workspace.login(False) - else: - workspace.credentials = BasicTokenAuthentication(token=self.dummy_auth_token) - - return workspace - -class CustomRecordingProcessor(RecordingProcessor): - - ALLOW_HEADERS = [ - 'content-length', - 'content-type', - 'accept', - 'accept-encoding', - 'accept-charset', - 'accept-ranges', - 'x-ms-range', - 'transfer-encoding', - 'x-ms-blob-content-md5', - 'x-ms-blob-type', - 'x-ms-creation-time', - 'x-ms-lease-state', - 'x-ms-lease-status', - 'x-ms-server-encrypted', - 'x-ms-version' - ] - - def __init__(self): - self._regexes = [] - - def register_regex(self, oldRegex, new): - self._regexes.append((re.compile(oldRegex), new)) - - def process_request(self, request): - headers = {} - for key in request.headers: - if key.lower() in self.ALLOW_HEADERS: - headers[key] = request.headers[key] - #request.headers = headers - - for oldRegex, new in self._regexes: - request.uri = oldRegex.sub(new, request.uri) - - if _get_content_type(request) == "application/x-www-form-urlencoded": - body = request.body.decode("utf-8") - for oldRegex, new in self._regexes: - body = oldRegex.sub(new, body) - request.body = body.encode("utf-8") - else: - body = str(request.body) - for oldRegex, new in self._regexes: - body = oldRegex.sub(new, body) - request.body = body - - return request - - def process_response(self, response): - import six - - headers = {} - for key in response['headers']: - if key.lower() in self.ALLOW_HEADERS: - headers[key.lower()] = response['headers'][key] - #response['headers'] = headers - - if is_text_payload(response): - body = response['body']['string'] - if not isinstance(body, six.string_types): - body = body.decode("utf-8") - if is_text_payload(response) and body: - for oldRegex, new in self._regexes: - body = oldRegex.sub(new, body) - response['body']['string'] = body - - return response - diff --git a/azure-quantum/tests/unit/test_job.py b/azure-quantum/tests/unit/test_job.py index 2b95da2e3..4752bfbd8 100644 --- a/azure-quantum/tests/unit/test_job.py +++ b/azure-quantum/tests/unit/test_job.py @@ -15,7 +15,7 @@ from azure.quantum.optimization import Problem from azure.quantum.optimization.solvers import SimulatedAnnealing from azure.quantum import Job -from quantum_test_base import QuantumTestBase +from common import QuantumTestBase class TestJob(QuantumTestBase): diff --git a/azure-quantum/tests/unit/test_optimization.py b/azure-quantum/tests/unit/test_optimization.py index a845d615f..462b56d9a 100644 --- a/azure-quantum/tests/unit/test_optimization.py +++ b/azure-quantum/tests/unit/test_optimization.py @@ -15,7 +15,7 @@ from azure.quantum import Workspace from azure.quantum.optimization import Problem, ProblemType, Term from azure.quantum.optimization.solvers import ParallelTempering, PopulationAnnealing, RangeSchedule, SimulatedAnnealing, HardwarePlatform, QuantumMonteCarlo, SubstochasticMonteCarlo -from quantum_test_base import QuantumTestBase +from common import QuantumTestBase class TestProblem(QuantumTestBase): def test_add_terms(self): diff --git a/azure-quantum/tests/unit/test_workspace.py b/azure-quantum/tests/unit/test_workspace.py index 1f272a1e4..312972bd4 100644 --- a/azure-quantum/tests/unit/test_workspace.py +++ b/azure-quantum/tests/unit/test_workspace.py @@ -13,7 +13,7 @@ import pytest from azure.quantum import Workspace -from quantum_test_base import QuantumTestBase +from common import QuantumTestBase class TestWorkspace(QuantumTestBase): def test_workspace_login(self): From d83a6d53a153f90f40f60a7394bda97032432ed7 Mon Sep 17 00:00:00 2001 From: Sanjana Gupta <42555338+sanjgupt@users.noreply.github.com> Date: Mon, 3 May 2021 11:40:10 -0700 Subject: [PATCH 02/21] nit --- .../quantum/optimization/online_problem.py | 27 +++ azure-quantum/tests/unit/common.py | 211 ++++++++++++++++++ .../tests/unit/test_online_problem.py | 29 +++ azure-quantum/tests/unit/test_optimization.py | 2 +- azure-quantum/tests/unit/test_problem.py | 26 +++ 5 files changed, 294 insertions(+), 1 deletion(-) create mode 100644 azure-quantum/azure/quantum/optimization/online_problem.py create mode 100644 azure-quantum/tests/unit/common.py create mode 100644 azure-quantum/tests/unit/test_online_problem.py create mode 100644 azure-quantum/tests/unit/test_problem.py diff --git a/azure-quantum/azure/quantum/optimization/online_problem.py b/azure-quantum/azure/quantum/optimization/online_problem.py new file mode 100644 index 000000000..32e1d0903 --- /dev/null +++ b/azure-quantum/azure/quantum/optimization/online_problem.py @@ -0,0 +1,27 @@ +import logging +from typing import TYPE_CHECKING, Union, Dict +from azure.quantum.optimization import Problem + +logger = logging.getLogger(__name__) + +__all__ = ['OnlineProblem'] + +if TYPE_CHECKING: + from azure.quantum.workspace import Workspace + +class OnlineProblem(Problem): + def __init__(self, name:str, blob_uri:str): + #super().__init__(self, self.name = name) + self.name = name + self.uploaded_blob_uri = blob_uri + + def evaluate(self, configuration: Union[Dict[int, int], Dict[str, int]]) -> float: + """ + An OnlineProblem cannot be evaluated on client side. Calling this function will raise a user exception + """ + raise Exception('An Online Problem cannot be evaluated. Please download the problem to do this operation') + + def download(self)-> Problem: + logger.warning('The problem will be downloaded to the client') + return super().download() + diff --git a/azure-quantum/tests/unit/common.py b/azure-quantum/tests/unit/common.py new file mode 100644 index 000000000..3ec67f343 --- /dev/null +++ b/azure-quantum/tests/unit/common.py @@ -0,0 +1,211 @@ +#!/bin/env python +# -*- coding: utf-8 -*- +## +# recording_updater.py: Updates test recordings with dummy values +## +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. +## + +## IMPORTS ## + +import os +import re +import unittest.mock +from azure.quantum import Workspace +from azure.common.credentials import ServicePrincipalCredentials +from msrest.authentication import BasicTokenAuthentication +from azure_devtools.scenario_tests.base import ReplayableTest +from azure_devtools.scenario_tests.recording_processors import RecordingProcessor, is_text_payload, AccessTokenReplacer +from azure_devtools.scenario_tests.utilities import _get_content_type +import json +class QuantumTestBase(ReplayableTest): + """QuantumTestBase + + During init, gets Azure Credentials and Azure Quantum Workspace parameters from OS environment variables. + """ + + dummy_uid = "00000000-0000-0000-0000-000000000000" + dummy_rg = "dummy-rg" + dummy_ws = "dummy-ws" + dummy_clientsecret = "sanitized" + dummy_auth_token = {'access_token': 'eyJ1eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJidWQiOiJodHRwczovL3F1YW50dW0ubWljcm9zb2Z0LmNvbSIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTE2ODMwNjAsIm5iZiI6MTYxMTY4MzA2MCwiZXhwIjoxNjExNjg2OTYwLCJfY2xhaW1fbmFtZXMiOnsiZ3JvdXBzIjoic3JjMSJ9LCJfY2xhaW1fc291cmNlcyI6eyJzcmMxIjp7ImVuZHBvaW50IjoiaHR0cHM6Ly9ncmFwaC53aW5kb3dzLm5ldC83MmY5ODhiZi04NmYxLTQxYWYtOTFhYi0yZDdjZDAxMWRiNDcvdXNlcnMvZTlhNGE5ZTEtODcxNS00Yjc1LTk2NWQtYzBkZDQxMTIzODY4L2dldE1lbWJlck9iamVjdHMifX0sImFjciI6IjEiLCJhaW8iOiJBVlFBcS84U0FBQUFXMnNsMlRORXd5eXA2OGdvejM2RnRoSXFZSlJDdmRibDF0WVJPanUrUzNCZDV5MGsyeWMyOFdKUk9IQ283a0VuNGRpaDh1dkpLQm00TFNoTHRUQ3FsMHMwNkp6N3NYclNpNTFJOEljZThZcz0iLCJhbXIiOlsid2lhIiwibWZhIl0sImFwcGlkIjoiODRiYTA5NDctNmM1My00ZGQyLTljYTktYjM2OTQ3NjE1MjFiIiwiYXBwaWRhY3IiOiIwIiwiZmFtaWx5X25hbWUiOiJCcm93biIsImdpdmVuX25hbWUiOiJUb20iLCJpbl9jb3JwIjoidHJ1ZSIsImlwYWRkciI6IjczLjgzLjM5LjEwIiwibmFtZSI6IlRvbSBCcm93biIsIm9pZCI6ImU5YTRhOWUxLTg3MTUtNGI3NS05NjVkLWMwZGQ0MTEyMzg2OCIsIm9ucHJlbV9zaWQiOiJTLTEtNS0yMS0yMTI3NTIxMTg0LTE2MDQwMTI5MjAtMTg4NzkyNzUyNy0xNzc1MDU1MSIsInB1aWQiOiIxMDAzN0ZGRTkyREI4MzEyIiwicmgiOiIwLkFSb0F2NGo1Y3ZHR3IwR1JxeTE4MEJIYlIwY0p1b1JUYk5KTm5LbXphVWRoVWhzYUFPOC4iLCJzY3AiOiJKb2JzLlJlYWRXcml0ZSIsInN1YiI6IjNxVk1XZ3cxRWozYVRlTEdTenE0bmVsMms1UHFVS1BBY2ZVNDBSUl9JZ3MiLCJ0aWQiOiI3MmY5ODhiZi04NmYxLTQxYWYtOTFhYi0yZDdjZDAxMWRiNDciLCJ1bmlxdWVfbmFtZSI6InRoYnJvQG1pY3Jvc29mdC5jb20iLCJ1cG4iOiJ0aGJyb0BtaWNyb3NvZnQuY29tIiwidXRpIjoiUzMxNVVqbk9JVWUzeDdRR3ZaVWFBQSIsInZlciI6IjEuMCIsIndpZHMiOlsiYjc5ZmJmNGQtM2VmOS00Njg5LTgxNDMtNzZiMTk0ZTg1NTA5Il19.PCWEtCdso3_jehm3Ppg9lCSy_VgwY96IG0_Lqji5tN3yEmBmsP4Du-6MA2IHlz7pbKfQ8Qdw4aeobWZkuDW71Zo9PCkBSLQewng5EMbDvZO3jPJfCOd0IepaPVdtvtaCL2KnPEZicEM4kIO_9f8hCC4Ik8MAem788HuutNhN_YExJDWtM-aNoXIBLtDm39u3bCr2WFk4he3xpISLD3ZqAk2UPKagMwuwO-tArtcoQvA1_n_owv-I5P8vEk1wOmUh6LTB6pUAIS4wFIMgINUE1dBSuQmyimEfc7rRuWl-YJrMH0WRdbgFutwbBv_5dKs6VcYGgrvA3nIGU_Xz5vuJMA', 'token_type': 'Bearer', 'expires_in': 485} + + def __init__(self, method_name): + self._client_id = os.environ.get("AZURE_CLIENT_ID", self.dummy_uid) + self._client_secret = os.environ.get("AZURE_CLIENT_SECRET", self.dummy_clientsecret) + self._tenant_id = os.environ.get("AZURE_TENANT_ID", self.dummy_uid) + self._resource_group = os.environ.get("RESOURCE_GROUP", self.dummy_rg) + self._subscription_id = os.environ.get("SUBSCRIPTION_ID", self.dummy_uid) + self._workspace_name = os.environ.get("WORKSPACE_NAME", self.dummy_ws) + + regex_replacer = CustomRecordingProcessor() + recording_processors = [] + recording_processors.append(regex_replacer) + recording_processors.append(AccessTokenReplacer()) + replay_processors = [] + + super(QuantumTestBase, self).__init__(method_name, recording_processors=recording_processors, replay_processors=replay_processors) + + if not (self.in_recording or self.is_live): + self._client_id = self.dummy_uid + self._client_secret = self.dummy_clientsecret + self._tenant_id = self.dummy_uid + self._resource_group = self.dummy_rg + self._subscription_id = self.dummy_uid + self._workspace_name = self.dummy_ws + + regex_replacer.register_regex(self.client_id, self.dummy_uid) + regex_replacer.register_regex(self.client_secret, self.dummy_clientsecret) + regex_replacer.register_regex(self.tenant_id, self.dummy_uid) + regex_replacer.register_regex(self.subscription_id, self.dummy_uid) + regex_replacer.register_regex(self.workspace_name, self.dummy_ws) + regex_replacer.register_regex(self.resource_group, self.dummy_rg) + regex_replacer.register_regex(r'/subscriptions/([a-f0-9]+[-]){4}[a-f0-9]+', "/subscriptions/" + self.dummy_uid) + regex_replacer.register_regex(r'job-([a-f0-9]+[-]){4}[a-f0-9]+', "job-" + self.dummy_uid) + regex_replacer.register_regex(r'jobs/([a-f0-9]+[-]){4}[a-f0-9]+', "jobs/" + self.dummy_uid) + regex_replacer.register_regex(r'"id":\s*"([a-f0-9]+[-]){4}[a-f0-9]+"', '"id": "{}"'. format(self.dummy_uid)) + regex_replacer.register_regex(r'/resourceGroups/[a-z0-9-]+/', "/resourceGroups/dummy-rg/") + regex_replacer.register_regex(r'/workspaces/[a-z0-9-]+/', "/workspaces/dummy-ws/") + regex_replacer.register_regex(r'sig=[0-9a-zA-Z%]+\&', "sig=sanitized&") + regex_replacer.register_regex(r'sv=[^&]+\&', "sv=sanitized&") + regex_replacer.register_regex(r'se=[^&]+\&', "se=sanitized&") + + def setUp(self): + super(QuantumTestBase, self).setUp() + # mitigation for issue https://github.com/kevin1024/vcrpy/issues/533 + self.cassette.allow_playback_repeats = True + + @property + def client_id(self): + return self._client_id + + @property + def client_secret(self): + return self._client_secret + + @property + def tenant_id(self): + return self._tenant_id + + @property + def resource_group(self): + return self._resource_group + + @property + def subscription_id(self): + return self._subscription_id + + @property + def workspace_name(self): + return self._workspace_name + + def create_workspace(self) -> Workspace: + """Create workspace using credentials stored in config file + + :return: Workspace + :rtype: Workspace + """ + + workspace = Workspace( + + subscription_id=self.subscription_id, + resource_group=self.resource_group, + name=self.workspace_name, + ) + + if self.is_live or self.in_recording: + workspace.credentials = ServicePrincipalCredentials( + tenant=self.tenant_id, + client_id=self.client_id, + secret=self.client_secret, + resource = "https://quantum.microsoft.com" + ) + workspace.login(False) + else: + workspace.credentials = BasicTokenAuthentication(token=self.dummy_auth_token) + + return workspace + +class CustomRecordingProcessor(RecordingProcessor): + + ALLOW_HEADERS = [ + 'content-length', + 'content-type', + 'accept', + 'accept-encoding', + 'accept-charset', + 'accept-ranges', + 'x-ms-range', + 'transfer-encoding', + 'x-ms-blob-content-md5', + 'x-ms-blob-type', + 'x-ms-creation-time', + 'x-ms-lease-state', + 'x-ms-lease-status', + 'x-ms-server-encrypted', + 'x-ms-version' + ] + + def __init__(self): + self._regexes = [] + + def register_regex(self, oldRegex, new): + self._regexes.append((re.compile(oldRegex), new)) + + def process_request(self, request): + headers = {} + for key in request.headers: + if key.lower() in self.ALLOW_HEADERS: + headers[key] = request.headers[key] + #request.headers = headers + + for oldRegex, new in self._regexes: + request.uri = oldRegex.sub(new, request.uri) + + if _get_content_type(request) == "application/x-www-form-urlencoded": + body = request.body.decode("utf-8") + for oldRegex, new in self._regexes: + body = oldRegex.sub(new, body) + request.body = body.encode("utf-8") + else: + body = str(request.body) + for oldRegex, new in self._regexes: + body = oldRegex.sub(new, body) + request.body = body + + return request + + def process_response(self, response): + import six + + headers = {} + for key in response['headers']: + if key.lower() in self.ALLOW_HEADERS: + headers[key.lower()] = response['headers'][key] + #response['headers'] = headers + + if is_text_payload(response): + body = response['body']['string'] + if not isinstance(body, six.string_types): + body = body.decode("utf-8") + if is_text_payload(response) and body: + for oldRegex, new in self._regexes: + body = oldRegex.sub(new, body) + response['body']['string'] = body + + return response + +#helper functions + +# helpers +def expected_terms(): + expected = json.dumps({ + "cost_function": { + "version": "1.1", + "type": "ising", + "terms": [ { 'c':3, 'ids':[1,0] }, {'c':5, 'ids':[2,0]} ], + "initial_configuration": {"0":-1 , "1": 1, "2": -1}, + } + }) + return expected \ No newline at end of file diff --git a/azure-quantum/tests/unit/test_online_problem.py b/azure-quantum/tests/unit/test_online_problem.py new file mode 100644 index 000000000..bec97caa8 --- /dev/null +++ b/azure-quantum/tests/unit/test_online_problem.py @@ -0,0 +1,29 @@ +import unittest +from unittest.mock import Mock, patch +from azure.quantum.optimization import Problem, Term, OnlineProblem +import azure.quantum.optimization.problem +from common import expected_terms +import json + + +class TestOnlineProblemClass(unittest.TestCase): + + def setUp(self): + self.o_problem = OnlineProblem(name = "test", blob_uri = "mock_blob_uri") + + def test_download(self): + azure.quantum.optimization.problem.download_blob = Mock(return_value = expected_terms()) + acutal_result = self.o_problem.download() + #to-do add test that user warning was registered in log + assert acutal_result.name == 'test' + azure.quantum.optimization.problem.download_blob.assert_called_once() + + def test_evaluate(self): + config_dict = { + 1:1, + 0:1 + } + with self.assertRaises(Exception): + self.o_problem.evaluate(config_dict) + + diff --git a/azure-quantum/tests/unit/test_optimization.py b/azure-quantum/tests/unit/test_optimization.py index 462b56d9a..cfcbf70e6 100644 --- a/azure-quantum/tests/unit/test_optimization.py +++ b/azure-quantum/tests/unit/test_optimization.py @@ -11,7 +11,7 @@ ## IMPORTS ## import json - +import unittest from azure.quantum import Workspace from azure.quantum.optimization import Problem, ProblemType, Term from azure.quantum.optimization.solvers import ParallelTempering, PopulationAnnealing, RangeSchedule, SimulatedAnnealing, HardwarePlatform, QuantumMonteCarlo, SubstochasticMonteCarlo diff --git a/azure-quantum/tests/unit/test_problem.py b/azure-quantum/tests/unit/test_problem.py new file mode 100644 index 000000000..011882789 --- /dev/null +++ b/azure-quantum/tests/unit/test_problem.py @@ -0,0 +1,26 @@ +import unittest +from unittest.mock import Mock, patch +from azure.quantum.optimization import Problem, Term +import azure.quantum.optimization.problem +from common import expected_terms +import json + + +class TestProblemClass(unittest.TestCase): + + def setUp(self): + self.problem = Problem(name = "test") + self.problem.terms = [ + Term(c = 3, indices=[1,0]), + Term(c = 5, indices=[2,0]) + ] + self.problem.uploaded_blob_uri = "mock_blob_uri" + + def test_download(self): + azure.quantum.optimization.problem.download_blob = Mock(return_value = expected_terms()) + acutal_result = self.problem.download() + assert acutal_result.name == 'test' + azure.quantum.optimization.problem.download_blob.assert_called_once() + + + From 35620ab2d9b3c11ee6457066e35d3f9035563e9c Mon Sep 17 00:00:00 2001 From: Sanjana Gupta <42555338+sanjgupt@users.noreply.github.com> Date: Mon, 3 May 2021 11:42:46 -0700 Subject: [PATCH 03/21] add another assertion for online problems --- azure-quantum/tests/unit/test_online_problem.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/azure-quantum/tests/unit/test_online_problem.py b/azure-quantum/tests/unit/test_online_problem.py index bec97caa8..00184383b 100644 --- a/azure-quantum/tests/unit/test_online_problem.py +++ b/azure-quantum/tests/unit/test_online_problem.py @@ -11,12 +11,14 @@ class TestOnlineProblemClass(unittest.TestCase): def setUp(self): self.o_problem = OnlineProblem(name = "test", blob_uri = "mock_blob_uri") + def test_download(self): azure.quantum.optimization.problem.download_blob = Mock(return_value = expected_terms()) acutal_result = self.o_problem.download() #to-do add test that user warning was registered in log assert acutal_result.name == 'test' azure.quantum.optimization.problem.download_blob.assert_called_once() + assert isinstance(acutal_result, Problem) def test_evaluate(self): config_dict = { From 926ad2a2b39357da4db5352fa159a0ba9c18d533 Mon Sep 17 00:00:00 2001 From: Sanjana Gupta <42555338+sanjgupt@users.noreply.github.com> Date: Mon, 3 May 2021 12:20:21 -0700 Subject: [PATCH 04/21] update solver to handle online problmes --- .../quantum/optimization/online_problem.py | 2 +- .../azure/quantum/optimization/solvers.py | 5 ++++- azure-quantum/tests/unit/common.py | 2 +- .../tests/unit/test_online_problem.py | 2 +- azure-quantum/tests/unit/test_problem.py | 2 +- azure-quantum/tests/unit/test_solvers.py | 21 +++++++++++++++++++ 6 files changed, 29 insertions(+), 5 deletions(-) create mode 100644 azure-quantum/tests/unit/test_solvers.py diff --git a/azure-quantum/azure/quantum/optimization/online_problem.py b/azure-quantum/azure/quantum/optimization/online_problem.py index 32e1d0903..9d0a5e4a9 100644 --- a/azure-quantum/azure/quantum/optimization/online_problem.py +++ b/azure-quantum/azure/quantum/optimization/online_problem.py @@ -11,7 +11,7 @@ class OnlineProblem(Problem): def __init__(self, name:str, blob_uri:str): - #super().__init__(self, self.name = name) + super().__init__(self) self.name = name self.uploaded_blob_uri = blob_uri diff --git a/azure-quantum/azure/quantum/optimization/solvers.py b/azure-quantum/azure/quantum/optimization/solvers.py index 800ec0529..f98ca65ba 100644 --- a/azure-quantum/azure/quantum/optimization/solvers.py +++ b/azure-quantum/azure/quantum/optimization/solvers.py @@ -101,7 +101,10 @@ def submit(self, problem: Union[str, Problem], compress: bool = True) -> Job: if isinstance(problem, str): name = "Optimization problem" - problem_uri = problem + problem_uri = problem + elif not problem.terms: + name = problem.name + problem_uri = problem.uploaded_blob_uri else: name = problem.name problem_uri = problem.upload(self.workspace, compress=compress, container_name=container_name, blob_name="inputData") diff --git a/azure-quantum/tests/unit/common.py b/azure-quantum/tests/unit/common.py index 3ec67f343..eeef69f4a 100644 --- a/azure-quantum/tests/unit/common.py +++ b/azure-quantum/tests/unit/common.py @@ -208,4 +208,4 @@ def expected_terms(): "initial_configuration": {"0":-1 , "1": 1, "2": -1}, } }) - return expected \ No newline at end of file + return expected diff --git a/azure-quantum/tests/unit/test_online_problem.py b/azure-quantum/tests/unit/test_online_problem.py index 00184383b..227edb305 100644 --- a/azure-quantum/tests/unit/test_online_problem.py +++ b/azure-quantum/tests/unit/test_online_problem.py @@ -1,5 +1,5 @@ import unittest -from unittest.mock import Mock, patch +from unittest.mock import Mock from azure.quantum.optimization import Problem, Term, OnlineProblem import azure.quantum.optimization.problem from common import expected_terms diff --git a/azure-quantum/tests/unit/test_problem.py b/azure-quantum/tests/unit/test_problem.py index 011882789..208d23d82 100644 --- a/azure-quantum/tests/unit/test_problem.py +++ b/azure-quantum/tests/unit/test_problem.py @@ -1,5 +1,5 @@ import unittest -from unittest.mock import Mock, patch +from unittest.mock import Mock from azure.quantum.optimization import Problem, Term import azure.quantum.optimization.problem from common import expected_terms diff --git a/azure-quantum/tests/unit/test_solvers.py b/azure-quantum/tests/unit/test_solvers.py new file mode 100644 index 000000000..f4f601015 --- /dev/null +++ b/azure-quantum/tests/unit/test_solvers.py @@ -0,0 +1,21 @@ +import unittest +from unittest.mock import Mock, patch +from azure.quantum import Workspace, storage +from azure.quantum.optimization import Solver, OnlineProblem +import azure.quantum.storage + +class TestSolvers(unittest.TestCase): + def setUp(self): + self.mock_ws = Mock(spec = Workspace) + self.mock_ws.storage = "mock_storage" + #self.mock_ws.submit_job = Mock(return_value = ) + self.testsolver = Solver(self.mock_ws, 'Microsoft', 'SimulatedAnnealing', 'json', 'json') + + def test_submit_online_problem(self): + #Arrange + o_problem = OnlineProblem(name = "test", blob_uri = "mock_blob_uri") + #Act + azure.quantum.storage.get_container_uri = Mock(return_value = "mock_container_uri") + _ = self.testsolver.submit(o_problem) + #Assert + self.testsolver.workspace.submit_job.assert_called_once() From f473660d635a38fe23ed4fd933efb74966c09e7d Mon Sep 17 00:00:00 2001 From: Sanjana Gupta <42555338+sanjgupt@users.noreply.github.com> Date: Mon, 3 May 2021 14:01:25 -0700 Subject: [PATCH 05/21] Raise error for setting fixed variables for online problem and test --- .../azure/quantum/optimization/online_problem.py | 6 ++++++ azure-quantum/tests/unit/test_online_problem.py | 8 ++++++++ 2 files changed, 14 insertions(+) diff --git a/azure-quantum/azure/quantum/optimization/online_problem.py b/azure-quantum/azure/quantum/optimization/online_problem.py index 9d0a5e4a9..96e6d4ccb 100644 --- a/azure-quantum/azure/quantum/optimization/online_problem.py +++ b/azure-quantum/azure/quantum/optimization/online_problem.py @@ -20,6 +20,12 @@ def evaluate(self, configuration: Union[Dict[int, int], Dict[str, int]]) -> floa An OnlineProblem cannot be evaluated on client side. Calling this function will raise a user exception """ raise Exception('An Online Problem cannot be evaluated. Please download the problem to do this operation') + + def set_fixed_variables(self, fixed_variables: Union[Dict[int, int], Dict[str, int]]) -> Problem: + """ + An OnlineProblem cannot be evaluated on client side. Calling this function will raise a user exception + """ + raise Exception('An Online Problem cannot set fixed terms. Please download the problem to do this operation') def download(self)-> Problem: logger.warning('The problem will be downloaded to the client') diff --git a/azure-quantum/tests/unit/test_online_problem.py b/azure-quantum/tests/unit/test_online_problem.py index 227edb305..c62d9c128 100644 --- a/azure-quantum/tests/unit/test_online_problem.py +++ b/azure-quantum/tests/unit/test_online_problem.py @@ -27,5 +27,13 @@ def test_evaluate(self): } with self.assertRaises(Exception): self.o_problem.evaluate(config_dict) + + def test_set_fixed_variables(self): + config_dict = { + 1:1, + 0:1 + } + with self.assertRaises(Exception): + self.o_problem.set_fixed_variables(config_dict) From a15062f3ddf09baa212c7b8867cb6319b09b9319 Mon Sep 17 00:00:00 2001 From: sanjgupt Date: Tue, 4 May 2021 11:41:21 -0700 Subject: [PATCH 06/21] codestyle errors --- .../azure/quantum/_client/__init__.py | 3 +- .../azure/quantum/_client/models/__init__.py | 33 +- .../quantum/_client/models/blob_details.py | 10 +- .../_client/models/blob_details_py3.py | 10 +- .../quantum/_client/models/error_data.py | 8 +- .../quantum/_client/models/error_data_py3.py | 8 +- .../quantum/_client/models/job_details.py | 79 ++--- .../_client/models/job_details_paged.py | 4 +- .../quantum/_client/models/job_details_py3.py | 74 +++-- .../quantum/_client/models/provider_status.py | 12 +- .../_client/models/provider_status_paged.py | 4 +- .../_client/models/provider_status_py3.py | 12 +- .../azure/quantum/_client/models/quota.py | 28 +- .../quantum/_client/models/quota_paged.py | 4 +- .../azure/quantum/_client/models/quota_py3.py | 27 +- .../quantum/_client/models/rest_error.py | 8 +- .../quantum/_client/models/rest_error_py3.py | 6 +- .../_client/models/sas_uri_response.py | 4 +- .../_client/models/sas_uri_response_py3.py | 4 +- .../quantum/_client/models/target_status.py | 16 +- .../_client/models/target_status_py3.py | 16 +- .../quantum/_client/operations/__init__.py | 8 +- .../_client/operations/jobs_operations.py | 183 ++++++++--- .../operations/providers_operations.py | 55 +++- .../_client/operations/quotas_operations.py | 55 +++- .../_client/operations/storage_operations.py | 46 ++- .../azure/quantum/_client/quantum_client.py | 60 +++- .../azure/quantum/_client/version.py | 1 - azure-quantum/azure/quantum/job.py | 31 +- .../quantum/optimization/online_problem.py | 40 ++- .../azure/quantum/optimization/problem.py | 47 +-- .../azure/quantum/optimization/solvers.py | 91 ++++-- .../quantum/optimization/streaming_problem.py | 64 ++-- .../azure/quantum/optimization/term.py | 23 +- azure-quantum/azure/quantum/storage.py | 91 +++--- azure-quantum/azure/quantum/workspace.py | 37 +-- azure-quantum/setup.py | 6 +- .../integration/integration_test_util.py | 30 +- .../tests/integration/test_integration.py | 14 +- .../integration/test_streaming_problem.py | 39 ++- azure-quantum/tests/unit/common.py | 68 ++-- azure-quantum/tests/unit/test_job.py | 32 +- .../tests/unit/test_online_problem.py | 30 +- azure-quantum/tests/unit/test_optimization.py | 297 ++++++++---------- azure-quantum/tests/unit/test_problem.py | 20 +- azure-quantum/tests/unit/test_solvers.py | 23 +- azure-quantum/tests/unit/test_workspace.py | 3 +- 47 files changed, 1022 insertions(+), 742 deletions(-) diff --git a/azure-quantum/azure/quantum/_client/__init__.py b/azure-quantum/azure/quantum/_client/__init__.py index 97d75e884..ee13655c5 100644 --- a/azure-quantum/azure/quantum/_client/__init__.py +++ b/azure-quantum/azure/quantum/_client/__init__.py @@ -12,7 +12,6 @@ from .quantum_client import QuantumClient from .version import VERSION -__all__ = ['QuantumClient'] +__all__ = ["QuantumClient"] __version__ = VERSION - diff --git a/azure-quantum/azure/quantum/_client/models/__init__.py b/azure-quantum/azure/quantum/_client/models/__init__.py index d82cd869b..2b845f0b5 100644 --- a/azure-quantum/azure/quantum/_client/models/__init__.py +++ b/azure-quantum/azure/quantum/_client/models/__init__.py @@ -39,20 +39,21 @@ ) __all__ = [ - 'ErrorData', - 'JobDetails', - 'BlobDetails', - 'SasUriResponse', - 'TargetStatus', - 'ProviderStatus', - 'Quota', - 'RestError', 'RestErrorException', - 'JobDetailsPaged', - 'ProviderStatusPaged', - 'QuotaPaged', - 'JobStatus', - 'ProviderAvailability', - 'TargetAvailability', - 'DimensionScope', - 'MeterPeriod', + "ErrorData", + "JobDetails", + "BlobDetails", + "SasUriResponse", + "TargetStatus", + "ProviderStatus", + "Quota", + "RestError", + "RestErrorException", + "JobDetailsPaged", + "ProviderStatusPaged", + "QuotaPaged", + "JobStatus", + "ProviderAvailability", + "TargetAvailability", + "DimensionScope", + "MeterPeriod", ] diff --git a/azure-quantum/azure/quantum/_client/models/blob_details.py b/azure-quantum/azure/quantum/_client/models/blob_details.py index 5eca3fc53..55bcc7b4c 100644 --- a/azure-quantum/azure/quantum/_client/models/blob_details.py +++ b/azure-quantum/azure/quantum/_client/models/blob_details.py @@ -24,15 +24,15 @@ class BlobDetails(Model): """ _validation = { - 'container_name': {'required': True}, + "container_name": {"required": True}, } _attribute_map = { - 'container_name': {'key': 'containerName', 'type': 'str'}, - 'blob_name': {'key': 'blobName', 'type': 'str'}, + "container_name": {"key": "containerName", "type": "str"}, + "blob_name": {"key": "blobName", "type": "str"}, } def __init__(self, **kwargs): super(BlobDetails, self).__init__(**kwargs) - self.container_name = kwargs.get('container_name', None) - self.blob_name = kwargs.get('blob_name', None) + self.container_name = kwargs.get("container_name", None) + self.blob_name = kwargs.get("blob_name", None) diff --git a/azure-quantum/azure/quantum/_client/models/blob_details_py3.py b/azure-quantum/azure/quantum/_client/models/blob_details_py3.py index d3cb67335..5080cba8e 100644 --- a/azure-quantum/azure/quantum/_client/models/blob_details_py3.py +++ b/azure-quantum/azure/quantum/_client/models/blob_details_py3.py @@ -24,15 +24,17 @@ class BlobDetails(Model): """ _validation = { - 'container_name': {'required': True}, + "container_name": {"required": True}, } _attribute_map = { - 'container_name': {'key': 'containerName', 'type': 'str'}, - 'blob_name': {'key': 'blobName', 'type': 'str'}, + "container_name": {"key": "containerName", "type": "str"}, + "blob_name": {"key": "blobName", "type": "str"}, } - def __init__(self, *, container_name: str, blob_name: str=None, **kwargs) -> None: + def __init__( + self, *, container_name: str, blob_name: str = None, **kwargs + ) -> None: super(BlobDetails, self).__init__(**kwargs) self.container_name = container_name self.blob_name = blob_name diff --git a/azure-quantum/azure/quantum/_client/models/error_data.py b/azure-quantum/azure/quantum/_client/models/error_data.py index 7d55dbac1..b96941afc 100644 --- a/azure-quantum/azure/quantum/_client/models/error_data.py +++ b/azure-quantum/azure/quantum/_client/models/error_data.py @@ -24,11 +24,11 @@ class ErrorData(Model): """ _attribute_map = { - 'code': {'key': 'code', 'type': 'str'}, - 'message': {'key': 'message', 'type': 'str'}, + "code": {"key": "code", "type": "str"}, + "message": {"key": "message", "type": "str"}, } def __init__(self, **kwargs): super(ErrorData, self).__init__(**kwargs) - self.code = kwargs.get('code', None) - self.message = kwargs.get('message', None) + self.code = kwargs.get("code", None) + self.message = kwargs.get("message", None) diff --git a/azure-quantum/azure/quantum/_client/models/error_data_py3.py b/azure-quantum/azure/quantum/_client/models/error_data_py3.py index b0d83bcbc..6ed699b71 100644 --- a/azure-quantum/azure/quantum/_client/models/error_data_py3.py +++ b/azure-quantum/azure/quantum/_client/models/error_data_py3.py @@ -24,11 +24,13 @@ class ErrorData(Model): """ _attribute_map = { - 'code': {'key': 'code', 'type': 'str'}, - 'message': {'key': 'message', 'type': 'str'}, + "code": {"key": "code", "type": "str"}, + "message": {"key": "message", "type": "str"}, } - def __init__(self, *, code: str=None, message: str=None, **kwargs) -> None: + def __init__( + self, *, code: str = None, message: str = None, **kwargs + ) -> None: super(ErrorData, self).__init__(**kwargs) self.code = code self.message = message diff --git a/azure-quantum/azure/quantum/_client/models/job_details.py b/azure-quantum/azure/quantum/_client/models/job_details.py index 78b3bd4d8..108f36019 100644 --- a/azure-quantum/azure/quantum/_client/models/job_details.py +++ b/azure-quantum/azure/quantum/_client/models/job_details.py @@ -67,51 +67,54 @@ class JobDetails(Model): """ _validation = { - 'container_uri': {'required': True}, - 'input_data_format': {'required': True}, - 'provider_id': {'required': True}, - 'target': {'required': True}, - 'status': {'readonly': True}, - 'creation_time': {'readonly': True}, - 'begin_execution_time': {'readonly': True}, - 'end_execution_time': {'readonly': True}, - 'cancellation_time': {'readonly': True}, - 'error_data': {'readonly': True}, + "container_uri": {"required": True}, + "input_data_format": {"required": True}, + "provider_id": {"required": True}, + "target": {"required": True}, + "status": {"readonly": True}, + "creation_time": {"readonly": True}, + "begin_execution_time": {"readonly": True}, + "end_execution_time": {"readonly": True}, + "cancellation_time": {"readonly": True}, + "error_data": {"readonly": True}, } _attribute_map = { - 'id': {'key': 'id', 'type': 'str'}, - 'name': {'key': 'name', 'type': 'str'}, - 'container_uri': {'key': 'containerUri', 'type': 'str'}, - 'input_data_uri': {'key': 'inputDataUri', 'type': 'str'}, - 'input_data_format': {'key': 'inputDataFormat', 'type': 'str'}, - 'input_params': {'key': 'inputParams', 'type': 'object'}, - 'provider_id': {'key': 'providerId', 'type': 'str'}, - 'target': {'key': 'target', 'type': 'str'}, - 'metadata': {'key': 'metadata', 'type': '{str}'}, - 'output_data_uri': {'key': 'outputDataUri', 'type': 'str'}, - 'output_data_format': {'key': 'outputDataFormat', 'type': 'str'}, - 'status': {'key': 'status', 'type': 'str'}, - 'creation_time': {'key': 'creationTime', 'type': 'iso-8601'}, - 'begin_execution_time': {'key': 'beginExecutionTime', 'type': 'iso-8601'}, - 'end_execution_time': {'key': 'endExecutionTime', 'type': 'iso-8601'}, - 'cancellation_time': {'key': 'cancellationTime', 'type': 'iso-8601'}, - 'error_data': {'key': 'errorData', 'type': 'ErrorData'}, + "id": {"key": "id", "type": "str"}, + "name": {"key": "name", "type": "str"}, + "container_uri": {"key": "containerUri", "type": "str"}, + "input_data_uri": {"key": "inputDataUri", "type": "str"}, + "input_data_format": {"key": "inputDataFormat", "type": "str"}, + "input_params": {"key": "inputParams", "type": "object"}, + "provider_id": {"key": "providerId", "type": "str"}, + "target": {"key": "target", "type": "str"}, + "metadata": {"key": "metadata", "type": "{str}"}, + "output_data_uri": {"key": "outputDataUri", "type": "str"}, + "output_data_format": {"key": "outputDataFormat", "type": "str"}, + "status": {"key": "status", "type": "str"}, + "creation_time": {"key": "creationTime", "type": "iso-8601"}, + "begin_execution_time": { + "key": "beginExecutionTime", + "type": "iso-8601", + }, + "end_execution_time": {"key": "endExecutionTime", "type": "iso-8601"}, + "cancellation_time": {"key": "cancellationTime", "type": "iso-8601"}, + "error_data": {"key": "errorData", "type": "ErrorData"}, } def __init__(self, **kwargs): super(JobDetails, self).__init__(**kwargs) - self.id = kwargs.get('id', None) - self.name = kwargs.get('name', None) - self.container_uri = kwargs.get('container_uri', None) - self.input_data_uri = kwargs.get('input_data_uri', None) - self.input_data_format = kwargs.get('input_data_format', None) - self.input_params = kwargs.get('input_params', None) - self.provider_id = kwargs.get('provider_id', None) - self.target = kwargs.get('target', None) - self.metadata = kwargs.get('metadata', None) - self.output_data_uri = kwargs.get('output_data_uri', None) - self.output_data_format = kwargs.get('output_data_format', None) + self.id = kwargs.get("id", None) + self.name = kwargs.get("name", None) + self.container_uri = kwargs.get("container_uri", None) + self.input_data_uri = kwargs.get("input_data_uri", None) + self.input_data_format = kwargs.get("input_data_format", None) + self.input_params = kwargs.get("input_params", None) + self.provider_id = kwargs.get("provider_id", None) + self.target = kwargs.get("target", None) + self.metadata = kwargs.get("metadata", None) + self.output_data_uri = kwargs.get("output_data_uri", None) + self.output_data_format = kwargs.get("output_data_format", None) self.status = None self.creation_time = None self.begin_execution_time = None diff --git a/azure-quantum/azure/quantum/_client/models/job_details_paged.py b/azure-quantum/azure/quantum/_client/models/job_details_paged.py index f8c5167c5..e9da5bb0b 100644 --- a/azure-quantum/azure/quantum/_client/models/job_details_paged.py +++ b/azure-quantum/azure/quantum/_client/models/job_details_paged.py @@ -18,8 +18,8 @@ class JobDetailsPaged(Paged): """ _attribute_map = { - 'next_link': {'key': 'nextLink', 'type': 'str'}, - 'current_page': {'key': 'value', 'type': '[JobDetails]'} + "next_link": {"key": "nextLink", "type": "str"}, + "current_page": {"key": "value", "type": "[JobDetails]"}, } def __init__(self, *args, **kwargs): diff --git a/azure-quantum/azure/quantum/_client/models/job_details_py3.py b/azure-quantum/azure/quantum/_client/models/job_details_py3.py index 749ef493f..7ee7c1274 100644 --- a/azure-quantum/azure/quantum/_client/models/job_details_py3.py +++ b/azure-quantum/azure/quantum/_client/models/job_details_py3.py @@ -67,39 +67,57 @@ class JobDetails(Model): """ _validation = { - 'container_uri': {'required': True}, - 'input_data_format': {'required': True}, - 'provider_id': {'required': True}, - 'target': {'required': True}, - 'status': {'readonly': True}, - 'creation_time': {'readonly': True}, - 'begin_execution_time': {'readonly': True}, - 'end_execution_time': {'readonly': True}, - 'cancellation_time': {'readonly': True}, - 'error_data': {'readonly': True}, + "container_uri": {"required": True}, + "input_data_format": {"required": True}, + "provider_id": {"required": True}, + "target": {"required": True}, + "status": {"readonly": True}, + "creation_time": {"readonly": True}, + "begin_execution_time": {"readonly": True}, + "end_execution_time": {"readonly": True}, + "cancellation_time": {"readonly": True}, + "error_data": {"readonly": True}, } _attribute_map = { - 'id': {'key': 'id', 'type': 'str'}, - 'name': {'key': 'name', 'type': 'str'}, - 'container_uri': {'key': 'containerUri', 'type': 'str'}, - 'input_data_uri': {'key': 'inputDataUri', 'type': 'str'}, - 'input_data_format': {'key': 'inputDataFormat', 'type': 'str'}, - 'input_params': {'key': 'inputParams', 'type': 'object'}, - 'provider_id': {'key': 'providerId', 'type': 'str'}, - 'target': {'key': 'target', 'type': 'str'}, - 'metadata': {'key': 'metadata', 'type': '{str}'}, - 'output_data_uri': {'key': 'outputDataUri', 'type': 'str'}, - 'output_data_format': {'key': 'outputDataFormat', 'type': 'str'}, - 'status': {'key': 'status', 'type': 'str'}, - 'creation_time': {'key': 'creationTime', 'type': 'iso-8601'}, - 'begin_execution_time': {'key': 'beginExecutionTime', 'type': 'iso-8601'}, - 'end_execution_time': {'key': 'endExecutionTime', 'type': 'iso-8601'}, - 'cancellation_time': {'key': 'cancellationTime', 'type': 'iso-8601'}, - 'error_data': {'key': 'errorData', 'type': 'ErrorData'}, + "id": {"key": "id", "type": "str"}, + "name": {"key": "name", "type": "str"}, + "container_uri": {"key": "containerUri", "type": "str"}, + "input_data_uri": {"key": "inputDataUri", "type": "str"}, + "input_data_format": {"key": "inputDataFormat", "type": "str"}, + "input_params": {"key": "inputParams", "type": "object"}, + "provider_id": {"key": "providerId", "type": "str"}, + "target": {"key": "target", "type": "str"}, + "metadata": {"key": "metadata", "type": "{str}"}, + "output_data_uri": {"key": "outputDataUri", "type": "str"}, + "output_data_format": {"key": "outputDataFormat", "type": "str"}, + "status": {"key": "status", "type": "str"}, + "creation_time": {"key": "creationTime", "type": "iso-8601"}, + "begin_execution_time": { + "key": "beginExecutionTime", + "type": "iso-8601", + }, + "end_execution_time": {"key": "endExecutionTime", "type": "iso-8601"}, + "cancellation_time": {"key": "cancellationTime", "type": "iso-8601"}, + "error_data": {"key": "errorData", "type": "ErrorData"}, } - def __init__(self, *, container_uri: str, input_data_format: str, provider_id: str, target: str, id: str=None, name: str=None, input_data_uri: str=None, input_params=None, metadata=None, output_data_uri: str=None, output_data_format: str=None, **kwargs) -> None: + def __init__( + self, + *, + container_uri: str, + input_data_format: str, + provider_id: str, + target: str, + id: str = None, + name: str = None, + input_data_uri: str = None, + input_params=None, + metadata=None, + output_data_uri: str = None, + output_data_format: str = None, + **kwargs + ) -> None: super(JobDetails, self).__init__(**kwargs) self.id = id self.name = name diff --git a/azure-quantum/azure/quantum/_client/models/provider_status.py b/azure-quantum/azure/quantum/_client/models/provider_status.py index 74a8a3989..e5123b0e4 100644 --- a/azure-quantum/azure/quantum/_client/models/provider_status.py +++ b/azure-quantum/azure/quantum/_client/models/provider_status.py @@ -29,15 +29,15 @@ class ProviderStatus(Model): """ _validation = { - 'id': {'readonly': True}, - 'current_availability': {'readonly': True}, - 'targets': {'readonly': True}, + "id": {"readonly": True}, + "current_availability": {"readonly": True}, + "targets": {"readonly": True}, } _attribute_map = { - 'id': {'key': 'id', 'type': 'str'}, - 'current_availability': {'key': 'currentAvailability', 'type': 'str'}, - 'targets': {'key': 'targets', 'type': '[TargetStatus]'}, + "id": {"key": "id", "type": "str"}, + "current_availability": {"key": "currentAvailability", "type": "str"}, + "targets": {"key": "targets", "type": "[TargetStatus]"}, } def __init__(self, **kwargs): diff --git a/azure-quantum/azure/quantum/_client/models/provider_status_paged.py b/azure-quantum/azure/quantum/_client/models/provider_status_paged.py index 630b1dcda..bd5a6f867 100644 --- a/azure-quantum/azure/quantum/_client/models/provider_status_paged.py +++ b/azure-quantum/azure/quantum/_client/models/provider_status_paged.py @@ -18,8 +18,8 @@ class ProviderStatusPaged(Paged): """ _attribute_map = { - 'next_link': {'key': 'nextLink', 'type': 'str'}, - 'current_page': {'key': 'value', 'type': '[ProviderStatus]'} + "next_link": {"key": "nextLink", "type": "str"}, + "current_page": {"key": "value", "type": "[ProviderStatus]"}, } def __init__(self, *args, **kwargs): diff --git a/azure-quantum/azure/quantum/_client/models/provider_status_py3.py b/azure-quantum/azure/quantum/_client/models/provider_status_py3.py index c87bbe00e..8e459ce42 100644 --- a/azure-quantum/azure/quantum/_client/models/provider_status_py3.py +++ b/azure-quantum/azure/quantum/_client/models/provider_status_py3.py @@ -29,15 +29,15 @@ class ProviderStatus(Model): """ _validation = { - 'id': {'readonly': True}, - 'current_availability': {'readonly': True}, - 'targets': {'readonly': True}, + "id": {"readonly": True}, + "current_availability": {"readonly": True}, + "targets": {"readonly": True}, } _attribute_map = { - 'id': {'key': 'id', 'type': 'str'}, - 'current_availability': {'key': 'currentAvailability', 'type': 'str'}, - 'targets': {'key': 'targets', 'type': '[TargetStatus]'}, + "id": {"key": "id", "type": "str"}, + "current_availability": {"key": "currentAvailability", "type": "str"}, + "targets": {"key": "targets", "type": "[TargetStatus]"}, } def __init__(self, **kwargs) -> None: diff --git a/azure-quantum/azure/quantum/_client/models/quota.py b/azure-quantum/azure/quantum/_client/models/quota.py index 66b6c0a4a..5116367e1 100644 --- a/azure-quantum/azure/quantum/_client/models/quota.py +++ b/azure-quantum/azure/quantum/_client/models/quota.py @@ -37,21 +37,21 @@ class Quota(Model): """ _attribute_map = { - 'dimension': {'key': 'dimension', 'type': 'str'}, - 'scope': {'key': 'scope', 'type': 'str'}, - 'provider_id': {'key': 'providerId', 'type': 'str'}, - 'utilization': {'key': 'utilization', 'type': 'float'}, - 'holds': {'key': 'holds', 'type': 'float'}, - 'limit': {'key': 'limit', 'type': 'float'}, - 'period': {'key': 'period', 'type': 'str'}, + "dimension": {"key": "dimension", "type": "str"}, + "scope": {"key": "scope", "type": "str"}, + "provider_id": {"key": "providerId", "type": "str"}, + "utilization": {"key": "utilization", "type": "float"}, + "holds": {"key": "holds", "type": "float"}, + "limit": {"key": "limit", "type": "float"}, + "period": {"key": "period", "type": "str"}, } def __init__(self, **kwargs): super(Quota, self).__init__(**kwargs) - self.dimension = kwargs.get('dimension', None) - self.scope = kwargs.get('scope', None) - self.provider_id = kwargs.get('provider_id', None) - self.utilization = kwargs.get('utilization', None) - self.holds = kwargs.get('holds', None) - self.limit = kwargs.get('limit', None) - self.period = kwargs.get('period', None) + self.dimension = kwargs.get("dimension", None) + self.scope = kwargs.get("scope", None) + self.provider_id = kwargs.get("provider_id", None) + self.utilization = kwargs.get("utilization", None) + self.holds = kwargs.get("holds", None) + self.limit = kwargs.get("limit", None) + self.period = kwargs.get("period", None) diff --git a/azure-quantum/azure/quantum/_client/models/quota_paged.py b/azure-quantum/azure/quantum/_client/models/quota_paged.py index b425263c8..9edb6c7bb 100644 --- a/azure-quantum/azure/quantum/_client/models/quota_paged.py +++ b/azure-quantum/azure/quantum/_client/models/quota_paged.py @@ -18,8 +18,8 @@ class QuotaPaged(Paged): """ _attribute_map = { - 'next_link': {'key': 'nextLink', 'type': 'str'}, - 'current_page': {'key': 'value', 'type': '[Quota]'} + "next_link": {"key": "nextLink", "type": "str"}, + "current_page": {"key": "value", "type": "[Quota]"}, } def __init__(self, *args, **kwargs): diff --git a/azure-quantum/azure/quantum/_client/models/quota_py3.py b/azure-quantum/azure/quantum/_client/models/quota_py3.py index 0e7c260bc..186010738 100644 --- a/azure-quantum/azure/quantum/_client/models/quota_py3.py +++ b/azure-quantum/azure/quantum/_client/models/quota_py3.py @@ -37,16 +37,27 @@ class Quota(Model): """ _attribute_map = { - 'dimension': {'key': 'dimension', 'type': 'str'}, - 'scope': {'key': 'scope', 'type': 'str'}, - 'provider_id': {'key': 'providerId', 'type': 'str'}, - 'utilization': {'key': 'utilization', 'type': 'float'}, - 'holds': {'key': 'holds', 'type': 'float'}, - 'limit': {'key': 'limit', 'type': 'float'}, - 'period': {'key': 'period', 'type': 'str'}, + "dimension": {"key": "dimension", "type": "str"}, + "scope": {"key": "scope", "type": "str"}, + "provider_id": {"key": "providerId", "type": "str"}, + "utilization": {"key": "utilization", "type": "float"}, + "holds": {"key": "holds", "type": "float"}, + "limit": {"key": "limit", "type": "float"}, + "period": {"key": "period", "type": "str"}, } - def __init__(self, *, dimension: str=None, scope=None, provider_id: str=None, utilization: float=None, holds: float=None, limit: float=None, period=None, **kwargs) -> None: + def __init__( + self, + *, + dimension: str = None, + scope=None, + provider_id: str = None, + utilization: float = None, + holds: float = None, + limit: float = None, + period=None, + **kwargs + ) -> None: super(Quota, self).__init__(**kwargs) self.dimension = dimension self.scope = scope diff --git a/azure-quantum/azure/quantum/_client/models/rest_error.py b/azure-quantum/azure/quantum/_client/models/rest_error.py index f50e5f7e5..82acb888a 100644 --- a/azure-quantum/azure/quantum/_client/models/rest_error.py +++ b/azure-quantum/azure/quantum/_client/models/rest_error.py @@ -21,12 +21,12 @@ class RestError(Model): """ _attribute_map = { - 'error': {'key': 'error', 'type': 'ErrorData'}, + "error": {"key": "error", "type": "ErrorData"}, } def __init__(self, **kwargs): super(RestError, self).__init__(**kwargs) - self.error = kwargs.get('error', None) + self.error = kwargs.get("error", None) class RestErrorException(HttpOperationError): @@ -38,4 +38,6 @@ class RestErrorException(HttpOperationError): def __init__(self, deserialize, response, *args): - super(RestErrorException, self).__init__(deserialize, response, 'RestError', *args) + super(RestErrorException, self).__init__( + deserialize, response, "RestError", *args + ) diff --git a/azure-quantum/azure/quantum/_client/models/rest_error_py3.py b/azure-quantum/azure/quantum/_client/models/rest_error_py3.py index f39b8fcf0..2286bfd22 100644 --- a/azure-quantum/azure/quantum/_client/models/rest_error_py3.py +++ b/azure-quantum/azure/quantum/_client/models/rest_error_py3.py @@ -21,7 +21,7 @@ class RestError(Model): """ _attribute_map = { - 'error': {'key': 'error', 'type': 'ErrorData'}, + "error": {"key": "error", "type": "ErrorData"}, } def __init__(self, *, error=None, **kwargs) -> None: @@ -38,4 +38,6 @@ class RestErrorException(HttpOperationError): def __init__(self, deserialize, response, *args): - super(RestErrorException, self).__init__(deserialize, response, 'RestError', *args) + super(RestErrorException, self).__init__( + deserialize, response, "RestError", *args + ) diff --git a/azure-quantum/azure/quantum/_client/models/sas_uri_response.py b/azure-quantum/azure/quantum/_client/models/sas_uri_response.py index de48f2c42..cc4fe3b3f 100644 --- a/azure-quantum/azure/quantum/_client/models/sas_uri_response.py +++ b/azure-quantum/azure/quantum/_client/models/sas_uri_response.py @@ -21,9 +21,9 @@ class SasUriResponse(Model): """ _attribute_map = { - 'sas_uri': {'key': 'sasUri', 'type': 'str'}, + "sas_uri": {"key": "sasUri", "type": "str"}, } def __init__(self, **kwargs): super(SasUriResponse, self).__init__(**kwargs) - self.sas_uri = kwargs.get('sas_uri', None) + self.sas_uri = kwargs.get("sas_uri", None) diff --git a/azure-quantum/azure/quantum/_client/models/sas_uri_response_py3.py b/azure-quantum/azure/quantum/_client/models/sas_uri_response_py3.py index 61e07b356..277adb6cf 100644 --- a/azure-quantum/azure/quantum/_client/models/sas_uri_response_py3.py +++ b/azure-quantum/azure/quantum/_client/models/sas_uri_response_py3.py @@ -21,9 +21,9 @@ class SasUriResponse(Model): """ _attribute_map = { - 'sas_uri': {'key': 'sasUri', 'type': 'str'}, + "sas_uri": {"key": "sasUri", "type": "str"}, } - def __init__(self, *, sas_uri: str=None, **kwargs) -> None: + def __init__(self, *, sas_uri: str = None, **kwargs) -> None: super(SasUriResponse, self).__init__(**kwargs) self.sas_uri = sas_uri diff --git a/azure-quantum/azure/quantum/_client/models/target_status.py b/azure-quantum/azure/quantum/_client/models/target_status.py index a97e8d6a3..8ef938a7b 100644 --- a/azure-quantum/azure/quantum/_client/models/target_status.py +++ b/azure-quantum/azure/quantum/_client/models/target_status.py @@ -31,17 +31,17 @@ class TargetStatus(Model): """ _validation = { - 'id': {'readonly': True}, - 'current_availability': {'readonly': True}, - 'average_queue_time': {'readonly': True}, - 'status_page': {'readonly': True}, + "id": {"readonly": True}, + "current_availability": {"readonly": True}, + "average_queue_time": {"readonly": True}, + "status_page": {"readonly": True}, } _attribute_map = { - 'id': {'key': 'id', 'type': 'str'}, - 'current_availability': {'key': 'currentAvailability', 'type': 'str'}, - 'average_queue_time': {'key': 'averageQueueTime', 'type': 'long'}, - 'status_page': {'key': 'statusPage', 'type': 'str'}, + "id": {"key": "id", "type": "str"}, + "current_availability": {"key": "currentAvailability", "type": "str"}, + "average_queue_time": {"key": "averageQueueTime", "type": "long"}, + "status_page": {"key": "statusPage", "type": "str"}, } def __init__(self, **kwargs): diff --git a/azure-quantum/azure/quantum/_client/models/target_status_py3.py b/azure-quantum/azure/quantum/_client/models/target_status_py3.py index 1313de7a8..bc2e9f6e4 100644 --- a/azure-quantum/azure/quantum/_client/models/target_status_py3.py +++ b/azure-quantum/azure/quantum/_client/models/target_status_py3.py @@ -31,17 +31,17 @@ class TargetStatus(Model): """ _validation = { - 'id': {'readonly': True}, - 'current_availability': {'readonly': True}, - 'average_queue_time': {'readonly': True}, - 'status_page': {'readonly': True}, + "id": {"readonly": True}, + "current_availability": {"readonly": True}, + "average_queue_time": {"readonly": True}, + "status_page": {"readonly": True}, } _attribute_map = { - 'id': {'key': 'id', 'type': 'str'}, - 'current_availability': {'key': 'currentAvailability', 'type': 'str'}, - 'average_queue_time': {'key': 'averageQueueTime', 'type': 'long'}, - 'status_page': {'key': 'statusPage', 'type': 'str'}, + "id": {"key": "id", "type": "str"}, + "current_availability": {"key": "currentAvailability", "type": "str"}, + "average_queue_time": {"key": "averageQueueTime", "type": "long"}, + "status_page": {"key": "statusPage", "type": "str"}, } def __init__(self, **kwargs) -> None: diff --git a/azure-quantum/azure/quantum/_client/operations/__init__.py b/azure-quantum/azure/quantum/_client/operations/__init__.py index 86281dc01..9049c2d49 100644 --- a/azure-quantum/azure/quantum/_client/operations/__init__.py +++ b/azure-quantum/azure/quantum/_client/operations/__init__.py @@ -15,8 +15,8 @@ from .quotas_operations import QuotasOperations __all__ = [ - 'JobsOperations', - 'ProvidersOperations', - 'StorageOperations', - 'QuotasOperations', + "JobsOperations", + "ProvidersOperations", + "StorageOperations", + "QuotasOperations", ] diff --git a/azure-quantum/azure/quantum/_client/operations/jobs_operations.py b/azure-quantum/azure/quantum/_client/operations/jobs_operations.py index a0d88ec04..fdd766f30 100644 --- a/azure-quantum/azure/quantum/_client/operations/jobs_operations.py +++ b/azure-quantum/azure/quantum/_client/operations/jobs_operations.py @@ -35,8 +35,7 @@ def __init__(self, client, config, serializer, deserializer): self.config = config - def list( - self, custom_headers=None, raw=False, **operation_config): + def list(self, custom_headers=None, raw=False, **operation_config): """List jobs. :param dict custom_headers: headers that will be added to the request @@ -49,15 +48,28 @@ def list( ~azure.quantum.models.JobDetailsPaged[~azure.quantum.models.JobDetails] :raises: :class:`CloudError` """ + def internal_paging(next_link=None, raw=False): if not next_link: # Construct URL - url = self.list.metadata['url'] + url = self.list.metadata["url"] path_format_arguments = { - 'subscriptionId': self._serialize.url("self.config.subscription_id", self.config.subscription_id, 'str'), - 'resourceGroupName': self._serialize.url("self.config.resource_group_name", self.config.resource_group_name, 'str'), - 'workspaceName': self._serialize.url("self.config.workspace_name", self.config.workspace_name, 'str') + "subscriptionId": self._serialize.url( + "self.config.subscription_id", + self.config.subscription_id, + "str", + ), + "resourceGroupName": self._serialize.url( + "self.config.resource_group_name", + self.config.resource_group_name, + "str", + ), + "workspaceName": self._serialize.url( + "self.config.workspace_name", + self.config.workspace_name, + "str", + ), } url = self._client.format_url(url, **path_format_arguments) @@ -70,38 +82,52 @@ def internal_paging(next_link=None, raw=False): # Construct headers header_parameters = {} - header_parameters['Accept'] = 'application/json' + header_parameters["Accept"] = "application/json" if self.config.generate_client_request_id: - header_parameters['x-ms-client-request-id'] = str(uuid.uuid1()) + header_parameters["x-ms-client-request-id"] = str(uuid.uuid1()) if custom_headers: header_parameters.update(custom_headers) if self.config.accept_language is not None: - header_parameters['accept-language'] = self._serialize.header("self.config.accept_language", self.config.accept_language, 'str') + header_parameters["accept-language"] = self._serialize.header( + "self.config.accept_language", + self.config.accept_language, + "str", + ) # Construct and send request - request = self._client.get(url, query_parameters, header_parameters) - response = self._client.send(request, stream=False, **operation_config) + request = self._client.get( + url, query_parameters, header_parameters + ) + response = self._client.send( + request, stream=False, **operation_config + ) if response.status_code not in [200]: exp = CloudError(response) - exp.request_id = response.headers.get('x-ms-request-id') + exp.request_id = response.headers.get("x-ms-request-id") raise exp return response # Deserialize response - deserialized = models.JobDetailsPaged(internal_paging, self._deserialize.dependencies) + deserialized = models.JobDetailsPaged( + internal_paging, self._deserialize.dependencies + ) if raw: header_dict = {} - client_raw_response = models.JobDetailsPaged(internal_paging, self._deserialize.dependencies, header_dict) + client_raw_response = models.JobDetailsPaged( + internal_paging, self._deserialize.dependencies, header_dict + ) return client_raw_response return deserialized - list.metadata = {'url': '/v1.0/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Quantum/workspaces/{workspaceName}/jobs'} - def get( - self, job_id, custom_headers=None, raw=False, **operation_config): + list.metadata = { + "url": "/v1.0/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Quantum/workspaces/{workspaceName}/jobs" + } + + def get(self, job_id, custom_headers=None, raw=False, **operation_config): """Get job by id. :param job_id: Id of the job. @@ -118,12 +144,22 @@ def get( :class:`RestErrorException` """ # Construct URL - url = self.get.metadata['url'] + url = self.get.metadata["url"] path_format_arguments = { - 'subscriptionId': self._serialize.url("self.config.subscription_id", self.config.subscription_id, 'str'), - 'resourceGroupName': self._serialize.url("self.config.resource_group_name", self.config.resource_group_name, 'str'), - 'workspaceName': self._serialize.url("self.config.workspace_name", self.config.workspace_name, 'str'), - 'jobId': self._serialize.url("job_id", job_id, 'str') + "subscriptionId": self._serialize.url( + "self.config.subscription_id", + self.config.subscription_id, + "str", + ), + "resourceGroupName": self._serialize.url( + "self.config.resource_group_name", + self.config.resource_group_name, + "str", + ), + "workspaceName": self._serialize.url( + "self.config.workspace_name", self.config.workspace_name, "str" + ), + "jobId": self._serialize.url("job_id", job_id, "str"), } url = self._client.format_url(url, **path_format_arguments) @@ -132,13 +168,17 @@ def get( # Construct headers header_parameters = {} - header_parameters['Accept'] = 'application/json' + header_parameters["Accept"] = "application/json" if self.config.generate_client_request_id: - header_parameters['x-ms-client-request-id'] = str(uuid.uuid1()) + header_parameters["x-ms-client-request-id"] = str(uuid.uuid1()) if custom_headers: header_parameters.update(custom_headers) if self.config.accept_language is not None: - header_parameters['accept-language'] = self._serialize.header("self.config.accept_language", self.config.accept_language, 'str') + header_parameters["accept-language"] = self._serialize.header( + "self.config.accept_language", + self.config.accept_language, + "str", + ) # Construct and send request request = self._client.get(url, query_parameters, header_parameters) @@ -150,17 +190,21 @@ def get( deserialized = None if response.status_code == 200: - deserialized = self._deserialize('JobDetails', response) + deserialized = self._deserialize("JobDetails", response) if raw: client_raw_response = ClientRawResponse(deserialized, response) return client_raw_response return deserialized - get.metadata = {'url': '/v1.0/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Quantum/workspaces/{workspaceName}/jobs/{jobId}'} + + get.metadata = { + "url": "/v1.0/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Quantum/workspaces/{workspaceName}/jobs/{jobId}" + } def create( - self, job_id, job, custom_headers=None, raw=False, **operation_config): + self, job_id, job, custom_headers=None, raw=False, **operation_config + ): """Create a job. :param job_id: Id of the job. @@ -179,12 +223,22 @@ def create( :class:`RestErrorException` """ # Construct URL - url = self.create.metadata['url'] + url = self.create.metadata["url"] path_format_arguments = { - 'subscriptionId': self._serialize.url("self.config.subscription_id", self.config.subscription_id, 'str'), - 'resourceGroupName': self._serialize.url("self.config.resource_group_name", self.config.resource_group_name, 'str'), - 'workspaceName': self._serialize.url("self.config.workspace_name", self.config.workspace_name, 'str'), - 'jobId': self._serialize.url("job_id", job_id, 'str') + "subscriptionId": self._serialize.url( + "self.config.subscription_id", + self.config.subscription_id, + "str", + ), + "resourceGroupName": self._serialize.url( + "self.config.resource_group_name", + self.config.resource_group_name, + "str", + ), + "workspaceName": self._serialize.url( + "self.config.workspace_name", self.config.workspace_name, "str" + ), + "jobId": self._serialize.url("job_id", job_id, "str"), } url = self._client.format_url(url, **path_format_arguments) @@ -193,20 +247,26 @@ def create( # Construct headers header_parameters = {} - header_parameters['Accept'] = 'application/json' - header_parameters['Content-Type'] = 'application/json; charset=utf-8' + header_parameters["Accept"] = "application/json" + header_parameters["Content-Type"] = "application/json; charset=utf-8" if self.config.generate_client_request_id: - header_parameters['x-ms-client-request-id'] = str(uuid.uuid1()) + header_parameters["x-ms-client-request-id"] = str(uuid.uuid1()) if custom_headers: header_parameters.update(custom_headers) if self.config.accept_language is not None: - header_parameters['accept-language'] = self._serialize.header("self.config.accept_language", self.config.accept_language, 'str') + header_parameters["accept-language"] = self._serialize.header( + "self.config.accept_language", + self.config.accept_language, + "str", + ) # Construct body - body_content = self._serialize.body(job, 'JobDetails') + body_content = self._serialize.body(job, "JobDetails") # Construct and send request - request = self._client.put(url, query_parameters, header_parameters, body_content) + request = self._client.put( + url, query_parameters, header_parameters, body_content + ) response = self._client.send(request, stream=False, **operation_config) if response.status_code not in [200, 201]: @@ -215,19 +275,23 @@ def create( deserialized = None if response.status_code == 200: - deserialized = self._deserialize('JobDetails', response) + deserialized = self._deserialize("JobDetails", response) if response.status_code == 201: - deserialized = self._deserialize('JobDetails', response) + deserialized = self._deserialize("JobDetails", response) if raw: client_raw_response = ClientRawResponse(deserialized, response) return client_raw_response return deserialized - create.metadata = {'url': '/v1.0/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Quantum/workspaces/{workspaceName}/jobs/{jobId}'} + + create.metadata = { + "url": "/v1.0/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Quantum/workspaces/{workspaceName}/jobs/{jobId}" + } def cancel( - self, job_id, custom_headers=None, raw=False, **operation_config): + self, job_id, custom_headers=None, raw=False, **operation_config + ): """Cancel a job. :param job_id: Id of the job. @@ -243,12 +307,22 @@ def cancel( :class:`RestErrorException` """ # Construct URL - url = self.cancel.metadata['url'] + url = self.cancel.metadata["url"] path_format_arguments = { - 'subscriptionId': self._serialize.url("self.config.subscription_id", self.config.subscription_id, 'str'), - 'resourceGroupName': self._serialize.url("self.config.resource_group_name", self.config.resource_group_name, 'str'), - 'workspaceName': self._serialize.url("self.config.workspace_name", self.config.workspace_name, 'str'), - 'jobId': self._serialize.url("job_id", job_id, 'str') + "subscriptionId": self._serialize.url( + "self.config.subscription_id", + self.config.subscription_id, + "str", + ), + "resourceGroupName": self._serialize.url( + "self.config.resource_group_name", + self.config.resource_group_name, + "str", + ), + "workspaceName": self._serialize.url( + "self.config.workspace_name", self.config.workspace_name, "str" + ), + "jobId": self._serialize.url("job_id", job_id, "str"), } url = self._client.format_url(url, **path_format_arguments) @@ -258,11 +332,15 @@ def cancel( # Construct headers header_parameters = {} if self.config.generate_client_request_id: - header_parameters['x-ms-client-request-id'] = str(uuid.uuid1()) + header_parameters["x-ms-client-request-id"] = str(uuid.uuid1()) if custom_headers: header_parameters.update(custom_headers) if self.config.accept_language is not None: - header_parameters['accept-language'] = self._serialize.header("self.config.accept_language", self.config.accept_language, 'str') + header_parameters["accept-language"] = self._serialize.header( + "self.config.accept_language", + self.config.accept_language, + "str", + ) # Construct and send request request = self._client.delete(url, query_parameters, header_parameters) @@ -274,4 +352,7 @@ def cancel( if raw: client_raw_response = ClientRawResponse(None, response) return client_raw_response - cancel.metadata = {'url': '/v1.0/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Quantum/workspaces/{workspaceName}/jobs/{jobId}'} + + cancel.metadata = { + "url": "/v1.0/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Quantum/workspaces/{workspaceName}/jobs/{jobId}" + } diff --git a/azure-quantum/azure/quantum/_client/operations/providers_operations.py b/azure-quantum/azure/quantum/_client/operations/providers_operations.py index 0835a2dd0..d234c43ef 100644 --- a/azure-quantum/azure/quantum/_client/operations/providers_operations.py +++ b/azure-quantum/azure/quantum/_client/operations/providers_operations.py @@ -34,8 +34,7 @@ def __init__(self, client, config, serializer, deserializer): self.config = config - def get_status( - self, custom_headers=None, raw=False, **operation_config): + def get_status(self, custom_headers=None, raw=False, **operation_config): """Get provider status. :param dict custom_headers: headers that will be added to the request @@ -49,15 +48,28 @@ def get_status( :raises: :class:`RestErrorException` """ + def internal_paging(next_link=None, raw=False): if not next_link: # Construct URL - url = self.get_status.metadata['url'] + url = self.get_status.metadata["url"] path_format_arguments = { - 'subscriptionId': self._serialize.url("self.config.subscription_id", self.config.subscription_id, 'str'), - 'resourceGroupName': self._serialize.url("self.config.resource_group_name", self.config.resource_group_name, 'str'), - 'workspaceName': self._serialize.url("self.config.workspace_name", self.config.workspace_name, 'str') + "subscriptionId": self._serialize.url( + "self.config.subscription_id", + self.config.subscription_id, + "str", + ), + "resourceGroupName": self._serialize.url( + "self.config.resource_group_name", + self.config.resource_group_name, + "str", + ), + "workspaceName": self._serialize.url( + "self.config.workspace_name", + self.config.workspace_name, + "str", + ), } url = self._client.format_url(url, **path_format_arguments) @@ -70,17 +82,25 @@ def internal_paging(next_link=None, raw=False): # Construct headers header_parameters = {} - header_parameters['Accept'] = 'application/json' + header_parameters["Accept"] = "application/json" if self.config.generate_client_request_id: - header_parameters['x-ms-client-request-id'] = str(uuid.uuid1()) + header_parameters["x-ms-client-request-id"] = str(uuid.uuid1()) if custom_headers: header_parameters.update(custom_headers) if self.config.accept_language is not None: - header_parameters['accept-language'] = self._serialize.header("self.config.accept_language", self.config.accept_language, 'str') + header_parameters["accept-language"] = self._serialize.header( + "self.config.accept_language", + self.config.accept_language, + "str", + ) # Construct and send request - request = self._client.get(url, query_parameters, header_parameters) - response = self._client.send(request, stream=False, **operation_config) + request = self._client.get( + url, query_parameters, header_parameters + ) + response = self._client.send( + request, stream=False, **operation_config + ) if response.status_code not in [200]: raise models.RestErrorException(self._deserialize, response) @@ -88,12 +108,19 @@ def internal_paging(next_link=None, raw=False): return response # Deserialize response - deserialized = models.ProviderStatusPaged(internal_paging, self._deserialize.dependencies) + deserialized = models.ProviderStatusPaged( + internal_paging, self._deserialize.dependencies + ) if raw: header_dict = {} - client_raw_response = models.ProviderStatusPaged(internal_paging, self._deserialize.dependencies, header_dict) + client_raw_response = models.ProviderStatusPaged( + internal_paging, self._deserialize.dependencies, header_dict + ) return client_raw_response return deserialized - get_status.metadata = {'url': '/v1.0/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Quantum/workspaces/{workspaceName}/providerStatus'} + + get_status.metadata = { + "url": "/v1.0/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Quantum/workspaces/{workspaceName}/providerStatus" + } diff --git a/azure-quantum/azure/quantum/_client/operations/quotas_operations.py b/azure-quantum/azure/quantum/_client/operations/quotas_operations.py index dfc59b10e..00e103b4a 100644 --- a/azure-quantum/azure/quantum/_client/operations/quotas_operations.py +++ b/azure-quantum/azure/quantum/_client/operations/quotas_operations.py @@ -34,8 +34,7 @@ def __init__(self, client, config, serializer, deserializer): self.config = config - def list( - self, custom_headers=None, raw=False, **operation_config): + def list(self, custom_headers=None, raw=False, **operation_config): """List quotas for the given workspace. :param dict custom_headers: headers that will be added to the request @@ -48,15 +47,28 @@ def list( :raises: :class:`RestErrorException` """ + def internal_paging(next_link=None, raw=False): if not next_link: # Construct URL - url = self.list.metadata['url'] + url = self.list.metadata["url"] path_format_arguments = { - 'subscriptionId': self._serialize.url("self.config.subscription_id", self.config.subscription_id, 'str'), - 'resourceGroupName': self._serialize.url("self.config.resource_group_name", self.config.resource_group_name, 'str'), - 'workspaceName': self._serialize.url("self.config.workspace_name", self.config.workspace_name, 'str') + "subscriptionId": self._serialize.url( + "self.config.subscription_id", + self.config.subscription_id, + "str", + ), + "resourceGroupName": self._serialize.url( + "self.config.resource_group_name", + self.config.resource_group_name, + "str", + ), + "workspaceName": self._serialize.url( + "self.config.workspace_name", + self.config.workspace_name, + "str", + ), } url = self._client.format_url(url, **path_format_arguments) @@ -69,17 +81,25 @@ def internal_paging(next_link=None, raw=False): # Construct headers header_parameters = {} - header_parameters['Accept'] = 'application/json' + header_parameters["Accept"] = "application/json" if self.config.generate_client_request_id: - header_parameters['x-ms-client-request-id'] = str(uuid.uuid1()) + header_parameters["x-ms-client-request-id"] = str(uuid.uuid1()) if custom_headers: header_parameters.update(custom_headers) if self.config.accept_language is not None: - header_parameters['accept-language'] = self._serialize.header("self.config.accept_language", self.config.accept_language, 'str') + header_parameters["accept-language"] = self._serialize.header( + "self.config.accept_language", + self.config.accept_language, + "str", + ) # Construct and send request - request = self._client.get(url, query_parameters, header_parameters) - response = self._client.send(request, stream=False, **operation_config) + request = self._client.get( + url, query_parameters, header_parameters + ) + response = self._client.send( + request, stream=False, **operation_config + ) if response.status_code not in [200]: raise models.RestErrorException(self._deserialize, response) @@ -87,12 +107,19 @@ def internal_paging(next_link=None, raw=False): return response # Deserialize response - deserialized = models.QuotaPaged(internal_paging, self._deserialize.dependencies) + deserialized = models.QuotaPaged( + internal_paging, self._deserialize.dependencies + ) if raw: header_dict = {} - client_raw_response = models.QuotaPaged(internal_paging, self._deserialize.dependencies, header_dict) + client_raw_response = models.QuotaPaged( + internal_paging, self._deserialize.dependencies, header_dict + ) return client_raw_response return deserialized - list.metadata = {'url': '/v1.0/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Quantum/workspaces/{workspaceName}/quotas'} + + list.metadata = { + "url": "/v1.0/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Quantum/workspaces/{workspaceName}/quotas" + } diff --git a/azure-quantum/azure/quantum/_client/operations/storage_operations.py b/azure-quantum/azure/quantum/_client/operations/storage_operations.py index eabe621c2..964eed1f3 100644 --- a/azure-quantum/azure/quantum/_client/operations/storage_operations.py +++ b/azure-quantum/azure/quantum/_client/operations/storage_operations.py @@ -35,7 +35,8 @@ def __init__(self, client, config, serializer, deserializer): self.config = config def sas_uri( - self, blob_details, custom_headers=None, raw=False, **operation_config): + self, blob_details, custom_headers=None, raw=False, **operation_config + ): """Gets a URL with SAS token for a container/blob in the storage account associated with the workspace. The SAS URL can be used to upload job input and/or download job output. @@ -55,11 +56,21 @@ def sas_uri( :class:`RestErrorException` """ # Construct URL - url = self.sas_uri.metadata['url'] + url = self.sas_uri.metadata["url"] path_format_arguments = { - 'subscriptionId': self._serialize.url("self.config.subscription_id", self.config.subscription_id, 'str'), - 'resourceGroupName': self._serialize.url("self.config.resource_group_name", self.config.resource_group_name, 'str'), - 'workspaceName': self._serialize.url("self.config.workspace_name", self.config.workspace_name, 'str') + "subscriptionId": self._serialize.url( + "self.config.subscription_id", + self.config.subscription_id, + "str", + ), + "resourceGroupName": self._serialize.url( + "self.config.resource_group_name", + self.config.resource_group_name, + "str", + ), + "workspaceName": self._serialize.url( + "self.config.workspace_name", self.config.workspace_name, "str" + ), } url = self._client.format_url(url, **path_format_arguments) @@ -68,20 +79,26 @@ def sas_uri( # Construct headers header_parameters = {} - header_parameters['Accept'] = 'application/json' - header_parameters['Content-Type'] = 'application/json; charset=utf-8' + header_parameters["Accept"] = "application/json" + header_parameters["Content-Type"] = "application/json; charset=utf-8" if self.config.generate_client_request_id: - header_parameters['x-ms-client-request-id'] = str(uuid.uuid1()) + header_parameters["x-ms-client-request-id"] = str(uuid.uuid1()) if custom_headers: header_parameters.update(custom_headers) if self.config.accept_language is not None: - header_parameters['accept-language'] = self._serialize.header("self.config.accept_language", self.config.accept_language, 'str') + header_parameters["accept-language"] = self._serialize.header( + "self.config.accept_language", + self.config.accept_language, + "str", + ) # Construct body - body_content = self._serialize.body(blob_details, 'BlobDetails') + body_content = self._serialize.body(blob_details, "BlobDetails") # Construct and send request - request = self._client.post(url, query_parameters, header_parameters, body_content) + request = self._client.post( + url, query_parameters, header_parameters, body_content + ) response = self._client.send(request, stream=False, **operation_config) if response.status_code not in [200]: @@ -90,11 +107,14 @@ def sas_uri( deserialized = None if response.status_code == 200: - deserialized = self._deserialize('SasUriResponse', response) + deserialized = self._deserialize("SasUriResponse", response) if raw: client_raw_response = ClientRawResponse(deserialized, response) return client_raw_response return deserialized - sas_uri.metadata = {'url': '/v1.0/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Quantum/workspaces/{workspaceName}/storage/sasUri'} + + sas_uri.metadata = { + "url": "/v1.0/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Quantum/workspaces/{workspaceName}/storage/sasUri" + } diff --git a/azure-quantum/azure/quantum/_client/quantum_client.py b/azure-quantum/azure/quantum/_client/quantum_client.py index 7cef055b3..05eec42d5 100644 --- a/azure-quantum/azure/quantum/_client/quantum_client.py +++ b/azure-quantum/azure/quantum/_client/quantum_client.py @@ -39,23 +39,31 @@ class QuantumClientConfiguration(AzureConfiguration): """ def __init__( - self, credentials, subscription_id, resource_group_name, workspace_name, base_url=None): + self, + credentials, + subscription_id, + resource_group_name, + workspace_name, + base_url=None, + ): if credentials is None: raise ValueError("Parameter 'credentials' must not be None.") if subscription_id is None: raise ValueError("Parameter 'subscription_id' must not be None.") if resource_group_name is None: - raise ValueError("Parameter 'resource_group_name' must not be None.") + raise ValueError( + "Parameter 'resource_group_name' must not be None." + ) if workspace_name is None: raise ValueError("Parameter 'workspace_name' must not be None.") if not base_url: - base_url = 'https://quantum.azure.com' + base_url = "https://quantum.azure.com" super(QuantumClientConfiguration, self).__init__(base_url) - self.add_user_agent('quantumclient/{}'.format(VERSION)) - self.add_user_agent('Azure-SDK-For-Python') + self.add_user_agent("quantumclient/{}".format(VERSION)) + self.add_user_agent("Azure-SDK-For-Python") self.credentials = credentials self.subscription_id = subscription_id @@ -92,21 +100,41 @@ class QuantumClient(SDKClient): """ def __init__( - self, credentials, subscription_id, resource_group_name, workspace_name, base_url=None): - - self.config = QuantumClientConfiguration(credentials, subscription_id, resource_group_name, workspace_name, base_url) - super(QuantumClient, self).__init__(self.config.credentials, self.config) - - client_models = {k: v for k, v in models.__dict__.items() if isinstance(v, type)} - self.api_version = '2019-11-04-preview' + self, + credentials, + subscription_id, + resource_group_name, + workspace_name, + base_url=None, + ): + + self.config = QuantumClientConfiguration( + credentials, + subscription_id, + resource_group_name, + workspace_name, + base_url, + ) + super(QuantumClient, self).__init__( + self.config.credentials, self.config + ) + + client_models = { + k: v for k, v in models.__dict__.items() if isinstance(v, type) + } + self.api_version = "2019-11-04-preview" self._serialize = Serializer(client_models) self._deserialize = Deserializer(client_models) self.jobs = JobsOperations( - self._client, self.config, self._serialize, self._deserialize) + self._client, self.config, self._serialize, self._deserialize + ) self.providers = ProvidersOperations( - self._client, self.config, self._serialize, self._deserialize) + self._client, self.config, self._serialize, self._deserialize + ) self.storage = StorageOperations( - self._client, self.config, self._serialize, self._deserialize) + self._client, self.config, self._serialize, self._deserialize + ) self.quotas = QuotasOperations( - self._client, self.config, self._serialize, self._deserialize) + self._client, self.config, self._serialize, self._deserialize + ) diff --git a/azure-quantum/azure/quantum/_client/version.py b/azure-quantum/azure/quantum/_client/version.py index f85b9c124..f40ff0f3b 100644 --- a/azure-quantum/azure/quantum/_client/version.py +++ b/azure-quantum/azure/quantum/_client/version.py @@ -10,4 +10,3 @@ # -------------------------------------------------------------------------- VERSION = "2019-11-04-preview" - diff --git a/azure-quantum/azure/quantum/job.py b/azure-quantum/azure/quantum/job.py index 45416304d..808bf9635 100644 --- a/azure-quantum/azure/quantum/job.py +++ b/azure-quantum/azure/quantum/job.py @@ -43,9 +43,11 @@ def refresh(self): self.details = self.workspace.get_job(self.id).details def has_completed(self): - return (self.details.status == "Succeeded" - or self.details.status == "Failed" - or self.details.status == "Cancelled") + return ( + self.details.status == "Succeeded" + or self.details.status == "Failed" + or self.details.status == "Cancelled" + ) def wait_until_completed(self, max_poll_wait_secs=30): """Keeps refreshing the Job's details @@ -54,14 +56,17 @@ def wait_until_completed(self, max_poll_wait_secs=30): poll_wait = 0.2 while not self.has_completed(): logger.debug( - f"Waiting for job {self.id}," + - f"it is in status '{self.details.status}'" + f"Waiting for job {self.id}," + + f"it is in status '{self.details.status}'" ) print(".", end="", flush=True) time.sleep(poll_wait) self.refresh() - poll_wait = (max_poll_wait_secs if poll_wait >= max_poll_wait_secs - else poll_wait * 1.5) + poll_wait = ( + max_poll_wait_secs + if poll_wait >= max_poll_wait_secs + else poll_wait * 1.5 + ) def get_results(self): if self.results is not None: @@ -72,9 +77,9 @@ def get_results(self): if not self.details.status == "Succeeded": raise RuntimeError( - f'{"Cannot retrieve results as job execution failed"}' + - f"(status: {self.details.status}." + - f"error: {self.details.error_data})" + f'{"Cannot retrieve results as job execution failed"}' + + f"(status: {self.details.status}." + + f"error: {self.details.error_data})" ) url = urlparse(self.details.output_data_uri) @@ -82,9 +87,11 @@ def get_results(self): # output_data_uri does not contains SAS token, # get sas url from service blob_client = BlobClient.from_blob_url( - self.details.output_data_uri) + self.details.output_data_uri + ) blob_uri = self.workspace._get_linked_storage_sas_uri( - blob_client.container_name, blob_client.blob_name) + blob_client.container_name, blob_client.blob_name + ) payload = download_blob(blob_uri) else: # output_data_uri contains SAS token, use it diff --git a/azure-quantum/azure/quantum/optimization/online_problem.py b/azure-quantum/azure/quantum/optimization/online_problem.py index 96e6d4ccb..2898ca88f 100644 --- a/azure-quantum/azure/quantum/optimization/online_problem.py +++ b/azure-quantum/azure/quantum/optimization/online_problem.py @@ -1,33 +1,45 @@ import logging -from typing import TYPE_CHECKING, Union, Dict +from typing import TYPE_CHECKING, Union, Dict from azure.quantum.optimization import Problem logger = logging.getLogger(__name__) -__all__ = ['OnlineProblem'] +__all__ = ["OnlineProblem"] if TYPE_CHECKING: from azure.quantum.workspace import Workspace + class OnlineProblem(Problem): - def __init__(self, name:str, blob_uri:str): + def __init__(self, name: str, blob_uri: str): super().__init__(self) self.name = name self.uploaded_blob_uri = blob_uri - - def evaluate(self, configuration: Union[Dict[int, int], Dict[str, int]]) -> float: + + def evaluate( + self, configuration: Union[Dict[int, int], Dict[str, int]] + ) -> float: """ - An OnlineProblem cannot be evaluated on client side. Calling this function will raise a user exception + An OnlineProblem cannot be evaluated on client side. + Calling this function will raise a user exception """ - raise Exception('An Online Problem cannot be evaluated. Please download the problem to do this operation') - - def set_fixed_variables(self, fixed_variables: Union[Dict[int, int], Dict[str, int]]) -> Problem: + raise Exception( + "An Online Problem cannot be evaluated. \ + Please download the problem to do this operation" + ) + + def set_fixed_variables( + self, fixed_variables: Union[Dict[int, int], Dict[str, int]] + ) -> Problem: """ - An OnlineProblem cannot be evaluated on client side. Calling this function will raise a user exception + An OnlineProblem cannot be evaluated on client side. + Calling this function will raise a user exception """ - raise Exception('An Online Problem cannot set fixed terms. Please download the problem to do this operation') + raise Exception( + "An Online Problem cannot set fixed terms. \ + Please download the problem to do this operation" + ) - def download(self)-> Problem: - logger.warning('The problem will be downloaded to the client') + def download(self) -> Problem: + logger.warning("The problem will be downloaded to the client") return super().download() - diff --git a/azure-quantum/azure/quantum/optimization/problem.py b/azure-quantum/azure/quantum/optimization/problem.py index 64eea93b5..14d2fa12e 100644 --- a/azure-quantum/azure/quantum/optimization/problem.py +++ b/azure-quantum/azure/quantum/optimization/problem.py @@ -43,6 +43,7 @@ class Problem: ProblemType.ising), defaults to ProblemType.ising :type problem_type: ProblemType, optional """ + def __init__( self, name: str, @@ -100,7 +101,8 @@ def deserialize(cls, problem_as_json: str, name: str): if "initial_configuration" in result["cost_function"]: problem.init_config = result["cost_function"][ - "initial_configuration"] + "initial_configuration" + ] return problem @@ -167,9 +169,11 @@ def upload( if not workspace.storage: # No storage account is passed, use the linked one container_uri = workspace._get_linked_storage_sas_uri( - container_name) + container_name + ) container_client = ContainerClient.from_container_url( - container_uri) + container_uri + ) self.uploaded_blob_uri = upload_blob( container_client, blob_name, @@ -181,7 +185,8 @@ def upload( else: # Use the specified storage account container_client = ContainerClient.from_connection_string( - workspace.storage, container_name) + workspace.storage, container_name + ) self.uploaded_blob_uri = upload_blob( container_client, blob_name, @@ -195,8 +200,8 @@ def upload( return self.uploaded_blob_uri def set_fixed_variables( - self, fixed_variables: Union[Dict[int, int], - Dict[str, int]]) -> Problem: + self, fixed_variables: Union[Dict[int, int], Dict[str, int]] + ) -> Problem: """Transforms the current problem with a set of fixed variables and returns the new modified problem. The original Problem instance is untouched. @@ -211,8 +216,7 @@ def set_fixed_variables( ) fixed_transformed = { - int(k): fixed_variables[k] - for k in fixed_variables + int(k): fixed_variables[k] for k in fixed_variables } # if ids are given in string form, convert them to int new_terms = [] @@ -233,7 +237,8 @@ def set_fixed_variables( if self.init_config: new_init_config = { k: self.init_config[k] - for k in self.init_config if int(k) not in fixed_transformed + for k in self.init_config + if int(k) not in fixed_transformed } return Problem( @@ -244,8 +249,8 @@ def set_fixed_variables( ) def evaluate( - self, configuration: Union[Dict[int, int], Dict[str, - int]]) -> float: + self, configuration: Union[Dict[int, int], Dict[str, int]] + ) -> float: """Given a configuration/variable assignment, return the cost function value of this problem. @@ -253,8 +258,7 @@ def evaluate( variable ids to their assigned value """ configuration_transformed = { - int(k): configuration[k] - for k in configuration + int(k): configuration[k] for k in configuration } # if ids are given in string form, convert them to int total_cost = 0 if self.terms: @@ -274,14 +278,17 @@ def is_large(self) -> bool: set_vars = set() for term in self.terms: set_vars.update(term.ids) - - return (len(set_vars) >= Problem.NUM_VARIABLES_LARGE and len(self.terms) >= Problem.NUM_TERMS_LARGE) + + return ( + len(set_vars) >= Problem.NUM_VARIABLES_LARGE + and len(self.terms) >= Problem.NUM_TERMS_LARGE + ) def download(self): - """Dowloads an uploaded problem as an instance of 'Problem' - """ - if not self.uploaded_blob_uri: - raise Exception("Problem must be uploaded before it can be downloaded") + """Dowloads an uploaded problem as an instance of 'Problem'""" + if not self.uploaded_blob_uri: + raise Exception( + "Problem must be uploaded before it can be downloaded" + ) contents = download_blob(self.uploaded_blob_uri) return Problem.deserialize(contents, self.name) - diff --git a/azure-quantum/azure/quantum/optimization/solvers.py b/azure-quantum/azure/quantum/optimization/solvers.py index e00c009ce..f10a7d94f 100644 --- a/azure-quantum/azure/quantum/optimization/solvers.py +++ b/azure-quantum/azure/quantum/optimization/solvers.py @@ -45,10 +45,12 @@ def __init__(self, schedule_type: str, initial: float, final: float): self.schedule_type = schedule_type self.initial = initial self.final = final - if not (self.schedule_type == "linear" - or self.schedule_type == "geometric"): + if not ( + self.schedule_type == "linear" or self.schedule_type == "geometric" + ): raise ValueError( - '"schedule_type" can only be "linear" or "geometric"!') + '"schedule_type" can only be "linear" or "geometric"!' + ) class Solver: @@ -76,9 +78,9 @@ def __init__( SWEEPS_WARNING = 10000 TIMEOUT_WARNING = 600 - def submit(self, - problem: Union[str, Problem], - compress: bool = True) -> Job: + def submit( + self, problem: Union[str, Problem], compress: bool = True + ) -> Job: """Submits a job to execution to the associated Azure Quantum Workspace. @@ -100,22 +102,26 @@ def submit(self, # No storage account is passed, in this # case, get linked account from the service container_uri = self.workspace._get_linked_storage_sas_uri( - container_name) + container_name + ) container_client = ContainerClient.from_container_url( - container_uri) + container_uri + ) create_container_using_client(container_client) container_uri = azure.quantum.storage.remove_sas_token( - container_uri) + container_uri + ) else: # Storage account is passed, use it to generate a container_uri container_uri = azure.quantum.storage.get_container_uri( - self.workspace.storage, container_name) + self.workspace.storage, container_name + ) logger.debug(f"Container URI: {container_uri}") if isinstance(problem, str): name = "Optimization problem" - problem_uri = problem + problem_uri = problem elif not problem.terms: name = problem.name problem_uri = problem.uploaded_blob_uri @@ -167,8 +173,9 @@ def optimize(self, problem: Union[str, Problem]): def set_one_param(self, name: str, value: Any): if value is not None: - params = (self.params["params"] - if self.nested_params else self.params) + params = ( + self.params["params"] if self.nested_params else self.params + ) params[name] = str(value) if self.force_str_params else value def check_submission_warnings(self, problem: Problem): @@ -184,7 +191,7 @@ def check_submission_warnings(self, problem: Problem): f"There is a large problem submitted and \ a large number of sweeps ({sweeps}) configured. \ This submission could result in a long runtime." - ) + ) # do a timeout check if param-free, to warn # new users who accidentally set high timeout values. @@ -209,7 +216,8 @@ def check_set_schedule(self, schedule: RangeSchedule, schedule_name: str): if not (schedule is None): if not isinstance(schedule, RangeSchedule): raise ValueError( - f'{schedule_name} can only be from class "RangeSchedule"!') + f'{schedule_name} can only be from class "RangeSchedule"!' + ) schedule_param = { "type": schedule.schedule_type, "initial": schedule.initial, @@ -231,8 +239,9 @@ def check_set_positive_int(self, var: int, var_name: str): raise ValueError(f"{var_name} must be positive!") self.set_one_param(var_name, var) - def check_set_float_limit(self, var: float, var_name: str, - var_limit: float): + def check_set_float_limit( + self, var: float, var_name: str, var_limit: float + ): """Check whether the var parameter is a float larger than var_limit. :param var: var paramter to be checked @@ -247,7 +256,8 @@ def check_set_float_limit(self, var: float, var_name: str, raise ValueError(f"{var_name} shall be float!") if var <= var_limit: raise ValueError( - f"{var_name} can not be smaller than {var_limit}!") + f"{var_name} can not be smaller than {var_limit}!" + ) self.set_one_param(var_name, var) @@ -292,8 +302,11 @@ def __init__( if platform == HardwarePlatform.FPGA: target = "microsoft.paralleltempering.fpga" else: - target = ("microsoft.paralleltempering-parameterfree.cpu" - if param_free else "microsoft.paralleltempering.cpu") + target = ( + "microsoft.paralleltempering-parameterfree.cpu" + if param_free + else "microsoft.paralleltempering.cpu" + ) super().__init__( workspace=workspace, @@ -316,8 +329,8 @@ def __init__( self.set_one_param("replicas", len(all_betas)) elif len(all_betas) != replicas: raise ValueError( - "Parameter 'replicas' must equal the" + - "length of the 'all_betas' parameters." + "Parameter 'replicas' must equal the" + + "length of the 'all_betas' parameters." ) @@ -357,15 +370,25 @@ def __init__( specifies hardware platform HardwarePlatform.CPU or HardwarePlatform.FPGA. """ - param_free = (beta_start is None and beta_stop is None - and sweeps is None and restarts is None) + param_free = ( + beta_start is None + and beta_stop is None + and sweeps is None + and restarts is None + ) if platform == HardwarePlatform.FPGA: - target = ("microsoft.simulatedannealing-parameterfree.fpga" - if param_free else "microsoft.simulatedannealing.fpga") + target = ( + "microsoft.simulatedannealing-parameterfree.fpga" + if param_free + else "microsoft.simulatedannealing.fpga" + ) else: - target = ("microsoft.simulatedannealing-parameterfree.cpu" - if param_free else "microsoft.simulatedannealing.cpu") + target = ( + "microsoft.simulatedannealing-parameterfree.cpu" + if param_free + else "microsoft.simulatedannealing.cpu" + ) super().__init__( workspace=workspace, @@ -414,11 +437,15 @@ def __init__( :param seed: specifies a random seed value. """ - param_free = (sweeps is None and tabu_tenure is None - and restarts is None) + param_free = ( + sweeps is None and tabu_tenure is None and restarts is None + ) - target = ("microsoft.tabu-parameterfree.cpu" - if param_free else "microsoft.tabu.cpu") + target = ( + "microsoft.tabu-parameterfree.cpu" + if param_free + else "microsoft.tabu.cpu" + ) super().__init__( workspace=workspace, diff --git a/azure-quantum/azure/quantum/optimization/streaming_problem.py b/azure-quantum/azure/quantum/optimization/streaming_problem.py index 8ad6c1b13..c054f95c4 100644 --- a/azure-quantum/azure/quantum/optimization/streaming_problem.py +++ b/azure-quantum/azure/quantum/optimization/streaming_problem.py @@ -47,6 +47,7 @@ class StreamingProblem(object): ProblemType.ising), defaults to ProblemType.ising :type problem_type: ProblemType, optional """ + def __init__( self, workspace: Workspace, @@ -99,17 +100,21 @@ def _get_upload_coords(self): blob_client = BlobClient.from_blob_url(self.upload_to_url) container_client = ContainerClient.from_container_url( self.workspace._get_linked_storage_sas_uri( - blob_client.container_name)) + blob_client.container_name + ) + ) blob_name = blob_client.blob_name elif not self.workspace.storage: # No storage account is passed, use the linked one container_uri = self.workspace._get_linked_storage_sas_uri(self.id) container_client = ContainerClient.from_container_url( - container_uri) + container_uri + ) else: # Use the specified storage account container_client = ContainerClient.from_connection_string( - self.workspace.storage, self.id) + self.workspace.storage, self.id + ) return {"blob_name": blob_name, "container_client": container_client} @@ -136,15 +141,17 @@ def add_terms(self, terms: List[Term]): self.uploader.start() elif self.uploader.is_done(): raise Exception( - "Cannot add terms after problem has been uploaded") + "Cannot add terms after problem has been uploaded" + ) term_couplings = [len(term.ids) for term in terms] max_coupling = max(term_couplings) min_coupling = min(term_couplings) self.__n_couplers += sum(term_couplings) self.stats["num_terms"] += len(terms) - self.stats["avg_coupling"] = (self.__n_couplers / - self.stats["num_terms"]) + self.stats["avg_coupling"] = ( + self.__n_couplers / self.stats["num_terms"] + ) if self.stats["max_coupling"] < max_coupling: self.stats["max_coupling"] = max_coupling if self.stats["min_coupling"] > min_coupling: @@ -155,7 +162,8 @@ def download(self): """Downloads the uploaded problem as an instance of `Problem`""" if not self.uploaded_uri: raise Exception( - "StreamingProblem may not be downloaded before it is uploaded") + "StreamingProblem may not be downloaded before it is uploaded" + ) coords = self._get_upload_coords() blob = coords["container_client"].get_blob_client(coords["blob_name"]) @@ -177,11 +185,7 @@ def upload( """ if not self.uploaded_uri: self.uploader.blob_properties = { - k: str(v) - for k, v in { - **self.stats, - **self.metadata - }.items() + k: str(v) for k, v in {**self.stats, **self.metadata}.items() } self.terms_queue.put(None) blob = self.uploader.join() @@ -206,6 +210,7 @@ class JsonStreamingProblemUploader: Once this many terms are ready to be uploaded, the chunk will be uploaded. :param blob_properties: Properties to set on the blob. """ + def __init__( self, problem: StreamingProblem, @@ -225,8 +230,11 @@ def __init__( self._get_content_type(compress), ) self.compressedStream = io.BytesIO() if compress else None - self.compressor = (gzip.GzipFile( - mode="wb", fileobj=self.compressedStream) if compress else None) + self.compressor = ( + gzip.GzipFile(mode="wb", fileobj=self.compressedStream) + if compress + else None + ) self.uploaded_terms = 0 self.blob_properties = blob_properties self.__thread = None @@ -245,7 +253,8 @@ def start(self): """Starts the problem uploader in another thread""" if self.__thread is not None: raise Exception( - "JsonStreamingProblemUploader thread already started") + "JsonStreamingProblemUploader thread already started" + ) self.__thread = threading.Thread(target=self._run_queue) self.__thread.start() @@ -273,7 +282,8 @@ def _run_queue(self): while continue_processing: try: new_terms = self.problem.terms_queue.get( - block=True, timeout=self.__queue_wait_timeout) + block=True, timeout=self.__queue_wait_timeout + ) if new_terms is None: continue_processing = False else: @@ -296,13 +306,18 @@ def _upload_start(self, terms): self._upload_chunk( f'{{"cost_function":{{"version":"{self._get_version()}",' + f'"type":"{self._scrub(self.problem.problem_type.name)}",' - + self._get_initial_config_string() + '"terms":[' + - self._get_terms_string(terms)) + + self._get_initial_config_string() + + '"terms":[' + + self._get_terms_string(terms) + ) def _get_initial_config_string(self): if self.problem.init_config: - return (f'{"initial_configuration":}' + - json.dumps(self.problem.init_config) + ",") + return ( + f'{"initial_configuration":}' + + json.dumps(self.problem.init_config) + + "," + ) return "" def _get_version(self): @@ -310,7 +325,8 @@ def _get_version(self): def _get_terms_string(self, terms): result = ("," if self.uploaded_terms > 0 else "") + ",".join( - [json.dumps(term.to_dict()) for term in terms]) + [json.dumps(term.to_dict()) for term in terms] + ) self.uploaded_terms += len(terms) return result @@ -338,8 +354,10 @@ def _maybe_compress_bits(self, chunk: bytes, is_final: bool): if is_final: self.compressor.flush() self.compressor.close() - elif (self.compressedStream.getbuffer().nbytes < - self.__upload_size_threshold): + elif ( + self.compressedStream.getbuffer().nbytes + < self.__upload_size_threshold + ): self.__read_pos = 0 return diff --git a/azure-quantum/azure/quantum/optimization/term.py b/azure-quantum/azure/quantum/optimization/term.py index d47c6ffa3..0049191a8 100644 --- a/azure-quantum/azure/quantum/optimization/term.py +++ b/azure-quantum/azure/quantum/optimization/term.py @@ -52,12 +52,15 @@ def _convert_if_numpy_type(param: WArray): # Handle scalar-like arrays, if specified. param = param[0] - if (hasattr(param, "dtype") - and param.dtype in numpy_integer_types + numpy_float_types): + if ( + hasattr(param, "dtype") + and param.dtype in numpy_integer_types + numpy_float_types + ): return param.item() else: return param + except ImportError: npt = None WArray = Union[int, float] @@ -108,19 +111,25 @@ def evaluate(self, configuration: Dict[int, int]) -> float: The dictionary of variable ids to their assigned value """ try: - multiplier = (np.prod([configuration[i] for i in self.ids]) - if len(self.ids) > 0 else 1.0) + multiplier = ( + np.prod([configuration[i] for i in self.ids]) + if len(self.ids) > 0 + else 1.0 + ) except KeyError: print( "Error - variable id found in term {0}, \ - but not found in the supplied configuration." - .format(self.ids)) + but not found in the supplied configuration.".format( + self.ids + ) + ) raise return multiplier * self.c def reduce_by_variable_state( - self, fixed_variables: Dict[int, int]) -> Optional[Term]: + self, fixed_variables: Dict[int, int] + ) -> Optional[Term]: """Given some fixed variable states, transform the existing term into new term. Returns None if the new term is effectively 0 diff --git a/azure-quantum/azure/quantum/storage.py b/azure-quantum/azure/quantum/storage.py index 2f3998ff4..215fa9e1f 100644 --- a/azure-quantum/azure/quantum/storage.py +++ b/azure-quantum/azure/quantum/storage.py @@ -21,16 +21,18 @@ logger = logging.getLogger(__name__) -def create_container(connection_string: str, - container_name: str) -> ContainerClient: +def create_container( + connection_string: str, container_name: str +) -> ContainerClient: """ Creates and initialize a container; returns the client needed to access it. """ blob_service_client = BlobServiceClient.from_connection_string( - connection_string) + connection_string + ) logger.info( - f'{"Initializing storage client for account:"}' + - f"{blob_service_client.account_name}" + f'{"Initializing storage client for account:"}' + + f"{blob_service_client.account_name}" ) container_client = blob_service_client.get_container_client(container_name) @@ -60,18 +62,17 @@ def get_container_uri(connection_string: str, container_name: str) -> str: """ container = create_container(connection_string, container_name) logger.info( - f'{"Creating SAS token for container"}' + - f"'{container_name}' on account: '{container.account_name}'" + f'{"Creating SAS token for container"}' + + f"'{container_name}' on account: '{container.account_name}'" ) sas_token = generate_container_sas( container.account_name, container.container_name, account_key=container.credential.account_key, - permission=BlobSasPermissions(read=True, - add=True, - write=True, - create=True), + permission=BlobSasPermissions( + read=True, add=True, write=True, create=True + ), expiry=datetime.utcnow() + timedelta(days=14), ) @@ -96,13 +97,14 @@ def upload_blob( """ create_container_using_client(container) logger.info( - f"Uploading blob '{blob_name}'" + - f"to container '{container.container_name}'" + - f"on account: '{container.account_name}'" + f"Uploading blob '{blob_name}'" + + f"to container '{container.container_name}'" + + f"on account: '{container.account_name}'" ) - content_settings = ContentSettings(content_type=content_type, - content_encoding=content_encoding) + content_settings = ContentSettings( + content_type=content_type, content_encoding=content_encoding + ) 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.") @@ -134,21 +136,23 @@ def append_blob( """ create_container_using_client(container) logger.info( - f"Appending data to blob '{blob_name}'" + - f"in container '{container.container_name}'" + - f"on account: '{container.account_name}'" + f"Appending data to blob '{blob_name}'" + + f"in container '{container.container_name}'" + + f"on account: '{container.account_name}'" ) - content_settings = ContentSettings(content_type=content_type, - content_encoding=content_encoding) + content_settings = ContentSettings( + content_type=content_type, content_encoding=content_encoding + ) blob = container.get_blob_client(blob_name) try: props = blob.get_blob_properties() if props.blob_type != BlobType.AppendBlob: raise Exception("blob must be an append blob") except exceptions.ResourceNotFoundError: - props = blob.create_append_blob(content_settings=content_settings, - metadata=metadata) + props = blob.create_append_blob( + content_settings=content_settings, metadata=metadata + ) blob.append_block(data, len(data)) logger.debug(f" - blob '{blob_name}' appended. generating sas token.") @@ -183,9 +187,9 @@ def download_blob(blob_url: str) -> Any: """ blob_client = BlobClient.from_blob_url(blob_url) logger.info( - f"Downloading blob '{blob_client.blob_name}'" + - f"from container '{blob_client.container_name}'" + - f"on account: '{blob_client.account_name}'" + f"Downloading blob '{blob_client.blob_name}'" + + f"from container '{blob_client.container_name}'" + + f"on account: '{blob_client.account_name}'" ) response = blob_client.download_blob().readall() @@ -198,9 +202,9 @@ def download_blob_properties(blob_url: str) -> Dict[str, str]: """Downloads the blob properties from Azure for the given blob URI""" blob_client = BlobClient.from_blob_url(blob_url) logger.info( - f"Downloading blob properties '{blob_client.blob_name}'" + - f"from container '{blob_client.container_name}'" + - f"on account: '{blob_client.account_name}'" + f"Downloading blob properties '{blob_client.blob_name}'" + + f"from container '{blob_client.container_name}'" + + f"on account: '{blob_client.account_name}'" ) response = blob_client.get_blob_properties() @@ -219,9 +223,9 @@ def set_blob_metadata(blob_url: str, metadata: Dict[str, str]): """Sets the provided dictionary as the metadata on the Azure blob""" blob_client = BlobClient.from_blob_url(blob_url) logger.info( - f"Setting blob properties '{blob_client.blob_name}'" + - f"from container '{blob_client.container_name}' on account:" + - f"'{blob_client.account_name}'" + f"Setting blob properties '{blob_client.blob_name}'" + + f"from container '{blob_client.container_name}' on account:" + + f"'{blob_client.account_name}'" ) return blob_client.set_blob_metadata(metadata=metadata) @@ -251,13 +255,14 @@ def init_blob_for_streaming_upload( """ create_container_using_client(container) logger.info( - f"Streaming blob '{blob_name}'" + - f"to container '{container.container_name}' on account:" + - f"'{container.account_name}'" + f"Streaming blob '{blob_name}'" + + f"to container '{container.container_name}' on account:" + + f"'{container.account_name}'" ) - content_settings = ContentSettings(content_type=content_type, - content_encoding=content_encoding) + content_settings = ContentSettings( + content_type=content_type, content_encoding=content_encoding + ) blob = container.get_blob_client(blob_name) blob.stage_block() blob.commit_block_list() @@ -307,6 +312,7 @@ class StreamedBlob: :param content_encoding: The HTTP content encoding to apply to the blob metadata """ + def __init__( self, container: ContainerClient, @@ -317,7 +323,8 @@ def __init__( self.container = container self.blob_name = blob_name self.content_settings = ContentSettings( - content_type=content_type, content_encoding=content_encoding) + content_type=content_type, content_encoding=content_encoding + ) self.state = StreamedBlobState.not_initialized self.blob = container.get_blob_client(blob_name) self.blocks = [] @@ -331,9 +338,9 @@ def upload_data(self, data): if self.state == StreamedBlobState.not_initialized: create_container_using_client(self.container) logger.info( - f"Streaming blob '{self.blob_name}' to container" + - f"'{self.container.container_name}'" + - f"on account: '{self.container.account_name}'" + f"Streaming blob '{self.blob_name}' to container" + + f"'{self.container.container_name}'" + + f"on account: '{self.container.account_name}'" ) self.initialized = True @@ -366,7 +373,7 @@ def commit(self, metadata: Dict[str, str] = None): def getUri(self, with_sas_token: bool = False): """Gets the full Azure Storage URI for the - uploaded blob after it has been committed""" + uploaded blob after it has been committed""" if self.state != StreamedBlobState.committed: raise Exception("Can only retrieve sas token for committed blob") if with_sas_token: diff --git a/azure-quantum/azure/quantum/workspace.py b/azure-quantum/azure/quantum/workspace.py index 14e1f929b..272698be1 100644 --- a/azure-quantum/azure/quantum/workspace.py +++ b/azure-quantum/azure/quantum/workspace.py @@ -118,8 +118,8 @@ def __init__(self, subscription_id: str, refresh: bool): def get_tenant_authorization_uri(self): try: uri = ( - f"{ARM_BASE_URL}/subscriptions/" + - f"{self.subscription_id}?api-version=2018-01-01" + f"{ARM_BASE_URL}/subscriptions/" + + f"{self.subscription_id}?api-version=2018-01-01" ) response = requests.get(uri) @@ -128,7 +128,8 @@ def get_tenant_authorization_uri(self): # We make a unauthenticated request to ARM and extract the tenant # authority from the WWW-Authenticate header in the response. # The header is of the form: - # Bearer authorization_uri=https://login.microsoftonline.com/tenantId, key1=value1s + # Bearer authorization_uri= + # https://login.microsoftonline.com/tenantId, key1=value1s auth_header = response.headers["WWW-Authenticate"] logger.debug( f'{"got the following auth header from"}' @@ -152,8 +153,8 @@ def get_tenant_authorization_uri(self): ] # strip it of surrounding quotes logger.debug( - f'{"got the following tenant uri from"}' + - f"the authentication header: {tenant_uri}" + f'{"got the following tenant uri from"}' + + f"the authentication header: {tenant_uri}" ) return tenant_uri @@ -170,8 +171,8 @@ def get_app(self): if authority is None: raise ValueError( f'{"Failed to get tenant authority for subscription"}' - f"{self.subscription_id}." + - f'{"Make sure the subscription id is correct."}' + f"{self.subscription_id}." + + f'{"Make sure the subscription id is correct."}' ) try: @@ -187,8 +188,8 @@ def get_app(self): ) except Exception as e: raise ValueError( - f'{"Failed to create PublicClientApplication"}' + - f"with tenant authority: {e}" + f'{"Failed to create PublicClientApplication"}' + + f"with tenant authority: {e}" ) return _msal_apps[self.subscription_id] @@ -250,9 +251,9 @@ def try_get_account_from_app(app): if _last_account != account["username"]: _last_account = account["username"] logger.info( - f'{"Account(s) exists in aad token cache."}' + - f'{"Getting token for"}' + - f"(userName: {account['username']}, tenantId: {tid})" + f'{"Account(s) exists in aad token cache."}' + + f'{"Getting token for"}' + + f"(userName: {account['username']}, tenantId: {tid})" ) return self.get_app().acquire_token_silent(self.scopes, account) @@ -374,10 +375,10 @@ def __init__( if not subscription_id or not resource_group or not name: raise ValueError( - "Azure Quantum workspace not fully specified." + - "Please specify either a valid resource ID " + - "or a valid combination of subscription ID," + - "resource group name, and workspace name." + "Azure Quantum workspace not fully specified." + + "Please specify either a valid resource ID " + + "or a valid combination of subscription ID," + + "resource group name, and workspace name." ) self.name = name @@ -399,8 +400,8 @@ def _create_client(self) -> QuantumClient: auth = self.login() base_url = BASE_URL(self.location) logger.debug( - f"Creating client for: subs:{self.subscription_id}," + - f"rg={self.resource_group}, ws={self.name}, frontdoor={base_url}" + f"Creating client for: subs:{self.subscription_id}," + + f"rg={self.resource_group}, ws={self.name}, frontdoor={base_url}" ) client = QuantumClient( auth, diff --git a/azure-quantum/setup.py b/azure-quantum/setup.py index 3f77441bf..821a94e30 100644 --- a/azure-quantum/setup.py +++ b/azure-quantum/setup.py @@ -24,7 +24,8 @@ version = os.environ.get("PYTHON_VERSION", "0.0.0.1") with open("./azure/quantum/version.py", "w") as f: - f.write(f"""# Auto-generated file, do not edit. + f.write( + f"""# Auto-generated file, do not edit. ## # version.py: Specifies the version of the azure.quantum package. ## @@ -32,7 +33,8 @@ # Licensed under the MIT License. ## __version__ = "{version}" -""") +""" + ) # DESCRIPTION # # The long description metadata passed to setuptools is used to populate the diff --git a/azure-quantum/tests/integration/integration_test_util.py b/azure-quantum/tests/integration/integration_test_util.py index 6df9d7d51..d3dade104 100644 --- a/azure-quantum/tests/integration/integration_test_util.py +++ b/azure-quantum/tests/integration/integration_test_util.py @@ -17,18 +17,24 @@ def create_workspace() -> Workspace: subscription_id = os.environ.get("SUBSCRIPTION_ID", "") workspace_name = os.environ.get("WORKSPACE_NAME", "") - assert (len(client_id) > - 0), "AZURE_CLIENT_ID not found in environment variables." - assert (len(client_secret) > - 0), "AZURE_CLIENT_SECRET not found in environment variables." - assert (len(tenant_id) > - 0), "AZURE_TENANT_ID not found in environment variables." - assert (len(resource_group) > - 0), "RESOURCE_GROUP not found in environment variables." - assert (len(subscription_id) > - 0), "SUBSCRIPTION_ID not found in environment variables." - assert (len(workspace_name) > - 0), "WORKSPACE_NAME not found in environment variables." + assert ( + len(client_id) > 0 + ), "AZURE_CLIENT_ID not found in environment variables." + assert ( + len(client_secret) > 0 + ), "AZURE_CLIENT_SECRET not found in environment variables." + assert ( + len(tenant_id) > 0 + ), "AZURE_TENANT_ID not found in environment variables." + assert ( + len(resource_group) > 0 + ), "RESOURCE_GROUP not found in environment variables." + assert ( + len(subscription_id) > 0 + ), "SUBSCRIPTION_ID not found in environment variables." + assert ( + len(workspace_name) > 0 + ), "WORKSPACE_NAME not found in environment variables." if len(client_secret) > 0: workspace = Workspace( diff --git a/azure-quantum/tests/integration/test_integration.py b/azure-quantum/tests/integration/test_integration.py index d162124a5..463acbbbb 100644 --- a/azure-quantum/tests/integration/test_integration.py +++ b/azure-quantum/tests/integration/test_integration.py @@ -2,7 +2,8 @@ # Licensed under the MIT License. ## -# Integration tests for connecting to the Azure Quantum service and solving Optimization problems. +# Integration tests for connecting to the +# Azure Quantum service and solving Optimization problems. ## import os @@ -57,13 +58,14 @@ def create_problem(init: bool = False) -> Problem: ) else: - return Problem(name="first-demo", - terms=terms, - problem_type=ProblemType.pubo) + return Problem( + name="first-demo", terms=terms, problem_type=ProblemType.pubo + ) -def solve(problem: Problem, solver_name: str, - solver_factory: callable) -> None: +def solve( + problem: Problem, solver_name: str, solver_factory: callable +) -> None: """Solve the problem with the given solver :param problem Problem to solve diff --git a/azure-quantum/tests/integration/test_streaming_problem.py b/azure-quantum/tests/integration/test_streaming_problem.py index 1d48ab38f..589eb0b4c 100644 --- a/azure-quantum/tests/integration/test_streaming_problem.py +++ b/azure-quantum/tests/integration/test_streaming_problem.py @@ -6,9 +6,6 @@ # Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. ## - -## IMPORTS ## - import unittest import json import os @@ -27,22 +24,23 @@ class TestStreamingProblem(unittest.TestCase): - def __test_upload_problem(self, - count: int, - terms_thresh: int, - size_thresh: int, - compress: bool, - problem_type: ProblemType = ProblemType.ising, - initial_terms: List[Term] = [], - **kwargs): + def __test_upload_problem( + self, + count: int, + terms_thresh: int, + size_thresh: int, + compress: bool, + problem_type: ProblemType = ProblemType.ising, + initial_terms: List[Term] = [], + **kwargs + ): ws = create_workspace() - sProblem = StreamingProblem(ws, - name="test", - problem_type=problem_type, - terms=initial_terms) - rProblem = Problem("test", - problem_type=problem_type, - terms=initial_terms) + sProblem = StreamingProblem( + ws, name="test", problem_type=problem_type, terms=initial_terms + ) + rProblem = Problem( + "test", problem_type=problem_type, terms=initial_terms + ) sProblem.upload_terms_threshold = terms_thresh sProblem.upload_size_threshold = size_thresh sProblem.compress = compress @@ -53,8 +51,9 @@ def __test_upload_problem(self, self.assertEqual(problem_type, sProblem.problem_type) self.assertEqual(problem_type.name, sProblem.stats["type"]) - self.assertEqual(count + len(initial_terms), - sProblem.stats["num_terms"]) + self.assertEqual( + count + len(initial_terms), sProblem.stats["num_terms"] + ) self.assertEqual( self.__kwarg_or_value(kwargs, "avg_coupling", 2), sProblem.stats["avg_coupling"], diff --git a/azure-quantum/tests/unit/common.py b/azure-quantum/tests/unit/common.py index cbb9527ff..e5b99acd0 100644 --- a/azure-quantum/tests/unit/common.py +++ b/azure-quantum/tests/unit/common.py @@ -21,26 +21,35 @@ ) from azure_devtools.scenario_tests.utilities import _get_content_type import json + + class QuantumTestBase(ReplayableTest): """QuantumTestBase - During init, gets Azure Credentials and Azure Quantum Workspace parameters from OS environment variables. + During init, gets Azure Credentials and + Azure Quantum Workspace parameters from OS environment variables. """ dummy_uid = "00000000-0000-0000-0000-000000000000" dummy_rg = "dummy-rg" dummy_ws = "dummy-ws" dummy_clientsecret = "PLACEHOLDER" - dummy_auth_token = {'access_token': 'PLACEHOLDER', 'token_type': 'Bearer', 'expires_in': 485} + dummy_auth_token = { + "access_token": "PLACEHOLDER", + "token_type": "Bearer", + "expires_in": 485, + } def __init__(self, method_name): self._client_id = os.environ.get("AZURE_CLIENT_ID", self.dummy_uid) - self._client_secret = os.environ.get("AZURE_CLIENT_SECRET", - self.dummy_clientsecret) + self._client_secret = os.environ.get( + "AZURE_CLIENT_SECRET", self.dummy_clientsecret + ) self._tenant_id = os.environ.get("AZURE_TENANT_ID", self.dummy_uid) self._resource_group = os.environ.get("RESOURCE_GROUP", self.dummy_rg) - self._subscription_id = os.environ.get("SUBSCRIPTION_ID", - self.dummy_uid) + self._subscription_id = os.environ.get( + "SUBSCRIPTION_ID", self.dummy_uid + ) self._workspace_name = os.environ.get("WORKSPACE_NAME", self.dummy_ws) regex_replacer = CustomRecordingProcessor() @@ -64,8 +73,9 @@ def __init__(self, method_name): self._workspace_name = self.dummy_ws regex_replacer.register_regex(self.client_id, self.dummy_uid) - regex_replacer.register_regex(self.client_secret, - self.dummy_clientsecret) + regex_replacer.register_regex( + self.client_secret, self.dummy_clientsecret + ) regex_replacer.register_regex(self.tenant_id, self.dummy_uid) regex_replacer.register_regex(self.subscription_id, self.dummy_uid) regex_replacer.register_regex(self.workspace_name, self.dummy_ws) @@ -74,18 +84,22 @@ def __init__(self, method_name): r"/subscriptions/([a-f0-9]+[-]){4}[a-f0-9]+", "/subscriptions/" + self.dummy_uid, ) - regex_replacer.register_regex(r"job-([a-f0-9]+[-]){4}[a-f0-9]+", - "job-" + self.dummy_uid) - regex_replacer.register_regex(r"jobs/([a-f0-9]+[-]){4}[a-f0-9]+", - "jobs/" + self.dummy_uid) + regex_replacer.register_regex( + r"job-([a-f0-9]+[-]){4}[a-f0-9]+", "job-" + self.dummy_uid + ) + regex_replacer.register_regex( + r"jobs/([a-f0-9]+[-]){4}[a-f0-9]+", "jobs/" + self.dummy_uid + ) regex_replacer.register_regex( r'"id":\s*"([a-f0-9]+[-]){4}[a-f0-9]+"', '"id": "{}"'.format(self.dummy_uid), ) - regex_replacer.register_regex(r"/resourceGroups/[a-z0-9-]+/", - "/resourceGroups/dummy-rg/") - regex_replacer.register_regex(r"/workspaces/[a-z0-9-]+/", - "/workspaces/dummy-ws/") + regex_replacer.register_regex( + r"/resourceGroups/[a-z0-9-]+/", "/resourceGroups/dummy-rg/" + ) + regex_replacer.register_regex( + r"/workspaces/[a-z0-9-]+/", "/workspaces/dummy-ws/" + ) regex_replacer.register_regex(r"sig=[0-9a-zA-Z%]+\&", "sig=sanitized&") regex_replacer.register_regex(r"sv=[^&]+\&", "sv=sanitized&") regex_replacer.register_regex(r"se=[^&]+\&", "se=sanitized&") @@ -142,7 +156,8 @@ def create_workspace(self) -> Workspace: workspace.login(False) else: workspace.credentials = BasicTokenAuthentication( - token=self.dummy_auth_token) + token=self.dummy_auth_token + ) return workspace @@ -216,16 +231,19 @@ def process_response(self, response): return response -#helper functions + +# helper functions # helpers def expected_terms(): - expected = json.dumps({ - "cost_function": { - "version": "1.1", - "type": "ising", - "terms": [ { 'c':3, 'ids':[1,0] }, {'c':5, 'ids':[2,0]} ], - "initial_configuration": {"0":-1 , "1": 1, "2": -1}, + expected = json.dumps( + { + "cost_function": { + "version": "1.1", + "type": "ising", + "terms": [{"c": 3, "ids": [1, 0]}, {"c": 5, "ids": [2, 0]}], + "initial_configuration": {"0": -1, "1": 1, "2": -1}, + } } - }) + ) return expected diff --git a/azure-quantum/tests/unit/test_job.py b/azure-quantum/tests/unit/test_job.py index 2817f5214..eb1ff3fb5 100644 --- a/azure-quantum/tests/unit/test_job.py +++ b/azure-quantum/tests/unit/test_job.py @@ -39,9 +39,9 @@ def test_job_refresh(self): problem.add_term(c=i, indices=[i, i + 1]) with unittest.mock.patch.object( - Job, - self.mock_create_job_id_name, - return_value=self.get_dummy_job_id(), + Job, + self.mock_create_job_id_name, + return_value=self.get_dummy_job_id(), ): solver = SimulatedAnnealing(ws) job = solver.submit(problem) @@ -57,9 +57,9 @@ def test_job_has_completed(self): problem.add_term(c=i, indices=[i, i + 1]) with unittest.mock.patch.object( - Job, - self.mock_create_job_id_name, - return_value=self.get_dummy_job_id(), + Job, + self.mock_create_job_id_name, + return_value=self.get_dummy_job_id(), ): solver = SimulatedAnnealing(ws) job = solver.submit(problem) @@ -79,9 +79,9 @@ def test_job_wait_unit_completed(self): problem.add_term(c=i, indices=[i, i + 1]) with unittest.mock.patch.object( - Job, - self.mock_create_job_id_name, - return_value=self.get_dummy_job_id(), + Job, + self.mock_create_job_id_name, + return_value=self.get_dummy_job_id(), ): solver = SimulatedAnnealing(ws) job = solver.submit(problem) @@ -100,9 +100,9 @@ def test_job_get_results(self): problem.add_term(c=i, indices=[i, i + 1]) with unittest.mock.patch.object( - Job, - self.mock_create_job_id_name, - return_value=self.get_dummy_job_id(), + Job, + self.mock_create_job_id_name, + return_value=self.get_dummy_job_id(), ): solver = SimulatedAnnealing(ws) job = solver.submit(problem) @@ -111,13 +111,7 @@ def test_job_get_results(self): actual = job.get_results() expected = { - "configuration": { - "0": 1, - "1": 1, - "2": -1, - "3": 1, - "4": -1 - }, + "configuration": {"0": 1, "1": 1, "2": -1, "3": 1, "4": -1}, "cost": -6.0, "parameters": { "beta_start": 0.2, diff --git a/azure-quantum/tests/unit/test_online_problem.py b/azure-quantum/tests/unit/test_online_problem.py index 5bd04ce8a..aca452852 100644 --- a/azure-quantum/tests/unit/test_online_problem.py +++ b/azure-quantum/tests/unit/test_online_problem.py @@ -10,39 +10,31 @@ import unittest from unittest.mock import Mock from azure.quantum.optimization import Problem, Term, OnlineProblem -import azure.quantum.optimization.problem +import azure.quantum.optimization.problem from common import expected_terms import json class TestOnlineProblemClass(unittest.TestCase): - def setUp(self): - self.o_problem = OnlineProblem(name = "test", blob_uri = "mock_blob_uri") - - + self.o_problem = OnlineProblem(name="test", blob_uri="mock_blob_uri") + def test_download(self): - azure.quantum.optimization.problem.download_blob = Mock(return_value = expected_terms()) + azure.quantum.optimization.problem.download_blob = Mock( + return_value=expected_terms() + ) acutal_result = self.o_problem.download() - #to-do add test that user warning was registered in log - assert acutal_result.name == 'test' + # to-do add test that user warning was registered in log + assert acutal_result.name == "test" azure.quantum.optimization.problem.download_blob.assert_called_once() assert isinstance(acutal_result, Problem) def test_evaluate(self): - config_dict = { - 1:1, - 0:1 - } + config_dict = {1: 1, 0: 1} with self.assertRaises(Exception): self.o_problem.evaluate(config_dict) - + def test_set_fixed_variables(self): - config_dict = { - 1:1, - 0:1 - } + config_dict = {1: 1, 0: 1} with self.assertRaises(Exception): self.o_problem.set_fixed_variables(config_dict) - - diff --git a/azure-quantum/tests/unit/test_optimization.py b/azure-quantum/tests/unit/test_optimization.py index 0cea6b216..ae21143db 100644 --- a/azure-quantum/tests/unit/test_optimization.py +++ b/azure-quantum/tests/unit/test_optimization.py @@ -39,17 +39,18 @@ def test_add_terms(self): more.append(Term(w=i, indices=[i, i - 1])) problem.add_terms(more) self.assertEqual((count * 2) + 1, len(problem.terms)) - self.assertEqual(Term(w=count, indices=[count, count - 1]), - problem.terms[count * 2]) + self.assertEqual( + Term(w=count, indices=[count, count - 1]), problem.terms[count * 2] + ) def test_provide_terms(self): count = 4 terms = [] for i in range(count): terms.append(Term(w=i, indices=[i, i + 1])) - problem = Problem(name="test", - terms=terms, - problem_type=ProblemType.pubo) + problem = Problem( + name="test", terms=terms, problem_type=ProblemType.pubo + ) self.assertEqual(ProblemType.pubo, problem.problem_type) self.assertEqual(count, len(problem.terms)) @@ -70,17 +71,18 @@ def test_add_terms_cterms(self): more.append(Term(c=i, indices=[i, i - 1])) problem.add_terms(more) self.assertEqual((count * 2) + 1, len(problem.terms)) - self.assertEqual(Term(c=count, indices=[count, count - 1]), - problem.terms[count * 2]) + self.assertEqual( + Term(c=count, indices=[count, count - 1]), problem.terms[count * 2] + ) def test_provide_cterms(self): count = 4 terms = [] for i in range(count): terms.append(Term(c=i, indices=[i, i + 1])) - problem = Problem(name="test", - terms=terms, - problem_type=ProblemType.pubo) + problem = Problem( + name="test", terms=terms, problem_type=ProblemType.pubo + ) self.assertEqual(ProblemType.pubo, problem.problem_type) self.assertEqual(count, len(problem.terms)) @@ -93,22 +95,18 @@ def test_serialization_cterms(self): terms.append(Term(c=i, indices=[i, i + 1])) problem = Problem(name="test", terms=terms) - expected = json.dumps({ - "cost_function": { - "version": "1.0", - "type": "ising", - "terms": [ - { - "c": 0, - "ids": [0, 1] - }, - { - "c": 1, - "ids": [1, 2] - }, - ], + expected = json.dumps( + { + "cost_function": { + "version": "1.0", + "type": "ising", + "terms": [ + {"c": 0, "ids": [0, 1]}, + {"c": 1, "ids": [1, 2]}, + ], + } } - }) + ) print(problem.serialize()) actual = problem.serialize() self.assertEqual(expected, actual) @@ -121,27 +119,19 @@ def test_serialization_init_config(self): init_config = {"0": -1, "1": 1, "2": -1} problem = Problem(name="test", terms=terms, init_config=init_config) - expected = json.dumps({ - "cost_function": { - "version": "1.1", - "type": "ising", - "terms": [ - { - "c": 0, - "ids": [0, 1] - }, - { - "c": 1, - "ids": [1, 2] - }, - ], - "initial_configuration": { - "0": -1, - "1": 1, - "2": -1 - }, + expected = json.dumps( + { + "cost_function": { + "version": "1.1", + "type": "ising", + "terms": [ + {"c": 0, "ids": [0, 1]}, + {"c": 1, "ids": [1, 2]}, + ], + "initial_configuration": {"0": -1, "1": 1, "2": -1}, + } } - }) + ) actual = problem.serialize() self.assertEqual(expected, actual) @@ -176,79 +166,67 @@ def test_deserialize_init_config(self): def test_problem_evaluate(self): terms = [] - problem = Problem(name="test", - terms=terms, - problem_type=ProblemType.pubo) + problem = Problem( + name="test", terms=terms, problem_type=ProblemType.pubo + ) self.assertEqual(0, problem.evaluate({})) self.assertEqual(0, problem.evaluate({"0": 1})) terms = [Term(c=10, indices=[0, 1, 2])] - problem = Problem(name="test", - terms=terms, - problem_type=ProblemType.pubo) + problem = Problem( + name="test", terms=terms, problem_type=ProblemType.pubo + ) self.assertEqual(0, problem.evaluate({"0": 0, "1": 1, "2": 1})) self.assertEqual(10, problem.evaluate({"0": 1, "1": 1, "2": 1})) - problem = Problem(name="test", - terms=terms, - problem_type=ProblemType.ising) + problem = Problem( + name="test", terms=terms, problem_type=ProblemType.ising + ) self.assertEqual(-10, problem.evaluate({"0": -1, "1": 1, "2": 1})) self.assertEqual(10, problem.evaluate({"0": -1, "1": -1, "2": 1})) terms = [Term(c=10, indices=[0, 1, 2]), Term(c=-5, indices=[1, 2])] - problem = Problem(name="test", - terms=terms, - problem_type=ProblemType.pubo) + problem = Problem( + name="test", terms=terms, problem_type=ProblemType.pubo + ) self.assertEqual(-5, problem.evaluate({"0": 0, "1": 1, "2": 1})) self.assertEqual(5, problem.evaluate({"0": 1, "1": 1, "2": 1})) terms = [Term(c=10, indices=[])] # constant term - problem = Problem(name="test", - terms=terms, - problem_type=ProblemType.pubo) + problem = Problem( + name="test", terms=terms, problem_type=ProblemType.pubo + ) self.assertEqual(10, problem.evaluate({})) def test_problem_fixed_variables(self): terms = [] - problem = Problem(name="test", - terms=terms, - problem_type=ProblemType.pubo) + problem = Problem( + name="test", terms=terms, problem_type=ProblemType.pubo + ) problem_new = problem.set_fixed_variables({"0": 1}) self.assertEqual([], problem_new.terms) # test small cases terms = [Term(c=10, indices=[0, 1, 2]), Term(c=-5, indices=[1, 2])] - problem = Problem(name="test", - terms=terms, - problem_type=ProblemType.pubo) + problem = Problem( + name="test", terms=terms, problem_type=ProblemType.pubo + ) self.assertEqual([], problem.set_fixed_variables({"1": 0}).terms) self.assertEqual( - [Term(c=10, indices=[0]), - Term(c=-5, indices=[])], - problem.set_fixed_variables({ - "1": 1, - "2": 1 - }).terms, + [Term(c=10, indices=[0]), Term(c=-5, indices=[])], + problem.set_fixed_variables({"1": 1, "2": 1}).terms, ) # test all const terms get merged self.assertEqual( [Term(c=5, indices=[])], - problem.set_fixed_variables({ - "0": 1, - "1": 1, - "2": 1 - }).terms, + problem.set_fixed_variables({"0": 1, "1": 1, "2": 1}).terms, ) # test init_config gets transferred - problem = Problem("My Problem", - terms=terms, - init_config={ - "0": 1, - "1": 1, - "2": 1 - }) + problem = Problem( + "My Problem", terms=terms, init_config={"0": 1, "1": 1, "2": 1} + ) problem2 = problem.set_fixed_variables({"0": 0}) self.assertEqual({"1": 1, "2": 1}, problem2.init_config) @@ -262,16 +240,16 @@ def test_problem_large(self): problem.add_term(6.0, list(range(3000))) self.assertTrue(not problem.is_large()) - problem.add_terms([Term(indices=[9999], c=1.0)] * - int(1e6)) # create 1mil dummy terms + problem.add_terms( + [Term(indices=[9999], c=1.0)] * int(1e6) + ) # create 1mil dummy terms self.assertTrue(problem.is_large()) def _init_ws_(): - return Workspace(subscription_id="subs_id", - resource_group="rg", - name="n", - storage=None) + return Workspace( + subscription_id="subs_id", resource_group="rg", name="n", storage=None + ) class TestSolvers(QuantumTestBase): @@ -290,50 +268,43 @@ def test_input_params(self): s2_params = SimulatedAnnealing(ws, timeout=1010).params self.assertEqual({"timeout": 1010}, s2_params["params"]) - p3_params = ParallelTempering(ws, sweeps=2024, all_betas=[3, 4, - 5]).params + p3_params = ParallelTempering( + ws, sweeps=2024, all_betas=[3, 4, 5] + ).params self.assertEqual( - { - "all_betas": [3, 4, 5], - "replicas": 3, - "sweeps": 2024 - }, + {"all_betas": [3, 4, 5], "replicas": 3, "sweeps": 2024}, p3_params["params"], ) s3_params = SimulatedAnnealing(ws, beta_start=3.2, sweeps=12).params - self.assertEqual({ - "beta_start": 3.2, - "sweeps": 12 - }, s3_params["params"]) + self.assertEqual( + {"beta_start": 3.2, "sweeps": 12}, s3_params["params"] + ) def test_ParallelTempering_input_params(self): ws = _init_ws_() good = ParallelTempering(ws, timeout=1011) self.assertIsNotNone(good) - self.assertEqual("microsoft.paralleltempering-parameterfree.cpu", - good.target) + self.assertEqual( + "microsoft.paralleltempering-parameterfree.cpu", good.target + ) self.assertEqual({"timeout": 1011}, good.params["params"]) good = ParallelTempering(ws, seed=20) self.assertIsNotNone(good) - self.assertEqual("microsoft.paralleltempering-parameterfree.cpu", - good.target) + self.assertEqual( + "microsoft.paralleltempering-parameterfree.cpu", good.target + ) self.assertEqual({"seed": 20}, good.params["params"]) - good = ParallelTempering(ws, - sweeps=20, - replicas=3, - all_betas=[3, 5, 9]) + good = ParallelTempering( + ws, sweeps=20, replicas=3, all_betas=[3, 5, 9] + ) self.assertIsNotNone(good) self.assertEqual("microsoft.paralleltempering.cpu", good.target) self.assertEqual( - { - "sweeps": 20, - "replicas": 3, - "all_betas": [3, 5, 9] - }, + {"sweeps": 20, "replicas": 3, "all_betas": [3, 5, 9]}, good.params["params"], ) @@ -341,52 +312,46 @@ def test_ParallelTempering_input_params(self): self.assertIsNotNone(good) self.assertEqual("microsoft.paralleltempering.cpu", good.target) self.assertEqual( - { - "sweeps": 20, - "replicas": 2, - "all_betas": [3, 9] - }, + {"sweeps": 20, "replicas": 2, "all_betas": [3, 9]}, good.params["params"], ) with self.assertRaises(ValueError): - _ = ParallelTempering(ws, - sweeps=20, - replicas=3, - all_betas=[1, 3, 5, 7, 9]) + _ = ParallelTempering( + ws, sweeps=20, replicas=3, all_betas=[1, 3, 5, 7, 9] + ) def test_SimulatedAnnealing_input_params(self): ws = _init_ws_() good = SimulatedAnnealing(ws, timeout=1011, seed=4321) self.assertIsNotNone(good) - self.assertEqual("microsoft.simulatedannealing-parameterfree.cpu", - good.target) - self.assertEqual({ - "timeout": 1011, - "seed": 4321 - }, good.params["params"]) - - good = SimulatedAnnealing(ws, - timeout=1011, - seed=4321, - platform=HardwarePlatform.FPGA) + self.assertEqual( + "microsoft.simulatedannealing-parameterfree.cpu", good.target + ) + self.assertEqual( + {"timeout": 1011, "seed": 4321}, good.params["params"] + ) + + good = SimulatedAnnealing( + ws, timeout=1011, seed=4321, platform=HardwarePlatform.FPGA + ) self.assertIsNotNone(good) - self.assertEqual("microsoft.simulatedannealing-parameterfree.fpga", - good.target) - self.assertEqual({ - "timeout": 1011, - "seed": 4321 - }, good.params["params"]) + self.assertEqual( + "microsoft.simulatedannealing-parameterfree.fpga", good.target + ) + self.assertEqual( + {"timeout": 1011, "seed": 4321}, good.params["params"] + ) good = SimulatedAnnealing(ws, beta_start=21) self.assertIsNotNone(good) self.assertEqual("microsoft.simulatedannealing.cpu", good.target) self.assertEqual({"beta_start": 21}, good.params["params"]) - good = SimulatedAnnealing(ws, - beta_start=21, - platform=HardwarePlatform.FPGA) + good = SimulatedAnnealing( + ws, beta_start=21, platform=HardwarePlatform.FPGA + ) self.assertIsNotNone(good) self.assertEqual("microsoft.simulatedannealing.fpga", good.target) self.assertEqual({"beta_start": 21}, good.params["params"]) @@ -396,10 +361,9 @@ def test_QuantumMonteCarlo_input_params(self): good = QuantumMonteCarlo(ws, trotter_number=100, seed=4321) self.assertIsNotNone(good) self.assertEqual("microsoft.qmc.cpu", good.target) - self.assertEqual({ - "trotter_number": 100, - "seed": 4321 - }, good.params["params"]) + self.assertEqual( + {"trotter_number": 100, "seed": 4321}, good.params["params"] + ) def test_PopulationAnnealing_input_params(self): ws = _init_ws_() @@ -421,11 +385,7 @@ def test_PopulationAnnealing_input_params(self): self.assertEqual(1000, good.params["params"]["sweeps"]) self.assertEqual(0.5, good.params["params"]["culling_fraction"]) self.assertEqual( - { - "type": "linear", - "initial": 0.8, - "final": 5.8 - }, + {"type": "linear", "initial": 0.8, "final": 5.8}, good.params["params"]["beta"], ) @@ -446,22 +406,14 @@ def test_SubstochasticMonteCarlo_input_params(self): self.assertEqual("microsoft.substochasticmontecarlo.cpu", good.target) self.assertEqual(1888, good.params["params"]["seed"]) self.assertEqual( - { - "type": "geometric", - "initial": 1.8, - "final": 2.8 - }, + {"type": "geometric", "initial": 1.8, "final": 2.8}, good.params["params"]["alpha"], ) self.assertEqual(3000, good.params["params"]["target_population"]) self.assertEqual(1000, good.params["params"]["step_limit"]) self.assertEqual(5, good.params["params"]["steps_per_walker"]) self.assertEqual( - { - "type": "linear", - "initial": 2.8, - "final": 15.8 - }, + {"type": "linear", "initial": 2.8, "final": 15.8}, good.params["params"]["beta"], ) @@ -470,7 +422,8 @@ def test_SSMC_bad_input_params(self): with self.assertRaises(ValueError) as context: bad_range = RangeSchedule("nothing", 2.8, 15.8) self.assertTrue( - '"schedule_type" can only be' in str(context.exception)) + '"schedule_type" can only be' in str(context.exception) + ) self.assertTrue(bad_range is None) beta = 1 alpha = 2 @@ -486,8 +439,9 @@ def test_SSMC_bad_input_params(self): steps_per_walker=5, beta=beta, ) - self.assertTrue('can only be from class "RangeSchedule"!' in str( - context.exception)) + self.assertTrue( + 'can only be from class "RangeSchedule"!' in str(context.exception) + ) self.assertTrue(bad_solver is None) with self.assertRaises(ValueError) as context: @@ -515,8 +469,9 @@ def test_PA_bad_input_params(self): culling_fraction=0.5, beta=beta, ) - self.assertTrue('can only be from class "RangeSchedule"!' in str( - context.exception)) + self.assertTrue( + 'can only be from class "RangeSchedule"!' in str(context.exception) + ) self.assertTrue(bad_solver is None) with self.assertRaises(ValueError) as context: @@ -532,11 +487,9 @@ def test_PA_bad_input_params(self): self.assertTrue(bad_solver is None) with self.assertRaises(ValueError) as context: - bad_solver = PopulationAnnealing(ws, - alpha=0.2, - seed=8888, - sweeps=1000, - culling_fraction=0.5) + bad_solver = PopulationAnnealing( + ws, alpha=0.2, seed=8888, sweeps=1000, culling_fraction=0.5 + ) self.assertTrue("can not be smaller than" in str(context.exception)) self.assertTrue(bad_solver is None) diff --git a/azure-quantum/tests/unit/test_problem.py b/azure-quantum/tests/unit/test_problem.py index 0653cb7f5..98fd318ec 100644 --- a/azure-quantum/tests/unit/test_problem.py +++ b/azure-quantum/tests/unit/test_problem.py @@ -10,26 +10,24 @@ import unittest from unittest.mock import Mock from azure.quantum.optimization import Problem, Term -import azure.quantum.optimization.problem +import azure.quantum.optimization.problem from common import expected_terms import json class TestProblemClass(unittest.TestCase): - def setUp(self): - self.problem = Problem(name = "test") + self.problem = Problem(name="test") self.problem.terms = [ - Term(c = 3, indices=[1,0]), - Term(c = 5, indices=[2,0]) + Term(c=3, indices=[1, 0]), + Term(c=5, indices=[2, 0]), ] self.problem.uploaded_blob_uri = "mock_blob_uri" - + def test_download(self): - azure.quantum.optimization.problem.download_blob = Mock(return_value = expected_terms()) + azure.quantum.optimization.problem.download_blob = Mock( + return_value=expected_terms() + ) acutal_result = self.problem.download() - assert acutal_result.name == 'test' + assert acutal_result.name == "test" azure.quantum.optimization.problem.download_blob.assert_called_once() - - - diff --git a/azure-quantum/tests/unit/test_solvers.py b/azure-quantum/tests/unit/test_solvers.py index 9156e8e39..eea6b7b30 100644 --- a/azure-quantum/tests/unit/test_solvers.py +++ b/azure-quantum/tests/unit/test_solvers.py @@ -13,18 +13,23 @@ from azure.quantum.optimization import Solver, OnlineProblem import azure.quantum.storage + class TestSolvers(unittest.TestCase): def setUp(self): - self.mock_ws = Mock(spec = Workspace) + self.mock_ws = Mock(spec=Workspace) self.mock_ws.storage = "mock_storage" - #self.mock_ws.submit_job = Mock(return_value = ) - self.testsolver = Solver(self.mock_ws, 'Microsoft', 'SimulatedAnnealing', 'json', 'json') - + # self.mock_ws.submit_job = Mock(return_value = ) + self.testsolver = Solver( + self.mock_ws, "Microsoft", "SimulatedAnnealing", "json", "json" + ) + def test_submit_online_problem(self): - #Arrange - o_problem = OnlineProblem(name = "test", blob_uri = "mock_blob_uri") - #Act - azure.quantum.storage.get_container_uri = Mock(return_value = "mock_container_uri") + # Arrange + o_problem = OnlineProblem(name="test", blob_uri="mock_blob_uri") + # Act + azure.quantum.storage.get_container_uri = Mock( + return_value="mock_container_uri" + ) _ = self.testsolver.submit(o_problem) - #Assert + # Assert self.testsolver.workspace.submit_job.assert_called_once() diff --git a/azure-quantum/tests/unit/test_workspace.py b/azure-quantum/tests/unit/test_workspace.py index 8c33e1dfd..a1f9c2aed 100644 --- a/azure-quantum/tests/unit/test_workspace.py +++ b/azure-quantum/tests/unit/test_workspace.py @@ -10,7 +10,8 @@ import pytest from azure.quantum import Workspace -from common import QuantumTestBase +from common import QuantumTestBase + class TestWorkspace(QuantumTestBase): def test_workspace_login(self): From 95d808dd60b30121588a54bbb0946629490bdd4f Mon Sep 17 00:00:00 2001 From: Sanjana Gupta <42555338+sanjgupt@users.noreply.github.com> Date: Tue, 4 May 2021 11:46:57 -0700 Subject: [PATCH 07/21] nit --- azure-quantum/tests/integration/test_integration.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azure-quantum/tests/integration/test_integration.py b/azure-quantum/tests/integration/test_integration.py index 463acbbbb..dea2ffc6f 100644 --- a/azure-quantum/tests/integration/test_integration.py +++ b/azure-quantum/tests/integration/test_integration.py @@ -78,7 +78,7 @@ def solve( """ ws = create_workspace() - ## Call optimize on a solver to find the solution of a problem: + # Call optimize on a solver to find the solution of a problem: print("Finding solution...") solver = solver_factory(ws) print(solver) From 6ba91ab25a2c633ba3801a6c6727291594e1b0ec Mon Sep 17 00:00:00 2001 From: Sanjana Gupta <42555338+sanjgupt@users.noreply.github.com> Date: Tue, 4 May 2021 15:43:59 -0700 Subject: [PATCH 08/21] Make online problem wrapper for name and url --- .../azure/quantum/optimization/online_problem.py | 15 +++++++-------- .../azure/quantum/optimization/solvers.py | 8 ++++---- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/azure-quantum/azure/quantum/optimization/online_problem.py b/azure-quantum/azure/quantum/optimization/online_problem.py index 2898ca88f..794affe5d 100644 --- a/azure-quantum/azure/quantum/optimization/online_problem.py +++ b/azure-quantum/azure/quantum/optimization/online_problem.py @@ -6,13 +6,12 @@ __all__ = ["OnlineProblem"] -if TYPE_CHECKING: - from azure.quantum.workspace import Workspace - - -class OnlineProblem(Problem): - def __init__(self, name: str, blob_uri: str): - super().__init__(self) +class OnlineProblem(object): + def __init__( + self, name: str, + blob_uri: str, + **kw): + super(OnlineProblem,self).__init__(**kw) self.name = name self.uploaded_blob_uri = blob_uri @@ -42,4 +41,4 @@ def set_fixed_variables( def download(self) -> Problem: logger.warning("The problem will be downloaded to the client") - return super().download() + return Problem.download(self) diff --git a/azure-quantum/azure/quantum/optimization/solvers.py b/azure-quantum/azure/quantum/optimization/solvers.py index f10a7d94f..a95a9d744 100644 --- a/azure-quantum/azure/quantum/optimization/solvers.py +++ b/azure-quantum/azure/quantum/optimization/solvers.py @@ -122,10 +122,7 @@ def submit( if isinstance(problem, str): name = "Optimization problem" problem_uri = problem - elif not problem.terms: - name = problem.name - problem_uri = problem.uploaded_blob_uri - else: + elif isinstance(problem, Problem): name = problem.name problem_uri = problem.upload( self.workspace, @@ -133,6 +130,9 @@ def submit( container_name=container_name, blob_name="inputData", ) + else: + name = problem.name + problem_uri = problem.uploaded_blob_uri logger.info( f"Submitting problem '{name}'. Using payload from: '{problem_uri}'" From 40c1f0b584283967ca06d781ef63df477160b35f Mon Sep 17 00:00:00 2001 From: Sanjana Gupta <42555338+sanjgupt@users.noreply.github.com> Date: Tue, 4 May 2021 15:54:06 -0700 Subject: [PATCH 09/21] codestyle errors --- .../azure/quantum/optimization/online_problem.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/azure-quantum/azure/quantum/optimization/online_problem.py b/azure-quantum/azure/quantum/optimization/online_problem.py index 794affe5d..7925e7646 100644 --- a/azure-quantum/azure/quantum/optimization/online_problem.py +++ b/azure-quantum/azure/quantum/optimization/online_problem.py @@ -6,12 +6,14 @@ __all__ = ["OnlineProblem"] + class OnlineProblem(object): def __init__( - self, name: str, + self, name: str, blob_uri: str, - **kw): - super(OnlineProblem,self).__init__(**kw) + **kw + ): + super(OnlineProblem, self).__init__(**kw) self.name = name self.uploaded_blob_uri = blob_uri From cabf16e4e5c0eff11ceb8fc4b7eca368e4cfa216 Mon Sep 17 00:00:00 2001 From: Sanjana Gupta <42555338+sanjgupt@users.noreply.github.com> Date: Tue, 4 May 2021 16:31:59 -0700 Subject: [PATCH 10/21] add a small function to enable getting terms from index --- .../azure/quantum/optimization/problem.py | 14 ++++++++++++++ azure-quantum/tests/unit/test_problem.py | 9 +++++++++ 2 files changed, 23 insertions(+) diff --git a/azure-quantum/azure/quantum/optimization/problem.py b/azure-quantum/azure/quantum/optimization/problem.py index 14d2fa12e..3d445b56a 100644 --- a/azure-quantum/azure/quantum/optimization/problem.py +++ b/azure-quantum/azure/quantum/optimization/problem.py @@ -292,3 +292,17 @@ def download(self): ) contents = download_blob(self.uploaded_blob_uri) return Problem.deserialize(contents, self.name) + + def get_terms(self, id:int) -> List[Term]: + """ Given an index the function will return + a list of terms with that index + """ + terms = [] + if self.terms != []: + for term in self.terms: + if id in term.ids: + terms.append(term) + return terms + else: + raise Exception("Please download the problem on the client" \ + "to perform this operation") diff --git a/azure-quantum/tests/unit/test_problem.py b/azure-quantum/tests/unit/test_problem.py index 98fd318ec..ad89c7b53 100644 --- a/azure-quantum/tests/unit/test_problem.py +++ b/azure-quantum/tests/unit/test_problem.py @@ -31,3 +31,12 @@ def test_download(self): acutal_result = self.problem.download() assert acutal_result.name == "test" azure.quantum.optimization.problem.download_blob.assert_called_once() + + def test_get_term(self): + terms = self.problem.get_terms(0) + assert len(terms) == 2 + + def test_get_term_raise_exception(self): + test_prob = Problem(name="random") + with self.assertRaises(Exception): + test_prob.get_terms(id=0) From 89226d9f13df7027b1d4d64def545482d3cc4e93 Mon Sep 17 00:00:00 2001 From: Sanjana Gupta <42555338+sanjgupt@users.noreply.github.com> Date: Wed, 5 May 2021 13:14:28 -0700 Subject: [PATCH 11/21] remove evalutate and fixed variables from online problem --- .../quantum/optimization/online_problem.py | 24 ------------------- .../tests/unit/test_online_problem.py | 10 -------- 2 files changed, 34 deletions(-) diff --git a/azure-quantum/azure/quantum/optimization/online_problem.py b/azure-quantum/azure/quantum/optimization/online_problem.py index 7925e7646..15f035cbe 100644 --- a/azure-quantum/azure/quantum/optimization/online_problem.py +++ b/azure-quantum/azure/quantum/optimization/online_problem.py @@ -17,30 +17,6 @@ def __init__( self.name = name self.uploaded_blob_uri = blob_uri - def evaluate( - self, configuration: Union[Dict[int, int], Dict[str, int]] - ) -> float: - """ - An OnlineProblem cannot be evaluated on client side. - Calling this function will raise a user exception - """ - raise Exception( - "An Online Problem cannot be evaluated. \ - Please download the problem to do this operation" - ) - - def set_fixed_variables( - self, fixed_variables: Union[Dict[int, int], Dict[str, int]] - ) -> Problem: - """ - An OnlineProblem cannot be evaluated on client side. - Calling this function will raise a user exception - """ - raise Exception( - "An Online Problem cannot set fixed terms. \ - Please download the problem to do this operation" - ) - def download(self) -> Problem: logger.warning("The problem will be downloaded to the client") return Problem.download(self) diff --git a/azure-quantum/tests/unit/test_online_problem.py b/azure-quantum/tests/unit/test_online_problem.py index aca452852..2ab4ee9bf 100644 --- a/azure-quantum/tests/unit/test_online_problem.py +++ b/azure-quantum/tests/unit/test_online_problem.py @@ -28,13 +28,3 @@ def test_download(self): assert acutal_result.name == "test" azure.quantum.optimization.problem.download_blob.assert_called_once() assert isinstance(acutal_result, Problem) - - def test_evaluate(self): - config_dict = {1: 1, 0: 1} - with self.assertRaises(Exception): - self.o_problem.evaluate(config_dict) - - def test_set_fixed_variables(self): - config_dict = {1: 1, 0: 1} - with self.assertRaises(Exception): - self.o_problem.set_fixed_variables(config_dict) From cd4272f5745bfdf5a5319bd7387016845fe6c315 Mon Sep 17 00:00:00 2001 From: Sanjana Gupta <42555338+sanjgupt@users.noreply.github.com> Date: Wed, 5 May 2021 14:38:20 -0700 Subject: [PATCH 12/21] update the download function to correctly authenticate the storage account for download --- .../quantum/optimization/online_problem.py | 6 ++++-- .../azure/quantum/optimization/problem.py | 18 +++++++++++++----- .../tests/unit/test_online_problem.py | 10 ++++++++-- azure-quantum/tests/unit/test_problem.py | 10 ++++++++-- 4 files changed, 33 insertions(+), 11 deletions(-) diff --git a/azure-quantum/azure/quantum/optimization/online_problem.py b/azure-quantum/azure/quantum/optimization/online_problem.py index 15f035cbe..650368c20 100644 --- a/azure-quantum/azure/quantum/optimization/online_problem.py +++ b/azure-quantum/azure/quantum/optimization/online_problem.py @@ -6,6 +6,8 @@ __all__ = ["OnlineProblem"] +if TYPE_CHECKING: + from azure.quantum.workspace import Workspace class OnlineProblem(object): def __init__( @@ -17,6 +19,6 @@ def __init__( self.name = name self.uploaded_blob_uri = blob_uri - def download(self) -> Problem: + def download(self, workspace:"Workspace") -> Problem: logger.warning("The problem will be downloaded to the client") - return Problem.download(self) + return Problem.download(self, workspace) diff --git a/azure-quantum/azure/quantum/optimization/problem.py b/azure-quantum/azure/quantum/optimization/problem.py index 3d445b56a..8946c1c68 100644 --- a/azure-quantum/azure/quantum/optimization/problem.py +++ b/azure-quantum/azure/quantum/optimization/problem.py @@ -13,7 +13,7 @@ from typing import List, Union, Dict, Optional, TYPE_CHECKING from enum import Enum from azure.quantum.optimization import Term -from azure.quantum.storage import upload_blob, ContainerClient, download_blob +from azure.quantum.storage import upload_blob, ContainerClient, download_blob, BlobClient logger = logging.getLogger(__name__) @@ -284,13 +284,21 @@ def is_large(self) -> bool: and len(self.terms) >= Problem.NUM_TERMS_LARGE ) - def download(self): - """Dowloads an uploaded problem as an instance of 'Problem'""" + def download(self, workspace:"Workspace"): + """Downloads the uploaded problem as an instance of `Problem`""" if not self.uploaded_blob_uri: raise Exception( - "Problem must be uploaded before it can be downloaded" + "Problem may not be downloaded before it is uploaded" ) - contents = download_blob(self.uploaded_blob_uri) + blob_client = BlobClient.from_blob_url(self.uploaded_blob_uri) + container_client = ContainerClient.from_container_url( + workspace._get_linked_storage_sas_uri( + blob_client.container_name + ) + ) + blob_name = blob_client.blob_name + blob = container_client.get_blob_client(blob_name) + contents = download_blob(blob.url) return Problem.deserialize(contents, self.name) def get_terms(self, id:int) -> List[Term]: diff --git a/azure-quantum/tests/unit/test_online_problem.py b/azure-quantum/tests/unit/test_online_problem.py index 2ab4ee9bf..f3a5fdbe3 100644 --- a/azure-quantum/tests/unit/test_online_problem.py +++ b/azure-quantum/tests/unit/test_online_problem.py @@ -9,21 +9,27 @@ import unittest from unittest.mock import Mock +from typing import TYPE_CHECKING from azure.quantum.optimization import Problem, Term, OnlineProblem import azure.quantum.optimization.problem from common import expected_terms import json - class TestOnlineProblemClass(unittest.TestCase): def setUp(self): + self.mock_ws = Mock() + self.mock_ws._get_linked_storage_sas_uri.return_value = Mock() self.o_problem = OnlineProblem(name="test", blob_uri="mock_blob_uri") def test_download(self): azure.quantum.optimization.problem.download_blob = Mock( return_value=expected_terms() ) - acutal_result = self.o_problem.download() + azure.quantum.optimization.problem.BlobClient = Mock() + azure.quantum.optimization.problem.BlobClient.from_blob_url.return_value = Mock() + azure.quantum.optimization.problem.ContainerClient = Mock() + azure.quantum.optimization.problem.ContainerClient.from_container_url.return_value = Mock() + acutal_result = self.o_problem.download(self.mock_ws) # to-do add test that user warning was registered in log assert acutal_result.name == "test" azure.quantum.optimization.problem.download_blob.assert_called_once() diff --git a/azure-quantum/tests/unit/test_problem.py b/azure-quantum/tests/unit/test_problem.py index ad89c7b53..5c957b2a7 100644 --- a/azure-quantum/tests/unit/test_problem.py +++ b/azure-quantum/tests/unit/test_problem.py @@ -9,14 +9,16 @@ import unittest from unittest.mock import Mock +from typing import TYPE_CHECKING from azure.quantum.optimization import Problem, Term import azure.quantum.optimization.problem from common import expected_terms import json - class TestProblemClass(unittest.TestCase): def setUp(self): + self.mock_ws = Mock() + self.mock_ws._get_linked_storage_sas_uri.return_value = Mock() self.problem = Problem(name="test") self.problem.terms = [ Term(c=3, indices=[1, 0]), @@ -28,7 +30,11 @@ def test_download(self): azure.quantum.optimization.problem.download_blob = Mock( return_value=expected_terms() ) - acutal_result = self.problem.download() + azure.quantum.optimization.problem.BlobClient = Mock() + azure.quantum.optimization.problem.BlobClient.from_blob_url.return_value = Mock() + azure.quantum.optimization.problem.ContainerClient = Mock() + azure.quantum.optimization.problem.ContainerClient.from_container_url.return_value = Mock() + acutal_result = self.problem.download(self.mock_ws) assert acutal_result.name == "test" azure.quantum.optimization.problem.download_blob.assert_called_once() From 197754dc8c478ad4d1cff0d5129cb7e826933d47 Mon Sep 17 00:00:00 2001 From: Sanjana Gupta <42555338+sanjgupt@users.noreply.github.com> Date: Wed, 5 May 2021 14:42:50 -0700 Subject: [PATCH 13/21] styling errors --- azure-quantum/azure/quantum/optimization/online_problem.py | 3 ++- azure-quantum/azure/quantum/optimization/problem.py | 5 +++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/azure-quantum/azure/quantum/optimization/online_problem.py b/azure-quantum/azure/quantum/optimization/online_problem.py index 650368c20..ca7df16dc 100644 --- a/azure-quantum/azure/quantum/optimization/online_problem.py +++ b/azure-quantum/azure/quantum/optimization/online_problem.py @@ -9,12 +9,13 @@ if TYPE_CHECKING: from azure.quantum.workspace import Workspace + class OnlineProblem(object): def __init__( self, name: str, blob_uri: str, **kw - ): + ): super(OnlineProblem, self).__init__(**kw) self.name = name self.uploaded_blob_uri = blob_uri diff --git a/azure-quantum/azure/quantum/optimization/problem.py b/azure-quantum/azure/quantum/optimization/problem.py index 8946c1c68..b1a5866ea 100644 --- a/azure-quantum/azure/quantum/optimization/problem.py +++ b/azure-quantum/azure/quantum/optimization/problem.py @@ -312,5 +312,6 @@ def get_terms(self, id:int) -> List[Term]: terms.append(term) return terms else: - raise Exception("Please download the problem on the client" \ - "to perform this operation") + raise Exception("There are currently no terms in this problem. \ + Please download the problem on the client or add terms to the \ + problem to perform this operation") From ace79655d13c9db1fc276b1f013da472687463c5 Mon Sep 17 00:00:00 2001 From: Sanjana Gupta <42555338+sanjgupt@users.noreply.github.com> Date: Wed, 5 May 2021 14:47:37 -0700 Subject: [PATCH 14/21] styling errors --- azure-quantum/azure/quantum/optimization/problem.py | 7 ++++++- azure-quantum/tests/unit/test_online_problem.py | 1 + 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/azure-quantum/azure/quantum/optimization/problem.py b/azure-quantum/azure/quantum/optimization/problem.py index b1a5866ea..50bb26810 100644 --- a/azure-quantum/azure/quantum/optimization/problem.py +++ b/azure-quantum/azure/quantum/optimization/problem.py @@ -13,7 +13,12 @@ from typing import List, Union, Dict, Optional, TYPE_CHECKING from enum import Enum from azure.quantum.optimization import Term -from azure.quantum.storage import upload_blob, ContainerClient, download_blob, BlobClient +from azure.quantum.storage import ( + upload_blob, + ContainerClient, + download_blob, + BlobClient +) logger = logging.getLogger(__name__) diff --git a/azure-quantum/tests/unit/test_online_problem.py b/azure-quantum/tests/unit/test_online_problem.py index f3a5fdbe3..ac076e358 100644 --- a/azure-quantum/tests/unit/test_online_problem.py +++ b/azure-quantum/tests/unit/test_online_problem.py @@ -15,6 +15,7 @@ from common import expected_terms import json + class TestOnlineProblemClass(unittest.TestCase): def setUp(self): self.mock_ws = Mock() From 0d3b9b298772fced42248c301a1e7e631a587a40 Mon Sep 17 00:00:00 2001 From: Sanjana Gupta <42555338+sanjgupt@users.noreply.github.com> Date: Thu, 6 May 2021 12:06:49 -0700 Subject: [PATCH 15/21] nit --- azure-quantum/azure/quantum/optimization/streaming_problem.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azure-quantum/azure/quantum/optimization/streaming_problem.py b/azure-quantum/azure/quantum/optimization/streaming_problem.py index c054f95c4..f1da38b5c 100644 --- a/azure-quantum/azure/quantum/optimization/streaming_problem.py +++ b/azure-quantum/azure/quantum/optimization/streaming_problem.py @@ -32,7 +32,7 @@ class StreamingProblem(object): Streaming problems are uploaded on the fly as terms are added, meaning that the whole problem representation is not kept in memory. This - is very useful when constructing large problems. + is very useful when constructing large problems. :param workspace: Workspace to upload problem to :type workspace: Workspace From 9986d47565f43ac56d91b6e08578a9d4c11f1413 Mon Sep 17 00:00:00 2001 From: Sanjana Gupta <42555338+sanjgupt@users.noreply.github.com> Date: Fri, 7 May 2021 11:30:02 -0700 Subject: [PATCH 16/21] disablinb test for Online Problem for now till it becomes available in the SDK --- azure-quantum/tests/unit/test_online_problem.py | 1 + 1 file changed, 1 insertion(+) diff --git a/azure-quantum/tests/unit/test_online_problem.py b/azure-quantum/tests/unit/test_online_problem.py index ac076e358..26e33b26e 100644 --- a/azure-quantum/tests/unit/test_online_problem.py +++ b/azure-quantum/tests/unit/test_online_problem.py @@ -22,6 +22,7 @@ def setUp(self): self.mock_ws._get_linked_storage_sas_uri.return_value = Mock() self.o_problem = OnlineProblem(name="test", blob_uri="mock_blob_uri") + @pytesat.skip(reason= "OnlineProblem not available in SDK yet") def test_download(self): azure.quantum.optimization.problem.download_blob = Mock( return_value=expected_terms() From ee2a67c63c9cdd2c4f9a2d8d255c725e28536a6d Mon Sep 17 00:00:00 2001 From: Sanjana Gupta <42555338+sanjgupt@users.noreply.github.com> Date: Mon, 10 May 2021 09:00:47 -0700 Subject: [PATCH 17/21] Update azure-quantum/tests/unit/test_online_problem.py Co-authored-by: Guen Prawiroatmodjo --- azure-quantum/tests/unit/test_online_problem.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azure-quantum/tests/unit/test_online_problem.py b/azure-quantum/tests/unit/test_online_problem.py index 26e33b26e..ab5c2493b 100644 --- a/azure-quantum/tests/unit/test_online_problem.py +++ b/azure-quantum/tests/unit/test_online_problem.py @@ -22,7 +22,7 @@ def setUp(self): self.mock_ws._get_linked_storage_sas_uri.return_value = Mock() self.o_problem = OnlineProblem(name="test", blob_uri="mock_blob_uri") - @pytesat.skip(reason= "OnlineProblem not available in SDK yet") + @pytest.skip(reason= "OnlineProblem not available in SDK yet") def test_download(self): azure.quantum.optimization.problem.download_blob = Mock( return_value=expected_terms() From e05559ba07b343a12d169fd9bbbf151ba5ccf6a9 Mon Sep 17 00:00:00 2001 From: Sanjana Gupta <42555338+sanjgupt@users.noreply.github.com> Date: Mon, 10 May 2021 09:20:07 -0700 Subject: [PATCH 18/21] revert styles changes to _client. This folder should not be changed by code --- .../azure/quantum/_client/__init__.py | 3 +- .../azure/quantum/_client/models/__init__.py | 33 ++-- .../quantum/_client/models/blob_details.py | 10 +- .../_client/models/blob_details_py3.py | 10 +- .../quantum/_client/models/error_data.py | 8 +- .../quantum/_client/models/error_data_py3.py | 8 +- .../quantum/_client/models/job_details.py | 79 ++++---- .../_client/models/job_details_paged.py | 4 +- .../quantum/_client/models/job_details_py3.py | 74 +++---- .../quantum/_client/models/provider_status.py | 12 +- .../_client/models/provider_status_paged.py | 4 +- .../_client/models/provider_status_py3.py | 12 +- .../azure/quantum/_client/models/quota.py | 28 +-- .../quantum/_client/models/quota_paged.py | 4 +- .../azure/quantum/_client/models/quota_py3.py | 27 +-- .../quantum/_client/models/rest_error.py | 8 +- .../quantum/_client/models/rest_error_py3.py | 6 +- .../_client/models/sas_uri_response.py | 4 +- .../_client/models/sas_uri_response_py3.py | 4 +- .../quantum/_client/models/target_status.py | 16 +- .../_client/models/target_status_py3.py | 16 +- .../quantum/_client/operations/__init__.py | 8 +- .../_client/operations/jobs_operations.py | 183 +++++------------- .../operations/providers_operations.py | 55 ++---- .../_client/operations/quotas_operations.py | 55 ++---- .../_client/operations/storage_operations.py | 46 ++--- .../azure/quantum/_client/quantum_client.py | 60 ++---- .../azure/quantum/_client/version.py | 1 + 28 files changed, 278 insertions(+), 500 deletions(-) diff --git a/azure-quantum/azure/quantum/_client/__init__.py b/azure-quantum/azure/quantum/_client/__init__.py index ee13655c5..97d75e884 100644 --- a/azure-quantum/azure/quantum/_client/__init__.py +++ b/azure-quantum/azure/quantum/_client/__init__.py @@ -12,6 +12,7 @@ from .quantum_client import QuantumClient from .version import VERSION -__all__ = ["QuantumClient"] +__all__ = ['QuantumClient'] __version__ = VERSION + diff --git a/azure-quantum/azure/quantum/_client/models/__init__.py b/azure-quantum/azure/quantum/_client/models/__init__.py index 2b845f0b5..d82cd869b 100644 --- a/azure-quantum/azure/quantum/_client/models/__init__.py +++ b/azure-quantum/azure/quantum/_client/models/__init__.py @@ -39,21 +39,20 @@ ) __all__ = [ - "ErrorData", - "JobDetails", - "BlobDetails", - "SasUriResponse", - "TargetStatus", - "ProviderStatus", - "Quota", - "RestError", - "RestErrorException", - "JobDetailsPaged", - "ProviderStatusPaged", - "QuotaPaged", - "JobStatus", - "ProviderAvailability", - "TargetAvailability", - "DimensionScope", - "MeterPeriod", + 'ErrorData', + 'JobDetails', + 'BlobDetails', + 'SasUriResponse', + 'TargetStatus', + 'ProviderStatus', + 'Quota', + 'RestError', 'RestErrorException', + 'JobDetailsPaged', + 'ProviderStatusPaged', + 'QuotaPaged', + 'JobStatus', + 'ProviderAvailability', + 'TargetAvailability', + 'DimensionScope', + 'MeterPeriod', ] diff --git a/azure-quantum/azure/quantum/_client/models/blob_details.py b/azure-quantum/azure/quantum/_client/models/blob_details.py index 55bcc7b4c..5eca3fc53 100644 --- a/azure-quantum/azure/quantum/_client/models/blob_details.py +++ b/azure-quantum/azure/quantum/_client/models/blob_details.py @@ -24,15 +24,15 @@ class BlobDetails(Model): """ _validation = { - "container_name": {"required": True}, + 'container_name': {'required': True}, } _attribute_map = { - "container_name": {"key": "containerName", "type": "str"}, - "blob_name": {"key": "blobName", "type": "str"}, + 'container_name': {'key': 'containerName', 'type': 'str'}, + 'blob_name': {'key': 'blobName', 'type': 'str'}, } def __init__(self, **kwargs): super(BlobDetails, self).__init__(**kwargs) - self.container_name = kwargs.get("container_name", None) - self.blob_name = kwargs.get("blob_name", None) + self.container_name = kwargs.get('container_name', None) + self.blob_name = kwargs.get('blob_name', None) diff --git a/azure-quantum/azure/quantum/_client/models/blob_details_py3.py b/azure-quantum/azure/quantum/_client/models/blob_details_py3.py index 5080cba8e..d3cb67335 100644 --- a/azure-quantum/azure/quantum/_client/models/blob_details_py3.py +++ b/azure-quantum/azure/quantum/_client/models/blob_details_py3.py @@ -24,17 +24,15 @@ class BlobDetails(Model): """ _validation = { - "container_name": {"required": True}, + 'container_name': {'required': True}, } _attribute_map = { - "container_name": {"key": "containerName", "type": "str"}, - "blob_name": {"key": "blobName", "type": "str"}, + 'container_name': {'key': 'containerName', 'type': 'str'}, + 'blob_name': {'key': 'blobName', 'type': 'str'}, } - def __init__( - self, *, container_name: str, blob_name: str = None, **kwargs - ) -> None: + def __init__(self, *, container_name: str, blob_name: str=None, **kwargs) -> None: super(BlobDetails, self).__init__(**kwargs) self.container_name = container_name self.blob_name = blob_name diff --git a/azure-quantum/azure/quantum/_client/models/error_data.py b/azure-quantum/azure/quantum/_client/models/error_data.py index b96941afc..7d55dbac1 100644 --- a/azure-quantum/azure/quantum/_client/models/error_data.py +++ b/azure-quantum/azure/quantum/_client/models/error_data.py @@ -24,11 +24,11 @@ class ErrorData(Model): """ _attribute_map = { - "code": {"key": "code", "type": "str"}, - "message": {"key": "message", "type": "str"}, + 'code': {'key': 'code', 'type': 'str'}, + 'message': {'key': 'message', 'type': 'str'}, } def __init__(self, **kwargs): super(ErrorData, self).__init__(**kwargs) - self.code = kwargs.get("code", None) - self.message = kwargs.get("message", None) + self.code = kwargs.get('code', None) + self.message = kwargs.get('message', None) diff --git a/azure-quantum/azure/quantum/_client/models/error_data_py3.py b/azure-quantum/azure/quantum/_client/models/error_data_py3.py index 6ed699b71..b0d83bcbc 100644 --- a/azure-quantum/azure/quantum/_client/models/error_data_py3.py +++ b/azure-quantum/azure/quantum/_client/models/error_data_py3.py @@ -24,13 +24,11 @@ class ErrorData(Model): """ _attribute_map = { - "code": {"key": "code", "type": "str"}, - "message": {"key": "message", "type": "str"}, + 'code': {'key': 'code', 'type': 'str'}, + 'message': {'key': 'message', 'type': 'str'}, } - def __init__( - self, *, code: str = None, message: str = None, **kwargs - ) -> None: + def __init__(self, *, code: str=None, message: str=None, **kwargs) -> None: super(ErrorData, self).__init__(**kwargs) self.code = code self.message = message diff --git a/azure-quantum/azure/quantum/_client/models/job_details.py b/azure-quantum/azure/quantum/_client/models/job_details.py index 108f36019..78b3bd4d8 100644 --- a/azure-quantum/azure/quantum/_client/models/job_details.py +++ b/azure-quantum/azure/quantum/_client/models/job_details.py @@ -67,54 +67,51 @@ class JobDetails(Model): """ _validation = { - "container_uri": {"required": True}, - "input_data_format": {"required": True}, - "provider_id": {"required": True}, - "target": {"required": True}, - "status": {"readonly": True}, - "creation_time": {"readonly": True}, - "begin_execution_time": {"readonly": True}, - "end_execution_time": {"readonly": True}, - "cancellation_time": {"readonly": True}, - "error_data": {"readonly": True}, + 'container_uri': {'required': True}, + 'input_data_format': {'required': True}, + 'provider_id': {'required': True}, + 'target': {'required': True}, + 'status': {'readonly': True}, + 'creation_time': {'readonly': True}, + 'begin_execution_time': {'readonly': True}, + 'end_execution_time': {'readonly': True}, + 'cancellation_time': {'readonly': True}, + 'error_data': {'readonly': True}, } _attribute_map = { - "id": {"key": "id", "type": "str"}, - "name": {"key": "name", "type": "str"}, - "container_uri": {"key": "containerUri", "type": "str"}, - "input_data_uri": {"key": "inputDataUri", "type": "str"}, - "input_data_format": {"key": "inputDataFormat", "type": "str"}, - "input_params": {"key": "inputParams", "type": "object"}, - "provider_id": {"key": "providerId", "type": "str"}, - "target": {"key": "target", "type": "str"}, - "metadata": {"key": "metadata", "type": "{str}"}, - "output_data_uri": {"key": "outputDataUri", "type": "str"}, - "output_data_format": {"key": "outputDataFormat", "type": "str"}, - "status": {"key": "status", "type": "str"}, - "creation_time": {"key": "creationTime", "type": "iso-8601"}, - "begin_execution_time": { - "key": "beginExecutionTime", - "type": "iso-8601", - }, - "end_execution_time": {"key": "endExecutionTime", "type": "iso-8601"}, - "cancellation_time": {"key": "cancellationTime", "type": "iso-8601"}, - "error_data": {"key": "errorData", "type": "ErrorData"}, + 'id': {'key': 'id', 'type': 'str'}, + 'name': {'key': 'name', 'type': 'str'}, + 'container_uri': {'key': 'containerUri', 'type': 'str'}, + 'input_data_uri': {'key': 'inputDataUri', 'type': 'str'}, + 'input_data_format': {'key': 'inputDataFormat', 'type': 'str'}, + 'input_params': {'key': 'inputParams', 'type': 'object'}, + 'provider_id': {'key': 'providerId', 'type': 'str'}, + 'target': {'key': 'target', 'type': 'str'}, + 'metadata': {'key': 'metadata', 'type': '{str}'}, + 'output_data_uri': {'key': 'outputDataUri', 'type': 'str'}, + 'output_data_format': {'key': 'outputDataFormat', 'type': 'str'}, + 'status': {'key': 'status', 'type': 'str'}, + 'creation_time': {'key': 'creationTime', 'type': 'iso-8601'}, + 'begin_execution_time': {'key': 'beginExecutionTime', 'type': 'iso-8601'}, + 'end_execution_time': {'key': 'endExecutionTime', 'type': 'iso-8601'}, + 'cancellation_time': {'key': 'cancellationTime', 'type': 'iso-8601'}, + 'error_data': {'key': 'errorData', 'type': 'ErrorData'}, } def __init__(self, **kwargs): super(JobDetails, self).__init__(**kwargs) - self.id = kwargs.get("id", None) - self.name = kwargs.get("name", None) - self.container_uri = kwargs.get("container_uri", None) - self.input_data_uri = kwargs.get("input_data_uri", None) - self.input_data_format = kwargs.get("input_data_format", None) - self.input_params = kwargs.get("input_params", None) - self.provider_id = kwargs.get("provider_id", None) - self.target = kwargs.get("target", None) - self.metadata = kwargs.get("metadata", None) - self.output_data_uri = kwargs.get("output_data_uri", None) - self.output_data_format = kwargs.get("output_data_format", None) + self.id = kwargs.get('id', None) + self.name = kwargs.get('name', None) + self.container_uri = kwargs.get('container_uri', None) + self.input_data_uri = kwargs.get('input_data_uri', None) + self.input_data_format = kwargs.get('input_data_format', None) + self.input_params = kwargs.get('input_params', None) + self.provider_id = kwargs.get('provider_id', None) + self.target = kwargs.get('target', None) + self.metadata = kwargs.get('metadata', None) + self.output_data_uri = kwargs.get('output_data_uri', None) + self.output_data_format = kwargs.get('output_data_format', None) self.status = None self.creation_time = None self.begin_execution_time = None diff --git a/azure-quantum/azure/quantum/_client/models/job_details_paged.py b/azure-quantum/azure/quantum/_client/models/job_details_paged.py index e9da5bb0b..f8c5167c5 100644 --- a/azure-quantum/azure/quantum/_client/models/job_details_paged.py +++ b/azure-quantum/azure/quantum/_client/models/job_details_paged.py @@ -18,8 +18,8 @@ class JobDetailsPaged(Paged): """ _attribute_map = { - "next_link": {"key": "nextLink", "type": "str"}, - "current_page": {"key": "value", "type": "[JobDetails]"}, + 'next_link': {'key': 'nextLink', 'type': 'str'}, + 'current_page': {'key': 'value', 'type': '[JobDetails]'} } def __init__(self, *args, **kwargs): diff --git a/azure-quantum/azure/quantum/_client/models/job_details_py3.py b/azure-quantum/azure/quantum/_client/models/job_details_py3.py index 7ee7c1274..749ef493f 100644 --- a/azure-quantum/azure/quantum/_client/models/job_details_py3.py +++ b/azure-quantum/azure/quantum/_client/models/job_details_py3.py @@ -67,57 +67,39 @@ class JobDetails(Model): """ _validation = { - "container_uri": {"required": True}, - "input_data_format": {"required": True}, - "provider_id": {"required": True}, - "target": {"required": True}, - "status": {"readonly": True}, - "creation_time": {"readonly": True}, - "begin_execution_time": {"readonly": True}, - "end_execution_time": {"readonly": True}, - "cancellation_time": {"readonly": True}, - "error_data": {"readonly": True}, + 'container_uri': {'required': True}, + 'input_data_format': {'required': True}, + 'provider_id': {'required': True}, + 'target': {'required': True}, + 'status': {'readonly': True}, + 'creation_time': {'readonly': True}, + 'begin_execution_time': {'readonly': True}, + 'end_execution_time': {'readonly': True}, + 'cancellation_time': {'readonly': True}, + 'error_data': {'readonly': True}, } _attribute_map = { - "id": {"key": "id", "type": "str"}, - "name": {"key": "name", "type": "str"}, - "container_uri": {"key": "containerUri", "type": "str"}, - "input_data_uri": {"key": "inputDataUri", "type": "str"}, - "input_data_format": {"key": "inputDataFormat", "type": "str"}, - "input_params": {"key": "inputParams", "type": "object"}, - "provider_id": {"key": "providerId", "type": "str"}, - "target": {"key": "target", "type": "str"}, - "metadata": {"key": "metadata", "type": "{str}"}, - "output_data_uri": {"key": "outputDataUri", "type": "str"}, - "output_data_format": {"key": "outputDataFormat", "type": "str"}, - "status": {"key": "status", "type": "str"}, - "creation_time": {"key": "creationTime", "type": "iso-8601"}, - "begin_execution_time": { - "key": "beginExecutionTime", - "type": "iso-8601", - }, - "end_execution_time": {"key": "endExecutionTime", "type": "iso-8601"}, - "cancellation_time": {"key": "cancellationTime", "type": "iso-8601"}, - "error_data": {"key": "errorData", "type": "ErrorData"}, + 'id': {'key': 'id', 'type': 'str'}, + 'name': {'key': 'name', 'type': 'str'}, + 'container_uri': {'key': 'containerUri', 'type': 'str'}, + 'input_data_uri': {'key': 'inputDataUri', 'type': 'str'}, + 'input_data_format': {'key': 'inputDataFormat', 'type': 'str'}, + 'input_params': {'key': 'inputParams', 'type': 'object'}, + 'provider_id': {'key': 'providerId', 'type': 'str'}, + 'target': {'key': 'target', 'type': 'str'}, + 'metadata': {'key': 'metadata', 'type': '{str}'}, + 'output_data_uri': {'key': 'outputDataUri', 'type': 'str'}, + 'output_data_format': {'key': 'outputDataFormat', 'type': 'str'}, + 'status': {'key': 'status', 'type': 'str'}, + 'creation_time': {'key': 'creationTime', 'type': 'iso-8601'}, + 'begin_execution_time': {'key': 'beginExecutionTime', 'type': 'iso-8601'}, + 'end_execution_time': {'key': 'endExecutionTime', 'type': 'iso-8601'}, + 'cancellation_time': {'key': 'cancellationTime', 'type': 'iso-8601'}, + 'error_data': {'key': 'errorData', 'type': 'ErrorData'}, } - def __init__( - self, - *, - container_uri: str, - input_data_format: str, - provider_id: str, - target: str, - id: str = None, - name: str = None, - input_data_uri: str = None, - input_params=None, - metadata=None, - output_data_uri: str = None, - output_data_format: str = None, - **kwargs - ) -> None: + def __init__(self, *, container_uri: str, input_data_format: str, provider_id: str, target: str, id: str=None, name: str=None, input_data_uri: str=None, input_params=None, metadata=None, output_data_uri: str=None, output_data_format: str=None, **kwargs) -> None: super(JobDetails, self).__init__(**kwargs) self.id = id self.name = name diff --git a/azure-quantum/azure/quantum/_client/models/provider_status.py b/azure-quantum/azure/quantum/_client/models/provider_status.py index e5123b0e4..74a8a3989 100644 --- a/azure-quantum/azure/quantum/_client/models/provider_status.py +++ b/azure-quantum/azure/quantum/_client/models/provider_status.py @@ -29,15 +29,15 @@ class ProviderStatus(Model): """ _validation = { - "id": {"readonly": True}, - "current_availability": {"readonly": True}, - "targets": {"readonly": True}, + 'id': {'readonly': True}, + 'current_availability': {'readonly': True}, + 'targets': {'readonly': True}, } _attribute_map = { - "id": {"key": "id", "type": "str"}, - "current_availability": {"key": "currentAvailability", "type": "str"}, - "targets": {"key": "targets", "type": "[TargetStatus]"}, + 'id': {'key': 'id', 'type': 'str'}, + 'current_availability': {'key': 'currentAvailability', 'type': 'str'}, + 'targets': {'key': 'targets', 'type': '[TargetStatus]'}, } def __init__(self, **kwargs): diff --git a/azure-quantum/azure/quantum/_client/models/provider_status_paged.py b/azure-quantum/azure/quantum/_client/models/provider_status_paged.py index bd5a6f867..630b1dcda 100644 --- a/azure-quantum/azure/quantum/_client/models/provider_status_paged.py +++ b/azure-quantum/azure/quantum/_client/models/provider_status_paged.py @@ -18,8 +18,8 @@ class ProviderStatusPaged(Paged): """ _attribute_map = { - "next_link": {"key": "nextLink", "type": "str"}, - "current_page": {"key": "value", "type": "[ProviderStatus]"}, + 'next_link': {'key': 'nextLink', 'type': 'str'}, + 'current_page': {'key': 'value', 'type': '[ProviderStatus]'} } def __init__(self, *args, **kwargs): diff --git a/azure-quantum/azure/quantum/_client/models/provider_status_py3.py b/azure-quantum/azure/quantum/_client/models/provider_status_py3.py index 8e459ce42..c87bbe00e 100644 --- a/azure-quantum/azure/quantum/_client/models/provider_status_py3.py +++ b/azure-quantum/azure/quantum/_client/models/provider_status_py3.py @@ -29,15 +29,15 @@ class ProviderStatus(Model): """ _validation = { - "id": {"readonly": True}, - "current_availability": {"readonly": True}, - "targets": {"readonly": True}, + 'id': {'readonly': True}, + 'current_availability': {'readonly': True}, + 'targets': {'readonly': True}, } _attribute_map = { - "id": {"key": "id", "type": "str"}, - "current_availability": {"key": "currentAvailability", "type": "str"}, - "targets": {"key": "targets", "type": "[TargetStatus]"}, + 'id': {'key': 'id', 'type': 'str'}, + 'current_availability': {'key': 'currentAvailability', 'type': 'str'}, + 'targets': {'key': 'targets', 'type': '[TargetStatus]'}, } def __init__(self, **kwargs) -> None: diff --git a/azure-quantum/azure/quantum/_client/models/quota.py b/azure-quantum/azure/quantum/_client/models/quota.py index 5116367e1..66b6c0a4a 100644 --- a/azure-quantum/azure/quantum/_client/models/quota.py +++ b/azure-quantum/azure/quantum/_client/models/quota.py @@ -37,21 +37,21 @@ class Quota(Model): """ _attribute_map = { - "dimension": {"key": "dimension", "type": "str"}, - "scope": {"key": "scope", "type": "str"}, - "provider_id": {"key": "providerId", "type": "str"}, - "utilization": {"key": "utilization", "type": "float"}, - "holds": {"key": "holds", "type": "float"}, - "limit": {"key": "limit", "type": "float"}, - "period": {"key": "period", "type": "str"}, + 'dimension': {'key': 'dimension', 'type': 'str'}, + 'scope': {'key': 'scope', 'type': 'str'}, + 'provider_id': {'key': 'providerId', 'type': 'str'}, + 'utilization': {'key': 'utilization', 'type': 'float'}, + 'holds': {'key': 'holds', 'type': 'float'}, + 'limit': {'key': 'limit', 'type': 'float'}, + 'period': {'key': 'period', 'type': 'str'}, } def __init__(self, **kwargs): super(Quota, self).__init__(**kwargs) - self.dimension = kwargs.get("dimension", None) - self.scope = kwargs.get("scope", None) - self.provider_id = kwargs.get("provider_id", None) - self.utilization = kwargs.get("utilization", None) - self.holds = kwargs.get("holds", None) - self.limit = kwargs.get("limit", None) - self.period = kwargs.get("period", None) + self.dimension = kwargs.get('dimension', None) + self.scope = kwargs.get('scope', None) + self.provider_id = kwargs.get('provider_id', None) + self.utilization = kwargs.get('utilization', None) + self.holds = kwargs.get('holds', None) + self.limit = kwargs.get('limit', None) + self.period = kwargs.get('period', None) diff --git a/azure-quantum/azure/quantum/_client/models/quota_paged.py b/azure-quantum/azure/quantum/_client/models/quota_paged.py index 9edb6c7bb..b425263c8 100644 --- a/azure-quantum/azure/quantum/_client/models/quota_paged.py +++ b/azure-quantum/azure/quantum/_client/models/quota_paged.py @@ -18,8 +18,8 @@ class QuotaPaged(Paged): """ _attribute_map = { - "next_link": {"key": "nextLink", "type": "str"}, - "current_page": {"key": "value", "type": "[Quota]"}, + 'next_link': {'key': 'nextLink', 'type': 'str'}, + 'current_page': {'key': 'value', 'type': '[Quota]'} } def __init__(self, *args, **kwargs): diff --git a/azure-quantum/azure/quantum/_client/models/quota_py3.py b/azure-quantum/azure/quantum/_client/models/quota_py3.py index 186010738..0e7c260bc 100644 --- a/azure-quantum/azure/quantum/_client/models/quota_py3.py +++ b/azure-quantum/azure/quantum/_client/models/quota_py3.py @@ -37,27 +37,16 @@ class Quota(Model): """ _attribute_map = { - "dimension": {"key": "dimension", "type": "str"}, - "scope": {"key": "scope", "type": "str"}, - "provider_id": {"key": "providerId", "type": "str"}, - "utilization": {"key": "utilization", "type": "float"}, - "holds": {"key": "holds", "type": "float"}, - "limit": {"key": "limit", "type": "float"}, - "period": {"key": "period", "type": "str"}, + 'dimension': {'key': 'dimension', 'type': 'str'}, + 'scope': {'key': 'scope', 'type': 'str'}, + 'provider_id': {'key': 'providerId', 'type': 'str'}, + 'utilization': {'key': 'utilization', 'type': 'float'}, + 'holds': {'key': 'holds', 'type': 'float'}, + 'limit': {'key': 'limit', 'type': 'float'}, + 'period': {'key': 'period', 'type': 'str'}, } - def __init__( - self, - *, - dimension: str = None, - scope=None, - provider_id: str = None, - utilization: float = None, - holds: float = None, - limit: float = None, - period=None, - **kwargs - ) -> None: + def __init__(self, *, dimension: str=None, scope=None, provider_id: str=None, utilization: float=None, holds: float=None, limit: float=None, period=None, **kwargs) -> None: super(Quota, self).__init__(**kwargs) self.dimension = dimension self.scope = scope diff --git a/azure-quantum/azure/quantum/_client/models/rest_error.py b/azure-quantum/azure/quantum/_client/models/rest_error.py index 82acb888a..f50e5f7e5 100644 --- a/azure-quantum/azure/quantum/_client/models/rest_error.py +++ b/azure-quantum/azure/quantum/_client/models/rest_error.py @@ -21,12 +21,12 @@ class RestError(Model): """ _attribute_map = { - "error": {"key": "error", "type": "ErrorData"}, + 'error': {'key': 'error', 'type': 'ErrorData'}, } def __init__(self, **kwargs): super(RestError, self).__init__(**kwargs) - self.error = kwargs.get("error", None) + self.error = kwargs.get('error', None) class RestErrorException(HttpOperationError): @@ -38,6 +38,4 @@ class RestErrorException(HttpOperationError): def __init__(self, deserialize, response, *args): - super(RestErrorException, self).__init__( - deserialize, response, "RestError", *args - ) + super(RestErrorException, self).__init__(deserialize, response, 'RestError', *args) diff --git a/azure-quantum/azure/quantum/_client/models/rest_error_py3.py b/azure-quantum/azure/quantum/_client/models/rest_error_py3.py index 2286bfd22..f39b8fcf0 100644 --- a/azure-quantum/azure/quantum/_client/models/rest_error_py3.py +++ b/azure-quantum/azure/quantum/_client/models/rest_error_py3.py @@ -21,7 +21,7 @@ class RestError(Model): """ _attribute_map = { - "error": {"key": "error", "type": "ErrorData"}, + 'error': {'key': 'error', 'type': 'ErrorData'}, } def __init__(self, *, error=None, **kwargs) -> None: @@ -38,6 +38,4 @@ class RestErrorException(HttpOperationError): def __init__(self, deserialize, response, *args): - super(RestErrorException, self).__init__( - deserialize, response, "RestError", *args - ) + super(RestErrorException, self).__init__(deserialize, response, 'RestError', *args) diff --git a/azure-quantum/azure/quantum/_client/models/sas_uri_response.py b/azure-quantum/azure/quantum/_client/models/sas_uri_response.py index cc4fe3b3f..de48f2c42 100644 --- a/azure-quantum/azure/quantum/_client/models/sas_uri_response.py +++ b/azure-quantum/azure/quantum/_client/models/sas_uri_response.py @@ -21,9 +21,9 @@ class SasUriResponse(Model): """ _attribute_map = { - "sas_uri": {"key": "sasUri", "type": "str"}, + 'sas_uri': {'key': 'sasUri', 'type': 'str'}, } def __init__(self, **kwargs): super(SasUriResponse, self).__init__(**kwargs) - self.sas_uri = kwargs.get("sas_uri", None) + self.sas_uri = kwargs.get('sas_uri', None) diff --git a/azure-quantum/azure/quantum/_client/models/sas_uri_response_py3.py b/azure-quantum/azure/quantum/_client/models/sas_uri_response_py3.py index 277adb6cf..61e07b356 100644 --- a/azure-quantum/azure/quantum/_client/models/sas_uri_response_py3.py +++ b/azure-quantum/azure/quantum/_client/models/sas_uri_response_py3.py @@ -21,9 +21,9 @@ class SasUriResponse(Model): """ _attribute_map = { - "sas_uri": {"key": "sasUri", "type": "str"}, + 'sas_uri': {'key': 'sasUri', 'type': 'str'}, } - def __init__(self, *, sas_uri: str = None, **kwargs) -> None: + def __init__(self, *, sas_uri: str=None, **kwargs) -> None: super(SasUriResponse, self).__init__(**kwargs) self.sas_uri = sas_uri diff --git a/azure-quantum/azure/quantum/_client/models/target_status.py b/azure-quantum/azure/quantum/_client/models/target_status.py index 8ef938a7b..a97e8d6a3 100644 --- a/azure-quantum/azure/quantum/_client/models/target_status.py +++ b/azure-quantum/azure/quantum/_client/models/target_status.py @@ -31,17 +31,17 @@ class TargetStatus(Model): """ _validation = { - "id": {"readonly": True}, - "current_availability": {"readonly": True}, - "average_queue_time": {"readonly": True}, - "status_page": {"readonly": True}, + 'id': {'readonly': True}, + 'current_availability': {'readonly': True}, + 'average_queue_time': {'readonly': True}, + 'status_page': {'readonly': True}, } _attribute_map = { - "id": {"key": "id", "type": "str"}, - "current_availability": {"key": "currentAvailability", "type": "str"}, - "average_queue_time": {"key": "averageQueueTime", "type": "long"}, - "status_page": {"key": "statusPage", "type": "str"}, + 'id': {'key': 'id', 'type': 'str'}, + 'current_availability': {'key': 'currentAvailability', 'type': 'str'}, + 'average_queue_time': {'key': 'averageQueueTime', 'type': 'long'}, + 'status_page': {'key': 'statusPage', 'type': 'str'}, } def __init__(self, **kwargs): diff --git a/azure-quantum/azure/quantum/_client/models/target_status_py3.py b/azure-quantum/azure/quantum/_client/models/target_status_py3.py index bc2e9f6e4..1313de7a8 100644 --- a/azure-quantum/azure/quantum/_client/models/target_status_py3.py +++ b/azure-quantum/azure/quantum/_client/models/target_status_py3.py @@ -31,17 +31,17 @@ class TargetStatus(Model): """ _validation = { - "id": {"readonly": True}, - "current_availability": {"readonly": True}, - "average_queue_time": {"readonly": True}, - "status_page": {"readonly": True}, + 'id': {'readonly': True}, + 'current_availability': {'readonly': True}, + 'average_queue_time': {'readonly': True}, + 'status_page': {'readonly': True}, } _attribute_map = { - "id": {"key": "id", "type": "str"}, - "current_availability": {"key": "currentAvailability", "type": "str"}, - "average_queue_time": {"key": "averageQueueTime", "type": "long"}, - "status_page": {"key": "statusPage", "type": "str"}, + 'id': {'key': 'id', 'type': 'str'}, + 'current_availability': {'key': 'currentAvailability', 'type': 'str'}, + 'average_queue_time': {'key': 'averageQueueTime', 'type': 'long'}, + 'status_page': {'key': 'statusPage', 'type': 'str'}, } def __init__(self, **kwargs) -> None: diff --git a/azure-quantum/azure/quantum/_client/operations/__init__.py b/azure-quantum/azure/quantum/_client/operations/__init__.py index 9049c2d49..86281dc01 100644 --- a/azure-quantum/azure/quantum/_client/operations/__init__.py +++ b/azure-quantum/azure/quantum/_client/operations/__init__.py @@ -15,8 +15,8 @@ from .quotas_operations import QuotasOperations __all__ = [ - "JobsOperations", - "ProvidersOperations", - "StorageOperations", - "QuotasOperations", + 'JobsOperations', + 'ProvidersOperations', + 'StorageOperations', + 'QuotasOperations', ] diff --git a/azure-quantum/azure/quantum/_client/operations/jobs_operations.py b/azure-quantum/azure/quantum/_client/operations/jobs_operations.py index fdd766f30..a0d88ec04 100644 --- a/azure-quantum/azure/quantum/_client/operations/jobs_operations.py +++ b/azure-quantum/azure/quantum/_client/operations/jobs_operations.py @@ -35,7 +35,8 @@ def __init__(self, client, config, serializer, deserializer): self.config = config - def list(self, custom_headers=None, raw=False, **operation_config): + def list( + self, custom_headers=None, raw=False, **operation_config): """List jobs. :param dict custom_headers: headers that will be added to the request @@ -48,28 +49,15 @@ def list(self, custom_headers=None, raw=False, **operation_config): ~azure.quantum.models.JobDetailsPaged[~azure.quantum.models.JobDetails] :raises: :class:`CloudError` """ - def internal_paging(next_link=None, raw=False): if not next_link: # Construct URL - url = self.list.metadata["url"] + url = self.list.metadata['url'] path_format_arguments = { - "subscriptionId": self._serialize.url( - "self.config.subscription_id", - self.config.subscription_id, - "str", - ), - "resourceGroupName": self._serialize.url( - "self.config.resource_group_name", - self.config.resource_group_name, - "str", - ), - "workspaceName": self._serialize.url( - "self.config.workspace_name", - self.config.workspace_name, - "str", - ), + 'subscriptionId': self._serialize.url("self.config.subscription_id", self.config.subscription_id, 'str'), + 'resourceGroupName': self._serialize.url("self.config.resource_group_name", self.config.resource_group_name, 'str'), + 'workspaceName': self._serialize.url("self.config.workspace_name", self.config.workspace_name, 'str') } url = self._client.format_url(url, **path_format_arguments) @@ -82,52 +70,38 @@ def internal_paging(next_link=None, raw=False): # Construct headers header_parameters = {} - header_parameters["Accept"] = "application/json" + header_parameters['Accept'] = 'application/json' if self.config.generate_client_request_id: - header_parameters["x-ms-client-request-id"] = str(uuid.uuid1()) + header_parameters['x-ms-client-request-id'] = str(uuid.uuid1()) if custom_headers: header_parameters.update(custom_headers) if self.config.accept_language is not None: - header_parameters["accept-language"] = self._serialize.header( - "self.config.accept_language", - self.config.accept_language, - "str", - ) + header_parameters['accept-language'] = self._serialize.header("self.config.accept_language", self.config.accept_language, 'str') # Construct and send request - request = self._client.get( - url, query_parameters, header_parameters - ) - response = self._client.send( - request, stream=False, **operation_config - ) + request = self._client.get(url, query_parameters, header_parameters) + response = self._client.send(request, stream=False, **operation_config) if response.status_code not in [200]: exp = CloudError(response) - exp.request_id = response.headers.get("x-ms-request-id") + exp.request_id = response.headers.get('x-ms-request-id') raise exp return response # Deserialize response - deserialized = models.JobDetailsPaged( - internal_paging, self._deserialize.dependencies - ) + deserialized = models.JobDetailsPaged(internal_paging, self._deserialize.dependencies) if raw: header_dict = {} - client_raw_response = models.JobDetailsPaged( - internal_paging, self._deserialize.dependencies, header_dict - ) + client_raw_response = models.JobDetailsPaged(internal_paging, self._deserialize.dependencies, header_dict) return client_raw_response return deserialized + list.metadata = {'url': '/v1.0/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Quantum/workspaces/{workspaceName}/jobs'} - list.metadata = { - "url": "/v1.0/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Quantum/workspaces/{workspaceName}/jobs" - } - - def get(self, job_id, custom_headers=None, raw=False, **operation_config): + def get( + self, job_id, custom_headers=None, raw=False, **operation_config): """Get job by id. :param job_id: Id of the job. @@ -144,22 +118,12 @@ def get(self, job_id, custom_headers=None, raw=False, **operation_config): :class:`RestErrorException` """ # Construct URL - url = self.get.metadata["url"] + url = self.get.metadata['url'] path_format_arguments = { - "subscriptionId": self._serialize.url( - "self.config.subscription_id", - self.config.subscription_id, - "str", - ), - "resourceGroupName": self._serialize.url( - "self.config.resource_group_name", - self.config.resource_group_name, - "str", - ), - "workspaceName": self._serialize.url( - "self.config.workspace_name", self.config.workspace_name, "str" - ), - "jobId": self._serialize.url("job_id", job_id, "str"), + 'subscriptionId': self._serialize.url("self.config.subscription_id", self.config.subscription_id, 'str'), + 'resourceGroupName': self._serialize.url("self.config.resource_group_name", self.config.resource_group_name, 'str'), + 'workspaceName': self._serialize.url("self.config.workspace_name", self.config.workspace_name, 'str'), + 'jobId': self._serialize.url("job_id", job_id, 'str') } url = self._client.format_url(url, **path_format_arguments) @@ -168,17 +132,13 @@ def get(self, job_id, custom_headers=None, raw=False, **operation_config): # Construct headers header_parameters = {} - header_parameters["Accept"] = "application/json" + header_parameters['Accept'] = 'application/json' if self.config.generate_client_request_id: - header_parameters["x-ms-client-request-id"] = str(uuid.uuid1()) + header_parameters['x-ms-client-request-id'] = str(uuid.uuid1()) if custom_headers: header_parameters.update(custom_headers) if self.config.accept_language is not None: - header_parameters["accept-language"] = self._serialize.header( - "self.config.accept_language", - self.config.accept_language, - "str", - ) + header_parameters['accept-language'] = self._serialize.header("self.config.accept_language", self.config.accept_language, 'str') # Construct and send request request = self._client.get(url, query_parameters, header_parameters) @@ -190,21 +150,17 @@ def get(self, job_id, custom_headers=None, raw=False, **operation_config): deserialized = None if response.status_code == 200: - deserialized = self._deserialize("JobDetails", response) + deserialized = self._deserialize('JobDetails', response) if raw: client_raw_response = ClientRawResponse(deserialized, response) return client_raw_response return deserialized - - get.metadata = { - "url": "/v1.0/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Quantum/workspaces/{workspaceName}/jobs/{jobId}" - } + get.metadata = {'url': '/v1.0/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Quantum/workspaces/{workspaceName}/jobs/{jobId}'} def create( - self, job_id, job, custom_headers=None, raw=False, **operation_config - ): + self, job_id, job, custom_headers=None, raw=False, **operation_config): """Create a job. :param job_id: Id of the job. @@ -223,22 +179,12 @@ def create( :class:`RestErrorException` """ # Construct URL - url = self.create.metadata["url"] + url = self.create.metadata['url'] path_format_arguments = { - "subscriptionId": self._serialize.url( - "self.config.subscription_id", - self.config.subscription_id, - "str", - ), - "resourceGroupName": self._serialize.url( - "self.config.resource_group_name", - self.config.resource_group_name, - "str", - ), - "workspaceName": self._serialize.url( - "self.config.workspace_name", self.config.workspace_name, "str" - ), - "jobId": self._serialize.url("job_id", job_id, "str"), + 'subscriptionId': self._serialize.url("self.config.subscription_id", self.config.subscription_id, 'str'), + 'resourceGroupName': self._serialize.url("self.config.resource_group_name", self.config.resource_group_name, 'str'), + 'workspaceName': self._serialize.url("self.config.workspace_name", self.config.workspace_name, 'str'), + 'jobId': self._serialize.url("job_id", job_id, 'str') } url = self._client.format_url(url, **path_format_arguments) @@ -247,26 +193,20 @@ def create( # Construct headers header_parameters = {} - header_parameters["Accept"] = "application/json" - header_parameters["Content-Type"] = "application/json; charset=utf-8" + header_parameters['Accept'] = 'application/json' + header_parameters['Content-Type'] = 'application/json; charset=utf-8' if self.config.generate_client_request_id: - header_parameters["x-ms-client-request-id"] = str(uuid.uuid1()) + header_parameters['x-ms-client-request-id'] = str(uuid.uuid1()) if custom_headers: header_parameters.update(custom_headers) if self.config.accept_language is not None: - header_parameters["accept-language"] = self._serialize.header( - "self.config.accept_language", - self.config.accept_language, - "str", - ) + header_parameters['accept-language'] = self._serialize.header("self.config.accept_language", self.config.accept_language, 'str') # Construct body - body_content = self._serialize.body(job, "JobDetails") + body_content = self._serialize.body(job, 'JobDetails') # Construct and send request - request = self._client.put( - url, query_parameters, header_parameters, body_content - ) + request = self._client.put(url, query_parameters, header_parameters, body_content) response = self._client.send(request, stream=False, **operation_config) if response.status_code not in [200, 201]: @@ -275,23 +215,19 @@ def create( deserialized = None if response.status_code == 200: - deserialized = self._deserialize("JobDetails", response) + deserialized = self._deserialize('JobDetails', response) if response.status_code == 201: - deserialized = self._deserialize("JobDetails", response) + deserialized = self._deserialize('JobDetails', response) if raw: client_raw_response = ClientRawResponse(deserialized, response) return client_raw_response return deserialized - - create.metadata = { - "url": "/v1.0/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Quantum/workspaces/{workspaceName}/jobs/{jobId}" - } + create.metadata = {'url': '/v1.0/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Quantum/workspaces/{workspaceName}/jobs/{jobId}'} def cancel( - self, job_id, custom_headers=None, raw=False, **operation_config - ): + self, job_id, custom_headers=None, raw=False, **operation_config): """Cancel a job. :param job_id: Id of the job. @@ -307,22 +243,12 @@ def cancel( :class:`RestErrorException` """ # Construct URL - url = self.cancel.metadata["url"] + url = self.cancel.metadata['url'] path_format_arguments = { - "subscriptionId": self._serialize.url( - "self.config.subscription_id", - self.config.subscription_id, - "str", - ), - "resourceGroupName": self._serialize.url( - "self.config.resource_group_name", - self.config.resource_group_name, - "str", - ), - "workspaceName": self._serialize.url( - "self.config.workspace_name", self.config.workspace_name, "str" - ), - "jobId": self._serialize.url("job_id", job_id, "str"), + 'subscriptionId': self._serialize.url("self.config.subscription_id", self.config.subscription_id, 'str'), + 'resourceGroupName': self._serialize.url("self.config.resource_group_name", self.config.resource_group_name, 'str'), + 'workspaceName': self._serialize.url("self.config.workspace_name", self.config.workspace_name, 'str'), + 'jobId': self._serialize.url("job_id", job_id, 'str') } url = self._client.format_url(url, **path_format_arguments) @@ -332,15 +258,11 @@ def cancel( # Construct headers header_parameters = {} if self.config.generate_client_request_id: - header_parameters["x-ms-client-request-id"] = str(uuid.uuid1()) + header_parameters['x-ms-client-request-id'] = str(uuid.uuid1()) if custom_headers: header_parameters.update(custom_headers) if self.config.accept_language is not None: - header_parameters["accept-language"] = self._serialize.header( - "self.config.accept_language", - self.config.accept_language, - "str", - ) + header_parameters['accept-language'] = self._serialize.header("self.config.accept_language", self.config.accept_language, 'str') # Construct and send request request = self._client.delete(url, query_parameters, header_parameters) @@ -352,7 +274,4 @@ def cancel( if raw: client_raw_response = ClientRawResponse(None, response) return client_raw_response - - cancel.metadata = { - "url": "/v1.0/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Quantum/workspaces/{workspaceName}/jobs/{jobId}" - } + cancel.metadata = {'url': '/v1.0/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Quantum/workspaces/{workspaceName}/jobs/{jobId}'} diff --git a/azure-quantum/azure/quantum/_client/operations/providers_operations.py b/azure-quantum/azure/quantum/_client/operations/providers_operations.py index d234c43ef..0835a2dd0 100644 --- a/azure-quantum/azure/quantum/_client/operations/providers_operations.py +++ b/azure-quantum/azure/quantum/_client/operations/providers_operations.py @@ -34,7 +34,8 @@ def __init__(self, client, config, serializer, deserializer): self.config = config - def get_status(self, custom_headers=None, raw=False, **operation_config): + def get_status( + self, custom_headers=None, raw=False, **operation_config): """Get provider status. :param dict custom_headers: headers that will be added to the request @@ -48,28 +49,15 @@ def get_status(self, custom_headers=None, raw=False, **operation_config): :raises: :class:`RestErrorException` """ - def internal_paging(next_link=None, raw=False): if not next_link: # Construct URL - url = self.get_status.metadata["url"] + url = self.get_status.metadata['url'] path_format_arguments = { - "subscriptionId": self._serialize.url( - "self.config.subscription_id", - self.config.subscription_id, - "str", - ), - "resourceGroupName": self._serialize.url( - "self.config.resource_group_name", - self.config.resource_group_name, - "str", - ), - "workspaceName": self._serialize.url( - "self.config.workspace_name", - self.config.workspace_name, - "str", - ), + 'subscriptionId': self._serialize.url("self.config.subscription_id", self.config.subscription_id, 'str'), + 'resourceGroupName': self._serialize.url("self.config.resource_group_name", self.config.resource_group_name, 'str'), + 'workspaceName': self._serialize.url("self.config.workspace_name", self.config.workspace_name, 'str') } url = self._client.format_url(url, **path_format_arguments) @@ -82,25 +70,17 @@ def internal_paging(next_link=None, raw=False): # Construct headers header_parameters = {} - header_parameters["Accept"] = "application/json" + header_parameters['Accept'] = 'application/json' if self.config.generate_client_request_id: - header_parameters["x-ms-client-request-id"] = str(uuid.uuid1()) + header_parameters['x-ms-client-request-id'] = str(uuid.uuid1()) if custom_headers: header_parameters.update(custom_headers) if self.config.accept_language is not None: - header_parameters["accept-language"] = self._serialize.header( - "self.config.accept_language", - self.config.accept_language, - "str", - ) + header_parameters['accept-language'] = self._serialize.header("self.config.accept_language", self.config.accept_language, 'str') # Construct and send request - request = self._client.get( - url, query_parameters, header_parameters - ) - response = self._client.send( - request, stream=False, **operation_config - ) + request = self._client.get(url, query_parameters, header_parameters) + response = self._client.send(request, stream=False, **operation_config) if response.status_code not in [200]: raise models.RestErrorException(self._deserialize, response) @@ -108,19 +88,12 @@ def internal_paging(next_link=None, raw=False): return response # Deserialize response - deserialized = models.ProviderStatusPaged( - internal_paging, self._deserialize.dependencies - ) + deserialized = models.ProviderStatusPaged(internal_paging, self._deserialize.dependencies) if raw: header_dict = {} - client_raw_response = models.ProviderStatusPaged( - internal_paging, self._deserialize.dependencies, header_dict - ) + client_raw_response = models.ProviderStatusPaged(internal_paging, self._deserialize.dependencies, header_dict) return client_raw_response return deserialized - - get_status.metadata = { - "url": "/v1.0/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Quantum/workspaces/{workspaceName}/providerStatus" - } + get_status.metadata = {'url': '/v1.0/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Quantum/workspaces/{workspaceName}/providerStatus'} diff --git a/azure-quantum/azure/quantum/_client/operations/quotas_operations.py b/azure-quantum/azure/quantum/_client/operations/quotas_operations.py index 00e103b4a..dfc59b10e 100644 --- a/azure-quantum/azure/quantum/_client/operations/quotas_operations.py +++ b/azure-quantum/azure/quantum/_client/operations/quotas_operations.py @@ -34,7 +34,8 @@ def __init__(self, client, config, serializer, deserializer): self.config = config - def list(self, custom_headers=None, raw=False, **operation_config): + def list( + self, custom_headers=None, raw=False, **operation_config): """List quotas for the given workspace. :param dict custom_headers: headers that will be added to the request @@ -47,28 +48,15 @@ def list(self, custom_headers=None, raw=False, **operation_config): :raises: :class:`RestErrorException` """ - def internal_paging(next_link=None, raw=False): if not next_link: # Construct URL - url = self.list.metadata["url"] + url = self.list.metadata['url'] path_format_arguments = { - "subscriptionId": self._serialize.url( - "self.config.subscription_id", - self.config.subscription_id, - "str", - ), - "resourceGroupName": self._serialize.url( - "self.config.resource_group_name", - self.config.resource_group_name, - "str", - ), - "workspaceName": self._serialize.url( - "self.config.workspace_name", - self.config.workspace_name, - "str", - ), + 'subscriptionId': self._serialize.url("self.config.subscription_id", self.config.subscription_id, 'str'), + 'resourceGroupName': self._serialize.url("self.config.resource_group_name", self.config.resource_group_name, 'str'), + 'workspaceName': self._serialize.url("self.config.workspace_name", self.config.workspace_name, 'str') } url = self._client.format_url(url, **path_format_arguments) @@ -81,25 +69,17 @@ def internal_paging(next_link=None, raw=False): # Construct headers header_parameters = {} - header_parameters["Accept"] = "application/json" + header_parameters['Accept'] = 'application/json' if self.config.generate_client_request_id: - header_parameters["x-ms-client-request-id"] = str(uuid.uuid1()) + header_parameters['x-ms-client-request-id'] = str(uuid.uuid1()) if custom_headers: header_parameters.update(custom_headers) if self.config.accept_language is not None: - header_parameters["accept-language"] = self._serialize.header( - "self.config.accept_language", - self.config.accept_language, - "str", - ) + header_parameters['accept-language'] = self._serialize.header("self.config.accept_language", self.config.accept_language, 'str') # Construct and send request - request = self._client.get( - url, query_parameters, header_parameters - ) - response = self._client.send( - request, stream=False, **operation_config - ) + request = self._client.get(url, query_parameters, header_parameters) + response = self._client.send(request, stream=False, **operation_config) if response.status_code not in [200]: raise models.RestErrorException(self._deserialize, response) @@ -107,19 +87,12 @@ def internal_paging(next_link=None, raw=False): return response # Deserialize response - deserialized = models.QuotaPaged( - internal_paging, self._deserialize.dependencies - ) + deserialized = models.QuotaPaged(internal_paging, self._deserialize.dependencies) if raw: header_dict = {} - client_raw_response = models.QuotaPaged( - internal_paging, self._deserialize.dependencies, header_dict - ) + client_raw_response = models.QuotaPaged(internal_paging, self._deserialize.dependencies, header_dict) return client_raw_response return deserialized - - list.metadata = { - "url": "/v1.0/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Quantum/workspaces/{workspaceName}/quotas" - } + list.metadata = {'url': '/v1.0/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Quantum/workspaces/{workspaceName}/quotas'} diff --git a/azure-quantum/azure/quantum/_client/operations/storage_operations.py b/azure-quantum/azure/quantum/_client/operations/storage_operations.py index 964eed1f3..eabe621c2 100644 --- a/azure-quantum/azure/quantum/_client/operations/storage_operations.py +++ b/azure-quantum/azure/quantum/_client/operations/storage_operations.py @@ -35,8 +35,7 @@ def __init__(self, client, config, serializer, deserializer): self.config = config def sas_uri( - self, blob_details, custom_headers=None, raw=False, **operation_config - ): + self, blob_details, custom_headers=None, raw=False, **operation_config): """Gets a URL with SAS token for a container/blob in the storage account associated with the workspace. The SAS URL can be used to upload job input and/or download job output. @@ -56,21 +55,11 @@ def sas_uri( :class:`RestErrorException` """ # Construct URL - url = self.sas_uri.metadata["url"] + url = self.sas_uri.metadata['url'] path_format_arguments = { - "subscriptionId": self._serialize.url( - "self.config.subscription_id", - self.config.subscription_id, - "str", - ), - "resourceGroupName": self._serialize.url( - "self.config.resource_group_name", - self.config.resource_group_name, - "str", - ), - "workspaceName": self._serialize.url( - "self.config.workspace_name", self.config.workspace_name, "str" - ), + 'subscriptionId': self._serialize.url("self.config.subscription_id", self.config.subscription_id, 'str'), + 'resourceGroupName': self._serialize.url("self.config.resource_group_name", self.config.resource_group_name, 'str'), + 'workspaceName': self._serialize.url("self.config.workspace_name", self.config.workspace_name, 'str') } url = self._client.format_url(url, **path_format_arguments) @@ -79,26 +68,20 @@ def sas_uri( # Construct headers header_parameters = {} - header_parameters["Accept"] = "application/json" - header_parameters["Content-Type"] = "application/json; charset=utf-8" + header_parameters['Accept'] = 'application/json' + header_parameters['Content-Type'] = 'application/json; charset=utf-8' if self.config.generate_client_request_id: - header_parameters["x-ms-client-request-id"] = str(uuid.uuid1()) + header_parameters['x-ms-client-request-id'] = str(uuid.uuid1()) if custom_headers: header_parameters.update(custom_headers) if self.config.accept_language is not None: - header_parameters["accept-language"] = self._serialize.header( - "self.config.accept_language", - self.config.accept_language, - "str", - ) + header_parameters['accept-language'] = self._serialize.header("self.config.accept_language", self.config.accept_language, 'str') # Construct body - body_content = self._serialize.body(blob_details, "BlobDetails") + body_content = self._serialize.body(blob_details, 'BlobDetails') # Construct and send request - request = self._client.post( - url, query_parameters, header_parameters, body_content - ) + request = self._client.post(url, query_parameters, header_parameters, body_content) response = self._client.send(request, stream=False, **operation_config) if response.status_code not in [200]: @@ -107,14 +90,11 @@ def sas_uri( deserialized = None if response.status_code == 200: - deserialized = self._deserialize("SasUriResponse", response) + deserialized = self._deserialize('SasUriResponse', response) if raw: client_raw_response = ClientRawResponse(deserialized, response) return client_raw_response return deserialized - - sas_uri.metadata = { - "url": "/v1.0/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Quantum/workspaces/{workspaceName}/storage/sasUri" - } + sas_uri.metadata = {'url': '/v1.0/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Quantum/workspaces/{workspaceName}/storage/sasUri'} diff --git a/azure-quantum/azure/quantum/_client/quantum_client.py b/azure-quantum/azure/quantum/_client/quantum_client.py index 05eec42d5..7cef055b3 100644 --- a/azure-quantum/azure/quantum/_client/quantum_client.py +++ b/azure-quantum/azure/quantum/_client/quantum_client.py @@ -39,31 +39,23 @@ class QuantumClientConfiguration(AzureConfiguration): """ def __init__( - self, - credentials, - subscription_id, - resource_group_name, - workspace_name, - base_url=None, - ): + self, credentials, subscription_id, resource_group_name, workspace_name, base_url=None): if credentials is None: raise ValueError("Parameter 'credentials' must not be None.") if subscription_id is None: raise ValueError("Parameter 'subscription_id' must not be None.") if resource_group_name is None: - raise ValueError( - "Parameter 'resource_group_name' must not be None." - ) + raise ValueError("Parameter 'resource_group_name' must not be None.") if workspace_name is None: raise ValueError("Parameter 'workspace_name' must not be None.") if not base_url: - base_url = "https://quantum.azure.com" + base_url = 'https://quantum.azure.com' super(QuantumClientConfiguration, self).__init__(base_url) - self.add_user_agent("quantumclient/{}".format(VERSION)) - self.add_user_agent("Azure-SDK-For-Python") + self.add_user_agent('quantumclient/{}'.format(VERSION)) + self.add_user_agent('Azure-SDK-For-Python') self.credentials = credentials self.subscription_id = subscription_id @@ -100,41 +92,21 @@ class QuantumClient(SDKClient): """ def __init__( - self, - credentials, - subscription_id, - resource_group_name, - workspace_name, - base_url=None, - ): - - self.config = QuantumClientConfiguration( - credentials, - subscription_id, - resource_group_name, - workspace_name, - base_url, - ) - super(QuantumClient, self).__init__( - self.config.credentials, self.config - ) - - client_models = { - k: v for k, v in models.__dict__.items() if isinstance(v, type) - } - self.api_version = "2019-11-04-preview" + self, credentials, subscription_id, resource_group_name, workspace_name, base_url=None): + + self.config = QuantumClientConfiguration(credentials, subscription_id, resource_group_name, workspace_name, base_url) + super(QuantumClient, self).__init__(self.config.credentials, self.config) + + client_models = {k: v for k, v in models.__dict__.items() if isinstance(v, type)} + self.api_version = '2019-11-04-preview' self._serialize = Serializer(client_models) self._deserialize = Deserializer(client_models) self.jobs = JobsOperations( - self._client, self.config, self._serialize, self._deserialize - ) + self._client, self.config, self._serialize, self._deserialize) self.providers = ProvidersOperations( - self._client, self.config, self._serialize, self._deserialize - ) + self._client, self.config, self._serialize, self._deserialize) self.storage = StorageOperations( - self._client, self.config, self._serialize, self._deserialize - ) + self._client, self.config, self._serialize, self._deserialize) self.quotas = QuotasOperations( - self._client, self.config, self._serialize, self._deserialize - ) + self._client, self.config, self._serialize, self._deserialize) diff --git a/azure-quantum/azure/quantum/_client/version.py b/azure-quantum/azure/quantum/_client/version.py index f40ff0f3b..f85b9c124 100644 --- a/azure-quantum/azure/quantum/_client/version.py +++ b/azure-quantum/azure/quantum/_client/version.py @@ -10,3 +10,4 @@ # -------------------------------------------------------------------------- VERSION = "2019-11-04-preview" + From e68e221feae34e6b0b63ee754f04972a930fb441 Mon Sep 17 00:00:00 2001 From: Sanjana Gupta <42555338+sanjgupt@users.noreply.github.com> Date: Mon, 10 May 2021 09:33:35 -0700 Subject: [PATCH 19/21] nit --- azure-quantum/azure/quantum/optimization/toshiba/solvers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azure-quantum/azure/quantum/optimization/toshiba/solvers.py b/azure-quantum/azure/quantum/optimization/toshiba/solvers.py index c6827a1c4..eb62e4f50 100644 --- a/azure-quantum/azure/quantum/optimization/toshiba/solvers.py +++ b/azure-quantum/azure/quantum/optimization/toshiba/solvers.py @@ -34,7 +34,7 @@ def __init__( Goto, H., Tatsumura, K., & Dixon, A. R. (2019) Combinatorial optimization by simulating adiabatic bifurcations in nonlinear Hamiltonian systems, Science Advances, - 5(4), DOI:10.1126/sciadv.aav2372 + 5(4), DOI:10.1126/sciadv.aav2372 :param steps: The number of steps in a computation request. The default is 0. From 342f43040daa979714d399a13c5944ff38efe77c Mon Sep 17 00:00:00 2001 From: Sanjana Gupta <42555338+sanjgupt@users.noreply.github.com> Date: Mon, 10 May 2021 10:11:10 -0700 Subject: [PATCH 20/21] commneting out onliune problem code till OnlineProblem can be made available in the qdk --- azure-quantum/tests/unit/test_online_problem.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/azure-quantum/tests/unit/test_online_problem.py b/azure-quantum/tests/unit/test_online_problem.py index ab5c2493b..dbd9b5d73 100644 --- a/azure-quantum/tests/unit/test_online_problem.py +++ b/azure-quantum/tests/unit/test_online_problem.py @@ -6,7 +6,7 @@ # Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. ## - +''' import unittest from unittest.mock import Mock from typing import TYPE_CHECKING @@ -36,3 +36,4 @@ def test_download(self): assert acutal_result.name == "test" azure.quantum.optimization.problem.download_blob.assert_called_once() assert isinstance(acutal_result, Problem) +''' \ No newline at end of file From bad76994e8e022956c8e856a2fa393cd49efbc14 Mon Sep 17 00:00:00 2001 From: Sanjana Gupta <42555338+sanjgupt@users.noreply.github.com> Date: Mon, 10 May 2021 10:59:40 -0700 Subject: [PATCH 21/21] nit --- azure-quantum/azure/quantum/optimization/toshiba/solvers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azure-quantum/azure/quantum/optimization/toshiba/solvers.py b/azure-quantum/azure/quantum/optimization/toshiba/solvers.py index eb62e4f50..c6827a1c4 100644 --- a/azure-quantum/azure/quantum/optimization/toshiba/solvers.py +++ b/azure-quantum/azure/quantum/optimization/toshiba/solvers.py @@ -34,7 +34,7 @@ def __init__( Goto, H., Tatsumura, K., & Dixon, A. R. (2019) Combinatorial optimization by simulating adiabatic bifurcations in nonlinear Hamiltonian systems, Science Advances, - 5(4), DOI:10.1126/sciadv.aav2372 + 5(4), DOI:10.1126/sciadv.aav2372 :param steps: The number of steps in a computation request. The default is 0.