Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions ChangeLog.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ Modelerfour version: 4.13.351
- We have added a `--credential-default-policy-type` flag. Its default value is `BearerTokenCredentialPolicy`, but it can also accept
`AzureKeyCredentialPolicy`. The value passed in will be the default authentication policy in the client's config, so users using the
generated library will use that auth policy unless they pass in a separate one through kwargs #686
- Added support for a data plane multiapi client #693

### 2020-06-08 - 5.1.0-preview.2
Modelerfour version: 4.13.351
Expand Down
7 changes: 6 additions & 1 deletion autorest/codegen/templates/metadata.json.jinja2
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
{% import 'operation_tools.jinja2' as op_tools %}
{% import 'keywords.jinja2' as keywords %}
{
"chosen_version": {{ chosen_version | tojson }},
"total_api_version_list": {{ total_api_version_list | tojson }},
"client": {
"name": {{ code_model.class_name | tojson }},
"filename": {{ ("_" + code_model.module_name) | tojson }},
"description": {{ code_model.description | tojson }}
"description": {{ code_model.description | tojson }},
{% set base_url = code_model.base_url if code_model.base_url else ('https://management.azure.com' if code_model.options["azure_arm"] else None )%}
"base_url": {{ (keywords.escape_str(base_url) if base_url else None) | tojson }},
"custom_base_url": {{ (keywords.escape_str(code_model.custom_base_url) if code_model.custom_base_url else None) | tojson }},
"azure_arm": {{ code_model.options["azure_arm"] | tojson }}
},
"global_parameters": {
"sync_method": {
Expand Down
5 changes: 4 additions & 1 deletion autorest/multiapi/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -364,7 +364,10 @@ def process(self) -> bool:
"config": metadata_json["config"],
"global_parameters": metadata_json["global_parameters"],
"sync_imports": str(FileImportSerializer(sync_imports, is_python_3_file=False)),
"async_imports": str(FileImportSerializer(async_imports, is_python_3_file=True))
"async_imports": str(FileImportSerializer(async_imports, is_python_3_file=True)),
"base_url": metadata_json["client"]["base_url"],
"custom_base_url": metadata_json["client"]["custom_base_url"],
"azure_arm": metadata_json["client"]["azure_arm"]
}

multiapi_serializer = MultiAPISerializer(
Expand Down
29 changes: 17 additions & 12 deletions autorest/multiapi/templates/multiapi_service_client.py.jinja2
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,11 @@ def __init__(
{# actual template starts here #}
{% set config_import = "._configuration_async" if async_mode else "._configuration" %}
{% set operations_mixin_import = "._operations_mixin_async" if async_mode else "._operations_mixin" %}
{% set pipeline_client = "AsyncARMPipelineClient" if async_mode else "ARMPipelineClient" %}
{% set pipeline_client = "ARMPipelineClient" if azure_arm else "PipelineClient" %}
{% set relative_path = ".." if async_mode else "." %}
{% set def = "async def" if async_mode else "def" %}
{% set async_prefix = "a" if async_mode else "" %}
{% set async_prefix = "Async" if async_mode else "" %}
{% set a_prefix = "a" if async_mode else "" %}
{% set await = "await " if async_mode else "" %}
# coding=utf-8
# --------------------------------------------------------------------------
Expand All @@ -36,7 +37,7 @@ def __init__(
# regenerated.
# --------------------------------------------------------------------------

from azure.mgmt.core import {{ pipeline_client }}
from azure.{{ "mgmt." if azure_arm }}core import {{ async_prefix }}{{ pipeline_client }}
from msrest import Serializer, Deserializer

from azure.profiles import KnownProfiles, ProfileDefinition
Expand Down Expand Up @@ -70,7 +71,9 @@ class {{ client_name }}({% if mixin_operations %}{{ client_name }}OperationsMixi
{% endfor %}
:param str api_version: API version to use if no profile is provided, or if
missing in profile.
{% if not custom_base_url %}
:param str base_url: Service URL
{% endif %}
:param profile: A profile definition, from KnownProfiles to dict.
:type profile: azure.profiles.KnownProfiles
:keyword int polling_interval: Default waiting time between two polls for LRO operations if no Retry-After header is present.
Expand All @@ -90,13 +93,15 @@ class {{ client_name }}({% if mixin_operations %}{{ client_name }}OperationsMixi
)

{{ method_signature()|indent }}
{% if not base_url %}
base_url = {{ custom_base_url }}
{% else %}
if not base_url:
base_url = 'https://management.azure.com'
self._config = {{ client_name }}Configuration({{ global_parameters["call"] }}, **kwargs)
self._client = {{ pipeline_client }}(base_url=base_url, config=self._config, **kwargs)
base_url = {{ base_url }}
{% endif %}
self._config = {{ client_name }}Configuration({{ global_parameters["call"] }}{{ ", " if global_parameters["call"] }}**kwargs)
self._client = {{ async_prefix }}{{ pipeline_client }}(base_url=base_url, config=self._config, **kwargs)
super({{ client_name }}, self).__init__(
credential,
self._config,
api_version=api_version,
profile=profile
)
Expand Down Expand Up @@ -143,8 +148,8 @@ class {{ client_name }}({% if mixin_operations %}{{ client_name }}OperationsMixi

{{ def }} close(self):
{{ await }}self._client.close()
{{ def }} __{{ async_prefix }}enter__(self):
{{ await }}self._client.__{{ async_prefix }}enter__()
{{ def }} __{{ a_prefix }}enter__(self):
{{ await }}self._client.__{{ a_prefix }}enter__()
return self
{{ def }} __{{ async_prefix }}exit__(self, *exc_details):
{{ await }}self._client.__{{ async_prefix }}exit__(*exc_details)
{{ def }} __{{ a_prefix }}exit__(self, *exc_details):
{{ await }}self._client.__{{ a_prefix }}exit__(*exc_details)
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
},
"devDependencies": {
"@autorest/autorest": "^3.0.0",
"@microsoft.azure/autorest.testserver": "^2.10.43"
"@microsoft.azure/autorest.testserver": "^2.10.44"
},
"files": [
"autorest/**/*.py",
Expand Down
4 changes: 3 additions & 1 deletion tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,9 @@ def regenerate_multiapi(c, debug=False, swagger_name="test"):
# create multiapi client with no aio folder (package-name=multiapinoasync)
"test/multiapi/specification/multiapinoasync/README.md",
# create multiapi client with AzureKeyCredentialPolicy
"test/multiapi/specification/multiapicredentialdefaultpolicy/README.md"
"test/multiapi/specification/multiapicredentialdefaultpolicy/README.md",
# create multiapi client data plane
"test/multiapi/specification/multiapidataplane/README.md"
]

cmds = [_multiapi_command_line(spec) for spec in available_specifications if swagger_name.lower() in spec]
Expand Down
5 changes: 5 additions & 0 deletions test/multiapi/AcceptanceTests/asynctests/test_multiapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import inspect
import json
from azure.profiles import KnownProfiles
from azure.mgmt.core import AsyncARMPipelineClient
from .multiapi_base import NotTested


Expand Down Expand Up @@ -68,5 +69,9 @@ def test_configuration_kwargs(default_client):
# making sure that the package name is correct in the sdk moniker
assert default_client._config.user_agent_policy._user_agent.startswith("azsdk-python-multiapi/")

def test_pipeline_client(default_client):
# assert the pipeline client is AsyncARMPipelineClient from azure.mgmt.core, since this is mgmt plane
assert type(default_client._client) == AsyncARMPipelineClient

class TestMultiapiClient(NotTested.TestMultiapiBase):
pass
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
# --------------------------------------------------------------------------
#
# Copyright (c) Microsoft Corporation. All rights reserved.
#
# The MIT License (MIT)
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the ""Software""), to
# deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.
#
# --------------------------------------------------------------------------
from async_generator import yield_, async_generator
import pytest
import inspect
import json
from azure.profiles import KnownProfiles
from azure.core import AsyncPipelineClient
from .multiapi_base import NotTested


@pytest.fixture
@async_generator
async def default_client(credential, authentication_policy):
from multiapidataplane.aio import MultiapiServiceClient
async with MultiapiServiceClient(
base_url="http://localhost:3000",
credential=credential,
authentication_policy=authentication_policy
) as default_client:
await yield_(default_client)

@pytest.fixture
@async_generator
async def client(credential, authentication_policy, api_version):
from multiapidataplane.aio import MultiapiServiceClient

async with MultiapiServiceClient(
base_url="http://localhost:3000",
api_version=api_version,
credential=credential,
authentication_policy=authentication_policy
) as client:
await yield_(client)

@pytest.fixture
def namespace_models():
from multiapidataplane import models
return models

@pytest.mark.parametrize('api_version', ["2.0.0"])
def test_specify_api_version_multiapi_client(client):
assert client.profile.label == "multiapidataplane.MultiapiServiceClient 2.0.0"

def test_configuration_kwargs(default_client):
# making sure that the package name is correct in the sdk moniker
assert default_client._config.user_agent_policy._user_agent.startswith("azsdk-python-multiapidataplane/")

def test_pipeline_client(default_client):
# assert the pipeline client is AsyncPipelineClient from azure.core, since this is data plane
assert type(default_client._client) == AsyncPipelineClient

class TestMultiapiClient(NotTested.TestMultiapiBase):
pass
5 changes: 5 additions & 0 deletions test/multiapi/AcceptanceTests/test_multiapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import pytest
import inspect
import json
from azure.mgmt.core import ARMPipelineClient
from azure.profiles import KnownProfiles
from .multiapi_base import NotTested

Expand Down Expand Up @@ -69,6 +70,10 @@ def test_configuration_kwargs(default_client):
def test_patch_file():
from multiapi.models import PatchAddedModel

def test_pipeline_client(default_client):
# assert the pipeline client is ARMPipelineClient from azure.mgmt.core, since this is mgmt plane
assert type(default_client._client) == ARMPipelineClient

class TestMultiapiClient(NotTested.TestMultiapiBase):
pass

76 changes: 76 additions & 0 deletions test/multiapi/AcceptanceTests/test_multiapi_data_plane.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
# --------------------------------------------------------------------------
#
# Copyright (c) Microsoft Corporation. All rights reserved.
#
# The MIT License (MIT)
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the ""Software""), to
# deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.
#
# --------------------------------------------------------------------------
import pytest
import inspect
import json
from azure.profiles import KnownProfiles
from azure.core import PipelineClient
from .multiapi_base import NotTested


@pytest.fixture
def default_client(credential, authentication_policy):
from multiapidataplane import MultiapiServiceClient
with MultiapiServiceClient(
base_url="http://localhost:3000",
credential=credential,
authentication_policy=authentication_policy
) as default_client:
yield default_client

@pytest.fixture
def client(credential, authentication_policy, api_version):
from multiapidataplane import MultiapiServiceClient

with MultiapiServiceClient(
base_url="http://localhost:3000",
api_version=api_version,
credential=credential,
authentication_policy=authentication_policy
) as client:
yield client

@pytest.fixture
def namespace_models():
from multiapidataplane import models
return models


@pytest.mark.parametrize('api_version', ["2.0.0"])
def test_specify_api_version_multiapi_client(client):
assert client.profile.label == "multiapidataplane.MultiapiServiceClient 2.0.0"

def test_configuration_kwargs(default_client):
# making sure that the package name is correct in the sdk moniker
assert default_client._config.user_agent_policy._user_agent.startswith("azsdk-python-multiapidataplane/")

def test_pipeline_client(default_client):
# assert the pipeline client is PipelineClient from azure.core, since this is data plane
assert type(default_client._client) == PipelineClient

class TestMultiapiClient(NotTested.TestMultiapiBase):
pass

Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ def __init__(
super(MultiapiServiceClientConfiguration, self).__init__(**kwargs)

self.credential = credential
self.credential_scopes = []
self.credential_scopes = ['https://management.azure.com/.default']
self.credential_scopes.extend(kwargs.pop('credential_scopes', []))
kwargs.setdefault('sdk_moniker', 'multiapi/{}'.format(VERSION))
self._configure(**kwargs)
Expand All @@ -55,7 +55,5 @@ def _configure(
self.custom_hook_policy = kwargs.get('custom_hook_policy') or policies.CustomHookPolicy(**kwargs)
self.redirect_policy = kwargs.get('redirect_policy') or policies.RedirectPolicy(**kwargs)
self.authentication_policy = kwargs.get('authentication_policy')
if not self.credential_scopes and not self.authentication_policy:
raise ValueError("You must provide either credential_scopes or authentication_policy as kwargs")
if self.credential and not self.authentication_policy:
self.authentication_policy = policies.BearerTokenCredentialPolicy(self.credential, *self.credential_scopes, **kwargs)
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,10 @@ def __init__(
**kwargs # type: Any
):
if not base_url:
base_url = 'https://management.azure.com'
base_url = 'http://localhost:3000'
self._config = MultiapiServiceClientConfiguration(credential, **kwargs)
self._client = ARMPipelineClient(base_url=base_url, config=self._config, **kwargs)
super(MultiapiServiceClient, self).__init__(
credential,
self._config,
api_version=api_version,
profile=profile
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
from azure.core.pipeline import PipelineResponse
from azure.core.pipeline.transport import HttpRequest, HttpResponse
from azure.core.polling import LROPoller, NoPolling, PollingMethod
from azure.core.polling.base_polling import LROBasePolling
from azure.mgmt.core.exceptions import ARMErrorFormat
from azure.mgmt.core.polling.arm_polling import ARMPolling

if TYPE_CHECKING:
# pylint: disable=unused-import,ungrouped-imports
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ def __init__(
super(MultiapiServiceClientConfiguration, self).__init__(**kwargs)

self.credential = credential
self.credential_scopes = []
self.credential_scopes = ['https://management.azure.com/.default']
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reason for these mgmt changes in the old multiapi generation, is because I incorrectly had the flag as azure, and have fixed it to be azure-arm

self.credential_scopes.extend(kwargs.pop('credential_scopes', []))
kwargs.setdefault('sdk_moniker', 'multiapi/{}'.format(VERSION))
self._configure(**kwargs)
Expand All @@ -54,7 +54,5 @@ def _configure(
self.custom_hook_policy = kwargs.get('custom_hook_policy') or policies.CustomHookPolicy(**kwargs)
self.redirect_policy = kwargs.get('redirect_policy') or policies.AsyncRedirectPolicy(**kwargs)
self.authentication_policy = kwargs.get('authentication_policy')
if not self.credential_scopes and not self.authentication_policy:
raise ValueError("You must provide either credential_scopes or authentication_policy as kwargs")
if self.credential and not self.authentication_policy:
self.authentication_policy = policies.AsyncBearerTokenCredentialPolicy(self.credential, *self.credential_scopes, **kwargs)
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,10 @@ def __init__(
**kwargs # type: Any
) -> None:
if not base_url:
base_url = 'https://management.azure.com'
base_url = 'http://localhost:3000'
self._config = MultiapiServiceClientConfiguration(credential, **kwargs)
self._client = AsyncARMPipelineClient(base_url=base_url, config=self._config, **kwargs)
super(MultiapiServiceClient, self).__init__(
credential,
self._config,
api_version=api_version,
profile=profile
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
from azure.core.pipeline import PipelineResponse
from azure.core.pipeline.transport import AsyncHttpResponse, HttpRequest
from azure.core.polling import AsyncLROPoller, AsyncNoPolling, AsyncPollingMethod
from azure.core.polling.async_base_polling import AsyncLROBasePolling
from azure.mgmt.core.exceptions import ARMErrorFormat
from azure.mgmt.core.polling.async_arm_polling import AsyncARMPolling


class MultiapiServiceClientOperationsMixin(object):
Expand Down
Loading