@typespec/http-client-python 0.15.2 → 0.16.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/dist/emitter/code-model.d.ts.map +1 -1
- package/dist/emitter/code-model.js +8 -1
- package/dist/emitter/code-model.js.map +1 -1
- package/dist/emitter/http.d.ts +5 -0
- package/dist/emitter/http.d.ts.map +1 -1
- package/dist/emitter/http.js +20 -1
- package/dist/emitter/http.js.map +1 -1
- package/emitter/src/code-model.ts +12 -0
- package/emitter/src/http.ts +23 -1
- package/emitter/temp/tsconfig.tsbuildinfo +1 -1
- package/eng/scripts/ci/regenerate.ts +1 -1
- package/eng/scripts/ci/util.py +1 -1
- package/eng/scripts/setup/__pycache__/package_manager.cpython-39.pyc +0 -0
- package/eng/scripts/setup/__pycache__/venvtools.cpython-39.pyc +0 -0
- package/generator/build/lib/pygen/__init__.py +7 -21
- package/generator/build/lib/pygen/codegen/__init__.py +4 -4
- package/generator/build/lib/pygen/codegen/models/__init__.py +2 -2
- package/generator/build/lib/pygen/codegen/models/base.py +9 -12
- package/generator/build/lib/pygen/codegen/models/base_builder.py +4 -6
- package/generator/build/lib/pygen/codegen/models/client.py +61 -102
- package/generator/build/lib/pygen/codegen/models/code_model.py +29 -29
- package/generator/build/lib/pygen/codegen/models/combined_type.py +7 -7
- package/generator/build/lib/pygen/codegen/models/constant_type.py +4 -11
- package/generator/build/lib/pygen/codegen/models/credential_types.py +9 -11
- package/generator/build/lib/pygen/codegen/models/dictionary_type.py +7 -8
- package/generator/build/lib/pygen/codegen/models/enum_type.py +7 -7
- package/generator/build/lib/pygen/codegen/models/imports.py +24 -29
- package/generator/build/lib/pygen/codegen/models/list_type.py +15 -14
- package/generator/build/lib/pygen/codegen/models/lro_operation.py +6 -6
- package/generator/build/lib/pygen/codegen/models/lro_paging_operation.py +2 -2
- package/generator/build/lib/pygen/codegen/models/model_type.py +11 -11
- package/generator/build/lib/pygen/codegen/models/operation.py +26 -56
- package/generator/build/lib/pygen/codegen/models/operation_group.py +11 -22
- package/generator/build/lib/pygen/codegen/models/paging_operation.py +15 -19
- package/generator/build/lib/pygen/codegen/models/parameter.py +12 -21
- package/generator/build/lib/pygen/codegen/models/parameter_list.py +37 -39
- package/generator/build/lib/pygen/codegen/models/primitive_types.py +24 -18
- package/generator/build/lib/pygen/codegen/models/property.py +10 -10
- package/generator/build/lib/pygen/codegen/models/request_builder.py +7 -8
- package/generator/build/lib/pygen/codegen/models/request_builder_parameter.py +3 -3
- package/generator/build/lib/pygen/codegen/models/response.py +15 -40
- package/generator/build/lib/pygen/codegen/models/utils.py +2 -2
- package/generator/build/lib/pygen/codegen/serializers/__init__.py +15 -40
- package/generator/build/lib/pygen/codegen/serializers/builder_serializer.py +101 -94
- package/generator/build/lib/pygen/codegen/serializers/client_serializer.py +22 -25
- package/generator/build/lib/pygen/codegen/serializers/enum_serializer.py +2 -2
- package/generator/build/lib/pygen/codegen/serializers/general_serializer.py +46 -60
- package/generator/build/lib/pygen/codegen/serializers/import_serializer.py +6 -7
- package/generator/build/lib/pygen/codegen/serializers/model_init_serializer.py +1 -2
- package/generator/build/lib/pygen/codegen/serializers/model_serializer.py +15 -17
- package/generator/build/lib/pygen/codegen/serializers/operation_groups_serializer.py +3 -3
- package/generator/build/lib/pygen/codegen/serializers/operations_init_serializer.py +5 -6
- package/generator/build/lib/pygen/codegen/serializers/parameter_serializer.py +28 -18
- package/generator/build/lib/pygen/codegen/serializers/patch_serializer.py +1 -2
- package/generator/build/lib/pygen/codegen/serializers/request_builders_serializer.py +1 -2
- package/generator/build/lib/pygen/codegen/serializers/sample_serializer.py +9 -14
- package/generator/build/lib/pygen/codegen/serializers/test_serializer.py +7 -7
- package/generator/build/lib/pygen/codegen/serializers/utils.py +2 -2
- package/generator/build/lib/pygen/codegen/templates/model_base.py.jinja2 +30 -24
- package/generator/build/lib/pygen/codegen/templates/model_dpg.py.jinja2 +1 -1
- package/generator/build/lib/pygen/codegen/templates/operation_group.py.jinja2 +1 -11
- package/generator/build/lib/pygen/codegen/templates/operations_folder_init.py.jinja2 +1 -1
- package/generator/build/lib/pygen/codegen/templates/packaging_templates/dev_requirements.txt.jinja2 +1 -1
- package/generator/build/lib/pygen/codegen/templates/packaging_templates/pyproject.toml.jinja2 +7 -0
- package/generator/build/lib/pygen/codegen/templates/patch.py.jinja2 +1 -1
- package/generator/build/lib/pygen/codegen/templates/serialization.py.jinja2 +11 -13
- package/generator/build/lib/pygen/codegen/templates/utils.py.jinja2 +6 -6
- package/generator/build/lib/pygen/preprocess/__init__.py +47 -30
- package/generator/build/lib/pygen/preprocess/helpers.py +2 -2
- package/generator/build/lib/pygen/utils.py +6 -6
- package/generator/dist/pygen-0.1.0-py3-none-any.whl +0 -0
- package/generator/pygen/__init__.py +7 -21
- package/generator/pygen/codegen/__init__.py +4 -4
- package/generator/pygen/codegen/models/__init__.py +2 -2
- package/generator/pygen/codegen/models/base.py +9 -12
- package/generator/pygen/codegen/models/base_builder.py +4 -6
- package/generator/pygen/codegen/models/client.py +61 -102
- package/generator/pygen/codegen/models/code_model.py +29 -29
- package/generator/pygen/codegen/models/combined_type.py +7 -7
- package/generator/pygen/codegen/models/constant_type.py +4 -11
- package/generator/pygen/codegen/models/credential_types.py +9 -11
- package/generator/pygen/codegen/models/dictionary_type.py +7 -8
- package/generator/pygen/codegen/models/enum_type.py +7 -7
- package/generator/pygen/codegen/models/imports.py +24 -29
- package/generator/pygen/codegen/models/list_type.py +15 -14
- package/generator/pygen/codegen/models/lro_operation.py +6 -6
- package/generator/pygen/codegen/models/lro_paging_operation.py +2 -2
- package/generator/pygen/codegen/models/model_type.py +11 -11
- package/generator/pygen/codegen/models/operation.py +26 -56
- package/generator/pygen/codegen/models/operation_group.py +11 -22
- package/generator/pygen/codegen/models/paging_operation.py +15 -19
- package/generator/pygen/codegen/models/parameter.py +12 -21
- package/generator/pygen/codegen/models/parameter_list.py +37 -39
- package/generator/pygen/codegen/models/primitive_types.py +24 -18
- package/generator/pygen/codegen/models/property.py +10 -10
- package/generator/pygen/codegen/models/request_builder.py +7 -8
- package/generator/pygen/codegen/models/request_builder_parameter.py +3 -3
- package/generator/pygen/codegen/models/response.py +15 -40
- package/generator/pygen/codegen/models/utils.py +2 -2
- package/generator/pygen/codegen/serializers/__init__.py +15 -40
- package/generator/pygen/codegen/serializers/builder_serializer.py +101 -94
- package/generator/pygen/codegen/serializers/client_serializer.py +22 -25
- package/generator/pygen/codegen/serializers/enum_serializer.py +2 -2
- package/generator/pygen/codegen/serializers/general_serializer.py +46 -60
- package/generator/pygen/codegen/serializers/import_serializer.py +6 -7
- package/generator/pygen/codegen/serializers/model_init_serializer.py +1 -2
- package/generator/pygen/codegen/serializers/model_serializer.py +15 -17
- package/generator/pygen/codegen/serializers/operation_groups_serializer.py +3 -3
- package/generator/pygen/codegen/serializers/operations_init_serializer.py +5 -6
- package/generator/pygen/codegen/serializers/parameter_serializer.py +28 -18
- package/generator/pygen/codegen/serializers/patch_serializer.py +1 -2
- package/generator/pygen/codegen/serializers/request_builders_serializer.py +1 -2
- package/generator/pygen/codegen/serializers/sample_serializer.py +9 -14
- package/generator/pygen/codegen/serializers/test_serializer.py +7 -7
- package/generator/pygen/codegen/serializers/utils.py +2 -2
- package/generator/pygen/codegen/templates/model_base.py.jinja2 +30 -24
- package/generator/pygen/codegen/templates/model_dpg.py.jinja2 +1 -1
- package/generator/pygen/codegen/templates/operation_group.py.jinja2 +1 -11
- package/generator/pygen/codegen/templates/operations_folder_init.py.jinja2 +1 -1
- package/generator/pygen/codegen/templates/packaging_templates/dev_requirements.txt.jinja2 +1 -1
- package/generator/pygen/codegen/templates/packaging_templates/pyproject.toml.jinja2 +7 -0
- package/generator/pygen/codegen/templates/patch.py.jinja2 +1 -1
- package/generator/pygen/codegen/templates/serialization.py.jinja2 +11 -13
- package/generator/pygen/codegen/templates/utils.py.jinja2 +6 -6
- package/generator/pygen/preprocess/__init__.py +47 -30
- package/generator/pygen/preprocess/helpers.py +2 -2
- package/generator/pygen/utils.py +6 -6
- package/generator/pygen.egg-info/SOURCES.txt +0 -2
- package/generator/test/azure/mock_api_tests/asynctests/test_azure_arm_operationtemplates_async.py +79 -0
- package/generator/test/azure/mock_api_tests/asynctests/test_client_naming_async.py +4 -4
- package/generator/test/azure/mock_api_tests/asynctests/test_client_naming_enum_conflict_async.py +37 -0
- package/generator/test/azure/mock_api_tests/conftest.py +2 -2
- package/generator/test/azure/mock_api_tests/test_azure_arm_operationtemplates.py +72 -0
- package/generator/test/azure/mock_api_tests/test_client_naming.py +3 -3
- package/generator/test/azure/mock_api_tests/test_client_naming_enum_conflict.py +35 -0
- package/generator/test/azure/requirements.txt +1 -0
- package/generator/test/unbranded/mock_api_tests/conftest.py +1 -2
- package/generator/test/unittests/test_model_base_serialization.py +88 -92
- package/generator/test/unittests/test_model_base_xml_serialization.py +19 -23
- package/package.json +8 -8
- package/generator/build/lib/pygen/codegen/serializers/metadata_serializer.py +0 -216
- package/generator/build/lib/pygen/codegen/templates/metadata.json.jinja2 +0 -167
- package/generator/pygen/codegen/serializers/metadata_serializer.py +0 -216
- 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:
|
|
229
|
-
_attribute_map:
|
|
230
|
-
_validation:
|
|
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[
|
|
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,
|
|
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,
|
|
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
|
|
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:
|
|
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
|
|
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(
|
|
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:
|
|
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
|
-
|
|
69
|
+
tuple[Optional[str], FileContent],
|
|
70
70
|
# (filename, file (or bytes), content_type)
|
|
71
|
-
|
|
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:
|
|
81
|
-
) ->
|
|
82
|
-
files:
|
|
83
|
-
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] = {}
|
|
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,
|
|
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:
|
|
30
|
-
yaml_data:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
193
|
-
body_parameter:
|
|
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:
|
|
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:
|
|
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
|
-
|
|
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:
|
|
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:
|
|
362
|
-
yaml_data:
|
|
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:
|
|
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:
|
|
414
|
-
yaml_data:
|
|
430
|
+
code_model: dict[str, Any],
|
|
431
|
+
yaml_data: dict[str, Any],
|
|
415
432
|
is_overload: bool = False,
|
|
416
|
-
item_type: Optional[
|
|
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:
|
|
434
|
-
yaml_data:
|
|
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:
|
|
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:
|
|
453
|
-
yaml_data:
|
|
469
|
+
code_model: dict[str, Any],
|
|
470
|
+
yaml_data: dict[str, Any],
|
|
454
471
|
is_overload: bool = False,
|
|
455
|
-
item_type: Optional[
|
|
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:
|
|
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:
|
|
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
|
|
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:
|
|
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
|
|
package/generator/pygen/utils.py
CHANGED
|
@@ -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
|
|
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:
|
|
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
|
-
) ->
|
|
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:
|
|
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:
|
|
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
|
-
) ->
|
|
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
|
package/generator/test/azure/mock_api_tests/asynctests/test_azure_arm_operationtemplates_async.py
CHANGED
|
@@ -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"
|
|
@@ -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.
|
|
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.
|
|
59
|
+
await client.model_client.language(models.PythonModel(default_name=True))
|
|
60
60
|
|
|
61
61
|
|
|
62
62
|
@pytest.mark.asyncio
|
package/generator/test/azure/mock_api_tests/asynctests/test_client_naming_enum_conflict_async.py
ADDED
|
@@ -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
|
|
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() ->
|
|
194
|
+
def special_words() -> list[str]:
|
|
195
195
|
return SPECIAL_WORDS
|
|
196
196
|
|
|
197
197
|
|
|
@@ -82,3 +82,75 @@ def test_lro_begin_delete(client):
|
|
|
82
82
|
resource_group_name=RESOURCE_GROUP_NAME,
|
|
83
83
|
order_name="order1",
|
|
84
84
|
).result()
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def test_optional_body_get(client):
|
|
88
|
+
result = client.optional_body.get(
|
|
89
|
+
resource_group_name=RESOURCE_GROUP_NAME,
|
|
90
|
+
widget_name="widget1",
|
|
91
|
+
)
|
|
92
|
+
assert result.name == "widget1"
|
|
93
|
+
assert (
|
|
94
|
+
result.id
|
|
95
|
+
== "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Azure.ResourceManager.OperationTemplates/widgets/widget1"
|
|
96
|
+
)
|
|
97
|
+
assert result.type == "Azure.ResourceManager.OperationTemplates/widgets"
|
|
98
|
+
assert result.location == "eastus"
|
|
99
|
+
assert result.properties.name == "widget1"
|
|
100
|
+
assert result.properties.description == "A test widget"
|
|
101
|
+
assert result.properties.provisioning_state == "Succeeded"
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def test_optional_body_patch_without_body(client):
|
|
105
|
+
result = client.optional_body.patch(
|
|
106
|
+
resource_group_name=RESOURCE_GROUP_NAME,
|
|
107
|
+
widget_name="widget1",
|
|
108
|
+
)
|
|
109
|
+
assert result.name == "widget1"
|
|
110
|
+
assert result.properties.name == "widget1"
|
|
111
|
+
assert result.properties.description == "A test widget"
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def test_optional_body_patch_with_body(client):
|
|
115
|
+
result = client.optional_body.patch(
|
|
116
|
+
resource_group_name=RESOURCE_GROUP_NAME,
|
|
117
|
+
widget_name="widget1",
|
|
118
|
+
properties=models.Widget(
|
|
119
|
+
location="eastus",
|
|
120
|
+
properties=models.WidgetProperties(name="updated-widget", description="Updated description"),
|
|
121
|
+
),
|
|
122
|
+
)
|
|
123
|
+
assert result.name == "widget1"
|
|
124
|
+
assert result.properties.name == "updated-widget"
|
|
125
|
+
assert result.properties.description == "Updated description"
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def test_optional_body_post_without_body(client):
|
|
129
|
+
result = client.optional_body.post(
|
|
130
|
+
resource_group_name=RESOURCE_GROUP_NAME,
|
|
131
|
+
widget_name="widget1",
|
|
132
|
+
)
|
|
133
|
+
assert result.result == "Action completed successfully"
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
def test_optional_body_post_with_body(client):
|
|
137
|
+
result = client.optional_body.post(
|
|
138
|
+
resource_group_name=RESOURCE_GROUP_NAME,
|
|
139
|
+
widget_name="widget1",
|
|
140
|
+
body=models.ActionRequest(action_type="perform", parameters="test-parameters"),
|
|
141
|
+
)
|
|
142
|
+
assert result.result == "Action completed successfully with parameters"
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
def test_optional_body_provider_post_without_body(client):
|
|
146
|
+
result = client.optional_body.provider_post()
|
|
147
|
+
assert result.total_allowed == 50
|
|
148
|
+
assert result.status == "Changed to default allowance"
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
def test_optional_body_provider_post_with_body(client):
|
|
152
|
+
result = client.optional_body.provider_post(
|
|
153
|
+
body=models.ChangeAllowanceRequest(total_allowed=100, reason="Increased demand"),
|
|
154
|
+
)
|
|
155
|
+
assert result.total_allowed == 100
|
|
156
|
+
assert result.status == "Changed to requested allowance"
|