@autorest/python 5.15.0 → 5.18.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 (118) hide show
  1. package/ChangeLog.md +98 -4
  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 +122 -211
  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} +68 -45
  10. package/autorest/codegen/models/client.py +193 -40
  11. package/autorest/codegen/models/code_model.py +145 -245
  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 +131 -0
  16. package/autorest/codegen/models/enum_type.py +195 -0
  17. package/autorest/codegen/models/imports.py +93 -41
  18. package/autorest/codegen/models/list_type.py +149 -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 +262 -0
  22. package/autorest/codegen/models/operation.py +412 -259
  23. package/autorest/codegen/models/operation_group.py +80 -91
  24. package/autorest/codegen/models/paging_operation.py +101 -117
  25. package/autorest/codegen/models/parameter.py +302 -341
  26. package/autorest/codegen/models/parameter_list.py +373 -357
  27. package/autorest/codegen/models/primitive_types.py +544 -0
  28. package/autorest/codegen/models/property.py +136 -134
  29. package/autorest/codegen/models/request_builder.py +138 -86
  30. package/autorest/codegen/models/request_builder_parameter.py +122 -86
  31. package/autorest/codegen/models/response.py +325 -0
  32. package/autorest/codegen/models/utils.py +13 -17
  33. package/autorest/codegen/serializers/__init__.py +212 -112
  34. package/autorest/codegen/serializers/builder_serializer.py +931 -1040
  35. package/autorest/codegen/serializers/client_serializer.py +140 -84
  36. package/autorest/codegen/serializers/general_serializer.py +26 -50
  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 +62 -34
  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 -19
  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 +4 -1
  47. package/autorest/codegen/serializers/request_builders_serializer.py +57 -0
  48. package/autorest/codegen/serializers/utils.py +0 -126
  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 -1
  54. package/autorest/codegen/templates/init.py.jinja2 +3 -3
  55. package/autorest/codegen/templates/lro_operation.py.jinja2 +6 -5
  56. package/autorest/codegen/templates/lro_paging_operation.py.jinja2 +6 -5
  57. package/autorest/codegen/templates/metadata.json.jinja2 +36 -35
  58. package/autorest/codegen/templates/model.py.jinja2 +23 -24
  59. package/autorest/codegen/templates/model_container.py.jinja2 +2 -1
  60. package/autorest/codegen/templates/model_init.py.jinja2 +3 -5
  61. package/autorest/codegen/templates/operation.py.jinja2 +10 -14
  62. package/autorest/codegen/templates/operation_group.py.jinja2 +9 -15
  63. package/autorest/codegen/templates/operation_groups_container.py.jinja2 +1 -1
  64. package/autorest/codegen/templates/operation_tools.jinja2 +8 -2
  65. package/autorest/codegen/templates/paging_operation.py.jinja2 +7 -8
  66. package/autorest/codegen/templates/request_builder.py.jinja2 +19 -10
  67. package/autorest/codegen/templates/setup.py.jinja2 +9 -3
  68. package/autorest/codegen/templates/vendor.py.jinja2 +1 -1
  69. package/autorest/jsonrpc/__init__.py +7 -12
  70. package/autorest/jsonrpc/localapi.py +4 -3
  71. package/autorest/jsonrpc/server.py +28 -9
  72. package/autorest/jsonrpc/stdstream.py +13 -6
  73. package/autorest/m2r/__init__.py +5 -8
  74. package/autorest/m4reformatter/__init__.py +1126 -0
  75. package/autorest/multiapi/__init__.py +24 -14
  76. package/autorest/multiapi/models/client.py +21 -11
  77. package/autorest/multiapi/models/code_model.py +23 -10
  78. package/autorest/multiapi/models/config.py +4 -1
  79. package/autorest/multiapi/models/constant_global_parameter.py +1 -0
  80. package/autorest/multiapi/models/global_parameter.py +2 -1
  81. package/autorest/multiapi/models/global_parameters.py +14 -8
  82. package/autorest/multiapi/models/imports.py +24 -17
  83. package/autorest/multiapi/models/mixin_operation.py +5 -5
  84. package/autorest/multiapi/models/operation_group.py +2 -1
  85. package/autorest/multiapi/models/operation_mixin_group.py +21 -10
  86. package/autorest/multiapi/serializers/__init__.py +20 -25
  87. package/autorest/multiapi/serializers/import_serializer.py +47 -17
  88. package/autorest/multiapi/serializers/multiapi_serializer.py +17 -17
  89. package/autorest/multiapi/templates/multiapi_config.py.jinja2 +3 -3
  90. package/autorest/multiapi/templates/multiapi_init.py.jinja2 +2 -2
  91. package/autorest/multiapi/templates/multiapi_operations_mixin.py.jinja2 +4 -4
  92. package/autorest/multiapi/templates/multiapi_service_client.py.jinja2 +9 -9
  93. package/autorest/multiapi/utils.py +3 -3
  94. package/autorest/postprocess/__init__.py +202 -0
  95. package/autorest/postprocess/get_all.py +19 -0
  96. package/autorest/postprocess/venvtools.py +73 -0
  97. package/autorest/preprocess/__init__.py +210 -0
  98. package/autorest/preprocess/helpers.py +54 -0
  99. package/autorest/{namer → preprocess}/python_mappings.py +25 -32
  100. package/package.json +3 -3
  101. package/run-python3.js +2 -3
  102. package/venvtools.py +1 -1
  103. package/autorest/codegen/models/constant_schema.py +0 -101
  104. package/autorest/codegen/models/credential_model.py +0 -47
  105. package/autorest/codegen/models/credential_schema.py +0 -91
  106. package/autorest/codegen/models/credential_schema_policy.py +0 -77
  107. package/autorest/codegen/models/dictionary_schema.py +0 -103
  108. package/autorest/codegen/models/enum_schema.py +0 -215
  109. package/autorest/codegen/models/list_schema.py +0 -123
  110. package/autorest/codegen/models/object_schema.py +0 -253
  111. package/autorest/codegen/models/primitive_schemas.py +0 -466
  112. package/autorest/codegen/models/request_builder_parameter_list.py +0 -280
  113. package/autorest/codegen/models/rest.py +0 -42
  114. package/autorest/codegen/models/schema_request.py +0 -45
  115. package/autorest/codegen/models/schema_response.py +0 -136
  116. package/autorest/codegen/serializers/rest_serializer.py +0 -57
  117. package/autorest/namer/__init__.py +0 -25
  118. package/autorest/namer/name_converter.py +0 -412
@@ -3,172 +3,174 @@
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
+ from .model_type import ModelType
17
+
13
18
 
14
19
  class Property(BaseModel): # pylint: disable=too-many-instance-attributes
15
20
  def __init__(
16
21
  self,
17
22
  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
23
+ code_model: "CodeModel",
24
+ type: BaseType,
25
25
  ) -> 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)
26
+ super().__init__(yaml_data, code_model)
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)
34
32
  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)
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
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)
56
+ )
57
+ return add_to_description(description, type_description)
38
58
 
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 += "Known values are: {}.".format(", ".join(values))
64
- if self.schema.default_value:
65
- description += f' Default value: "{self.schema.default_value}".'
66
- return description
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"
67
66
 
68
67
  @property
69
68
  def constant(self) -> bool:
70
69
  # this bool doesn't consider you to be constant if you are a discriminator
71
70
  # you also have to be required to be considered a constant
72
71
  return (
73
- isinstance(self.schema, ConstantSchema) and
74
- self.required and
75
- not self.is_discriminator
72
+ isinstance(self.type, ConstantType)
73
+ and not self.optional
74
+ and not self.is_discriminator
75
+ )
76
+
77
+ @property
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,
76
107
  )
77
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
+
78
122
  @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:
123
+ def validation(self) -> Optional[Dict[str, Any]]:
124
+ retval: Dict[str, Any] = {}
125
+ if not self.optional:
82
126
  retval["required"] = True
83
127
  if self.readonly:
84
128
  retval["readonly"] = True
85
129
  if self.constant:
86
130
  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)
131
+ retval.update(self.type.validation or {})
90
132
  return retval or None
91
133
 
92
134
  @property
93
- def escaped_swagger_name(self) -> str:
94
- """Return the RestAPI name correctly escaped for serialization.
95
- """
135
+ def attribute_map(self) -> str:
96
136
  if self.flattened_names:
97
- return ".".join(n.replace(".", "\\\\.") for n in self.flattened_names)
98
- 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
99
163
 
100
164
  @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)
165
+ def from_yaml(
166
+ cls,
167
+ yaml_data: Dict[str, Any],
168
+ code_model: "CodeModel",
169
+ ) -> "Property":
170
+ from . import build_type # pylint: disable=import-outside-toplevel
171
+
109
172
  return cls(
110
173
  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"),
174
+ code_model=code_model,
175
+ type=build_type(yaml_data["type"], code_model),
116
176
  )
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
- def type_annotation(self, *, is_operation_file: bool = False) -> str:
153
- if self.required:
154
- return self.schema.type_annotation(is_operation_file=is_operation_file)
155
- return f"Optional[{self.schema.type_annotation(is_operation_file=is_operation_file)}]"
156
-
157
- def get_json_template_representation(self, **kwargs: Any) -> Any:
158
- kwargs["optional"] = not self.required
159
- if self.default_value:
160
- kwargs["default_value_declaration"] = self.schema.get_declaration(self.default_value)
161
- if self.description:
162
- kwargs["description"] = self.description
163
- return self.schema.get_json_template_representation(**kwargs)
164
-
165
- def get_files_and_data_template_representation(self, **kwargs: Any) -> Any:
166
- kwargs["optional"] = not self.required
167
- return self.schema.get_files_and_data_template_representation(**kwargs)
168
-
169
- def model_file_imports(self) -> FileImport:
170
- file_import = self.schema.model_file_imports()
171
- if not self.required:
172
- file_import.add_submodule_import("typing", "Optional", ImportType.STDLIB, TypingSection.CONDITIONAL)
173
- file_import.merge(self.schema.model_file_imports())
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/dpcodegen/python/send_request 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("azure.core.utils", "case_insensitive_dict", ImportType.AZURECORE)
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
+ )
86
100
  file_import.add_submodule_import(
87
101
  "typing", "Any", ImportType.STDLIB, typing_section=TypingSection.CONDITIONAL
88
102
  )
89
103
  file_import.add_submodule_import("msrest", "Serializer", ImportType.THIRDPARTY)
90
- if self.parameters.has_body and (
91
- self.code_model.options["builders_visibility"] != "embedded" or
92
- self.code_model.options["add_python3_operation_files"]
104
+ if (
105
+ self.overloads
106
+ and self.code_model.options["builders_visibility"] != "embedded"
93
107
  ):
94
- file_import.define_mypy_type("JSONType", "Any")
108
+ file_import.add_submodule_import("typing", "overload", ImportType.STDLIB)
95
109
  return file_import
96
110
 
97
- @classmethod
98
- 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
+ ...
99
117
 
100
- # 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.
101
121
  # So add operation group name is effective method
102
122
  additional_mark = ""
103
- if code_model.options["combine_operation_files"] and code_model.options["builders_visibility"] == "embedded":
104
- 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"]
105
128
  names = [
106
129
  "build",
107
130
  additional_mark,
108
- yaml_data["language"]["python"]["name"],
109
- "request"
131
+ yaml_data["name"],
132
+ "request",
110
133
  ]
111
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
112
156
 
113
- first_request = yaml_data["requests"][0]
114
- schema_requests = [SchemaRequest.from_yaml(yaml, code_model=code_model) for yaml in yaml_data["requests"]]
115
- parameters, multiple_content_type_parameters = (
116
- create_parameters(yaml_data, code_model, RequestBuilderParameter.from_yaml)
117
- )
118
- parameter_list = RequestBuilderParameterList(
119
- code_model, parameters + multiple_content_type_parameters, schema_requests
120
- )
121
- request_builder_class = cls(
122
- code_model=code_model,
157
+ return cls(
123
158
  yaml_data=yaml_data,
159
+ code_model=code_model,
124
160
  name=name,
125
- url=first_request["protocol"]["http"]["path"],
126
- method=first_request["protocol"]["http"]["method"].upper(),
127
- multipart=first_request["protocol"]["http"].get("multipart", False),
128
- schema_requests=schema_requests,
129
161
  parameters=parameter_list,
130
- description=yaml_data["language"]["python"]["description"],
131
- responses=[
132
- SchemaResponse.from_yaml(yaml, code_model=code_model) for yaml in yaml_data.get("responses", [])
133
- ],
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)