@typespec/http-client-python 0.9.3-dev.2 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +19 -36
- package/dist/emitter/emitter.js +40 -0
- package/dist/emitter/emitter.js.map +1 -1
- package/dist/emitter/http.js +5 -2
- package/dist/emitter/http.js.map +1 -1
- package/dist/emitter/utils.d.ts.map +1 -1
- package/dist/emitter/utils.js +9 -1
- package/dist/emitter/utils.js.map +1 -1
- package/emitter/src/emitter.ts +46 -0
- package/emitter/src/http.ts +12 -2
- package/emitter/src/utils.ts +11 -1
- package/emitter/temp/tsconfig.tsbuildinfo +1 -1
- package/eng/scripts/setup/__pycache__/venvtools.cpython-39.pyc +0 -0
- package/eng/scripts/setup/install.py +1 -0
- package/eng/scripts/setup/run_tsp.py +2 -3
- package/generator/build/lib/pygen/codegen/models/client.py +39 -2
- package/generator/build/lib/pygen/codegen/models/parameter.py +3 -0
- package/generator/build/lib/pygen/codegen/serializers/client_serializer.py +32 -6
- package/generator/build/lib/pygen/codegen/serializers/general_serializer.py +28 -14
- package/generator/build/lib/pygen/codegen/serializers/parameter_serializer.py +6 -1
- package/generator/build/lib/pygen/codegen/serializers/sample_serializer.py +2 -2
- package/generator/build/lib/pygen/codegen/templates/client.py.jinja2 +1 -1
- package/generator/build/lib/pygen/codegen/templates/config.py.jinja2 +2 -8
- package/generator/component-detection-pip-report.json +4 -5
- package/generator/dist/pygen-0.1.0-py3-none-any.whl +0 -0
- package/generator/pygen/codegen/models/client.py +39 -2
- package/generator/pygen/codegen/models/parameter.py +3 -0
- package/generator/pygen/codegen/serializers/client_serializer.py +32 -6
- package/generator/pygen/codegen/serializers/general_serializer.py +28 -14
- package/generator/pygen/codegen/serializers/parameter_serializer.py +6 -1
- package/generator/pygen/codegen/serializers/sample_serializer.py +2 -2
- package/generator/pygen/codegen/templates/client.py.jinja2 +1 -1
- package/generator/pygen/codegen/templates/config.py.jinja2 +2 -8
- package/generator/test/azure/mock_api_tests/asynctests/test_azure_client_generator_core_client_initialization_async.py +50 -0
- package/generator/test/azure/mock_api_tests/test_azure_client_generator_core_client_initialization.py +44 -0
- package/generator/test/azure/requirements.txt +4 -3
- package/generator/test/generic_mock_api_tests/asynctests/test_parameters_path_async.py +24 -0
- package/generator/test/generic_mock_api_tests/asynctests/test_payload_json_merge_patch_async.py +1 -1
- package/generator/test/generic_mock_api_tests/test_parameters_path.py +22 -0
- package/generator/test/generic_mock_api_tests/test_payload_json_merge_patch.py +1 -1
- package/generator/test/unbranded/requirements.txt +1 -0
- package/package.json +5 -5
|
@@ -15,7 +15,7 @@ from .request_builder import (
|
|
|
15
15
|
OverloadedRequestBuilder,
|
|
16
16
|
get_request_builder,
|
|
17
17
|
)
|
|
18
|
-
from .parameter import Parameter, ParameterMethodLocation
|
|
18
|
+
from .parameter import Parameter, ParameterMethodLocation, ParameterLocation
|
|
19
19
|
from .lro_operation import LROOperation
|
|
20
20
|
from .lro_paging_operation import LROPagingOperation
|
|
21
21
|
from ...utils import extract_original_name, NAME_LENGTH_LIMIT
|
|
@@ -54,7 +54,7 @@ class _ClientConfigBase(Generic[ParameterListType], BaseModel):
|
|
|
54
54
|
return self.yaml_data["name"]
|
|
55
55
|
|
|
56
56
|
|
|
57
|
-
class Client(_ClientConfigBase[ClientGlobalParameterList]):
|
|
57
|
+
class Client(_ClientConfigBase[ClientGlobalParameterList]): # pylint: disable=too-many-public-methods
|
|
58
58
|
"""Model representing our service client"""
|
|
59
59
|
|
|
60
60
|
def __init__(
|
|
@@ -79,6 +79,27 @@ class Client(_ClientConfigBase[ClientGlobalParameterList]):
|
|
|
79
79
|
self.request_id_header_name = self.yaml_data.get("requestIdHeaderName", None)
|
|
80
80
|
self.has_etag: bool = yaml_data.get("hasEtag", False)
|
|
81
81
|
|
|
82
|
+
# update the host parameter value. In later logic, SDK will overwrite it
|
|
83
|
+
# with value from cloud_setting if users don't provide it.
|
|
84
|
+
if self.need_cloud_setting:
|
|
85
|
+
for p in self.parameters.parameters:
|
|
86
|
+
if p.location == ParameterLocation.ENDPOINT_PATH:
|
|
87
|
+
p.client_default_value = None
|
|
88
|
+
p.optional = True
|
|
89
|
+
break
|
|
90
|
+
|
|
91
|
+
@property
|
|
92
|
+
def need_cloud_setting(self) -> bool:
|
|
93
|
+
return bool(
|
|
94
|
+
self.code_model.options.get("azure_arm", False)
|
|
95
|
+
and self.credential_scopes is not None
|
|
96
|
+
and self.endpoint_parameter is not None
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
@property
|
|
100
|
+
def endpoint_parameter(self) -> Optional[Parameter]:
|
|
101
|
+
return next((p for p in self.parameters.parameters if p.location == ParameterLocation.ENDPOINT_PATH), None)
|
|
102
|
+
|
|
82
103
|
def _build_request_builders(
|
|
83
104
|
self,
|
|
84
105
|
) -> List[Union[RequestBuilder, OverloadedRequestBuilder]]:
|
|
@@ -233,6 +254,10 @@ class Client(_ClientConfigBase[ClientGlobalParameterList]):
|
|
|
233
254
|
"Self",
|
|
234
255
|
ImportType.STDLIB,
|
|
235
256
|
)
|
|
257
|
+
if self.need_cloud_setting:
|
|
258
|
+
file_import.add_submodule_import("typing", "cast", ImportType.STDLIB)
|
|
259
|
+
file_import.add_submodule_import("azure.core.settings", "settings", ImportType.SDKCORE)
|
|
260
|
+
file_import.add_submodule_import("azure.mgmt.core.tools", "get_arm_endpoints", ImportType.SDKCORE)
|
|
236
261
|
return file_import
|
|
237
262
|
|
|
238
263
|
@property
|
|
@@ -332,6 +357,18 @@ class Client(_ClientConfigBase[ClientGlobalParameterList]):
|
|
|
332
357
|
)
|
|
333
358
|
return file_import
|
|
334
359
|
|
|
360
|
+
@property
|
|
361
|
+
def credential_scopes(self) -> Optional[List[str]]:
|
|
362
|
+
"""Credential scopes for this client"""
|
|
363
|
+
|
|
364
|
+
if self.credential:
|
|
365
|
+
if hasattr(getattr(self.credential.type, "policy", None), "credential_scopes"):
|
|
366
|
+
return self.credential.type.policy.credential_scopes # type: ignore
|
|
367
|
+
for t in getattr(self.credential.type, "types", []):
|
|
368
|
+
if hasattr(getattr(t, "policy", None), "credential_scopes"):
|
|
369
|
+
return t.policy.credential_scopes
|
|
370
|
+
return None
|
|
371
|
+
|
|
335
372
|
@classmethod
|
|
336
373
|
def from_yaml(
|
|
337
374
|
cls,
|
|
@@ -357,6 +357,9 @@ class Parameter(_ParameterBase):
|
|
|
357
357
|
)
|
|
358
358
|
if self.code_model.options["only_path_and_body_params_positional"] and query_or_header:
|
|
359
359
|
return ParameterMethodLocation.KEYWORD_ONLY
|
|
360
|
+
# for optional path parameter, we need to use keyword only
|
|
361
|
+
if self.location == ParameterLocation.PATH and self.optional:
|
|
362
|
+
return ParameterMethodLocation.KEYWORD_ONLY
|
|
360
363
|
return ParameterMethodLocation.POSITIONAL
|
|
361
364
|
|
|
362
365
|
@classmethod
|
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
# Licensed under the MIT License. See License.txt in the project root for
|
|
4
4
|
# license information.
|
|
5
5
|
# --------------------------------------------------------------------------
|
|
6
|
-
from typing import List
|
|
6
|
+
from typing import List, cast
|
|
7
7
|
|
|
8
8
|
from . import utils
|
|
9
|
-
from ..models import Client, ParameterMethodLocation
|
|
9
|
+
from ..models import Client, ParameterMethodLocation, Parameter, ParameterLocation
|
|
10
10
|
from .parameter_serializer import ParameterSerializer, PopKwargType
|
|
11
11
|
from ...utils import build_policies
|
|
12
12
|
|
|
@@ -77,17 +77,40 @@ class ClientSerializer:
|
|
|
77
77
|
retval.append('"""')
|
|
78
78
|
return retval
|
|
79
79
|
|
|
80
|
-
def initialize_config(self) -> str:
|
|
80
|
+
def initialize_config(self) -> List[str]:
|
|
81
|
+
retval = []
|
|
82
|
+
additional_signatures = []
|
|
83
|
+
if self.client.need_cloud_setting:
|
|
84
|
+
additional_signatures.append("credential_scopes=credential_scopes")
|
|
85
|
+
endpoint_parameter = cast(Parameter, self.client.endpoint_parameter)
|
|
86
|
+
retval.extend(
|
|
87
|
+
[
|
|
88
|
+
'_cloud = kwargs.pop("cloud_setting", None) or settings.current.azure_cloud # type: ignore',
|
|
89
|
+
"_endpoints = get_arm_endpoints(_cloud)",
|
|
90
|
+
f"if not {endpoint_parameter.client_name}:",
|
|
91
|
+
f' {endpoint_parameter.client_name} = _endpoints["resource_manager"]',
|
|
92
|
+
'credential_scopes = kwargs.pop("credential_scopes", _endpoints["credential_scopes"])',
|
|
93
|
+
]
|
|
94
|
+
)
|
|
81
95
|
config_name = f"{self.client.name}Configuration"
|
|
82
96
|
config_call = ", ".join(
|
|
83
97
|
[
|
|
84
|
-
|
|
98
|
+
(
|
|
99
|
+
f"{p.client_name}="
|
|
100
|
+
+ (
|
|
101
|
+
f"cast(str, {p.client_name})"
|
|
102
|
+
if self.client.need_cloud_setting and p.location == ParameterLocation.ENDPOINT_PATH
|
|
103
|
+
else p.client_name
|
|
104
|
+
)
|
|
105
|
+
)
|
|
85
106
|
for p in self.client.config.parameters.method
|
|
86
107
|
if p.method_location != ParameterMethodLocation.KWARG
|
|
87
108
|
]
|
|
109
|
+
+ additional_signatures
|
|
88
110
|
+ ["**kwargs"]
|
|
89
111
|
)
|
|
90
|
-
|
|
112
|
+
retval.append(f"self._config = {config_name}({config_call})")
|
|
113
|
+
return retval
|
|
91
114
|
|
|
92
115
|
@property
|
|
93
116
|
def host_variable_name(self) -> str:
|
|
@@ -104,8 +127,11 @@ class ClientSerializer:
|
|
|
104
127
|
result = []
|
|
105
128
|
pipeline_client_name = self.client.pipeline_class(async_mode)
|
|
106
129
|
endpoint_name = "base_url" if self.client.code_model.is_azure_flavor else "endpoint"
|
|
130
|
+
host_variable_name = (
|
|
131
|
+
f"cast(str, {self.host_variable_name})" if self.client.need_cloud_setting else self.host_variable_name
|
|
132
|
+
)
|
|
107
133
|
params = {
|
|
108
|
-
endpoint_name:
|
|
134
|
+
endpoint_name: host_variable_name,
|
|
109
135
|
"policies": "_policies",
|
|
110
136
|
}
|
|
111
137
|
if not self.client.code_model.is_legacy and self.client.request_id_header_name:
|
|
@@ -19,7 +19,7 @@ from .base_serializer import BaseSerializer
|
|
|
19
19
|
VERSION_MAP = {
|
|
20
20
|
"msrest": "0.7.1",
|
|
21
21
|
"isodate": "0.6.1",
|
|
22
|
-
"azure-mgmt-core": "1.
|
|
22
|
+
"azure-mgmt-core": "1.5.0",
|
|
23
23
|
"azure-core": "1.30.0",
|
|
24
24
|
"typing-extensions": "4.6.0",
|
|
25
25
|
"corehttp": "1.0.0b6",
|
|
@@ -225,19 +225,33 @@ class GeneralSerializer(BaseSerializer):
|
|
|
225
225
|
if not enum.internal
|
|
226
226
|
}
|
|
227
227
|
)
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
228
|
+
for client in self.code_model.clients:
|
|
229
|
+
for operation_group in client.operation_groups:
|
|
230
|
+
for operation in operation_group.operations:
|
|
231
|
+
if operation.name.startswith("_"):
|
|
232
|
+
continue
|
|
233
|
+
cross_langauge_def_dict.update(
|
|
234
|
+
{
|
|
235
|
+
f"{self.code_model.namespace}."
|
|
236
|
+
+ (
|
|
237
|
+
f"{client.name}."
|
|
238
|
+
if operation_group.is_mixin
|
|
239
|
+
else f"operations.{operation_group.class_name}."
|
|
240
|
+
)
|
|
241
|
+
+ f"{operation.name}": operation.cross_language_definition_id
|
|
242
|
+
}
|
|
243
|
+
)
|
|
244
|
+
cross_langauge_def_dict.update(
|
|
245
|
+
{
|
|
246
|
+
f"{self.code_model.namespace}.aio."
|
|
247
|
+
+ (
|
|
248
|
+
f"{client.name}."
|
|
249
|
+
if operation_group.is_mixin
|
|
250
|
+
else f"operations.{operation_group.class_name}."
|
|
251
|
+
)
|
|
252
|
+
+ f"{operation.name}": operation.cross_language_definition_id
|
|
253
|
+
}
|
|
254
|
+
)
|
|
241
255
|
return json.dumps(
|
|
242
256
|
{
|
|
243
257
|
"CrossLanguagePackageId": self.code_model.cross_language_package_id,
|
|
@@ -109,6 +109,7 @@ class ParameterSerializer:
|
|
|
109
109
|
return f"[{serialize_line} if q is not None else '' for q in {origin_name}]"
|
|
110
110
|
return serialize_line
|
|
111
111
|
|
|
112
|
+
# pylint: disable=line-too-long
|
|
112
113
|
def serialize_path(
|
|
113
114
|
self,
|
|
114
115
|
parameters: Union[
|
|
@@ -124,7 +125,11 @@ class ParameterSerializer:
|
|
|
124
125
|
[
|
|
125
126
|
' "{}": {},'.format(
|
|
126
127
|
path_parameter.wire_name,
|
|
127
|
-
|
|
128
|
+
(
|
|
129
|
+
f'"" if {path_parameter.full_client_name} is None else "/" + {self.serialize_parameter(path_parameter, serializer_name)}'
|
|
130
|
+
if path_parameter.optional and isinstance(path_parameter, RequestBuilderParameter)
|
|
131
|
+
else self.serialize_parameter(path_parameter, serializer_name)
|
|
132
|
+
),
|
|
128
133
|
)
|
|
129
134
|
for path_parameter in parameters
|
|
130
135
|
]
|
|
@@ -62,7 +62,7 @@ class SampleSerializer(BaseSerializer):
|
|
|
62
62
|
ImportType.SDKCORE,
|
|
63
63
|
)
|
|
64
64
|
for param in self.operation.parameters.positional + self.operation.parameters.keyword_only:
|
|
65
|
-
if
|
|
65
|
+
if param.client_default_value is None and not param.optional and param.wire_name in self.sample_params:
|
|
66
66
|
imports.merge(param.type.imports_for_sample())
|
|
67
67
|
return FileImportSerializer(imports, True)
|
|
68
68
|
|
|
@@ -80,7 +80,7 @@ class SampleSerializer(BaseSerializer):
|
|
|
80
80
|
for p in (
|
|
81
81
|
self.code_model.clients[0].parameters.positional + self.code_model.clients[0].parameters.keyword_only
|
|
82
82
|
)
|
|
83
|
-
if not
|
|
83
|
+
if not p.optional and p.client_default_value is None
|
|
84
84
|
]
|
|
85
85
|
client_params = {
|
|
86
86
|
p.client_name: special_param.get(
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
{% if client.has_parameterized_host %}
|
|
10
10
|
{{ serializer.host_variable_name }} = {{ keywords.escape_str(client.url) }}
|
|
11
11
|
{% endif %}
|
|
12
|
-
{{ serializer.initialize_config() }}
|
|
12
|
+
{{ op_tools.serialize(serializer.initialize_config()) | indent(8) }}
|
|
13
13
|
{{ op_tools.serialize(serializer.initialize_pipeline_client(async_mode)) | indent(8) }}
|
|
14
14
|
|
|
15
15
|
{{ op_tools.serialize(serializer.serializers_and_operation_groups_properties()) | indent(8) }}
|
|
@@ -21,14 +21,8 @@ class {{ client.name }}Configuration: {{ client.config.pylint_disable() }}
|
|
|
21
21
|
{% if serializer.set_constants() %}
|
|
22
22
|
{{ op_tools.serialize(serializer.set_constants()) | indent(8) -}}
|
|
23
23
|
{% endif %}
|
|
24
|
-
{% if client.
|
|
25
|
-
|
|
26
|
-
{% if not cred_scopes %}
|
|
27
|
-
{% set cred_scopes = client.credential.type.types | selectattr("policy.credential_scopes") | first if client.credential.type.types is defined %}
|
|
28
|
-
{% endif %}
|
|
29
|
-
{% if cred_scopes %}
|
|
30
|
-
self.credential_scopes = kwargs.pop('credential_scopes', {{ cred_scopes.policy.credential_scopes }})
|
|
31
|
-
{% endif %}
|
|
24
|
+
{% if client.credential_scopes is not none %}
|
|
25
|
+
self.credential_scopes = kwargs.pop('credential_scopes', {{ client.credential_scopes }})
|
|
32
26
|
{% endif %}
|
|
33
27
|
kwargs.setdefault('sdk_moniker', '{{ client.config.sdk_moniker }}/{}'.format(VERSION))
|
|
34
28
|
self.polling_interval = kwargs.get("polling_interval", 30)
|
|
@@ -4,11 +4,11 @@
|
|
|
4
4
|
"install": [
|
|
5
5
|
{
|
|
6
6
|
"download_info": {
|
|
7
|
-
"url": "https://files.pythonhosted.org/packages/
|
|
7
|
+
"url": "https://files.pythonhosted.org/packages/cc/ea/d53f2f8897c46a36df085964d07761ea4c2d1f2cf92019693b6742b7aabb/setuptools-79.0.0-py3-none-any.whl",
|
|
8
8
|
"archive_info": {
|
|
9
|
-
"hash": "sha256=
|
|
9
|
+
"hash": "sha256=b9ab3a104bedb292323f53797b00864e10e434a3ab3906813a7169e4745b912a",
|
|
10
10
|
"hashes": {
|
|
11
|
-
"sha256": "
|
|
11
|
+
"sha256": "b9ab3a104bedb292323f53797b00864e10e434a3ab3906813a7169e4745b912a"
|
|
12
12
|
}
|
|
13
13
|
}
|
|
14
14
|
},
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"metadata": {
|
|
19
19
|
"metadata_version": "2.4",
|
|
20
20
|
"name": "setuptools",
|
|
21
|
-
"version": "
|
|
21
|
+
"version": "79.0.0",
|
|
22
22
|
"dynamic": [
|
|
23
23
|
"license-file"
|
|
24
24
|
],
|
|
@@ -39,7 +39,6 @@
|
|
|
39
39
|
"classifier": [
|
|
40
40
|
"Development Status :: 5 - Production/Stable",
|
|
41
41
|
"Intended Audience :: Developers",
|
|
42
|
-
"License :: OSI Approved :: MIT License",
|
|
43
42
|
"Programming Language :: Python :: 3",
|
|
44
43
|
"Programming Language :: Python :: 3 :: Only",
|
|
45
44
|
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
Binary file
|
|
@@ -15,7 +15,7 @@ from .request_builder import (
|
|
|
15
15
|
OverloadedRequestBuilder,
|
|
16
16
|
get_request_builder,
|
|
17
17
|
)
|
|
18
|
-
from .parameter import Parameter, ParameterMethodLocation
|
|
18
|
+
from .parameter import Parameter, ParameterMethodLocation, ParameterLocation
|
|
19
19
|
from .lro_operation import LROOperation
|
|
20
20
|
from .lro_paging_operation import LROPagingOperation
|
|
21
21
|
from ...utils import extract_original_name, NAME_LENGTH_LIMIT
|
|
@@ -54,7 +54,7 @@ class _ClientConfigBase(Generic[ParameterListType], BaseModel):
|
|
|
54
54
|
return self.yaml_data["name"]
|
|
55
55
|
|
|
56
56
|
|
|
57
|
-
class Client(_ClientConfigBase[ClientGlobalParameterList]):
|
|
57
|
+
class Client(_ClientConfigBase[ClientGlobalParameterList]): # pylint: disable=too-many-public-methods
|
|
58
58
|
"""Model representing our service client"""
|
|
59
59
|
|
|
60
60
|
def __init__(
|
|
@@ -79,6 +79,27 @@ class Client(_ClientConfigBase[ClientGlobalParameterList]):
|
|
|
79
79
|
self.request_id_header_name = self.yaml_data.get("requestIdHeaderName", None)
|
|
80
80
|
self.has_etag: bool = yaml_data.get("hasEtag", False)
|
|
81
81
|
|
|
82
|
+
# update the host parameter value. In later logic, SDK will overwrite it
|
|
83
|
+
# with value from cloud_setting if users don't provide it.
|
|
84
|
+
if self.need_cloud_setting:
|
|
85
|
+
for p in self.parameters.parameters:
|
|
86
|
+
if p.location == ParameterLocation.ENDPOINT_PATH:
|
|
87
|
+
p.client_default_value = None
|
|
88
|
+
p.optional = True
|
|
89
|
+
break
|
|
90
|
+
|
|
91
|
+
@property
|
|
92
|
+
def need_cloud_setting(self) -> bool:
|
|
93
|
+
return bool(
|
|
94
|
+
self.code_model.options.get("azure_arm", False)
|
|
95
|
+
and self.credential_scopes is not None
|
|
96
|
+
and self.endpoint_parameter is not None
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
@property
|
|
100
|
+
def endpoint_parameter(self) -> Optional[Parameter]:
|
|
101
|
+
return next((p for p in self.parameters.parameters if p.location == ParameterLocation.ENDPOINT_PATH), None)
|
|
102
|
+
|
|
82
103
|
def _build_request_builders(
|
|
83
104
|
self,
|
|
84
105
|
) -> List[Union[RequestBuilder, OverloadedRequestBuilder]]:
|
|
@@ -233,6 +254,10 @@ class Client(_ClientConfigBase[ClientGlobalParameterList]):
|
|
|
233
254
|
"Self",
|
|
234
255
|
ImportType.STDLIB,
|
|
235
256
|
)
|
|
257
|
+
if self.need_cloud_setting:
|
|
258
|
+
file_import.add_submodule_import("typing", "cast", ImportType.STDLIB)
|
|
259
|
+
file_import.add_submodule_import("azure.core.settings", "settings", ImportType.SDKCORE)
|
|
260
|
+
file_import.add_submodule_import("azure.mgmt.core.tools", "get_arm_endpoints", ImportType.SDKCORE)
|
|
236
261
|
return file_import
|
|
237
262
|
|
|
238
263
|
@property
|
|
@@ -332,6 +357,18 @@ class Client(_ClientConfigBase[ClientGlobalParameterList]):
|
|
|
332
357
|
)
|
|
333
358
|
return file_import
|
|
334
359
|
|
|
360
|
+
@property
|
|
361
|
+
def credential_scopes(self) -> Optional[List[str]]:
|
|
362
|
+
"""Credential scopes for this client"""
|
|
363
|
+
|
|
364
|
+
if self.credential:
|
|
365
|
+
if hasattr(getattr(self.credential.type, "policy", None), "credential_scopes"):
|
|
366
|
+
return self.credential.type.policy.credential_scopes # type: ignore
|
|
367
|
+
for t in getattr(self.credential.type, "types", []):
|
|
368
|
+
if hasattr(getattr(t, "policy", None), "credential_scopes"):
|
|
369
|
+
return t.policy.credential_scopes
|
|
370
|
+
return None
|
|
371
|
+
|
|
335
372
|
@classmethod
|
|
336
373
|
def from_yaml(
|
|
337
374
|
cls,
|
|
@@ -357,6 +357,9 @@ class Parameter(_ParameterBase):
|
|
|
357
357
|
)
|
|
358
358
|
if self.code_model.options["only_path_and_body_params_positional"] and query_or_header:
|
|
359
359
|
return ParameterMethodLocation.KEYWORD_ONLY
|
|
360
|
+
# for optional path parameter, we need to use keyword only
|
|
361
|
+
if self.location == ParameterLocation.PATH and self.optional:
|
|
362
|
+
return ParameterMethodLocation.KEYWORD_ONLY
|
|
360
363
|
return ParameterMethodLocation.POSITIONAL
|
|
361
364
|
|
|
362
365
|
@classmethod
|
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
# Licensed under the MIT License. See License.txt in the project root for
|
|
4
4
|
# license information.
|
|
5
5
|
# --------------------------------------------------------------------------
|
|
6
|
-
from typing import List
|
|
6
|
+
from typing import List, cast
|
|
7
7
|
|
|
8
8
|
from . import utils
|
|
9
|
-
from ..models import Client, ParameterMethodLocation
|
|
9
|
+
from ..models import Client, ParameterMethodLocation, Parameter, ParameterLocation
|
|
10
10
|
from .parameter_serializer import ParameterSerializer, PopKwargType
|
|
11
11
|
from ...utils import build_policies
|
|
12
12
|
|
|
@@ -77,17 +77,40 @@ class ClientSerializer:
|
|
|
77
77
|
retval.append('"""')
|
|
78
78
|
return retval
|
|
79
79
|
|
|
80
|
-
def initialize_config(self) -> str:
|
|
80
|
+
def initialize_config(self) -> List[str]:
|
|
81
|
+
retval = []
|
|
82
|
+
additional_signatures = []
|
|
83
|
+
if self.client.need_cloud_setting:
|
|
84
|
+
additional_signatures.append("credential_scopes=credential_scopes")
|
|
85
|
+
endpoint_parameter = cast(Parameter, self.client.endpoint_parameter)
|
|
86
|
+
retval.extend(
|
|
87
|
+
[
|
|
88
|
+
'_cloud = kwargs.pop("cloud_setting", None) or settings.current.azure_cloud # type: ignore',
|
|
89
|
+
"_endpoints = get_arm_endpoints(_cloud)",
|
|
90
|
+
f"if not {endpoint_parameter.client_name}:",
|
|
91
|
+
f' {endpoint_parameter.client_name} = _endpoints["resource_manager"]',
|
|
92
|
+
'credential_scopes = kwargs.pop("credential_scopes", _endpoints["credential_scopes"])',
|
|
93
|
+
]
|
|
94
|
+
)
|
|
81
95
|
config_name = f"{self.client.name}Configuration"
|
|
82
96
|
config_call = ", ".join(
|
|
83
97
|
[
|
|
84
|
-
|
|
98
|
+
(
|
|
99
|
+
f"{p.client_name}="
|
|
100
|
+
+ (
|
|
101
|
+
f"cast(str, {p.client_name})"
|
|
102
|
+
if self.client.need_cloud_setting and p.location == ParameterLocation.ENDPOINT_PATH
|
|
103
|
+
else p.client_name
|
|
104
|
+
)
|
|
105
|
+
)
|
|
85
106
|
for p in self.client.config.parameters.method
|
|
86
107
|
if p.method_location != ParameterMethodLocation.KWARG
|
|
87
108
|
]
|
|
109
|
+
+ additional_signatures
|
|
88
110
|
+ ["**kwargs"]
|
|
89
111
|
)
|
|
90
|
-
|
|
112
|
+
retval.append(f"self._config = {config_name}({config_call})")
|
|
113
|
+
return retval
|
|
91
114
|
|
|
92
115
|
@property
|
|
93
116
|
def host_variable_name(self) -> str:
|
|
@@ -104,8 +127,11 @@ class ClientSerializer:
|
|
|
104
127
|
result = []
|
|
105
128
|
pipeline_client_name = self.client.pipeline_class(async_mode)
|
|
106
129
|
endpoint_name = "base_url" if self.client.code_model.is_azure_flavor else "endpoint"
|
|
130
|
+
host_variable_name = (
|
|
131
|
+
f"cast(str, {self.host_variable_name})" if self.client.need_cloud_setting else self.host_variable_name
|
|
132
|
+
)
|
|
107
133
|
params = {
|
|
108
|
-
endpoint_name:
|
|
134
|
+
endpoint_name: host_variable_name,
|
|
109
135
|
"policies": "_policies",
|
|
110
136
|
}
|
|
111
137
|
if not self.client.code_model.is_legacy and self.client.request_id_header_name:
|
|
@@ -19,7 +19,7 @@ from .base_serializer import BaseSerializer
|
|
|
19
19
|
VERSION_MAP = {
|
|
20
20
|
"msrest": "0.7.1",
|
|
21
21
|
"isodate": "0.6.1",
|
|
22
|
-
"azure-mgmt-core": "1.
|
|
22
|
+
"azure-mgmt-core": "1.5.0",
|
|
23
23
|
"azure-core": "1.30.0",
|
|
24
24
|
"typing-extensions": "4.6.0",
|
|
25
25
|
"corehttp": "1.0.0b6",
|
|
@@ -225,19 +225,33 @@ class GeneralSerializer(BaseSerializer):
|
|
|
225
225
|
if not enum.internal
|
|
226
226
|
}
|
|
227
227
|
)
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
228
|
+
for client in self.code_model.clients:
|
|
229
|
+
for operation_group in client.operation_groups:
|
|
230
|
+
for operation in operation_group.operations:
|
|
231
|
+
if operation.name.startswith("_"):
|
|
232
|
+
continue
|
|
233
|
+
cross_langauge_def_dict.update(
|
|
234
|
+
{
|
|
235
|
+
f"{self.code_model.namespace}."
|
|
236
|
+
+ (
|
|
237
|
+
f"{client.name}."
|
|
238
|
+
if operation_group.is_mixin
|
|
239
|
+
else f"operations.{operation_group.class_name}."
|
|
240
|
+
)
|
|
241
|
+
+ f"{operation.name}": operation.cross_language_definition_id
|
|
242
|
+
}
|
|
243
|
+
)
|
|
244
|
+
cross_langauge_def_dict.update(
|
|
245
|
+
{
|
|
246
|
+
f"{self.code_model.namespace}.aio."
|
|
247
|
+
+ (
|
|
248
|
+
f"{client.name}."
|
|
249
|
+
if operation_group.is_mixin
|
|
250
|
+
else f"operations.{operation_group.class_name}."
|
|
251
|
+
)
|
|
252
|
+
+ f"{operation.name}": operation.cross_language_definition_id
|
|
253
|
+
}
|
|
254
|
+
)
|
|
241
255
|
return json.dumps(
|
|
242
256
|
{
|
|
243
257
|
"CrossLanguagePackageId": self.code_model.cross_language_package_id,
|
|
@@ -109,6 +109,7 @@ class ParameterSerializer:
|
|
|
109
109
|
return f"[{serialize_line} if q is not None else '' for q in {origin_name}]"
|
|
110
110
|
return serialize_line
|
|
111
111
|
|
|
112
|
+
# pylint: disable=line-too-long
|
|
112
113
|
def serialize_path(
|
|
113
114
|
self,
|
|
114
115
|
parameters: Union[
|
|
@@ -124,7 +125,11 @@ class ParameterSerializer:
|
|
|
124
125
|
[
|
|
125
126
|
' "{}": {},'.format(
|
|
126
127
|
path_parameter.wire_name,
|
|
127
|
-
|
|
128
|
+
(
|
|
129
|
+
f'"" if {path_parameter.full_client_name} is None else "/" + {self.serialize_parameter(path_parameter, serializer_name)}'
|
|
130
|
+
if path_parameter.optional and isinstance(path_parameter, RequestBuilderParameter)
|
|
131
|
+
else self.serialize_parameter(path_parameter, serializer_name)
|
|
132
|
+
),
|
|
128
133
|
)
|
|
129
134
|
for path_parameter in parameters
|
|
130
135
|
]
|
|
@@ -62,7 +62,7 @@ class SampleSerializer(BaseSerializer):
|
|
|
62
62
|
ImportType.SDKCORE,
|
|
63
63
|
)
|
|
64
64
|
for param in self.operation.parameters.positional + self.operation.parameters.keyword_only:
|
|
65
|
-
if
|
|
65
|
+
if param.client_default_value is None and not param.optional and param.wire_name in self.sample_params:
|
|
66
66
|
imports.merge(param.type.imports_for_sample())
|
|
67
67
|
return FileImportSerializer(imports, True)
|
|
68
68
|
|
|
@@ -80,7 +80,7 @@ class SampleSerializer(BaseSerializer):
|
|
|
80
80
|
for p in (
|
|
81
81
|
self.code_model.clients[0].parameters.positional + self.code_model.clients[0].parameters.keyword_only
|
|
82
82
|
)
|
|
83
|
-
if not
|
|
83
|
+
if not p.optional and p.client_default_value is None
|
|
84
84
|
]
|
|
85
85
|
client_params = {
|
|
86
86
|
p.client_name: special_param.get(
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
{% if client.has_parameterized_host %}
|
|
10
10
|
{{ serializer.host_variable_name }} = {{ keywords.escape_str(client.url) }}
|
|
11
11
|
{% endif %}
|
|
12
|
-
{{ serializer.initialize_config() }}
|
|
12
|
+
{{ op_tools.serialize(serializer.initialize_config()) | indent(8) }}
|
|
13
13
|
{{ op_tools.serialize(serializer.initialize_pipeline_client(async_mode)) | indent(8) }}
|
|
14
14
|
|
|
15
15
|
{{ op_tools.serialize(serializer.serializers_and_operation_groups_properties()) | indent(8) }}
|
|
@@ -21,14 +21,8 @@ class {{ client.name }}Configuration: {{ client.config.pylint_disable() }}
|
|
|
21
21
|
{% if serializer.set_constants() %}
|
|
22
22
|
{{ op_tools.serialize(serializer.set_constants()) | indent(8) -}}
|
|
23
23
|
{% endif %}
|
|
24
|
-
{% if client.
|
|
25
|
-
|
|
26
|
-
{% if not cred_scopes %}
|
|
27
|
-
{% set cred_scopes = client.credential.type.types | selectattr("policy.credential_scopes") | first if client.credential.type.types is defined %}
|
|
28
|
-
{% endif %}
|
|
29
|
-
{% if cred_scopes %}
|
|
30
|
-
self.credential_scopes = kwargs.pop('credential_scopes', {{ cred_scopes.policy.credential_scopes }})
|
|
31
|
-
{% endif %}
|
|
24
|
+
{% if client.credential_scopes is not none %}
|
|
25
|
+
self.credential_scopes = kwargs.pop('credential_scopes', {{ client.credential_scopes }})
|
|
32
26
|
{% endif %}
|
|
33
27
|
kwargs.setdefault('sdk_moniker', '{{ client.config.sdk_moniker }}/{}'.format(VERSION))
|
|
34
28
|
self.polling_interval = kwargs.get("polling_interval", 30)
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# -------------------------------------------------------------------------
|
|
2
|
+
# Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3
|
+
# Licensed under the MIT License. See License.txt in the project root for
|
|
4
|
+
# license information.
|
|
5
|
+
# --------------------------------------------------------------------------
|
|
6
|
+
import pytest
|
|
7
|
+
from specs.azure.clientgenerator.core.clientinitialization.aio import (
|
|
8
|
+
HeaderParamClient,
|
|
9
|
+
MultipleParamsClient,
|
|
10
|
+
MixedParamsClient,
|
|
11
|
+
PathParamClient,
|
|
12
|
+
ParamAliasClient,
|
|
13
|
+
)
|
|
14
|
+
from specs.azure.clientgenerator.core.clientinitialization.models import Input
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@pytest.mark.asyncio
|
|
18
|
+
async def test_header_param_client():
|
|
19
|
+
async with HeaderParamClient("test-name-value") as client:
|
|
20
|
+
await client.with_query(id="test-id")
|
|
21
|
+
await client.with_body(Input(name="test-name"))
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@pytest.mark.asyncio
|
|
25
|
+
async def test_multiple_params_client():
|
|
26
|
+
async with MultipleParamsClient("test-name-value", "us-west") as client:
|
|
27
|
+
await client.with_query(id="test-id")
|
|
28
|
+
await client.with_body(Input(name="test-name"))
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@pytest.mark.asyncio
|
|
32
|
+
async def test_mixed_params_client():
|
|
33
|
+
async with MixedParamsClient("test-name-value") as client:
|
|
34
|
+
await client.with_query(region="us-west", id="test-id")
|
|
35
|
+
await client.with_body(Input(name="test-name"), region="us-west")
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
@pytest.mark.asyncio
|
|
39
|
+
async def test_path_param_client():
|
|
40
|
+
async with PathParamClient("sample-blob") as client:
|
|
41
|
+
await client.with_query(format="text")
|
|
42
|
+
await client.get_standalone()
|
|
43
|
+
await client.delete_standalone()
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
@pytest.mark.asyncio
|
|
47
|
+
async def test_param_alias_client():
|
|
48
|
+
async with ParamAliasClient("sample-blob") as client:
|
|
49
|
+
await client.with_aliased_name()
|
|
50
|
+
await client.with_original_name()
|