@typespec/http-client-python 0.4.3 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (139) hide show
  1. package/dist/emitter/emitter.d.ts.map +1 -1
  2. package/dist/emitter/emitter.js +85 -24
  3. package/dist/emitter/emitter.js.map +1 -1
  4. package/dist/emitter/lib.d.ts +1 -0
  5. package/dist/emitter/lib.d.ts.map +1 -1
  6. package/dist/emitter/lib.js +1 -0
  7. package/dist/emitter/lib.js.map +1 -1
  8. package/dist/emitter/run-python3.d.ts +2 -0
  9. package/dist/emitter/run-python3.d.ts.map +1 -0
  10. package/dist/emitter/run-python3.js +19 -0
  11. package/dist/emitter/run-python3.js.map +1 -0
  12. package/dist/emitter/system-requirements.d.ts +17 -0
  13. package/dist/emitter/system-requirements.d.ts.map +1 -0
  14. package/dist/emitter/system-requirements.js +167 -0
  15. package/dist/emitter/system-requirements.js.map +1 -0
  16. package/emitter/src/emitter.ts +88 -23
  17. package/emitter/src/lib.ts +2 -0
  18. package/emitter/src/run-python3.ts +20 -0
  19. package/emitter/src/system-requirements.ts +261 -0
  20. package/emitter/temp/tsconfig.tsbuildinfo +1 -1
  21. package/eng/scripts/ci/regenerate.ts +16 -4
  22. package/eng/scripts/setup/__pycache__/venvtools.cpython-38.pyc +0 -0
  23. package/eng/scripts/setup/build.ts +16 -0
  24. package/eng/scripts/setup/build_pygen_wheel.py +40 -0
  25. package/eng/scripts/setup/install.py +9 -3
  26. package/eng/scripts/setup/install.ts +32 -0
  27. package/eng/scripts/setup/prepare.py +3 -1
  28. package/eng/scripts/setup/prepare.ts +11 -0
  29. package/eng/scripts/setup/run-python3.ts +1 -6
  30. package/generator/build/lib/pygen/__init__.py +107 -0
  31. package/generator/build/lib/pygen/_version.py +7 -0
  32. package/generator/build/lib/pygen/black.py +71 -0
  33. package/generator/build/lib/pygen/codegen/__init__.py +357 -0
  34. package/generator/build/lib/pygen/codegen/_utils.py +17 -0
  35. package/generator/build/lib/pygen/codegen/models/__init__.py +204 -0
  36. package/generator/build/lib/pygen/codegen/models/base.py +186 -0
  37. package/generator/build/lib/pygen/codegen/models/base_builder.py +118 -0
  38. package/generator/build/lib/pygen/codegen/models/client.py +435 -0
  39. package/generator/build/lib/pygen/codegen/models/code_model.py +237 -0
  40. package/generator/build/lib/pygen/codegen/models/combined_type.py +149 -0
  41. package/generator/build/lib/pygen/codegen/models/constant_type.py +129 -0
  42. package/generator/build/lib/pygen/codegen/models/credential_types.py +214 -0
  43. package/generator/build/lib/pygen/codegen/models/dictionary_type.py +127 -0
  44. package/generator/build/lib/pygen/codegen/models/enum_type.py +238 -0
  45. package/generator/build/lib/pygen/codegen/models/imports.py +291 -0
  46. package/generator/build/lib/pygen/codegen/models/list_type.py +143 -0
  47. package/generator/build/lib/pygen/codegen/models/lro_operation.py +142 -0
  48. package/generator/build/lib/pygen/codegen/models/lro_paging_operation.py +32 -0
  49. package/generator/build/lib/pygen/codegen/models/model_type.py +357 -0
  50. package/generator/build/lib/pygen/codegen/models/operation.py +509 -0
  51. package/generator/build/lib/pygen/codegen/models/operation_group.py +184 -0
  52. package/generator/build/lib/pygen/codegen/models/paging_operation.py +155 -0
  53. package/generator/build/lib/pygen/codegen/models/parameter.py +412 -0
  54. package/generator/build/lib/pygen/codegen/models/parameter_list.py +387 -0
  55. package/generator/build/lib/pygen/codegen/models/primitive_types.py +659 -0
  56. package/generator/build/lib/pygen/codegen/models/property.py +170 -0
  57. package/generator/build/lib/pygen/codegen/models/request_builder.py +189 -0
  58. package/generator/build/lib/pygen/codegen/models/request_builder_parameter.py +115 -0
  59. package/generator/build/lib/pygen/codegen/models/response.py +348 -0
  60. package/generator/build/lib/pygen/codegen/models/utils.py +21 -0
  61. package/generator/build/lib/pygen/codegen/serializers/__init__.py +574 -0
  62. package/generator/build/lib/pygen/codegen/serializers/base_serializer.py +21 -0
  63. package/generator/build/lib/pygen/codegen/serializers/builder_serializer.py +1533 -0
  64. package/generator/build/lib/pygen/codegen/serializers/client_serializer.py +294 -0
  65. package/generator/build/lib/pygen/codegen/serializers/enum_serializer.py +15 -0
  66. package/generator/build/lib/pygen/codegen/serializers/general_serializer.py +213 -0
  67. package/generator/build/lib/pygen/codegen/serializers/import_serializer.py +126 -0
  68. package/generator/build/lib/pygen/codegen/serializers/metadata_serializer.py +198 -0
  69. package/generator/build/lib/pygen/codegen/serializers/model_init_serializer.py +33 -0
  70. package/generator/build/lib/pygen/codegen/serializers/model_serializer.py +335 -0
  71. package/generator/build/lib/pygen/codegen/serializers/operation_groups_serializer.py +89 -0
  72. package/generator/build/lib/pygen/codegen/serializers/operations_init_serializer.py +44 -0
  73. package/generator/build/lib/pygen/codegen/serializers/parameter_serializer.py +221 -0
  74. package/generator/build/lib/pygen/codegen/serializers/patch_serializer.py +19 -0
  75. package/generator/build/lib/pygen/codegen/serializers/request_builders_serializer.py +52 -0
  76. package/generator/build/lib/pygen/codegen/serializers/sample_serializer.py +168 -0
  77. package/generator/build/lib/pygen/codegen/serializers/test_serializer.py +292 -0
  78. package/generator/build/lib/pygen/codegen/serializers/types_serializer.py +31 -0
  79. package/generator/build/lib/pygen/codegen/serializers/utils.py +68 -0
  80. package/generator/build/lib/pygen/codegen/templates/client.py.jinja2 +37 -0
  81. package/generator/build/lib/pygen/codegen/templates/client_container.py.jinja2 +12 -0
  82. package/generator/build/lib/pygen/codegen/templates/config.py.jinja2 +73 -0
  83. package/generator/build/lib/pygen/codegen/templates/config_container.py.jinja2 +16 -0
  84. package/generator/build/lib/pygen/codegen/templates/conftest.py.jinja2 +28 -0
  85. package/generator/build/lib/pygen/codegen/templates/enum.py.jinja2 +13 -0
  86. package/generator/build/lib/pygen/codegen/templates/enum_container.py.jinja2 +10 -0
  87. package/generator/build/lib/pygen/codegen/templates/init.py.jinja2 +24 -0
  88. package/generator/build/lib/pygen/codegen/templates/keywords.jinja2 +27 -0
  89. package/generator/build/lib/pygen/codegen/templates/lro_operation.py.jinja2 +16 -0
  90. package/generator/build/lib/pygen/codegen/templates/lro_paging_operation.py.jinja2 +18 -0
  91. package/generator/build/lib/pygen/codegen/templates/macros.jinja2 +12 -0
  92. package/generator/build/lib/pygen/codegen/templates/metadata.json.jinja2 +167 -0
  93. package/generator/build/lib/pygen/codegen/templates/model_base.py.jinja2 +1174 -0
  94. package/generator/build/lib/pygen/codegen/templates/model_container.py.jinja2 +15 -0
  95. package/generator/build/lib/pygen/codegen/templates/model_dpg.py.jinja2 +97 -0
  96. package/generator/build/lib/pygen/codegen/templates/model_init.py.jinja2 +33 -0
  97. package/generator/build/lib/pygen/codegen/templates/model_msrest.py.jinja2 +92 -0
  98. package/generator/build/lib/pygen/codegen/templates/operation.py.jinja2 +21 -0
  99. package/generator/build/lib/pygen/codegen/templates/operation_group.py.jinja2 +75 -0
  100. package/generator/build/lib/pygen/codegen/templates/operation_groups_container.py.jinja2 +19 -0
  101. package/generator/build/lib/pygen/codegen/templates/operation_tools.jinja2 +81 -0
  102. package/generator/build/lib/pygen/codegen/templates/operations_folder_init.py.jinja2 +17 -0
  103. package/generator/build/lib/pygen/codegen/templates/packaging_templates/CHANGELOG.md.jinja2 +6 -0
  104. package/generator/build/lib/pygen/codegen/templates/packaging_templates/LICENSE.jinja2 +21 -0
  105. package/generator/build/lib/pygen/codegen/templates/packaging_templates/MANIFEST.in.jinja2 +8 -0
  106. package/generator/build/lib/pygen/codegen/templates/packaging_templates/README.md.jinja2 +107 -0
  107. package/generator/build/lib/pygen/codegen/templates/packaging_templates/dev_requirements.txt.jinja2 +9 -0
  108. package/generator/build/lib/pygen/codegen/templates/packaging_templates/setup.py.jinja2 +108 -0
  109. package/generator/build/lib/pygen/codegen/templates/paging_operation.py.jinja2 +21 -0
  110. package/generator/build/lib/pygen/codegen/templates/patch.py.jinja2 +19 -0
  111. package/generator/build/lib/pygen/codegen/templates/pkgutil_init.py.jinja2 +1 -0
  112. package/generator/build/lib/pygen/codegen/templates/request_builder.py.jinja2 +28 -0
  113. package/generator/build/lib/pygen/codegen/templates/request_builders.py.jinja2 +10 -0
  114. package/generator/build/lib/pygen/codegen/templates/rest_init.py.jinja2 +12 -0
  115. package/generator/build/lib/pygen/codegen/templates/sample.py.jinja2 +44 -0
  116. package/generator/build/lib/pygen/codegen/templates/serialization.py.jinja2 +2117 -0
  117. package/generator/build/lib/pygen/codegen/templates/test.py.jinja2 +50 -0
  118. package/generator/build/lib/pygen/codegen/templates/testpreparer.py.jinja2 +26 -0
  119. package/generator/build/lib/pygen/codegen/templates/types.py.jinja2 +7 -0
  120. package/generator/build/lib/pygen/codegen/templates/validation.py.jinja2 +38 -0
  121. package/generator/build/lib/pygen/codegen/templates/vendor.py.jinja2 +96 -0
  122. package/generator/build/lib/pygen/codegen/templates/version.py.jinja2 +4 -0
  123. package/generator/build/lib/pygen/m2r.py +65 -0
  124. package/generator/build/lib/pygen/preprocess/__init__.py +515 -0
  125. package/generator/build/lib/pygen/preprocess/helpers.py +27 -0
  126. package/generator/build/lib/pygen/preprocess/python_mappings.py +226 -0
  127. package/generator/build/lib/pygen/utils.py +163 -0
  128. package/generator/component-detection-pip-report.json +134 -0
  129. package/generator/dev_requirements.txt +0 -1
  130. package/generator/dist/pygen-0.1.0-py3-none-any.whl +0 -0
  131. package/generator/pygen/m2r.py +1 -1
  132. package/generator/pygen.egg-info/PKG-INFO +7 -4
  133. package/generator/pygen.egg-info/requires.txt +7 -4
  134. package/generator/requirements.txt +5 -10
  135. package/generator/setup.py +7 -4
  136. package/generator/test/azure/requirements.txt +2 -0
  137. package/generator/test/generic_mock_api_tests/unittests/test_m2r.py +10 -0
  138. package/generator/test/unbranded/requirements.txt +2 -0
  139. package/package.json +6 -5
@@ -0,0 +1,292 @@
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 Dict, Any, List, Optional
7
+ from jinja2 import Environment
8
+
9
+ from .import_serializer import FileImportSerializer
10
+ from .base_serializer import BaseSerializer
11
+ from ..models import (
12
+ CodeModel,
13
+ ImportType,
14
+ OperationGroup,
15
+ Client,
16
+ OperationType,
17
+ ModelType,
18
+ BaseType,
19
+ CombinedType,
20
+ FileImport,
21
+ )
22
+ from .utils import get_namespace_from_package_name, json_dumps_template
23
+
24
+
25
+ def is_lro(operation_type: str) -> bool:
26
+ return operation_type in ("lro", "lropaging")
27
+
28
+
29
+ def is_paging(operation_type: str) -> bool:
30
+ return operation_type in ("paging", "lropaging")
31
+
32
+
33
+ def is_common_operation(operation_type: str) -> bool:
34
+ return operation_type == "operation"
35
+
36
+
37
+ class TestName:
38
+ def __init__(self, code_model: CodeModel, client_name: str, *, is_async: bool = False) -> None:
39
+ self.code_model = code_model
40
+ self.client_name = client_name
41
+ self.is_async = is_async
42
+
43
+ @property
44
+ def async_suffix_capt(self) -> str:
45
+ return "Async" if self.is_async else ""
46
+
47
+ @property
48
+ def create_client_name(self) -> str:
49
+ return "create_async_client" if self.is_async else "create_client"
50
+
51
+ @property
52
+ def prefix(self) -> str:
53
+ return self.client_name.replace("Client", "")
54
+
55
+ @property
56
+ def preparer_name(self) -> str:
57
+ if self.code_model.options["azure_arm"]:
58
+ return "RandomNameResourceGroupPreparer"
59
+ return self.prefix + "Preparer"
60
+
61
+ @property
62
+ def base_test_class_name(self) -> str:
63
+ if self.code_model.options["azure_arm"]:
64
+ return "AzureMgmtRecordedTestCase"
65
+ return f"{self.client_name}TestBase{self.async_suffix_capt}"
66
+
67
+
68
+ class TestCase:
69
+ def __init__(
70
+ self,
71
+ operation_groups: List[OperationGroup],
72
+ params: Dict[str, Any],
73
+ operation: OperationType,
74
+ *,
75
+ is_async: bool = False,
76
+ ) -> None:
77
+ self.operation_groups = operation_groups
78
+ self.params = params
79
+ self.operation = operation
80
+ self.is_async = is_async
81
+
82
+ @property
83
+ def name(self) -> str:
84
+ if self.operation_groups[-1].is_mixin:
85
+ return self.operation.name
86
+ return "_".join([og.property_name for og in self.operation_groups] + [self.operation.name])
87
+
88
+ @property
89
+ def operation_group_prefix(self) -> str:
90
+ if self.operation_groups[-1].is_mixin:
91
+ return ""
92
+ return "." + ".".join([og.property_name for og in self.operation_groups])
93
+
94
+ @property
95
+ def response(self) -> str:
96
+ if self.is_async:
97
+ if is_lro(self.operation.operation_type):
98
+ return "response = await (await "
99
+ if is_common_operation(self.operation.operation_type):
100
+ return "response = await "
101
+ return "response = "
102
+
103
+ @property
104
+ def lro_comment(self) -> str:
105
+ return " # call '.result()' to poll until service return final result"
106
+
107
+ @property
108
+ def operation_suffix(self) -> str:
109
+ if is_lro(self.operation.operation_type):
110
+ extra = ")" if self.is_async else ""
111
+ return f"{extra}.result(){self.lro_comment}"
112
+ return ""
113
+
114
+ @property
115
+ def extra_operation(self) -> str:
116
+ if is_paging(self.operation.operation_type):
117
+ async_str = "async " if self.is_async else ""
118
+ return f"result = [r {async_str}for r in response]"
119
+ return ""
120
+
121
+
122
+ class Test(TestName):
123
+ def __init__(
124
+ self,
125
+ code_model: CodeModel,
126
+ client_name: str,
127
+ operation_group: OperationGroup,
128
+ testcases: List[TestCase],
129
+ test_class_name: str,
130
+ *,
131
+ is_async: bool = False,
132
+ ) -> None:
133
+ super().__init__(code_model, client_name, is_async=is_async)
134
+ self.operation_group = operation_group
135
+ self.testcases = testcases
136
+ self.test_class_name = test_class_name
137
+
138
+
139
+ class TestGeneralSerializer(BaseSerializer):
140
+ def __init__(self, code_model: CodeModel, env: Environment, *, is_async: bool = False) -> None:
141
+ super().__init__(code_model, env)
142
+ self.is_async = is_async
143
+
144
+ @property
145
+ def aio_str(self) -> str:
146
+ return ".aio" if self.is_async else ""
147
+
148
+ @property
149
+ def test_names(self) -> List[TestName]:
150
+ return [TestName(self.code_model, c.name, is_async=self.is_async) for c in self.code_model.clients]
151
+
152
+ def add_import_client(self, imports: FileImport) -> None:
153
+ namespace = get_namespace_from_package_name(self.code_model.options["package_name"])
154
+ for client in self.code_model.clients:
155
+ imports.add_submodule_import(namespace + self.aio_str, client.name, ImportType.STDLIB)
156
+
157
+ @property
158
+ def import_clients(self) -> FileImportSerializer:
159
+ imports = self.init_file_import()
160
+
161
+ imports.add_submodule_import("devtools_testutils", "AzureRecordedTestCase", ImportType.STDLIB)
162
+ if not self.is_async:
163
+ imports.add_import("functools", ImportType.STDLIB)
164
+ imports.add_submodule_import("devtools_testutils", "PowerShellPreparer", ImportType.STDLIB)
165
+ self.add_import_client(imports)
166
+
167
+ return FileImportSerializer(imports, self.is_async)
168
+
169
+ def serialize_conftest(self) -> str:
170
+ return self.env.get_template("conftest.py.jinja2").render(
171
+ test_names=self.test_names,
172
+ code_model=self.code_model,
173
+ )
174
+
175
+ def serialize_testpreparer(self) -> str:
176
+ return self.env.get_template("testpreparer.py.jinja2").render(
177
+ test_names=self.test_names,
178
+ imports=self.import_clients,
179
+ code_model=self.code_model,
180
+ )
181
+
182
+
183
+ class TestSerializer(TestGeneralSerializer):
184
+ def __init__(
185
+ self,
186
+ code_model: CodeModel,
187
+ env: Environment,
188
+ *,
189
+ client: Client,
190
+ operation_group: OperationGroup,
191
+ is_async: bool = False,
192
+ ) -> None:
193
+ super().__init__(code_model, env, is_async=is_async)
194
+ self.client = client
195
+ self.operation_group = operation_group
196
+
197
+ @property
198
+ def import_test(self) -> FileImportSerializer:
199
+ imports = self.init_file_import()
200
+ test_name = TestName(self.code_model, self.client.name, is_async=self.is_async)
201
+ async_suffix = "_async" if self.is_async else ""
202
+ imports.add_submodule_import(
203
+ "devtools_testutils" if self.code_model.options["azure_arm"] else "testpreparer" + async_suffix,
204
+ test_name.base_test_class_name,
205
+ ImportType.LOCAL,
206
+ )
207
+ imports.add_submodule_import(
208
+ "devtools_testutils" if self.code_model.options["azure_arm"] else "testpreparer",
209
+ test_name.preparer_name,
210
+ ImportType.LOCAL,
211
+ )
212
+ imports.add_submodule_import(
213
+ "devtools_testutils" + self.aio_str,
214
+ "recorded_by_proxy" + async_suffix,
215
+ ImportType.LOCAL,
216
+ )
217
+ if self.code_model.options["azure_arm"]:
218
+ self.add_import_client(imports)
219
+ return FileImportSerializer(imports, self.is_async)
220
+
221
+ @property
222
+ def breadth_search_operation_group(self) -> List[List[OperationGroup]]:
223
+ result = []
224
+ queue = [[self.operation_group]]
225
+ while queue:
226
+ current = queue.pop(0)
227
+ if current[-1].operations:
228
+ result.append(current)
229
+ if current[-1].operation_groups:
230
+ queue.extend([current + [og] for og in current[-1].operation_groups])
231
+ return result
232
+
233
+ def get_sub_type(self, param_type: ModelType) -> ModelType:
234
+ if param_type.discriminated_subtypes:
235
+ for item in param_type.discriminated_subtypes.values():
236
+ return self.get_sub_type(item)
237
+ return param_type
238
+
239
+ def get_model_type(self, param_type: BaseType) -> Optional[ModelType]:
240
+ if isinstance(param_type, ModelType):
241
+ return param_type
242
+ if isinstance(param_type, CombinedType):
243
+ return param_type.target_model_subtype((ModelType,))
244
+ return None
245
+
246
+ def get_operation_params(self, operation: OperationType) -> Dict[str, Any]:
247
+ operation_params = {}
248
+ required_params = [p for p in operation.parameters.method if not p.optional]
249
+ for param in required_params:
250
+ model_type = self.get_model_type(param.type)
251
+ param_type = self.get_sub_type(model_type) if model_type else param.type
252
+ operation_params[param.client_name] = json_dumps_template(param_type.get_json_template_representation())
253
+ return operation_params
254
+
255
+ def get_test(self) -> Test:
256
+ testcases = []
257
+ for operation_groups in self.breadth_search_operation_group:
258
+ for operation in operation_groups[-1].operations:
259
+ if operation.internal or operation.is_lro_initial_operation:
260
+ continue
261
+ operation_params = self.get_operation_params(operation)
262
+ testcase = TestCase(
263
+ operation_groups=operation_groups,
264
+ params=operation_params,
265
+ operation=operation,
266
+ is_async=self.is_async,
267
+ )
268
+ testcases.append(testcase)
269
+ if not testcases:
270
+ raise Exception("no public operation to test") # pylint: disable=broad-exception-raised
271
+
272
+ return Test(
273
+ code_model=self.code_model,
274
+ client_name=self.client.name,
275
+ operation_group=self.operation_group,
276
+ testcases=testcases,
277
+ test_class_name=self.test_class_name,
278
+ is_async=self.is_async,
279
+ )
280
+
281
+ @property
282
+ def test_class_name(self) -> str:
283
+ test_name = TestName(self.code_model, self.client.name, is_async=self.is_async)
284
+ class_name = "" if self.operation_group.is_mixin else self.operation_group.class_name
285
+ return f"Test{test_name.prefix}{class_name}{test_name.async_suffix_capt}"
286
+
287
+ def serialize_test(self) -> str:
288
+ return self.env.get_template("test.py.jinja2").render(
289
+ imports=self.import_test,
290
+ code_model=self.code_model,
291
+ test=self.get_test(),
292
+ )
@@ -0,0 +1,31 @@
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 ..models.imports import FileImport, ImportType
7
+ from .import_serializer import FileImportSerializer
8
+ from .base_serializer import BaseSerializer
9
+
10
+
11
+ class TypesSerializer(BaseSerializer):
12
+ def imports(self) -> FileImport:
13
+ file_import = FileImport(self.code_model)
14
+ if self.code_model.named_unions:
15
+ file_import.add_submodule_import(
16
+ "typing",
17
+ "Union",
18
+ ImportType.STDLIB,
19
+ )
20
+ for nu in self.code_model.named_unions:
21
+ file_import.merge(nu.imports(relative_path=".", model_typing=True, is_types_file=True))
22
+ return file_import
23
+
24
+ def serialize(self) -> str:
25
+ # Generate the models
26
+ template = self.env.get_template("types.py.jinja2")
27
+ return template.render(
28
+ code_model=self.code_model,
29
+ imports=FileImportSerializer(self.imports()),
30
+ serializer=self,
31
+ )
@@ -0,0 +1,68 @@
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 json
7
+ from typing import Optional, List, Any
8
+ from pathlib import Path
9
+
10
+ from ..models import Client, OperationGroup
11
+
12
+
13
+ def method_signature_and_response_type_annotation_template(
14
+ *,
15
+ method_signature: str,
16
+ response_type_annotation: str,
17
+ ) -> str:
18
+ return f"{method_signature} -> {response_type_annotation}:"
19
+
20
+
21
+ def extract_sample_name(file_path: str) -> str:
22
+ file = file_path.split("specification")[-1]
23
+ return Path(file).parts[-1].replace(".json", "")
24
+
25
+
26
+ def strip_end(namespace: str) -> str:
27
+ return ".".join(namespace.split(".")[:-1])
28
+
29
+
30
+ def get_namespace_config(namespace: str, multiapi: bool) -> str:
31
+ return strip_end(namespace) if multiapi else namespace
32
+
33
+
34
+ def get_namespace_from_package_name(package_name: Optional[str]) -> str:
35
+ return (package_name or "").replace("-", ".")
36
+
37
+
38
+ def get_all_operation_groups_recursively(clients: List[Client]) -> List[OperationGroup]:
39
+ operation_groups = []
40
+ queue = []
41
+ for client in clients:
42
+ queue.extend(client.operation_groups)
43
+ while queue:
44
+ operation_groups.append(queue.pop(0))
45
+ if operation_groups[-1].operation_groups:
46
+ queue.extend(operation_groups[-1].operation_groups)
47
+ return operation_groups
48
+
49
+
50
+ def _improve_json_string(template_representation: str) -> Any:
51
+ origin = template_representation.split("\n")
52
+ final = []
53
+ for line in origin:
54
+ idx0 = line.find("#")
55
+ idx1 = line.rfind('"')
56
+ modified_line = ""
57
+ if idx0 > -1 and idx1 > -1:
58
+ modified_line = line[:idx0] + line[idx1:] + " " + line[idx0:idx1] + "\n"
59
+ else:
60
+ modified_line = line + "\n"
61
+ modified_line = modified_line.replace('"', "").replace("\\", '"')
62
+ final.append(modified_line)
63
+ return "".join(final)
64
+
65
+
66
+ def json_dumps_template(template_representation: Any) -> Any:
67
+ # only for template use, since it wraps everything in strings
68
+ return _improve_json_string(json.dumps(template_representation, indent=4))
@@ -0,0 +1,37 @@
1
+ {{ serializer.class_definition() }}
2
+ """{{ op_tools.wrap_string(client.description, "\n") | indent }}
3
+
4
+ {{ op_tools.serialize_with_wrap(serializer.property_descriptions(async_mode), "\n ") | indent }}
5
+ {{ serializer.init_signature_and_response_type_annotation(async_mode) | indent }}
6
+ {% if serializer.should_init_super %}
7
+ super().__init__()
8
+ {% endif %}
9
+ {% if client.has_parameterized_host %}
10
+ {{ serializer.host_variable_name }} = {{ keywords.escape_str(client.url) }}{{ client.url_pylint_disable }}
11
+ {% endif %}
12
+ {{ serializer.initialize_config() }}
13
+ {{ op_tools.serialize(serializer.initialize_pipeline_client(async_mode)) | indent(8) }}
14
+
15
+ {{ op_tools.serialize(serializer.serializers_and_operation_groups_properties()) | indent(8) }}
16
+
17
+ {% set http_response = keywords.async_class + "HttpResponse" %}
18
+ {{ serializer.send_request_signature_and_response_type_annotation(async_mode) | indent }}
19
+ {{ op_tools.serialize(serializer.send_request_description(async_mode)) | indent(8) }}
20
+ request_copy = deepcopy(request)
21
+ {% if client.parameters.path %}
22
+ {{ op_tools.serialize(serializer.serialize_path()) | indent(8) }}
23
+ request_copy.url = self._client.format_url(request_copy.url, **path_format_arguments)
24
+ {% else %}
25
+ request_copy.url = self._client.format_url(request_copy.url)
26
+ {% endif %}
27
+ return self._client.send_request(request_copy, stream=stream, **kwargs) # type: ignore
28
+
29
+ {{ keywords.def }} close(self) -> None:
30
+ {{ keywords.await }}self._client.close()
31
+
32
+ {{ keywords.def }} __{{ keywords.async_prefix }}enter__(self) -> Self:
33
+ {{ keywords.await }}self._client.__{{ keywords.async_prefix }}enter__()
34
+ return self
35
+
36
+ {{ keywords.def }} __{{ keywords.async_prefix }}exit__(self, *exc_details: Any) -> None:
37
+ {{ keywords.await }}self._client.__{{ keywords.async_prefix }}exit__(*exc_details)
@@ -0,0 +1,12 @@
1
+ {% import 'keywords.jinja2' as keywords with context %}
2
+ {% import 'operation_tools.jinja2' as op_tools %}
3
+ {# actual template starts here #}
4
+ # coding=utf-8
5
+ {{ code_model.options['license_header'] }}
6
+
7
+ {{ imports }}
8
+
9
+ {% for client in clients %}
10
+ {% set serializer = get_serializer(client) %}
11
+ {% include "client.py.jinja2" %}
12
+ {% endfor %}
@@ -0,0 +1,73 @@
1
+ class {{ client.name }}Configuration: {{ client.config.pylint_disable() }}
2
+ """Configuration for {{ client.name }}.
3
+
4
+ Note that all parameters used to create this instance are saved as instance
5
+ attributes.
6
+ {% if client.config.parameters.method | first %}
7
+
8
+ {% endif %}
9
+ {{ op_tools.serialize_with_wrap(serializer.property_descriptions(async_mode), "\n ") | indent }}
10
+ {{ serializer.init_signature_and_response_type_annotation(async_mode) | indent }}
11
+ {% if client.config.parameters.kwargs_to_pop %}
12
+ {{ op_tools.serialize(serializer.pop_kwargs_from_signature()) | indent(8) }}
13
+ {% endif %}
14
+ {% if serializer.check_required_parameters() %}
15
+ {{ op_tools.serialize(serializer.check_required_parameters()) | indent(8) -}}
16
+ {% endif %}
17
+
18
+ {% for parameter in client.config.parameters.method %}
19
+ self.{{ parameter.client_name }} = {{ parameter.client_name }}
20
+ {% endfor %}
21
+ {% if serializer.set_constants() %}
22
+ {{ op_tools.serialize(serializer.set_constants()) | indent(8) -}}
23
+ {% endif %}
24
+ {% if client.credential %}
25
+ {% set cred_scopes = client.credential.type if client.credential.type.policy is defined and client.credential.type.policy.credential_scopes is defined %}
26
+ {% if not cred_scopes %}
27
+ {% set cred_scopes = client.credential.type.types | selectattr("policy.credential_scopes") | first if client.credential.type.types is defined %}
28
+ {% endif %}
29
+ {% if cred_scopes %}
30
+ self.credential_scopes = kwargs.pop('credential_scopes', {{ cred_scopes.policy.credential_scopes }})
31
+ {% endif %}
32
+ {% endif %}
33
+ kwargs.setdefault('sdk_moniker', '{{ client.config.sdk_moniker }}/{}'.format(VERSION))
34
+ self.polling_interval = kwargs.get("polling_interval", 30)
35
+ self._configure(**kwargs)
36
+
37
+ {% if client.credential and client.credential.type.types is defined %}
38
+ def _infer_policy(self, **kwargs):
39
+ {% for cred_type in client.credential.type.types %}
40
+ if {{ cred_type.instance_check_template.format("self.credential") }}:
41
+ return {{ cred_type.policy.call(async_mode) }}
42
+ {% endfor %}
43
+ raise TypeError(f"Unsupported credential: {self.credential}")
44
+ {% endif %}
45
+
46
+ def _configure(
47
+ self,
48
+ **kwargs: Any
49
+ ) -> None:
50
+ self.user_agent_policy = kwargs.get('user_agent_policy') or policies.UserAgentPolicy(**kwargs)
51
+ self.headers_policy = kwargs.get('headers_policy') or policies.HeadersPolicy(**kwargs)
52
+ self.proxy_policy = kwargs.get('proxy_policy') or policies.ProxyPolicy(**kwargs)
53
+ self.logging_policy = kwargs.get('logging_policy') or policies.NetworkTraceLoggingPolicy(**kwargs)
54
+ {% if code_model.is_azure_flavor %}
55
+ self.http_logging_policy = kwargs.get('http_logging_policy') or {{ "ARM" if client.code_model.options['azure_arm'] else "policies." }}HttpLoggingPolicy(**kwargs)
56
+ self.custom_hook_policy = kwargs.get('custom_hook_policy') or policies.CustomHookPolicy(**kwargs)
57
+ self.redirect_policy = kwargs.get('redirect_policy') or policies.{{ keywords.async_class }}RedirectPolicy(**kwargs)
58
+ {% endif %}
59
+ self.retry_policy = kwargs.get('retry_policy') or policies.{{ keywords.async_class }}RetryPolicy(**kwargs)
60
+ self.authentication_policy = kwargs.get('authentication_policy')
61
+ {% if client.credential and client.credential.type.policy is defined %}
62
+ {# only adding this if credential_scopes is not passed during code generation #}
63
+ {% if client.credential.type.policy.credential_scopes is defined and client.credential.type.policy.credential_scopes | length == 0 %}
64
+ if not self.credential_scopes and not self.authentication_policy:
65
+ raise ValueError("You must provide either credential_scopes or authentication_policy as kwargs")
66
+ {% endif %}
67
+ if self.credential and not self.authentication_policy:
68
+ self.authentication_policy = {{ client.credential.type.policy.call(async_mode) }}
69
+ {% endif %}
70
+ {% if client.credential and client.credential.type.types is defined %}
71
+ if self.credential and not self.authentication_policy:
72
+ self.authentication_policy = self._infer_policy(**kwargs)
73
+ {% endif %}
@@ -0,0 +1,16 @@
1
+ {% import 'keywords.jinja2' as keywords with context %}
2
+ {% import 'operation_tools.jinja2' as op_tools %}
3
+ {# actual template starts here #}
4
+ # coding=utf-8
5
+ {{ code_model.options['license_header'] }}
6
+
7
+ {{ imports }}
8
+
9
+ {% if not code_model.options['package_version'] %}
10
+ VERSION = "unknown"
11
+ {% endif %}
12
+
13
+ {% for client in clients %}
14
+ {% set serializer = get_serializer(client) %}
15
+ {% include "config.py.jinja2" %}
16
+ {% endfor %}
@@ -0,0 +1,28 @@
1
+ # coding=utf-8
2
+ {{ code_model.options['license_header'] }}
3
+ import os
4
+ import pytest
5
+ from dotenv import load_dotenv
6
+ from devtools_testutils import test_proxy, add_general_regex_sanitizer, add_body_key_sanitizer, add_header_regex_sanitizer
7
+
8
+ load_dotenv()
9
+
10
+ # For security, please avoid record sensitive identity information in recordings
11
+ @pytest.fixture(scope="session", autouse=True)
12
+ def add_sanitizers(test_proxy):
13
+ {% for test_name in test_names %}
14
+ {% set prefix_upper = "AZURE" if code_model.options["azure_arm"] else test_name.prefix|upper %}
15
+ {% set prefix_lower = test_name.prefix|lower %}
16
+ {{ prefix_lower }}_subscription_id = os.environ.get("{{ prefix_upper }}_SUBSCRIPTION_ID", "00000000-0000-0000-0000-000000000000")
17
+ {{ prefix_lower }}_tenant_id = os.environ.get("{{ prefix_upper }}_TENANT_ID", "00000000-0000-0000-0000-000000000000")
18
+ {{ prefix_lower }}_client_id = os.environ.get("{{ prefix_upper }}_CLIENT_ID", "00000000-0000-0000-0000-000000000000")
19
+ {{ prefix_lower }}_client_secret = os.environ.get("{{ prefix_upper }}_CLIENT_SECRET", "00000000-0000-0000-0000-000000000000")
20
+ add_general_regex_sanitizer(regex={{ prefix_lower }}_subscription_id, value="00000000-0000-0000-0000-000000000000")
21
+ add_general_regex_sanitizer(regex={{ prefix_lower }}_tenant_id, value="00000000-0000-0000-0000-000000000000")
22
+ add_general_regex_sanitizer(regex={{ prefix_lower }}_client_id, value="00000000-0000-0000-0000-000000000000")
23
+ add_general_regex_sanitizer(regex={{ prefix_lower }}_client_secret, value="00000000-0000-0000-0000-000000000000")
24
+
25
+ {% endfor %}
26
+ add_header_regex_sanitizer(key="Set-Cookie", value="[set-cookie;]")
27
+ add_header_regex_sanitizer(key="Cookie", value="cookie;")
28
+ add_body_key_sanitizer(json_path="$..access_token", value="access_token")
@@ -0,0 +1,13 @@
1
+
2
+ class {{ enum.name }}({{ enum.value_type.type_annotation(is_operation_file=False) }}, Enum, metaclass=CaseInsensitiveEnumMeta):
3
+ {% if enum.yaml_data.get("description") %}
4
+ """{{ op_tools.wrap_string(enum.yaml_data["description"], "\n ") }}
5
+ """
6
+ {% endif %}
7
+
8
+ {% for value in enum.values %}
9
+ {{ value.name }} = {{ enum.value_type.get_declaration(value.value) }}
10
+ {% if value.description(is_operation_file=False) %}
11
+ """{{ op_tools.wrap_string(value.description(is_operation_file=False), "\n ") }}"""
12
+ {% endif %}
13
+ {% endfor %}
@@ -0,0 +1,10 @@
1
+ {% import 'operation_tools.jinja2' as op_tools %}
2
+ # coding=utf-8
3
+ {{ code_model.options['license_header'] }}
4
+
5
+ from enum import Enum
6
+ from {{ code_model.core_library }}{{ "" if code_model.is_azure_flavor else ".utils" }} import CaseInsensitiveEnumMeta
7
+
8
+ {% for enum in code_model.enums | sort %}
9
+ {% include "enum.py.jinja2" %}
10
+ {% endfor %}
@@ -0,0 +1,24 @@
1
+ {% import 'keywords.jinja2' as keywords %}
2
+ # coding=utf-8
3
+ {{ code_model.options['license_header'] }}
4
+ {{ keywords.path_type_checking_imports() }}
5
+ {% if clients %}
6
+ {% for client in clients %}
7
+ from .{{ client.filename }} import {{ client.name }} # type: ignore
8
+ {% endfor %}
9
+ {% endif %}
10
+ {% if not async_mode and code_model.options['package_version']%}
11
+ from ._version import VERSION
12
+
13
+ __version__ = VERSION
14
+ {% endif %}
15
+
16
+ {{ keywords.patch_imports(try_except=True) }}
17
+ __all__ = [
18
+ {% for client in clients %}
19
+ {{ keywords.escape_str(client.name) }},
20
+ {% endfor %}
21
+ ]
22
+ {{ keywords.extend_all }}
23
+
24
+ _patch_sdk()
@@ -0,0 +1,27 @@
1
+ {% set def = "async def" if async_mode else "def" %}
2
+ {% set async_prefix = "a" if async_mode else "" %}
3
+ {% set await = "await " if async_mode else "" %}
4
+ {% set async_class = "Async" if async_mode else "" %}
5
+ {% macro escape_str(s) %}'{{ s|replace("'", "\\'") }}'{% endmacro %}
6
+ {% set kwargs_declaration = "**kwargs: Any" %}
7
+ {% set extend_all = "__all__.extend([p for p in _patch_all if p not in __all__]) # pyright: ignore" %}
8
+ {% macro patch_imports(try_except=False) %}
9
+ {% set indentation = " " if try_except else "" %}
10
+ {% if try_except %}
11
+ try:
12
+ {% endif %}
13
+ {{ indentation }}from ._patch import __all__ as _patch_all
14
+ {{ indentation }}from ._patch import *
15
+ {% if try_except %}
16
+ except ImportError:
17
+ _patch_all = []
18
+ {% endif %}
19
+ from ._patch import patch_sdk as _patch_sdk{% endmacro %}
20
+ {% macro path_type_checking_imports() %}
21
+ # pylint: disable=wrong-import-position
22
+
23
+ from typing import TYPE_CHECKING
24
+
25
+ if TYPE_CHECKING:
26
+ from ._patch import * # pylint: disable=unused-wildcard-import
27
+ {% endmacro %}
@@ -0,0 +1,16 @@
1
+ {% import 'operation_tools.jinja2' as op_tools with context %}
2
+ {# actual template starts here #}
3
+ {% if operation.overloads and operation.include_documentation %}
4
+ {{ op_tools.generate_overloads(operation_serializer, operation) }}
5
+ {% endif %}
6
+ {{ operation_serializer.method_signature_and_response_type_annotation(operation) }}
7
+ {{ op_tools.description(operation, operation_serializer) | indent -}}
8
+ {% if not operation.abstract %}
9
+ {% if operation_serializer.pop_kwargs_from_signature(operation) %}
10
+ {{ op_tools.serialize(operation_serializer.pop_kwargs_from_signature(operation)) | indent }}
11
+ {%- endif %}
12
+ {{ op_tools.serialize(operation_serializer.initial_call(operation)) | indent }}
13
+ {{ op_tools.serialize(operation_serializer.get_long_running_output(operation)) | indent }}
14
+
15
+ {{ op_tools.serialize(operation_serializer.return_lro_poller(operation)) | indent }}
16
+ {% endif %}