@typespec/http-client-python 0.4.4 → 0.5.1
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 +110 -24
- package/dist/emitter/emitter.js.map +1 -1
- package/dist/emitter/http.js +1 -1
- package/dist/emitter/http.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 +111 -23
- package/emitter/src/http.ts +1 -1
- 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/Test-Packages.ps1 +1 -1
- package/eng/scripts/ci/regenerate.ts +20 -8
- 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 -8
- package/eng/scripts/setup/install.ts +12 -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/codegen/__init__.py +4 -4
- package/generator/pygen.egg-info/PKG-INFO +7 -4
- package/generator/pygen.egg-info/requires.txt +7 -4
- package/generator/setup.py +7 -4
- package/generator/test/azure/mock_api_tests/asynctests/test_azure_client_generator_core_flatten_async.py +1 -1
- package/generator/test/{generic_mock_api_tests/asynctests/test_payload_pageable_async.py → azure/mock_api_tests/asynctests/test_azure_payload_pageable_async.py} +1 -1
- package/generator/test/azure/mock_api_tests/conftest.py +5 -4
- package/generator/test/azure/mock_api_tests/test_azure_client_generator_core_flatten.py +1 -1
- package/generator/test/{generic_mock_api_tests/test_payload_pageable.py → azure/mock_api_tests/test_azure_payload_pageable.py} +1 -1
- package/generator/test/{generic_mock_api_tests → azure/mock_api_tests}/test_resiliency_srv_driven.py +4 -2
- package/generator/test/{generic_mock_api_tests/asynctests → azure/mock_api_tests}/test_resiliency_srv_driven_async.py +3 -2
- package/generator/test/azure/requirements.txt +9 -8
- package/generator/test/generic_mock_api_tests/conftest.py +9 -4
- package/generator/test/unbranded/mock_api_tests/conftest.py +4 -4
- package/generator/test/unbranded/mock_api_tests/test_unbranded.py +1 -1
- package/generator/test/unbranded/requirements.txt +1 -8
- package/package.json +10 -10
- package/generator/requirements.txt +0 -12
- /package/generator/test/{generic_mock_api_tests → azure/mock_api_tests}/asynctests/test_client_naming_async.py +0 -0
- /package/generator/test/{generic_mock_api_tests → azure/mock_api_tests}/asynctests/test_client_structure_async.py +0 -0
- /package/generator/test/{generic_mock_api_tests → azure/mock_api_tests}/test_client_naming.py +0 -0
- /package/generator/test/{generic_mock_api_tests → azure/mock_api_tests}/test_client_structure.py +0 -0
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# -------------------------------------------------------------------------
|
|
2
|
+
# Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3
|
+
# Licensed under the MIT License. See License.txt in the project root for
|
|
4
|
+
# license information.
|
|
5
|
+
# --------------------------------------------------------------------------
|
|
6
|
+
from typing import List
|
|
7
|
+
from jinja2 import Environment
|
|
8
|
+
|
|
9
|
+
from ..models.operation_group import OperationGroup
|
|
10
|
+
from ..models import CodeModel, Client
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class OperationsInitSerializer:
|
|
14
|
+
def __init__(
|
|
15
|
+
self,
|
|
16
|
+
code_model: CodeModel,
|
|
17
|
+
clients: List[Client],
|
|
18
|
+
env: Environment,
|
|
19
|
+
async_mode: bool,
|
|
20
|
+
) -> None:
|
|
21
|
+
self.code_model = code_model
|
|
22
|
+
self.clients = clients
|
|
23
|
+
self.env = env
|
|
24
|
+
self.async_mode = async_mode
|
|
25
|
+
|
|
26
|
+
def operation_group_imports(self) -> List[str]:
|
|
27
|
+
def _get_filename(operation_group: OperationGroup) -> str:
|
|
28
|
+
return "_operations" if self.code_model.options["combine_operation_files"] else operation_group.filename
|
|
29
|
+
|
|
30
|
+
return [
|
|
31
|
+
f"from .{_get_filename(og)} import {og.class_name} # type: ignore"
|
|
32
|
+
for client in self.clients
|
|
33
|
+
for og in client.operation_groups
|
|
34
|
+
]
|
|
35
|
+
|
|
36
|
+
def serialize(self) -> str:
|
|
37
|
+
operation_group_init_template = self.env.get_template("operations_folder_init.py.jinja2")
|
|
38
|
+
|
|
39
|
+
return operation_group_init_template.render(
|
|
40
|
+
code_model=self.code_model,
|
|
41
|
+
async_mode=self.async_mode,
|
|
42
|
+
operation_group_imports=self.operation_group_imports,
|
|
43
|
+
clients=self.clients,
|
|
44
|
+
)
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
# -------------------------------------------------------------------------
|
|
2
|
+
# Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3
|
+
# Licensed under the MIT License. See License.txt in the project root for
|
|
4
|
+
# license information.
|
|
5
|
+
# --------------------------------------------------------------------------
|
|
6
|
+
from typing import List, Sequence, Union, Optional, Dict
|
|
7
|
+
from enum import Enum, auto
|
|
8
|
+
|
|
9
|
+
from ..models import (
|
|
10
|
+
Parameter,
|
|
11
|
+
ParameterLocation,
|
|
12
|
+
ListType,
|
|
13
|
+
ParameterDelimeter,
|
|
14
|
+
RequestBuilderParameter,
|
|
15
|
+
ClientParameter,
|
|
16
|
+
ConfigParameter,
|
|
17
|
+
ParameterType,
|
|
18
|
+
)
|
|
19
|
+
from ..models.parameter import _ParameterBase
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class PopKwargType(Enum):
|
|
23
|
+
NO = auto()
|
|
24
|
+
SIMPLE = auto()
|
|
25
|
+
CASE_INSENSITIVE = auto()
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
SPECIAL_HEADER_SERIALIZATION: Dict[str, List[str]] = {
|
|
29
|
+
"repeatability-request-id": [
|
|
30
|
+
"""if "Repeatability-Request-ID" not in _headers:""",
|
|
31
|
+
""" _headers["Repeatability-Request-ID"] = str(uuid.uuid4())""",
|
|
32
|
+
],
|
|
33
|
+
"repeatability-first-sent": [
|
|
34
|
+
"""if "Repeatability-First-Sent" not in _headers:""",
|
|
35
|
+
""" _headers["Repeatability-First-Sent"] = _SERIALIZER.serialize_data(""",
|
|
36
|
+
""" datetime.datetime.now(datetime.timezone.utc), "rfc-1123")""",
|
|
37
|
+
],
|
|
38
|
+
"client-request-id": [],
|
|
39
|
+
"x-ms-client-request-id": [],
|
|
40
|
+
"return-client-request-id": [],
|
|
41
|
+
"etag": [
|
|
42
|
+
"""if_match = prep_if_match(etag, match_condition)""",
|
|
43
|
+
"""if if_match is not None:""",
|
|
44
|
+
""" _headers["If-Match"] = _SERIALIZER.header("if_match", if_match, "str")""",
|
|
45
|
+
],
|
|
46
|
+
"match-condition": [
|
|
47
|
+
"""if_none_match = prep_if_none_match(etag, match_condition)""",
|
|
48
|
+
"""if if_none_match is not None:""",
|
|
49
|
+
""" _headers["If-None-Match"] = _SERIALIZER.header("if_none_match", if_none_match, "str")""",
|
|
50
|
+
],
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class ParameterSerializer:
|
|
55
|
+
@staticmethod
|
|
56
|
+
def serialize_parameter(parameter: ParameterType, serializer_name: str) -> str:
|
|
57
|
+
optional_parameters = []
|
|
58
|
+
|
|
59
|
+
if parameter.skip_url_encoding:
|
|
60
|
+
optional_parameters.append("skip_quote=True")
|
|
61
|
+
|
|
62
|
+
if parameter.delimiter and not parameter.explode:
|
|
63
|
+
if parameter.delimiter == ParameterDelimeter.COMMA:
|
|
64
|
+
div_char = ","
|
|
65
|
+
elif parameter.delimiter == ParameterDelimeter.SPACE:
|
|
66
|
+
div_char = " "
|
|
67
|
+
elif parameter.delimiter == ParameterDelimeter.PIPE:
|
|
68
|
+
div_char = "|"
|
|
69
|
+
elif parameter.delimiter == ParameterDelimeter.TAB:
|
|
70
|
+
div_char = "\t"
|
|
71
|
+
else:
|
|
72
|
+
raise ValueError(f"We do not support {parameter.delimiter} yet")
|
|
73
|
+
optional_parameters.append(f"div='{div_char}'")
|
|
74
|
+
|
|
75
|
+
if parameter.explode:
|
|
76
|
+
if not isinstance(parameter.type, ListType):
|
|
77
|
+
raise ValueError("Got a explode boolean on a non-array schema")
|
|
78
|
+
type = parameter.type.element_type
|
|
79
|
+
else:
|
|
80
|
+
type = parameter.type
|
|
81
|
+
|
|
82
|
+
serialization_constraints = type.serialization_constraints
|
|
83
|
+
if serialization_constraints:
|
|
84
|
+
optional_parameters += serialization_constraints
|
|
85
|
+
|
|
86
|
+
origin_name = parameter.full_client_name
|
|
87
|
+
|
|
88
|
+
parameters = [
|
|
89
|
+
f'"{origin_name.lstrip("_")}"',
|
|
90
|
+
"q" if parameter.explode else origin_name,
|
|
91
|
+
f"'{type.serialization_type}'",
|
|
92
|
+
*optional_parameters,
|
|
93
|
+
]
|
|
94
|
+
parameters_line = ", ".join(parameters)
|
|
95
|
+
|
|
96
|
+
msrest_function_name = {
|
|
97
|
+
ParameterLocation.PATH: "url",
|
|
98
|
+
ParameterLocation.ENDPOINT_PATH: "url",
|
|
99
|
+
ParameterLocation.HEADER: "header",
|
|
100
|
+
ParameterLocation.QUERY: "query",
|
|
101
|
+
}[parameter.location]
|
|
102
|
+
|
|
103
|
+
serialize_line = f"{serializer_name}.{msrest_function_name}({parameters_line})"
|
|
104
|
+
|
|
105
|
+
if parameter.explode:
|
|
106
|
+
return f"[{serialize_line} if q is not None else '' for q in {origin_name}]"
|
|
107
|
+
return serialize_line
|
|
108
|
+
|
|
109
|
+
@staticmethod
|
|
110
|
+
def serialize_path(
|
|
111
|
+
parameters: Union[
|
|
112
|
+
List[Parameter],
|
|
113
|
+
List[RequestBuilderParameter],
|
|
114
|
+
List[ClientParameter],
|
|
115
|
+
List[ConfigParameter],
|
|
116
|
+
],
|
|
117
|
+
serializer_name: str,
|
|
118
|
+
) -> List[str]:
|
|
119
|
+
retval = ["path_format_arguments = {"]
|
|
120
|
+
retval.extend(
|
|
121
|
+
[
|
|
122
|
+
' "{}": {},'.format(
|
|
123
|
+
path_parameter.wire_name,
|
|
124
|
+
ParameterSerializer.serialize_parameter(path_parameter, serializer_name),
|
|
125
|
+
)
|
|
126
|
+
for path_parameter in parameters
|
|
127
|
+
]
|
|
128
|
+
)
|
|
129
|
+
retval.append("}")
|
|
130
|
+
return retval
|
|
131
|
+
|
|
132
|
+
@staticmethod
|
|
133
|
+
def serialize_query_header(
|
|
134
|
+
param: Parameter,
|
|
135
|
+
kwarg_name: str,
|
|
136
|
+
serializer_name: str,
|
|
137
|
+
is_legacy: bool,
|
|
138
|
+
) -> List[str]:
|
|
139
|
+
if (
|
|
140
|
+
not is_legacy
|
|
141
|
+
and param.location == ParameterLocation.HEADER
|
|
142
|
+
and param.wire_name.lower() in SPECIAL_HEADER_SERIALIZATION
|
|
143
|
+
):
|
|
144
|
+
return SPECIAL_HEADER_SERIALIZATION[param.wire_name.lower()]
|
|
145
|
+
|
|
146
|
+
set_parameter = "_{}['{}'] = {}".format(
|
|
147
|
+
kwarg_name,
|
|
148
|
+
param.wire_name,
|
|
149
|
+
ParameterSerializer.serialize_parameter(param, serializer_name),
|
|
150
|
+
)
|
|
151
|
+
if not param.optional and (param.in_method_signature or param.constant):
|
|
152
|
+
retval = [set_parameter]
|
|
153
|
+
else:
|
|
154
|
+
retval = [
|
|
155
|
+
f"if {param.full_client_name} is not None:",
|
|
156
|
+
f" {set_parameter}",
|
|
157
|
+
]
|
|
158
|
+
return retval
|
|
159
|
+
|
|
160
|
+
@staticmethod
|
|
161
|
+
def pop_kwargs_from_signature(
|
|
162
|
+
parameters: Sequence[_ParameterBase],
|
|
163
|
+
check_kwarg_dict: bool,
|
|
164
|
+
pop_headers_kwarg: PopKwargType,
|
|
165
|
+
pop_params_kwarg: PopKwargType,
|
|
166
|
+
check_client_input: bool = False,
|
|
167
|
+
operation_name: Optional[str] = None,
|
|
168
|
+
) -> List[str]:
|
|
169
|
+
retval = []
|
|
170
|
+
|
|
171
|
+
def append_pop_kwarg(key: str, pop_type: PopKwargType) -> None:
|
|
172
|
+
if PopKwargType.CASE_INSENSITIVE == pop_type:
|
|
173
|
+
retval.append(f'_{key} = case_insensitive_dict(kwargs.pop("{key}", {{}}) or {{}})')
|
|
174
|
+
elif PopKwargType.SIMPLE == pop_type:
|
|
175
|
+
retval.append(f'_{key} = kwargs.pop("{key}", {{}}) or {{}}')
|
|
176
|
+
|
|
177
|
+
append_pop_kwarg("headers", pop_headers_kwarg)
|
|
178
|
+
append_pop_kwarg("params", pop_params_kwarg)
|
|
179
|
+
if pop_headers_kwarg != PopKwargType.NO or pop_params_kwarg != PopKwargType.NO:
|
|
180
|
+
retval.append("")
|
|
181
|
+
for kwarg in parameters:
|
|
182
|
+
type_annotation = kwarg.type_annotation()
|
|
183
|
+
if kwarg.client_default_value is not None or kwarg.optional:
|
|
184
|
+
if check_client_input and kwarg.check_client_input:
|
|
185
|
+
default_value = f"self._config.{kwarg.client_name}"
|
|
186
|
+
else:
|
|
187
|
+
default_value = kwarg.client_default_value_declaration
|
|
188
|
+
if check_kwarg_dict and (kwarg.location in [ParameterLocation.HEADER, ParameterLocation.QUERY]):
|
|
189
|
+
kwarg_dict = "headers" if kwarg.location == ParameterLocation.HEADER else "params"
|
|
190
|
+
if (
|
|
191
|
+
kwarg.client_name == "api_version"
|
|
192
|
+
and kwarg.code_model.options["multiapi"]
|
|
193
|
+
and operation_name is not None
|
|
194
|
+
):
|
|
195
|
+
default_value = f"self._api_version{operation_name} or {default_value}"
|
|
196
|
+
default_value = f"_{kwarg_dict}.pop('{kwarg.wire_name}', {default_value})"
|
|
197
|
+
|
|
198
|
+
retval.append(
|
|
199
|
+
f"{kwarg.client_name}: {type_annotation} = kwargs.pop('{kwarg.client_name}', " + f"{default_value})"
|
|
200
|
+
)
|
|
201
|
+
else:
|
|
202
|
+
retval.append(f"{kwarg.client_name}: {type_annotation} = kwargs.pop('{kwarg.client_name}')")
|
|
203
|
+
return retval
|
|
204
|
+
|
|
205
|
+
@staticmethod
|
|
206
|
+
def serialize_method(
|
|
207
|
+
*,
|
|
208
|
+
function_def: str,
|
|
209
|
+
method_name: str,
|
|
210
|
+
need_self_param: bool,
|
|
211
|
+
method_param_signatures: List[str],
|
|
212
|
+
pylint_disable: str = "",
|
|
213
|
+
):
|
|
214
|
+
lines: List[str] = []
|
|
215
|
+
first_line = f"{function_def} {method_name}({pylint_disable}"
|
|
216
|
+
lines.append(first_line)
|
|
217
|
+
if need_self_param:
|
|
218
|
+
lines.append(" self,")
|
|
219
|
+
lines.extend([(" " + line) for line in method_param_signatures])
|
|
220
|
+
lines.append(")")
|
|
221
|
+
return "\n".join(lines)
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# -------------------------------------------------------------------------
|
|
2
|
+
# Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3
|
+
# Licensed under the MIT License. See License.txt in the project root for
|
|
4
|
+
# license information.
|
|
5
|
+
# --------------------------------------------------------------------------
|
|
6
|
+
from .import_serializer import FileImportSerializer
|
|
7
|
+
from ..models import ImportType, FileImport
|
|
8
|
+
from .base_serializer import BaseSerializer
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class PatchSerializer(BaseSerializer):
|
|
12
|
+
def serialize(self) -> str:
|
|
13
|
+
template = self.env.get_template("patch.py.jinja2")
|
|
14
|
+
imports = FileImport(self.code_model)
|
|
15
|
+
imports.add_submodule_import("typing", "List", ImportType.STDLIB)
|
|
16
|
+
return template.render(
|
|
17
|
+
code_model=self.code_model,
|
|
18
|
+
imports=FileImportSerializer(imports),
|
|
19
|
+
)
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# -------------------------------------------------------------------------
|
|
2
|
+
# Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3
|
+
# Licensed under the MIT License. See License.txt in the project root for
|
|
4
|
+
# license information.
|
|
5
|
+
# --------------------------------------------------------------------------
|
|
6
|
+
from typing import List
|
|
7
|
+
from jinja2 import Environment
|
|
8
|
+
|
|
9
|
+
from ..models import FileImport
|
|
10
|
+
from .import_serializer import FileImportSerializer
|
|
11
|
+
from ..models import CodeModel, RequestBuilderType
|
|
12
|
+
from .builder_serializer import RequestBuilderSerializer
|
|
13
|
+
from .base_serializer import BaseSerializer
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class RequestBuildersSerializer(BaseSerializer):
|
|
17
|
+
def __init__(
|
|
18
|
+
self,
|
|
19
|
+
code_model: CodeModel,
|
|
20
|
+
env: Environment,
|
|
21
|
+
request_builders: List[RequestBuilderType],
|
|
22
|
+
) -> None:
|
|
23
|
+
super().__init__(code_model, env)
|
|
24
|
+
self.request_builders = request_builders
|
|
25
|
+
self.group_name = request_builders[0].group_name
|
|
26
|
+
|
|
27
|
+
@property
|
|
28
|
+
def imports(self) -> FileImport:
|
|
29
|
+
file_import = FileImport(self.code_model)
|
|
30
|
+
for request_builder in self.request_builders:
|
|
31
|
+
if request_builder.group_name == self.group_name:
|
|
32
|
+
file_import.merge(request_builder.imports())
|
|
33
|
+
return file_import
|
|
34
|
+
|
|
35
|
+
def serialize_init(self) -> str:
|
|
36
|
+
template = self.env.get_template("rest_init.py.jinja2")
|
|
37
|
+
return template.render(
|
|
38
|
+
code_model=self.code_model,
|
|
39
|
+
request_builders=[r for r in self.request_builders if not r.is_overload],
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
def serialize_request_builders(self) -> str:
|
|
43
|
+
template = self.env.get_template("request_builders.py.jinja2")
|
|
44
|
+
|
|
45
|
+
return template.render(
|
|
46
|
+
code_model=self.code_model,
|
|
47
|
+
request_builders=[rb for rb in self.request_builders if not rb.abstract],
|
|
48
|
+
imports=FileImportSerializer(
|
|
49
|
+
self.imports,
|
|
50
|
+
),
|
|
51
|
+
request_builder_serializer=RequestBuilderSerializer(self.code_model, async_mode=False),
|
|
52
|
+
)
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
# -------------------------------------------------------------------------
|
|
2
|
+
# Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3
|
+
# Licensed under the MIT License. See License.txt in the project root for
|
|
4
|
+
# license information.
|
|
5
|
+
# --------------------------------------------------------------------------
|
|
6
|
+
import logging
|
|
7
|
+
from typing import Dict, Any, Union, Tuple
|
|
8
|
+
from jinja2 import Environment
|
|
9
|
+
|
|
10
|
+
from ..models.operation import OperationBase
|
|
11
|
+
from .import_serializer import FileImportSerializer
|
|
12
|
+
from .base_serializer import BaseSerializer
|
|
13
|
+
from ..models import (
|
|
14
|
+
CodeModel,
|
|
15
|
+
KeyCredentialType,
|
|
16
|
+
TokenCredentialType,
|
|
17
|
+
ImportType,
|
|
18
|
+
OperationGroup,
|
|
19
|
+
Parameter,
|
|
20
|
+
BodyParameter,
|
|
21
|
+
FileImport,
|
|
22
|
+
)
|
|
23
|
+
from .utils import get_namespace_config, get_namespace_from_package_name
|
|
24
|
+
|
|
25
|
+
_LOGGER = logging.getLogger(__name__)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class SampleSerializer(BaseSerializer):
|
|
29
|
+
def __init__(
|
|
30
|
+
self,
|
|
31
|
+
code_model: CodeModel,
|
|
32
|
+
env: Environment,
|
|
33
|
+
operation_group: OperationGroup,
|
|
34
|
+
operation: OperationBase[Any],
|
|
35
|
+
sample: Dict[str, Any],
|
|
36
|
+
file_name: str,
|
|
37
|
+
) -> None:
|
|
38
|
+
super().__init__(code_model, env)
|
|
39
|
+
self.operation_group = operation_group
|
|
40
|
+
self.operation = operation
|
|
41
|
+
self.sample = sample
|
|
42
|
+
self.file_name = file_name
|
|
43
|
+
self.sample_params = sample.get("parameters", {})
|
|
44
|
+
|
|
45
|
+
def _imports(self) -> FileImportSerializer:
|
|
46
|
+
imports = FileImport(self.code_model)
|
|
47
|
+
namespace_from_package_name = get_namespace_from_package_name(self.code_model.options["package_name"])
|
|
48
|
+
namespace_config = get_namespace_config(self.code_model.namespace, self.code_model.options["multiapi"])
|
|
49
|
+
namespace = namespace_from_package_name or namespace_config
|
|
50
|
+
# mainly for "azure-mgmt-rdbms"
|
|
51
|
+
if not self.code_model.options["multiapi"] and namespace_config.count(".") > namespace_from_package_name.count(
|
|
52
|
+
"."
|
|
53
|
+
):
|
|
54
|
+
namespace = namespace_config
|
|
55
|
+
client = self.code_model.clients[0]
|
|
56
|
+
imports.add_submodule_import(namespace, client.name, ImportType.LOCAL)
|
|
57
|
+
credential_type = getattr(client.credential, "type", None)
|
|
58
|
+
if isinstance(credential_type, TokenCredentialType):
|
|
59
|
+
imports.add_submodule_import("azure.identity", "DefaultAzureCredential", ImportType.SDKCORE)
|
|
60
|
+
elif isinstance(credential_type, KeyCredentialType):
|
|
61
|
+
imports.add_import("os", ImportType.STDLIB)
|
|
62
|
+
imports.add_submodule_import(
|
|
63
|
+
"credentials",
|
|
64
|
+
"AzureKeyCredential",
|
|
65
|
+
ImportType.SDKCORE,
|
|
66
|
+
)
|
|
67
|
+
for param in self.operation.parameters.positional + self.operation.parameters.keyword_only:
|
|
68
|
+
if not param.client_default_value and not param.optional and param.wire_name in self.sample_params:
|
|
69
|
+
imports.merge(param.type.imports_for_sample())
|
|
70
|
+
return FileImportSerializer(imports, True)
|
|
71
|
+
|
|
72
|
+
def _client_params(self) -> Dict[str, Any]:
|
|
73
|
+
# client params
|
|
74
|
+
special_param = {}
|
|
75
|
+
credential_type = getattr(self.code_model.clients[0].credential, "type", None)
|
|
76
|
+
if isinstance(credential_type, TokenCredentialType):
|
|
77
|
+
special_param.update({"credential": "DefaultAzureCredential()"})
|
|
78
|
+
elif isinstance(credential_type, KeyCredentialType):
|
|
79
|
+
special_param.update({"credential": 'AzureKeyCredential(key=os.getenv("AZURE_KEY"))'})
|
|
80
|
+
|
|
81
|
+
params = [
|
|
82
|
+
p
|
|
83
|
+
for p in (
|
|
84
|
+
self.code_model.clients[0].parameters.positional + self.code_model.clients[0].parameters.keyword_only
|
|
85
|
+
)
|
|
86
|
+
if not (p.optional or p.client_default_value)
|
|
87
|
+
]
|
|
88
|
+
client_params = {
|
|
89
|
+
p.client_name: special_param.get(
|
|
90
|
+
p.client_name,
|
|
91
|
+
f'"{self.sample_params.get(p.wire_name) or p.client_name.upper()}"',
|
|
92
|
+
)
|
|
93
|
+
for p in params
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return client_params
|
|
97
|
+
|
|
98
|
+
@staticmethod
|
|
99
|
+
def handle_param(param: Union[Parameter, BodyParameter], param_value: Any) -> str:
|
|
100
|
+
if isinstance(param_value, str):
|
|
101
|
+
if any(i in param_value for i in '\r\n"'):
|
|
102
|
+
return f'"""{param_value}"""'
|
|
103
|
+
|
|
104
|
+
return param.type.serialize_sample_value(param_value)
|
|
105
|
+
|
|
106
|
+
# prepare operation parameters
|
|
107
|
+
def _operation_params(self) -> Dict[str, Any]:
|
|
108
|
+
params = [
|
|
109
|
+
p
|
|
110
|
+
for p in (self.operation.parameters.positional + self.operation.parameters.keyword_only)
|
|
111
|
+
if not p.client_default_value
|
|
112
|
+
]
|
|
113
|
+
failure_info = "fail to find required param named {}"
|
|
114
|
+
operation_params = {}
|
|
115
|
+
for param in params:
|
|
116
|
+
if not param.optional:
|
|
117
|
+
param_value = self.sample_params.get(param.wire_name)
|
|
118
|
+
if not param_value:
|
|
119
|
+
raise Exception(failure_info.format(param.client_name)) # pylint: disable=broad-exception-raised
|
|
120
|
+
operation_params[param.client_name] = self.handle_param(param, param_value)
|
|
121
|
+
return operation_params
|
|
122
|
+
|
|
123
|
+
def _operation_group_name(self) -> str:
|
|
124
|
+
if self.operation_group.is_mixin:
|
|
125
|
+
return ""
|
|
126
|
+
return f".{self.operation_group.property_name}"
|
|
127
|
+
|
|
128
|
+
def _operation_result(self) -> Tuple[str, str]:
|
|
129
|
+
is_response_none = "None" in self.operation.response_type_annotation(async_mode=False)
|
|
130
|
+
lro = ".result()"
|
|
131
|
+
if is_response_none:
|
|
132
|
+
paging, normal_print, return_var = "", "", ""
|
|
133
|
+
else:
|
|
134
|
+
paging = "\n for item in response:\n print(item)"
|
|
135
|
+
normal_print = "\n print(response)"
|
|
136
|
+
return_var = "response = "
|
|
137
|
+
|
|
138
|
+
if self.operation.operation_type == "paging":
|
|
139
|
+
return paging, return_var
|
|
140
|
+
if self.operation.operation_type == "lro":
|
|
141
|
+
return lro + normal_print, return_var
|
|
142
|
+
if self.operation.operation_type == "lropaging":
|
|
143
|
+
return lro + paging, return_var
|
|
144
|
+
return normal_print, return_var
|
|
145
|
+
|
|
146
|
+
def _operation_name(self) -> str:
|
|
147
|
+
return f".{self.operation.name}"
|
|
148
|
+
|
|
149
|
+
def _origin_file(self) -> str:
|
|
150
|
+
name = self.sample.get("x-ms-original-file", "")
|
|
151
|
+
if "specification" in name:
|
|
152
|
+
return "specification" + name.split("specification")[-1]
|
|
153
|
+
return name if self.code_model.options["from_typespec"] else ""
|
|
154
|
+
|
|
155
|
+
def serialize(self) -> str:
|
|
156
|
+
operation_result, return_var = self._operation_result()
|
|
157
|
+
return self.env.get_template("sample.py.jinja2").render(
|
|
158
|
+
code_model=self.code_model,
|
|
159
|
+
file_name=self.file_name,
|
|
160
|
+
operation_result=operation_result,
|
|
161
|
+
operation_params=self._operation_params(),
|
|
162
|
+
operation_group_name=self._operation_group_name(),
|
|
163
|
+
operation_name=self._operation_name(),
|
|
164
|
+
imports=self._imports(),
|
|
165
|
+
client_params=self._client_params(),
|
|
166
|
+
origin_file=self._origin_file(),
|
|
167
|
+
return_var=return_var,
|
|
168
|
+
)
|