@autorest/python 5.14.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 (120) hide show
  1. package/ChangeLog.md +91 -2
  2. package/README.md +30 -4
  3. package/autorest/__init__.py +2 -3
  4. package/autorest/black/__init__.py +12 -5
  5. package/autorest/codegen/__init__.py +130 -179
  6. package/autorest/codegen/models/__init__.py +122 -78
  7. package/autorest/codegen/models/base_builder.py +70 -72
  8. package/autorest/codegen/models/base_model.py +7 -5
  9. package/autorest/codegen/models/{base_schema.py → base_type.py} +62 -49
  10. package/autorest/codegen/models/client.py +195 -36
  11. package/autorest/codegen/models/code_model.py +165 -299
  12. package/autorest/codegen/models/combined_type.py +107 -0
  13. package/autorest/codegen/models/constant_type.py +122 -0
  14. package/autorest/codegen/models/credential_types.py +224 -0
  15. package/autorest/codegen/models/dictionary_type.py +116 -0
  16. package/autorest/codegen/models/enum_type.py +195 -0
  17. package/autorest/codegen/models/imports.py +95 -41
  18. package/autorest/codegen/models/list_type.py +134 -0
  19. package/autorest/codegen/models/lro_operation.py +90 -133
  20. package/autorest/codegen/models/lro_paging_operation.py +28 -12
  21. package/autorest/codegen/models/model_type.py +239 -0
  22. package/autorest/codegen/models/operation.py +415 -241
  23. package/autorest/codegen/models/operation_group.py +82 -88
  24. package/autorest/codegen/models/paging_operation.py +101 -117
  25. package/autorest/codegen/models/parameter.py +307 -322
  26. package/autorest/codegen/models/parameter_list.py +366 -357
  27. package/autorest/codegen/models/primitive_types.py +544 -0
  28. package/autorest/codegen/models/property.py +122 -134
  29. package/autorest/codegen/models/request_builder.py +138 -86
  30. package/autorest/codegen/models/request_builder_parameter.py +122 -79
  31. package/autorest/codegen/models/response.py +325 -0
  32. package/autorest/codegen/models/utils.py +17 -1
  33. package/autorest/codegen/serializers/__init__.py +242 -118
  34. package/autorest/codegen/serializers/builder_serializer.py +863 -1027
  35. package/autorest/codegen/serializers/client_serializer.py +148 -82
  36. package/autorest/codegen/serializers/general_serializer.py +44 -47
  37. package/autorest/codegen/serializers/import_serializer.py +96 -31
  38. package/autorest/codegen/serializers/metadata_serializer.py +39 -79
  39. package/autorest/codegen/serializers/model_base_serializer.py +65 -29
  40. package/autorest/codegen/serializers/model_generic_serializer.py +9 -10
  41. package/autorest/codegen/serializers/model_init_serializer.py +4 -2
  42. package/autorest/codegen/serializers/model_python3_serializer.py +29 -22
  43. package/autorest/codegen/serializers/operation_groups_serializer.py +21 -18
  44. package/autorest/codegen/serializers/operations_init_serializer.py +23 -11
  45. package/autorest/codegen/serializers/parameter_serializer.py +174 -0
  46. package/autorest/codegen/serializers/patch_serializer.py +14 -2
  47. package/autorest/codegen/serializers/request_builders_serializer.py +57 -0
  48. package/autorest/codegen/serializers/utils.py +0 -103
  49. package/autorest/codegen/templates/MANIFEST.in.jinja2 +1 -0
  50. package/autorest/codegen/templates/{service_client.py.jinja2 → client.py.jinja2} +7 -7
  51. package/autorest/codegen/templates/config.py.jinja2 +13 -13
  52. package/autorest/codegen/templates/enum.py.jinja2 +4 -4
  53. package/autorest/codegen/templates/enum_container.py.jinja2 +1 -2
  54. package/autorest/codegen/templates/init.py.jinja2 +9 -6
  55. package/autorest/codegen/templates/keywords.jinja2 +14 -1
  56. package/autorest/codegen/templates/lro_operation.py.jinja2 +6 -5
  57. package/autorest/codegen/templates/lro_paging_operation.py.jinja2 +6 -5
  58. package/autorest/codegen/templates/metadata.json.jinja2 +36 -35
  59. package/autorest/codegen/templates/model.py.jinja2 +23 -29
  60. package/autorest/codegen/templates/model_container.py.jinja2 +2 -1
  61. package/autorest/codegen/templates/model_init.py.jinja2 +9 -8
  62. package/autorest/codegen/templates/operation.py.jinja2 +10 -15
  63. package/autorest/codegen/templates/operation_group.py.jinja2 +14 -13
  64. package/autorest/codegen/templates/operation_groups_container.py.jinja2 +1 -2
  65. package/autorest/codegen/templates/operation_tools.jinja2 +8 -2
  66. package/autorest/codegen/templates/operations_folder_init.py.jinja2 +4 -0
  67. package/autorest/codegen/templates/paging_operation.py.jinja2 +7 -8
  68. package/autorest/codegen/templates/patch.py.jinja2 +18 -29
  69. package/autorest/codegen/templates/request_builder.py.jinja2 +20 -13
  70. package/autorest/codegen/templates/setup.py.jinja2 +9 -3
  71. package/autorest/codegen/templates/vendor.py.jinja2 +12 -2
  72. package/autorest/jsonrpc/__init__.py +7 -12
  73. package/autorest/jsonrpc/localapi.py +4 -3
  74. package/autorest/jsonrpc/server.py +28 -9
  75. package/autorest/jsonrpc/stdstream.py +13 -6
  76. package/autorest/m2r/__init__.py +5 -8
  77. package/autorest/m4reformatter/__init__.py +1108 -0
  78. package/autorest/multiapi/__init__.py +24 -14
  79. package/autorest/multiapi/models/client.py +21 -11
  80. package/autorest/multiapi/models/code_model.py +23 -10
  81. package/autorest/multiapi/models/config.py +4 -1
  82. package/autorest/multiapi/models/constant_global_parameter.py +1 -0
  83. package/autorest/multiapi/models/global_parameter.py +2 -1
  84. package/autorest/multiapi/models/global_parameters.py +14 -8
  85. package/autorest/multiapi/models/imports.py +35 -18
  86. package/autorest/multiapi/models/mixin_operation.py +5 -5
  87. package/autorest/multiapi/models/operation_group.py +2 -1
  88. package/autorest/multiapi/models/operation_mixin_group.py +21 -10
  89. package/autorest/multiapi/serializers/__init__.py +20 -25
  90. package/autorest/multiapi/serializers/import_serializer.py +47 -15
  91. package/autorest/multiapi/serializers/multiapi_serializer.py +17 -17
  92. package/autorest/multiapi/templates/multiapi_config.py.jinja2 +3 -3
  93. package/autorest/multiapi/templates/multiapi_init.py.jinja2 +2 -2
  94. package/autorest/multiapi/templates/multiapi_operations_mixin.py.jinja2 +4 -4
  95. package/autorest/multiapi/templates/multiapi_service_client.py.jinja2 +9 -9
  96. package/autorest/multiapi/utils.py +3 -3
  97. package/autorest/postprocess/__init__.py +202 -0
  98. package/autorest/postprocess/get_all.py +19 -0
  99. package/autorest/postprocess/venvtools.py +73 -0
  100. package/autorest/preprocess/__init__.py +209 -0
  101. package/autorest/preprocess/helpers.py +54 -0
  102. package/autorest/{namer → preprocess}/python_mappings.py +25 -32
  103. package/package.json +3 -3
  104. package/run-python3.js +2 -3
  105. package/venvtools.py +1 -1
  106. package/autorest/codegen/models/constant_schema.py +0 -97
  107. package/autorest/codegen/models/credential_schema.py +0 -90
  108. package/autorest/codegen/models/credential_schema_policy.py +0 -77
  109. package/autorest/codegen/models/dictionary_schema.py +0 -103
  110. package/autorest/codegen/models/enum_schema.py +0 -246
  111. package/autorest/codegen/models/list_schema.py +0 -113
  112. package/autorest/codegen/models/object_schema.py +0 -249
  113. package/autorest/codegen/models/primitive_schemas.py +0 -476
  114. package/autorest/codegen/models/request_builder_parameter_list.py +0 -280
  115. package/autorest/codegen/models/rest.py +0 -42
  116. package/autorest/codegen/models/schema_request.py +0 -45
  117. package/autorest/codegen/models/schema_response.py +0 -123
  118. package/autorest/codegen/serializers/rest_serializer.py +0 -57
  119. package/autorest/namer/__init__.py +0 -25
  120. package/autorest/namer/name_converter.py +0 -412
@@ -3,172 +3,160 @@
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
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
+
14
+ if TYPE_CHECKING:
15
+ from .code_model import CodeModel
16
+
13
17
 
14
18
  class Property(BaseModel): # pylint: disable=too-many-instance-attributes
15
19
  def __init__(
16
20
  self,
17
21
  yaml_data: Dict[str, Any],
18
- name: str,
19
- schema: BaseSchema,
20
- original_swagger_name: str,
21
- *,
22
- flattened_names: Optional[List[str]] = None,
23
- description: Optional[str] = None,
24
- client_default_value: Optional[Any] = None
22
+ code_model: "CodeModel",
23
+ type: BaseType,
25
24
  ) -> None:
26
- super().__init__(yaml_data)
27
- self.name = name
28
- self.schema = schema
29
- self.original_swagger_name = original_swagger_name
30
- self.flattened_names = flattened_names or []
31
-
32
- self.required: bool = yaml_data.get("required", False)
33
- self.readonly: bool = yaml_data.get("readOnly", False)
25
+ super().__init__(yaml_data, code_model)
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)
34
31
  self.is_discriminator: bool = yaml_data.get("isDiscriminator", False)
35
- self.client_default_value = client_default_value
36
- self.description = self._create_description(description, yaml_data)
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", [])
37
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)
55
+ )
56
+ return add_to_description(description, type_description)
38
57
 
39
- def _create_description(self, description_input: Optional[str], yaml_data: Dict[str, Any]) -> str:
40
- description: str = description_input or yaml_data["language"]["python"]["description"]
41
- if description and description[-1] != ".":
42
- description += "."
43
- if self.name == "tags":
44
- description = "A set of tags. " + description
45
- if self.constant:
46
- description += f' Has constant value: {self.constant_declaration}.'
47
- elif self.required:
48
- if description:
49
- description = "Required. " + description
50
- else:
51
- description = "Required. "
52
- elif isinstance(self.schema, ConstantSchema):
53
- description += (
54
- f" The only acceptable values to pass in are None and {self.constant_declaration}. " +
55
- f"The default value is {self.default_value_declaration}."
56
- )
57
- if self.is_discriminator:
58
- description += "Constant filled by server. "
59
- if isinstance(self.schema, EnumSchema):
60
- values = [self.schema.enum_type.get_declaration(v.value) for v in self.schema.values]
61
- if description and description[-1] != " ":
62
- description += " "
63
- description += "Possible values include: {}.".format(", ".join(values))
64
- if self.schema.default_value:
65
- description += f' Default value: "{self.schema.default_value}".'
66
- return description
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"
67
65
 
68
66
  @property
69
67
  def constant(self) -> bool:
70
68
  # this bool doesn't consider you to be constant if you are a discriminator
71
69
  # you also have to be required to be considered a constant
72
70
  return (
73
- isinstance(self.schema, ConstantSchema) and
74
- self.required and
75
- not self.is_discriminator
71
+ isinstance(self.type, ConstantType)
72
+ and not self.optional
73
+ and not self.is_discriminator
74
+ )
75
+
76
+ @property
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,
76
106
  )
77
107
 
78
108
  @property
79
- def validation_map(self) -> Optional[Dict[str, Union[bool, int, str]]]:
80
- retval: Dict[str, Union[bool, int, str]] = {}
81
- if self.required:
109
+ def validation(self) -> Optional[Dict[str, Any]]:
110
+ retval: Dict[str, Any] = {}
111
+ if not self.optional:
82
112
  retval["required"] = True
83
113
  if self.readonly:
84
114
  retval["readonly"] = True
85
115
  if self.constant:
86
116
  retval["constant"] = True
87
- if self.schema.validation_map:
88
- validation_map_from_schema = cast(Dict[str, Union[bool, int, str]], self.schema.validation_map)
89
- retval.update(validation_map_from_schema)
117
+ retval.update(self.type.validation or {})
90
118
  return retval or None
91
119
 
92
120
  @property
93
- def escaped_swagger_name(self) -> str:
94
- """Return the RestAPI name correctly escaped for serialization.
95
- """
121
+ def attribute_map(self) -> str:
96
122
  if self.flattened_names:
97
- return ".".join(n.replace(".", "\\\\.") for n in self.flattened_names)
98
- 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
99
149
 
100
150
  @classmethod
101
- def from_yaml(cls, yaml_data: Dict[str, Any], **kwargs) -> "Property":
102
- from . import build_schema # pylint: disable=import-outside-toplevel
103
-
104
- name = yaml_data["language"]["python"]["name"]
105
- has_additional_properties = kwargs.pop("has_additional_properties", None)
106
- if name == "additional_properties" and has_additional_properties:
107
- name = "additional_properties1"
108
- schema = build_schema(yaml_data=yaml_data["schema"], **kwargs)
151
+ def from_yaml(
152
+ cls,
153
+ yaml_data: Dict[str, Any],
154
+ code_model: "CodeModel",
155
+ ) -> "Property":
156
+ from . import build_type # pylint: disable=import-outside-toplevel
157
+
109
158
  return cls(
110
159
  yaml_data=yaml_data,
111
- name=name,
112
- schema=schema,
113
- original_swagger_name=yaml_data["serializedName"],
114
- flattened_names=yaml_data.get("flattenedNames", []),
115
- client_default_value=yaml_data.get("clientDefaultValue"),
160
+ code_model=code_model,
161
+ type=build_type(yaml_data["type"], code_model),
116
162
  )
117
-
118
- @property
119
- def is_input(self):
120
- return not (self.constant or self.readonly or self.is_discriminator)
121
-
122
- @property
123
- def constant_declaration(self) -> str:
124
- if self.schema:
125
- if isinstance(self.schema, ConstantSchema):
126
- return self.schema.get_declaration(self.schema.value)
127
- raise ValueError(
128
- "Trying to get constant declaration for a schema that is not ConstantSchema"
129
- )
130
- raise ValueError("Trying to get a declaration for a schema that doesn't exist")
131
-
132
- @property
133
- def serialization_type(self) -> str:
134
- return self.schema.serialization_type
135
-
136
- @property
137
- def xml_metadata(self) -> str:
138
- if self.schema.has_xml_serialization_ctxt:
139
- return f", 'xml': {{{self.schema.xml_serialization_ctxt()}}}"
140
- return ""
141
-
142
- @property
143
- def default_value(self) -> Any:
144
- return self.client_default_value or self.schema.default_value
145
-
146
- @property
147
- def default_value_declaration(self) -> Any:
148
- if self.client_default_value:
149
- return self.schema.get_declaration(self.client_default_value)
150
- return self.schema.default_value_declaration
151
-
152
- @property
153
- def type_annotation(self) -> str:
154
- if self.required:
155
- return self.schema.type_annotation
156
- return f"Optional[{self.schema.type_annotation}]"
157
-
158
- def get_json_template_representation(self, **kwargs: Any) -> Any:
159
- kwargs["optional"] = not self.required
160
- if self.default_value:
161
- kwargs["default_value_declaration"] = self.schema.get_declaration(self.default_value)
162
- if self.description:
163
- kwargs["description"] = self.description
164
- return self.schema.get_json_template_representation(**kwargs)
165
-
166
- def get_files_and_data_template_representation(self, **kwargs: Any) -> Any:
167
- kwargs["optional"] = not self.required
168
- return self.schema.get_files_and_data_template_representation(**kwargs)
169
-
170
- def model_file_imports(self) -> FileImport:
171
- file_import = self.schema.model_file_imports()
172
- if not self.required:
173
- file_import.add_submodule_import("typing", "Optional", ImportType.STDLIB, TypingSection.CONDITIONAL)
174
- return file_import
@@ -3,136 +3,188 @@
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
6
+ import logging
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
7
18
 
8
- from .base_builder import BaseBuilder, create_parameters
9
- from .request_builder_parameter import RequestBuilderParameter
10
- from .request_builder_parameter_list import RequestBuilderParameterList
11
- from .schema_request import SchemaRequest
12
- from .schema_response import SchemaResponse
19
+ from .base_builder import BaseBuilder
20
+ from .parameter_list import (
21
+ RequestBuilderParameterList,
22
+ OverloadedRequestBuilderParameterList,
23
+ )
13
24
  from .imports import FileImport, ImportType, TypingSection
14
- from .parameter import Parameter
25
+ from .request_builder_parameter import RequestBuilderMultipartBodyParameter
15
26
 
27
+ if TYPE_CHECKING:
28
+ from .code_model import CodeModel
16
29
 
17
- T = TypeVar('T')
18
- OrderedSet = Dict[T, None]
30
+ _LOGGER = logging.getLogger(__name__)
31
+ ParameterListType = TypeVar(
32
+ "ParameterListType",
33
+ bound=Union[RequestBuilderParameterList, OverloadedRequestBuilderParameterList],
34
+ )
19
35
 
20
- class RequestBuilder(BaseBuilder):
36
+
37
+ class RequestBuilderBase(BaseBuilder[ParameterListType]):
21
38
  def __init__(
22
39
  self,
23
- code_model,
24
40
  yaml_data: Dict[str, Any],
41
+ code_model: "CodeModel",
25
42
  name: str,
26
- url: str,
27
- method: str,
28
- multipart: bool,
29
- schema_requests: List[SchemaRequest],
30
- parameters: RequestBuilderParameterList,
31
- description: str,
32
- summary: str,
33
- responses: Optional[List[SchemaResponse]] = None,
34
- ):
43
+ parameters: ParameterListType,
44
+ *,
45
+ overloads: Optional[List["RequestBuilder"]] = None,
46
+ abstract: bool = False,
47
+ ) -> None:
35
48
  super().__init__(
36
49
  code_model=code_model,
37
50
  yaml_data=yaml_data,
38
51
  name=name,
39
- description=description,
40
52
  parameters=parameters,
41
- responses=responses,
42
- schema_requests=schema_requests,
43
- summary=summary,
53
+ overloads=overloads,
54
+ abstract=abstract,
55
+ want_tracing=False,
44
56
  )
45
- self.url = url
46
- self.method = method
47
- self.multipart = multipart
48
-
49
- @property
50
- def is_stream(self) -> bool:
51
- """Is the request we're preparing a stream, like an upload."""
52
- return any(request.is_stream_request for request in self.schema_requests)
57
+ self.overloads: List["RequestBuilder"] = overloads or []
58
+ self.url: str = yaml_data["url"]
59
+ self.method: str = yaml_data["method"]
53
60
 
54
- @property
55
- def body_kwargs_to_get(self) -> List[Parameter]:
56
- return self.parameters.body_kwargs_to_get
61
+ def response_type_annotation(self, **kwargs) -> str:
62
+ return "HttpRequest"
57
63
 
58
- @property
59
- def operation_group_name(self) -> str:
60
- return self.yaml_data["language"]["python"]["operationGroupName"]
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
+ )
61
70
 
62
- @property
63
- def builder_group_name(self) -> str:
64
- return self.yaml_data["language"]["python"]["builderGroupName"]
71
+ def response_docstring_type(self, **kwargs) -> str:
72
+ return "~azure.core.rest.HttpRequest"
65
73
 
66
74
  def imports(self) -> FileImport:
67
75
  file_import = FileImport()
68
- for parameter in self.parameters:
69
- if parameter.need_import:
70
- 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))
71
79
 
72
80
  file_import.add_submodule_import(
73
81
  "azure.core.rest",
74
82
  "HttpRequest",
75
83
  ImportType.AZURECORE,
76
84
  )
77
- if self.parameters.path:
78
- relative_path = ".."
79
- if not self.code_model.options["builders_visibility"] == "embedded" and self.operation_group_name:
80
- relative_path = "..." if self.operation_group_name else ".."
81
- file_import.add_submodule_import(
82
- f"{relative_path}_vendor", "_format_url_section", ImportType.LOCAL
83
- )
84
- if self.parameters.headers or self.parameters.query:
85
- file_import.add_submodule_import(
86
- "typing", "Dict", ImportType.STDLIB, typing_section=TypingSection.CONDITIONAL
87
- )
85
+ if not self.abstract:
86
+ if self.parameters.path:
87
+ relative_path = ".."
88
+ if (
89
+ not self.code_model.options["builders_visibility"] == "embedded"
90
+ and self.group_name
91
+ ):
92
+ relative_path = "..." if self.group_name else ".."
93
+ file_import.add_submodule_import(
94
+ f"{relative_path}_vendor", "_format_url_section", ImportType.LOCAL
95
+ )
96
+ if self.parameters.headers or self.parameters.query:
97
+ file_import.add_submodule_import(
98
+ "azure.core.utils", "case_insensitive_dict", ImportType.AZURECORE
99
+ )
88
100
  file_import.add_submodule_import(
89
101
  "typing", "Any", ImportType.STDLIB, typing_section=TypingSection.CONDITIONAL
90
102
  )
91
103
  file_import.add_submodule_import("msrest", "Serializer", ImportType.THIRDPARTY)
92
- if self.parameters.has_body and (
93
- self.code_model.options["builders_visibility"] != "embedded" or
94
- self.code_model.options["add_python3_operation_files"]
104
+ if (
105
+ self.overloads
106
+ and self.code_model.options["builders_visibility"] != "embedded"
95
107
  ):
96
- file_import.define_mypy_type("JSONType", "Any")
108
+ file_import.add_submodule_import("typing", "overload", ImportType.STDLIB)
97
109
  return file_import
98
110
 
99
- @classmethod
100
- def from_yaml(cls, yaml_data: Dict[str, Any], *, code_model) -> "RequestBuilder":
111
+ @staticmethod
112
+ @abstractmethod
113
+ def parameter_list_type() -> Callable[
114
+ [Dict[str, Any], "CodeModel"], ParameterListType
115
+ ]:
116
+ ...
101
117
 
102
- # 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.
103
121
  # So add operation group name is effective method
104
122
  additional_mark = ""
105
- if code_model.options["combine_operation_files"] and code_model.options["builders_visibility"] == "embedded":
106
- additional_mark = yaml_data["language"]["python"]["builderGroupName"]
123
+ if (
124
+ code_model.options["combine_operation_files"]
125
+ and code_model.options["builders_visibility"] == "embedded"
126
+ ):
127
+ additional_mark = yaml_data["groupName"]
107
128
  names = [
108
129
  "build",
109
130
  additional_mark,
110
- yaml_data["language"]["python"]["name"],
111
- "request"
131
+ yaml_data["name"],
132
+ "request",
112
133
  ]
113
134
  name = "_".join([n for n in names if n])
135
+ overloads = [
136
+ RequestBuilder.from_yaml(rb_yaml_data, code_model)
137
+ for rb_yaml_data in yaml_data.get("overloads", [])
138
+ ]
139
+ abstract = False
140
+ parameter_list = cls.parameter_list_type()(yaml_data, code_model)
141
+ if (
142
+ code_model.options["version_tolerant"]
143
+ and parameter_list.has_body
144
+ and isinstance(
145
+ parameter_list.body_parameter, RequestBuilderMultipartBodyParameter
146
+ )
147
+ ):
148
+ _LOGGER.warning(
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",
153
+ name,
154
+ )
155
+ abstract = True
114
156
 
115
- first_request = yaml_data["requests"][0]
116
- schema_requests = [SchemaRequest.from_yaml(yaml, code_model=code_model) for yaml in yaml_data["requests"]]
117
- parameters, multiple_content_type_parameters = (
118
- create_parameters(yaml_data, code_model, RequestBuilderParameter.from_yaml)
119
- )
120
- parameter_list = RequestBuilderParameterList(
121
- code_model, parameters + multiple_content_type_parameters, schema_requests
122
- )
123
- request_builder_class = cls(
124
- code_model=code_model,
157
+ return cls(
125
158
  yaml_data=yaml_data,
159
+ code_model=code_model,
126
160
  name=name,
127
- url=first_request["protocol"]["http"]["path"],
128
- method=first_request["protocol"]["http"]["method"].upper(),
129
- multipart=first_request["protocol"]["http"].get("multipart", False),
130
- schema_requests=schema_requests,
131
161
  parameters=parameter_list,
132
- description=yaml_data["language"]["python"]["description"],
133
- responses=[SchemaResponse.from_yaml(yaml) for yaml in yaml_data.get("responses", [])],
134
- summary=yaml_data["language"]["python"].get("summary"),
162
+ overloads=overloads,
163
+ abstract=abstract,
135
164
  )
136
- code_model.request_builder_ids[id(yaml_data)] = request_builder_class
137
- parameter_list.add_body_kwargs()
138
- 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)