@typespec/http-client-python 0.32.0 → 0.33.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.js +10 -2
- package/dist/emitter/emitter.js.map +1 -1
- package/dist/emitter/lib.d.ts +6 -0
- package/dist/emitter/lib.d.ts.map +1 -1
- package/dist/emitter/lib.js +29 -0
- package/dist/emitter/lib.js.map +1 -1
- package/emitter/src/emitter.ts +9 -1
- package/emitter/src/lib.ts +36 -0
- 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/__init__.py +1 -0
- package/generator/build/lib/pygen/codegen/models/utils.py +17 -12
- package/generator/build/lib/pygen/codegen/serializers/general_serializer.py +32 -2
- package/generator/build/lib/pygen/codegen/templates/packaging_templates/pyproject.toml.jinja2 +30 -2
- package/generator/build/lib/pygen/preprocess/__init__.py +168 -52
- package/generator/build/lib/pygen/utils.py +38 -4
- package/generator/dist/pygen-0.1.0-py3-none-any.whl +0 -0
- package/generator/pygen/__init__.py +1 -0
- package/generator/pygen/codegen/models/utils.py +17 -12
- package/generator/pygen/codegen/serializers/general_serializer.py +32 -2
- package/generator/pygen/codegen/templates/packaging_templates/pyproject.toml.jinja2 +30 -2
- package/generator/pygen/preprocess/__init__.py +168 -52
- package/generator/pygen/utils.py +38 -4
- package/package.json +1 -1
|
@@ -22,6 +22,7 @@ from ..utils import (
|
|
|
22
22
|
get_body_type_for_description,
|
|
23
23
|
JSON_REGEXP,
|
|
24
24
|
KNOWN_TYPES,
|
|
25
|
+
description_ends_with_code_block,
|
|
25
26
|
)
|
|
26
27
|
|
|
27
28
|
|
|
@@ -35,14 +36,18 @@ def update_overload_section(
|
|
|
35
36
|
if overload_s.get("type"):
|
|
36
37
|
overload_s["type"] = original_s["type"]
|
|
37
38
|
if overload_s.get("headers"):
|
|
38
|
-
for overload_h, original_h in zip(
|
|
39
|
+
for overload_h, original_h in zip(
|
|
40
|
+
overload_s["headers"], original_s["headers"]
|
|
41
|
+
):
|
|
39
42
|
if overload_h.get("type"):
|
|
40
43
|
overload_h["type"] = original_h["type"]
|
|
41
44
|
except KeyError as exc:
|
|
42
45
|
raise ValueError(overload["name"]) from exc
|
|
43
46
|
|
|
44
47
|
|
|
45
|
-
def add_overload(
|
|
48
|
+
def add_overload(
|
|
49
|
+
yaml_data: dict[str, Any], body_type: dict[str, Any], for_flatten_params=False
|
|
50
|
+
):
|
|
46
51
|
overload = copy.deepcopy(yaml_data)
|
|
47
52
|
overload["isOverload"] = True
|
|
48
53
|
overload["bodyParameter"]["type"] = body_type
|
|
@@ -54,7 +59,9 @@ def add_overload(yaml_data: dict[str, Any], body_type: dict[str, Any], for_flatt
|
|
|
54
59
|
if for_flatten_params:
|
|
55
60
|
overload["bodyParameter"]["flattened"] = True
|
|
56
61
|
else:
|
|
57
|
-
overload["parameters"] = [
|
|
62
|
+
overload["parameters"] = [
|
|
63
|
+
p for p in overload["parameters"] if not p.get("inFlattenedBody")
|
|
64
|
+
]
|
|
58
65
|
# for yaml sync, we need to make sure all of the responses, parameters, and exceptions' types have the same yaml id
|
|
59
66
|
for overload_p, original_p in zip(overload["parameters"], yaml_data["parameters"]):
|
|
60
67
|
overload_p["type"] = original_p["type"]
|
|
@@ -62,7 +69,9 @@ def add_overload(yaml_data: dict[str, Any], body_type: dict[str, Any], for_flatt
|
|
|
62
69
|
update_overload_section(overload, yaml_data, "exceptions")
|
|
63
70
|
|
|
64
71
|
# update content type to be an overloads content type
|
|
65
|
-
content_type_param = next(
|
|
72
|
+
content_type_param = next(
|
|
73
|
+
p for p in overload["parameters"] if p["wireName"].lower() == "content-type"
|
|
74
|
+
)
|
|
66
75
|
content_type_param["inOverload"] = True
|
|
67
76
|
content_type_param["inDocstring"] = True
|
|
68
77
|
body_type_description = get_body_type_for_description(overload["bodyParameter"])
|
|
@@ -85,16 +94,25 @@ def add_overloads_for_body_param(yaml_data: dict[str, Any]) -> None:
|
|
|
85
94
|
body_parameter = yaml_data["bodyParameter"]
|
|
86
95
|
if not (
|
|
87
96
|
body_parameter["type"]["type"] == "combined"
|
|
88
|
-
and len(yaml_data["bodyParameter"]["type"]["types"])
|
|
97
|
+
and len(yaml_data["bodyParameter"]["type"]["types"])
|
|
98
|
+
> len(yaml_data["overloads"])
|
|
89
99
|
):
|
|
90
100
|
return
|
|
91
101
|
for body_type in body_parameter["type"]["types"]:
|
|
92
|
-
if any(
|
|
102
|
+
if any(
|
|
103
|
+
o
|
|
104
|
+
for o in yaml_data["overloads"]
|
|
105
|
+
if id(o["bodyParameter"]["type"]) == id(body_type)
|
|
106
|
+
):
|
|
93
107
|
continue
|
|
94
108
|
if body_type.get("type") == "model" and body_type.get("base") == "json":
|
|
95
|
-
yaml_data["overloads"].append(
|
|
109
|
+
yaml_data["overloads"].append(
|
|
110
|
+
add_overload(yaml_data, body_type, for_flatten_params=True)
|
|
111
|
+
)
|
|
96
112
|
yaml_data["overloads"].append(add_overload(yaml_data, body_type))
|
|
97
|
-
content_type_param = next(
|
|
113
|
+
content_type_param = next(
|
|
114
|
+
p for p in yaml_data["parameters"] if p["wireName"].lower() == "content-type"
|
|
115
|
+
)
|
|
98
116
|
content_type_param["inOverload"] = False
|
|
99
117
|
content_type_param["inOverridden"] = True
|
|
100
118
|
content_type_param["inDocstring"] = True
|
|
@@ -104,11 +122,19 @@ def add_overloads_for_body_param(yaml_data: dict[str, Any]) -> None:
|
|
|
104
122
|
content_type_param["optional"] = True
|
|
105
123
|
|
|
106
124
|
|
|
107
|
-
def update_description(
|
|
125
|
+
def update_description(
|
|
126
|
+
description: Optional[str], default_description: str = ""
|
|
127
|
+
) -> str:
|
|
108
128
|
if not description:
|
|
109
129
|
description = default_description
|
|
110
130
|
description.rstrip(" ")
|
|
111
|
-
|
|
131
|
+
# Don't append a trailing period when the description ends with a code block: the
|
|
132
|
+
# period would land inside the rendered literal block (e.g. "]." ) and break Sphinx.
|
|
133
|
+
if (
|
|
134
|
+
description
|
|
135
|
+
and description[-1] != "."
|
|
136
|
+
and not description_ends_with_code_block(description)
|
|
137
|
+
):
|
|
112
138
|
description += "."
|
|
113
139
|
return description
|
|
114
140
|
|
|
@@ -171,7 +197,9 @@ def _get_etag_role(parameter: dict[str, Any]) -> Optional[str]:
|
|
|
171
197
|
return parameter.get("etagRole")
|
|
172
198
|
|
|
173
199
|
|
|
174
|
-
def _pick_etag_slot(
|
|
200
|
+
def _pick_etag_slot(
|
|
201
|
+
candidates: list[dict[str, Any]], standard_wire_name: str
|
|
202
|
+
) -> Optional[dict[str, Any]]:
|
|
175
203
|
"""Choose which etag-typed header should be promoted to the etag/match_condition slot.
|
|
176
204
|
|
|
177
205
|
When more than one etag-typed header is present in an operation, prefer the
|
|
@@ -199,16 +227,25 @@ def _resolve_etag_pair(
|
|
|
199
227
|
Returns (property_if_match, property_if_none_match) — both None when
|
|
200
228
|
there are no etag candidates.
|
|
201
229
|
"""
|
|
202
|
-
property_if_match = _pick_etag_slot(
|
|
203
|
-
|
|
230
|
+
property_if_match = _pick_etag_slot(
|
|
231
|
+
if_match_candidates, STANDARD_IF_MATCH_WIRE_NAME
|
|
232
|
+
)
|
|
233
|
+
property_if_none_match = _pick_etag_slot(
|
|
234
|
+
if_none_match_candidates, STANDARD_IF_NONE_MATCH_WIRE_NAME
|
|
235
|
+
)
|
|
204
236
|
|
|
205
237
|
# Ensure the promoted pair come from the same family. When one slot is
|
|
206
238
|
# standard and the other custom (cross-family), replace the custom slot
|
|
207
239
|
# with a synthetic standard partner. Also synthesize the missing partner
|
|
208
240
|
# when only one side is present.
|
|
209
241
|
if property_if_match and property_if_none_match:
|
|
210
|
-
match_is_std =
|
|
211
|
-
|
|
242
|
+
match_is_std = (
|
|
243
|
+
get_wire_name_lower(property_if_match) == STANDARD_IF_MATCH_WIRE_NAME
|
|
244
|
+
)
|
|
245
|
+
none_match_is_std = (
|
|
246
|
+
get_wire_name_lower(property_if_none_match)
|
|
247
|
+
== STANDARD_IF_NONE_MATCH_WIRE_NAME
|
|
248
|
+
)
|
|
212
249
|
if match_is_std and not none_match_is_std:
|
|
213
250
|
property_if_none_match = property_if_match.copy()
|
|
214
251
|
property_if_none_match["wireName"] = STANDARD_IF_NONE_MATCH_WIRE_NAME
|
|
@@ -256,11 +293,15 @@ def _process_operation_etag_headers(
|
|
|
256
293
|
elif role == "ifNoneMatch":
|
|
257
294
|
if_none_match_candidates.append(p)
|
|
258
295
|
|
|
259
|
-
property_if_match, property_if_none_match = _resolve_etag_pair(
|
|
296
|
+
property_if_match, property_if_none_match = _resolve_etag_pair(
|
|
297
|
+
if_match_candidates, if_none_match_candidates
|
|
298
|
+
)
|
|
260
299
|
|
|
261
300
|
if property_if_match and property_if_none_match:
|
|
262
301
|
etag_params = {id(property_if_match), id(property_if_none_match)}
|
|
263
|
-
operation["parameters"] = [
|
|
302
|
+
operation["parameters"] = [
|
|
303
|
+
item for item in operation["parameters"] if id(item) not in etag_params
|
|
304
|
+
] + [
|
|
264
305
|
property_if_match,
|
|
265
306
|
property_if_none_match,
|
|
266
307
|
]
|
|
@@ -279,7 +320,9 @@ def has_json_content_type(yaml_data: dict[str, Any]) -> bool:
|
|
|
279
320
|
|
|
280
321
|
|
|
281
322
|
def has_multi_part_content_type(yaml_data: dict[str, Any]) -> bool:
|
|
282
|
-
return any(
|
|
323
|
+
return any(
|
|
324
|
+
ct for ct in yaml_data.get("contentTypes", []) if ct == "multipart/form-data"
|
|
325
|
+
)
|
|
283
326
|
|
|
284
327
|
|
|
285
328
|
class PreProcessPlugin(YamlUpdatePlugin):
|
|
@@ -310,13 +353,18 @@ class PreProcessPlugin(YamlUpdatePlugin):
|
|
|
310
353
|
if ( # pylint: disable=too-many-boolean-expressions
|
|
311
354
|
body_parameter
|
|
312
355
|
and body_parameter["type"]["type"] in ("model", "dict", "list")
|
|
313
|
-
and (
|
|
356
|
+
and (
|
|
357
|
+
has_json_content_type(body_parameter)
|
|
358
|
+
or (self.is_tsp and has_multi_part_content_type(body_parameter))
|
|
359
|
+
)
|
|
314
360
|
and not body_parameter["type"].get("xmlMetadata")
|
|
315
361
|
and not any(t for t in ["flattened", "groupedBy"] if body_parameter.get(t))
|
|
316
362
|
):
|
|
317
363
|
origin_type = body_parameter["type"]["type"]
|
|
318
364
|
model_type = (
|
|
319
|
-
body_parameter["type"]
|
|
365
|
+
body_parameter["type"]
|
|
366
|
+
if origin_type == "model"
|
|
367
|
+
else body_parameter["type"].get("elementType", {})
|
|
320
368
|
)
|
|
321
369
|
is_dpg_model = model_type.get("base") == "dpg"
|
|
322
370
|
body_parameter["type"] = {
|
|
@@ -333,19 +381,26 @@ class PreProcessPlugin(YamlUpdatePlugin):
|
|
|
333
381
|
else:
|
|
334
382
|
# dict or list
|
|
335
383
|
# copy the original dict / list type
|
|
336
|
-
any_obj_list_or_dict = copy.deepcopy(
|
|
384
|
+
any_obj_list_or_dict = copy.deepcopy(
|
|
385
|
+
body_parameter["type"]["types"][0]
|
|
386
|
+
)
|
|
337
387
|
any_obj_list_or_dict["elementType"] = KNOWN_TYPES["any-object"]
|
|
338
388
|
body_parameter["type"]["types"].insert(1, any_obj_list_or_dict)
|
|
339
389
|
code_model["types"].append(body_parameter["type"])
|
|
340
390
|
|
|
341
|
-
def pad_reserved_words(
|
|
391
|
+
def pad_reserved_words(
|
|
392
|
+
self, name: str, pad_type: PadType, yaml_type: dict[str, Any]
|
|
393
|
+
) -> str:
|
|
342
394
|
# we want to pad hidden variables as well
|
|
343
395
|
if not name:
|
|
344
396
|
# we'll pass in empty operation groups sometime etc.
|
|
345
397
|
return name
|
|
346
398
|
|
|
347
399
|
if self.is_tsp:
|
|
348
|
-
reserved_words = {
|
|
400
|
+
reserved_words = {
|
|
401
|
+
k: (v + TSP_RESERVED_WORDS.get(k, []))
|
|
402
|
+
for k, v in RESERVED_WORDS.items()
|
|
403
|
+
}
|
|
349
404
|
else:
|
|
350
405
|
reserved_words = RESERVED_WORDS
|
|
351
406
|
name = pad_special_chars(name)
|
|
@@ -362,18 +417,24 @@ class PreProcessPlugin(YamlUpdatePlugin):
|
|
|
362
417
|
def update_types(self, yaml_data: list[dict[str, Any]]) -> None:
|
|
363
418
|
for type in yaml_data:
|
|
364
419
|
for property in type.get("properties", []):
|
|
365
|
-
property["description"] = update_description(
|
|
420
|
+
property["description"] = update_description(
|
|
421
|
+
property.get("description", "")
|
|
422
|
+
)
|
|
366
423
|
if not property.get("isExactName", False):
|
|
367
424
|
property["clientName"] = self.pad_reserved_words(
|
|
368
425
|
property["clientName"].lower(), PadType.PROPERTY, property
|
|
369
426
|
)
|
|
370
427
|
add_redefined_builtin_info(property["clientName"], property)
|
|
371
428
|
if type.get("name"):
|
|
372
|
-
pad_type =
|
|
429
|
+
pad_type = (
|
|
430
|
+
PadType.MODEL if type["type"] == "model" else PadType.ENUM_CLASS
|
|
431
|
+
)
|
|
373
432
|
if type["type"] != "enumvalue":
|
|
374
433
|
name = self.pad_reserved_words(type["name"], pad_type, type)
|
|
375
434
|
type["name"] = name[0].upper() + name[1:]
|
|
376
|
-
type["description"] = update_description(
|
|
435
|
+
type["description"] = update_description(
|
|
436
|
+
type.get("description", ""), type["name"]
|
|
437
|
+
)
|
|
377
438
|
type["snakeCaseName"] = to_snake_case(type["name"])
|
|
378
439
|
if type.get("values"):
|
|
379
440
|
# we're enums - enum values are UPPER_CASE so no padding needed for reserved words
|
|
@@ -391,16 +452,24 @@ class PreProcessPlugin(YamlUpdatePlugin):
|
|
|
391
452
|
yaml_data.append(CLOUD_SETTING["type"]) # type: ignore
|
|
392
453
|
|
|
393
454
|
def update_client(self, yaml_data: dict[str, Any]) -> None:
|
|
394
|
-
yaml_data["description"] = update_description(
|
|
455
|
+
yaml_data["description"] = update_description(
|
|
456
|
+
yaml_data["description"], default_description=yaml_data["name"]
|
|
457
|
+
)
|
|
395
458
|
yaml_data["legacyFilename"] = to_snake_case(yaml_data["name"].replace(" ", "_"))
|
|
396
459
|
parameters = yaml_data["parameters"]
|
|
397
460
|
for parameter in parameters:
|
|
398
461
|
self.update_parameter(parameter)
|
|
399
462
|
if parameter["clientName"] == "credential":
|
|
400
463
|
policy = parameter["type"].get("policy")
|
|
401
|
-
if
|
|
464
|
+
if (
|
|
465
|
+
policy
|
|
466
|
+
and policy["type"] == "BearerTokenCredentialPolicy"
|
|
467
|
+
and self.azure_arm
|
|
468
|
+
):
|
|
402
469
|
policy["type"] = "ARMChallengeAuthenticationPolicy"
|
|
403
|
-
policy["credentialScopes"] = [
|
|
470
|
+
policy["credentialScopes"] = [
|
|
471
|
+
"https://management.azure.com/.default"
|
|
472
|
+
]
|
|
404
473
|
if (
|
|
405
474
|
(not self.version_tolerant or self.azure_arm)
|
|
406
475
|
and parameters
|
|
@@ -420,7 +489,9 @@ class PreProcessPlugin(YamlUpdatePlugin):
|
|
|
420
489
|
if self.azure_arm and yaml_data["parameters"]:
|
|
421
490
|
yaml_data["parameters"].append(CLOUD_SETTING)
|
|
422
491
|
|
|
423
|
-
def get_operation_updater(
|
|
492
|
+
def get_operation_updater(
|
|
493
|
+
self, yaml_data: dict[str, Any]
|
|
494
|
+
) -> Callable[[dict[str, Any], dict[str, Any]], None]:
|
|
424
495
|
if yaml_data["discriminator"] == "lropaging":
|
|
425
496
|
return self.update_lro_paging_operation
|
|
426
497
|
if yaml_data["discriminator"] == "lro":
|
|
@@ -432,7 +503,8 @@ class PreProcessPlugin(YamlUpdatePlugin):
|
|
|
432
503
|
def update_parameter(self, yaml_data: dict[str, Any]) -> None:
|
|
433
504
|
yaml_data["description"] = update_description(yaml_data.get("description", ""))
|
|
434
505
|
if not yaml_data.get("isExactName", False) and not (
|
|
435
|
-
yaml_data["location"] == "header"
|
|
506
|
+
yaml_data["location"] == "header"
|
|
507
|
+
and yaml_data["clientName"] in ("content_type", "accept")
|
|
436
508
|
):
|
|
437
509
|
yaml_data["clientName"] = self.pad_reserved_words(
|
|
438
510
|
yaml_data["clientName"].lower(), PadType.PARAMETER, yaml_data
|
|
@@ -448,13 +520,16 @@ class PreProcessPlugin(YamlUpdatePlugin):
|
|
|
448
520
|
prop: (
|
|
449
521
|
param_name
|
|
450
522
|
if prop in exact_name_props
|
|
451
|
-
else self.pad_reserved_words(
|
|
523
|
+
else self.pad_reserved_words(
|
|
524
|
+
param_name, PadType.PARAMETER, yaml_data
|
|
525
|
+
).lower()
|
|
452
526
|
)
|
|
453
527
|
for prop, param_name in yaml_data["propertyToParameterName"].items()
|
|
454
528
|
}
|
|
455
529
|
wire_name_lower = (yaml_data.get("wireName") or "").lower()
|
|
456
530
|
if yaml_data["location"] == "header" and (
|
|
457
|
-
wire_name_lower in HEADERS_HIDE_IN_METHOD
|
|
531
|
+
wire_name_lower in HEADERS_HIDE_IN_METHOD
|
|
532
|
+
or yaml_data.get("clientDefaultValue") == "multipart/form-data"
|
|
458
533
|
):
|
|
459
534
|
yaml_data["hideInMethod"] = True
|
|
460
535
|
if self.version_tolerant and yaml_data["location"] == "header":
|
|
@@ -463,7 +538,10 @@ class PreProcessPlugin(YamlUpdatePlugin):
|
|
|
463
538
|
headers_convert(yaml_data, ETAG_MATCH_DATA)
|
|
464
539
|
elif role == "ifNoneMatch":
|
|
465
540
|
headers_convert(yaml_data, ETAG_NONE_MATCH_DATA)
|
|
466
|
-
if
|
|
541
|
+
if (
|
|
542
|
+
wire_name_lower in ["$host", "content-type", "accept"]
|
|
543
|
+
and yaml_data["type"]["type"] == "constant"
|
|
544
|
+
):
|
|
467
545
|
yaml_data["clientDefaultValue"] = yaml_data["type"]["value"]
|
|
468
546
|
|
|
469
547
|
def update_operation(
|
|
@@ -473,24 +551,36 @@ class PreProcessPlugin(YamlUpdatePlugin):
|
|
|
473
551
|
*,
|
|
474
552
|
is_overload: bool = False,
|
|
475
553
|
) -> None:
|
|
476
|
-
yaml_data["groupName"] = self.pad_reserved_words(
|
|
554
|
+
yaml_data["groupName"] = self.pad_reserved_words(
|
|
555
|
+
yaml_data["groupName"], PadType.OPERATION_GROUP, yaml_data
|
|
556
|
+
)
|
|
477
557
|
yaml_data["groupName"] = to_snake_case(yaml_data["groupName"])
|
|
478
558
|
if yaml_data.get("isExactName", False):
|
|
479
559
|
# exact() client name: keep the operation name as-is without lowercasing,
|
|
480
560
|
# snake-casing, or padding reserved words.
|
|
481
561
|
if yaml_data.get("isLroInitialOperation") is True:
|
|
482
|
-
yaml_data["name"] =
|
|
562
|
+
yaml_data["name"] = (
|
|
563
|
+
"_" + extract_original_name(yaml_data["name"]) + "_initial"
|
|
564
|
+
)
|
|
483
565
|
else:
|
|
484
566
|
yaml_data["name"] = yaml_data["name"].lower()
|
|
485
567
|
if yaml_data.get("isLroInitialOperation") is True:
|
|
486
568
|
yaml_data["name"] = (
|
|
487
569
|
"_"
|
|
488
|
-
+ self.pad_reserved_words(
|
|
570
|
+
+ self.pad_reserved_words(
|
|
571
|
+
extract_original_name(yaml_data["name"]),
|
|
572
|
+
PadType.METHOD,
|
|
573
|
+
yaml_data,
|
|
574
|
+
)
|
|
489
575
|
+ "_initial"
|
|
490
576
|
)
|
|
491
577
|
else:
|
|
492
|
-
yaml_data["name"] = self.pad_reserved_words(
|
|
493
|
-
|
|
578
|
+
yaml_data["name"] = self.pad_reserved_words(
|
|
579
|
+
yaml_data["name"], PadType.METHOD, yaml_data
|
|
580
|
+
)
|
|
581
|
+
yaml_data["description"] = update_description(
|
|
582
|
+
yaml_data["description"], yaml_data["name"]
|
|
583
|
+
)
|
|
494
584
|
yaml_data["summary"] = update_description(yaml_data.get("summary", ""))
|
|
495
585
|
body_parameter = yaml_data.get("bodyParameter")
|
|
496
586
|
for parameter in yaml_data["parameters"]:
|
|
@@ -511,8 +601,12 @@ class PreProcessPlugin(YamlUpdatePlugin):
|
|
|
511
601
|
def _update_lro_operation_helper(self, yaml_data: dict[str, Any]) -> None:
|
|
512
602
|
for response in yaml_data.get("responses", []):
|
|
513
603
|
response["discriminator"] = "lro"
|
|
514
|
-
response["pollerSync"] =
|
|
515
|
-
|
|
604
|
+
response["pollerSync"] = (
|
|
605
|
+
response.get("pollerSync") or "azure.core.polling.LROPoller"
|
|
606
|
+
)
|
|
607
|
+
response["pollerAsync"] = (
|
|
608
|
+
response.get("pollerAsync") or "azure.core.polling.AsyncLROPoller"
|
|
609
|
+
)
|
|
516
610
|
if not response.get("pollingMethodSync"):
|
|
517
611
|
response["pollingMethodSync"] = (
|
|
518
612
|
"azure.mgmt.core.polling.arm_polling.ARMPolling"
|
|
@@ -534,7 +628,9 @@ class PreProcessPlugin(YamlUpdatePlugin):
|
|
|
534
628
|
item_type: Optional[dict[str, Any]] = None,
|
|
535
629
|
) -> None:
|
|
536
630
|
self.update_lro_operation(code_model, yaml_data, is_overload=is_overload)
|
|
537
|
-
self.update_paging_operation(
|
|
631
|
+
self.update_paging_operation(
|
|
632
|
+
code_model, yaml_data, is_overload=is_overload, item_type=item_type
|
|
633
|
+
)
|
|
538
634
|
yaml_data["discriminator"] = "lropaging"
|
|
539
635
|
for response in yaml_data.get("responses", []):
|
|
540
636
|
response["discriminator"] = "lropaging"
|
|
@@ -557,12 +653,16 @@ class PreProcessPlugin(YamlUpdatePlugin):
|
|
|
557
653
|
response["type"] = KNOWN_TYPES["binary"]
|
|
558
654
|
|
|
559
655
|
self.update_operation(code_model, yaml_data, is_overload=is_overload)
|
|
560
|
-
self.update_operation(
|
|
656
|
+
self.update_operation(
|
|
657
|
+
code_model, yaml_data["initialOperation"], is_overload=is_overload
|
|
658
|
+
)
|
|
561
659
|
convert_initial_operation_response_type(yaml_data["initialOperation"])
|
|
562
660
|
self._update_lro_operation_helper(yaml_data)
|
|
563
661
|
for overload in yaml_data.get("overloads", []):
|
|
564
662
|
self._update_lro_operation_helper(overload)
|
|
565
|
-
self.update_operation(
|
|
663
|
+
self.update_operation(
|
|
664
|
+
code_model, overload["initialOperation"], is_overload=True
|
|
665
|
+
)
|
|
566
666
|
convert_initial_operation_response_type(overload["initialOperation"])
|
|
567
667
|
|
|
568
668
|
def update_paging_operation(
|
|
@@ -576,9 +676,13 @@ class PreProcessPlugin(YamlUpdatePlugin):
|
|
|
576
676
|
item_type = item_type or yaml_data["itemType"]["elementType"]
|
|
577
677
|
if yaml_data.get("nextOperation"):
|
|
578
678
|
yaml_data["nextOperation"]["groupName"] = self.pad_reserved_words(
|
|
579
|
-
yaml_data["nextOperation"]["groupName"],
|
|
679
|
+
yaml_data["nextOperation"]["groupName"],
|
|
680
|
+
PadType.OPERATION_GROUP,
|
|
681
|
+
yaml_data["nextOperation"],
|
|
682
|
+
)
|
|
683
|
+
yaml_data["nextOperation"]["groupName"] = to_snake_case(
|
|
684
|
+
yaml_data["nextOperation"]["groupName"]
|
|
580
685
|
)
|
|
581
|
-
yaml_data["nextOperation"]["groupName"] = to_snake_case(yaml_data["nextOperation"]["groupName"])
|
|
582
686
|
for response in yaml_data["nextOperation"].get("responses", []):
|
|
583
687
|
update_paging_response(response)
|
|
584
688
|
response["itemType"] = item_type
|
|
@@ -586,9 +690,13 @@ class PreProcessPlugin(YamlUpdatePlugin):
|
|
|
586
690
|
update_paging_response(response)
|
|
587
691
|
response["itemType"] = item_type
|
|
588
692
|
for overload in yaml_data.get("overloads", []):
|
|
589
|
-
self.update_paging_operation(
|
|
693
|
+
self.update_paging_operation(
|
|
694
|
+
code_model, overload, is_overload=True, item_type=item_type
|
|
695
|
+
)
|
|
590
696
|
|
|
591
|
-
def update_operation_groups(
|
|
697
|
+
def update_operation_groups(
|
|
698
|
+
self, code_model: dict[str, Any], client: dict[str, Any]
|
|
699
|
+
) -> None:
|
|
592
700
|
operation_groups_yaml_data = client.get("operationGroups", [])
|
|
593
701
|
for operation_group in operation_groups_yaml_data:
|
|
594
702
|
operation_group["identifyName"] = self.pad_reserved_words(
|
|
@@ -596,11 +704,17 @@ class PreProcessPlugin(YamlUpdatePlugin):
|
|
|
596
704
|
PadType.OPERATION_GROUP,
|
|
597
705
|
operation_group,
|
|
598
706
|
)
|
|
599
|
-
operation_group["identifyName"] = to_snake_case(
|
|
707
|
+
operation_group["identifyName"] = to_snake_case(
|
|
708
|
+
operation_group["identifyName"]
|
|
709
|
+
)
|
|
600
710
|
operation_group["propertyName"] = self.pad_reserved_words(
|
|
601
|
-
operation_group["propertyName"],
|
|
711
|
+
operation_group["propertyName"],
|
|
712
|
+
PadType.OPERATION_GROUP,
|
|
713
|
+
operation_group,
|
|
714
|
+
)
|
|
715
|
+
operation_group["propertyName"] = to_snake_case(
|
|
716
|
+
operation_group["propertyName"]
|
|
602
717
|
)
|
|
603
|
-
operation_group["propertyName"] = to_snake_case(operation_group["propertyName"])
|
|
604
718
|
operation_group["className"] = update_operation_group_class_name(
|
|
605
719
|
client["name"], operation_group["className"]
|
|
606
720
|
)
|
|
@@ -624,4 +738,6 @@ class PreProcessPlugin(YamlUpdatePlugin):
|
|
|
624
738
|
if __name__ == "__main__":
|
|
625
739
|
# TSP pipeline will call this
|
|
626
740
|
args, unknown_args = parse_args()
|
|
627
|
-
PreProcessPlugin(
|
|
741
|
+
PreProcessPlugin(
|
|
742
|
+
output_folder=args.output_folder, tsp_file=args.tsp_file, **unknown_args
|
|
743
|
+
).process()
|
package/generator/pygen/utils.py
CHANGED
|
@@ -11,8 +11,31 @@ SWAGGER_PACKAGE_MODE = ["mgmtplane", "dataplane"] # for backward compatibility
|
|
|
11
11
|
TYPESPEC_PACKAGE_MODE = ["azure-mgmt", "azure-dataplane", "generic"]
|
|
12
12
|
VALID_PACKAGE_MODE = SWAGGER_PACKAGE_MODE + TYPESPEC_PACKAGE_MODE
|
|
13
13
|
|
|
14
|
+
CODE_BLOCK_MARKER = ".. code-block::"
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def description_ends_with_code_block(description: str) -> bool:
|
|
18
|
+
"""Return True when the description's trailing content is an RST ``.. code-block::``.
|
|
19
|
+
|
|
20
|
+
True when the last ``.. code-block::`` directive (starting its own line, so inline
|
|
21
|
+
mentions are ignored) is followed only by blank or indented lines, i.e. the literal
|
|
22
|
+
block runs to the end of the description.
|
|
23
|
+
"""
|
|
24
|
+
lines = description.rstrip().splitlines()
|
|
25
|
+
directives = [
|
|
26
|
+
i for i, line in enumerate(lines) if line.lstrip().startswith(CODE_BLOCK_MARKER)
|
|
27
|
+
]
|
|
28
|
+
if not directives:
|
|
29
|
+
return False
|
|
30
|
+
return all(
|
|
31
|
+
not line.strip() or line.startswith((" ", "\t"))
|
|
32
|
+
for line in lines[directives[-1] + 1 :]
|
|
33
|
+
)
|
|
34
|
+
|
|
14
35
|
|
|
15
|
-
def update_enum_value(
|
|
36
|
+
def update_enum_value(
|
|
37
|
+
name: str, value: Any, description: str, enum_type: dict[str, Any]
|
|
38
|
+
) -> dict[str, Any]:
|
|
16
39
|
return {
|
|
17
40
|
"name": name,
|
|
18
41
|
"type": "enumvalue",
|
|
@@ -39,7 +62,12 @@ def to_snake_case(name: str) -> str:
|
|
|
39
62
|
and len(name) - next_non_upper_case_char_location > 1
|
|
40
63
|
and name[next_non_upper_case_char_location].isalpha()
|
|
41
64
|
):
|
|
42
|
-
return
|
|
65
|
+
return (
|
|
66
|
+
prefix
|
|
67
|
+
+ match_str[: len(match_str) - 1]
|
|
68
|
+
+ "_"
|
|
69
|
+
+ match_str[len(match_str) - 1]
|
|
70
|
+
)
|
|
43
71
|
|
|
44
72
|
return prefix + match_str
|
|
45
73
|
|
|
@@ -86,7 +114,9 @@ def parse_args(
|
|
|
86
114
|
return value
|
|
87
115
|
|
|
88
116
|
unknown_args_ret = {
|
|
89
|
-
ua.strip("--").split("=", maxsplit=1)[0]: _get_value(
|
|
117
|
+
ua.strip("--").split("=", maxsplit=1)[0]: _get_value(
|
|
118
|
+
ua.strip("--").split("=", maxsplit=1)[1]
|
|
119
|
+
)
|
|
90
120
|
for ua in unknown_args
|
|
91
121
|
}
|
|
92
122
|
return args, unknown_args_ret
|
|
@@ -128,7 +158,11 @@ def build_policies(
|
|
|
128
158
|
"self._config.user_agent_policy",
|
|
129
159
|
"self._config.proxy_policy",
|
|
130
160
|
"policies.ContentDecodePolicy(**kwargs)",
|
|
131
|
-
(
|
|
161
|
+
(
|
|
162
|
+
f"{async_prefix}ARMAutoResourceProviderRegistrationPolicy()"
|
|
163
|
+
if is_arm
|
|
164
|
+
else None
|
|
165
|
+
),
|
|
132
166
|
"self._config.redirect_policy",
|
|
133
167
|
"self._config.retry_policy",
|
|
134
168
|
"self._config.authentication_policy",
|