@autorest/python 5.16.0 → 5.19.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 (96) hide show
  1. package/ChangeLog.md +79 -4
  2. package/README.md +30 -4
  3. package/autorest/__init__.py +1 -1
  4. package/autorest/codegen/__init__.py +55 -211
  5. package/autorest/codegen/models/__init__.py +116 -83
  6. package/autorest/codegen/models/base_builder.py +49 -88
  7. package/autorest/codegen/models/base_model.py +1 -1
  8. package/autorest/codegen/models/{base_schema.py → base_type.py} +61 -39
  9. package/autorest/codegen/models/client.py +165 -53
  10. package/autorest/codegen/models/code_model.py +122 -257
  11. package/autorest/codegen/models/combined_type.py +107 -0
  12. package/autorest/codegen/models/{constant_schema.py → constant_type.py} +49 -40
  13. package/autorest/codegen/models/credential_types.py +224 -0
  14. package/autorest/codegen/models/dictionary_type.py +131 -0
  15. package/autorest/codegen/models/enum_type.py +195 -0
  16. package/autorest/codegen/models/imports.py +80 -2
  17. package/autorest/codegen/models/list_type.py +149 -0
  18. package/autorest/codegen/models/lro_operation.py +79 -156
  19. package/autorest/codegen/models/lro_paging_operation.py +28 -11
  20. package/autorest/codegen/models/model_type.py +262 -0
  21. package/autorest/codegen/models/operation.py +331 -298
  22. package/autorest/codegen/models/operation_group.py +54 -91
  23. package/autorest/codegen/models/paging_operation.py +82 -123
  24. package/autorest/codegen/models/parameter.py +289 -396
  25. package/autorest/codegen/models/parameter_list.py +355 -360
  26. package/autorest/codegen/models/primitive_types.py +544 -0
  27. package/autorest/codegen/models/property.py +123 -139
  28. package/autorest/codegen/models/request_builder.py +130 -102
  29. package/autorest/codegen/models/request_builder_parameter.py +112 -100
  30. package/autorest/codegen/models/response.py +325 -0
  31. package/autorest/codegen/models/utils.py +12 -19
  32. package/autorest/codegen/serializers/__init__.py +55 -37
  33. package/autorest/codegen/serializers/builder_serializer.py +695 -1144
  34. package/autorest/codegen/serializers/client_serializer.py +92 -89
  35. package/autorest/codegen/serializers/general_serializer.py +15 -69
  36. package/autorest/codegen/serializers/import_serializer.py +7 -4
  37. package/autorest/codegen/serializers/metadata_serializer.py +15 -104
  38. package/autorest/codegen/serializers/model_base_serializer.py +49 -36
  39. package/autorest/codegen/serializers/model_generic_serializer.py +8 -6
  40. package/autorest/codegen/serializers/model_init_serializer.py +2 -4
  41. package/autorest/codegen/serializers/model_python3_serializer.py +22 -16
  42. package/autorest/codegen/serializers/operation_groups_serializer.py +7 -13
  43. package/autorest/codegen/serializers/parameter_serializer.py +174 -0
  44. package/autorest/codegen/serializers/request_builders_serializer.py +13 -30
  45. package/autorest/codegen/serializers/utils.py +0 -140
  46. package/autorest/codegen/templates/MANIFEST.in.jinja2 +1 -0
  47. package/autorest/codegen/templates/{service_client.py.jinja2 → client.py.jinja2} +10 -7
  48. package/autorest/codegen/templates/config.py.jinja2 +13 -13
  49. package/autorest/codegen/templates/enum.py.jinja2 +4 -4
  50. package/autorest/codegen/templates/enum_container.py.jinja2 +1 -1
  51. package/autorest/codegen/templates/init.py.jinja2 +2 -2
  52. package/autorest/codegen/templates/lro_operation.py.jinja2 +4 -1
  53. package/autorest/codegen/templates/lro_paging_operation.py.jinja2 +4 -1
  54. package/autorest/codegen/templates/metadata.json.jinja2 +33 -33
  55. package/autorest/codegen/templates/model.py.jinja2 +23 -24
  56. package/autorest/codegen/templates/model_container.py.jinja2 +2 -1
  57. package/autorest/codegen/templates/model_init.py.jinja2 +3 -5
  58. package/autorest/codegen/templates/operation.py.jinja2 +6 -8
  59. package/autorest/codegen/templates/operation_group.py.jinja2 +21 -8
  60. package/autorest/codegen/templates/operation_groups_container.py.jinja2 +2 -2
  61. package/autorest/codegen/templates/operation_tools.jinja2 +11 -3
  62. package/autorest/codegen/templates/paging_operation.py.jinja2 +2 -2
  63. package/autorest/codegen/templates/request_builder.py.jinja2 +10 -15
  64. package/autorest/codegen/templates/request_builders.py.jinja2 +1 -1
  65. package/autorest/codegen/templates/serialization.py.jinja2 +2006 -0
  66. package/autorest/codegen/templates/setup.py.jinja2 +13 -3
  67. package/autorest/codegen/templates/vendor.py.jinja2 +11 -1
  68. package/autorest/jsonrpc/server.py +15 -3
  69. package/autorest/m4reformatter/__init__.py +1126 -0
  70. package/autorest/multiapi/models/client.py +12 -2
  71. package/autorest/multiapi/models/code_model.py +1 -1
  72. package/autorest/multiapi/serializers/__init__.py +18 -4
  73. package/autorest/multiapi/templates/multiapi_config.py.jinja2 +3 -3
  74. package/autorest/multiapi/templates/multiapi_init.py.jinja2 +2 -2
  75. package/autorest/multiapi/templates/multiapi_operations_mixin.py.jinja2 +4 -4
  76. package/autorest/multiapi/templates/multiapi_service_client.py.jinja2 +9 -9
  77. package/autorest/postprocess/__init__.py +202 -0
  78. package/autorest/postprocess/get_all.py +19 -0
  79. package/autorest/postprocess/venvtools.py +73 -0
  80. package/autorest/preprocess/__init__.py +210 -0
  81. package/autorest/preprocess/helpers.py +54 -0
  82. package/autorest/{namer → preprocess}/python_mappings.py +21 -16
  83. package/package.json +2 -2
  84. package/autorest/codegen/models/credential_model.py +0 -55
  85. package/autorest/codegen/models/credential_schema.py +0 -95
  86. package/autorest/codegen/models/credential_schema_policy.py +0 -73
  87. package/autorest/codegen/models/dictionary_schema.py +0 -106
  88. package/autorest/codegen/models/enum_schema.py +0 -225
  89. package/autorest/codegen/models/list_schema.py +0 -135
  90. package/autorest/codegen/models/object_schema.py +0 -303
  91. package/autorest/codegen/models/primitive_schemas.py +0 -495
  92. package/autorest/codegen/models/request_builder_parameter_list.py +0 -249
  93. package/autorest/codegen/models/schema_request.py +0 -55
  94. package/autorest/codegen/models/schema_response.py +0 -141
  95. package/autorest/namer/__init__.py +0 -23
  96. package/autorest/namer/name_converter.py +0 -509
@@ -1,249 +0,0 @@
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 copy import copy
7
- from typing import List, Optional, Tuple, TypeVar, Dict, TYPE_CHECKING
8
- from .request_builder_parameter import RequestBuilderParameter
9
- from .parameter_list import ParameterList
10
- from .parameter import (
11
- ParameterLocation,
12
- Parameter,
13
- ParameterMethodLocation,
14
- ParameterStyle,
15
- )
16
- from .primitive_schemas import AnySchema
17
- from .dictionary_schema import DictionarySchema
18
- from .base_schema import BaseSchema
19
- from .list_schema import ListSchema
20
- from .object_schema import ObjectSchema
21
- from .schema_request import SchemaRequest
22
- from .utils import JSON_REGEXP
23
-
24
- if TYPE_CHECKING:
25
- from .code_model import CodeModel
26
-
27
- T = TypeVar("T")
28
- OrderedSet = Dict[T, None]
29
-
30
-
31
- def _update_content_types(content_types_to_assign: List[str], param: Parameter):
32
- return [c for c in content_types_to_assign if c not in param.content_types]
33
-
34
-
35
- def _kwarg_not_added(body_method_params, serialized_name: str) -> bool:
36
- return not any(
37
- b for b in body_method_params if b.serialized_name == serialized_name
38
- )
39
-
40
-
41
- class RequestBuilderParameterList(ParameterList):
42
- def __init__(
43
- self,
44
- code_model: "CodeModel",
45
- parameters: Optional[List[RequestBuilderParameter]] = None,
46
- schema_requests: Optional[List[SchemaRequest]] = None,
47
- ) -> None:
48
- super().__init__(code_model, parameters, schema_requests) # type: ignore
49
- self.body_kwarg_names: OrderedSet[str] = {}
50
- self.parameters: List[RequestBuilderParameter] = parameters or [] # type: ignore
51
-
52
- def _change_body_param_name(self, parameter: Parameter, name: str) -> None:
53
- self.body_kwarg_names[name] = None
54
- parameter.serialized_name = name
55
- parameter.is_body_kwarg = True
56
-
57
- def _is_json(self, body_method_param: Parameter) -> bool:
58
- if "json" in body_method_param.serialization_formats:
59
- return True
60
- if not any(
61
- flag
62
- for flag in ["version_tolerant", "low_level_client"]
63
- if self.code_model.options.get(flag)
64
- ):
65
- if body_method_param.style == ParameterStyle.binary:
66
- return False
67
- if any(
68
- sr
69
- for sr in self.schema_requests
70
- if sr.yaml_data.get("protocol", {}).get("http", {}).get("knownMediaType")
71
- == "json"
72
- ):
73
- return True
74
- return any(c for c in self.content_types if JSON_REGEXP.match(c))
75
-
76
- @property
77
- def body_kwargs_to_get(self) -> List[Parameter]:
78
- if not self.body_kwarg_names:
79
- return []
80
- return [b for b in self.body if b.content_types]
81
-
82
- def _update_constant_params(self):
83
- # we don't currently have a fully constant data or files input
84
- # so we don't need to modify the body kwarg
85
- constant_bodies = [
86
- p
87
- for p in self.parameters
88
- if p.location == ParameterLocation.Body and p.constant
89
- ]
90
- for constant_body in constant_bodies:
91
- if self._is_json(constant_body):
92
- constant_body.serialized_name = "json"
93
- else:
94
- constant_body.serialized_name = "content"
95
-
96
- def _add_json_kwarg(
97
- self, content_types_to_assign, body_method_param
98
- ) -> Tuple[List[str], RequestBuilderParameter]:
99
- json_kwarg = copy(body_method_param)
100
- self._change_body_param_name(json_kwarg, "json")
101
- json_kwarg.description = (
102
- "Pass in a JSON-serializable object (usually a dictionary). "
103
- "See the template in our example to find the input shape. "
104
- + json_kwarg.description
105
- )
106
- if not isinstance(
107
- body_method_param.schema, (ObjectSchema, DictionarySchema, ListSchema)
108
- ):
109
- json_kwarg.schema = AnySchema(yaml_data={}, code_model=self.code_model)
110
- json_kwarg.content_types = [
111
- c for c in content_types_to_assign if JSON_REGEXP.match(c)
112
- ]
113
- content_types_to_assign = _update_content_types(
114
- content_types_to_assign, json_kwarg
115
- )
116
- return content_types_to_assign, json_kwarg
117
-
118
- def _add_content_kwarg(
119
- self, content_types_to_assign, body_method_param
120
- ) -> RequestBuilderParameter:
121
- content_kwarg = copy(body_method_param)
122
- self._change_body_param_name(content_kwarg, "content")
123
- content_kwarg.schema = AnySchema(yaml_data={}, code_model=self.code_model)
124
- content_kwarg.description = (
125
- "Pass in binary content you want in the body of the request (typically bytes, "
126
- "a byte iterator, or stream input). " + content_kwarg.description
127
- )
128
- content_kwarg.content_types = content_types_to_assign
129
- return content_kwarg
130
-
131
- def add_body_kwargs(self) -> None:
132
- self._update_constant_params()
133
- body_kwargs_added: List[RequestBuilderParameter] = []
134
- body_method_params = [
135
- p
136
- for p in self.parameters
137
- if p.location == ParameterLocation.Body
138
- and not (p.constant or p.is_multipart or p.is_data_input)
139
- ]
140
- if not body_method_params:
141
- return
142
- content_types_to_assign = copy(self.content_types)
143
- for body_method_param in body_method_params:
144
- if self._is_json(body_method_param) and _kwarg_not_added(
145
- body_kwargs_added, "json"
146
- ):
147
- content_types_to_assign, json_kwarg = self._add_json_kwarg(
148
- content_types_to_assign, body_method_param
149
- )
150
- body_kwargs_added.append(json_kwarg)
151
-
152
- first_body_param = body_method_params[0]
153
- if _kwarg_not_added(body_kwargs_added, "content"):
154
- # we always add a content kwarg so users can pass in input by stream
155
- content_kwarg = self._add_content_kwarg(
156
- content_types_to_assign, first_body_param
157
- )
158
- body_kwargs_added.append(content_kwarg)
159
- if len(body_kwargs_added) == 1:
160
- body_kwargs_added[0].required = first_body_param.required
161
- else:
162
- for kwarg in body_kwargs_added:
163
- kwarg.required = False
164
- first_body_param.need_import = False
165
- self.parameters = body_kwargs_added + self.parameters
166
-
167
- @property
168
- def json_body(self) -> BaseSchema:
169
- if not self._json_body:
170
- try:
171
- json_param = next(
172
- b for b in self.body if not b.is_body_kwarg and b.is_json_parameter
173
- )
174
- self._json_body = json_param.schema
175
- return self._json_body
176
- except StopIteration:
177
- raise ValueError("There is no JSON body in these parameters")
178
- return self._json_body
179
-
180
- def kwargs_to_pop(self, is_python3_file: bool) -> List[Parameter]:
181
- # we don't want to pop the body kwargs in py2.7. We send them straight to HttpRequest
182
- kwargs_to_pop = self.kwargs
183
- if not is_python3_file:
184
- kwargs_to_pop += [
185
- k for k in self.keyword_only if not (k.is_body and not k.constant)
186
- ]
187
- return kwargs_to_pop
188
-
189
- @property
190
- def method(self) -> List[Parameter]:
191
- """The list of parameter used in method signature. Includes both positional and kwargs"""
192
- signature_parameters_no_default_value = []
193
- signature_parameters_default_value = []
194
-
195
- # Want all method parameters.
196
- # Also allow client parameters if they're going to be used in the request body.
197
- # i.e., path parameter, query parameter, header.
198
- parameters = self.get_from_predicate(
199
- lambda parameter: parameter.implementation == self.implementation
200
- or parameter.in_method_code
201
- )
202
- seen_content_type = False
203
-
204
- for parameter in parameters:
205
- if parameter.location == ParameterLocation.Body and (
206
- parameter.is_multipart or parameter.is_data_input
207
- ):
208
- # don't want any multipart for formdata params in our signature
209
- continue
210
- if (
211
- parameter.location == ParameterLocation.Body
212
- and not parameter.is_body_kwarg
213
- and not parameter.constant
214
- ):
215
- # we keep the original body param from the swagger for documentation purposes
216
- # we don't want it in the method signature
217
- continue
218
- if any(
219
- [g for g in self.groupers if id(g.yaml_data) == id(parameter.yaml_data)]
220
- ):
221
- # we don't allow a grouped parameter for the body param
222
- continue
223
- if seen_content_type and parameter.serialized_name == "content_type":
224
- # we ony want one content type
225
- # there can be multiple content types in the case of multiple media types
226
- continue
227
- if parameter.serialized_name == "content_type":
228
- seen_content_type = True
229
- if parameter.in_method_signature:
230
- if not parameter.default_value and parameter.required:
231
- signature_parameters_no_default_value.append(parameter)
232
- else:
233
- signature_parameters_default_value.append(parameter)
234
-
235
- signature_parameters = (
236
- signature_parameters_no_default_value + signature_parameters_default_value
237
- )
238
- signature_parameters.sort(
239
- key=lambda item: item.method_location
240
- == ParameterMethodLocation.KEYWORD_ONLY
241
- )
242
- signature_parameters = self._filter_out_multiple_content_type(
243
- signature_parameters
244
- )
245
- return signature_parameters
246
-
247
- @staticmethod
248
- def _wanted_path_parameter(parameter):
249
- return parameter.location == ParameterLocation.Path
@@ -1,55 +0,0 @@
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, List, Any, Optional, TYPE_CHECKING
7
-
8
- from .base_model import BaseModel
9
- from .parameter import Parameter
10
- from .parameter_list import ParameterList
11
-
12
- if TYPE_CHECKING:
13
- from .code_model import CodeModel
14
-
15
-
16
- class SchemaRequest(BaseModel):
17
- def __init__(
18
- self,
19
- yaml_data: Dict[str, Any],
20
- code_model: "CodeModel",
21
- content_types: List[str],
22
- parameters: ParameterList,
23
- ) -> None:
24
- super().__init__(yaml_data, code_model)
25
- self.content_types = content_types
26
- self.parameters = parameters
27
-
28
- @property
29
- def is_stream_request(self) -> bool:
30
- """Is the request expected to be streamable, like a download."""
31
- if self.yaml_data["protocol"]["http"].get("knownMediaType"):
32
- return (
33
- self.yaml_data["protocol"]["http"]["knownMediaType"] == "binary"
34
- ) # FIXME: this might be an m4 issue
35
- return self.yaml_data["protocol"]["http"].get("binary", False)
36
-
37
- @classmethod
38
- def from_yaml(
39
- cls, yaml_data: Dict[str, Any], code_model: "CodeModel"
40
- ) -> "SchemaRequest":
41
-
42
- parameters: Optional[List[Parameter]] = [
43
- Parameter.from_yaml(yaml, code_model=code_model)
44
- for yaml in yaml_data.get("parameters", [])
45
- ]
46
-
47
- return cls(
48
- yaml_data=yaml_data,
49
- code_model=code_model,
50
- content_types=yaml_data["protocol"]["http"].get("mediaTypes", []),
51
- parameters=ParameterList(code_model, parameters),
52
- )
53
-
54
- def __repr__(self) -> str:
55
- return f"<{self.__class__.__name__} {self.content_types}>"
@@ -1,141 +0,0 @@
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, Optional, List, Union, Any, cast, TYPE_CHECKING
7
-
8
- from .base_model import BaseModel
9
- from .base_schema import BaseSchema
10
- from .object_schema import ObjectSchema
11
- from .imports import FileImport, ImportType
12
- from .utils import get_schema
13
- from .primitive_schemas import IOSchema
14
-
15
- if TYPE_CHECKING:
16
- from .code_model import CodeModel
17
-
18
-
19
- class HeaderResponse:
20
- def __init__(self, name: str, schema) -> None:
21
- self.name = name
22
- self.schema = schema
23
-
24
- @property
25
- def serialization_type(self) -> str:
26
- return self.schema.serialization_type
27
-
28
-
29
- class SchemaResponse(BaseModel):
30
- def __init__(
31
- self,
32
- yaml_data: Dict[str, Any],
33
- code_model: "CodeModel",
34
- schema: Optional[BaseSchema],
35
- content_types: List[str],
36
- status_codes: List[Union[str, int]],
37
- headers: List[HeaderResponse],
38
- binary: bool,
39
- ) -> None:
40
- super().__init__(yaml_data, code_model)
41
- self.schema = schema
42
- self.content_types = content_types
43
- self.status_codes = status_codes
44
- self.headers = headers
45
- self.binary = binary
46
- self.nullable = self.yaml_data.get("nullable", False)
47
-
48
- @property
49
- def has_body(self) -> bool:
50
- """Tell if that response defines a body."""
51
- return bool(self.schema)
52
-
53
- @property
54
- def has_headers(self) -> bool:
55
- """Tell if that response defines headers."""
56
- return bool(self.headers)
57
-
58
- @property
59
- def serialization_type(self) -> str:
60
- if self.schema:
61
- return self.schema.serialization_type
62
- return "None"
63
-
64
- def type_annotation(self, *, is_operation_file: bool = False) -> str:
65
- if not self.schema:
66
- return "None"
67
- if self.nullable:
68
- return f"Optional[{self.schema.type_annotation(is_operation_file=is_operation_file)}]"
69
- return self.schema.type_annotation(is_operation_file=is_operation_file)
70
-
71
- @property
72
- def docstring_text(self) -> str:
73
- if not self.schema:
74
- return "None"
75
- if self.nullable:
76
- return f"{self.schema.docstring_text} or None"
77
- return self.schema.docstring_text
78
-
79
- @property
80
- def docstring_type(self) -> str:
81
- if not self.schema:
82
- return "None"
83
- if self.nullable:
84
- return f"{self.schema.docstring_type} or None"
85
- return self.schema.docstring_type
86
-
87
- @property
88
- def is_stream_response(self) -> bool:
89
- """Is the response expected to be streamable, like a download."""
90
- return self.binary
91
-
92
- @property
93
- def is_exception(self) -> bool:
94
- if self.schema:
95
- return cast(ObjectSchema, self.schema).is_exception
96
- return False
97
-
98
- @property
99
- def is_xml(self) -> bool:
100
- return any(["xml" in ct for ct in self.content_types])
101
-
102
- def imports(self, code_model) -> FileImport:
103
- file_import = FileImport()
104
- if not code_model.options["models_mode"] and self.is_xml:
105
- file_import.add_submodule_import(
106
- "xml.etree", "ElementTree", ImportType.STDLIB, alias="ET"
107
- )
108
- return file_import
109
-
110
- @classmethod
111
- def from_yaml(
112
- cls, yaml_data: Dict[str, Any], code_model: "CodeModel"
113
- ) -> "SchemaResponse":
114
- binary = yaml_data.get("binary", False)
115
- if binary:
116
- schema: BaseSchema = IOSchema(yaml_data={}, code_model=code_model)
117
- else:
118
- schema = get_schema(code_model, yaml_data.get("schema"))
119
- return cls(
120
- yaml_data=yaml_data,
121
- code_model=code_model,
122
- schema=schema,
123
- content_types=yaml_data["protocol"]["http"].get("mediaTypes", []),
124
- status_codes=[
125
- int(code) if code != "default" else "default"
126
- for code in yaml_data["protocol"]["http"]["statusCodes"]
127
- ],
128
- headers=[
129
- HeaderResponse(
130
- header_prop["header"],
131
- get_schema(
132
- code_model, header_prop["schema"], header_prop["header"]
133
- ),
134
- )
135
- for header_prop in yaml_data["protocol"]["http"].get("headers", [])
136
- ],
137
- binary=binary,
138
- )
139
-
140
- def __repr__(self) -> str:
141
- return f"<{self.__class__.__name__} {self.status_codes}>"
@@ -1,23 +0,0 @@
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
- """The namer autorest plugin.
7
- """
8
- import logging
9
- from typing import Dict, Any
10
-
11
- from .. import YamlUpdatePlugin
12
- from .name_converter import NameConverter
13
-
14
-
15
- _LOGGER = logging.getLogger(__name__)
16
-
17
-
18
- class Namer(YamlUpdatePlugin):
19
- """Add Python naming information."""
20
-
21
- def update_yaml(self, yaml_data: Dict[str, Any]) -> None:
22
- """Convert in place the YAML str."""
23
- NameConverter.convert_yaml_names(yaml_data)