@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.
Files changed (156) hide show
  1. package/dist/emitter/emitter.d.ts.map +1 -1
  2. package/dist/emitter/emitter.js +110 -24
  3. package/dist/emitter/emitter.js.map +1 -1
  4. package/dist/emitter/http.js +1 -1
  5. package/dist/emitter/http.js.map +1 -1
  6. package/dist/emitter/lib.d.ts +1 -0
  7. package/dist/emitter/lib.d.ts.map +1 -1
  8. package/dist/emitter/lib.js +1 -0
  9. package/dist/emitter/lib.js.map +1 -1
  10. package/dist/emitter/run-python3.d.ts +2 -0
  11. package/dist/emitter/run-python3.d.ts.map +1 -0
  12. package/dist/emitter/run-python3.js +19 -0
  13. package/dist/emitter/run-python3.js.map +1 -0
  14. package/dist/emitter/system-requirements.d.ts +17 -0
  15. package/dist/emitter/system-requirements.d.ts.map +1 -0
  16. package/dist/emitter/system-requirements.js +167 -0
  17. package/dist/emitter/system-requirements.js.map +1 -0
  18. package/emitter/src/emitter.ts +111 -23
  19. package/emitter/src/http.ts +1 -1
  20. package/emitter/src/lib.ts +2 -0
  21. package/emitter/src/run-python3.ts +20 -0
  22. package/emitter/src/system-requirements.ts +261 -0
  23. package/emitter/temp/tsconfig.tsbuildinfo +1 -1
  24. package/eng/scripts/Test-Packages.ps1 +1 -1
  25. package/eng/scripts/ci/regenerate.ts +20 -8
  26. package/eng/scripts/setup/__pycache__/venvtools.cpython-38.pyc +0 -0
  27. package/eng/scripts/setup/build.ts +16 -0
  28. package/eng/scripts/setup/build_pygen_wheel.py +40 -0
  29. package/eng/scripts/setup/install.py +9 -8
  30. package/eng/scripts/setup/install.ts +12 -0
  31. package/eng/scripts/setup/prepare.py +3 -1
  32. package/eng/scripts/setup/prepare.ts +11 -0
  33. package/eng/scripts/setup/run-python3.ts +1 -6
  34. package/generator/build/lib/pygen/__init__.py +107 -0
  35. package/generator/build/lib/pygen/_version.py +7 -0
  36. package/generator/build/lib/pygen/black.py +71 -0
  37. package/generator/build/lib/pygen/codegen/__init__.py +357 -0
  38. package/generator/build/lib/pygen/codegen/_utils.py +17 -0
  39. package/generator/build/lib/pygen/codegen/models/__init__.py +204 -0
  40. package/generator/build/lib/pygen/codegen/models/base.py +186 -0
  41. package/generator/build/lib/pygen/codegen/models/base_builder.py +118 -0
  42. package/generator/build/lib/pygen/codegen/models/client.py +435 -0
  43. package/generator/build/lib/pygen/codegen/models/code_model.py +237 -0
  44. package/generator/build/lib/pygen/codegen/models/combined_type.py +149 -0
  45. package/generator/build/lib/pygen/codegen/models/constant_type.py +129 -0
  46. package/generator/build/lib/pygen/codegen/models/credential_types.py +214 -0
  47. package/generator/build/lib/pygen/codegen/models/dictionary_type.py +127 -0
  48. package/generator/build/lib/pygen/codegen/models/enum_type.py +238 -0
  49. package/generator/build/lib/pygen/codegen/models/imports.py +291 -0
  50. package/generator/build/lib/pygen/codegen/models/list_type.py +143 -0
  51. package/generator/build/lib/pygen/codegen/models/lro_operation.py +142 -0
  52. package/generator/build/lib/pygen/codegen/models/lro_paging_operation.py +32 -0
  53. package/generator/build/lib/pygen/codegen/models/model_type.py +357 -0
  54. package/generator/build/lib/pygen/codegen/models/operation.py +509 -0
  55. package/generator/build/lib/pygen/codegen/models/operation_group.py +184 -0
  56. package/generator/build/lib/pygen/codegen/models/paging_operation.py +155 -0
  57. package/generator/build/lib/pygen/codegen/models/parameter.py +412 -0
  58. package/generator/build/lib/pygen/codegen/models/parameter_list.py +387 -0
  59. package/generator/build/lib/pygen/codegen/models/primitive_types.py +659 -0
  60. package/generator/build/lib/pygen/codegen/models/property.py +170 -0
  61. package/generator/build/lib/pygen/codegen/models/request_builder.py +189 -0
  62. package/generator/build/lib/pygen/codegen/models/request_builder_parameter.py +115 -0
  63. package/generator/build/lib/pygen/codegen/models/response.py +348 -0
  64. package/generator/build/lib/pygen/codegen/models/utils.py +21 -0
  65. package/generator/build/lib/pygen/codegen/serializers/__init__.py +574 -0
  66. package/generator/build/lib/pygen/codegen/serializers/base_serializer.py +21 -0
  67. package/generator/build/lib/pygen/codegen/serializers/builder_serializer.py +1533 -0
  68. package/generator/build/lib/pygen/codegen/serializers/client_serializer.py +294 -0
  69. package/generator/build/lib/pygen/codegen/serializers/enum_serializer.py +15 -0
  70. package/generator/build/lib/pygen/codegen/serializers/general_serializer.py +213 -0
  71. package/generator/build/lib/pygen/codegen/serializers/import_serializer.py +126 -0
  72. package/generator/build/lib/pygen/codegen/serializers/metadata_serializer.py +198 -0
  73. package/generator/build/lib/pygen/codegen/serializers/model_init_serializer.py +33 -0
  74. package/generator/build/lib/pygen/codegen/serializers/model_serializer.py +335 -0
  75. package/generator/build/lib/pygen/codegen/serializers/operation_groups_serializer.py +89 -0
  76. package/generator/build/lib/pygen/codegen/serializers/operations_init_serializer.py +44 -0
  77. package/generator/build/lib/pygen/codegen/serializers/parameter_serializer.py +221 -0
  78. package/generator/build/lib/pygen/codegen/serializers/patch_serializer.py +19 -0
  79. package/generator/build/lib/pygen/codegen/serializers/request_builders_serializer.py +52 -0
  80. package/generator/build/lib/pygen/codegen/serializers/sample_serializer.py +168 -0
  81. package/generator/build/lib/pygen/codegen/serializers/test_serializer.py +292 -0
  82. package/generator/build/lib/pygen/codegen/serializers/types_serializer.py +31 -0
  83. package/generator/build/lib/pygen/codegen/serializers/utils.py +68 -0
  84. package/generator/build/lib/pygen/codegen/templates/client.py.jinja2 +37 -0
  85. package/generator/build/lib/pygen/codegen/templates/client_container.py.jinja2 +12 -0
  86. package/generator/build/lib/pygen/codegen/templates/config.py.jinja2 +73 -0
  87. package/generator/build/lib/pygen/codegen/templates/config_container.py.jinja2 +16 -0
  88. package/generator/build/lib/pygen/codegen/templates/conftest.py.jinja2 +28 -0
  89. package/generator/build/lib/pygen/codegen/templates/enum.py.jinja2 +13 -0
  90. package/generator/build/lib/pygen/codegen/templates/enum_container.py.jinja2 +10 -0
  91. package/generator/build/lib/pygen/codegen/templates/init.py.jinja2 +24 -0
  92. package/generator/build/lib/pygen/codegen/templates/keywords.jinja2 +27 -0
  93. package/generator/build/lib/pygen/codegen/templates/lro_operation.py.jinja2 +16 -0
  94. package/generator/build/lib/pygen/codegen/templates/lro_paging_operation.py.jinja2 +18 -0
  95. package/generator/build/lib/pygen/codegen/templates/macros.jinja2 +12 -0
  96. package/generator/build/lib/pygen/codegen/templates/metadata.json.jinja2 +167 -0
  97. package/generator/build/lib/pygen/codegen/templates/model_base.py.jinja2 +1174 -0
  98. package/generator/build/lib/pygen/codegen/templates/model_container.py.jinja2 +15 -0
  99. package/generator/build/lib/pygen/codegen/templates/model_dpg.py.jinja2 +97 -0
  100. package/generator/build/lib/pygen/codegen/templates/model_init.py.jinja2 +33 -0
  101. package/generator/build/lib/pygen/codegen/templates/model_msrest.py.jinja2 +92 -0
  102. package/generator/build/lib/pygen/codegen/templates/operation.py.jinja2 +21 -0
  103. package/generator/build/lib/pygen/codegen/templates/operation_group.py.jinja2 +75 -0
  104. package/generator/build/lib/pygen/codegen/templates/operation_groups_container.py.jinja2 +19 -0
  105. package/generator/build/lib/pygen/codegen/templates/operation_tools.jinja2 +81 -0
  106. package/generator/build/lib/pygen/codegen/templates/operations_folder_init.py.jinja2 +17 -0
  107. package/generator/build/lib/pygen/codegen/templates/packaging_templates/CHANGELOG.md.jinja2 +6 -0
  108. package/generator/build/lib/pygen/codegen/templates/packaging_templates/LICENSE.jinja2 +21 -0
  109. package/generator/build/lib/pygen/codegen/templates/packaging_templates/MANIFEST.in.jinja2 +8 -0
  110. package/generator/build/lib/pygen/codegen/templates/packaging_templates/README.md.jinja2 +107 -0
  111. package/generator/build/lib/pygen/codegen/templates/packaging_templates/dev_requirements.txt.jinja2 +9 -0
  112. package/generator/build/lib/pygen/codegen/templates/packaging_templates/setup.py.jinja2 +108 -0
  113. package/generator/build/lib/pygen/codegen/templates/paging_operation.py.jinja2 +21 -0
  114. package/generator/build/lib/pygen/codegen/templates/patch.py.jinja2 +19 -0
  115. package/generator/build/lib/pygen/codegen/templates/pkgutil_init.py.jinja2 +1 -0
  116. package/generator/build/lib/pygen/codegen/templates/request_builder.py.jinja2 +28 -0
  117. package/generator/build/lib/pygen/codegen/templates/request_builders.py.jinja2 +10 -0
  118. package/generator/build/lib/pygen/codegen/templates/rest_init.py.jinja2 +12 -0
  119. package/generator/build/lib/pygen/codegen/templates/sample.py.jinja2 +44 -0
  120. package/generator/build/lib/pygen/codegen/templates/serialization.py.jinja2 +2117 -0
  121. package/generator/build/lib/pygen/codegen/templates/test.py.jinja2 +50 -0
  122. package/generator/build/lib/pygen/codegen/templates/testpreparer.py.jinja2 +26 -0
  123. package/generator/build/lib/pygen/codegen/templates/types.py.jinja2 +7 -0
  124. package/generator/build/lib/pygen/codegen/templates/validation.py.jinja2 +38 -0
  125. package/generator/build/lib/pygen/codegen/templates/vendor.py.jinja2 +96 -0
  126. package/generator/build/lib/pygen/codegen/templates/version.py.jinja2 +4 -0
  127. package/generator/build/lib/pygen/m2r.py +65 -0
  128. package/generator/build/lib/pygen/preprocess/__init__.py +515 -0
  129. package/generator/build/lib/pygen/preprocess/helpers.py +27 -0
  130. package/generator/build/lib/pygen/preprocess/python_mappings.py +226 -0
  131. package/generator/build/lib/pygen/utils.py +163 -0
  132. package/generator/component-detection-pip-report.json +134 -0
  133. package/generator/dev_requirements.txt +0 -1
  134. package/generator/dist/pygen-0.1.0-py3-none-any.whl +0 -0
  135. package/generator/pygen/codegen/__init__.py +4 -4
  136. package/generator/pygen.egg-info/PKG-INFO +7 -4
  137. package/generator/pygen.egg-info/requires.txt +7 -4
  138. package/generator/setup.py +7 -4
  139. package/generator/test/azure/mock_api_tests/asynctests/test_azure_client_generator_core_flatten_async.py +1 -1
  140. 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
  141. package/generator/test/azure/mock_api_tests/conftest.py +5 -4
  142. package/generator/test/azure/mock_api_tests/test_azure_client_generator_core_flatten.py +1 -1
  143. package/generator/test/{generic_mock_api_tests/test_payload_pageable.py → azure/mock_api_tests/test_azure_payload_pageable.py} +1 -1
  144. package/generator/test/{generic_mock_api_tests → azure/mock_api_tests}/test_resiliency_srv_driven.py +4 -2
  145. package/generator/test/{generic_mock_api_tests/asynctests → azure/mock_api_tests}/test_resiliency_srv_driven_async.py +3 -2
  146. package/generator/test/azure/requirements.txt +9 -8
  147. package/generator/test/generic_mock_api_tests/conftest.py +9 -4
  148. package/generator/test/unbranded/mock_api_tests/conftest.py +4 -4
  149. package/generator/test/unbranded/mock_api_tests/test_unbranded.py +1 -1
  150. package/generator/test/unbranded/requirements.txt +1 -8
  151. package/package.json +10 -10
  152. package/generator/requirements.txt +0 -12
  153. /package/generator/test/{generic_mock_api_tests → azure/mock_api_tests}/asynctests/test_client_naming_async.py +0 -0
  154. /package/generator/test/{generic_mock_api_tests → azure/mock_api_tests}/asynctests/test_client_structure_async.py +0 -0
  155. /package/generator/test/{generic_mock_api_tests → azure/mock_api_tests}/test_client_naming.py +0 -0
  156. /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
+ )