@typespec/http-client-python 0.15.2 → 0.16.1-dev.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 (156) hide show
  1. package/dist/emitter/code-model.d.ts.map +1 -1
  2. package/dist/emitter/code-model.js +8 -1
  3. package/dist/emitter/code-model.js.map +1 -1
  4. package/dist/emitter/emitter.d.ts.map +1 -1
  5. package/dist/emitter/emitter.js +5 -4
  6. package/dist/emitter/emitter.js.map +1 -1
  7. package/dist/emitter/http.d.ts +5 -0
  8. package/dist/emitter/http.d.ts.map +1 -1
  9. package/dist/emitter/http.js +20 -1
  10. package/dist/emitter/http.js.map +1 -1
  11. package/emitter/src/code-model.ts +12 -0
  12. package/emitter/src/emitter.ts +5 -4
  13. package/emitter/src/http.ts +23 -1
  14. package/emitter/temp/tsconfig.tsbuildinfo +1 -1
  15. package/eng/scripts/ci/regenerate.ts +5 -6
  16. package/eng/scripts/ci/util.py +1 -1
  17. package/eng/scripts/setup/__pycache__/package_manager.cpython-39.pyc +0 -0
  18. package/eng/scripts/setup/__pycache__/venvtools.cpython-39.pyc +0 -0
  19. package/eng/scripts/setup/install.py +21 -11
  20. package/eng/scripts/setup/install.ts +29 -4
  21. package/eng/scripts/setup/run-python3.ts +1 -1
  22. package/eng/scripts/setup/system-requirements.ts +13 -5
  23. package/generator/build/lib/pygen/__init__.py +7 -21
  24. package/generator/build/lib/pygen/black.py +2 -2
  25. package/generator/build/lib/pygen/codegen/__init__.py +4 -4
  26. package/generator/build/lib/pygen/codegen/models/__init__.py +2 -2
  27. package/generator/build/lib/pygen/codegen/models/base.py +9 -12
  28. package/generator/build/lib/pygen/codegen/models/base_builder.py +4 -6
  29. package/generator/build/lib/pygen/codegen/models/client.py +61 -102
  30. package/generator/build/lib/pygen/codegen/models/code_model.py +33 -29
  31. package/generator/build/lib/pygen/codegen/models/combined_type.py +7 -7
  32. package/generator/build/lib/pygen/codegen/models/constant_type.py +4 -11
  33. package/generator/build/lib/pygen/codegen/models/credential_types.py +9 -11
  34. package/generator/build/lib/pygen/codegen/models/dictionary_type.py +7 -8
  35. package/generator/build/lib/pygen/codegen/models/enum_type.py +7 -7
  36. package/generator/build/lib/pygen/codegen/models/imports.py +24 -29
  37. package/generator/build/lib/pygen/codegen/models/list_type.py +11 -14
  38. package/generator/build/lib/pygen/codegen/models/lro_operation.py +6 -6
  39. package/generator/build/lib/pygen/codegen/models/lro_paging_operation.py +2 -2
  40. package/generator/build/lib/pygen/codegen/models/model_type.py +11 -11
  41. package/generator/build/lib/pygen/codegen/models/operation.py +22 -56
  42. package/generator/build/lib/pygen/codegen/models/operation_group.py +11 -22
  43. package/generator/build/lib/pygen/codegen/models/paging_operation.py +15 -19
  44. package/generator/build/lib/pygen/codegen/models/parameter.py +12 -21
  45. package/generator/build/lib/pygen/codegen/models/parameter_list.py +37 -39
  46. package/generator/build/lib/pygen/codegen/models/primitive_types.py +24 -18
  47. package/generator/build/lib/pygen/codegen/models/property.py +10 -10
  48. package/generator/build/lib/pygen/codegen/models/request_builder.py +7 -8
  49. package/generator/build/lib/pygen/codegen/models/request_builder_parameter.py +3 -3
  50. package/generator/build/lib/pygen/codegen/models/response.py +15 -40
  51. package/generator/build/lib/pygen/codegen/models/utils.py +2 -2
  52. package/generator/build/lib/pygen/codegen/serializers/__init__.py +15 -40
  53. package/generator/build/lib/pygen/codegen/serializers/builder_serializer.py +101 -94
  54. package/generator/build/lib/pygen/codegen/serializers/client_serializer.py +22 -25
  55. package/generator/build/lib/pygen/codegen/serializers/enum_serializer.py +2 -2
  56. package/generator/build/lib/pygen/codegen/serializers/general_serializer.py +46 -60
  57. package/generator/build/lib/pygen/codegen/serializers/import_serializer.py +6 -7
  58. package/generator/build/lib/pygen/codegen/serializers/model_init_serializer.py +1 -2
  59. package/generator/build/lib/pygen/codegen/serializers/model_serializer.py +36 -29
  60. package/generator/build/lib/pygen/codegen/serializers/operation_groups_serializer.py +8 -3
  61. package/generator/build/lib/pygen/codegen/serializers/operations_init_serializer.py +5 -6
  62. package/generator/build/lib/pygen/codegen/serializers/parameter_serializer.py +28 -18
  63. package/generator/build/lib/pygen/codegen/serializers/patch_serializer.py +1 -2
  64. package/generator/build/lib/pygen/codegen/serializers/request_builders_serializer.py +1 -2
  65. package/generator/build/lib/pygen/codegen/serializers/sample_serializer.py +9 -14
  66. package/generator/build/lib/pygen/codegen/serializers/test_serializer.py +7 -7
  67. package/generator/build/lib/pygen/codegen/serializers/utils.py +2 -2
  68. package/generator/build/lib/pygen/codegen/templates/model_base.py.jinja2 +30 -24
  69. package/generator/build/lib/pygen/codegen/templates/model_dpg.py.jinja2 +1 -1
  70. package/generator/build/lib/pygen/codegen/templates/operation_group.py.jinja2 +1 -11
  71. package/generator/build/lib/pygen/codegen/templates/operations_folder_init.py.jinja2 +1 -1
  72. package/generator/build/lib/pygen/codegen/templates/packaging_templates/dev_requirements.txt.jinja2 +1 -1
  73. package/generator/build/lib/pygen/codegen/templates/packaging_templates/pyproject.toml.jinja2 +8 -1
  74. package/generator/build/lib/pygen/codegen/templates/patch.py.jinja2 +1 -1
  75. package/generator/build/lib/pygen/codegen/templates/serialization.py.jinja2 +11 -13
  76. package/generator/build/lib/pygen/codegen/templates/utils.py.jinja2 +6 -6
  77. package/generator/build/lib/pygen/preprocess/__init__.py +47 -30
  78. package/generator/build/lib/pygen/preprocess/helpers.py +2 -2
  79. package/generator/build/lib/pygen/utils.py +6 -6
  80. package/generator/dist/pygen-0.1.0-py3-none-any.whl +0 -0
  81. package/generator/pygen/__init__.py +7 -21
  82. package/generator/pygen/black.py +2 -2
  83. package/generator/pygen/codegen/__init__.py +4 -4
  84. package/generator/pygen/codegen/models/__init__.py +2 -2
  85. package/generator/pygen/codegen/models/base.py +9 -12
  86. package/generator/pygen/codegen/models/base_builder.py +4 -6
  87. package/generator/pygen/codegen/models/client.py +61 -102
  88. package/generator/pygen/codegen/models/code_model.py +33 -29
  89. package/generator/pygen/codegen/models/combined_type.py +7 -7
  90. package/generator/pygen/codegen/models/constant_type.py +4 -11
  91. package/generator/pygen/codegen/models/credential_types.py +9 -11
  92. package/generator/pygen/codegen/models/dictionary_type.py +7 -8
  93. package/generator/pygen/codegen/models/enum_type.py +7 -7
  94. package/generator/pygen/codegen/models/imports.py +24 -29
  95. package/generator/pygen/codegen/models/list_type.py +11 -14
  96. package/generator/pygen/codegen/models/lro_operation.py +6 -6
  97. package/generator/pygen/codegen/models/lro_paging_operation.py +2 -2
  98. package/generator/pygen/codegen/models/model_type.py +11 -11
  99. package/generator/pygen/codegen/models/operation.py +22 -56
  100. package/generator/pygen/codegen/models/operation_group.py +11 -22
  101. package/generator/pygen/codegen/models/paging_operation.py +15 -19
  102. package/generator/pygen/codegen/models/parameter.py +12 -21
  103. package/generator/pygen/codegen/models/parameter_list.py +37 -39
  104. package/generator/pygen/codegen/models/primitive_types.py +24 -18
  105. package/generator/pygen/codegen/models/property.py +10 -10
  106. package/generator/pygen/codegen/models/request_builder.py +7 -8
  107. package/generator/pygen/codegen/models/request_builder_parameter.py +3 -3
  108. package/generator/pygen/codegen/models/response.py +15 -40
  109. package/generator/pygen/codegen/models/utils.py +2 -2
  110. package/generator/pygen/codegen/serializers/__init__.py +15 -40
  111. package/generator/pygen/codegen/serializers/builder_serializer.py +101 -94
  112. package/generator/pygen/codegen/serializers/client_serializer.py +22 -25
  113. package/generator/pygen/codegen/serializers/enum_serializer.py +2 -2
  114. package/generator/pygen/codegen/serializers/general_serializer.py +46 -60
  115. package/generator/pygen/codegen/serializers/import_serializer.py +6 -7
  116. package/generator/pygen/codegen/serializers/model_init_serializer.py +1 -2
  117. package/generator/pygen/codegen/serializers/model_serializer.py +36 -29
  118. package/generator/pygen/codegen/serializers/operation_groups_serializer.py +8 -3
  119. package/generator/pygen/codegen/serializers/operations_init_serializer.py +5 -6
  120. package/generator/pygen/codegen/serializers/parameter_serializer.py +28 -18
  121. package/generator/pygen/codegen/serializers/patch_serializer.py +1 -2
  122. package/generator/pygen/codegen/serializers/request_builders_serializer.py +1 -2
  123. package/generator/pygen/codegen/serializers/sample_serializer.py +9 -14
  124. package/generator/pygen/codegen/serializers/test_serializer.py +7 -7
  125. package/generator/pygen/codegen/serializers/utils.py +2 -2
  126. package/generator/pygen/codegen/templates/model_base.py.jinja2 +30 -24
  127. package/generator/pygen/codegen/templates/model_dpg.py.jinja2 +1 -1
  128. package/generator/pygen/codegen/templates/operation_group.py.jinja2 +1 -11
  129. package/generator/pygen/codegen/templates/operations_folder_init.py.jinja2 +1 -1
  130. package/generator/pygen/codegen/templates/packaging_templates/dev_requirements.txt.jinja2 +1 -1
  131. package/generator/pygen/codegen/templates/packaging_templates/pyproject.toml.jinja2 +8 -1
  132. package/generator/pygen/codegen/templates/patch.py.jinja2 +1 -1
  133. package/generator/pygen/codegen/templates/serialization.py.jinja2 +11 -13
  134. package/generator/pygen/codegen/templates/utils.py.jinja2 +6 -6
  135. package/generator/pygen/preprocess/__init__.py +47 -30
  136. package/generator/pygen/preprocess/helpers.py +2 -2
  137. package/generator/pygen/utils.py +6 -6
  138. package/generator/pygen.egg-info/SOURCES.txt +0 -2
  139. package/generator/test/azure/mock_api_tests/asynctests/test_azure_arm_operationtemplates_async.py +79 -0
  140. package/generator/test/azure/mock_api_tests/asynctests/test_azure_client_generator_core_hierrarchy_building_async.py +53 -0
  141. package/generator/test/azure/mock_api_tests/asynctests/test_client_naming_async.py +4 -4
  142. package/generator/test/azure/mock_api_tests/asynctests/test_client_naming_enum_conflict_async.py +37 -0
  143. package/generator/test/azure/mock_api_tests/conftest.py +2 -2
  144. package/generator/test/azure/mock_api_tests/test_azure_arm_operationtemplates.py +72 -0
  145. package/generator/test/azure/mock_api_tests/test_azure_client_generator_core_hierrarchy_building.py +45 -0
  146. package/generator/test/azure/mock_api_tests/test_client_naming.py +3 -3
  147. package/generator/test/azure/mock_api_tests/test_client_naming_enum_conflict.py +35 -0
  148. package/generator/test/azure/requirements.txt +2 -0
  149. package/generator/test/unbranded/mock_api_tests/conftest.py +1 -2
  150. package/generator/test/unittests/test_model_base_serialization.py +135 -92
  151. package/generator/test/unittests/test_model_base_xml_serialization.py +19 -23
  152. package/package.json +8 -8
  153. package/generator/build/lib/pygen/codegen/serializers/metadata_serializer.py +0 -216
  154. package/generator/build/lib/pygen/codegen/templates/metadata.json.jinja2 +0 -167
  155. package/generator/pygen/codegen/serializers/metadata_serializer.py +0 -216
  156. package/generator/pygen/codegen/templates/metadata.json.jinja2 +0 -167
@@ -17,7 +17,6 @@ import re
17
17
  import sys
18
18
  import codecs
19
19
  from typing import (
20
- Dict,
21
20
  Any,
22
21
  cast,
23
22
  Optional,
@@ -27,7 +26,6 @@ from typing import (
27
26
  Mapping,
28
27
  Callable,
29
28
  MutableMapping,
30
- List,
31
29
  )
32
30
 
33
31
  try:
@@ -225,12 +223,12 @@ class Model:
225
223
  serialization and deserialization.
226
224
  """
227
225
 
228
- _subtype_map: Dict[str, Dict[str, Any]] = {}
229
- _attribute_map: Dict[str, Dict[str, Any]] = {}
230
- _validation: Dict[str, Dict[str, Any]] = {}
226
+ _subtype_map: dict[str, dict[str, Any]] = {}
227
+ _attribute_map: dict[str, dict[str, Any]] = {}
228
+ _validation: dict[str, dict[str, Any]] = {}
231
229
 
232
230
  def __init__(self, **kwargs: Any) -> None:
233
- self.additional_properties: Optional[Dict[str, Any]] = {}
231
+ self.additional_properties: Optional[dict[str, Any]] = {}
234
232
  for k in kwargs: # pylint: disable=consider-using-dict-items
235
233
  if k not in self._attribute_map:
236
234
  _LOGGER.warning("%s is not a known attribute of class %s and will be ignored", k, self.__class__)
@@ -307,7 +305,7 @@ class Model:
307
305
  def as_dict(
308
306
  self,
309
307
  keep_readonly: bool = True,
310
- key_transformer: Callable[[str, Dict[str, Any], Any], Any] = attribute_transformer,
308
+ key_transformer: Callable[[str, dict[str, Any], Any], Any] = attribute_transformer,
311
309
  **kwargs: Any
312
310
  ) -> JSON:
313
311
  """Return a dict that can be serialized using json.dump.
@@ -376,7 +374,7 @@ class Model:
376
374
  def from_dict(
377
375
  cls,
378
376
  data: Any,
379
- key_extractors: Optional[Callable[[str, Dict[str, Any], Any], Any]] = None,
377
+ key_extractors: Optional[Callable[[str, dict[str, Any], Any], Any]] = None,
380
378
  content_type: Optional[str] = None,
381
379
  ) -> Self:
382
380
  """Parse a dict using given key extractor return a model.
@@ -410,7 +408,7 @@ class Model:
410
408
  return {}
411
409
  result = dict(cls._subtype_map[key])
412
410
  for valuetype in cls._subtype_map[key].values():
413
- result.update(objects[valuetype]._flatten_subtype(key, objects)) # pylint: disable=protected-access
411
+ result |= objects[valuetype]._flatten_subtype(key, objects) # pylint: disable=protected-access
414
412
  return result
415
413
 
416
414
  @classmethod
@@ -524,7 +522,7 @@ class Serializer: # pylint: disable=too-many-public-methods
524
522
  "[]": self.serialize_iter,
525
523
  "{}": self.serialize_dict,
526
524
  }
527
- self.dependencies: Dict[str, type] = dict(classes) if classes else {}
525
+ self.dependencies: dict[str, type] = dict(classes) if classes else {}
528
526
  self.key_transformer = full_restapi_key_transformer
529
527
  self.client_side_validation = True
530
528
 
@@ -575,7 +573,7 @@ class Serializer: # pylint: disable=too-many-public-methods
575
573
 
576
574
  if attr_name == "additional_properties" and attr_desc["key"] == "":
577
575
  if target_obj.additional_properties is not None:
578
- serialized.update(target_obj.additional_properties)
576
+ serialized |= target_obj.additional_properties
579
577
  continue
580
578
  try:
581
579
 
@@ -1180,7 +1178,7 @@ def rest_key_extractor(attr, attr_desc, data): # pylint: disable=unused-argumen
1180
1178
 
1181
1179
  while "." in key:
1182
1180
  # Need the cast, as for some reasons "split" is typed as list[str | Any]
1183
- dict_keys = cast(List[str], _FLATTEN.split(key))
1181
+ dict_keys = cast(list[str], _FLATTEN.split(key))
1184
1182
  if len(dict_keys) == 1:
1185
1183
  key = _decode_attribute_map_key(dict_keys[0])
1186
1184
  break
@@ -1382,7 +1380,7 @@ class Deserializer:
1382
1380
  "duration": (isodate.Duration, datetime.timedelta),
1383
1381
  "iso-8601": (datetime.datetime),
1384
1382
  }
1385
- self.dependencies: Dict[str, type] = dict(classes) if classes else {}
1383
+ self.dependencies: dict[str, type] = dict(classes) if classes else {}
1386
1384
  self.key_extractors = [rest_key_extractor, xml_key_extractor]
1387
1385
  # Additional properties only works if the "rest_key_extractor" is used to
1388
1386
  # extract the keys. Making it to work whatever the key extractor is too much
@@ -66,9 +66,9 @@ FileType = Union[
66
66
  # file (or bytes)
67
67
  FileContent,
68
68
  # (filename, file (or bytes))
69
- Tuple[Optional[str], FileContent],
69
+ tuple[Optional[str], FileContent],
70
70
  # (filename, file (or bytes), content_type)
71
- Tuple[Optional[str], FileContent, Optional[str]],
71
+ tuple[Optional[str], FileContent, Optional[str]],
72
72
  ]
73
73
 
74
74
  def serialize_multipart_data_entry(data_entry: Any) -> Any:
@@ -77,10 +77,10 @@ def serialize_multipart_data_entry(data_entry: Any) -> Any:
77
77
  return data_entry
78
78
 
79
79
  def prepare_multipart_form_data(
80
- body: Mapping[str, Any], multipart_fields: List[str], data_fields: List[str]
81
- ) -> Tuple[List[FileType], Dict[str, Any]]:
82
- files: List[FileType] = []
83
- data: Dict[str, Any] = {}
80
+ body: Mapping[str, Any], multipart_fields: list[str], data_fields: list[str]
81
+ ) -> tuple[list[FileType], dict[str, Any]]:
82
+ files: list[FileType] = []
83
+ data: dict[str, Any] = {}
84
84
  for multipart_field in multipart_fields:
85
85
  multipart_entry = body.get(multipart_field)
86
86
  if isinstance(multipart_entry, list):
@@ -5,7 +5,7 @@
5
5
  # --------------------------------------------------------------------------
6
6
  """The preprocessing autorest plugin."""
7
7
  import copy
8
- from typing import Callable, Dict, Any, List, Optional
8
+ from typing import Callable, Any, Optional
9
9
 
10
10
  from ..utils import to_snake_case, extract_original_name
11
11
  from .helpers import (
@@ -26,8 +26,8 @@ from ..utils import (
26
26
 
27
27
 
28
28
  def update_overload_section(
29
- overload: Dict[str, Any],
30
- yaml_data: Dict[str, Any],
29
+ overload: dict[str, Any],
30
+ yaml_data: dict[str, Any],
31
31
  section: str,
32
32
  ):
33
33
  try:
@@ -42,7 +42,7 @@ def update_overload_section(
42
42
  raise ValueError(overload["name"]) from exc
43
43
 
44
44
 
45
- def add_overload(yaml_data: Dict[str, Any], body_type: Dict[str, Any], for_flatten_params=False):
45
+ def add_overload(yaml_data: dict[str, Any], body_type: dict[str, Any], for_flatten_params=False):
46
46
  overload = copy.deepcopy(yaml_data)
47
47
  overload["isOverload"] = True
48
48
  overload["bodyParameter"]["type"] = body_type
@@ -80,7 +80,7 @@ def add_overload(yaml_data: Dict[str, Any], body_type: Dict[str, Any], for_flatt
80
80
  return overload
81
81
 
82
82
 
83
- def add_overloads_for_body_param(yaml_data: Dict[str, Any]) -> None:
83
+ def add_overloads_for_body_param(yaml_data: dict[str, Any]) -> None:
84
84
  """If we added a body parameter type, add overloads for that type"""
85
85
  body_parameter = yaml_data["bodyParameter"]
86
86
  if not (
@@ -121,7 +121,7 @@ def update_operation_group_class_name(prefix: str, class_name: str) -> str:
121
121
  return class_name + "Operations"
122
122
 
123
123
 
124
- def update_paging_response(yaml_data: Dict[str, Any]) -> None:
124
+ def update_paging_response(yaml_data: dict[str, Any]) -> None:
125
125
  yaml_data["discriminator"] = "paging"
126
126
 
127
127
 
@@ -148,23 +148,35 @@ HEADERS_CONVERT_IN_METHOD = {
148
148
  },
149
149
  },
150
150
  }
151
+ CLOUD_SETTING = {
152
+ "optional": True,
153
+ "description": "The cloud setting for which to get the ARM endpoint.",
154
+ "clientName": "cloud_setting",
155
+ "implementation": "Client",
156
+ "location": "keyword",
157
+ "type": {
158
+ "type": "sdkcore",
159
+ "name": "AzureClouds",
160
+ "isTypingOnly": True,
161
+ },
162
+ }
151
163
 
152
164
 
153
- def get_wire_name_lower(parameter: Dict[str, Any]) -> str:
165
+ def get_wire_name_lower(parameter: dict[str, Any]) -> str:
154
166
  return (parameter.get("wireName") or "").lower()
155
167
 
156
168
 
157
- def headers_convert(yaml_data: Dict[str, Any], replace_data: Any) -> None:
169
+ def headers_convert(yaml_data: dict[str, Any], replace_data: Any) -> None:
158
170
  if isinstance(replace_data, dict):
159
171
  for k, v in replace_data.items():
160
172
  yaml_data[k] = v
161
173
 
162
174
 
163
- def has_json_content_type(yaml_data: Dict[str, Any]) -> bool:
175
+ def has_json_content_type(yaml_data: dict[str, Any]) -> bool:
164
176
  return any(ct for ct in yaml_data.get("contentTypes", []) if JSON_REGEXP.match(ct))
165
177
 
166
178
 
167
- def has_multi_part_content_type(yaml_data: Dict[str, Any]) -> bool:
179
+ def has_multi_part_content_type(yaml_data: dict[str, Any]) -> bool:
168
180
  return any(ct for ct in yaml_data.get("contentTypes", []) if ct == "multipart/form-data")
169
181
 
170
182
 
@@ -189,8 +201,8 @@ class PreProcessPlugin(YamlUpdatePlugin):
189
201
 
190
202
  def add_body_param_type(
191
203
  self,
192
- code_model: Dict[str, Any],
193
- body_parameter: Dict[str, Any],
204
+ code_model: dict[str, Any],
205
+ body_parameter: dict[str, Any],
194
206
  ):
195
207
  # only add overload for special content type
196
208
  if ( # pylint: disable=too-many-boolean-expressions
@@ -231,7 +243,7 @@ class PreProcessPlugin(YamlUpdatePlugin):
231
243
  return name_prefix + name + pad_type
232
244
  return name_prefix + name
233
245
 
234
- def update_types(self, yaml_data: List[Dict[str, Any]]) -> None:
246
+ def update_types(self, yaml_data: list[dict[str, Any]]) -> None:
235
247
  for type in yaml_data:
236
248
  for property in type.get("properties", []):
237
249
  property["description"] = update_description(property.get("description", ""))
@@ -268,8 +280,9 @@ class PreProcessPlugin(YamlUpdatePlugin):
268
280
  for v in HEADERS_CONVERT_IN_METHOD.values():
269
281
  if isinstance(v, dict) and "type" in v:
270
282
  yaml_data.append(v["type"])
283
+ yaml_data.append(CLOUD_SETTING["type"]) # type: ignore
271
284
 
272
- def update_client(self, yaml_data: Dict[str, Any]) -> None:
285
+ def update_client(self, yaml_data: dict[str, Any]) -> None:
273
286
  yaml_data["description"] = update_description(yaml_data["description"], default_description=yaml_data["name"])
274
287
  yaml_data["legacyFilename"] = to_snake_case(yaml_data["name"].replace(" ", "_"))
275
288
  parameters = yaml_data["parameters"]
@@ -325,7 +338,11 @@ class PreProcessPlugin(YamlUpdatePlugin):
325
338
  o["hasEtag"] = True
326
339
  yaml_data["hasEtag"] = True
327
340
 
328
- def get_operation_updater(self, yaml_data: Dict[str, Any]) -> Callable[[Dict[str, Any], Dict[str, Any]], None]:
341
+ # add client signature cloud_setting for arm
342
+ if self.azure_arm and yaml_data["parameters"]:
343
+ yaml_data["parameters"].append(CLOUD_SETTING)
344
+
345
+ def get_operation_updater(self, yaml_data: dict[str, Any]) -> Callable[[dict[str, Any], dict[str, Any]], None]:
329
346
  if yaml_data["discriminator"] == "lropaging":
330
347
  return self.update_lro_paging_operation
331
348
  if yaml_data["discriminator"] == "lro":
@@ -334,7 +351,7 @@ class PreProcessPlugin(YamlUpdatePlugin):
334
351
  return self.update_paging_operation
335
352
  return self.update_operation
336
353
 
337
- def update_parameter(self, yaml_data: Dict[str, Any]) -> None:
354
+ def update_parameter(self, yaml_data: dict[str, Any]) -> None:
338
355
  yaml_data["description"] = update_description(yaml_data.get("description", ""))
339
356
  if not (yaml_data["location"] == "header" and yaml_data["clientName"] in ("content_type", "accept")):
340
357
  yaml_data["clientName"] = self.pad_reserved_words(yaml_data["clientName"].lower(), PadType.PARAMETER)
@@ -358,8 +375,8 @@ class PreProcessPlugin(YamlUpdatePlugin):
358
375
 
359
376
  def update_operation(
360
377
  self,
361
- code_model: Dict[str, Any],
362
- yaml_data: Dict[str, Any],
378
+ code_model: dict[str, Any],
379
+ yaml_data: dict[str, Any],
363
380
  *,
364
381
  is_overload: bool = False,
365
382
  ) -> None:
@@ -390,7 +407,7 @@ class PreProcessPlugin(YamlUpdatePlugin):
390
407
  self.add_body_param_type(code_model, body_parameter)
391
408
  add_overloads_for_body_param(yaml_data)
392
409
 
393
- def _update_lro_operation_helper(self, yaml_data: Dict[str, Any]) -> None:
410
+ def _update_lro_operation_helper(self, yaml_data: dict[str, Any]) -> None:
394
411
  for response in yaml_data.get("responses", []):
395
412
  response["discriminator"] = "lro"
396
413
  response["pollerSync"] = response.get("pollerSync") or "azure.core.polling.LROPoller"
@@ -410,10 +427,10 @@ class PreProcessPlugin(YamlUpdatePlugin):
410
427
 
411
428
  def update_lro_paging_operation(
412
429
  self,
413
- code_model: Dict[str, Any],
414
- yaml_data: Dict[str, Any],
430
+ code_model: dict[str, Any],
431
+ yaml_data: dict[str, Any],
415
432
  is_overload: bool = False,
416
- item_type: Optional[Dict[str, Any]] = None,
433
+ item_type: Optional[dict[str, Any]] = None,
417
434
  ) -> None:
418
435
  self.update_lro_operation(code_model, yaml_data, is_overload=is_overload)
419
436
  self.update_paging_operation(code_model, yaml_data, is_overload=is_overload, item_type=item_type)
@@ -430,11 +447,11 @@ class PreProcessPlugin(YamlUpdatePlugin):
430
447
 
431
448
  def update_lro_operation(
432
449
  self,
433
- code_model: Dict[str, Any],
434
- yaml_data: Dict[str, Any],
450
+ code_model: dict[str, Any],
451
+ yaml_data: dict[str, Any],
435
452
  is_overload: bool = False,
436
453
  ) -> None:
437
- def convert_initial_operation_response_type(data: Dict[str, Any]) -> None:
454
+ def convert_initial_operation_response_type(data: dict[str, Any]) -> None:
438
455
  for response in data.get("responses", []):
439
456
  response["type"] = KNOWN_TYPES["binary"]
440
457
 
@@ -449,10 +466,10 @@ class PreProcessPlugin(YamlUpdatePlugin):
449
466
 
450
467
  def update_paging_operation(
451
468
  self,
452
- code_model: Dict[str, Any],
453
- yaml_data: Dict[str, Any],
469
+ code_model: dict[str, Any],
470
+ yaml_data: dict[str, Any],
454
471
  is_overload: bool = False,
455
- item_type: Optional[Dict[str, Any]] = None,
472
+ item_type: Optional[dict[str, Any]] = None,
456
473
  ) -> None:
457
474
  self.update_operation(code_model, yaml_data, is_overload=is_overload)
458
475
  item_type = item_type or yaml_data["itemType"]["elementType"]
@@ -470,7 +487,7 @@ class PreProcessPlugin(YamlUpdatePlugin):
470
487
  for overload in yaml_data.get("overloads", []):
471
488
  self.update_paging_operation(code_model, overload, is_overload=True, item_type=item_type)
472
489
 
473
- def update_operation_groups(self, code_model: Dict[str, Any], client: Dict[str, Any]) -> None:
490
+ def update_operation_groups(self, code_model: dict[str, Any], client: dict[str, Any]) -> None:
474
491
  operation_groups_yaml_data = client.get("operationGroups", [])
475
492
  for operation_group in operation_groups_yaml_data:
476
493
  operation_group["identifyName"] = self.pad_reserved_words(
@@ -491,7 +508,7 @@ class PreProcessPlugin(YamlUpdatePlugin):
491
508
  if operation_group.get("operationGroups"):
492
509
  self.update_operation_groups(code_model, operation_group)
493
510
 
494
- def update_yaml(self, yaml_data: Dict[str, Any]) -> None:
511
+ def update_yaml(self, yaml_data: dict[str, Any]) -> None:
495
512
  """Convert in place the YAML str."""
496
513
  self.update_types(yaml_data["types"])
497
514
  yaml_data["types"] += KNOWN_TYPES.values()
@@ -4,14 +4,14 @@
4
4
  # license information.
5
5
  # --------------------------------------------------------------------------
6
6
  import re
7
- from typing import Any, Dict
7
+ from typing import Any
8
8
  from .python_mappings import (
9
9
  REDEFINED_BUILTINS,
10
10
  BUILTIN_PACKAGES,
11
11
  )
12
12
 
13
13
 
14
- def add_redefined_builtin_info(name: str, yaml_data: Dict[str, Any]) -> None:
14
+ def add_redefined_builtin_info(name: str, yaml_data: dict[str, Any]) -> None:
15
15
  if name in REDEFINED_BUILTINS:
16
16
  yaml_data["pylintDisable"] = "redefined-builtin"
17
17
 
@@ -3,7 +3,7 @@
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 Any, Dict, Tuple, List
6
+ from typing import Any
7
7
  import re
8
8
  import argparse
9
9
 
@@ -12,7 +12,7 @@ TYPESPEC_PACKAGE_MODE = ["azure-mgmt", "azure-dataplane", "generic"]
12
12
  VALID_PACKAGE_MODE = SWAGGER_PACKAGE_MODE + TYPESPEC_PACKAGE_MODE
13
13
 
14
14
 
15
- def update_enum_value(name: str, value: Any, description: str, enum_type: Dict[str, Any]) -> Dict[str, Any]:
15
+ def update_enum_value(name: str, value: Any, description: str, enum_type: dict[str, Any]) -> dict[str, Any]:
16
16
  return {
17
17
  "name": name,
18
18
  "type": "enumvalue",
@@ -49,7 +49,7 @@ def to_snake_case(name: str) -> str:
49
49
 
50
50
  def parse_args(
51
51
  need_tsp_file: bool = True,
52
- ) -> Tuple[argparse.Namespace, Dict[str, Any]]:
52
+ ) -> tuple[argparse.Namespace, dict[str, Any]]:
53
53
  parser = argparse.ArgumentParser(
54
54
  description="Run mypy against target folder. Add a local custom plugin to the path prior to execution. "
55
55
  )
@@ -92,7 +92,7 @@ def parse_args(
92
92
  return args, unknown_args_ret
93
93
 
94
94
 
95
- def get_body_type_for_description(body_parameter: Dict[str, Any]) -> str:
95
+ def get_body_type_for_description(body_parameter: dict[str, Any]) -> str:
96
96
  if body_parameter["type"]["type"] == "binary":
97
97
  return "binary"
98
98
  if body_parameter["type"]["type"] == "string":
@@ -101,7 +101,7 @@ def get_body_type_for_description(body_parameter: Dict[str, Any]) -> str:
101
101
 
102
102
 
103
103
  # used if we want to get a string / binary type etc
104
- KNOWN_TYPES: Dict[str, Dict[str, Any]] = {
104
+ KNOWN_TYPES: dict[str, dict[str, Any]] = {
105
105
  "string": {"type": "string"},
106
106
  "binary": {"type": "binary"},
107
107
  "anydict": {"type": "dict", "elementType": {"type": "any"}},
@@ -118,7 +118,7 @@ def build_policies(
118
118
  *,
119
119
  is_azure_flavor: bool = False,
120
120
  tracing: bool = True,
121
- ) -> List[str]:
121
+ ) -> list[str]:
122
122
  if is_azure_flavor:
123
123
  # for Azure
124
124
  async_prefix = "Async" if async_mode else ""
@@ -46,7 +46,6 @@ pygen/codegen/serializers/client_serializer.py
46
46
  pygen/codegen/serializers/enum_serializer.py
47
47
  pygen/codegen/serializers/general_serializer.py
48
48
  pygen/codegen/serializers/import_serializer.py
49
- pygen/codegen/serializers/metadata_serializer.py
50
49
  pygen/codegen/serializers/model_init_serializer.py
51
50
  pygen/codegen/serializers/model_serializer.py
52
51
  pygen/codegen/serializers/operation_groups_serializer.py
@@ -70,7 +69,6 @@ pygen/codegen/templates/keywords.jinja2
70
69
  pygen/codegen/templates/lro_operation.py.jinja2
71
70
  pygen/codegen/templates/lro_paging_operation.py.jinja2
72
71
  pygen/codegen/templates/macros.jinja2
73
- pygen/codegen/templates/metadata.json.jinja2
74
72
  pygen/codegen/templates/model_base.py.jinja2
75
73
  pygen/codegen/templates/model_container.py.jinja2
76
74
  pygen/codegen/templates/model_dpg.py.jinja2
@@ -95,3 +95,82 @@ async def test_lro_begin_delete(client):
95
95
  order_name="order1",
96
96
  )
97
97
  ).result()
98
+
99
+
100
+ @pytest.mark.asyncio
101
+ async def test_optional_body_get(client):
102
+ result = await client.optional_body.get(
103
+ resource_group_name=RESOURCE_GROUP_NAME,
104
+ widget_name="widget1",
105
+ )
106
+ assert result.name == "widget1"
107
+ assert (
108
+ result.id
109
+ == "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Azure.ResourceManager.OperationTemplates/widgets/widget1"
110
+ )
111
+ assert result.type == "Azure.ResourceManager.OperationTemplates/widgets"
112
+ assert result.location == "eastus"
113
+ assert result.properties.name == "widget1"
114
+ assert result.properties.description == "A test widget"
115
+ assert result.properties.provisioning_state == "Succeeded"
116
+
117
+
118
+ @pytest.mark.asyncio
119
+ async def test_optional_body_patch_without_body(client):
120
+ result = await client.optional_body.patch(
121
+ resource_group_name=RESOURCE_GROUP_NAME,
122
+ widget_name="widget1",
123
+ )
124
+ assert result.name == "widget1"
125
+ assert result.properties.name == "widget1"
126
+ assert result.properties.description == "A test widget"
127
+
128
+
129
+ @pytest.mark.asyncio
130
+ async def test_optional_body_patch_with_body(client):
131
+ result = await client.optional_body.patch(
132
+ resource_group_name=RESOURCE_GROUP_NAME,
133
+ widget_name="widget1",
134
+ properties=models.Widget(
135
+ location="eastus",
136
+ properties=models.WidgetProperties(name="updated-widget", description="Updated description"),
137
+ ),
138
+ )
139
+ assert result.name == "widget1"
140
+ assert result.properties.name == "updated-widget"
141
+ assert result.properties.description == "Updated description"
142
+
143
+
144
+ @pytest.mark.asyncio
145
+ async def test_optional_body_post_without_body(client):
146
+ result = await client.optional_body.post(
147
+ resource_group_name=RESOURCE_GROUP_NAME,
148
+ widget_name="widget1",
149
+ )
150
+ assert result.result == "Action completed successfully"
151
+
152
+
153
+ @pytest.mark.asyncio
154
+ async def test_optional_body_post_with_body(client):
155
+ result = await client.optional_body.post(
156
+ resource_group_name=RESOURCE_GROUP_NAME,
157
+ widget_name="widget1",
158
+ body=models.ActionRequest(action_type="perform", parameters="test-parameters"),
159
+ )
160
+ assert result.result == "Action completed successfully with parameters"
161
+
162
+
163
+ @pytest.mark.asyncio
164
+ async def test_optional_body_provider_post_without_body(client):
165
+ result = await client.optional_body.provider_post()
166
+ assert result.total_allowed == 50
167
+ assert result.status == "Changed to default allowance"
168
+
169
+
170
+ @pytest.mark.asyncio
171
+ async def test_optional_body_provider_post_with_body(client):
172
+ result = await client.optional_body.provider_post(
173
+ body=models.ChangeAllowanceRequest(total_allowed=100, reason="Increased demand"),
174
+ )
175
+ assert result.total_allowed == 100
176
+ assert result.status == "Changed to requested allowance"
@@ -0,0 +1,53 @@
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.hierarchybuilding.aio import HierarchyBuildingClient
8
+ from specs.azure.clientgenerator.core.hierarchybuilding.models import (
9
+ Pet,
10
+ Dog,
11
+ )
12
+
13
+
14
+ @pytest.fixture
15
+ async def client():
16
+ async with HierarchyBuildingClient() as client:
17
+ yield client
18
+
19
+
20
+ # ========== test for spector ==========
21
+
22
+
23
+ @pytest.mark.asyncio
24
+ async def test_update_pet_as_pet(client: HierarchyBuildingClient):
25
+ resp = Pet(name="Buddy", trained=True)
26
+ assert await client.pet_operations.update_pet_as_pet(Pet(name="Buddy", trained=True)) == resp
27
+
28
+
29
+ @pytest.mark.asyncio
30
+ async def test_update_dog_as_pet(client: HierarchyBuildingClient):
31
+ resp = Dog(name="Rex", trained=True, breed="German Shepherd")
32
+ assert await client.pet_operations.update_dog_as_pet(Dog(name="Rex", trained=True, breed="German Shepherd")) == resp
33
+
34
+
35
+ @pytest.mark.asyncio
36
+ async def test_update_pet_as_animal(client: HierarchyBuildingClient):
37
+ resp = Pet(name="Buddy", trained=True)
38
+ assert await client.animal_operations.update_pet_as_animal(Pet(name="Buddy", trained=True)) == resp
39
+
40
+
41
+ @pytest.mark.asyncio
42
+ async def test_update_dog_as_animal(client: HierarchyBuildingClient):
43
+ resp = Dog(name="Rex", trained=True, breed="German Shepherd")
44
+ assert (
45
+ await client.animal_operations.update_dog_as_animal(Dog(name="Rex", trained=True, breed="German Shepherd"))
46
+ == resp
47
+ )
48
+
49
+
50
+ @pytest.mark.asyncio
51
+ async def test_update_dog_as_dog(client: HierarchyBuildingClient):
52
+ resp = Dog(name="Rex", trained=True, breed="German Shepherd")
53
+ assert await client.dog_operations.update_dog_as_dog(Dog(name="Rex", trained=True, breed="German Shepherd")) == resp
@@ -4,8 +4,8 @@
4
4
  # license information.
5
5
  # --------------------------------------------------------------------------
6
6
  import pytest
7
- from client.naming.aio import NamingClient
8
- from client.naming import models
7
+ from client.naming.main.aio import NamingClient
8
+ from client.naming.main import models
9
9
 
10
10
 
11
11
  @pytest.fixture
@@ -51,12 +51,12 @@ async def test_header_response(client: NamingClient):
51
51
 
52
52
  @pytest.mark.asyncio
53
53
  async def test_model_client(client: NamingClient):
54
- await client.client_model.client(models.ClientModel(default_name=True))
54
+ await client.model_client.client(models.ClientModel(default_name=True))
55
55
 
56
56
 
57
57
  @pytest.mark.asyncio
58
58
  async def test_model_language(client: NamingClient):
59
- await client.client_model.language(models.PythonModel(default_name=True))
59
+ await client.model_client.language(models.PythonModel(default_name=True))
60
60
 
61
61
 
62
62
  @pytest.mark.asyncio
@@ -0,0 +1,37 @@
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 client.naming.enumconflict.aio import EnumConflictClient
8
+ from client.naming.enumconflict.firstnamespace import models as first_models
9
+ from client.naming.enumconflict.secondnamespace import models as second_models
10
+
11
+
12
+ @pytest.fixture
13
+ async def client():
14
+ async with EnumConflictClient() as client:
15
+ yield client
16
+
17
+
18
+ @pytest.mark.asyncio
19
+ async def test_first_operations_first_async(client: EnumConflictClient):
20
+ """Test enum with same name in different namespace - first namespace (async)."""
21
+ body = first_models.FirstModel(status=first_models.Status.ACTIVE, name="test")
22
+
23
+ response = await client.first_operations.first(body=body)
24
+
25
+ assert response.status == "active"
26
+ assert response.name == "test"
27
+
28
+
29
+ @pytest.mark.asyncio
30
+ async def test_second_operations_second_async(client: EnumConflictClient):
31
+ """Test enum with same name in different namespace - second namespace (async)."""
32
+ body = second_models.SecondModel(status=second_models.SecondStatus.RUNNING, description="test description")
33
+
34
+ response = await client.second_operations.second(body=body)
35
+
36
+ assert response.status == "running"
37
+ assert response.description == "test description"
@@ -8,7 +8,7 @@ import subprocess
8
8
  import signal
9
9
  import pytest
10
10
  import re
11
- from typing import Literal, List
11
+ from typing import Literal
12
12
  from pathlib import Path
13
13
 
14
14
  FILE_FOLDER = Path(__file__).parent
@@ -191,7 +191,7 @@ SPECIAL_WORDS = [
191
191
 
192
192
 
193
193
  @pytest.fixture
194
- def special_words() -> List[str]:
194
+ def special_words() -> list[str]:
195
195
  return SPECIAL_WORDS
196
196
 
197
197