@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.
- package/ChangeLog.md +91 -2
- package/README.md +30 -4
- package/autorest/__init__.py +2 -3
- package/autorest/black/__init__.py +12 -5
- package/autorest/codegen/__init__.py +130 -179
- package/autorest/codegen/models/__init__.py +122 -78
- package/autorest/codegen/models/base_builder.py +70 -72
- package/autorest/codegen/models/base_model.py +7 -5
- package/autorest/codegen/models/{base_schema.py → base_type.py} +62 -49
- package/autorest/codegen/models/client.py +195 -36
- package/autorest/codegen/models/code_model.py +165 -299
- package/autorest/codegen/models/combined_type.py +107 -0
- package/autorest/codegen/models/constant_type.py +122 -0
- package/autorest/codegen/models/credential_types.py +224 -0
- package/autorest/codegen/models/dictionary_type.py +116 -0
- package/autorest/codegen/models/enum_type.py +195 -0
- package/autorest/codegen/models/imports.py +95 -41
- package/autorest/codegen/models/list_type.py +134 -0
- package/autorest/codegen/models/lro_operation.py +90 -133
- package/autorest/codegen/models/lro_paging_operation.py +28 -12
- package/autorest/codegen/models/model_type.py +239 -0
- package/autorest/codegen/models/operation.py +415 -241
- package/autorest/codegen/models/operation_group.py +82 -88
- package/autorest/codegen/models/paging_operation.py +101 -117
- package/autorest/codegen/models/parameter.py +307 -322
- package/autorest/codegen/models/parameter_list.py +366 -357
- package/autorest/codegen/models/primitive_types.py +544 -0
- package/autorest/codegen/models/property.py +122 -134
- package/autorest/codegen/models/request_builder.py +138 -86
- package/autorest/codegen/models/request_builder_parameter.py +122 -79
- package/autorest/codegen/models/response.py +325 -0
- package/autorest/codegen/models/utils.py +17 -1
- package/autorest/codegen/serializers/__init__.py +242 -118
- package/autorest/codegen/serializers/builder_serializer.py +863 -1027
- package/autorest/codegen/serializers/client_serializer.py +148 -82
- package/autorest/codegen/serializers/general_serializer.py +44 -47
- package/autorest/codegen/serializers/import_serializer.py +96 -31
- package/autorest/codegen/serializers/metadata_serializer.py +39 -79
- package/autorest/codegen/serializers/model_base_serializer.py +65 -29
- package/autorest/codegen/serializers/model_generic_serializer.py +9 -10
- package/autorest/codegen/serializers/model_init_serializer.py +4 -2
- package/autorest/codegen/serializers/model_python3_serializer.py +29 -22
- package/autorest/codegen/serializers/operation_groups_serializer.py +21 -18
- package/autorest/codegen/serializers/operations_init_serializer.py +23 -11
- package/autorest/codegen/serializers/parameter_serializer.py +174 -0
- package/autorest/codegen/serializers/patch_serializer.py +14 -2
- package/autorest/codegen/serializers/request_builders_serializer.py +57 -0
- package/autorest/codegen/serializers/utils.py +0 -103
- package/autorest/codegen/templates/MANIFEST.in.jinja2 +1 -0
- package/autorest/codegen/templates/{service_client.py.jinja2 → client.py.jinja2} +7 -7
- package/autorest/codegen/templates/config.py.jinja2 +13 -13
- package/autorest/codegen/templates/enum.py.jinja2 +4 -4
- package/autorest/codegen/templates/enum_container.py.jinja2 +1 -2
- package/autorest/codegen/templates/init.py.jinja2 +9 -6
- package/autorest/codegen/templates/keywords.jinja2 +14 -1
- package/autorest/codegen/templates/lro_operation.py.jinja2 +6 -5
- package/autorest/codegen/templates/lro_paging_operation.py.jinja2 +6 -5
- package/autorest/codegen/templates/metadata.json.jinja2 +36 -35
- package/autorest/codegen/templates/model.py.jinja2 +23 -29
- package/autorest/codegen/templates/model_container.py.jinja2 +2 -1
- package/autorest/codegen/templates/model_init.py.jinja2 +9 -8
- package/autorest/codegen/templates/operation.py.jinja2 +10 -15
- package/autorest/codegen/templates/operation_group.py.jinja2 +14 -13
- package/autorest/codegen/templates/operation_groups_container.py.jinja2 +1 -2
- package/autorest/codegen/templates/operation_tools.jinja2 +8 -2
- package/autorest/codegen/templates/operations_folder_init.py.jinja2 +4 -0
- package/autorest/codegen/templates/paging_operation.py.jinja2 +7 -8
- package/autorest/codegen/templates/patch.py.jinja2 +18 -29
- package/autorest/codegen/templates/request_builder.py.jinja2 +20 -13
- package/autorest/codegen/templates/setup.py.jinja2 +9 -3
- package/autorest/codegen/templates/vendor.py.jinja2 +12 -2
- package/autorest/jsonrpc/__init__.py +7 -12
- package/autorest/jsonrpc/localapi.py +4 -3
- package/autorest/jsonrpc/server.py +28 -9
- package/autorest/jsonrpc/stdstream.py +13 -6
- package/autorest/m2r/__init__.py +5 -8
- package/autorest/m4reformatter/__init__.py +1108 -0
- package/autorest/multiapi/__init__.py +24 -14
- package/autorest/multiapi/models/client.py +21 -11
- package/autorest/multiapi/models/code_model.py +23 -10
- package/autorest/multiapi/models/config.py +4 -1
- package/autorest/multiapi/models/constant_global_parameter.py +1 -0
- package/autorest/multiapi/models/global_parameter.py +2 -1
- package/autorest/multiapi/models/global_parameters.py +14 -8
- package/autorest/multiapi/models/imports.py +35 -18
- package/autorest/multiapi/models/mixin_operation.py +5 -5
- package/autorest/multiapi/models/operation_group.py +2 -1
- package/autorest/multiapi/models/operation_mixin_group.py +21 -10
- package/autorest/multiapi/serializers/__init__.py +20 -25
- package/autorest/multiapi/serializers/import_serializer.py +47 -15
- package/autorest/multiapi/serializers/multiapi_serializer.py +17 -17
- package/autorest/multiapi/templates/multiapi_config.py.jinja2 +3 -3
- package/autorest/multiapi/templates/multiapi_init.py.jinja2 +2 -2
- package/autorest/multiapi/templates/multiapi_operations_mixin.py.jinja2 +4 -4
- package/autorest/multiapi/templates/multiapi_service_client.py.jinja2 +9 -9
- package/autorest/multiapi/utils.py +3 -3
- package/autorest/postprocess/__init__.py +202 -0
- package/autorest/postprocess/get_all.py +19 -0
- package/autorest/postprocess/venvtools.py +73 -0
- package/autorest/preprocess/__init__.py +209 -0
- package/autorest/preprocess/helpers.py +54 -0
- package/autorest/{namer → preprocess}/python_mappings.py +25 -32
- package/package.json +3 -3
- package/run-python3.js +2 -3
- package/venvtools.py +1 -1
- package/autorest/codegen/models/constant_schema.py +0 -97
- package/autorest/codegen/models/credential_schema.py +0 -90
- package/autorest/codegen/models/credential_schema_policy.py +0 -77
- package/autorest/codegen/models/dictionary_schema.py +0 -103
- package/autorest/codegen/models/enum_schema.py +0 -246
- package/autorest/codegen/models/list_schema.py +0 -113
- package/autorest/codegen/models/object_schema.py +0 -249
- package/autorest/codegen/models/primitive_schemas.py +0 -476
- package/autorest/codegen/models/request_builder_parameter_list.py +0 -280
- package/autorest/codegen/models/rest.py +0 -42
- package/autorest/codegen/models/schema_request.py +0 -45
- package/autorest/codegen/models/schema_response.py +0 -123
- package/autorest/codegen/serializers/rest_serializer.py +0 -57
- package/autorest/namer/__init__.py +0 -25
- 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
|
|
6
|
+
from typing import Any, Dict, Optional, TYPE_CHECKING, List
|
|
7
7
|
|
|
8
8
|
from .base_model import BaseModel
|
|
9
|
-
from .
|
|
9
|
+
from .constant_type import ConstantType
|
|
10
|
+
from .base_type import BaseType
|
|
10
11
|
from .imports import FileImport, ImportType, TypingSection
|
|
11
|
-
from .
|
|
12
|
-
|
|
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
|
-
|
|
19
|
-
|
|
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.
|
|
28
|
-
self.
|
|
29
|
-
self.
|
|
30
|
-
self.
|
|
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 =
|
|
36
|
-
self.
|
|
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
|
-
|
|
40
|
-
|
|
41
|
-
if
|
|
42
|
-
|
|
43
|
-
if self.
|
|
44
|
-
|
|
45
|
-
|
|
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.
|
|
74
|
-
self.
|
|
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
|
|
80
|
-
retval: Dict[str,
|
|
81
|
-
if self.
|
|
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
|
-
|
|
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
|
|
94
|
-
"""Return the RestAPI name correctly escaped for serialization.
|
|
95
|
-
"""
|
|
121
|
+
def attribute_map(self) -> str:
|
|
96
122
|
if self.flattened_names:
|
|
97
|
-
|
|
98
|
-
|
|
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(
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
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
|
-
|
|
112
|
-
|
|
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
|
-
|
|
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
|
|
9
|
-
from .
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
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 .
|
|
25
|
+
from .request_builder_parameter import RequestBuilderMultipartBodyParameter
|
|
15
26
|
|
|
27
|
+
if TYPE_CHECKING:
|
|
28
|
+
from .code_model import CodeModel
|
|
16
29
|
|
|
17
|
-
|
|
18
|
-
|
|
30
|
+
_LOGGER = logging.getLogger(__name__)
|
|
31
|
+
ParameterListType = TypeVar(
|
|
32
|
+
"ParameterListType",
|
|
33
|
+
bound=Union[RequestBuilderParameterList, OverloadedRequestBuilderParameterList],
|
|
34
|
+
)
|
|
19
35
|
|
|
20
|
-
|
|
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
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
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
|
-
|
|
42
|
-
|
|
43
|
-
|
|
53
|
+
overloads=overloads,
|
|
54
|
+
abstract=abstract,
|
|
55
|
+
want_tracing=False,
|
|
44
56
|
)
|
|
45
|
-
self.
|
|
46
|
-
self.
|
|
47
|
-
self.
|
|
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
|
-
|
|
55
|
-
|
|
56
|
-
return self.parameters.body_kwargs_to_get
|
|
61
|
+
def response_type_annotation(self, **kwargs) -> str:
|
|
62
|
+
return "HttpRequest"
|
|
57
63
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
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
|
-
|
|
63
|
-
|
|
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
|
-
|
|
69
|
-
|
|
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.
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
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
|
|
93
|
-
self.
|
|
94
|
-
self.code_model.options["
|
|
104
|
+
if (
|
|
105
|
+
self.overloads
|
|
106
|
+
and self.code_model.options["builders_visibility"] != "embedded"
|
|
95
107
|
):
|
|
96
|
-
file_import.
|
|
108
|
+
file_import.add_submodule_import("typing", "overload", ImportType.STDLIB)
|
|
97
109
|
return file_import
|
|
98
110
|
|
|
99
|
-
@
|
|
100
|
-
|
|
111
|
+
@staticmethod
|
|
112
|
+
@abstractmethod
|
|
113
|
+
def parameter_list_type() -> Callable[
|
|
114
|
+
[Dict[str, Any], "CodeModel"], ParameterListType
|
|
115
|
+
]:
|
|
116
|
+
...
|
|
101
117
|
|
|
102
|
-
|
|
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
|
|
106
|
-
|
|
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["
|
|
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
|
-
|
|
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
|
-
|
|
133
|
-
|
|
134
|
-
summary=yaml_data["language"]["python"].get("summary"),
|
|
162
|
+
overloads=overloads,
|
|
163
|
+
abstract=abstract,
|
|
135
164
|
)
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
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)
|