@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
@@ -3,16 +3,17 @@
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
16
+ from .model_type import ModelType
16
17
 
17
18
 
18
19
  class Property(BaseModel): # pylint: disable=too-many-instance-attributes
@@ -20,173 +21,156 @@ class Property(BaseModel): # pylint: disable=too-many-instance-attributes
20
21
  self,
21
22
  yaml_data: Dict[str, Any],
22
23
  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,
24
+ type: BaseType,
30
25
  ) -> None:
31
26
  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)
27
+ self.rest_api_name: str = self.yaml_data["restApiName"]
28
+ self.client_name: str = self.yaml_data["clientName"]
29
+ self.type = type
30
+ self.optional: bool = self.yaml_data["optional"]
31
+ self.readonly: bool = self.yaml_data.get("readonly", False)
39
32
  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"]
33
+ self.client_default_value = yaml_data.get("clientDefaultValue", None)
34
+ if self.client_default_value is None:
35
+ self.client_default_value = self.type.client_default_value
36
+ self.flattened_names: List[str] = yaml_data.get("flattenedNames", [])
37
+
38
+ @property
39
+ def pylint_disable(self) -> str:
40
+ retval: str = ""
41
+ if self.yaml_data.get("pylintDisable"):
42
+ retval = add_to_pylint_disable(retval, self.yaml_data["pylintDisable"])
43
+ return retval
44
+
45
+ def description(self, *, is_operation_file: bool) -> str:
46
+ from .model_type import ModelType
47
+
48
+ description = self.yaml_data["description"]
49
+ if not (self.optional or self.client_default_value):
50
+ description = add_to_description(description, "Required.")
51
+ # don't want model type documentation as part of property doc
52
+ type_description = (
53
+ ""
54
+ if isinstance(self.type, ModelType)
55
+ else self.type.description(is_operation_file=is_operation_file)
48
56
  )
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
57
+ return add_to_description(description, type_description)
58
+
59
+ @property
60
+ def client_default_value_declaration(self) -> str:
61
+ if self.client_default_value is not None:
62
+ return self.type.get_declaration(self.client_default_value)
63
+ if self.type.client_default_value is not None:
64
+ return self.type.get_declaration(self.type.client_default_value)
65
+ return "None"
78
66
 
79
67
  @property
80
68
  def constant(self) -> bool:
81
69
  # this bool doesn't consider you to be constant if you are a discriminator
82
70
  # you also have to be required to be considered a constant
83
71
  return (
84
- isinstance(self.schema, ConstantSchema)
85
- and self.required
72
+ isinstance(self.type, ConstantType)
73
+ and not self.optional
86
74
  and not self.is_discriminator
87
75
  )
88
76
 
89
77
  @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:
78
+ def is_input(self):
79
+ return not (self.constant or self.readonly or self.is_discriminator)
80
+
81
+ @property
82
+ def serialization_type(self) -> str:
83
+ return self.type.serialization_type
84
+
85
+ def type_annotation(self, *, is_operation_file: bool = False) -> str:
86
+ if self.optional and self.client_default_value is None:
87
+ return f"Optional[{self.type.type_annotation(is_operation_file=is_operation_file)}]"
88
+ return self.type.type_annotation(is_operation_file=is_operation_file)
89
+
90
+ def get_json_template_representation(
91
+ self,
92
+ *,
93
+ optional: bool = True, # pylint: disable=unused-argument
94
+ client_default_value_declaration: Optional[str] = None,
95
+ description: Optional[str] = None,
96
+ ) -> Any:
97
+ if self.client_default_value:
98
+ client_default_value_declaration = self.type.get_declaration(
99
+ self.client_default_value
100
+ )
101
+ if self.description(is_operation_file=True):
102
+ description = self.description(is_operation_file=True)
103
+ return self.type.get_json_template_representation(
104
+ optional=self.optional,
105
+ client_default_value_declaration=client_default_value_declaration,
106
+ description=description,
107
+ )
108
+
109
+ def get_polymorphic_subtypes(self, polymorphic_subtypes: List["ModelType"]) -> None:
110
+ from .model_type import ModelType
111
+
112
+ if isinstance(self.type, ModelType):
113
+ is_polymorphic_subtype = (
114
+ self.type.discriminator_value and not self.type.discriminated_subtypes
115
+ )
116
+ if (
117
+ self.type.name not in (m.name for m in polymorphic_subtypes)
118
+ and is_polymorphic_subtype
119
+ ):
120
+ polymorphic_subtypes.append(self.type)
121
+
122
+ @property
123
+ def validation(self) -> Optional[Dict[str, Any]]:
124
+ retval: Dict[str, Any] = {}
125
+ if not self.optional:
93
126
  retval["required"] = True
94
127
  if self.readonly:
95
128
  retval["readonly"] = True
96
129
  if self.constant:
97
130
  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)
131
+ retval.update(self.type.validation or {})
103
132
  return retval or None
104
133
 
105
134
  @property
106
- def escaped_swagger_name(self) -> str:
107
- """Return the RestAPI name correctly escaped for serialization."""
135
+ def attribute_map(self) -> str:
108
136
  if self.flattened_names:
109
- return ".".join(n.replace(".", "\\\\.") for n in self.flattened_names)
110
- return self.original_swagger_name.replace(".", "\\\\.")
137
+ attribute_key = ".".join(
138
+ n.replace(".", "\\\\.") for n in self.flattened_names
139
+ )
140
+ else:
141
+ attribute_key = self.rest_api_name.replace(".", "\\\\.")
142
+ if self.type.xml_serialization_ctxt:
143
+ xml_metadata = f", 'xml': {{{self.type.xml_serialization_ctxt}}}"
144
+ else:
145
+ xml_metadata = ""
146
+ return f'"{self.client_name}": {{"key": "{attribute_key}", "type": "{self.serialization_type}"{xml_metadata}}},'
147
+
148
+ def imports(self) -> FileImport:
149
+ from .model_type import ModelType
150
+
151
+ file_import = self.type.imports(is_operation_file=False)
152
+ if self.optional and self.client_default_value is None:
153
+ file_import.add_submodule_import("typing", "Optional", ImportType.STDLIB)
154
+ if isinstance(self.type, ModelType):
155
+ file_import.add_submodule_import(
156
+ "..",
157
+ "models",
158
+ ImportType.LOCAL,
159
+ TypingSection.TYPING,
160
+ alias="_models",
161
+ )
162
+ return file_import
111
163
 
112
164
  @classmethod
113
165
  def from_yaml(
114
166
  cls,
115
167
  yaml_data: Dict[str, Any],
116
168
  code_model: "CodeModel",
117
- *,
118
- has_additional_properties: Optional[bool] = None,
119
169
  ) -> "Property":
120
- from . import build_schema # pylint: disable=import-outside-toplevel
170
+ from . import build_type # pylint: disable=import-outside-toplevel
121
171
 
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
172
  return cls(
127
173
  yaml_data=yaml_data,
128
174
  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"),
175
+ type=build_type(yaml_data["type"], code_model),
134
176
  )
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,171 +3,199 @@
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
14
- from .imports import FileImport, ImportType, TypingSection
15
- from .parameter import Parameter
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
+ )
24
+ from .imports import FileImport, ImportType, TypingSection, MsrestImportType
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/dpcodegen/python/send_request 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()
76
+ if self.abstract:
77
+ return file_import
78
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())
79
+ file_import.merge(parameter.imports(async_mode=False))
82
80
 
83
81
  file_import.add_submodule_import(
84
82
  "azure.core.rest",
85
83
  "HttpRequest",
86
84
  ImportType.AZURECORE,
87
85
  )
88
- if not self.abstract:
89
- if self.parameters.path:
90
- relative_path = ".."
91
- if (
92
- not self.code_model.options["builders_visibility"] == "embedded"
93
- and self.operation_group_name
94
- ):
95
- relative_path = "..." if self.operation_group_name else ".."
96
- file_import.add_submodule_import(
97
- f"{relative_path}_vendor", "_format_url_section", ImportType.LOCAL
98
- )
99
- if self.parameters.headers or self.parameters.query:
100
- file_import.add_submodule_import(
101
- "azure.core.utils", "case_insensitive_dict", ImportType.AZURECORE
102
- )
86
+
87
+ if self.parameters.path:
88
+ relative_path = ".."
89
+ if (
90
+ not self.code_model.options["builders_visibility"] == "embedded"
91
+ and self.group_name
92
+ ):
93
+ relative_path = "..." if self.group_name else ".."
94
+ file_import.add_submodule_import(
95
+ f"{relative_path}_vendor", "_format_url_section", ImportType.LOCAL
96
+ )
97
+ if self.parameters.headers or self.parameters.query:
98
+ file_import.add_submodule_import(
99
+ "azure.core.utils", "case_insensitive_dict", ImportType.AZURECORE
100
+ )
103
101
  file_import.add_submodule_import(
104
102
  "typing", "Any", ImportType.STDLIB, typing_section=TypingSection.CONDITIONAL
105
103
  )
106
- file_import.add_submodule_import("msrest", "Serializer", ImportType.THIRDPARTY)
104
+ file_import.add_msrest_import(
105
+ self.code_model,
106
+ "..."
107
+ if (
108
+ not self.code_model.options["builders_visibility"] == "embedded"
109
+ and self.group_name
110
+ )
111
+ else "..",
112
+ MsrestImportType.Serializer,
113
+ TypingSection.REGULAR,
114
+ )
115
+ if (
116
+ self.overloads
117
+ and self.code_model.options["builders_visibility"] != "embedded"
118
+ ):
119
+ file_import.add_submodule_import("typing", "overload", ImportType.STDLIB)
107
120
  return file_import
108
121
 
109
- @classmethod
110
- def from_yaml(
111
- cls, yaml_data: Dict[str, Any], code_model: "CodeModel"
112
- ) -> "RequestBuilder":
122
+ @staticmethod
123
+ @abstractmethod
124
+ def parameter_list_type() -> Callable[
125
+ [Dict[str, Any], "CodeModel"], ParameterListType
126
+ ]:
127
+ ...
113
128
 
114
- # when combine embeded builders into one operation file, we need to avoid duplicated build function name.
129
+ @classmethod
130
+ def from_yaml(cls, yaml_data: Dict[str, Any], code_model: "CodeModel"):
131
+ # when combine embedded builders into one operation file, we need to avoid duplicated build function name.
115
132
  # So add operation group name is effective method
116
133
  additional_mark = ""
117
134
  if (
118
135
  code_model.options["combine_operation_files"]
119
136
  and code_model.options["builders_visibility"] == "embedded"
120
137
  ):
121
- additional_mark = yaml_data["language"]["python"]["builderGroupName"]
138
+ additional_mark = yaml_data["groupName"]
122
139
  names = [
123
140
  "build",
124
141
  additional_mark,
125
- yaml_data["language"]["python"]["name"],
142
+ yaml_data["name"],
126
143
  "request",
127
144
  ]
128
145
  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"]
146
+ overloads = [
147
+ RequestBuilder.from_yaml(rb_yaml_data, code_model)
148
+ for rb_yaml_data in yaml_data.get("overloads", [])
134
149
  ]
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
150
  abstract = False
151
+ parameter_list = cls.parameter_list_type()(yaml_data, code_model)
142
152
  if (
143
153
  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):
154
+ and parameter_list.has_body
155
+ and isinstance(
156
+ parameter_list.body_parameter, RequestBuilderMultipartBodyParameter
157
+ )
158
+ ):
146
159
  _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.",
160
+ 'Not going to generate operation "%s" because it has multipart / urlencoded body parameters. '
161
+ "Multipart / urlencoded body parameters are not supported for version tolerant generation right now. "
162
+ 'Please write your own custom operation in the "_patch.py" file '
163
+ "following https://aka.ms/azsdk/python/dpcodegen/python/customize",
151
164
  name,
152
165
  )
153
166
  abstract = True
154
167
 
155
- request_builder_class = cls(
168
+ return cls(
156
169
  yaml_data=yaml_data,
157
170
  code_model=code_model,
158
171
  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
172
  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"),
173
+ overloads=overloads,
170
174
  abstract=abstract,
171
175
  )
172
- parameter_list.add_body_kwargs()
173
- return request_builder_class
176
+
177
+
178
+ class RequestBuilder(RequestBuilderBase[RequestBuilderParameterList]):
179
+ @staticmethod
180
+ def parameter_list_type() -> Callable[
181
+ [Dict[str, Any], "CodeModel"], RequestBuilderParameterList
182
+ ]:
183
+ return RequestBuilderParameterList.from_yaml
184
+
185
+
186
+ class OverloadedRequestBuilder(
187
+ RequestBuilderBase[OverloadedRequestBuilderParameterList]
188
+ ):
189
+ @staticmethod
190
+ def parameter_list_type() -> Callable[
191
+ [Dict[str, Any], "CodeModel"], OverloadedRequestBuilderParameterList
192
+ ]:
193
+ return OverloadedRequestBuilderParameterList.from_yaml
194
+
195
+
196
+ def get_request_builder(
197
+ yaml_data: Dict[str, Any], code_model: "CodeModel"
198
+ ) -> Union[RequestBuilder, OverloadedRequestBuilder]:
199
+ if yaml_data.get("overloads"):
200
+ return OverloadedRequestBuilder.from_yaml(yaml_data, code_model)
201
+ return RequestBuilder.from_yaml(yaml_data, code_model)