@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,141 +3,85 @@
|
|
|
3
3
|
# Licensed under the MIT License. See License.txt in the project root for
|
|
4
4
|
# license information.
|
|
5
5
|
# --------------------------------------------------------------------------
|
|
6
|
-
import
|
|
7
|
-
from enum import Enum
|
|
8
|
-
|
|
9
|
-
from typing import
|
|
10
|
-
|
|
11
|
-
|
|
6
|
+
import abc
|
|
7
|
+
from enum import Enum, auto
|
|
8
|
+
|
|
9
|
+
from typing import (
|
|
10
|
+
Dict,
|
|
11
|
+
Any,
|
|
12
|
+
TYPE_CHECKING,
|
|
13
|
+
List,
|
|
14
|
+
Optional,
|
|
15
|
+
TypeVar,
|
|
16
|
+
Union,
|
|
17
|
+
Generic,
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
from .imports import FileImport, ImportType
|
|
12
21
|
from .base_model import BaseModel
|
|
13
|
-
from .
|
|
14
|
-
from .
|
|
15
|
-
from .
|
|
16
|
-
|
|
17
|
-
|
|
22
|
+
from .base_type import BaseType
|
|
23
|
+
from .constant_type import ConstantType
|
|
24
|
+
from .utils import add_to_description
|
|
25
|
+
|
|
26
|
+
if TYPE_CHECKING:
|
|
27
|
+
from .code_model import CodeModel
|
|
28
|
+
from .request_builder_parameter import RequestBuilderBodyParameter
|
|
18
29
|
|
|
19
30
|
|
|
20
|
-
|
|
31
|
+
class ParameterLocation(str, Enum):
|
|
32
|
+
HEADER = "header"
|
|
33
|
+
PATH = "path"
|
|
34
|
+
ENDPOINT_PATH = "endpointPath"
|
|
35
|
+
QUERY = "query"
|
|
36
|
+
BODY = "body"
|
|
37
|
+
OTHER = "other"
|
|
21
38
|
|
|
22
|
-
_HIDDEN_KWARGS = ["content_type"]
|
|
23
39
|
|
|
40
|
+
class ParameterMethodLocation(Enum):
|
|
41
|
+
POSITIONAL = auto()
|
|
42
|
+
KEYWORD_ONLY = auto()
|
|
43
|
+
KWARG = auto()
|
|
24
44
|
|
|
25
|
-
class ParameterLocation(Enum):
|
|
26
|
-
Path = "path"
|
|
27
|
-
Body = "body"
|
|
28
|
-
Query = "query"
|
|
29
|
-
Header = "header"
|
|
30
|
-
Uri = "uri"
|
|
31
|
-
Other = "other"
|
|
32
45
|
|
|
46
|
+
class ParameterDelimeter(str, Enum):
|
|
47
|
+
SPACE = "space"
|
|
48
|
+
PIPE = "pipe"
|
|
49
|
+
TAB = "tab"
|
|
50
|
+
COMMA = "comma"
|
|
33
51
|
|
|
34
|
-
class ParameterStyle(Enum):
|
|
35
|
-
simple = "simple"
|
|
36
|
-
label = "label"
|
|
37
|
-
matrix = "matrix"
|
|
38
|
-
form = "form"
|
|
39
|
-
spaceDelimited = "spaceDelimited"
|
|
40
|
-
pipeDelimited = "pipeDelimited"
|
|
41
|
-
deepObject = "deepObject"
|
|
42
|
-
tabDelimited = "tabDelimited"
|
|
43
|
-
json = "json"
|
|
44
|
-
binary = "binary"
|
|
45
|
-
xml = "xml"
|
|
46
|
-
multipart = "multipart"
|
|
47
52
|
|
|
53
|
+
class _ParameterBase(
|
|
54
|
+
BaseModel, abc.ABC
|
|
55
|
+
): # pylint: disable=too-many-instance-attributes
|
|
56
|
+
"""Base class for all parameters"""
|
|
48
57
|
|
|
49
|
-
class Parameter(BaseModel): # pylint: disable=too-many-instance-attributes, too-many-public-methods
|
|
50
58
|
def __init__(
|
|
51
59
|
self,
|
|
52
|
-
code_model,
|
|
53
60
|
yaml_data: Dict[str, Any],
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
serialized_name: str,
|
|
57
|
-
description: str,
|
|
58
|
-
implementation: str,
|
|
59
|
-
required: bool,
|
|
60
|
-
location: ParameterLocation,
|
|
61
|
-
skip_url_encoding: bool,
|
|
62
|
-
constraints: List[Any],
|
|
63
|
-
target_property_name: Optional[Union[int, str]] = None, # first uses id as placeholder
|
|
64
|
-
style: Optional[ParameterStyle] = None,
|
|
65
|
-
explode: Optional[bool] = False,
|
|
66
|
-
*,
|
|
67
|
-
flattened: bool = False,
|
|
68
|
-
grouped_by: Optional["Parameter"] = None,
|
|
69
|
-
original_parameter: Optional["Parameter"] = None,
|
|
70
|
-
client_default_value: Optional[Any] = None,
|
|
71
|
-
keyword_only: Optional[bool] = None,
|
|
72
|
-
content_types: Optional[List[str]] = None,
|
|
61
|
+
code_model: "CodeModel",
|
|
62
|
+
type: BaseType,
|
|
73
63
|
) -> None:
|
|
74
|
-
super().__init__(yaml_data)
|
|
75
|
-
self.
|
|
76
|
-
self.
|
|
77
|
-
self.
|
|
78
|
-
self.
|
|
79
|
-
self.
|
|
80
|
-
self.
|
|
81
|
-
self.
|
|
82
|
-
self.
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
self.
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
self.
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
self.
|
|
92
|
-
self.
|
|
93
|
-
self.
|
|
94
|
-
self.
|
|
95
|
-
self._keyword_only = keyword_only
|
|
96
|
-
self.is_multipart = yaml_data.get("language", {}).get("python", {}).get("multipart", False)
|
|
97
|
-
self.is_data_input = yaml_data.get("isPartialBody", False) and not self.is_multipart
|
|
98
|
-
self.content_types = content_types or []
|
|
99
|
-
self.body_kwargs: List[Parameter] = []
|
|
100
|
-
self.is_body_kwarg = False
|
|
101
|
-
self.need_import = True
|
|
102
|
-
self.is_kwarg = (self.rest_api_name == "Content-Type" or (self.constant and self.rest_api_name != "Accept"))
|
|
103
|
-
|
|
104
|
-
def __hash__(self) -> int:
|
|
105
|
-
return hash(self.serialized_name)
|
|
106
|
-
|
|
107
|
-
@property
|
|
108
|
-
def description(self):
|
|
109
|
-
try:
|
|
110
|
-
description = self._description
|
|
111
|
-
if self.schema.extra_description_information:
|
|
112
|
-
if description:
|
|
113
|
-
description += " "
|
|
114
|
-
description += f"{self.schema.extra_description_information}"
|
|
115
|
-
if isinstance(self.schema, ConstantSchema) and not self.constant:
|
|
116
|
-
if description:
|
|
117
|
-
description += " "
|
|
118
|
-
description += f"Possible values are {self.schema.get_declaration(self.schema.value)} or {None}."
|
|
119
|
-
if self.has_default_value and not any(
|
|
120
|
-
l for l in ["default value is", "default is"] if l in description.lower()
|
|
121
|
-
):
|
|
122
|
-
description += f" Default value is {self.default_value_declaration}."
|
|
123
|
-
if self.constant:
|
|
124
|
-
description += " Note that overriding this default value may result in unsupported behavior."
|
|
125
|
-
return description
|
|
126
|
-
except AttributeError:
|
|
127
|
-
pass
|
|
128
|
-
return self._description
|
|
129
|
-
|
|
130
|
-
@description.setter
|
|
131
|
-
def description(self, val: str):
|
|
132
|
-
self._description = val
|
|
133
|
-
|
|
134
|
-
@property
|
|
135
|
-
def is_json_parameter(self) -> bool:
|
|
136
|
-
if self.is_multipart or self.is_data_input:
|
|
137
|
-
return False
|
|
138
|
-
if self.style == ParameterStyle.xml:
|
|
139
|
-
return False
|
|
140
|
-
return True
|
|
64
|
+
super().__init__(yaml_data, code_model)
|
|
65
|
+
self.rest_api_name: str = yaml_data["restApiName"]
|
|
66
|
+
self.client_name: str = self.yaml_data["clientName"]
|
|
67
|
+
self.optional: bool = self.yaml_data["optional"]
|
|
68
|
+
self.location: ParameterLocation = self.yaml_data["location"]
|
|
69
|
+
self.client_default_value = self.yaml_data.get("clientDefaultValue", None)
|
|
70
|
+
self.in_docstring = self.yaml_data.get("inDocstring", True)
|
|
71
|
+
self.type = type
|
|
72
|
+
if self.client_default_value is None:
|
|
73
|
+
self.client_default_value = self.type.client_default_value
|
|
74
|
+
# name of grouper if it is grouped by another parameter
|
|
75
|
+
self.grouped_by: Optional[str] = self.yaml_data.get("groupedBy")
|
|
76
|
+
# property matching property name to parameter name for grouping params
|
|
77
|
+
# and flattened body params
|
|
78
|
+
self.property_to_parameter_name: Optional[Dict[str, str]] = self.yaml_data.get(
|
|
79
|
+
"propertyToParameterName"
|
|
80
|
+
)
|
|
81
|
+
self.flattened: bool = self.yaml_data.get("flattened", False)
|
|
82
|
+
self.in_flattened_body: bool = self.yaml_data.get("inFlattenedBody", False)
|
|
83
|
+
self.grouper: bool = self.yaml_data.get("grouper", False)
|
|
84
|
+
self.check_client_input: bool = self.yaml_data.get("checkClientInput", False)
|
|
141
85
|
|
|
142
86
|
@property
|
|
143
87
|
def constant(self) -> bool:
|
|
@@ -145,260 +89,301 @@ class Parameter(BaseModel): # pylint: disable=too-many-instance-attributes, too
|
|
|
145
89
|
Checking to see if it's required, because if not, we don't consider it
|
|
146
90
|
a constant because it can have a value of None.
|
|
147
91
|
"""
|
|
148
|
-
|
|
149
|
-
if not self.schema.get("type") == "constant":
|
|
150
|
-
return False
|
|
151
|
-
else:
|
|
152
|
-
if not isinstance(self.schema, ConstantSchema):
|
|
153
|
-
return False
|
|
154
|
-
return self.required
|
|
92
|
+
return not self.optional and isinstance(self.type, ConstantType)
|
|
155
93
|
|
|
156
94
|
@property
|
|
157
|
-
def
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
95
|
+
def description(self) -> str:
|
|
96
|
+
base_description = self.yaml_data["description"]
|
|
97
|
+
type_description = self.type.description(is_operation_file=True)
|
|
98
|
+
if type_description:
|
|
99
|
+
base_description = add_to_description(base_description, type_description)
|
|
100
|
+
if self.optional and isinstance(self.type, ConstantType):
|
|
101
|
+
base_description = add_to_description(
|
|
102
|
+
base_description,
|
|
103
|
+
f"Known values are {self.type.get_declaration()} and None.",
|
|
104
|
+
)
|
|
105
|
+
if not (self.optional or self.client_default_value):
|
|
106
|
+
base_description = add_to_description(base_description, "Required.")
|
|
107
|
+
if self.client_default_value is not None:
|
|
108
|
+
base_description = add_to_description(
|
|
109
|
+
base_description,
|
|
110
|
+
f"Default value is {self.client_default_value_declaration}.",
|
|
111
|
+
)
|
|
112
|
+
if self.optional and self.client_default_value is None:
|
|
113
|
+
base_description = add_to_description(
|
|
114
|
+
base_description,
|
|
115
|
+
f"Default value is {self.client_default_value_declaration}.",
|
|
116
|
+
)
|
|
117
|
+
if self.constant:
|
|
118
|
+
base_description = add_to_description(
|
|
119
|
+
base_description,
|
|
120
|
+
"Note that overriding this default value may result in unsupported behavior.",
|
|
121
|
+
)
|
|
122
|
+
return base_description
|
|
165
123
|
|
|
166
124
|
@property
|
|
167
|
-
def
|
|
168
|
-
|
|
125
|
+
def client_default_value_declaration(self):
|
|
126
|
+
"""Declaration of parameter's client default value"""
|
|
127
|
+
if self.client_default_value is None:
|
|
128
|
+
return None
|
|
129
|
+
return self.type.get_declaration(self.client_default_value)
|
|
169
130
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
131
|
+
def type_annotation(self, **kwargs: Any) -> str:
|
|
132
|
+
kwargs["is_operation_file"] = True
|
|
133
|
+
type_annot = self.type.type_annotation(**kwargs)
|
|
134
|
+
if self.optional and self.client_default_value is None:
|
|
135
|
+
return f"Optional[{type_annot}]"
|
|
136
|
+
return type_annot
|
|
173
137
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
return self.location == ParameterLocation.Body
|
|
138
|
+
def docstring_text(self, **kwargs: Any) -> str:
|
|
139
|
+
return self.type.docstring_text(**kwargs)
|
|
177
140
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
"""Splits on semicolon of media types and returns the first half.
|
|
181
|
-
I.e. ["text/plain; charset=UTF-8"] -> ["text/plain"]
|
|
182
|
-
"""
|
|
183
|
-
return [content_type.split(";")[0] for content_type in self.content_types]
|
|
141
|
+
def docstring_type(self, **kwargs: Any) -> str:
|
|
142
|
+
return self.type.docstring_type(**kwargs)
|
|
184
143
|
|
|
185
144
|
@property
|
|
186
|
-
def
|
|
187
|
-
return
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
or self.grouped_by
|
|
194
|
-
# If I'm body and it's flattened, I'm not either
|
|
195
|
-
or (self.is_body and self.flattened)
|
|
145
|
+
def serialization_type(self) -> str:
|
|
146
|
+
return self.type.serialization_type
|
|
147
|
+
|
|
148
|
+
def imports(self, async_mode: bool, **kwargs: Any) -> FileImport:
|
|
149
|
+
file_import = FileImport()
|
|
150
|
+
file_import.merge(
|
|
151
|
+
self.type.imports(is_operation_file=True, async_mode=async_mode, **kwargs)
|
|
196
152
|
)
|
|
153
|
+
if self.optional and self.client_default_value is None:
|
|
154
|
+
file_import.add_submodule_import("typing", "Optional", ImportType.STDLIB)
|
|
155
|
+
return file_import
|
|
197
156
|
|
|
198
157
|
@property
|
|
199
|
-
def
|
|
200
|
-
|
|
201
|
-
raise ValueError("Should only be calling if your parameter is grouped")
|
|
202
|
-
try:
|
|
203
|
-
return next(
|
|
204
|
-
p for p in cast(ObjectSchema, self.grouped_by.schema).properties
|
|
205
|
-
if any(op for op in p.yaml_data['originalParameter'] if id(op) == self.id)
|
|
206
|
-
)
|
|
207
|
-
except StopIteration:
|
|
208
|
-
raise ValueError("There is not a corresponding grouped property for your parameter.")
|
|
158
|
+
def method_location(self) -> ParameterMethodLocation:
|
|
159
|
+
raise NotImplementedError("Please implement in children")
|
|
209
160
|
|
|
210
161
|
@property
|
|
211
|
-
def
|
|
212
|
-
return
|
|
162
|
+
def description_keyword(self) -> str:
|
|
163
|
+
return (
|
|
164
|
+
"param"
|
|
165
|
+
if self.method_location == ParameterMethodLocation.POSITIONAL
|
|
166
|
+
else "keyword"
|
|
167
|
+
)
|
|
213
168
|
|
|
214
169
|
@property
|
|
215
|
-
def
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
170
|
+
def docstring_type_keyword(self) -> str:
|
|
171
|
+
return (
|
|
172
|
+
"type"
|
|
173
|
+
if self.method_location == ParameterMethodLocation.POSITIONAL
|
|
174
|
+
else "paramtype"
|
|
175
|
+
)
|
|
220
176
|
|
|
221
177
|
@property
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
) and isinstance(self.schema, IOSchema)
|
|
226
|
-
|
|
227
|
-
def _default_value(self) -> Tuple[Optional[Any], str, str]:
|
|
228
|
-
type_annot = self.multiple_content_types_type_annot or self.schema.operation_type_annotation
|
|
229
|
-
if self._is_io_json:
|
|
230
|
-
type_annot = f"Union[{type_annot}, JSONType]"
|
|
231
|
-
any_types = ["Any", "JSONType"]
|
|
232
|
-
if not self.required and type_annot not in any_types and not self._is_io_json:
|
|
233
|
-
type_annot = f"Optional[{type_annot}]"
|
|
178
|
+
@abc.abstractmethod
|
|
179
|
+
def in_method_signature(self) -> bool:
|
|
180
|
+
...
|
|
234
181
|
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
if (self.required or
|
|
245
|
-
self.is_content_type or
|
|
246
|
-
not self.code_model.options["default_optional_constants_to_none"]):
|
|
247
|
-
default_value = self.schema.get_declaration(self.schema.value)
|
|
248
|
-
else:
|
|
249
|
-
default_value = None
|
|
250
|
-
default_value_declaration = default_value
|
|
251
|
-
else:
|
|
252
|
-
default_value = self.schema.default_value
|
|
253
|
-
default_value_declaration = self.schema.default_value_declaration
|
|
254
|
-
if default_value is not None and self.required:
|
|
255
|
-
_LOGGER.warning(
|
|
256
|
-
"Parameter '%s' is required and has a default value, this combination is not recommended",
|
|
257
|
-
self.rest_api_name
|
|
258
|
-
)
|
|
182
|
+
def method_signature(self, is_python3_file: bool, async_mode: bool) -> str:
|
|
183
|
+
type_annot = self.type_annotation(async_mode=async_mode)
|
|
184
|
+
if is_python3_file:
|
|
185
|
+
if self.client_default_value is not None or self.optional:
|
|
186
|
+
return f"{self.client_name}: {type_annot} = {self.client_default_value_declaration},"
|
|
187
|
+
return f"{self.client_name}: {type_annot},"
|
|
188
|
+
if self.client_default_value is not None or self.optional:
|
|
189
|
+
return f"{self.client_name}={self.client_default_value_declaration}, # type: {type_annot}"
|
|
190
|
+
return f"{self.client_name}, # type: {type_annot}"
|
|
259
191
|
|
|
260
|
-
return default_value, default_value_declaration, type_annot
|
|
261
192
|
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
return "keyword" if self.is_kwarg or self.is_keyword_only else "param"
|
|
193
|
+
class _BodyParameterBase(_ParameterBase):
|
|
194
|
+
"""Base class for body parameters"""
|
|
265
195
|
|
|
266
196
|
@property
|
|
267
|
-
def
|
|
268
|
-
|
|
197
|
+
def is_partial_body(self) -> bool:
|
|
198
|
+
"""Whether it's part of a bigger body parameter, i.e. a MultipartBodyParameter"""
|
|
199
|
+
return self.yaml_data.get("isPartialBody", False)
|
|
269
200
|
|
|
270
201
|
@property
|
|
271
|
-
def
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
202
|
+
def method_location(self) -> ParameterMethodLocation:
|
|
203
|
+
return (
|
|
204
|
+
ParameterMethodLocation.KWARG
|
|
205
|
+
if self.constant
|
|
206
|
+
else ParameterMethodLocation.POSITIONAL
|
|
207
|
+
)
|
|
275
208
|
|
|
276
209
|
@property
|
|
277
|
-
def
|
|
278
|
-
return self.
|
|
210
|
+
def in_method_signature(self) -> bool:
|
|
211
|
+
return not (self.flattened or self.grouped_by)
|
|
279
212
|
|
|
280
|
-
@property
|
|
281
|
-
def type_annotation(self) -> str:
|
|
282
|
-
return self._default_value()[2]
|
|
283
213
|
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
return self.schema.serialization_type
|
|
214
|
+
class BodyParameter(_BodyParameterBase):
|
|
215
|
+
"""Body parameter."""
|
|
287
216
|
|
|
288
217
|
@property
|
|
289
|
-
def
|
|
290
|
-
|
|
291
|
-
if self._is_io_json:
|
|
292
|
-
retval += " or JSONType"
|
|
293
|
-
return retval
|
|
218
|
+
def content_types(self) -> List[str]:
|
|
219
|
+
return self.yaml_data["contentTypes"]
|
|
294
220
|
|
|
295
221
|
@property
|
|
296
|
-
def
|
|
297
|
-
return self.
|
|
222
|
+
def default_content_type(self) -> str:
|
|
223
|
+
return self.yaml_data["defaultContentType"]
|
|
298
224
|
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
225
|
+
@classmethod
|
|
226
|
+
def from_yaml(
|
|
227
|
+
cls, yaml_data: Dict[str, Any], code_model: "CodeModel"
|
|
228
|
+
) -> "BodyParameter":
|
|
229
|
+
return cls(
|
|
230
|
+
yaml_data=yaml_data,
|
|
231
|
+
code_model=code_model,
|
|
232
|
+
type=code_model.lookup_type(id(yaml_data["type"])),
|
|
233
|
+
)
|
|
307
234
|
|
|
308
|
-
@property
|
|
309
|
-
def full_serialized_name(self) -> str:
|
|
310
|
-
origin_name = self.serialized_name
|
|
311
|
-
if self.implementation == "Client":
|
|
312
|
-
origin_name = f"self._config.{self.serialized_name}"
|
|
313
|
-
return origin_name
|
|
314
235
|
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
236
|
+
EntryBodyParameterType = TypeVar(
|
|
237
|
+
"EntryBodyParameterType", bound=Union[BodyParameter, "RequestBuilderBodyParameter"]
|
|
238
|
+
)
|
|
239
|
+
|
|
319
240
|
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
241
|
+
class _MultipartBodyParameter(Generic[EntryBodyParameterType], BodyParameter):
|
|
242
|
+
"""Base class for MultipartBodyParameter and RequestBuilderMultipartBodyParameter"""
|
|
243
|
+
|
|
244
|
+
def __init__(
|
|
245
|
+
self,
|
|
246
|
+
yaml_data: Dict[str, Any],
|
|
247
|
+
code_model: "CodeModel",
|
|
248
|
+
type: BaseType,
|
|
249
|
+
entries: List[EntryBodyParameterType],
|
|
250
|
+
) -> None:
|
|
251
|
+
super().__init__(yaml_data, code_model, type)
|
|
252
|
+
self.entries = entries
|
|
324
253
|
|
|
325
254
|
@property
|
|
326
|
-
def
|
|
327
|
-
|
|
328
|
-
|
|
255
|
+
def in_method_signature(self) -> bool:
|
|
256
|
+
# Right now, only legacy generates with multipart bodies
|
|
257
|
+
# and legacy generates with the multipart body arguments splatted out
|
|
258
|
+
return False
|
|
259
|
+
|
|
260
|
+
|
|
261
|
+
class MultipartBodyParameter(
|
|
262
|
+
_MultipartBodyParameter[BodyParameter] # pylint: disable=unsubscriptable-object
|
|
263
|
+
):
|
|
264
|
+
"""Multipart body parameter for Operation. Used for files and data input."""
|
|
265
|
+
|
|
266
|
+
@classmethod
|
|
267
|
+
def from_yaml(
|
|
268
|
+
cls, yaml_data: Dict[str, Any], code_model: "CodeModel"
|
|
269
|
+
) -> "MultipartBodyParameter":
|
|
270
|
+
return cls(
|
|
271
|
+
yaml_data=yaml_data,
|
|
272
|
+
code_model=code_model,
|
|
273
|
+
type=code_model.lookup_type(id(yaml_data["type"])),
|
|
274
|
+
entries=[
|
|
275
|
+
BodyParameter.from_yaml(entry, code_model)
|
|
276
|
+
for entry in yaml_data["entries"]
|
|
277
|
+
],
|
|
329
278
|
)
|
|
330
279
|
|
|
280
|
+
|
|
281
|
+
class Parameter(_ParameterBase):
|
|
282
|
+
"""Basic Parameter class"""
|
|
283
|
+
|
|
284
|
+
def __init__(
|
|
285
|
+
self,
|
|
286
|
+
yaml_data: Dict[str, Any],
|
|
287
|
+
code_model: "CodeModel",
|
|
288
|
+
type: BaseType,
|
|
289
|
+
) -> None:
|
|
290
|
+
super().__init__(yaml_data, code_model, type=type)
|
|
291
|
+
|
|
292
|
+
self.implementation: str = yaml_data["implementation"]
|
|
293
|
+
self.skip_url_encoding: bool = self.yaml_data.get("skipUrlEncoding", False)
|
|
294
|
+
self.explode: bool = self.yaml_data.get("explode", False)
|
|
295
|
+
self.in_overload: bool = self.yaml_data["inOverload"]
|
|
296
|
+
self.in_overriden: bool = self.yaml_data.get("inOverriden", False)
|
|
297
|
+
self.delimiter: Optional[ParameterDelimeter] = self.yaml_data.get("delimiter")
|
|
298
|
+
|
|
299
|
+
@property
|
|
300
|
+
def in_method_signature(self) -> bool:
|
|
301
|
+
return not (self.rest_api_name == "Accept" or self.grouped_by or self.flattened)
|
|
302
|
+
|
|
303
|
+
@property
|
|
304
|
+
def full_client_name(self) -> str:
|
|
305
|
+
if self.implementation == "Client":
|
|
306
|
+
return f"self._config.{self.client_name}"
|
|
307
|
+
return self.client_name
|
|
308
|
+
|
|
331
309
|
@property
|
|
332
|
-
def
|
|
333
|
-
return self.
|
|
310
|
+
def xml_serialization_ctxt(self) -> str:
|
|
311
|
+
return self.type.xml_serialization_ctxt or ""
|
|
334
312
|
|
|
335
313
|
@property
|
|
336
|
-
def
|
|
337
|
-
|
|
314
|
+
def method_location(self) -> ParameterMethodLocation:
|
|
315
|
+
if not self.in_method_signature:
|
|
316
|
+
raise ValueError(f"Parameter '{self.client_name}' is not in the method.")
|
|
317
|
+
if self.grouper:
|
|
318
|
+
return ParameterMethodLocation.POSITIONAL
|
|
319
|
+
if self.constant:
|
|
320
|
+
return ParameterMethodLocation.KWARG
|
|
321
|
+
if self.rest_api_name == "Content-Type":
|
|
322
|
+
if self.in_overload:
|
|
323
|
+
return ParameterMethodLocation.KEYWORD_ONLY
|
|
324
|
+
return ParameterMethodLocation.KWARG
|
|
325
|
+
query_or_header = self.location in (
|
|
326
|
+
ParameterLocation.HEADER,
|
|
327
|
+
ParameterLocation.QUERY,
|
|
328
|
+
)
|
|
329
|
+
if (
|
|
330
|
+
self.code_model.options["only_path_and_body_params_positional"]
|
|
331
|
+
and query_or_header
|
|
332
|
+
):
|
|
333
|
+
return ParameterMethodLocation.KEYWORD_ONLY
|
|
334
|
+
return ParameterMethodLocation.POSITIONAL
|
|
338
335
|
|
|
339
336
|
@classmethod
|
|
340
|
-
def from_yaml(
|
|
341
|
-
cls,
|
|
342
|
-
yaml_data: Dict[str, Any],
|
|
343
|
-
*,
|
|
344
|
-
code_model,
|
|
345
|
-
content_types: Optional[List[str]] = None
|
|
346
|
-
) -> "Parameter":
|
|
347
|
-
http_protocol = yaml_data["protocol"].get("http", {"in": ParameterLocation.Other})
|
|
337
|
+
def from_yaml(cls, yaml_data: Dict[str, Any], code_model: "CodeModel"):
|
|
348
338
|
return cls(
|
|
349
|
-
code_model=code_model,
|
|
350
339
|
yaml_data=yaml_data,
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
rest_api_name=yaml_data["language"]["default"].get(
|
|
354
|
-
"serializedName", yaml_data["language"]["default"]["name"]
|
|
355
|
-
),
|
|
356
|
-
serialized_name=yaml_data["language"]["python"]["name"],
|
|
357
|
-
description=yaml_data["language"]["python"]["description"],
|
|
358
|
-
implementation=yaml_data["implementation"],
|
|
359
|
-
required=yaml_data.get("required", False),
|
|
360
|
-
location=ParameterLocation(http_protocol["in"]),
|
|
361
|
-
skip_url_encoding=yaml_data.get("extensions", {}).get("x-ms-skip-url-encoding", False),
|
|
362
|
-
constraints=[], # FIXME constraints
|
|
363
|
-
target_property_name=id(yaml_data["targetProperty"]) if yaml_data.get("targetProperty") else None,
|
|
364
|
-
style=ParameterStyle(http_protocol["style"]) if "style" in http_protocol else None,
|
|
365
|
-
explode=http_protocol.get("explode", False),
|
|
366
|
-
grouped_by=yaml_data.get("groupedBy", None),
|
|
367
|
-
original_parameter=yaml_data.get("originalParameter", None),
|
|
368
|
-
flattened=yaml_data.get("flattened", False),
|
|
369
|
-
client_default_value=yaml_data.get("clientDefaultValue"),
|
|
370
|
-
content_types=content_types
|
|
340
|
+
code_model=code_model,
|
|
341
|
+
type=code_model.lookup_type(id(yaml_data["type"])),
|
|
371
342
|
)
|
|
372
343
|
|
|
373
|
-
def imports(self) -> FileImport:
|
|
374
|
-
file_import = self.schema.imports()
|
|
375
|
-
if not self.required:
|
|
376
|
-
file_import.add_submodule_import("typing", "Optional", ImportType.STDLIB, TypingSection.CONDITIONAL)
|
|
377
|
-
if self.has_multiple_content_types or self._is_io_json:
|
|
378
|
-
file_import.add_submodule_import("typing", "Union", ImportType.STDLIB, TypingSection.CONDITIONAL)
|
|
379
344
|
|
|
380
|
-
|
|
345
|
+
class ClientParameter(Parameter):
|
|
346
|
+
"""Client parameter"""
|
|
381
347
|
|
|
382
|
-
|
|
348
|
+
@property
|
|
349
|
+
def is_host(self) -> bool:
|
|
350
|
+
return self.rest_api_name == "$host"
|
|
383
351
|
|
|
384
352
|
@property
|
|
385
|
-
def
|
|
386
|
-
if self.
|
|
387
|
-
return
|
|
388
|
-
|
|
389
|
-
self.
|
|
390
|
-
self.
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
353
|
+
def method_location(self) -> ParameterMethodLocation:
|
|
354
|
+
if self.constant:
|
|
355
|
+
return ParameterMethodLocation.KWARG
|
|
356
|
+
if self.is_host and (
|
|
357
|
+
self.code_model.options["version_tolerant"]
|
|
358
|
+
or self.code_model.options["low_level_client"]
|
|
359
|
+
):
|
|
360
|
+
# this means i am the base url
|
|
361
|
+
return ParameterMethodLocation.KEYWORD_ONLY
|
|
362
|
+
return ParameterMethodLocation.POSITIONAL
|
|
363
|
+
|
|
395
364
|
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
self._keyword_only = val
|
|
399
|
-
self.is_kwarg = False
|
|
365
|
+
class ConfigParameter(Parameter):
|
|
366
|
+
"""Config Parameter"""
|
|
400
367
|
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
return
|
|
404
|
-
|
|
368
|
+
@property
|
|
369
|
+
def in_method_signature(self) -> bool:
|
|
370
|
+
return not self.is_host
|
|
371
|
+
|
|
372
|
+
@property
|
|
373
|
+
def is_host(self) -> bool:
|
|
374
|
+
return self.rest_api_name == "$host"
|
|
375
|
+
|
|
376
|
+
@property
|
|
377
|
+
def method_location(self) -> ParameterMethodLocation:
|
|
378
|
+
if self.constant:
|
|
379
|
+
return ParameterMethodLocation.KWARG
|
|
380
|
+
return ParameterMethodLocation.POSITIONAL
|
|
381
|
+
|
|
382
|
+
|
|
383
|
+
def get_body_parameter(
|
|
384
|
+
yaml_data: Dict[str, Any], code_model: "CodeModel"
|
|
385
|
+
) -> Union[BodyParameter, MultipartBodyParameter]:
|
|
386
|
+
"""Creates a regular body parameter or Multipart body parameter"""
|
|
387
|
+
if yaml_data.get("entries"):
|
|
388
|
+
return MultipartBodyParameter.from_yaml(yaml_data, code_model)
|
|
389
|
+
return BodyParameter.from_yaml(yaml_data, code_model)
|