@autorest/python 5.16.0 → 5.17.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 (92) hide show
  1. package/ChangeLog.md +43 -3
  2. package/README.md +30 -4
  3. package/autorest/__init__.py +1 -1
  4. package/autorest/codegen/__init__.py +48 -209
  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} +56 -40
  9. package/autorest/codegen/models/client.py +157 -48
  10. package/autorest/codegen/models/code_model.py +108 -254
  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_schema.py → dictionary_type.py} +41 -31
  15. package/autorest/codegen/models/enum_type.py +195 -0
  16. package/autorest/codegen/models/imports.py +23 -0
  17. package/autorest/codegen/models/list_type.py +134 -0
  18. package/autorest/codegen/models/lro_operation.py +77 -156
  19. package/autorest/codegen/models/lro_paging_operation.py +28 -11
  20. package/autorest/codegen/models/model_type.py +239 -0
  21. package/autorest/codegen/models/operation.py +303 -269
  22. package/autorest/codegen/models/operation_group.py +48 -89
  23. package/autorest/codegen/models/paging_operation.py +80 -123
  24. package/autorest/codegen/models/parameter.py +289 -396
  25. package/autorest/codegen/models/parameter_list.py +348 -360
  26. package/autorest/codegen/models/primitive_types.py +544 -0
  27. package/autorest/codegen/models/property.py +109 -139
  28. package/autorest/codegen/models/request_builder.py +105 -88
  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 +46 -37
  33. package/autorest/codegen/serializers/builder_serializer.py +604 -1146
  34. package/autorest/codegen/serializers/client_serializer.py +83 -88
  35. package/autorest/codegen/serializers/general_serializer.py +5 -64
  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 +40 -32
  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 +4 -13
  43. package/autorest/codegen/serializers/parameter_serializer.py +174 -0
  44. package/autorest/codegen/serializers/request_builders_serializer.py +12 -29
  45. package/autorest/codegen/serializers/utils.py +0 -142
  46. package/autorest/codegen/templates/MANIFEST.in.jinja2 +1 -0
  47. package/autorest/codegen/templates/{service_client.py.jinja2 → client.py.jinja2} +7 -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 +7 -7
  60. package/autorest/codegen/templates/operation_groups_container.py.jinja2 +1 -1
  61. package/autorest/codegen/templates/operation_tools.jinja2 +8 -2
  62. package/autorest/codegen/templates/paging_operation.py.jinja2 +2 -2
  63. package/autorest/codegen/templates/request_builder.py.jinja2 +13 -11
  64. package/autorest/codegen/templates/setup.py.jinja2 +9 -3
  65. package/autorest/codegen/templates/vendor.py.jinja2 +1 -1
  66. package/autorest/jsonrpc/server.py +15 -3
  67. package/autorest/m4reformatter/__init__.py +1108 -0
  68. package/autorest/multiapi/models/code_model.py +1 -1
  69. package/autorest/multiapi/serializers/__init__.py +4 -4
  70. package/autorest/multiapi/templates/multiapi_config.py.jinja2 +3 -3
  71. package/autorest/multiapi/templates/multiapi_init.py.jinja2 +2 -2
  72. package/autorest/multiapi/templates/multiapi_operations_mixin.py.jinja2 +3 -3
  73. package/autorest/multiapi/templates/multiapi_service_client.py.jinja2 +9 -9
  74. package/autorest/postprocess/__init__.py +202 -0
  75. package/autorest/postprocess/get_all.py +19 -0
  76. package/autorest/postprocess/venvtools.py +73 -0
  77. package/autorest/preprocess/__init__.py +209 -0
  78. package/autorest/preprocess/helpers.py +54 -0
  79. package/autorest/{namer → preprocess}/python_mappings.py +21 -16
  80. package/package.json +2 -2
  81. package/autorest/codegen/models/credential_model.py +0 -55
  82. package/autorest/codegen/models/credential_schema.py +0 -95
  83. package/autorest/codegen/models/credential_schema_policy.py +0 -73
  84. package/autorest/codegen/models/enum_schema.py +0 -225
  85. package/autorest/codegen/models/list_schema.py +0 -135
  86. package/autorest/codegen/models/object_schema.py +0 -303
  87. package/autorest/codegen/models/primitive_schemas.py +0 -495
  88. package/autorest/codegen/models/request_builder_parameter_list.py +0 -249
  89. package/autorest/codegen/models/schema_request.py +0 -55
  90. package/autorest/codegen/models/schema_response.py +0 -141
  91. package/autorest/namer/__init__.py +0 -23
  92. package/autorest/namer/name_converter.py +0 -509
@@ -3,13 +3,13 @@
3
3
  # Licensed under the MIT License. See License.txt in the project root for
4
4
  # license information.
5
5
  # --------------------------------------------------------------------------
6
- from typing import cast, Any, Dict, Union, List, Optional, TYPE_CHECKING
6
+ from typing import Any, Dict, Optional, TYPE_CHECKING, List
7
7
 
8
8
  from .base_model import BaseModel
9
- from .constant_schema import ConstantSchema
9
+ from .constant_type import ConstantType
10
+ from .base_type import BaseType
10
11
  from .imports import FileImport, ImportType, TypingSection
11
- from .base_schema import BaseSchema
12
- from .enum_schema import EnumSchema
12
+ from .utils import add_to_description, add_to_pylint_disable
13
13
 
14
14
  if TYPE_CHECKING:
15
15
  from .code_model import CodeModel
@@ -20,173 +20,143 @@ class Property(BaseModel): # pylint: disable=too-many-instance-attributes
20
20
  self,
21
21
  yaml_data: Dict[str, Any],
22
22
  code_model: "CodeModel",
23
- name: str,
24
- schema: BaseSchema,
25
- original_swagger_name: str,
26
- *,
27
- flattened_names: Optional[List[str]] = None,
28
- description: Optional[str] = None,
29
- client_default_value: Optional[Any] = None,
23
+ type: BaseType,
30
24
  ) -> None:
31
25
  super().__init__(yaml_data, code_model)
32
- self.name = name
33
- self.schema = schema
34
- self.original_swagger_name = original_swagger_name
35
- self.flattened_names = flattened_names or []
36
-
37
- self.required: bool = yaml_data.get("required", False)
38
- self.readonly: bool = yaml_data.get("readOnly", False)
26
+ self.rest_api_name: str = self.yaml_data["restApiName"]
27
+ self.client_name: str = self.yaml_data["clientName"]
28
+ self.type = type
29
+ self.optional: bool = self.yaml_data["optional"]
30
+ self.readonly: bool = self.yaml_data.get("readonly", False)
39
31
  self.is_discriminator: bool = yaml_data.get("isDiscriminator", False)
40
- self.client_default_value = client_default_value
41
- self.description = self._create_description(description, yaml_data)
42
-
43
- def _create_description(
44
- self, description_input: Optional[str], yaml_data: Dict[str, Any]
45
- ) -> str:
46
- description: str = (
47
- description_input or yaml_data["language"]["python"]["description"]
32
+ self.client_default_value = yaml_data.get("clientDefaultValue", None)
33
+ if self.client_default_value is None:
34
+ self.client_default_value = self.type.client_default_value
35
+ self.flattened_names: List[str] = yaml_data.get("flattenedNames", [])
36
+
37
+ @property
38
+ def pylint_disable(self) -> str:
39
+ retval: str = ""
40
+ if self.yaml_data.get("pylintDisable"):
41
+ retval = add_to_pylint_disable(retval, self.yaml_data["pylintDisable"])
42
+ return retval
43
+
44
+ def description(self, *, is_operation_file: bool) -> str:
45
+ from .model_type import ModelType
46
+
47
+ description = self.yaml_data["description"]
48
+ if not (self.optional or self.client_default_value):
49
+ description = add_to_description(description, "Required.")
50
+ # don't want model type documentation as part of property doc
51
+ type_description = (
52
+ ""
53
+ if isinstance(self.type, ModelType)
54
+ else self.type.description(is_operation_file=is_operation_file)
48
55
  )
49
- if description and description[-1] != ".":
50
- description += "."
51
- if self.name == "tags":
52
- description = "A set of tags. " + description
53
- if self.constant:
54
- description += f" Has constant value: {self.constant_declaration}."
55
- elif self.required:
56
- if description:
57
- description = "Required. " + description
58
- else:
59
- description = "Required. "
60
- elif isinstance(self.schema, ConstantSchema):
61
- description += (
62
- f" The only acceptable values to pass in are None and {self.constant_declaration}. "
63
- + f"The default value is {self.default_value_declaration}."
64
- )
65
- if self.is_discriminator:
66
- description += "Constant filled by server. "
67
- if isinstance(self.schema, EnumSchema):
68
- values = [
69
- self.schema.enum_type.get_declaration(v.value)
70
- for v in self.schema.values
71
- ]
72
- if description and description[-1] != " ":
73
- description += " "
74
- description += "Known values are: {}.".format(", ".join(values))
75
- if self.schema.default_value:
76
- description += f' Default value: "{self.schema.default_value}".'
77
- return description
56
+ return add_to_description(description, type_description)
57
+
58
+ @property
59
+ def client_default_value_declaration(self) -> str:
60
+ if self.client_default_value is not None:
61
+ return self.type.get_declaration(self.client_default_value)
62
+ if self.type.client_default_value is not None:
63
+ return self.type.get_declaration(self.type.client_default_value)
64
+ return "None"
78
65
 
79
66
  @property
80
67
  def constant(self) -> bool:
81
68
  # this bool doesn't consider you to be constant if you are a discriminator
82
69
  # you also have to be required to be considered a constant
83
70
  return (
84
- isinstance(self.schema, ConstantSchema)
85
- and self.required
71
+ isinstance(self.type, ConstantType)
72
+ and not self.optional
86
73
  and not self.is_discriminator
87
74
  )
88
75
 
89
76
  @property
90
- def validation_map(self) -> Optional[Dict[str, Union[bool, int, str]]]:
91
- retval: Dict[str, Union[bool, int, str]] = {}
92
- if self.required:
77
+ def is_input(self):
78
+ return not (self.constant or self.readonly or self.is_discriminator)
79
+
80
+ @property
81
+ def serialization_type(self) -> str:
82
+ return self.type.serialization_type
83
+
84
+ def type_annotation(self, *, is_operation_file: bool = False) -> str:
85
+ if self.optional and self.client_default_value is None:
86
+ return f"Optional[{self.type.type_annotation(is_operation_file=is_operation_file)}]"
87
+ return self.type.type_annotation(is_operation_file=is_operation_file)
88
+
89
+ def get_json_template_representation(
90
+ self,
91
+ *,
92
+ optional: bool = True, # pylint: disable=unused-argument
93
+ client_default_value_declaration: Optional[str] = None,
94
+ description: Optional[str] = None,
95
+ ) -> Any:
96
+ if self.client_default_value:
97
+ client_default_value_declaration = self.type.get_declaration(
98
+ self.client_default_value
99
+ )
100
+ if self.description(is_operation_file=True):
101
+ description = self.description(is_operation_file=True)
102
+ return self.type.get_json_template_representation(
103
+ optional=self.optional,
104
+ client_default_value_declaration=client_default_value_declaration,
105
+ description=description,
106
+ )
107
+
108
+ @property
109
+ def validation(self) -> Optional[Dict[str, Any]]:
110
+ retval: Dict[str, Any] = {}
111
+ if not self.optional:
93
112
  retval["required"] = True
94
113
  if self.readonly:
95
114
  retval["readonly"] = True
96
115
  if self.constant:
97
116
  retval["constant"] = True
98
- if self.schema.validation_map:
99
- validation_map_from_schema = cast(
100
- Dict[str, Union[bool, int, str]], self.schema.validation_map
101
- )
102
- retval.update(validation_map_from_schema)
117
+ retval.update(self.type.validation or {})
103
118
  return retval or None
104
119
 
105
120
  @property
106
- def escaped_swagger_name(self) -> str:
107
- """Return the RestAPI name correctly escaped for serialization."""
121
+ def attribute_map(self) -> str:
108
122
  if self.flattened_names:
109
- return ".".join(n.replace(".", "\\\\.") for n in self.flattened_names)
110
- return self.original_swagger_name.replace(".", "\\\\.")
123
+ attribute_key = ".".join(
124
+ n.replace(".", "\\\\.") for n in self.flattened_names
125
+ )
126
+ else:
127
+ attribute_key = self.rest_api_name.replace(".", "\\\\.")
128
+ if self.type.xml_serialization_ctxt:
129
+ xml_metadata = f", 'xml': {{{self.type.xml_serialization_ctxt}}}"
130
+ else:
131
+ xml_metadata = ""
132
+ return f'"{self.client_name}": {{"key": "{attribute_key}", "type": "{self.serialization_type}"{xml_metadata}}},'
133
+
134
+ def imports(self) -> FileImport:
135
+ from .model_type import ModelType
136
+
137
+ file_import = self.type.imports(is_operation_file=False)
138
+ if self.optional and self.client_default_value is None:
139
+ file_import.add_submodule_import("typing", "Optional", ImportType.STDLIB)
140
+ if isinstance(self.type, ModelType):
141
+ file_import.add_submodule_import(
142
+ "..",
143
+ "models",
144
+ ImportType.LOCAL,
145
+ TypingSection.TYPING,
146
+ alias="_models",
147
+ )
148
+ return file_import
111
149
 
112
150
  @classmethod
113
151
  def from_yaml(
114
152
  cls,
115
153
  yaml_data: Dict[str, Any],
116
154
  code_model: "CodeModel",
117
- *,
118
- has_additional_properties: Optional[bool] = None,
119
155
  ) -> "Property":
120
- from . import build_schema # pylint: disable=import-outside-toplevel
156
+ from . import build_type # pylint: disable=import-outside-toplevel
121
157
 
122
- name = yaml_data["language"]["python"]["name"]
123
- if name == "additional_properties" and has_additional_properties:
124
- name = "additional_properties1"
125
- schema = build_schema(yaml_data=yaml_data["schema"], code_model=code_model)
126
158
  return cls(
127
159
  yaml_data=yaml_data,
128
160
  code_model=code_model,
129
- name=name,
130
- schema=schema,
131
- original_swagger_name=yaml_data["serializedName"],
132
- flattened_names=yaml_data.get("flattenedNames", []),
133
- client_default_value=yaml_data.get("clientDefaultValue"),
161
+ type=build_type(yaml_data["type"], code_model),
134
162
  )
135
-
136
- @property
137
- def is_input(self):
138
- return not (self.constant or self.readonly or self.is_discriminator)
139
-
140
- @property
141
- def constant_declaration(self) -> str:
142
- if self.schema:
143
- if isinstance(self.schema, ConstantSchema):
144
- return self.schema.get_declaration(self.schema.value)
145
- raise ValueError(
146
- "Trying to get constant declaration for a schema that is not ConstantSchema"
147
- )
148
- raise ValueError("Trying to get a declaration for a schema that doesn't exist")
149
-
150
- @property
151
- def serialization_type(self) -> str:
152
- return self.schema.serialization_type
153
-
154
- @property
155
- def xml_metadata(self) -> str:
156
- if self.schema.has_xml_serialization_ctxt:
157
- return f", 'xml': {{{self.schema.xml_serialization_ctxt()}}}"
158
- return ""
159
-
160
- @property
161
- def default_value(self) -> Any:
162
- return self.client_default_value or self.schema.default_value
163
-
164
- @property
165
- def default_value_declaration(self) -> Any:
166
- if self.client_default_value:
167
- return self.schema.get_declaration(self.client_default_value)
168
- return self.schema.default_value_declaration
169
-
170
- def type_annotation(self, *, is_operation_file: bool = False) -> str:
171
- if self.required:
172
- return self.schema.type_annotation(is_operation_file=is_operation_file)
173
- return f"Optional[{self.schema.type_annotation(is_operation_file=is_operation_file)}]"
174
-
175
- def get_json_template_representation(self, **kwargs: Any) -> Any:
176
- kwargs["optional"] = not self.required
177
- if self.default_value:
178
- kwargs["default_value_declaration"] = self.schema.get_declaration(
179
- self.default_value
180
- )
181
- if self.description:
182
- kwargs["description"] = self.description
183
- return self.schema.get_json_template_representation(**kwargs)
184
-
185
- def model_file_imports(self) -> FileImport:
186
- file_import = self.schema.model_file_imports()
187
- if not self.required:
188
- file_import.add_submodule_import(
189
- "typing", "Optional", ImportType.STDLIB, TypingSection.CONDITIONAL
190
- )
191
- file_import.merge(self.schema.model_file_imports())
192
- return file_import
@@ -3,82 +3,79 @@
3
3
  # Licensed under the MIT License. See License.txt in the project root for
4
4
  # license information.
5
5
  # --------------------------------------------------------------------------
6
- from typing import Any, Dict, List, TypeVar, Optional, TYPE_CHECKING
7
6
  import logging
8
-
9
- from .base_builder import BaseBuilder, create_parameters
10
- from .request_builder_parameter import RequestBuilderParameter
11
- from .request_builder_parameter_list import RequestBuilderParameterList
12
- from .schema_request import SchemaRequest
13
- from .schema_response import SchemaResponse
7
+ from typing import (
8
+ Any,
9
+ Callable,
10
+ Dict,
11
+ List,
12
+ TypeVar,
13
+ TYPE_CHECKING,
14
+ Union,
15
+ Optional,
16
+ )
17
+ from abc import abstractmethod
18
+
19
+ from .base_builder import BaseBuilder
20
+ from .parameter_list import (
21
+ RequestBuilderParameterList,
22
+ OverloadedRequestBuilderParameterList,
23
+ )
14
24
  from .imports import FileImport, ImportType, TypingSection
15
- from .parameter import Parameter
25
+ from .request_builder_parameter import RequestBuilderMultipartBodyParameter
16
26
 
17
27
  if TYPE_CHECKING:
18
28
  from .code_model import CodeModel
19
29
 
20
30
  _LOGGER = logging.getLogger(__name__)
21
-
22
- T = TypeVar("T")
23
- OrderedSet = Dict[T, None]
31
+ ParameterListType = TypeVar(
32
+ "ParameterListType",
33
+ bound=Union[RequestBuilderParameterList, OverloadedRequestBuilderParameterList],
34
+ )
24
35
 
25
36
 
26
- class RequestBuilder(BaseBuilder):
37
+ class RequestBuilderBase(BaseBuilder[ParameterListType]):
27
38
  def __init__(
28
39
  self,
29
40
  yaml_data: Dict[str, Any],
30
41
  code_model: "CodeModel",
31
42
  name: str,
32
- url: str,
33
- method: str,
34
- multipart: bool,
35
- schema_requests: List[SchemaRequest],
36
- parameters: RequestBuilderParameterList,
37
- description: str,
38
- summary: str,
39
- responses: Optional[List[SchemaResponse]] = None,
43
+ parameters: ParameterListType,
40
44
  *,
45
+ overloads: Optional[List["RequestBuilder"]] = None,
41
46
  abstract: bool = False,
42
- ):
47
+ ) -> None:
43
48
  super().__init__(
44
- yaml_data=yaml_data,
45
49
  code_model=code_model,
50
+ yaml_data=yaml_data,
46
51
  name=name,
47
- description=description,
48
52
  parameters=parameters,
49
- responses=responses,
50
- schema_requests=schema_requests,
51
- summary=summary,
53
+ overloads=overloads,
52
54
  abstract=abstract,
53
55
  want_tracing=False,
54
56
  )
55
- self.url = url
56
- self.method = method
57
- self.multipart = multipart
58
-
59
- @property
60
- def is_stream(self) -> bool:
61
- """Is the request we're preparing a stream, like an upload."""
62
- return any(request.is_stream_request for request in self.schema_requests)
63
-
64
- @property
65
- def body_kwargs_to_get(self) -> List[Parameter]:
66
- return self.parameters.body_kwargs_to_get
67
-
68
- @property
69
- def operation_group_name(self) -> str:
70
- return self.yaml_data["language"]["python"]["operationGroupName"]
57
+ self.overloads: List["RequestBuilder"] = overloads or []
58
+ self.url: str = yaml_data["url"]
59
+ self.method: str = yaml_data["method"]
60
+
61
+ def response_type_annotation(self, **kwargs) -> str:
62
+ return "HttpRequest"
63
+
64
+ def response_docstring_text(self, **kwargs) -> str:
65
+ return (
66
+ "Returns an :class:`~azure.core.rest.HttpRequest` that you will pass to the client's "
67
+ + "`send_request` method. See https://aka.ms/azsdk/python/protocol/quickstart for how to "
68
+ + "incorporate this response into your code flow."
69
+ )
71
70
 
72
- @property
73
- def builder_group_name(self) -> str:
74
- return self.yaml_data["language"]["python"]["builderGroupName"]
71
+ def response_docstring_type(self, **kwargs) -> str:
72
+ return "~azure.core.rest.HttpRequest"
75
73
 
76
74
  def imports(self) -> FileImport:
77
75
  file_import = FileImport()
78
- for parameter in self.parameters.method:
79
- if self.abstract and (parameter.is_multipart or parameter.is_data_input):
80
- continue
81
- file_import.merge(parameter.imports())
76
+ if not self.abstract:
77
+ for parameter in self.parameters.method:
78
+ file_import.merge(parameter.imports(async_mode=False))
82
79
 
83
80
  file_import.add_submodule_import(
84
81
  "azure.core.rest",
@@ -90,9 +87,9 @@ class RequestBuilder(BaseBuilder):
90
87
  relative_path = ".."
91
88
  if (
92
89
  not self.code_model.options["builders_visibility"] == "embedded"
93
- and self.operation_group_name
90
+ and self.group_name
94
91
  ):
95
- relative_path = "..." if self.operation_group_name else ".."
92
+ relative_path = "..." if self.group_name else ".."
96
93
  file_import.add_submodule_import(
97
94
  f"{relative_path}_vendor", "_format_url_section", ImportType.LOCAL
98
95
  )
@@ -104,70 +101,90 @@ class RequestBuilder(BaseBuilder):
104
101
  "typing", "Any", ImportType.STDLIB, typing_section=TypingSection.CONDITIONAL
105
102
  )
106
103
  file_import.add_submodule_import("msrest", "Serializer", ImportType.THIRDPARTY)
104
+ if (
105
+ self.overloads
106
+ and self.code_model.options["builders_visibility"] != "embedded"
107
+ ):
108
+ file_import.add_submodule_import("typing", "overload", ImportType.STDLIB)
107
109
  return file_import
108
110
 
109
- @classmethod
110
- def from_yaml(
111
- cls, yaml_data: Dict[str, Any], code_model: "CodeModel"
112
- ) -> "RequestBuilder":
111
+ @staticmethod
112
+ @abstractmethod
113
+ def parameter_list_type() -> Callable[
114
+ [Dict[str, Any], "CodeModel"], ParameterListType
115
+ ]:
116
+ ...
113
117
 
114
- # when combine embeded builders into one operation file, we need to avoid duplicated build function name.
118
+ @classmethod
119
+ def from_yaml(cls, yaml_data: Dict[str, Any], code_model: "CodeModel"):
120
+ # when combine embedded builders into one operation file, we need to avoid duplicated build function name.
115
121
  # So add operation group name is effective method
116
122
  additional_mark = ""
117
123
  if (
118
124
  code_model.options["combine_operation_files"]
119
125
  and code_model.options["builders_visibility"] == "embedded"
120
126
  ):
121
- additional_mark = yaml_data["language"]["python"]["builderGroupName"]
127
+ additional_mark = yaml_data["groupName"]
122
128
  names = [
123
129
  "build",
124
130
  additional_mark,
125
- yaml_data["language"]["python"]["name"],
131
+ yaml_data["name"],
126
132
  "request",
127
133
  ]
128
134
  name = "_".join([n for n in names if n])
129
-
130
- first_request = yaml_data["requests"][0]
131
- schema_requests = [
132
- SchemaRequest.from_yaml(yaml, code_model=code_model)
133
- for yaml in yaml_data["requests"]
135
+ overloads = [
136
+ RequestBuilder.from_yaml(rb_yaml_data, code_model)
137
+ for rb_yaml_data in yaml_data.get("overloads", [])
134
138
  ]
135
- parameters, multiple_content_type_parameters = create_parameters(
136
- yaml_data, code_model, RequestBuilderParameter.from_yaml
137
- )
138
- parameter_list = RequestBuilderParameterList(
139
- code_model, parameters + multiple_content_type_parameters, schema_requests
140
- )
141
139
  abstract = False
140
+ parameter_list = cls.parameter_list_type()(yaml_data, code_model)
142
141
  if (
143
142
  code_model.options["version_tolerant"]
144
- or code_model.options["low_level_client"]
145
- ) and any(p for p in parameter_list if p.is_multipart or p.is_data_input):
143
+ and parameter_list.has_body
144
+ and isinstance(
145
+ parameter_list.body_parameter, RequestBuilderMultipartBodyParameter
146
+ )
147
+ ):
146
148
  _LOGGER.warning(
147
- 'Not going to generate request_builder "%s" because it has multipart / urlencoded '
148
- "body parameters. Multipart / urlencoded body parameters are not supported for version "
149
- "tolerant and low level generations right now. Please write your own custom operation "
150
- "in the _patch.py file following https://aka.ms/azsdk/python/dpcodegen/python/customize.",
149
+ 'Not going to generate operation "%s" because it has multipart / urlencoded body parameters. '
150
+ "Multipart / urlencoded body parameters are not supported for version tolerant generation right now. "
151
+ 'Please write your own custom operation in the "_patch.py" file '
152
+ "following https://aka.ms/azsdk/python/dpcodegen/python/customize",
151
153
  name,
152
154
  )
153
155
  abstract = True
154
156
 
155
- request_builder_class = cls(
157
+ return cls(
156
158
  yaml_data=yaml_data,
157
159
  code_model=code_model,
158
160
  name=name,
159
- url=first_request["protocol"]["http"]["path"],
160
- method=first_request["protocol"]["http"]["method"].upper(),
161
- multipart=first_request["protocol"]["http"].get("multipart", False),
162
- schema_requests=schema_requests,
163
161
  parameters=parameter_list,
164
- description=yaml_data["language"]["python"]["description"],
165
- responses=[
166
- SchemaResponse.from_yaml(yaml, code_model=code_model)
167
- for yaml in yaml_data.get("responses", [])
168
- ],
169
- summary=yaml_data["language"]["python"].get("summary"),
162
+ overloads=overloads,
170
163
  abstract=abstract,
171
164
  )
172
- parameter_list.add_body_kwargs()
173
- return request_builder_class
165
+
166
+
167
+ class RequestBuilder(RequestBuilderBase[RequestBuilderParameterList]):
168
+ @staticmethod
169
+ def parameter_list_type() -> Callable[
170
+ [Dict[str, Any], "CodeModel"], RequestBuilderParameterList
171
+ ]:
172
+ return RequestBuilderParameterList.from_yaml
173
+
174
+
175
+ class OverloadedRequestBuilder(
176
+ RequestBuilderBase[OverloadedRequestBuilderParameterList]
177
+ ):
178
+ @staticmethod
179
+ def parameter_list_type() -> Callable[
180
+ [Dict[str, Any], "CodeModel"], OverloadedRequestBuilderParameterList
181
+ ]:
182
+ return OverloadedRequestBuilderParameterList.from_yaml
183
+
184
+
185
+ def get_request_builder(
186
+ yaml_data: Dict[str, Any], code_model: "CodeModel"
187
+ ) -> Union[RequestBuilder, OverloadedRequestBuilder]:
188
+ if yaml_data.get("overloads"):
189
+ return OverloadedRequestBuilder.from_yaml(yaml_data, code_model)
190
+ return RequestBuilder.from_yaml(yaml_data, code_model)