@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.
Files changed (42) hide show
  1. package/README.md +19 -36
  2. package/dist/emitter/emitter.js +40 -0
  3. package/dist/emitter/emitter.js.map +1 -1
  4. package/dist/emitter/http.js +5 -2
  5. package/dist/emitter/http.js.map +1 -1
  6. package/dist/emitter/utils.d.ts.map +1 -1
  7. package/dist/emitter/utils.js +9 -1
  8. package/dist/emitter/utils.js.map +1 -1
  9. package/emitter/src/emitter.ts +46 -0
  10. package/emitter/src/http.ts +12 -2
  11. package/emitter/src/utils.ts +11 -1
  12. package/emitter/temp/tsconfig.tsbuildinfo +1 -1
  13. package/eng/scripts/setup/__pycache__/venvtools.cpython-39.pyc +0 -0
  14. package/eng/scripts/setup/install.py +1 -0
  15. package/eng/scripts/setup/run_tsp.py +2 -3
  16. package/generator/build/lib/pygen/codegen/models/client.py +39 -2
  17. package/generator/build/lib/pygen/codegen/models/parameter.py +3 -0
  18. package/generator/build/lib/pygen/codegen/serializers/client_serializer.py +32 -6
  19. package/generator/build/lib/pygen/codegen/serializers/general_serializer.py +28 -14
  20. package/generator/build/lib/pygen/codegen/serializers/parameter_serializer.py +6 -1
  21. package/generator/build/lib/pygen/codegen/serializers/sample_serializer.py +2 -2
  22. package/generator/build/lib/pygen/codegen/templates/client.py.jinja2 +1 -1
  23. package/generator/build/lib/pygen/codegen/templates/config.py.jinja2 +2 -8
  24. package/generator/component-detection-pip-report.json +4 -5
  25. package/generator/dist/pygen-0.1.0-py3-none-any.whl +0 -0
  26. package/generator/pygen/codegen/models/client.py +39 -2
  27. package/generator/pygen/codegen/models/parameter.py +3 -0
  28. package/generator/pygen/codegen/serializers/client_serializer.py +32 -6
  29. package/generator/pygen/codegen/serializers/general_serializer.py +28 -14
  30. package/generator/pygen/codegen/serializers/parameter_serializer.py +6 -1
  31. package/generator/pygen/codegen/serializers/sample_serializer.py +2 -2
  32. package/generator/pygen/codegen/templates/client.py.jinja2 +1 -1
  33. package/generator/pygen/codegen/templates/config.py.jinja2 +2 -8
  34. package/generator/test/azure/mock_api_tests/asynctests/test_azure_client_generator_core_client_initialization_async.py +50 -0
  35. package/generator/test/azure/mock_api_tests/test_azure_client_generator_core_client_initialization.py +44 -0
  36. package/generator/test/azure/requirements.txt +4 -3
  37. package/generator/test/generic_mock_api_tests/asynctests/test_parameters_path_async.py +24 -0
  38. package/generator/test/generic_mock_api_tests/asynctests/test_payload_json_merge_patch_async.py +1 -1
  39. package/generator/test/generic_mock_api_tests/test_parameters_path.py +22 -0
  40. package/generator/test/generic_mock_api_tests/test_payload_json_merge_patch.py +1 -1
  41. package/generator/test/unbranded/requirements.txt +1 -0
  42. 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
- f"{p.client_name}={p.client_name}"
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
- return f"self._config = {config_name}({config_call})"
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: self.host_variable_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.3.2",
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
- cross_langauge_def_dict.update(
229
- {
230
- (
231
- f"{self.code_model.namespace}.{client.name}."
232
- + ("" if operation_group.is_mixin else f"{operation_group.property_name}.")
233
- + f"{operation.name}"
234
- ): operation.cross_language_definition_id
235
- for client in self.code_model.clients
236
- for operation_group in client.operation_groups
237
- for operation in operation_group.operations
238
- if not operation.name.startswith("_")
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
- self.serialize_parameter(path_parameter, serializer_name),
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 not param.client_default_value and not param.optional and param.wire_name in self.sample_params:
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 (p.optional or p.client_default_value)
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.credential %}
25
- {% set cred_scopes = client.credential.type if client.credential.type.policy is defined and client.credential.type.policy.credential_scopes is defined %}
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/54/21/f43f0a1fa8b06b32812e0975981f4677d28e0f3271601dc88ac5a5b83220/setuptools-78.1.0-py3-none-any.whl",
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=3e386e96793c8702ae83d17b853fb93d3e09ef82ec62722e61da5cd22376dcd8",
9
+ "hash": "sha256=b9ab3a104bedb292323f53797b00864e10e434a3ab3906813a7169e4745b912a",
10
10
  "hashes": {
11
- "sha256": "3e386e96793c8702ae83d17b853fb93d3e09ef82ec62722e61da5cd22376dcd8"
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": "78.1.0",
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",
@@ -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
- f"{p.client_name}={p.client_name}"
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
- return f"self._config = {config_name}({config_call})"
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: self.host_variable_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.3.2",
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
- cross_langauge_def_dict.update(
229
- {
230
- (
231
- f"{self.code_model.namespace}.{client.name}."
232
- + ("" if operation_group.is_mixin else f"{operation_group.property_name}.")
233
- + f"{operation.name}"
234
- ): operation.cross_language_definition_id
235
- for client in self.code_model.clients
236
- for operation_group in client.operation_groups
237
- for operation in operation_group.operations
238
- if not operation.name.startswith("_")
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
- self.serialize_parameter(path_parameter, serializer_name),
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 not param.client_default_value and not param.optional and param.wire_name in self.sample_params:
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 (p.optional or p.client_default_value)
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.credential %}
25
- {% set cred_scopes = client.credential.type if client.credential.type.policy is defined and client.credential.type.policy.credential_scopes is defined %}
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()