@azure-tools/typespec-python 0.24.3 → 0.25.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 (132) hide show
  1. package/dist/src/code-model.d.ts.map +1 -1
  2. package/dist/src/code-model.js +1 -4
  3. package/dist/src/code-model.js.map +1 -1
  4. package/dist/src/emitter.d.ts.map +1 -1
  5. package/dist/src/emitter.js +5 -4
  6. package/dist/src/emitter.js.map +1 -1
  7. package/dist/src/external-process.d.ts +0 -9
  8. package/dist/src/external-process.d.ts.map +1 -1
  9. package/dist/src/external-process.js +1 -25
  10. package/dist/src/external-process.js.map +1 -1
  11. package/dist/src/types.d.ts.map +1 -1
  12. package/dist/src/types.js +2 -0
  13. package/dist/src/types.js.map +1 -1
  14. package/generator/LICENSE +21 -0
  15. package/generator/README.md +1 -0
  16. package/generator/dev_requirements.txt +5 -0
  17. package/generator/pygen/__init__.py +107 -0
  18. package/generator/pygen/_version.py +7 -0
  19. package/generator/pygen/black.py +71 -0
  20. package/generator/pygen/codegen/__init__.py +334 -0
  21. package/generator/pygen/codegen/_utils.py +16 -0
  22. package/generator/pygen/codegen/models/__init__.py +202 -0
  23. package/generator/pygen/codegen/models/base.py +186 -0
  24. package/generator/pygen/codegen/models/base_builder.py +119 -0
  25. package/generator/pygen/codegen/models/client.py +429 -0
  26. package/generator/pygen/codegen/models/code_model.py +239 -0
  27. package/generator/pygen/codegen/models/combined_type.py +149 -0
  28. package/generator/pygen/codegen/models/constant_type.py +129 -0
  29. package/generator/pygen/codegen/models/credential_types.py +221 -0
  30. package/generator/pygen/codegen/models/dictionary_type.py +127 -0
  31. package/generator/pygen/codegen/models/enum_type.py +238 -0
  32. package/generator/pygen/codegen/models/imports.py +291 -0
  33. package/generator/pygen/codegen/models/list_type.py +143 -0
  34. package/generator/pygen/codegen/models/lro_operation.py +143 -0
  35. package/generator/pygen/codegen/models/lro_paging_operation.py +32 -0
  36. package/generator/pygen/codegen/models/model_type.py +361 -0
  37. package/generator/pygen/codegen/models/operation.py +518 -0
  38. package/generator/pygen/codegen/models/operation_group.py +184 -0
  39. package/generator/pygen/codegen/models/paging_operation.py +156 -0
  40. package/generator/pygen/codegen/models/parameter.py +402 -0
  41. package/generator/pygen/codegen/models/parameter_list.py +390 -0
  42. package/generator/pygen/codegen/models/primitive_types.py +626 -0
  43. package/generator/pygen/codegen/models/property.py +175 -0
  44. package/generator/pygen/codegen/models/request_builder.py +189 -0
  45. package/generator/pygen/codegen/models/request_builder_parameter.py +115 -0
  46. package/generator/pygen/codegen/models/response.py +348 -0
  47. package/generator/pygen/codegen/models/utils.py +23 -0
  48. package/generator/pygen/codegen/serializers/__init__.py +570 -0
  49. package/generator/pygen/codegen/serializers/base_serializer.py +21 -0
  50. package/generator/pygen/codegen/serializers/builder_serializer.py +1454 -0
  51. package/generator/pygen/codegen/serializers/client_serializer.py +295 -0
  52. package/generator/pygen/codegen/serializers/enum_serializer.py +15 -0
  53. package/generator/pygen/codegen/serializers/general_serializer.py +212 -0
  54. package/generator/pygen/codegen/serializers/import_serializer.py +127 -0
  55. package/generator/pygen/codegen/serializers/metadata_serializer.py +198 -0
  56. package/generator/pygen/codegen/serializers/model_init_serializer.py +33 -0
  57. package/generator/pygen/codegen/serializers/model_serializer.py +287 -0
  58. package/generator/pygen/codegen/serializers/operation_groups_serializer.py +89 -0
  59. package/generator/pygen/codegen/serializers/operations_init_serializer.py +44 -0
  60. package/generator/pygen/codegen/serializers/parameter_serializer.py +221 -0
  61. package/generator/pygen/codegen/serializers/patch_serializer.py +19 -0
  62. package/generator/pygen/codegen/serializers/request_builders_serializer.py +52 -0
  63. package/generator/pygen/codegen/serializers/sample_serializer.py +163 -0
  64. package/generator/pygen/codegen/serializers/test_serializer.py +287 -0
  65. package/generator/pygen/codegen/serializers/types_serializer.py +31 -0
  66. package/generator/pygen/codegen/serializers/utils.py +68 -0
  67. package/generator/pygen/codegen/templates/client.py.jinja2 +37 -0
  68. package/generator/pygen/codegen/templates/client_container.py.jinja2 +12 -0
  69. package/generator/pygen/codegen/templates/config.py.jinja2 +73 -0
  70. package/generator/pygen/codegen/templates/config_container.py.jinja2 +16 -0
  71. package/generator/pygen/codegen/templates/conftest.py.jinja2 +28 -0
  72. package/generator/pygen/codegen/templates/enum.py.jinja2 +13 -0
  73. package/generator/pygen/codegen/templates/enum_container.py.jinja2 +10 -0
  74. package/generator/pygen/codegen/templates/init.py.jinja2 +24 -0
  75. package/generator/pygen/codegen/templates/keywords.jinja2 +19 -0
  76. package/generator/pygen/codegen/templates/lro_operation.py.jinja2 +16 -0
  77. package/generator/pygen/codegen/templates/lro_paging_operation.py.jinja2 +18 -0
  78. package/generator/pygen/codegen/templates/macros.jinja2 +12 -0
  79. package/generator/pygen/codegen/templates/metadata.json.jinja2 +167 -0
  80. package/generator/pygen/codegen/templates/model_base.py.jinja2 +899 -0
  81. package/generator/pygen/codegen/templates/model_container.py.jinja2 +13 -0
  82. package/generator/pygen/codegen/templates/model_dpg.py.jinja2 +92 -0
  83. package/generator/pygen/codegen/templates/model_init.py.jinja2 +28 -0
  84. package/generator/pygen/codegen/templates/model_msrest.py.jinja2 +92 -0
  85. package/generator/pygen/codegen/templates/operation.py.jinja2 +21 -0
  86. package/generator/pygen/codegen/templates/operation_group.py.jinja2 +75 -0
  87. package/generator/pygen/codegen/templates/operation_groups_container.py.jinja2 +20 -0
  88. package/generator/pygen/codegen/templates/operation_tools.jinja2 +74 -0
  89. package/generator/pygen/codegen/templates/operations_folder_init.py.jinja2 +17 -0
  90. package/generator/pygen/codegen/templates/packaging_templates/CHANGELOG.md.jinja2 +6 -0
  91. package/generator/pygen/codegen/templates/packaging_templates/LICENSE.jinja2 +21 -0
  92. package/generator/pygen/codegen/templates/packaging_templates/MANIFEST.in.jinja2 +8 -0
  93. package/generator/pygen/codegen/templates/packaging_templates/README.md.jinja2 +107 -0
  94. package/generator/pygen/codegen/templates/packaging_templates/dev_requirements.txt.jinja2 +9 -0
  95. package/generator/pygen/codegen/templates/packaging_templates/setup.py.jinja2 +108 -0
  96. package/generator/pygen/codegen/templates/paging_operation.py.jinja2 +21 -0
  97. package/generator/pygen/codegen/templates/patch.py.jinja2 +19 -0
  98. package/generator/pygen/codegen/templates/pkgutil_init.py.jinja2 +1 -0
  99. package/generator/pygen/codegen/templates/request_builder.py.jinja2 +28 -0
  100. package/generator/pygen/codegen/templates/request_builders.py.jinja2 +10 -0
  101. package/generator/pygen/codegen/templates/rest_init.py.jinja2 +12 -0
  102. package/generator/pygen/codegen/templates/sample.py.jinja2 +44 -0
  103. package/generator/pygen/codegen/templates/serialization.py.jinja2 +2006 -0
  104. package/generator/pygen/codegen/templates/test.py.jinja2 +50 -0
  105. package/generator/pygen/codegen/templates/testpreparer.py.jinja2 +26 -0
  106. package/generator/pygen/codegen/templates/types.py.jinja2 +8 -0
  107. package/generator/pygen/codegen/templates/validation.py.jinja2 +38 -0
  108. package/generator/pygen/codegen/templates/vendor.py.jinja2 +98 -0
  109. package/generator/pygen/codegen/templates/version.py.jinja2 +4 -0
  110. package/generator/pygen/m2r.py +65 -0
  111. package/generator/pygen/postprocess/__init__.py +183 -0
  112. package/generator/pygen/postprocess/get_all.py +19 -0
  113. package/generator/pygen/postprocess/venvtools.py +77 -0
  114. package/generator/pygen/preprocess/__init__.py +503 -0
  115. package/generator/pygen/preprocess/helpers.py +27 -0
  116. package/generator/pygen/preprocess/python_mappings.py +222 -0
  117. package/generator/pygen/utils.py +149 -0
  118. package/generator/pygen.egg-info/PKG-INFO +25 -0
  119. package/generator/pygen.egg-info/SOURCES.txt +66 -0
  120. package/generator/pygen.egg-info/dependency_links.txt +1 -0
  121. package/generator/pygen.egg-info/requires.txt +4 -0
  122. package/generator/pygen.egg-info/top_level.txt +1 -0
  123. package/generator/requirements.txt +12 -0
  124. package/generator/setup.py +55 -0
  125. package/package.json +10 -7
  126. package/scripts/__pycache__/venvtools.cpython-38.pyc +0 -0
  127. package/scripts/install.py +49 -0
  128. package/scripts/prepare.py +38 -0
  129. package/scripts/run-python3.cjs +22 -0
  130. package/scripts/run_tsp.py +40 -0
  131. package/scripts/system-requirements.cjs +180 -0
  132. package/scripts/venvtools.py +81 -0
@@ -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:
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_annot = 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_annot} = kwargs.pop('{kwarg.client_name}', " + f"{default_value})"
200
+ )
201
+ else:
202
+ retval.append(f"{kwarg.client_name}: {type_annot} = 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,163 @@
1
+ # pylint: disable=too-many-lines
2
+ # -------------------------------------------------------------------------
3
+ # Copyright (c) Microsoft Corporation. All rights reserved.
4
+ # Licensed under the MIT License. See License.txt in the project root for
5
+ # license information.
6
+ # --------------------------------------------------------------------------
7
+ import logging
8
+ from typing import Dict, Any, Union, Tuple
9
+ from jinja2 import Environment
10
+
11
+ from ..models.operation import OperationBase
12
+ from .import_serializer import FileImportSerializer
13
+ from .base_serializer import BaseSerializer
14
+ from ..models import (
15
+ CodeModel,
16
+ KeyCredentialType,
17
+ TokenCredentialType,
18
+ ImportType,
19
+ OperationGroup,
20
+ Parameter,
21
+ BodyParameter,
22
+ FileImport,
23
+ )
24
+ from .utils import get_namespace_config, get_namespace_from_package_name
25
+ from ...utils import to_snake_case
26
+
27
+ _LOGGER = logging.getLogger(__name__)
28
+
29
+
30
+ class SampleSerializer(BaseSerializer):
31
+ def __init__(
32
+ self,
33
+ code_model: CodeModel,
34
+ env: Environment,
35
+ operation_group: OperationGroup,
36
+ operation: OperationBase[Any],
37
+ sample: Dict[str, Any],
38
+ file_name: str,
39
+ ) -> None:
40
+ super().__init__(code_model, env)
41
+ self.operation_group = operation_group
42
+ self.operation = operation
43
+ self.sample = sample
44
+ self.file_name = file_name
45
+ self.sample_params = {to_snake_case(k): v for k, v in sample.get("parameters", {}).items()}
46
+
47
+ def _imports(self) -> FileImportSerializer:
48
+ imports = FileImport(self.code_model)
49
+ namespace_from_package_name = get_namespace_from_package_name(self.code_model.options["package_name"])
50
+ namespace_config = get_namespace_config(self.code_model.namespace, self.code_model.options["multiapi"])
51
+ namespace = namespace_from_package_name or namespace_config
52
+ # mainly for "azure-mgmt-rdbms"
53
+ if not self.code_model.options["multiapi"] and namespace_config.count(".") > namespace_from_package_name.count(
54
+ "."
55
+ ):
56
+ namespace = namespace_config
57
+ client = self.code_model.clients[0]
58
+ imports.add_submodule_import(namespace, client.name, ImportType.LOCAL)
59
+ credential_type = getattr(client.credential, "type", None)
60
+ if isinstance(credential_type, TokenCredentialType):
61
+ imports.add_submodule_import("azure.identity", "DefaultAzureCredential", ImportType.SDKCORE)
62
+ elif isinstance(credential_type, KeyCredentialType):
63
+ imports.add_import("os", ImportType.STDLIB)
64
+ imports.add_submodule_import(
65
+ "credentials",
66
+ "AzureKeyCredential",
67
+ ImportType.SDKCORE,
68
+ )
69
+ for param in self.operation.parameters.positional:
70
+ if not param.client_default_value and not param.optional and param.client_name in self.sample_params:
71
+ imports.merge(param.type.imports_for_sample())
72
+ return FileImportSerializer(imports, True)
73
+
74
+ def _client_params(self) -> Dict[str, Any]:
75
+ # client params
76
+ special_param = {}
77
+ credential_type = getattr(self.code_model.clients[0].credential, "type", None)
78
+ if isinstance(credential_type, TokenCredentialType):
79
+ special_param.update({"credential": "DefaultAzureCredential()"})
80
+ elif isinstance(credential_type, KeyCredentialType):
81
+ special_param.update({"credential": 'AzureKeyCredential(key=os.getenv("AZURE_KEY"))'})
82
+
83
+ params_positional = [
84
+ p for p in self.code_model.clients[0].parameters.positional if not (p.optional or p.client_default_value)
85
+ ]
86
+ client_params = {
87
+ p.client_name: special_param.get(
88
+ p.client_name,
89
+ f'"{self.sample_params.get(p.client_name) or p.client_name.upper()}"',
90
+ )
91
+ for p in params_positional
92
+ }
93
+
94
+ return client_params
95
+
96
+ @staticmethod
97
+ def handle_param(param: Union[Parameter, BodyParameter], param_value: Any) -> str:
98
+ if isinstance(param_value, str):
99
+ if any(i in param_value for i in '\r\n"'):
100
+ return f'"""{param_value}"""'
101
+
102
+ return param.type.serialize_sample_value(param_value)
103
+
104
+ # prepare operation parameters
105
+ def _operation_params(self) -> Dict[str, Any]:
106
+ params_positional = [p for p in self.operation.parameters.positional if not p.client_default_value]
107
+ failure_info = "fail to find required param named {}"
108
+ operation_params = {}
109
+ for param in params_positional:
110
+ name = param.client_name
111
+ param_value = self.sample_params.get(name)
112
+ if not param.optional:
113
+ if not param_value:
114
+ raise Exception(failure_info.format(name)) # pylint: disable=broad-exception-raised
115
+ operation_params[param.client_name] = self.handle_param(param, param_value)
116
+ return operation_params
117
+
118
+ def _operation_group_name(self) -> str:
119
+ if self.operation_group.is_mixin:
120
+ return ""
121
+ return f".{self.operation_group.property_name}"
122
+
123
+ def _operation_result(self) -> Tuple[str, str]:
124
+ is_response_none = "None" in self.operation.response_type_annotation(async_mode=False)
125
+ lro = ".result()"
126
+ if is_response_none:
127
+ paging, normal_print, return_var = "", "", ""
128
+ else:
129
+ paging = "\n for item in response:\n print(item)"
130
+ normal_print = "\n print(response)"
131
+ return_var = "response = "
132
+
133
+ if self.operation.operation_type == "paging":
134
+ return paging, return_var
135
+ if self.operation.operation_type == "lro":
136
+ return lro + normal_print, return_var
137
+ if self.operation.operation_type == "lropaging":
138
+ return lro + paging, return_var
139
+ return normal_print, return_var
140
+
141
+ def _operation_name(self) -> str:
142
+ return f".{self.operation.name}"
143
+
144
+ def _origin_file(self) -> str:
145
+ name = self.sample.get("x-ms-original-file", "")
146
+ if "specification" in name:
147
+ return "specification" + name.split("specification")[-1]
148
+ return ""
149
+
150
+ def serialize(self) -> str:
151
+ operation_result, return_var = self._operation_result()
152
+ return self.env.get_template("sample.py.jinja2").render(
153
+ code_model=self.code_model,
154
+ file_name=self.file_name,
155
+ operation_result=operation_result,
156
+ operation_params=self._operation_params(),
157
+ operation_group_name=self._operation_group_name(),
158
+ operation_name=self._operation_name(),
159
+ imports=self._imports(),
160
+ client_params=self._client_params(),
161
+ origin_file=self._origin_file(),
162
+ return_var=return_var,
163
+ )