@typespec/http-client-python 0.37.3 → 0.38.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/emitter/temp/tsconfig.tsbuildinfo +1 -1
- package/eng/scripts/setup/__pycache__/package_manager.cpython-311.pyc +0 -0
- package/eng/scripts/setup/__pycache__/venvtools.cpython-311.pyc +0 -0
- package/generator/build/lib/pygen/codegen/models/response.py +5 -0
- package/generator/build/lib/pygen/codegen/serializers/builder_serializer.py +76 -23
- package/generator/build/lib/pygen/codegen/serializers/unions_serializer.py +14 -3
- package/generator/build/lib/pygen/codegen/templates/streaming_base.py.jinja2 +235 -54
- package/generator/build/lib/pygen/codegen/templates/unions.py.jinja2 +1 -1
- package/generator/build/lib/pygen/preprocess/__init__.py +4 -3
- package/generator/dist/pygen-0.1.0-py3-none-any.whl +0 -0
- package/generator/pygen/codegen/models/response.py +5 -0
- package/generator/pygen/codegen/serializers/builder_serializer.py +76 -23
- package/generator/pygen/codegen/serializers/unions_serializer.py +14 -3
- package/generator/pygen/codegen/templates/streaming_base.py.jinja2 +235 -54
- package/generator/pygen/codegen/templates/unions.py.jinja2 +1 -1
- package/generator/pygen/preprocess/__init__.py +4 -3
- package/package.json +1 -1
|
Binary file
|
|
Binary file
|
|
@@ -267,6 +267,11 @@ class Response(BaseModel):
|
|
|
267
267
|
file_import.add_submodule_import(relative_path, stream_class, ImportType.LOCAL)
|
|
268
268
|
if self.streaming_kind == "sse":
|
|
269
269
|
file_import.add_import("json", ImportType.STDLIB)
|
|
270
|
+
read_response_helper = (
|
|
271
|
+
"_read_sse_response_async" if kwargs.get("async_mode", False) else "_read_sse_response"
|
|
272
|
+
)
|
|
273
|
+
file_import.add_submodule_import(relative_path, read_response_helper, ImportType.LOCAL)
|
|
274
|
+
file_import.add_submodule_import(relative_path, "_update_sse_request_headers", ImportType.LOCAL)
|
|
270
275
|
for event in self.streaming_events:
|
|
271
276
|
file_import.merge(event.payload_type.imports(**kwargs))
|
|
272
277
|
return file_import
|
|
@@ -1150,22 +1150,36 @@ class _OperationSerializer(_BuilderBaseSerializer[OperationType]):
|
|
|
1150
1150
|
return retval
|
|
1151
1151
|
|
|
1152
1152
|
def handle_error_response( # pylint: disable=too-many-statements, too-many-branches
|
|
1153
|
-
self,
|
|
1153
|
+
self,
|
|
1154
|
+
builder: OperationType,
|
|
1155
|
+
*,
|
|
1156
|
+
response_name: str = "response",
|
|
1157
|
+
pipeline_response_name: str = "pipeline_response",
|
|
1158
|
+
success_status_codes: Optional[list[int]] = None,
|
|
1159
|
+
stream_value: Optional[Union[str, bool]] = None,
|
|
1160
|
+
response_read_name: Optional[str] = None,
|
|
1154
1161
|
) -> list[str]:
|
|
1155
1162
|
async_await = "await " if self.async_mode else ""
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
"
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1163
|
+
success_status_codes = builder.success_status_codes if success_status_codes is None else success_status_codes
|
|
1164
|
+
stream_value = builder.stream_value if stream_value is None else stream_value
|
|
1165
|
+
retval = [f"if {response_name}.status_code not in {str(success_status_codes)}:"]
|
|
1166
|
+
if response_read_name:
|
|
1167
|
+
response_read = [f" {async_await}{response_read_name}({response_name})"]
|
|
1168
|
+
else:
|
|
1169
|
+
response_read = [
|
|
1170
|
+
" try:",
|
|
1171
|
+
f" {async_await}{response_name}.read() # Load the body in memory and close the socket",
|
|
1172
|
+
" except (StreamConsumedError, StreamClosedError):",
|
|
1173
|
+
" pass",
|
|
1174
|
+
]
|
|
1175
|
+
if stream_value is True: # _stream is True so no need to judge it
|
|
1164
1176
|
retval.extend(response_read)
|
|
1165
|
-
elif isinstance(
|
|
1177
|
+
elif isinstance(stream_value, str): # _stream is not sure, so we need to judge it
|
|
1166
1178
|
retval.append(" if _stream:")
|
|
1167
1179
|
retval.extend([f" {l}" for l in response_read])
|
|
1168
|
-
retval.append(
|
|
1180
|
+
retval.append(
|
|
1181
|
+
f" map_error(status_code={response_name}.status_code, " f"response={response_name}, error_map=error_map)"
|
|
1182
|
+
)
|
|
1169
1183
|
error_model = ""
|
|
1170
1184
|
if builder.non_default_errors and ( # pylint: disable=too-many-nested-blocks
|
|
1171
1185
|
self.code_model.options["models-mode"] or self.code_model.generate_typeddict_only
|
|
@@ -1181,7 +1195,7 @@ class _OperationSerializer(_BuilderBaseSerializer[OperationType]):
|
|
|
1181
1195
|
pylint_disable = ""
|
|
1182
1196
|
if isinstance(e.status_codes[0], int):
|
|
1183
1197
|
for status_code in e.status_codes:
|
|
1184
|
-
retval.append(f" {condition}
|
|
1198
|
+
retval.append(f" {condition} {response_name}.status_code == {status_code}:")
|
|
1185
1199
|
type_annotation = e.type.type_annotation( # type: ignore
|
|
1186
1200
|
is_operation_file=True, skip_quote=True, serialize_namespace=self.serialize_namespace
|
|
1187
1201
|
)
|
|
@@ -1190,13 +1204,15 @@ class _OperationSerializer(_BuilderBaseSerializer[OperationType]):
|
|
|
1190
1204
|
fn = "_failsafe_deserialize_xml"
|
|
1191
1205
|
else:
|
|
1192
1206
|
fn = "_failsafe_deserialize"
|
|
1193
|
-
retval.append(
|
|
1207
|
+
retval.append(
|
|
1208
|
+
f" error = {fn}({type_annotation},{pylint_disable}\n {response_name})"
|
|
1209
|
+
)
|
|
1194
1210
|
else:
|
|
1195
1211
|
retval.extend(
|
|
1196
1212
|
[
|
|
1197
1213
|
" error = self._deserialize.failsafe_deserialize(",
|
|
1198
1214
|
f" {type_annotation},{pylint_disable}",
|
|
1199
|
-
"
|
|
1215
|
+
f" {pipeline_response_name},",
|
|
1200
1216
|
" )",
|
|
1201
1217
|
]
|
|
1202
1218
|
)
|
|
@@ -1209,7 +1225,8 @@ class _OperationSerializer(_BuilderBaseSerializer[OperationType]):
|
|
|
1209
1225
|
# ranged status code only exist in typespec and will not have multiple status codes
|
|
1210
1226
|
else:
|
|
1211
1227
|
retval.append(
|
|
1212
|
-
f" {condition} {e.status_codes[0][0]} <=
|
|
1228
|
+
f" {condition} {e.status_codes[0][0]} <= "
|
|
1229
|
+
f"{response_name}.status_code <= {e.status_codes[0][1]}:"
|
|
1213
1230
|
)
|
|
1214
1231
|
type_annotation = e.type.type_annotation( # type: ignore
|
|
1215
1232
|
is_operation_file=True, skip_quote=True, serialize_namespace=self.serialize_namespace
|
|
@@ -1218,19 +1235,19 @@ class _OperationSerializer(_BuilderBaseSerializer[OperationType]):
|
|
|
1218
1235
|
if xml_serializable(str(e.default_content_type)):
|
|
1219
1236
|
retval.append(
|
|
1220
1237
|
" error = _failsafe_deserialize_xml("
|
|
1221
|
-
f"{type_annotation},{pylint_disable}\n
|
|
1238
|
+
f"{type_annotation},{pylint_disable}\n {response_name})"
|
|
1222
1239
|
)
|
|
1223
1240
|
else:
|
|
1224
1241
|
retval.append(
|
|
1225
|
-
" error = _failsafe_deserialize("
|
|
1226
|
-
f"{type_annotation},{pylint_disable}\n
|
|
1242
|
+
f" error = _failsafe_deserialize("
|
|
1243
|
+
f"{type_annotation},{pylint_disable}\n {response_name})"
|
|
1227
1244
|
)
|
|
1228
1245
|
else:
|
|
1229
1246
|
retval.extend(
|
|
1230
1247
|
[
|
|
1231
1248
|
" error = self._deserialize.failsafe_deserialize(",
|
|
1232
1249
|
f" {type_annotation},{pylint_disable}",
|
|
1233
|
-
"
|
|
1250
|
+
f" {pipeline_response_name},",
|
|
1234
1251
|
" )",
|
|
1235
1252
|
]
|
|
1236
1253
|
)
|
|
@@ -1254,7 +1271,7 @@ class _OperationSerializer(_BuilderBaseSerializer[OperationType]):
|
|
|
1254
1271
|
[
|
|
1255
1272
|
f"{indent}error = {fn}(",
|
|
1256
1273
|
f"{indent} {default_error_deserialization}",
|
|
1257
|
-
f"{indent}
|
|
1274
|
+
f"{indent} {response_name},",
|
|
1258
1275
|
f"{indent})",
|
|
1259
1276
|
]
|
|
1260
1277
|
)
|
|
@@ -1263,12 +1280,13 @@ class _OperationSerializer(_BuilderBaseSerializer[OperationType]):
|
|
|
1263
1280
|
[
|
|
1264
1281
|
f"{indent}error = self._deserialize.failsafe_deserialize(",
|
|
1265
1282
|
f"{indent} {default_error_deserialization}",
|
|
1266
|
-
f"{indent}
|
|
1283
|
+
f"{indent} {pipeline_response_name},",
|
|
1267
1284
|
f"{indent})",
|
|
1268
1285
|
]
|
|
1269
1286
|
)
|
|
1270
1287
|
retval.append(
|
|
1271
|
-
" raise HttpResponseError(response=
|
|
1288
|
+
" raise HttpResponseError(response={}{}{})".format(
|
|
1289
|
+
response_name,
|
|
1272
1290
|
error_model,
|
|
1273
1291
|
(", error_format=ARMErrorFormat" if self.code_model.options["azure-arm"] else ""),
|
|
1274
1292
|
)
|
|
@@ -1378,6 +1396,41 @@ class _OperationSerializer(_BuilderBaseSerializer[OperationType]):
|
|
|
1378
1396
|
stream_kwargs.append(f"terminal_event={terminal_event!r}")
|
|
1379
1397
|
if terminal_event_names:
|
|
1380
1398
|
stream_kwargs.append(f"terminal_event_names={terminal_event_names!r}")
|
|
1399
|
+
if response.streaming_kind == "sse": # type: ignore[attr-defined]
|
|
1400
|
+
retval.append("")
|
|
1401
|
+
retval.append(
|
|
1402
|
+
"async def _reconnect(_last_event_id, _reconnect_delay):"
|
|
1403
|
+
if self.async_mode
|
|
1404
|
+
else "def _reconnect(_last_event_id, _reconnect_delay):"
|
|
1405
|
+
)
|
|
1406
|
+
retval.append(" _transport: Any = pipeline_response.context.transport")
|
|
1407
|
+
retval.append(f" {'await ' if self.async_mode else ''}_transport.sleep(_reconnect_delay)")
|
|
1408
|
+
retval.append(" _update_sse_request_headers(_request, _last_event_id)")
|
|
1409
|
+
retval.append(
|
|
1410
|
+
f" _reconnect_response = {self._call_method}self._client.send_request("
|
|
1411
|
+
"_request, stream=True, **kwargs)"
|
|
1412
|
+
)
|
|
1413
|
+
reconnect_status_codes = list(builder.success_status_codes)
|
|
1414
|
+
if 204 not in reconnect_status_codes:
|
|
1415
|
+
reconnect_status_codes.append(204)
|
|
1416
|
+
retval.extend(
|
|
1417
|
+
[
|
|
1418
|
+
f" {line}"
|
|
1419
|
+
for line in self.handle_error_response(
|
|
1420
|
+
builder,
|
|
1421
|
+
response_name="_reconnect_response",
|
|
1422
|
+
pipeline_response_name=(
|
|
1423
|
+
"PipelineResponse(_request, _reconnect_response, pipeline_response.context)"
|
|
1424
|
+
),
|
|
1425
|
+
success_status_codes=reconnect_status_codes,
|
|
1426
|
+
stream_value=True,
|
|
1427
|
+
response_read_name=("_read_sse_response_async" if self.async_mode else "_read_sse_response"),
|
|
1428
|
+
)
|
|
1429
|
+
]
|
|
1430
|
+
)
|
|
1431
|
+
retval.append(" return _reconnect_response")
|
|
1432
|
+
stream_kwargs.append("last_event_id=_last_event_id")
|
|
1433
|
+
stream_kwargs.append("reconnect_callback=_reconnect")
|
|
1381
1434
|
unnamed_terminal_values = (
|
|
1382
1435
|
[discriminator_value for discriminator_value, event in unnamed_discriminator[1] if event.is_terminal]
|
|
1383
1436
|
if unnamed_discriminator is not None
|
|
@@ -1843,7 +1896,7 @@ class _LROOperationSerializer(_OperationSerializer[LROOperationType]):
|
|
|
1843
1896
|
if builder.lro_response.headers:
|
|
1844
1897
|
retval.append(" response_headers = {}")
|
|
1845
1898
|
if (
|
|
1846
|
-
|
|
1899
|
+
not self.code_model.options["models-mode"]
|
|
1847
1900
|
or self.code_model.options["models-mode"] == "dpg"
|
|
1848
1901
|
or builder.lro_response.headers
|
|
1849
1902
|
):
|
|
@@ -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 ..models import CodeModel
|
|
6
|
+
from ..models import CodeModel, CombinedType
|
|
7
7
|
from ..models.imports import FileImport, ImportType
|
|
8
8
|
from ..models.utils import NamespaceType
|
|
9
9
|
from .import_serializer import FileImportSerializer
|
|
@@ -18,9 +18,19 @@ class UnionsSerializer(BaseSerializer):
|
|
|
18
18
|
):
|
|
19
19
|
super().__init__(code_model=code_model, env=env)
|
|
20
20
|
|
|
21
|
+
@property
|
|
22
|
+
def named_unions(self) -> list[CombinedType]:
|
|
23
|
+
# The same named union can reach codegen as multiple objects, so collapse
|
|
24
|
+
# by emitted alias name (keeping insertion order) to avoid duplicate aliases.
|
|
25
|
+
deduped: dict[str, CombinedType] = {}
|
|
26
|
+
for union in self.code_model.named_unions:
|
|
27
|
+
if union.name:
|
|
28
|
+
deduped.setdefault(union.name, union)
|
|
29
|
+
return list(deduped.values())
|
|
30
|
+
|
|
21
31
|
def imports(self) -> FileImport:
|
|
22
32
|
file_import = FileImport(self.code_model)
|
|
23
|
-
if self.
|
|
33
|
+
if self.named_unions:
|
|
24
34
|
file_import.add_submodule_import(
|
|
25
35
|
"typing",
|
|
26
36
|
"TypeAlias",
|
|
@@ -31,7 +41,7 @@ class UnionsSerializer(BaseSerializer):
|
|
|
31
41
|
"Union",
|
|
32
42
|
ImportType.STDLIB,
|
|
33
43
|
)
|
|
34
|
-
for nu in self.
|
|
44
|
+
for nu in self.named_unions:
|
|
35
45
|
file_import.merge(
|
|
36
46
|
nu.imports(
|
|
37
47
|
serialize_namespace=self.serialize_namespace,
|
|
@@ -44,6 +54,7 @@ class UnionsSerializer(BaseSerializer):
|
|
|
44
54
|
template = self.env.get_template("unions.py.jinja2")
|
|
45
55
|
return template.render(
|
|
46
56
|
code_model=self.code_model,
|
|
57
|
+
named_unions=self.named_unions,
|
|
47
58
|
imports=FileImportSerializer(self.imports()),
|
|
48
59
|
serializer=self,
|
|
49
60
|
)
|