Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
63 commits
Select commit Hold shift + click to select a range
70bbafa
Add new python client
Dec 5, 2024
313f376
Add first round of pagincation cod
Dec 6, 2024
a8f7794
Add first unit test
Dec 9, 2024
5912919
Add unit test
Dec 9, 2024
398b3ec
fix a bug
Dec 9, 2024
fb3280a
update tests
Dec 11, 2024
6b4c106
Simplify code
Dec 11, 2024
33101fa
update tests
Dec 13, 2024
ef10b52
add test case
Dec 13, 2024
50cb510
remove unused file
Dec 13, 2024
f73c83f
add a new record
Dec 13, 2024
fe66995
Add a test
Dec 17, 2024
1f672f6
add another test
Dec 17, 2024
6ce272f
combine test
Dec 17, 2024
9c615b7
Add another test
Dec 17, 2024
e5972c2
Add a test
Dec 17, 2024
09f2699
Add a test
Dec 17, 2024
ecefa1d
Add a test
Dec 17, 2024
3c1dfd0
Add a test
Dec 17, 2024
c3bd4aa
Add a test
Dec 17, 2024
a8f77e0
Add a test
Dec 17, 2024
0383ab5
Add a test
Dec 17, 2024
f24bd1f
Add a test
Dec 17, 2024
2c32956
Add a test
Dec 17, 2024
5b1cd6b
Add a test
Dec 17, 2024
28c7020
Add a test
Dec 17, 2024
1f7c0b2
Add a test
Dec 17, 2024
7793a18
Add a test
Dec 17, 2024
2e87622
Add a test
Dec 17, 2024
6d85b2f
Add a test
Dec 17, 2024
c0f9b8a
Add a test
Dec 17, 2024
67a0af6
Add a test
Dec 17, 2024
f595d69
Add a test
Dec 17, 2024
7dad4e1
Add a test
Dec 17, 2024
221c7b1
Add a test
Dec 17, 2024
6cda6cf
Add a test
Dec 17, 2024
e58ed3a
Add a test
Dec 17, 2024
3293dfa
Add a test
Dec 17, 2024
d37554f
Add a test
Dec 17, 2024
0f3e63a
Add a test
Dec 17, 2024
006b785
Add a test
Dec 17, 2024
b356358
Add a test
Dec 17, 2024
57053fa
Add keyword restriction
Feb 3, 2025
e574685
rename pagesize to top
Feb 3, 2025
d89d06c
Add unit tests
Feb 6, 2025
16c907e
Merge remote-tracking branch 'origin/main' into guyi/AddPagination
Feb 6, 2025
8903565
update tests
Feb 7, 2025
f93c5fb
update tests
Feb 7, 2025
5d2ddd1
Merge remote-tracking branch 'origin/main' into guyi/AddPagination
Feb 12, 2025
3a1debf
limit package version
Feb 12, 2025
10f993e
limit package version
Feb 12, 2025
2cd1e15
update
Feb 14, 2025
c5a4fbd
update tests
Feb 15, 2025
a9655ea
update datetime
Feb 15, 2025
3e4ab7d
update recording and readme
Feb 18, 2025
93a0c39
update unit tests
Feb 18, 2025
f712c63
update length count
Feb 19, 2025
f42f3e0
update unit test
Feb 21, 2025
872fdd2
update unit test
Feb 21, 2025
d4254be
remove aio folder
Feb 21, 2025
7c65799
Merge branch 'main' into guyi/AddPagination
04diiguyi Feb 21, 2025
4c3fdb9
Merge branch 'main' into guyi/AddPagination
04diiguyi Feb 21, 2025
a76449e
Merge branch 'main' into guyi/AddPagination
04diiguyi Feb 26, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 79 additions & 7 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,18 +67,90 @@ To read more about how to create and update recordings for testing code that int

Before merging your code contribution to `main`, make sure that all new code is covered by unit tests and that the unit tests have up-to-date recordings. If you recorded your tests and then updated or refactored the code afterwards, remember to re-record the tests.

### Update/re-generate the Azure Quantum internal SDK client based on Swagger ###
### Update/re-generate the Azure Quantum internal SDK client ###

The internal Azure Quantum Python SDK client (`azure/quantum/_client`) needs to be re-generated every time there is a change in the [Azure Quantum Service API definition](https://github.com/Azure/azure-rest-api-specs/tree/main/specification/quantum/data-plane) (aka Swagger).

To re-generate the client based on the latest published API definition simply run the following PowerShell script
#### Prerequisites
Python 3.8 or later is required

```powershell
./eng/Generate-DataPlane-Client.ps1
```
> See the Generate-DataPlane-Client.ps1 script for more options
linux

sudo apt install python3

sudo apt install python3-pip

sudo apt install python3.{?}-venv explicitly if needed

Node.js 18.3 LTS or later is required

#### Setup your repo
Fork and clone the azure-sdk-for-python repo (we call it's name SDK repo and it's absolute path)

Create a branch in SDK repo to work in

Make sure your typespec definition is merged into main branch of public rest repo (we call it rest repo) or you already make a PR in rest repo so that you could get the github link of your typespec definition which contains commit id (e.g. https://github.com/Azure/azure-rest-api-specs/blob/46ca83821edd120552403d4d11cf1dd22360c0b5/specification/contosowidgetmanager/Contoso.WidgetManager/tspconfig.yaml)

#### Project service name and package name
Two key pieces of information for your project are the service_name and package_name.

The service_name is the short name for the Azure service. The service_name should match across all the SDK language repos and should be name of the directory in the specification folder of the azure-rest-api-specs repo that contains the REST API definition file. An example is Service Bus, whose API definitions are in the specification/servicebus folder of the azure-rest-api-specs repo, and uses the service_name "servicebus". Not every service follows this convention, but it should be the standard unless there are strong reasons to deviate.

In Python, a project's package name is the name used to publish the package in PyPI. For data plane libraries (management plane uses a different convention), the package_name could be just azure-{service_name}. An example is "azure-servicebus".

Some services may need several different packages. For these cases a third component, the module_name, is added to the package_name, as azure-{service_name}-{module_name}. The module_name usually comes from the name of the REST API file itself or one of the directories toward the end of the file path. An example is the Synapse service, with packages azure-synapse, azure-synapse-accesscontrol, azure-synapse-artifacts, etc.

#### Project folder structure
Before we start, we probably should get to know the project folder for SDK repo.

Normally, the folder structure would be something like:

sdk/{service_name}/{package_name}: the PROJECT_ROOT folder
/azure/{service_name}/{module_name} : folder where generated code is.
/tests: folder of test files
/samples: folder of sample files
azure-{service_name}-{module_name}: package name. Usually, package name is same with part of ${PROJECT_ROOT} folder. After release, you can find it in pypi. For example: you can find azure-messaging-webpubsubservice in pypi.
there are also some other files (like setup.py, README.md, etc.) which are necessary for a complete package.
More details on the structure of Azure SDK repos is available in the Azure SDK common repo.

#### How to generate SDK code with Dataplane Codegen
We are working on to automatically generate everything right now, but currently we still need some manual work to get a releasable package. Here're the steps of how to get the package.

1. Configure python emitter in tspconfig.yaml
In rest repo, there shall be tspconfig.yaml where main.tsp of your service is. Make sure there are configuration for Python SDK like:

parameters:
"service-dir":
default: "YOUR_SERVICE_DIRECTORY"

emit: [
"@azure-tools/typespec-autorest", // this value does not affect python code generation
]

options:
"@azure-tools/typespec-python":
package-dir: "YOUR_PACKAGE_NAME"
package-name: "{package-dir}"
flavor: "azure"
YOUR_PACKAGE_NAME is your package name; YOUR_SERVICE_DIRECTORY is SDK directory name. For example, assume that package name is "azure-ai-anomalydetector" and you want to put it in folder "azure-sdk-for-python/sdk/anomalydetector", then "YOUR_PACKAGE_NAME" is "azure-ai-anomalydetector" and "YOUR_SERVICE_DIRECTORY" is "sdk/anomalydetector"

2. Run cmd to generate the SDK
Install tsp-client CLI tool:

npm install -g @azure-tools/typespec-client-generator-cli
For initial set up, from the root of the SDK repo, call:

D:\dev\azure-sdk-for-python> tsp-client init -c YOUR_REMOTE_TSPCONFIG_URL
An example of YOUR_REMOTE_TSPCONFIG_URL is https://github.com/Azure/azure-rest-api-specs/blob/46ca83821edd120552403d4d11cf1dd22360c0b5/specification/contosowidgetmanager/Contoso.WidgetManager/tspconfig.yaml

To update your TypeSpec generated SDK, go to your SDK folder where your tsp-location.yaml is located, call:

D:\dev\azure-sdk-for-python\sdk\contoso\azure-contoso-widget> tox run -e generate -c ..\..\..\eng\tox\tox.ini --root .
Note: To know more about tox, read our contributing guidelines

The tox run -e generate call will look for a tsp-location.yaml file in your local directory. tsp-location.yaml contains the configuration information that will be used to sync your TypeSpec project and generate your SDK. Please make sure that the commit is targeting the correct TypeSpec project updates you wish to generate your SDK from.

After re-generating the client make sure to:
#### After re-generating the client make sure to:

1. Re-run/Re-record all unit tests against the live-service (you can run `./eng/Record-Tests.ps1`)
1. If necessary, adjust the convenience layer for breaking-changes or to expose new features
Expand Down
16 changes: 11 additions & 5 deletions azure-quantum/azure/quantum/_client/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,31 @@
# --------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
# Code generated by Microsoft (R) AutoRest Code Generator.
# Code generated by Microsoft (R) Python Code Generator.
# Changes may cause incorrect behavior and will be lost if the code is regenerated.
# --------------------------------------------------------------------------
# pylint: disable=wrong-import-position

from ._client import QuantumClient
from typing import TYPE_CHECKING

if TYPE_CHECKING:
from ._patch import * # pylint: disable=unused-wildcard-import

from ._client import ServicesClient # type: ignore
from ._version import VERSION

__version__ = VERSION

try:
from ._patch import __all__ as _patch_all
from ._patch import * # pylint: disable=unused-wildcard-import
from ._patch import *
except ImportError:
_patch_all = []
from ._patch import patch_sdk as _patch_sdk

__all__ = [
"QuantumClient",
"ServicesClient",
]
__all__.extend([p for p in _patch_all if p not in __all__])
__all__.extend([p for p in _patch_all if p not in __all__]) # pyright: ignore

_patch_sdk()
89 changes: 40 additions & 49 deletions azure-quantum/azure/quantum/_client/_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,20 @@
# --------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
# Code generated by Microsoft (R) AutoRest Code Generator.
# Code generated by Microsoft (R) Python Code Generator.
# Changes may cause incorrect behavior and will be lost if the code is regenerated.
# --------------------------------------------------------------------------

from copy import deepcopy
from typing import Any, TYPE_CHECKING
from typing import Any, TYPE_CHECKING, Union
from typing_extensions import Self

from azure.core import PipelineClient
from azure.core.credentials import AzureKeyCredential
from azure.core.pipeline import policies
from azure.core.rest import HttpRequest, HttpResponse

from . import models as _models
from ._configuration import QuantumClientConfiguration
from ._configuration import ServicesClientConfiguration
from ._serialization import Deserializer, Serializer
from .operations import (
JobsOperations,
Expand All @@ -26,59 +27,50 @@
)

if TYPE_CHECKING:
# pylint: disable=unused-import,ungrouped-imports
from azure.core.credentials import TokenCredential


class QuantumClient: # pylint: disable=client-accepts-api-version-keyword
"""Azure Quantum REST API client.
class ServicesClient:
"""Azure Quantum Workspace Services.

:ivar jobs: JobsOperations operations
:vartype jobs: azure.quantum._client.operations.JobsOperations
:vartype jobs: azure.quantum.operations.JobsOperations
:ivar sessions: SessionsOperations operations
:vartype sessions: azure.quantum.operations.SessionsOperations
:ivar providers: ProvidersOperations operations
:vartype providers: azure.quantum._client.operations.ProvidersOperations
:vartype providers: azure.quantum.operations.ProvidersOperations
:ivar storage: StorageOperations operations
:vartype storage: azure.quantum._client.operations.StorageOperations
:vartype storage: azure.quantum.operations.StorageOperations
:ivar quotas: QuotasOperations operations
:vartype quotas: azure.quantum._client.operations.QuotasOperations
:ivar sessions: SessionsOperations operations
:vartype sessions: azure.quantum._client.operations.SessionsOperations
:vartype quotas: azure.quantum.operations.QuotasOperations
:ivar top_level_items: TopLevelItemsOperations operations
:vartype top_level_items: azure.quantum._client.operations.TopLevelItemsOperations
:param azure_region: Supported Azure regions for Azure Quantum Services. For example, "eastus".
Required.
:type azure_region: str
:param subscription_id: The Azure subscription ID. This is a GUID-formatted string (e.g.
00000000-0000-0000-0000-000000000000). Required.
:type subscription_id: str
:param resource_group_name: Name of an Azure resource group. Required.
:type resource_group_name: str
:param workspace_name: Name of the workspace. Required.
:type workspace_name: str
:param credential: Credential needed for the client to connect to Azure. Required.
:type credential: ~azure.core.credentials.TokenCredential
:keyword api_version: Api Version. Default value is "2023-11-13-preview". Note that overriding
this default value may result in unsupported behavior.
:vartype top_level_items: azure.quantum.operations.TopLevelItemsOperations
:param region: The Azure region where the Azure Quantum Workspace is located. Required.
:type region: str
:param credential: Credential used to authenticate requests to the service. Is either a
TokenCredential type or a AzureKeyCredential type. Required.
:type credential: ~azure.core.credentials.TokenCredential or
~azure.core.credentials.AzureKeyCredential
:keyword service_base_url: The Azure Quantum service base url. Default value is
"quantum.azure.com".
:paramtype service_base_url: str
:keyword api_version: The API version to use for this operation. Default value is
"2024-10-01-preview". Note that overriding this default value may result in unsupported
behavior.
:paramtype api_version: str
"""

def __init__(
self,
azure_region: str,
subscription_id: str,
resource_group_name: str,
workspace_name: str,
credential: "TokenCredential",
region: str,
credential: Union["TokenCredential", AzureKeyCredential],
*,
service_base_url: str = "quantum.azure.com",
**kwargs: Any
) -> None:
_endpoint = kwargs.pop("endpoint", f"https://{azure_region}.quantum.azure.com")
self._config = QuantumClientConfiguration(
azure_region=azure_region,
subscription_id=subscription_id,
resource_group_name=resource_group_name,
workspace_name=workspace_name,
credential=credential,
**kwargs
_endpoint = "https://{region}.{serviceBaseUrl}"
self._config = ServicesClientConfiguration(
region=region, credential=credential, service_base_url=service_base_url, **kwargs
)
_policies = kwargs.pop("policies", None)
if _policies is None:
Expand All @@ -99,16 +91,14 @@ def __init__(
]
self._client: PipelineClient = PipelineClient(base_url=_endpoint, policies=_policies, **kwargs)

client_models = {k: v for k, v in _models._models.__dict__.items() if isinstance(v, type)}
client_models.update({k: v for k, v in _models.__dict__.items() if isinstance(v, type)})
self._serialize = Serializer(client_models)
self._deserialize = Deserializer(client_models)
self._serialize = Serializer()
self._deserialize = Deserializer()
self._serialize.client_side_validation = False
self.jobs = JobsOperations(self._client, self._config, self._serialize, self._deserialize)
self.sessions = SessionsOperations(self._client, self._config, self._serialize, self._deserialize)
self.providers = ProvidersOperations(self._client, self._config, self._serialize, self._deserialize)
self.storage = StorageOperations(self._client, self._config, self._serialize, self._deserialize)
self.quotas = QuotasOperations(self._client, self._config, self._serialize, self._deserialize)
self.sessions = SessionsOperations(self._client, self._config, self._serialize, self._deserialize)
self.top_level_items = TopLevelItemsOperations(self._client, self._config, self._serialize, self._deserialize)

def send_request(self, request: HttpRequest, *, stream: bool = False, **kwargs: Any) -> HttpResponse:
Expand All @@ -131,8 +121,9 @@ def send_request(self, request: HttpRequest, *, stream: bool = False, **kwargs:

request_copy = deepcopy(request)
path_format_arguments = {
"azureRegion": self._serialize.url(
"self._config.azure_region", self._config.azure_region, "str", skip_quote=True
"region": self._serialize.url("self._config.region", self._config.region, "str"),
"serviceBaseUrl": self._serialize.url(
"self._config.service_base_url", self._config.service_base_url, "str"
),
}

Expand All @@ -142,7 +133,7 @@ def send_request(self, request: HttpRequest, *, stream: bool = False, **kwargs:
def close(self) -> None:
self._client.close()

def __enter__(self) -> "QuantumClient":
def __enter__(self) -> Self:
self._client.__enter__()
return self

Expand Down
Loading
Loading