@typespec/http-client-python 0.4.3 → 0.5.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/emitter.d.ts.map +1 -1
- package/dist/emitter/emitter.js +85 -24
- package/dist/emitter/emitter.js.map +1 -1
- package/dist/emitter/lib.d.ts +1 -0
- package/dist/emitter/lib.d.ts.map +1 -1
- package/dist/emitter/lib.js +1 -0
- package/dist/emitter/lib.js.map +1 -1
- package/dist/emitter/run-python3.d.ts +2 -0
- package/dist/emitter/run-python3.d.ts.map +1 -0
- package/dist/emitter/run-python3.js +19 -0
- package/dist/emitter/run-python3.js.map +1 -0
- package/dist/emitter/system-requirements.d.ts +17 -0
- package/dist/emitter/system-requirements.d.ts.map +1 -0
- package/dist/emitter/system-requirements.js +167 -0
- package/dist/emitter/system-requirements.js.map +1 -0
- package/emitter/src/emitter.ts +88 -23
- package/emitter/src/lib.ts +2 -0
- package/emitter/src/run-python3.ts +20 -0
- package/emitter/src/system-requirements.ts +261 -0
- package/emitter/temp/tsconfig.tsbuildinfo +1 -1
- package/eng/scripts/ci/regenerate.ts +16 -4
- package/eng/scripts/setup/__pycache__/venvtools.cpython-38.pyc +0 -0
- package/eng/scripts/setup/build.ts +16 -0
- package/eng/scripts/setup/build_pygen_wheel.py +40 -0
- package/eng/scripts/setup/install.py +9 -3
- package/eng/scripts/setup/install.ts +32 -0
- package/eng/scripts/setup/prepare.py +3 -1
- package/eng/scripts/setup/prepare.ts +11 -0
- package/eng/scripts/setup/run-python3.ts +1 -6
- package/generator/build/lib/pygen/__init__.py +107 -0
- package/generator/build/lib/pygen/_version.py +7 -0
- package/generator/build/lib/pygen/black.py +71 -0
- package/generator/build/lib/pygen/codegen/__init__.py +357 -0
- package/generator/build/lib/pygen/codegen/_utils.py +17 -0
- package/generator/build/lib/pygen/codegen/models/__init__.py +204 -0
- package/generator/build/lib/pygen/codegen/models/base.py +186 -0
- package/generator/build/lib/pygen/codegen/models/base_builder.py +118 -0
- package/generator/build/lib/pygen/codegen/models/client.py +435 -0
- package/generator/build/lib/pygen/codegen/models/code_model.py +237 -0
- package/generator/build/lib/pygen/codegen/models/combined_type.py +149 -0
- package/generator/build/lib/pygen/codegen/models/constant_type.py +129 -0
- package/generator/build/lib/pygen/codegen/models/credential_types.py +214 -0
- package/generator/build/lib/pygen/codegen/models/dictionary_type.py +127 -0
- package/generator/build/lib/pygen/codegen/models/enum_type.py +238 -0
- package/generator/build/lib/pygen/codegen/models/imports.py +291 -0
- package/generator/build/lib/pygen/codegen/models/list_type.py +143 -0
- package/generator/build/lib/pygen/codegen/models/lro_operation.py +142 -0
- package/generator/build/lib/pygen/codegen/models/lro_paging_operation.py +32 -0
- package/generator/build/lib/pygen/codegen/models/model_type.py +357 -0
- package/generator/build/lib/pygen/codegen/models/operation.py +509 -0
- package/generator/build/lib/pygen/codegen/models/operation_group.py +184 -0
- package/generator/build/lib/pygen/codegen/models/paging_operation.py +155 -0
- package/generator/build/lib/pygen/codegen/models/parameter.py +412 -0
- package/generator/build/lib/pygen/codegen/models/parameter_list.py +387 -0
- package/generator/build/lib/pygen/codegen/models/primitive_types.py +659 -0
- package/generator/build/lib/pygen/codegen/models/property.py +170 -0
- package/generator/build/lib/pygen/codegen/models/request_builder.py +189 -0
- package/generator/build/lib/pygen/codegen/models/request_builder_parameter.py +115 -0
- package/generator/build/lib/pygen/codegen/models/response.py +348 -0
- package/generator/build/lib/pygen/codegen/models/utils.py +21 -0
- package/generator/build/lib/pygen/codegen/serializers/__init__.py +574 -0
- package/generator/build/lib/pygen/codegen/serializers/base_serializer.py +21 -0
- package/generator/build/lib/pygen/codegen/serializers/builder_serializer.py +1533 -0
- package/generator/build/lib/pygen/codegen/serializers/client_serializer.py +294 -0
- package/generator/build/lib/pygen/codegen/serializers/enum_serializer.py +15 -0
- package/generator/build/lib/pygen/codegen/serializers/general_serializer.py +213 -0
- package/generator/build/lib/pygen/codegen/serializers/import_serializer.py +126 -0
- package/generator/build/lib/pygen/codegen/serializers/metadata_serializer.py +198 -0
- package/generator/build/lib/pygen/codegen/serializers/model_init_serializer.py +33 -0
- package/generator/build/lib/pygen/codegen/serializers/model_serializer.py +335 -0
- package/generator/build/lib/pygen/codegen/serializers/operation_groups_serializer.py +89 -0
- package/generator/build/lib/pygen/codegen/serializers/operations_init_serializer.py +44 -0
- package/generator/build/lib/pygen/codegen/serializers/parameter_serializer.py +221 -0
- package/generator/build/lib/pygen/codegen/serializers/patch_serializer.py +19 -0
- package/generator/build/lib/pygen/codegen/serializers/request_builders_serializer.py +52 -0
- package/generator/build/lib/pygen/codegen/serializers/sample_serializer.py +168 -0
- package/generator/build/lib/pygen/codegen/serializers/test_serializer.py +292 -0
- package/generator/build/lib/pygen/codegen/serializers/types_serializer.py +31 -0
- package/generator/build/lib/pygen/codegen/serializers/utils.py +68 -0
- package/generator/build/lib/pygen/codegen/templates/client.py.jinja2 +37 -0
- package/generator/build/lib/pygen/codegen/templates/client_container.py.jinja2 +12 -0
- package/generator/build/lib/pygen/codegen/templates/config.py.jinja2 +73 -0
- package/generator/build/lib/pygen/codegen/templates/config_container.py.jinja2 +16 -0
- package/generator/build/lib/pygen/codegen/templates/conftest.py.jinja2 +28 -0
- package/generator/build/lib/pygen/codegen/templates/enum.py.jinja2 +13 -0
- package/generator/build/lib/pygen/codegen/templates/enum_container.py.jinja2 +10 -0
- package/generator/build/lib/pygen/codegen/templates/init.py.jinja2 +24 -0
- package/generator/build/lib/pygen/codegen/templates/keywords.jinja2 +27 -0
- package/generator/build/lib/pygen/codegen/templates/lro_operation.py.jinja2 +16 -0
- package/generator/build/lib/pygen/codegen/templates/lro_paging_operation.py.jinja2 +18 -0
- package/generator/build/lib/pygen/codegen/templates/macros.jinja2 +12 -0
- package/generator/build/lib/pygen/codegen/templates/metadata.json.jinja2 +167 -0
- package/generator/build/lib/pygen/codegen/templates/model_base.py.jinja2 +1174 -0
- package/generator/build/lib/pygen/codegen/templates/model_container.py.jinja2 +15 -0
- package/generator/build/lib/pygen/codegen/templates/model_dpg.py.jinja2 +97 -0
- package/generator/build/lib/pygen/codegen/templates/model_init.py.jinja2 +33 -0
- package/generator/build/lib/pygen/codegen/templates/model_msrest.py.jinja2 +92 -0
- package/generator/build/lib/pygen/codegen/templates/operation.py.jinja2 +21 -0
- package/generator/build/lib/pygen/codegen/templates/operation_group.py.jinja2 +75 -0
- package/generator/build/lib/pygen/codegen/templates/operation_groups_container.py.jinja2 +19 -0
- package/generator/build/lib/pygen/codegen/templates/operation_tools.jinja2 +81 -0
- package/generator/build/lib/pygen/codegen/templates/operations_folder_init.py.jinja2 +17 -0
- package/generator/build/lib/pygen/codegen/templates/packaging_templates/CHANGELOG.md.jinja2 +6 -0
- package/generator/build/lib/pygen/codegen/templates/packaging_templates/LICENSE.jinja2 +21 -0
- package/generator/build/lib/pygen/codegen/templates/packaging_templates/MANIFEST.in.jinja2 +8 -0
- package/generator/build/lib/pygen/codegen/templates/packaging_templates/README.md.jinja2 +107 -0
- package/generator/build/lib/pygen/codegen/templates/packaging_templates/dev_requirements.txt.jinja2 +9 -0
- package/generator/build/lib/pygen/codegen/templates/packaging_templates/setup.py.jinja2 +108 -0
- package/generator/build/lib/pygen/codegen/templates/paging_operation.py.jinja2 +21 -0
- package/generator/build/lib/pygen/codegen/templates/patch.py.jinja2 +19 -0
- package/generator/build/lib/pygen/codegen/templates/pkgutil_init.py.jinja2 +1 -0
- package/generator/build/lib/pygen/codegen/templates/request_builder.py.jinja2 +28 -0
- package/generator/build/lib/pygen/codegen/templates/request_builders.py.jinja2 +10 -0
- package/generator/build/lib/pygen/codegen/templates/rest_init.py.jinja2 +12 -0
- package/generator/build/lib/pygen/codegen/templates/sample.py.jinja2 +44 -0
- package/generator/build/lib/pygen/codegen/templates/serialization.py.jinja2 +2117 -0
- package/generator/build/lib/pygen/codegen/templates/test.py.jinja2 +50 -0
- package/generator/build/lib/pygen/codegen/templates/testpreparer.py.jinja2 +26 -0
- package/generator/build/lib/pygen/codegen/templates/types.py.jinja2 +7 -0
- package/generator/build/lib/pygen/codegen/templates/validation.py.jinja2 +38 -0
- package/generator/build/lib/pygen/codegen/templates/vendor.py.jinja2 +96 -0
- package/generator/build/lib/pygen/codegen/templates/version.py.jinja2 +4 -0
- package/generator/build/lib/pygen/m2r.py +65 -0
- package/generator/build/lib/pygen/preprocess/__init__.py +515 -0
- package/generator/build/lib/pygen/preprocess/helpers.py +27 -0
- package/generator/build/lib/pygen/preprocess/python_mappings.py +226 -0
- package/generator/build/lib/pygen/utils.py +163 -0
- package/generator/component-detection-pip-report.json +134 -0
- package/generator/dev_requirements.txt +0 -1
- package/generator/dist/pygen-0.1.0-py3-none-any.whl +0 -0
- package/generator/pygen/m2r.py +1 -1
- package/generator/pygen.egg-info/PKG-INFO +7 -4
- package/generator/pygen.egg-info/requires.txt +7 -4
- package/generator/requirements.txt +5 -10
- package/generator/setup.py +7 -4
- package/generator/test/azure/requirements.txt +2 -0
- package/generator/test/generic_mock_api_tests/unittests/test_m2r.py +10 -0
- package/generator/test/unbranded/requirements.txt +2 -0
- package/package.json +6 -5
|
@@ -0,0 +1,1533 @@
|
|
|
1
|
+
# pylint: disable=too-many-lines
|
|
2
|
+
# -------------------------------------------------------------------------
|
|
3
|
+
# Copyright (c) Microsoft Corporation. All rights reserved.
|
|
4
|
+
# Licensed under the MIT License. See License.txt in the project root for
|
|
5
|
+
# license information.
|
|
6
|
+
# --------------------------------------------------------------------------
|
|
7
|
+
from abc import abstractmethod
|
|
8
|
+
from collections import defaultdict
|
|
9
|
+
from typing import Generic, List, Type, TypeVar, Dict, Union, Optional, cast
|
|
10
|
+
|
|
11
|
+
from ..models import (
|
|
12
|
+
Operation,
|
|
13
|
+
PagingOperation,
|
|
14
|
+
CodeModel,
|
|
15
|
+
LROOperation,
|
|
16
|
+
LROPagingOperation,
|
|
17
|
+
ModelType,
|
|
18
|
+
DictionaryType,
|
|
19
|
+
ListType,
|
|
20
|
+
RequestBuilder,
|
|
21
|
+
ParameterLocation,
|
|
22
|
+
Response,
|
|
23
|
+
BinaryType,
|
|
24
|
+
BodyParameter,
|
|
25
|
+
ParameterMethodLocation,
|
|
26
|
+
OverloadedRequestBuilder,
|
|
27
|
+
Property,
|
|
28
|
+
RequestBuilderType,
|
|
29
|
+
CombinedType,
|
|
30
|
+
JSONModelType,
|
|
31
|
+
DPGModelType,
|
|
32
|
+
ParameterListType,
|
|
33
|
+
ByteArraySchema,
|
|
34
|
+
)
|
|
35
|
+
from .parameter_serializer import ParameterSerializer, PopKwargType
|
|
36
|
+
from ..models.parameter_list import ParameterType
|
|
37
|
+
from . import utils
|
|
38
|
+
from ...utils import xml_serializable, json_serializable
|
|
39
|
+
|
|
40
|
+
T = TypeVar("T")
|
|
41
|
+
OrderedSet = Dict[T, None]
|
|
42
|
+
|
|
43
|
+
BuilderType = TypeVar(
|
|
44
|
+
"BuilderType",
|
|
45
|
+
bound=Union[
|
|
46
|
+
RequestBuilder,
|
|
47
|
+
Operation,
|
|
48
|
+
PagingOperation,
|
|
49
|
+
LROOperation,
|
|
50
|
+
LROPagingOperation,
|
|
51
|
+
OverloadedRequestBuilder,
|
|
52
|
+
],
|
|
53
|
+
)
|
|
54
|
+
OperationType = TypeVar(
|
|
55
|
+
"OperationType",
|
|
56
|
+
bound=Union[Operation, PagingOperation, LROOperation, LROPagingOperation],
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def _all_same(data: List[List[str]]) -> bool:
|
|
61
|
+
return len(data) > 1 and all(sorted(data[0]) == sorted(data[i]) for i in range(1, len(data)))
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def _xml_config(send_xml: bool, content_types: List[str]) -> str:
|
|
65
|
+
if not (send_xml and "xml" in str(content_types)):
|
|
66
|
+
return ""
|
|
67
|
+
if len(content_types) == 1:
|
|
68
|
+
return ", is_xml=True"
|
|
69
|
+
return ", is_xml='xml' in str(content_type)"
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def _escape_str(input_str: str) -> str:
|
|
73
|
+
replace = input_str.replace("'", "\\'")
|
|
74
|
+
return f'"{replace}"'
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def _get_polymorphic_subtype_template(polymorphic_subtype: ModelType) -> List[str]:
|
|
78
|
+
retval: List[str] = []
|
|
79
|
+
retval.append("")
|
|
80
|
+
retval.append(f'# JSON input template for discriminator value "{polymorphic_subtype.discriminator_value}":')
|
|
81
|
+
subtype_template = utils.json_dumps_template(
|
|
82
|
+
polymorphic_subtype.get_json_template_representation(),
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
def _get_polymorphic_parent(
|
|
86
|
+
polymorphic_subtype: Optional[ModelType],
|
|
87
|
+
) -> Optional[ModelType]:
|
|
88
|
+
if not polymorphic_subtype:
|
|
89
|
+
return None
|
|
90
|
+
try:
|
|
91
|
+
return next(p for p in polymorphic_subtype.parents if p.discriminated_subtypes)
|
|
92
|
+
except StopIteration:
|
|
93
|
+
return None
|
|
94
|
+
|
|
95
|
+
polymorphic_parent = _get_polymorphic_parent(polymorphic_subtype)
|
|
96
|
+
while _get_polymorphic_parent(polymorphic_parent):
|
|
97
|
+
polymorphic_parent = _get_polymorphic_parent(polymorphic_parent)
|
|
98
|
+
retval.extend(f"{cast(ModelType, polymorphic_parent).snake_case_name} = {subtype_template}".splitlines())
|
|
99
|
+
return retval
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def _serialize_grouped_body(builder: BuilderType) -> List[str]:
|
|
103
|
+
retval: List[str] = []
|
|
104
|
+
for grouped_parameter in builder.parameters.grouped:
|
|
105
|
+
retval.append(f"{grouped_parameter.client_name} = None")
|
|
106
|
+
groupers = [p for p in builder.parameters if p.grouper]
|
|
107
|
+
for grouper in groupers:
|
|
108
|
+
retval.append(f"if {grouper.client_name} is not None:")
|
|
109
|
+
retval.extend(
|
|
110
|
+
[
|
|
111
|
+
f" {parameter} = {grouper.client_name}.{property}"
|
|
112
|
+
for property, parameter in grouper.property_to_parameter_name.items()
|
|
113
|
+
]
|
|
114
|
+
)
|
|
115
|
+
return retval
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def _serialize_flattened_body(body_parameter: BodyParameter) -> List[str]:
|
|
119
|
+
retval: List[str] = []
|
|
120
|
+
if not body_parameter.property_to_parameter_name:
|
|
121
|
+
raise ValueError("This method can't be called if the operation doesn't need parameter flattening")
|
|
122
|
+
|
|
123
|
+
parameter_string = ", ".join(
|
|
124
|
+
f"{property_name}={parameter_name}"
|
|
125
|
+
for property_name, parameter_name in body_parameter.property_to_parameter_name.items()
|
|
126
|
+
)
|
|
127
|
+
model_type = cast(ModelType, body_parameter.type)
|
|
128
|
+
retval.append(f"{body_parameter.client_name} = _models.{model_type.name}({parameter_string})")
|
|
129
|
+
return retval
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def _serialize_json_model_body(body_parameter: BodyParameter, parameters: List[ParameterType]) -> List[str]:
|
|
133
|
+
retval: List[str] = []
|
|
134
|
+
if not body_parameter.property_to_parameter_name:
|
|
135
|
+
raise ValueError("This method can't be called if the operation doesn't need parameter flattening")
|
|
136
|
+
|
|
137
|
+
retval.append(f"if {body_parameter.client_name} is _Unset:")
|
|
138
|
+
for p in parameters:
|
|
139
|
+
if p.client_default_value is None and not p.optional and p.default_to_unset_sentinel:
|
|
140
|
+
retval.append(f" if {p.client_name} is _Unset:")
|
|
141
|
+
retval.append(f" raise TypeError('missing required argument: {p.client_name}')")
|
|
142
|
+
parameter_string = ", \n".join(
|
|
143
|
+
f'"{property_name}": {parameter_name}'
|
|
144
|
+
for property_name, parameter_name in body_parameter.property_to_parameter_name.items()
|
|
145
|
+
)
|
|
146
|
+
model_type = cast(ModelType, body_parameter.type)
|
|
147
|
+
if isinstance(model_type, CombinedType) and model_type.target_model_subtype((JSONModelType,)):
|
|
148
|
+
model_type = model_type.target_model_subtype((JSONModelType,))
|
|
149
|
+
retval.append(f" {body_parameter.client_name} = {{{parameter_string}}}")
|
|
150
|
+
retval.append(f" {body_parameter.client_name} = {{")
|
|
151
|
+
retval.append(f" k: v for k, v in {body_parameter.client_name}.items() if v is not None")
|
|
152
|
+
retval.append(" }")
|
|
153
|
+
return retval
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
def _serialize_multipart_body(builder: BuilderType) -> List[str]:
|
|
157
|
+
retval: List[str] = []
|
|
158
|
+
body_param = builder.parameters.body_parameter
|
|
159
|
+
# we have to construct our form data before passing to the request as well
|
|
160
|
+
retval.append("# Construct form data")
|
|
161
|
+
retval.append(f"_{body_param.client_name} = {{")
|
|
162
|
+
for param in body_param.entries:
|
|
163
|
+
retval.append(f' "{param.wire_name}": {param.client_name},')
|
|
164
|
+
retval.append("}")
|
|
165
|
+
return retval
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
def _get_json_response_template_to_status_codes(
|
|
169
|
+
builder: OperationType,
|
|
170
|
+
) -> Dict[str, List[str]]:
|
|
171
|
+
retval = defaultdict(list)
|
|
172
|
+
for response in builder.responses:
|
|
173
|
+
json_template = response.get_json_template_representation()
|
|
174
|
+
if not json_template:
|
|
175
|
+
continue
|
|
176
|
+
status_codes = [str(status_code) for status_code in response.status_codes]
|
|
177
|
+
response_json = utils.json_dumps_template(json_template)
|
|
178
|
+
retval[response_json].extend(status_codes)
|
|
179
|
+
return retval
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
def is_json_model_type(parameters: ParameterListType) -> bool:
|
|
183
|
+
return (
|
|
184
|
+
parameters.has_body
|
|
185
|
+
and parameters.body_parameter.has_json_model_type
|
|
186
|
+
and any(p.in_flattened_body for p in parameters.parameters)
|
|
187
|
+
)
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
class _BuilderBaseSerializer(Generic[BuilderType]):
|
|
191
|
+
def __init__(self, code_model: CodeModel, async_mode: bool) -> None:
|
|
192
|
+
self.code_model = code_model
|
|
193
|
+
self.async_mode = async_mode
|
|
194
|
+
self.parameter_serializer = ParameterSerializer()
|
|
195
|
+
|
|
196
|
+
@property
|
|
197
|
+
@abstractmethod
|
|
198
|
+
def _need_self_param(self) -> bool: ...
|
|
199
|
+
|
|
200
|
+
@property
|
|
201
|
+
@abstractmethod
|
|
202
|
+
def _function_def(self) -> str:
|
|
203
|
+
"""The def keyword for the builder we're serializing, i.e. 'def' or 'async def'"""
|
|
204
|
+
|
|
205
|
+
@property
|
|
206
|
+
@abstractmethod
|
|
207
|
+
def _call_method(self) -> str:
|
|
208
|
+
"""How to call network calls. Await if we have to await network calls"""
|
|
209
|
+
|
|
210
|
+
@property
|
|
211
|
+
@abstractmethod
|
|
212
|
+
def serializer_name(self) -> str:
|
|
213
|
+
"""Name of serializer"""
|
|
214
|
+
|
|
215
|
+
@abstractmethod
|
|
216
|
+
def response_docstring(self, builder: BuilderType) -> List[str]:
|
|
217
|
+
"""Response portion of the docstring"""
|
|
218
|
+
|
|
219
|
+
def decorators(self, builder: BuilderType) -> List[str]:
|
|
220
|
+
"""Decorators for the method"""
|
|
221
|
+
retval: List[str] = []
|
|
222
|
+
if builder.is_overload:
|
|
223
|
+
return ["@overload"]
|
|
224
|
+
if self.code_model.options["tracing"] and builder.want_tracing:
|
|
225
|
+
retval.append(f"@distributed_trace{'_async' if self.async_mode else ''}")
|
|
226
|
+
return retval
|
|
227
|
+
|
|
228
|
+
def _method_signature(self, builder: BuilderType) -> str:
|
|
229
|
+
return self.parameter_serializer.serialize_method(
|
|
230
|
+
function_def=self._function_def,
|
|
231
|
+
method_name=builder.name,
|
|
232
|
+
need_self_param=self._need_self_param,
|
|
233
|
+
method_param_signatures=builder.method_signature(self.async_mode),
|
|
234
|
+
pylint_disable=builder.pylint_disable(self.async_mode),
|
|
235
|
+
)
|
|
236
|
+
|
|
237
|
+
def method_signature_and_response_type_annotation(
|
|
238
|
+
self, builder: BuilderType, *, want_decorators: Optional[bool] = True
|
|
239
|
+
) -> str:
|
|
240
|
+
response_type_annotation = builder.response_type_annotation(async_mode=self.async_mode)
|
|
241
|
+
method_signature = self._method_signature(builder)
|
|
242
|
+
decorators = self.decorators(builder)
|
|
243
|
+
decorators_str = ""
|
|
244
|
+
if decorators and want_decorators:
|
|
245
|
+
decorators_str = "\n".join(decorators) + "\n"
|
|
246
|
+
return decorators_str + utils.method_signature_and_response_type_annotation_template(
|
|
247
|
+
method_signature=method_signature,
|
|
248
|
+
response_type_annotation=response_type_annotation,
|
|
249
|
+
)
|
|
250
|
+
|
|
251
|
+
def description_and_summary(self, builder: BuilderType) -> List[str]:
|
|
252
|
+
description_list: List[str] = []
|
|
253
|
+
description_list.append(f"{builder.summary.strip() if builder.summary else builder.description.strip()}")
|
|
254
|
+
if builder.summary and builder.description:
|
|
255
|
+
description_list.append("")
|
|
256
|
+
description_list.append(builder.description.strip())
|
|
257
|
+
description_list.append("")
|
|
258
|
+
return description_list
|
|
259
|
+
|
|
260
|
+
@staticmethod
|
|
261
|
+
def line_too_long(docs: List[str], indentation: int = 0) -> bool:
|
|
262
|
+
return any(len(line) > (120 - indentation) for line in docs)
|
|
263
|
+
|
|
264
|
+
def example_template(self, builder: BuilderType) -> List[str]:
|
|
265
|
+
template = []
|
|
266
|
+
if builder.abstract:
|
|
267
|
+
return []
|
|
268
|
+
if self._json_input_example_template(builder):
|
|
269
|
+
template.append("")
|
|
270
|
+
template += self._json_input_example_template(builder)
|
|
271
|
+
return template
|
|
272
|
+
|
|
273
|
+
def param_description(self, builder: BuilderType) -> List[str]:
|
|
274
|
+
description_list: List[str] = []
|
|
275
|
+
for param in builder.parameters.method:
|
|
276
|
+
if (
|
|
277
|
+
not param.in_docstring
|
|
278
|
+
or param.hide_in_operation_signature
|
|
279
|
+
or param.method_location == ParameterMethodLocation.KWARG
|
|
280
|
+
):
|
|
281
|
+
continue
|
|
282
|
+
description_list.extend(
|
|
283
|
+
f":{param.description_keyword} {param.client_name}: {param.description}".replace("\n", "\n ").split(
|
|
284
|
+
"\n"
|
|
285
|
+
)
|
|
286
|
+
)
|
|
287
|
+
docstring_type = param.docstring_type(
|
|
288
|
+
async_mode=self.async_mode,
|
|
289
|
+
)
|
|
290
|
+
description_list.append(f":{param.docstring_type_keyword} {param.client_name}: {docstring_type}")
|
|
291
|
+
return description_list
|
|
292
|
+
|
|
293
|
+
def param_description_and_response_docstring(self, builder: BuilderType) -> List[str]:
|
|
294
|
+
if builder.abstract:
|
|
295
|
+
return []
|
|
296
|
+
return self.param_description(builder) + self.response_docstring(builder)
|
|
297
|
+
|
|
298
|
+
@property
|
|
299
|
+
@abstractmethod
|
|
300
|
+
def _json_response_template_name(self) -> str: ...
|
|
301
|
+
|
|
302
|
+
def _json_input_example_template(self, builder: BuilderType) -> List[str]:
|
|
303
|
+
template: List[str] = []
|
|
304
|
+
if not builder.parameters.has_body or builder.parameters.body_parameter.flattened:
|
|
305
|
+
# No input template if now body parameter
|
|
306
|
+
return template
|
|
307
|
+
|
|
308
|
+
body_param = builder.parameters.body_parameter
|
|
309
|
+
if not isinstance(body_param.type, (ListType, DictionaryType, ModelType, CombinedType)):
|
|
310
|
+
return template
|
|
311
|
+
|
|
312
|
+
if (
|
|
313
|
+
isinstance(body_param.type, (ListType, DictionaryType))
|
|
314
|
+
and self.code_model.options["models_mode"] == "msrest"
|
|
315
|
+
):
|
|
316
|
+
return template
|
|
317
|
+
|
|
318
|
+
if isinstance(body_param.type, ModelType) and body_param.type.base == "msrest":
|
|
319
|
+
return template
|
|
320
|
+
|
|
321
|
+
json_type = body_param.type
|
|
322
|
+
if isinstance(body_param.type, CombinedType):
|
|
323
|
+
target_model_type = body_param.type.target_model_subtype((JSONModelType, DPGModelType))
|
|
324
|
+
if target_model_type is None:
|
|
325
|
+
return template
|
|
326
|
+
json_type = target_model_type
|
|
327
|
+
|
|
328
|
+
polymorphic_subtypes: List[ModelType] = []
|
|
329
|
+
json_type.get_polymorphic_subtypes(polymorphic_subtypes)
|
|
330
|
+
if polymorphic_subtypes:
|
|
331
|
+
# we just assume one kind of polymorphic body for input
|
|
332
|
+
discriminator_name = cast(Property, polymorphic_subtypes[0].discriminator).wire_name
|
|
333
|
+
template.append(
|
|
334
|
+
"# The input is polymorphic. The following are possible polymorphic "
|
|
335
|
+
f'inputs based off discriminator "{discriminator_name}":'
|
|
336
|
+
)
|
|
337
|
+
for idx in range(
|
|
338
|
+
min(
|
|
339
|
+
self.code_model.options["polymorphic_examples"],
|
|
340
|
+
len(polymorphic_subtypes),
|
|
341
|
+
)
|
|
342
|
+
):
|
|
343
|
+
template.extend(_get_polymorphic_subtype_template(polymorphic_subtypes[idx]))
|
|
344
|
+
template.append("")
|
|
345
|
+
template.append("# JSON input template you can fill out and use as your body input.")
|
|
346
|
+
json_template = utils.json_dumps_template(
|
|
347
|
+
json_type.get_json_template_representation(),
|
|
348
|
+
)
|
|
349
|
+
template.extend(f"{builder.parameters.body_parameter.client_name} = {json_template}".splitlines())
|
|
350
|
+
return template
|
|
351
|
+
|
|
352
|
+
def serialize_path(self, builder: BuilderType) -> List[str]:
|
|
353
|
+
return self.parameter_serializer.serialize_path(builder.parameters.path, self.serializer_name)
|
|
354
|
+
|
|
355
|
+
@property
|
|
356
|
+
def pipeline_name(self) -> str:
|
|
357
|
+
return f"{'_' if self.code_model.is_azure_flavor else ''}pipeline"
|
|
358
|
+
|
|
359
|
+
|
|
360
|
+
############################## REQUEST BUILDERS ##############################
|
|
361
|
+
|
|
362
|
+
|
|
363
|
+
class RequestBuilderSerializer(_BuilderBaseSerializer[RequestBuilderType]):
|
|
364
|
+
def description_and_summary(self, builder: RequestBuilderType) -> List[str]:
|
|
365
|
+
retval = super().description_and_summary(builder)
|
|
366
|
+
retval += [
|
|
367
|
+
"See https://aka.ms/azsdk/dpcodegen/python/send_request for how to incorporate this "
|
|
368
|
+
"request builder into your code flow.",
|
|
369
|
+
"",
|
|
370
|
+
]
|
|
371
|
+
return retval
|
|
372
|
+
|
|
373
|
+
@property
|
|
374
|
+
def _call_method(self) -> str:
|
|
375
|
+
return ""
|
|
376
|
+
|
|
377
|
+
@property
|
|
378
|
+
def serializer_name(self) -> str:
|
|
379
|
+
return "_SERIALIZER"
|
|
380
|
+
|
|
381
|
+
@property
|
|
382
|
+
def _json_response_template_name(self) -> str:
|
|
383
|
+
return "response.json()"
|
|
384
|
+
|
|
385
|
+
@staticmethod
|
|
386
|
+
def declare_non_inputtable_headers_queries(
|
|
387
|
+
builder: RequestBuilderType,
|
|
388
|
+
) -> List[str]:
|
|
389
|
+
def _get_value(param):
|
|
390
|
+
declaration = param.get_declaration() if param.constant else None
|
|
391
|
+
if param.location in [ParameterLocation.HEADER, ParameterLocation.QUERY]:
|
|
392
|
+
kwarg_dict = "headers" if param.location == ParameterLocation.HEADER else "params"
|
|
393
|
+
return f"_{kwarg_dict}.pop('{param.wire_name}', {declaration})"
|
|
394
|
+
return declaration
|
|
395
|
+
|
|
396
|
+
return [
|
|
397
|
+
f"{p.client_name} = {_get_value(p)}"
|
|
398
|
+
for p in (builder.parameters.headers + builder.parameters.query)
|
|
399
|
+
if not p.in_method_signature
|
|
400
|
+
]
|
|
401
|
+
|
|
402
|
+
@property
|
|
403
|
+
def _function_def(self) -> str:
|
|
404
|
+
return "def"
|
|
405
|
+
|
|
406
|
+
@property
|
|
407
|
+
def _need_self_param(self) -> bool:
|
|
408
|
+
return False
|
|
409
|
+
|
|
410
|
+
def response_docstring(self, builder: RequestBuilderType) -> List[str]:
|
|
411
|
+
request_full_path = f"{self.code_model.core_library}.rest.HttpRequest"
|
|
412
|
+
response_str = (
|
|
413
|
+
f":return: Returns an :class:`~{request_full_path}` that you will pass to the client's "
|
|
414
|
+
+ "`send_request` method. See https://aka.ms/azsdk/dpcodegen/python/send_request for how to "
|
|
415
|
+
+ "incorporate this response into your code flow."
|
|
416
|
+
)
|
|
417
|
+
rtype_str = f":rtype: ~{request_full_path}"
|
|
418
|
+
return [response_str, rtype_str]
|
|
419
|
+
|
|
420
|
+
def pop_kwargs_from_signature(self, builder: RequestBuilderType) -> List[str]:
|
|
421
|
+
return self.parameter_serializer.pop_kwargs_from_signature(
|
|
422
|
+
builder.parameters.kwargs_to_pop,
|
|
423
|
+
check_kwarg_dict=True,
|
|
424
|
+
pop_headers_kwarg=(PopKwargType.CASE_INSENSITIVE if bool(builder.parameters.headers) else PopKwargType.NO),
|
|
425
|
+
pop_params_kwarg=(PopKwargType.CASE_INSENSITIVE if bool(builder.parameters.query) else PopKwargType.NO),
|
|
426
|
+
)
|
|
427
|
+
|
|
428
|
+
@staticmethod
|
|
429
|
+
def create_http_request(builder: RequestBuilderType) -> List[str]:
|
|
430
|
+
retval = ["return HttpRequest("]
|
|
431
|
+
retval.append(f' method="{builder.method}",')
|
|
432
|
+
retval.append(" url=_url,")
|
|
433
|
+
if builder.parameters.query:
|
|
434
|
+
retval.append(" params=_params,")
|
|
435
|
+
if builder.parameters.headers:
|
|
436
|
+
retval.append(" headers=_headers,")
|
|
437
|
+
if builder.parameters.has_body and builder.parameters.body_parameter.in_method_signature:
|
|
438
|
+
body_param = builder.parameters.body_parameter
|
|
439
|
+
if body_param.constant or body_param.method_location != ParameterMethodLocation.KWARG:
|
|
440
|
+
# we only need to pass it through if it's not a kwarg or it's a popped kwarg
|
|
441
|
+
retval.append(
|
|
442
|
+
f" {builder.parameters.body_parameter.client_name}="
|
|
443
|
+
f"{builder.parameters.body_parameter.client_name},"
|
|
444
|
+
)
|
|
445
|
+
retval.append(" **kwargs")
|
|
446
|
+
retval.append(")")
|
|
447
|
+
return retval
|
|
448
|
+
|
|
449
|
+
def serialize_headers(self, builder: RequestBuilderType) -> List[str]:
|
|
450
|
+
headers = [
|
|
451
|
+
h
|
|
452
|
+
for h in builder.parameters.headers
|
|
453
|
+
if not builder.has_form_data_body or h.wire_name.lower() != "content-type"
|
|
454
|
+
]
|
|
455
|
+
retval = ["# Construct headers"] if headers else []
|
|
456
|
+
for header in headers:
|
|
457
|
+
retval.extend(
|
|
458
|
+
self.parameter_serializer.serialize_query_header(
|
|
459
|
+
header,
|
|
460
|
+
"headers",
|
|
461
|
+
self.serializer_name,
|
|
462
|
+
self.code_model.is_legacy,
|
|
463
|
+
)
|
|
464
|
+
)
|
|
465
|
+
return retval
|
|
466
|
+
|
|
467
|
+
def serialize_query(self, builder: RequestBuilderType) -> List[str]:
|
|
468
|
+
retval = ["# Construct parameters"]
|
|
469
|
+
for parameter in builder.parameters.query:
|
|
470
|
+
retval.extend(
|
|
471
|
+
self.parameter_serializer.serialize_query_header(
|
|
472
|
+
parameter,
|
|
473
|
+
"params",
|
|
474
|
+
self.serializer_name,
|
|
475
|
+
self.code_model.is_legacy,
|
|
476
|
+
)
|
|
477
|
+
)
|
|
478
|
+
return retval
|
|
479
|
+
|
|
480
|
+
def construct_url(self, builder: RequestBuilderType) -> str:
|
|
481
|
+
if any(o for o in ["low_level_client", "version_tolerant"] if self.code_model.options.get(o)):
|
|
482
|
+
url_value = _escape_str(builder.url)
|
|
483
|
+
else:
|
|
484
|
+
url_value = f'kwargs.pop("template_url", {_escape_str(builder.url)})'
|
|
485
|
+
return f"_url = {url_value}{' # pylint: disable=line-too-long' if len(url_value) > 114 else ''}"
|
|
486
|
+
|
|
487
|
+
|
|
488
|
+
############################## NORMAL OPERATIONS ##############################
|
|
489
|
+
|
|
490
|
+
|
|
491
|
+
class _OperationSerializer(_BuilderBaseSerializer[OperationType]):
|
|
492
|
+
def description_and_summary(self, builder: OperationType) -> List[str]:
|
|
493
|
+
retval = super().description_and_summary(builder)
|
|
494
|
+
if builder.deprecated:
|
|
495
|
+
retval.append(".. warning::")
|
|
496
|
+
retval.append(" This method is deprecated")
|
|
497
|
+
retval.append("")
|
|
498
|
+
if builder.external_docs and builder.external_docs.get("url"):
|
|
499
|
+
retval.append(".. seealso::")
|
|
500
|
+
retval.append(f" - {builder.external_docs['url']}")
|
|
501
|
+
retval.append("")
|
|
502
|
+
return retval
|
|
503
|
+
|
|
504
|
+
@property
|
|
505
|
+
def _json_response_template_name(self) -> str:
|
|
506
|
+
return "response"
|
|
507
|
+
|
|
508
|
+
def example_template(self, builder: OperationType) -> List[str]:
|
|
509
|
+
if self.code_model.options["models_mode"] in ("msrest", "dpg"):
|
|
510
|
+
return []
|
|
511
|
+
retval = super().example_template(builder)
|
|
512
|
+
for response in builder.responses:
|
|
513
|
+
polymorphic_subtypes: List[ModelType] = []
|
|
514
|
+
if not response.type:
|
|
515
|
+
continue
|
|
516
|
+
response.get_polymorphic_subtypes(polymorphic_subtypes)
|
|
517
|
+
if polymorphic_subtypes:
|
|
518
|
+
# we just assume one kind of polymorphic body for input
|
|
519
|
+
discriminator_name = cast(Property, polymorphic_subtypes[0].discriminator).wire_name
|
|
520
|
+
retval.append("")
|
|
521
|
+
retval.append(
|
|
522
|
+
"# The response is polymorphic. The following are possible polymorphic "
|
|
523
|
+
f'responses based off discriminator "{discriminator_name}":'
|
|
524
|
+
)
|
|
525
|
+
for idx in range(
|
|
526
|
+
min(
|
|
527
|
+
self.code_model.options["polymorphic_examples"],
|
|
528
|
+
len(polymorphic_subtypes),
|
|
529
|
+
)
|
|
530
|
+
):
|
|
531
|
+
retval.extend(_get_polymorphic_subtype_template(polymorphic_subtypes[idx]))
|
|
532
|
+
|
|
533
|
+
if _get_json_response_template_to_status_codes(builder):
|
|
534
|
+
retval.append("")
|
|
535
|
+
for (
|
|
536
|
+
response_body,
|
|
537
|
+
status_codes,
|
|
538
|
+
) in _get_json_response_template_to_status_codes(builder).items():
|
|
539
|
+
retval.append("# response body for status code(s): {}".format(", ".join(status_codes)))
|
|
540
|
+
retval.extend(f"{self._json_response_template_name} == {response_body}".splitlines())
|
|
541
|
+
return retval
|
|
542
|
+
|
|
543
|
+
def make_pipeline_call(self, builder: OperationType) -> List[str]:
|
|
544
|
+
retval = []
|
|
545
|
+
type_ignore = self.async_mode and builder.group_name == "" # is in a mixin
|
|
546
|
+
if builder.stream_value is True and not self.code_model.options["version_tolerant"]:
|
|
547
|
+
retval.append("_decompress = kwargs.pop('decompress', True)")
|
|
548
|
+
pylint_disable = " # pylint: disable=protected-access" if self.code_model.is_azure_flavor else ""
|
|
549
|
+
retval.extend(
|
|
550
|
+
[
|
|
551
|
+
f"_stream = {builder.stream_value}",
|
|
552
|
+
f"pipeline_response: PipelineResponse = {self._call_method}self._client.{self.pipeline_name}.run( "
|
|
553
|
+
+ f"{'# type: ignore' if type_ignore else ''}{pylint_disable}",
|
|
554
|
+
" _request,",
|
|
555
|
+
" stream=_stream,",
|
|
556
|
+
" **kwargs",
|
|
557
|
+
")",
|
|
558
|
+
]
|
|
559
|
+
)
|
|
560
|
+
return retval
|
|
561
|
+
|
|
562
|
+
@property
|
|
563
|
+
def _function_def(self) -> str:
|
|
564
|
+
return "async def" if self.async_mode else "def"
|
|
565
|
+
|
|
566
|
+
@property
|
|
567
|
+
def _need_self_param(self) -> bool:
|
|
568
|
+
return True
|
|
569
|
+
|
|
570
|
+
@property
|
|
571
|
+
def serializer_name(self) -> str:
|
|
572
|
+
return "self._serialize"
|
|
573
|
+
|
|
574
|
+
def decorators(self, builder: OperationType) -> List[str]:
|
|
575
|
+
"""Decorators for the method"""
|
|
576
|
+
retval = super().decorators(builder)
|
|
577
|
+
if self._api_version_validation(builder):
|
|
578
|
+
retval.append(self._api_version_validation(builder))
|
|
579
|
+
return retval
|
|
580
|
+
|
|
581
|
+
def _api_version_validation(self, builder: OperationType) -> str:
|
|
582
|
+
if builder.is_overload:
|
|
583
|
+
return ""
|
|
584
|
+
retval: List[str] = []
|
|
585
|
+
if builder.added_on:
|
|
586
|
+
retval.append(f' method_added_on="{builder.added_on}",')
|
|
587
|
+
params_added_on = defaultdict(list)
|
|
588
|
+
for parameter in builder.parameters:
|
|
589
|
+
if parameter.added_on:
|
|
590
|
+
params_added_on[parameter.added_on].append(parameter.client_name)
|
|
591
|
+
if params_added_on:
|
|
592
|
+
retval.append(f" params_added_on={dict(params_added_on)},")
|
|
593
|
+
if retval:
|
|
594
|
+
retval_str = "\n".join(retval)
|
|
595
|
+
return f"@api_version_validation(\n{retval_str}\n)"
|
|
596
|
+
return ""
|
|
597
|
+
|
|
598
|
+
def pop_kwargs_from_signature(self, builder: OperationType) -> List[str]:
|
|
599
|
+
kwargs_to_pop = builder.parameters.kwargs_to_pop
|
|
600
|
+
kwargs = self.parameter_serializer.pop_kwargs_from_signature(
|
|
601
|
+
kwargs_to_pop,
|
|
602
|
+
check_kwarg_dict=True,
|
|
603
|
+
pop_headers_kwarg=(
|
|
604
|
+
PopKwargType.CASE_INSENSITIVE
|
|
605
|
+
if builder.has_kwargs_to_pop_with_default(kwargs_to_pop, ParameterLocation.HEADER) # type: ignore
|
|
606
|
+
else PopKwargType.SIMPLE
|
|
607
|
+
),
|
|
608
|
+
pop_params_kwarg=(
|
|
609
|
+
PopKwargType.CASE_INSENSITIVE
|
|
610
|
+
if builder.has_kwargs_to_pop_with_default(kwargs_to_pop, ParameterLocation.QUERY) # type: ignore
|
|
611
|
+
else PopKwargType.SIMPLE
|
|
612
|
+
),
|
|
613
|
+
check_client_input=not self.code_model.options["multiapi"],
|
|
614
|
+
operation_name=f"('{builder.name}')" if builder.group_name == "" else "",
|
|
615
|
+
)
|
|
616
|
+
for p in builder.parameters.parameters:
|
|
617
|
+
if p.hide_in_operation_signature:
|
|
618
|
+
kwargs.append(f'{p.client_name} = kwargs.pop("{p.client_name}", None)')
|
|
619
|
+
cls_annotation = builder.cls_type_annotation(async_mode=self.async_mode)
|
|
620
|
+
kwargs.append(f"cls: {cls_annotation} = kwargs.pop(\n 'cls', None\n)")
|
|
621
|
+
return kwargs
|
|
622
|
+
|
|
623
|
+
def response_docstring(self, builder: OperationType) -> List[str]:
|
|
624
|
+
response_str = f":return: {builder.response_docstring_text(async_mode=self.async_mode)}"
|
|
625
|
+
rtype_str = f":rtype: {builder.response_docstring_type(async_mode=self.async_mode)}"
|
|
626
|
+
return [
|
|
627
|
+
response_str,
|
|
628
|
+
rtype_str,
|
|
629
|
+
f":raises ~{self.code_model.core_library}.exceptions.HttpResponseError:",
|
|
630
|
+
]
|
|
631
|
+
|
|
632
|
+
def _serialize_body_parameter(self, builder: OperationType) -> List[str]:
|
|
633
|
+
"""We need to serialize params if they're not meant to be streamed in.
|
|
634
|
+
|
|
635
|
+
This function serializes the body params that need to be serialized.
|
|
636
|
+
"""
|
|
637
|
+
retval: List[str] = []
|
|
638
|
+
body_param = builder.parameters.body_parameter
|
|
639
|
+
if body_param.is_form_data:
|
|
640
|
+
model_type = cast(
|
|
641
|
+
ModelType,
|
|
642
|
+
(
|
|
643
|
+
body_param.type.target_model_subtype((JSONModelType, DPGModelType))
|
|
644
|
+
if isinstance(body_param.type, CombinedType)
|
|
645
|
+
else body_param.type
|
|
646
|
+
),
|
|
647
|
+
)
|
|
648
|
+
file_fields = [p.wire_name for p in model_type.properties if p.is_multipart_file_input]
|
|
649
|
+
data_fields = [p.wire_name for p in model_type.properties if not p.is_multipart_file_input]
|
|
650
|
+
retval.extend(
|
|
651
|
+
[
|
|
652
|
+
"_body = (",
|
|
653
|
+
f" {body_param.client_name}.as_dict()",
|
|
654
|
+
f" if isinstance({body_param.client_name}, _model_base.Model) else",
|
|
655
|
+
f" {body_param.client_name}",
|
|
656
|
+
")",
|
|
657
|
+
f"_file_fields: List[str] = {file_fields}",
|
|
658
|
+
f"_data_fields: List[str] = {data_fields}",
|
|
659
|
+
"_files, _data = prepare_multipart_form_data(_body, _file_fields, _data_fields)",
|
|
660
|
+
]
|
|
661
|
+
)
|
|
662
|
+
return retval
|
|
663
|
+
|
|
664
|
+
body_kwarg_name = builder.request_builder.parameters.body_parameter.client_name
|
|
665
|
+
send_xml = builder.parameters.body_parameter.type.is_xml
|
|
666
|
+
xml_serialization_ctxt = body_param.type.xml_serialization_ctxt if send_xml else None
|
|
667
|
+
ser_ctxt_name = "serialization_ctxt"
|
|
668
|
+
if xml_serialization_ctxt and self.code_model.options["models_mode"]:
|
|
669
|
+
retval.append(f'{ser_ctxt_name} = {{"xml": {{{xml_serialization_ctxt}}}}}')
|
|
670
|
+
if self.code_model.options["models_mode"] == "msrest":
|
|
671
|
+
is_xml_cmd = _xml_config(send_xml, builder.parameters.body_parameter.content_types)
|
|
672
|
+
serialization_ctxt_cmd = f", {ser_ctxt_name}={ser_ctxt_name}" if xml_serialization_ctxt else ""
|
|
673
|
+
create_body_call = (
|
|
674
|
+
f"_{body_kwarg_name} = self._serialize.body({body_param.client_name}, "
|
|
675
|
+
f"'{body_param.type.serialization_type}'{is_xml_cmd}{serialization_ctxt_cmd})"
|
|
676
|
+
)
|
|
677
|
+
elif self.code_model.options["models_mode"] == "dpg":
|
|
678
|
+
if json_serializable(body_param.default_content_type):
|
|
679
|
+
if hasattr(body_param.type, "encode") and body_param.type.encode: # type: ignore
|
|
680
|
+
create_body_call = (
|
|
681
|
+
f"_{body_kwarg_name} = json.dumps({body_param.client_name}, "
|
|
682
|
+
"cls=SdkJSONEncoder, exclude_readonly=True, "
|
|
683
|
+
f"format='{body_param.type.encode}') # type: ignore" # type: ignore
|
|
684
|
+
)
|
|
685
|
+
else:
|
|
686
|
+
create_body_call = (
|
|
687
|
+
f"_{body_kwarg_name} = json.dumps({body_param.client_name}, "
|
|
688
|
+
"cls=SdkJSONEncoder, exclude_readonly=True) # type: ignore"
|
|
689
|
+
)
|
|
690
|
+
elif xml_serializable(body_param.default_content_type):
|
|
691
|
+
create_body_call = f"_{body_kwarg_name} = _get_element({body_param.client_name})"
|
|
692
|
+
else:
|
|
693
|
+
create_body_call = f"_{body_kwarg_name} = {body_param.client_name}"
|
|
694
|
+
else:
|
|
695
|
+
create_body_call = f"_{body_kwarg_name} = {body_param.client_name}"
|
|
696
|
+
if body_param.optional:
|
|
697
|
+
retval.append(f"if {body_param.client_name} is not None:")
|
|
698
|
+
retval.append(" " + create_body_call)
|
|
699
|
+
retval.append("else:")
|
|
700
|
+
retval.append(f" _{body_kwarg_name} = None")
|
|
701
|
+
else:
|
|
702
|
+
retval.append(create_body_call)
|
|
703
|
+
return retval
|
|
704
|
+
|
|
705
|
+
def _create_body_parameter(
|
|
706
|
+
self,
|
|
707
|
+
builder: OperationType,
|
|
708
|
+
) -> List[str]:
|
|
709
|
+
"""Create the body parameter before we pass it as either json or content to the request builder"""
|
|
710
|
+
retval = []
|
|
711
|
+
body_param = builder.parameters.body_parameter
|
|
712
|
+
if body_param.entries:
|
|
713
|
+
return _serialize_multipart_body(builder)
|
|
714
|
+
body_kwarg_name = builder.request_builder.parameters.body_parameter.client_name
|
|
715
|
+
body_param_type = body_param.type
|
|
716
|
+
if isinstance(body_param_type, BinaryType) or (
|
|
717
|
+
isinstance(body_param.type, ByteArraySchema) and body_param.default_content_type != "application/json"
|
|
718
|
+
):
|
|
719
|
+
retval.append(f"_{body_kwarg_name} = {body_param.client_name}")
|
|
720
|
+
if (
|
|
721
|
+
not body_param.default_content_type
|
|
722
|
+
and not next(p for p in builder.parameters if p.wire_name.lower() == "content-type").optional
|
|
723
|
+
):
|
|
724
|
+
content_types = "'" + "', '".join(body_param.content_types) + "'"
|
|
725
|
+
retval.extend(
|
|
726
|
+
[
|
|
727
|
+
"if not content_type:",
|
|
728
|
+
f' raise TypeError("Missing required keyword-only argument: content_type. '
|
|
729
|
+
f'Known values are:" + "{content_types}")',
|
|
730
|
+
]
|
|
731
|
+
)
|
|
732
|
+
else:
|
|
733
|
+
retval.extend(self._serialize_body_parameter(builder))
|
|
734
|
+
return retval
|
|
735
|
+
|
|
736
|
+
def _initialize_overloads(self, builder: OperationType, is_paging: bool = False) -> List[str]:
|
|
737
|
+
retval: List[str] = []
|
|
738
|
+
# For paging, we put body parameter in local place outside `prepare_request`
|
|
739
|
+
if is_paging:
|
|
740
|
+
return retval
|
|
741
|
+
same_content_type = len(set(o.parameters.body_parameter.default_content_type for o in builder.overloads)) == 1
|
|
742
|
+
if same_content_type:
|
|
743
|
+
default_content_type = builder.overloads[0].parameters.body_parameter.default_content_type
|
|
744
|
+
retval.append(f'content_type = content_type or "{default_content_type}"')
|
|
745
|
+
client_names = [
|
|
746
|
+
overload.request_builder.parameters.body_parameter.client_name for overload in builder.overloads
|
|
747
|
+
]
|
|
748
|
+
for v in sorted(set(client_names), key=client_names.index):
|
|
749
|
+
retval.append(f"_{v} = None")
|
|
750
|
+
try:
|
|
751
|
+
# if there is a binary overload, we do a binary check first.
|
|
752
|
+
binary_overload = cast(
|
|
753
|
+
OperationType,
|
|
754
|
+
next((o for o in builder.overloads if isinstance(o.parameters.body_parameter.type, BinaryType))),
|
|
755
|
+
)
|
|
756
|
+
binary_body_param = binary_overload.parameters.body_parameter
|
|
757
|
+
retval.append(f"if {binary_body_param.type.instance_check_template.format(binary_body_param.client_name)}:")
|
|
758
|
+
if binary_body_param.default_content_type and not same_content_type:
|
|
759
|
+
retval.append(f' content_type = content_type or "{binary_body_param.default_content_type}"')
|
|
760
|
+
retval.extend(f" {l}" for l in self._create_body_parameter(binary_overload))
|
|
761
|
+
retval.append("else:")
|
|
762
|
+
other_overload = cast(
|
|
763
|
+
OperationType,
|
|
764
|
+
next((o for o in builder.overloads if not isinstance(o.parameters.body_parameter.type, BinaryType))),
|
|
765
|
+
)
|
|
766
|
+
retval.extend(f" {l}" for l in self._create_body_parameter(other_overload))
|
|
767
|
+
if other_overload.parameters.body_parameter.default_content_type and not same_content_type:
|
|
768
|
+
retval.append(
|
|
769
|
+
" content_type = content_type or "
|
|
770
|
+
f'"{other_overload.parameters.body_parameter.default_content_type}"'
|
|
771
|
+
)
|
|
772
|
+
except StopIteration:
|
|
773
|
+
for idx, overload in enumerate(builder.overloads):
|
|
774
|
+
if_statement = "if" if idx == 0 else "elif"
|
|
775
|
+
body_param = overload.parameters.body_parameter
|
|
776
|
+
retval.append(
|
|
777
|
+
f"{if_statement} {body_param.type.instance_check_template.format(body_param.client_name)}:"
|
|
778
|
+
)
|
|
779
|
+
if body_param.default_content_type and not same_content_type:
|
|
780
|
+
retval.append(f' content_type = content_type or "{body_param.default_content_type}"')
|
|
781
|
+
retval.extend(f" {l}" for l in self._create_body_parameter(cast(OperationType, overload)))
|
|
782
|
+
return retval
|
|
783
|
+
|
|
784
|
+
def _create_request_builder_call(
|
|
785
|
+
self,
|
|
786
|
+
builder: OperationType,
|
|
787
|
+
request_builder: RequestBuilderType,
|
|
788
|
+
is_next_request: bool = False,
|
|
789
|
+
) -> List[str]:
|
|
790
|
+
retval: List[str] = []
|
|
791
|
+
if self.code_model.options["builders_visibility"] == "embedded":
|
|
792
|
+
request_path_name = request_builder.name
|
|
793
|
+
else:
|
|
794
|
+
group_name = request_builder.group_name
|
|
795
|
+
request_path_name = "rest{}.{}".format(
|
|
796
|
+
("_" + group_name) if group_name else "",
|
|
797
|
+
request_builder.name,
|
|
798
|
+
)
|
|
799
|
+
retval.append(f"_request = {request_path_name}(")
|
|
800
|
+
for parameter in request_builder.parameters.method:
|
|
801
|
+
if parameter.location == ParameterLocation.BODY:
|
|
802
|
+
# going to pass in body later based off of overloads
|
|
803
|
+
continue
|
|
804
|
+
if (
|
|
805
|
+
is_next_request
|
|
806
|
+
and builder.operation_type == "paging"
|
|
807
|
+
and not bool(builder.next_request_builder) # type: ignore
|
|
808
|
+
and parameter.location == ParameterLocation.QUERY
|
|
809
|
+
):
|
|
810
|
+
# if we don't want to reformat query parameters for next link calls
|
|
811
|
+
# in paging operations with a single swagger operation defintion,
|
|
812
|
+
# we skip passing query params when building the next request
|
|
813
|
+
continue
|
|
814
|
+
type_ignore = (
|
|
815
|
+
parameter.grouped_by
|
|
816
|
+
and parameter.client_default_value is not None
|
|
817
|
+
and next(p for p in builder.parameters if p.grouper and p.client_name == parameter.grouped_by).optional
|
|
818
|
+
)
|
|
819
|
+
retval.append(
|
|
820
|
+
f" {parameter.client_name}={parameter.name_in_high_level_operation},"
|
|
821
|
+
f"{' # type: ignore' if type_ignore else ''}"
|
|
822
|
+
)
|
|
823
|
+
if builder.parameters.has_body and builder.parameters.body_parameter.entries:
|
|
824
|
+
# this is for legacy
|
|
825
|
+
client_name = builder.parameters.body_parameter.client_name
|
|
826
|
+
retval.append(f" {client_name}=_{client_name},")
|
|
827
|
+
elif request_builder.has_form_data_body:
|
|
828
|
+
retval.append(" files=_files,")
|
|
829
|
+
retval.append(" data=_data,")
|
|
830
|
+
elif request_builder.overloads:
|
|
831
|
+
seen_body_params = set()
|
|
832
|
+
for overload in request_builder.overloads:
|
|
833
|
+
body_param = overload.parameters.body_parameter
|
|
834
|
+
if body_param.client_name in seen_body_params:
|
|
835
|
+
continue
|
|
836
|
+
seen_body_params.add(body_param.client_name)
|
|
837
|
+
|
|
838
|
+
retval.append(f" {body_param.client_name}={body_param.name_in_high_level_operation},")
|
|
839
|
+
elif request_builder.parameters.has_body:
|
|
840
|
+
body_param = request_builder.parameters.body_parameter
|
|
841
|
+
retval.append(f" {body_param.client_name}={body_param.name_in_high_level_operation},")
|
|
842
|
+
retval.append(" headers=_headers,")
|
|
843
|
+
retval.append(" params=_params,")
|
|
844
|
+
retval.append(")")
|
|
845
|
+
return retval
|
|
846
|
+
|
|
847
|
+
def _postprocess_http_request(self, builder: OperationType, template_url: Optional[str] = None) -> List[str]:
|
|
848
|
+
retval: List[str] = []
|
|
849
|
+
if builder.parameters.path:
|
|
850
|
+
retval.extend(self.serialize_path(builder))
|
|
851
|
+
url_to_format = "_request.url"
|
|
852
|
+
if self.code_model.options["version_tolerant"] and template_url:
|
|
853
|
+
url_to_format = template_url
|
|
854
|
+
retval.append(
|
|
855
|
+
"_request.url = self._client.format_url({}{})".format(
|
|
856
|
+
url_to_format,
|
|
857
|
+
", **path_format_arguments" if builder.parameters.path else "",
|
|
858
|
+
)
|
|
859
|
+
)
|
|
860
|
+
return retval
|
|
861
|
+
|
|
862
|
+
def _call_request_builder_helper(
|
|
863
|
+
self,
|
|
864
|
+
builder: OperationType,
|
|
865
|
+
request_builder: RequestBuilderType,
|
|
866
|
+
template_url: Optional[str] = None,
|
|
867
|
+
is_next_request: bool = False,
|
|
868
|
+
is_paging: bool = False,
|
|
869
|
+
) -> List[str]:
|
|
870
|
+
retval = []
|
|
871
|
+
if builder.parameters.grouped:
|
|
872
|
+
# request builders don't allow grouped parameters, so we group them before making the call
|
|
873
|
+
retval.extend(_serialize_grouped_body(builder))
|
|
874
|
+
if builder.parameters.has_body and builder.parameters.body_parameter.flattened:
|
|
875
|
+
# serialize flattened body before passing to request builder as well
|
|
876
|
+
retval.extend(_serialize_flattened_body(builder.parameters.body_parameter))
|
|
877
|
+
if is_json_model_type(builder.parameters):
|
|
878
|
+
retval.extend(_serialize_json_model_body(builder.parameters.body_parameter, builder.parameters.parameters))
|
|
879
|
+
if builder.has_form_data_body:
|
|
880
|
+
retval.extend(self._create_body_parameter(builder))
|
|
881
|
+
elif builder.overloads:
|
|
882
|
+
# we are only dealing with two overloads. If there are three, we generate an abstract operation
|
|
883
|
+
retval.extend(self._initialize_overloads(builder, is_paging=is_paging))
|
|
884
|
+
elif builder.parameters.has_body:
|
|
885
|
+
# non-overloaded body
|
|
886
|
+
retval.extend(self._create_body_parameter(builder))
|
|
887
|
+
retval.append("")
|
|
888
|
+
retval.extend(self._create_request_builder_call(builder, request_builder, is_next_request))
|
|
889
|
+
retval.extend(self._postprocess_http_request(builder, template_url))
|
|
890
|
+
return retval
|
|
891
|
+
|
|
892
|
+
def call_request_builder(self, builder: OperationType, is_paging: bool = False) -> List[str]:
|
|
893
|
+
return self._call_request_builder_helper(builder, builder.request_builder, is_paging=is_paging)
|
|
894
|
+
|
|
895
|
+
def response_headers_and_deserialization(
|
|
896
|
+
self,
|
|
897
|
+
builder: OperationType,
|
|
898
|
+
response: Response,
|
|
899
|
+
) -> List[str]:
|
|
900
|
+
return self.response_headers(response) + self.response_deserialization(builder, response)
|
|
901
|
+
|
|
902
|
+
def response_headers(self, response: Response) -> List[str]:
|
|
903
|
+
retval: List[str] = [
|
|
904
|
+
(
|
|
905
|
+
f"response_headers['{response_header.wire_name}']=self._deserialize("
|
|
906
|
+
f"'{response_header.serialization_type}', response.headers.get('{response_header.wire_name}'))"
|
|
907
|
+
)
|
|
908
|
+
for response_header in response.headers
|
|
909
|
+
]
|
|
910
|
+
if response.headers:
|
|
911
|
+
retval.append("")
|
|
912
|
+
return retval
|
|
913
|
+
|
|
914
|
+
def response_deserialization(
|
|
915
|
+
self,
|
|
916
|
+
builder: OperationType,
|
|
917
|
+
response: Response,
|
|
918
|
+
) -> List[str]:
|
|
919
|
+
retval: List[str] = []
|
|
920
|
+
deserialize_code: List[str] = []
|
|
921
|
+
stream_logic = True
|
|
922
|
+
if builder.has_stream_response:
|
|
923
|
+
if isinstance(response.type, ByteArraySchema):
|
|
924
|
+
deserialized = f"{'await ' if self.async_mode else ''}response.read()"
|
|
925
|
+
else:
|
|
926
|
+
stream_logic = False
|
|
927
|
+
if self.code_model.options["version_tolerant"]:
|
|
928
|
+
deserialized = "response.iter_bytes()"
|
|
929
|
+
else:
|
|
930
|
+
deserialized = (
|
|
931
|
+
f"response.stream_download(self._client.{self.pipeline_name}, decompress=_decompress)"
|
|
932
|
+
)
|
|
933
|
+
deserialize_code.append(f"deserialized = {deserialized}")
|
|
934
|
+
elif response.type:
|
|
935
|
+
pylint_disable = ""
|
|
936
|
+
if isinstance(response.type, ModelType) and response.type.internal:
|
|
937
|
+
pylint_disable = " # pylint: disable=protected-access"
|
|
938
|
+
if self.code_model.options["models_mode"] == "msrest":
|
|
939
|
+
deserialize_code.append("deserialized = self._deserialize(")
|
|
940
|
+
deserialize_code.append(f" '{response.serialization_type}',{pylint_disable}")
|
|
941
|
+
deserialize_code.append(" pipeline_response.http_response")
|
|
942
|
+
deserialize_code.append(")")
|
|
943
|
+
elif self.code_model.options["models_mode"] == "dpg":
|
|
944
|
+
if builder.has_stream_response:
|
|
945
|
+
deserialize_code.append("deserialized = response.content")
|
|
946
|
+
else:
|
|
947
|
+
format_filed = (
|
|
948
|
+
f', format="{response.type.encode}"'
|
|
949
|
+
if isinstance(response.type, ByteArraySchema)
|
|
950
|
+
and response.default_content_type == "application/json"
|
|
951
|
+
else ""
|
|
952
|
+
)
|
|
953
|
+
response_attr = "json" if json_serializable(str(response.default_content_type)) else "text"
|
|
954
|
+
deserialize_func = "_deserialize"
|
|
955
|
+
if xml_serializable(str(response.default_content_type)):
|
|
956
|
+
deserialize_func = "_deserialize_xml"
|
|
957
|
+
deserialize_code.append(f"deserialized = {deserialize_func}(")
|
|
958
|
+
deserialize_code.append(
|
|
959
|
+
f" {response.type.type_annotation(is_operation_file=True)},{pylint_disable}"
|
|
960
|
+
)
|
|
961
|
+
deserialize_code.append(f" response.{response_attr}(){response.result_property}{format_filed}")
|
|
962
|
+
deserialize_code.append(")")
|
|
963
|
+
|
|
964
|
+
else:
|
|
965
|
+
deserialized_value = "ET.fromstring(response.text())" if response.type.is_xml else "response.json()"
|
|
966
|
+
deserialize_code.append("if response.content:")
|
|
967
|
+
deserialize_code.append(f" deserialized = {deserialized_value}")
|
|
968
|
+
deserialize_code.append("else:")
|
|
969
|
+
deserialize_code.append(" deserialized = None")
|
|
970
|
+
if len(deserialize_code) > 0:
|
|
971
|
+
if builder.expose_stream_keyword and stream_logic:
|
|
972
|
+
retval.append("if _stream:")
|
|
973
|
+
retval.append(" deserialized = response.iter_bytes()")
|
|
974
|
+
retval.append("else:")
|
|
975
|
+
retval.extend([f" {dc}" for dc in deserialize_code])
|
|
976
|
+
else:
|
|
977
|
+
retval.extend(deserialize_code)
|
|
978
|
+
return retval
|
|
979
|
+
|
|
980
|
+
def handle_error_response(self, builder: OperationType) -> List[str]:
|
|
981
|
+
async_await = "await " if self.async_mode else ""
|
|
982
|
+
retval = [f"if response.status_code not in {str(builder.success_status_codes)}:"]
|
|
983
|
+
response_read = [
|
|
984
|
+
" try:",
|
|
985
|
+
f" {async_await}response.read() # Load the body in memory and close the socket",
|
|
986
|
+
" except (StreamConsumedError, StreamClosedError):",
|
|
987
|
+
" pass",
|
|
988
|
+
]
|
|
989
|
+
if builder.stream_value is True: # _stream is True so no need to judge it
|
|
990
|
+
retval.extend(response_read)
|
|
991
|
+
elif isinstance(builder.stream_value, str): # _stream is not sure, so we need to judge it
|
|
992
|
+
retval.append(" if _stream:")
|
|
993
|
+
retval.extend([f" {l}" for l in response_read])
|
|
994
|
+
retval.append(" map_error(status_code=response.status_code, response=response, error_map=error_map)")
|
|
995
|
+
error_model = ""
|
|
996
|
+
if builder.non_default_errors and self.code_model.options["models_mode"]:
|
|
997
|
+
error_model = ", model=error"
|
|
998
|
+
condition = "if"
|
|
999
|
+
retval.append(" error = None")
|
|
1000
|
+
for e in builder.non_default_errors:
|
|
1001
|
+
# single status code
|
|
1002
|
+
if isinstance(e.status_codes[0], int):
|
|
1003
|
+
for status_code in e.status_codes:
|
|
1004
|
+
retval.append(f" {condition} response.status_code == {status_code}:")
|
|
1005
|
+
if self.code_model.options["models_mode"] == "dpg":
|
|
1006
|
+
retval.append(f" error = _failsafe_deserialize({e.type.type_annotation(is_operation_file=True, skip_quote=True)}, response.json())") # type: ignore # pylint: disable=line-too-long
|
|
1007
|
+
else:
|
|
1008
|
+
retval.append(
|
|
1009
|
+
f" error = self._deserialize.failsafe_deserialize({e.type.type_annotation(is_operation_file=True, skip_quote=True)}, " # type: ignore # pylint: disable=line-too-long
|
|
1010
|
+
"pipeline_response)"
|
|
1011
|
+
)
|
|
1012
|
+
# add build-in error type
|
|
1013
|
+
# TODO: we should decide whether need to this wrapper for customized error type
|
|
1014
|
+
if status_code == 401:
|
|
1015
|
+
retval.append(
|
|
1016
|
+
" raise ClientAuthenticationError(response=response{}{})".format(
|
|
1017
|
+
error_model,
|
|
1018
|
+
(", error_format=ARMErrorFormat" if self.code_model.options["azure_arm"] else ""),
|
|
1019
|
+
)
|
|
1020
|
+
)
|
|
1021
|
+
elif status_code == 404:
|
|
1022
|
+
retval.append(
|
|
1023
|
+
" raise ResourceNotFoundError(response=response{}{})".format(
|
|
1024
|
+
error_model,
|
|
1025
|
+
(", error_format=ARMErrorFormat" if self.code_model.options["azure_arm"] else ""),
|
|
1026
|
+
)
|
|
1027
|
+
)
|
|
1028
|
+
elif status_code == 409:
|
|
1029
|
+
retval.append(
|
|
1030
|
+
" raise ResourceExistsError(response=response{}{})".format(
|
|
1031
|
+
error_model,
|
|
1032
|
+
(", error_format=ARMErrorFormat" if self.code_model.options["azure_arm"] else ""),
|
|
1033
|
+
)
|
|
1034
|
+
)
|
|
1035
|
+
elif status_code == 304:
|
|
1036
|
+
retval.append(
|
|
1037
|
+
" raise ResourceNotModifiedError(response=response{}{})".format(
|
|
1038
|
+
error_model,
|
|
1039
|
+
(", error_format=ARMErrorFormat" if self.code_model.options["azure_arm"] else ""),
|
|
1040
|
+
)
|
|
1041
|
+
)
|
|
1042
|
+
# ranged status code only exist in typespec and will not have multiple status codes
|
|
1043
|
+
else:
|
|
1044
|
+
retval.append(
|
|
1045
|
+
f" {condition} {e.status_codes[0][0]} <= response.status_code <= {e.status_codes[0][1]}:"
|
|
1046
|
+
)
|
|
1047
|
+
if self.code_model.options["models_mode"] == "dpg":
|
|
1048
|
+
retval.append(f" error = _failsafe_deserialize({e.type.type_annotation(is_operation_file=True, skip_quote=True)}, response.json())") # type: ignore # pylint: disable=line-too-long
|
|
1049
|
+
else:
|
|
1050
|
+
retval.append(
|
|
1051
|
+
f" error = self._deserialize.failsafe_deserialize({e.type.type_annotation(is_operation_file=True, skip_quote=True)}, " # type: ignore # pylint: disable=line-too-long
|
|
1052
|
+
"pipeline_response)"
|
|
1053
|
+
)
|
|
1054
|
+
condition = "elif"
|
|
1055
|
+
# default error handling
|
|
1056
|
+
if builder.default_error_deserialization and self.code_model.options["models_mode"]:
|
|
1057
|
+
error_model = ", model=error"
|
|
1058
|
+
indent = " " if builder.non_default_errors else " "
|
|
1059
|
+
if builder.non_default_errors:
|
|
1060
|
+
retval.append(" else:")
|
|
1061
|
+
if self.code_model.options["models_mode"] == "dpg":
|
|
1062
|
+
retval.append(
|
|
1063
|
+
f"{indent}error = _failsafe_deserialize({builder.default_error_deserialization}, response.json())"
|
|
1064
|
+
)
|
|
1065
|
+
else:
|
|
1066
|
+
retval.append(
|
|
1067
|
+
f"{indent}error = self._deserialize.failsafe_deserialize({builder.default_error_deserialization}, "
|
|
1068
|
+
"pipeline_response)"
|
|
1069
|
+
)
|
|
1070
|
+
retval.append(
|
|
1071
|
+
" raise HttpResponseError(response=response{}{})".format(
|
|
1072
|
+
error_model,
|
|
1073
|
+
(", error_format=ARMErrorFormat" if self.code_model.options["azure_arm"] else ""),
|
|
1074
|
+
)
|
|
1075
|
+
)
|
|
1076
|
+
return retval
|
|
1077
|
+
|
|
1078
|
+
def handle_response(self, builder: OperationType) -> List[str]:
|
|
1079
|
+
retval: List[str] = ["response = pipeline_response.http_response"]
|
|
1080
|
+
retval.append("")
|
|
1081
|
+
retval.extend(self.handle_error_response(builder))
|
|
1082
|
+
retval.append("")
|
|
1083
|
+
if builder.has_optional_return_type:
|
|
1084
|
+
retval.append("deserialized = None")
|
|
1085
|
+
if builder.any_response_has_headers:
|
|
1086
|
+
retval.append("response_headers = {}")
|
|
1087
|
+
if builder.has_response_body or builder.any_response_has_headers: # pylint: disable=too-many-nested-blocks
|
|
1088
|
+
if len(builder.responses) > 1:
|
|
1089
|
+
status_codes, res_headers, res_deserialization = [], [], []
|
|
1090
|
+
for status_code in builder.success_status_codes:
|
|
1091
|
+
response = builder.get_response_from_status(status_code) # type: ignore
|
|
1092
|
+
if response.headers or response.type:
|
|
1093
|
+
status_codes.append(status_code)
|
|
1094
|
+
res_headers.append(self.response_headers(response))
|
|
1095
|
+
res_deserialization.append(self.response_deserialization(builder, response))
|
|
1096
|
+
|
|
1097
|
+
is_headers_same = _all_same(res_headers)
|
|
1098
|
+
is_deserialization_same = _all_same(res_deserialization)
|
|
1099
|
+
if is_deserialization_same:
|
|
1100
|
+
if is_headers_same:
|
|
1101
|
+
retval.extend(res_headers[0])
|
|
1102
|
+
retval.extend(res_deserialization[0])
|
|
1103
|
+
retval.append("")
|
|
1104
|
+
else:
|
|
1105
|
+
for status_code, headers in zip(status_codes, res_headers):
|
|
1106
|
+
if headers:
|
|
1107
|
+
retval.append(f"if response.status_code == {status_code}:")
|
|
1108
|
+
retval.extend([f" {line}" for line in headers])
|
|
1109
|
+
retval.append("")
|
|
1110
|
+
retval.extend(res_deserialization[0])
|
|
1111
|
+
retval.append("")
|
|
1112
|
+
else:
|
|
1113
|
+
for status_code, headers, deserialization in zip(status_codes, res_headers, res_deserialization):
|
|
1114
|
+
retval.append(f"if response.status_code == {status_code}:")
|
|
1115
|
+
retval.extend([f" {line}" for line in headers])
|
|
1116
|
+
retval.extend([f" {line}" for line in deserialization])
|
|
1117
|
+
retval.append("")
|
|
1118
|
+
else:
|
|
1119
|
+
retval.extend(self.response_headers_and_deserialization(builder, builder.responses[0]))
|
|
1120
|
+
retval.append("")
|
|
1121
|
+
if builder.has_optional_return_type or self.code_model.options["models_mode"]:
|
|
1122
|
+
deserialized = "deserialized"
|
|
1123
|
+
else:
|
|
1124
|
+
deserialized = f"cast({builder.response_type_annotation(async_mode=self.async_mode)}, deserialized)"
|
|
1125
|
+
retval.append("if cls:")
|
|
1126
|
+
retval.append(
|
|
1127
|
+
" return cls(pipeline_response, {}, {}){}".format(
|
|
1128
|
+
deserialized if builder.has_response_body else "None",
|
|
1129
|
+
"response_headers" if builder.any_response_has_headers else "{}",
|
|
1130
|
+
" # type: ignore",
|
|
1131
|
+
)
|
|
1132
|
+
)
|
|
1133
|
+
if builder.has_response_body and any(
|
|
1134
|
+
response.is_stream_response or response.type for response in builder.responses
|
|
1135
|
+
):
|
|
1136
|
+
retval.append("")
|
|
1137
|
+
retval.append(f"return {deserialized} # type: ignore")
|
|
1138
|
+
if builder.request_builder.method == "HEAD" and self.code_model.options["head_as_boolean"]:
|
|
1139
|
+
retval.append("return 200 <= response.status_code <= 299")
|
|
1140
|
+
return retval
|
|
1141
|
+
|
|
1142
|
+
def _need_specific_error_map(self, code: int, builder: OperationType) -> bool:
|
|
1143
|
+
for non_default_error in builder.non_default_errors:
|
|
1144
|
+
# single status code
|
|
1145
|
+
if code in non_default_error.status_codes:
|
|
1146
|
+
return False
|
|
1147
|
+
# ranged status code
|
|
1148
|
+
if (
|
|
1149
|
+
isinstance(non_default_error.status_codes[0], list)
|
|
1150
|
+
and non_default_error.status_codes[0][0] <= code <= non_default_error.status_codes[0][1]
|
|
1151
|
+
):
|
|
1152
|
+
return False
|
|
1153
|
+
return True
|
|
1154
|
+
|
|
1155
|
+
def error_map(self, builder: OperationType) -> List[str]:
|
|
1156
|
+
retval = ["error_map: MutableMapping = {"]
|
|
1157
|
+
if builder.non_default_errors and self.code_model.options["models_mode"]:
|
|
1158
|
+
# TODO: we should decide whether to add the build-in error map when there is a customized default error type
|
|
1159
|
+
if self._need_specific_error_map(401, builder):
|
|
1160
|
+
retval.append(" 401: ClientAuthenticationError,")
|
|
1161
|
+
if self._need_specific_error_map(404, builder):
|
|
1162
|
+
retval.append(" 404: ResourceNotFoundError,")
|
|
1163
|
+
if self._need_specific_error_map(409, builder):
|
|
1164
|
+
retval.append(" 409: ResourceExistsError,")
|
|
1165
|
+
if self._need_specific_error_map(304, builder):
|
|
1166
|
+
retval.append(" 304: ResourceNotModifiedError,")
|
|
1167
|
+
else:
|
|
1168
|
+
retval.append(
|
|
1169
|
+
" 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError, "
|
|
1170
|
+
"304: ResourceNotModifiedError"
|
|
1171
|
+
)
|
|
1172
|
+
retval.append("}")
|
|
1173
|
+
if builder.has_etag:
|
|
1174
|
+
retval.extend(
|
|
1175
|
+
[
|
|
1176
|
+
"if match_condition == MatchConditions.IfNotModified:",
|
|
1177
|
+
" error_map[412] = ResourceModifiedError",
|
|
1178
|
+
"elif match_condition == MatchConditions.IfPresent:",
|
|
1179
|
+
" error_map[412] = ResourceNotFoundError",
|
|
1180
|
+
"elif match_condition == MatchConditions.IfMissing:",
|
|
1181
|
+
" error_map[412] = ResourceExistsError",
|
|
1182
|
+
]
|
|
1183
|
+
)
|
|
1184
|
+
retval.append("error_map.update(kwargs.pop('error_map', {}) or {})")
|
|
1185
|
+
return retval
|
|
1186
|
+
|
|
1187
|
+
@property
|
|
1188
|
+
def _call_method(self) -> str:
|
|
1189
|
+
return "await " if self.async_mode else ""
|
|
1190
|
+
|
|
1191
|
+
|
|
1192
|
+
class OperationSerializer(_OperationSerializer[Operation]): ...
|
|
1193
|
+
|
|
1194
|
+
|
|
1195
|
+
############################## PAGING OPERATIONS ##############################
|
|
1196
|
+
|
|
1197
|
+
PagingOperationType = TypeVar("PagingOperationType", bound=Union[PagingOperation, LROPagingOperation])
|
|
1198
|
+
|
|
1199
|
+
|
|
1200
|
+
class _PagingOperationSerializer(_OperationSerializer[PagingOperationType]):
|
|
1201
|
+
def __init__(self, code_model: CodeModel, async_mode: bool) -> None:
|
|
1202
|
+
# for pylint reasons need to redefine init
|
|
1203
|
+
# probably because inheritance is going too deep
|
|
1204
|
+
super().__init__(code_model, async_mode)
|
|
1205
|
+
self.code_model = code_model
|
|
1206
|
+
self.async_mode = async_mode
|
|
1207
|
+
self.parameter_serializer = ParameterSerializer()
|
|
1208
|
+
|
|
1209
|
+
def serialize_path(self, builder: PagingOperationType) -> List[str]:
|
|
1210
|
+
return self.parameter_serializer.serialize_path(builder.parameters.path, self.serializer_name)
|
|
1211
|
+
|
|
1212
|
+
def decorators(self, builder: PagingOperationType) -> List[str]:
|
|
1213
|
+
"""Decorators for the method"""
|
|
1214
|
+
retval: List[str] = []
|
|
1215
|
+
if builder.is_overload:
|
|
1216
|
+
return ["@overload"]
|
|
1217
|
+
if self.code_model.options["tracing"] and builder.want_tracing:
|
|
1218
|
+
retval.append("@distributed_trace")
|
|
1219
|
+
if self._api_version_validation(builder):
|
|
1220
|
+
retval.append(self._api_version_validation(builder))
|
|
1221
|
+
return retval
|
|
1222
|
+
|
|
1223
|
+
def call_next_link_request_builder(self, builder: PagingOperationType) -> List[str]:
|
|
1224
|
+
if builder.next_request_builder:
|
|
1225
|
+
request_builder = builder.next_request_builder
|
|
1226
|
+
template_url = None
|
|
1227
|
+
else:
|
|
1228
|
+
request_builder = builder.request_builder
|
|
1229
|
+
template_url = "next_link"
|
|
1230
|
+
|
|
1231
|
+
request_builder = builder.next_request_builder or builder.request_builder
|
|
1232
|
+
if builder.next_request_builder:
|
|
1233
|
+
return self._call_request_builder_helper(
|
|
1234
|
+
builder,
|
|
1235
|
+
request_builder,
|
|
1236
|
+
template_url=template_url,
|
|
1237
|
+
is_next_request=True,
|
|
1238
|
+
)
|
|
1239
|
+
retval: List[str] = []
|
|
1240
|
+
query_str = ""
|
|
1241
|
+
next_link_str = "next_link"
|
|
1242
|
+
try:
|
|
1243
|
+
api_version_param = next(
|
|
1244
|
+
p for p in builder.client.parameters if p.is_api_version and p.location == ParameterLocation.QUERY
|
|
1245
|
+
)
|
|
1246
|
+
retval.append("# make call to next link with the client's api-version")
|
|
1247
|
+
retval.append("_parsed_next_link = urllib.parse.urlparse(next_link)")
|
|
1248
|
+
retval.extend(
|
|
1249
|
+
[
|
|
1250
|
+
"_next_request_params = case_insensitive_dict({",
|
|
1251
|
+
" key: [urllib.parse.quote(v) for v in value]"
|
|
1252
|
+
" for key, value in urllib.parse.parse_qs(_parsed_next_link.query).items()"
|
|
1253
|
+
"})",
|
|
1254
|
+
]
|
|
1255
|
+
)
|
|
1256
|
+
api_version = (
|
|
1257
|
+
"self._api_version"
|
|
1258
|
+
if self.code_model.options["multiapi"] and builder.group_name
|
|
1259
|
+
else api_version_param.full_client_name
|
|
1260
|
+
)
|
|
1261
|
+
retval.append(f'_next_request_params["api-version"] = {api_version}')
|
|
1262
|
+
query_str = ", params=_next_request_params"
|
|
1263
|
+
next_link_str = "urllib.parse.urljoin(next_link, _parsed_next_link.path)"
|
|
1264
|
+
except StopIteration:
|
|
1265
|
+
pass
|
|
1266
|
+
|
|
1267
|
+
retval.append(f'_request = HttpRequest("GET", {next_link_str}{query_str})')
|
|
1268
|
+
retval.extend(self._postprocess_http_request(builder, "_request.url"))
|
|
1269
|
+
|
|
1270
|
+
return retval
|
|
1271
|
+
|
|
1272
|
+
def _prepare_request_callback(self, builder: PagingOperationType) -> List[str]:
|
|
1273
|
+
retval = self._initialize_overloads(builder)
|
|
1274
|
+
retval.append("def prepare_request(next_link=None):")
|
|
1275
|
+
retval.append(" if not next_link:")
|
|
1276
|
+
retval.extend([f" {line}" for line in self.call_request_builder(builder, is_paging=True)])
|
|
1277
|
+
retval.append("")
|
|
1278
|
+
retval.append(" else:")
|
|
1279
|
+
retval.extend([f" {line}" for line in self.call_next_link_request_builder(builder)])
|
|
1280
|
+
if not builder.next_request_builder and self.code_model.is_legacy:
|
|
1281
|
+
retval.append(' _request.method = "GET"')
|
|
1282
|
+
else:
|
|
1283
|
+
retval.append("")
|
|
1284
|
+
retval.append(" return _request")
|
|
1285
|
+
return retval
|
|
1286
|
+
|
|
1287
|
+
@property
|
|
1288
|
+
def _function_def(self) -> str:
|
|
1289
|
+
return "def"
|
|
1290
|
+
|
|
1291
|
+
def _extract_data_callback(self, builder: PagingOperationType) -> List[str]:
|
|
1292
|
+
retval = [f"{'async ' if self.async_mode else ''}def extract_data(pipeline_response):"]
|
|
1293
|
+
response = builder.responses[0]
|
|
1294
|
+
deserialized = "pipeline_response.http_response.json()"
|
|
1295
|
+
if self.code_model.options["models_mode"] == "msrest":
|
|
1296
|
+
suffix = ".http_response" if hasattr(builder, "initial_operation") else ""
|
|
1297
|
+
deserialize_type = response.serialization_type
|
|
1298
|
+
pylint_disable = " # pylint: disable=protected-access"
|
|
1299
|
+
if isinstance(response.type, ModelType) and not response.type.internal:
|
|
1300
|
+
deserialize_type = f'"{response.serialization_type}"'
|
|
1301
|
+
pylint_disable = ""
|
|
1302
|
+
deserialized = (
|
|
1303
|
+
f"self._deserialize(\n {deserialize_type},{pylint_disable}\n pipeline_response{suffix}\n)"
|
|
1304
|
+
)
|
|
1305
|
+
retval.append(f" deserialized = {deserialized}")
|
|
1306
|
+
elif self.code_model.options["models_mode"] == "dpg":
|
|
1307
|
+
# we don't want to generate paging models for DPG
|
|
1308
|
+
retval.append(f" deserialized = {deserialized}")
|
|
1309
|
+
else:
|
|
1310
|
+
retval.append(f" deserialized = {deserialized}")
|
|
1311
|
+
item_name = builder.item_name
|
|
1312
|
+
access = f".{item_name}" if self.code_model.options["models_mode"] == "msrest" else f'["{item_name}"]'
|
|
1313
|
+
list_of_elem_deserialized = ""
|
|
1314
|
+
if self.code_model.options["models_mode"] == "dpg":
|
|
1315
|
+
item_type = builder.item_type.type_annotation(is_operation_file=True)
|
|
1316
|
+
list_of_elem_deserialized = f"_deserialize({item_type}, deserialized{access})"
|
|
1317
|
+
else:
|
|
1318
|
+
list_of_elem_deserialized = f"deserialized{access}"
|
|
1319
|
+
retval.append(f" list_of_elem = {list_of_elem_deserialized}")
|
|
1320
|
+
retval.append(" if cls:")
|
|
1321
|
+
retval.append(" list_of_elem = cls(list_of_elem) # type: ignore")
|
|
1322
|
+
|
|
1323
|
+
continuation_token_name = builder.continuation_token_name
|
|
1324
|
+
if not continuation_token_name:
|
|
1325
|
+
cont_token_property = "None"
|
|
1326
|
+
elif self.code_model.options["models_mode"] == "msrest":
|
|
1327
|
+
cont_token_property = f"deserialized.{continuation_token_name} or None"
|
|
1328
|
+
else:
|
|
1329
|
+
cont_token_property = f'deserialized.get("{continuation_token_name}") or None'
|
|
1330
|
+
list_type = "AsyncList" if self.async_mode else "iter"
|
|
1331
|
+
retval.append(f" return {cont_token_property}, {list_type}(list_of_elem)")
|
|
1332
|
+
return retval
|
|
1333
|
+
|
|
1334
|
+
def _get_next_callback(self, builder: PagingOperationType) -> List[str]:
|
|
1335
|
+
retval = [f"{'async ' if self.async_mode else ''}def get_next(next_link=None):"]
|
|
1336
|
+
retval.append(" _request = prepare_request(next_link)")
|
|
1337
|
+
retval.append("")
|
|
1338
|
+
retval.extend([f" {l}" for l in self.make_pipeline_call(builder)])
|
|
1339
|
+
retval.append(" response = pipeline_response.http_response")
|
|
1340
|
+
retval.append("")
|
|
1341
|
+
retval.extend([f" {line}" for line in self.handle_error_response(builder)])
|
|
1342
|
+
retval.append("")
|
|
1343
|
+
retval.append(" return pipeline_response")
|
|
1344
|
+
return retval
|
|
1345
|
+
|
|
1346
|
+
def set_up_params_for_pager(self, builder: PagingOperationType) -> List[str]:
|
|
1347
|
+
retval = []
|
|
1348
|
+
retval.extend(self.error_map(builder))
|
|
1349
|
+
retval.extend(self._prepare_request_callback(builder))
|
|
1350
|
+
retval.append("")
|
|
1351
|
+
retval.extend(self._extract_data_callback(builder))
|
|
1352
|
+
retval.append("")
|
|
1353
|
+
retval.extend(self._get_next_callback(builder))
|
|
1354
|
+
return retval
|
|
1355
|
+
|
|
1356
|
+
|
|
1357
|
+
class PagingOperationSerializer(_PagingOperationSerializer[PagingOperation]): ...
|
|
1358
|
+
|
|
1359
|
+
|
|
1360
|
+
############################## LRO OPERATIONS ##############################
|
|
1361
|
+
|
|
1362
|
+
LROOperationType = TypeVar("LROOperationType", bound=Union[LROOperation, LROPagingOperation])
|
|
1363
|
+
|
|
1364
|
+
|
|
1365
|
+
class _LROOperationSerializer(_OperationSerializer[LROOperationType]):
|
|
1366
|
+
def __init__(self, code_model: CodeModel, async_mode: bool) -> None:
|
|
1367
|
+
# for pylint reasons need to redefine init
|
|
1368
|
+
# probably because inheritance is going too deep
|
|
1369
|
+
super().__init__(code_model, async_mode)
|
|
1370
|
+
self.code_model = code_model
|
|
1371
|
+
self.async_mode = async_mode
|
|
1372
|
+
self.parameter_serializer = ParameterSerializer()
|
|
1373
|
+
|
|
1374
|
+
def serialize_path(self, builder: LROOperationType) -> List[str]:
|
|
1375
|
+
return self.parameter_serializer.serialize_path(builder.parameters.path, self.serializer_name)
|
|
1376
|
+
|
|
1377
|
+
def initial_call(self, builder: LROOperationType) -> List[str]:
|
|
1378
|
+
retval = [
|
|
1379
|
+
f"polling: Union[bool, {builder.get_base_polling_method(self.async_mode)}] = kwargs.pop('polling', True)",
|
|
1380
|
+
]
|
|
1381
|
+
retval.append("lro_delay = kwargs.pop(")
|
|
1382
|
+
retval.append(" 'polling_interval',")
|
|
1383
|
+
retval.append(" self._config.polling_interval")
|
|
1384
|
+
retval.append(")")
|
|
1385
|
+
retval.append("cont_token: Optional[str] = kwargs.pop('continuation_token', None)")
|
|
1386
|
+
retval.append("if cont_token is None:")
|
|
1387
|
+
retval.append(
|
|
1388
|
+
f" raw_result = {self._call_method}self.{builder.initial_operation.name}("
|
|
1389
|
+
f"{'' if any(rsp.type for rsp in builder.initial_operation.responses) else ' # type: ignore'}"
|
|
1390
|
+
)
|
|
1391
|
+
retval.extend(
|
|
1392
|
+
[f" {parameter.client_name}={parameter.client_name}," for parameter in builder.parameters.method]
|
|
1393
|
+
)
|
|
1394
|
+
retval.append(" cls=lambda x,y,z: x,")
|
|
1395
|
+
retval.append(" headers=_headers,")
|
|
1396
|
+
retval.append(" params=_params,")
|
|
1397
|
+
retval.append(" **kwargs")
|
|
1398
|
+
retval.append(" )")
|
|
1399
|
+
retval.append(f" {'await ' if self.async_mode else ''}raw_result.http_response.read() # type: ignore")
|
|
1400
|
+
|
|
1401
|
+
retval.append("kwargs.pop('error_map', None)")
|
|
1402
|
+
return retval
|
|
1403
|
+
|
|
1404
|
+
def return_lro_poller(self, builder: LROOperationType) -> List[str]:
|
|
1405
|
+
retval = []
|
|
1406
|
+
lro_options_str = (
|
|
1407
|
+
"lro_options={'final-state-via': '" + builder.lro_options["final-state-via"] + "'},"
|
|
1408
|
+
if builder.lro_options
|
|
1409
|
+
else ""
|
|
1410
|
+
)
|
|
1411
|
+
path_format_arguments_str = ""
|
|
1412
|
+
if builder.parameters.path:
|
|
1413
|
+
path_format_arguments_str = "path_format_arguments=path_format_arguments,"
|
|
1414
|
+
retval.extend(self.serialize_path(builder))
|
|
1415
|
+
retval.append("")
|
|
1416
|
+
retval.extend(
|
|
1417
|
+
[
|
|
1418
|
+
"if polling is True:",
|
|
1419
|
+
f" polling_method: {builder.get_base_polling_method(self.async_mode)} "
|
|
1420
|
+
+ f"= cast({builder.get_base_polling_method(self.async_mode)}, "
|
|
1421
|
+
f"{builder.get_polling_method(self.async_mode)}(",
|
|
1422
|
+
" lro_delay,",
|
|
1423
|
+
f" {lro_options_str}",
|
|
1424
|
+
f" {path_format_arguments_str}",
|
|
1425
|
+
" **kwargs",
|
|
1426
|
+
"))",
|
|
1427
|
+
]
|
|
1428
|
+
)
|
|
1429
|
+
retval.append(
|
|
1430
|
+
f"elif polling is False: polling_method = cast({builder.get_base_polling_method(self.async_mode)}, "
|
|
1431
|
+
f"{builder.get_no_polling_method(self.async_mode)}())"
|
|
1432
|
+
)
|
|
1433
|
+
retval.append("else: polling_method = polling")
|
|
1434
|
+
retval.append("if cont_token:")
|
|
1435
|
+
retval.append(f" return {builder.get_poller_with_response_type(self.async_mode)}.from_continuation_token(")
|
|
1436
|
+
retval.append(" polling_method=polling_method,")
|
|
1437
|
+
retval.append(" continuation_token=cont_token,")
|
|
1438
|
+
retval.append(" client=self._client,")
|
|
1439
|
+
retval.append(" deserialization_callback=get_long_running_output")
|
|
1440
|
+
retval.append(" )")
|
|
1441
|
+
retval.append(f"return {builder.get_poller_with_response_type(self.async_mode)}(")
|
|
1442
|
+
retval.append(" self._client, raw_result, get_long_running_output, polling_method # type: ignore")
|
|
1443
|
+
retval.append(" )")
|
|
1444
|
+
return retval
|
|
1445
|
+
|
|
1446
|
+
def get_long_running_output(self, builder: LROOperationType) -> List[str]:
|
|
1447
|
+
pylint_disable = ""
|
|
1448
|
+
if not builder.lro_response:
|
|
1449
|
+
pylint_disable = " # pylint: disable=inconsistent-return-statements"
|
|
1450
|
+
retval = [f"def get_long_running_output(pipeline_response):{pylint_disable}"]
|
|
1451
|
+
if builder.lro_response:
|
|
1452
|
+
if builder.lro_response.headers:
|
|
1453
|
+
retval.append(" response_headers = {}")
|
|
1454
|
+
if (
|
|
1455
|
+
not self.code_model.options["models_mode"]
|
|
1456
|
+
or self.code_model.options["models_mode"] == "dpg"
|
|
1457
|
+
or builder.lro_response.headers
|
|
1458
|
+
):
|
|
1459
|
+
retval.append(" response = pipeline_response.http_response")
|
|
1460
|
+
retval.extend(
|
|
1461
|
+
[f" {line}" for line in self.response_headers_and_deserialization(builder, builder.lro_response)]
|
|
1462
|
+
)
|
|
1463
|
+
retval.append(" if cls:")
|
|
1464
|
+
retval.append(
|
|
1465
|
+
" return cls(pipeline_response, {}, {}){}".format(
|
|
1466
|
+
("deserialized" if builder.lro_response and builder.lro_response.type else "None"),
|
|
1467
|
+
("response_headers" if builder.lro_response and builder.lro_response.headers else "{}"),
|
|
1468
|
+
" # type: ignore",
|
|
1469
|
+
)
|
|
1470
|
+
)
|
|
1471
|
+
if builder.lro_response and builder.lro_response.type:
|
|
1472
|
+
retval.append(" return deserialized")
|
|
1473
|
+
return retval
|
|
1474
|
+
|
|
1475
|
+
|
|
1476
|
+
class LROOperationSerializer(_LROOperationSerializer[LROOperation]): ...
|
|
1477
|
+
|
|
1478
|
+
|
|
1479
|
+
############################## LRO PAGING OPERATIONS ##############################
|
|
1480
|
+
|
|
1481
|
+
|
|
1482
|
+
class LROPagingOperationSerializer(
|
|
1483
|
+
_LROOperationSerializer[LROPagingOperation],
|
|
1484
|
+
_PagingOperationSerializer[LROPagingOperation],
|
|
1485
|
+
):
|
|
1486
|
+
@property
|
|
1487
|
+
def _call_method(self) -> str:
|
|
1488
|
+
return "await " if self.async_mode else ""
|
|
1489
|
+
|
|
1490
|
+
@property
|
|
1491
|
+
def _function_def(self) -> str:
|
|
1492
|
+
return "async def" if self.async_mode else "def"
|
|
1493
|
+
|
|
1494
|
+
def get_long_running_output(self, builder: LROPagingOperation) -> List[str]:
|
|
1495
|
+
retval = ["def get_long_running_output(pipeline_response):"]
|
|
1496
|
+
retval.append(f" {self._function_def} internal_get_next(next_link=None):")
|
|
1497
|
+
retval.append(" if next_link is None:")
|
|
1498
|
+
retval.append(" return pipeline_response")
|
|
1499
|
+
retval.append(f" return {self._call_method}get_next(next_link)")
|
|
1500
|
+
retval.append("")
|
|
1501
|
+
retval.append(f" return {builder.get_pager(self.async_mode)}(")
|
|
1502
|
+
retval.append(" internal_get_next, extract_data")
|
|
1503
|
+
retval.append(" )")
|
|
1504
|
+
return retval
|
|
1505
|
+
|
|
1506
|
+
def decorators(self, builder: LROPagingOperation) -> List[str]:
|
|
1507
|
+
"""Decorators for the method"""
|
|
1508
|
+
return _LROOperationSerializer.decorators(self, builder) # type: ignore
|
|
1509
|
+
|
|
1510
|
+
|
|
1511
|
+
def get_operation_serializer(
|
|
1512
|
+
builder: Operation,
|
|
1513
|
+
code_model,
|
|
1514
|
+
async_mode: bool,
|
|
1515
|
+
) -> Union[
|
|
1516
|
+
OperationSerializer,
|
|
1517
|
+
PagingOperationSerializer,
|
|
1518
|
+
LROOperationSerializer,
|
|
1519
|
+
LROPagingOperationSerializer,
|
|
1520
|
+
]:
|
|
1521
|
+
ret_cls: Union[
|
|
1522
|
+
Type[OperationSerializer],
|
|
1523
|
+
Type[PagingOperationSerializer],
|
|
1524
|
+
Type[LROOperationSerializer],
|
|
1525
|
+
Type[LROPagingOperationSerializer],
|
|
1526
|
+
] = OperationSerializer
|
|
1527
|
+
if builder.operation_type == "lropaging":
|
|
1528
|
+
ret_cls = LROPagingOperationSerializer
|
|
1529
|
+
elif builder.operation_type == "lro":
|
|
1530
|
+
ret_cls = LROOperationSerializer
|
|
1531
|
+
elif builder.operation_type == "paging":
|
|
1532
|
+
ret_cls = PagingOperationSerializer
|
|
1533
|
+
return ret_cls(code_model, async_mode)
|