@autorest/python 5.11.0 → 5.12.1
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 +68 -0
- package/autorest/codegen/__init__.py +5 -5
- package/autorest/codegen/models/__init__.py +3 -23
- package/autorest/codegen/models/base_builder.py +2 -5
- package/autorest/codegen/models/client.py +5 -3
- package/autorest/codegen/models/code_model.py +14 -1
- package/autorest/codegen/models/operation_group.py +7 -7
- package/autorest/codegen/models/parameter.py +4 -3
- package/autorest/codegen/models/parameter_list.py +32 -27
- package/autorest/codegen/models/request_builder.py +5 -1
- package/autorest/codegen/models/request_builder_parameter.py +4 -3
- package/autorest/codegen/models/request_builder_parameter_list.py +18 -11
- package/autorest/codegen/models/rest.py +3 -2
- package/autorest/codegen/models/utils.py +8 -0
- package/autorest/codegen/serializers/__init__.py +52 -51
- package/autorest/codegen/serializers/builder_serializer.py +150 -146
- package/autorest/codegen/serializers/client_serializer.py +37 -9
- package/autorest/codegen/serializers/general_serializer.py +7 -5
- package/autorest/codegen/serializers/import_serializer.py +6 -6
- package/autorest/codegen/serializers/metadata_serializer.py +2 -2
- package/autorest/codegen/serializers/model_base_serializer.py +3 -3
- package/autorest/codegen/serializers/model_generic_serializer.py +1 -1
- package/autorest/codegen/serializers/model_python3_serializer.py +1 -1
- package/autorest/codegen/serializers/{operation_group_serializer.py → operation_groups_serializer.py} +27 -29
- package/autorest/codegen/serializers/operations_init_serializer.py +34 -2
- package/autorest/codegen/serializers/patch_serializer.py +15 -0
- package/autorest/codegen/serializers/rest_serializer.py +9 -4
- package/autorest/codegen/serializers/utils.py +2 -2
- package/autorest/codegen/templates/config.py.jinja2 +1 -11
- package/autorest/codegen/templates/init.py.jinja2 +4 -5
- package/autorest/codegen/templates/metadata.json.jinja2 +2 -2
- package/autorest/codegen/templates/model_init.py.jinja2 +1 -1
- package/autorest/codegen/templates/{operations_class.py.jinja2 → operation_group.py.jinja2} +2 -0
- package/autorest/codegen/templates/operation_groups_container.py.jinja2 +26 -0
- package/autorest/codegen/templates/operation_tools.jinja2 +7 -0
- package/autorest/codegen/templates/operations_folder_init.py.jinja2 +13 -0
- package/autorest/codegen/templates/patch.py.jinja2 +31 -0
- package/autorest/codegen/templates/request_builder.py.jinja2 +7 -2
- package/autorest/codegen/templates/request_builders.py.jinja2 +3 -3
- package/autorest/codegen/templates/setup.py.jinja2 +1 -1
- package/autorest/multiapi/serializers/__init__.py +3 -3
- package/autorest/multiapi/serializers/import_serializer.py +5 -5
- package/autorest/namer/name_converter.py +3 -1
- package/install.py +1 -0
- package/package.json +2 -2
- package/setup.py +1 -0
- package/autorest/codegen/templates/operations_class_mixin.py.jinja2 +0 -16
- package/autorest/codegen/templates/operations_container.py.jinja2 +0 -39
- package/autorest/codegen/templates/operations_container_init.py.jinja2 +0 -24
- package/autorest/codegen/templates/operations_container_mixin.py.jinja2 +0 -20
package/ChangeLog.md
CHANGED
|
@@ -1,5 +1,73 @@
|
|
|
1
1
|
# Change Log
|
|
2
2
|
|
|
3
|
+
### 2022-01-10 - 5.12.1
|
|
4
|
+
|
|
5
|
+
| Library | Min Version
|
|
6
|
+
| --------------- | -------
|
|
7
|
+
|`@autorest/core` | `3.6.2`
|
|
8
|
+
|`@autorest/modelerfour` | `4.19.1`
|
|
9
|
+
|`azure-core` dep of generated code | `1.20.1`
|
|
10
|
+
|`msrest` dep of generated code | `0.6.21`
|
|
11
|
+
|`azure-mgmt-core` dep of generated code (If generating mgmt plane code) | `1.3.0`
|
|
12
|
+
|
|
13
|
+
**Bug Fixes**
|
|
14
|
+
|
|
15
|
+
- Fix support for json merge patch #1117
|
|
16
|
+
|
|
17
|
+
### 2021-12-06 - 5.12.0
|
|
18
|
+
|
|
19
|
+
| Library | Min Version
|
|
20
|
+
| --------------- | -------
|
|
21
|
+
|`@autorest/core` | `3.6.2`
|
|
22
|
+
|`@autorest/modelerfour` | `4.19.1`
|
|
23
|
+
|`azure-core` dep of generated code | `1.20.1`
|
|
24
|
+
|`msrest` dep of generated code | `0.6.21`
|
|
25
|
+
|`azure-mgmt-core` dep of generated code (If generating mgmt plane code) | `1.3.0`
|
|
26
|
+
|
|
27
|
+
**Breaking Changes in Version Tolerant Generation**
|
|
28
|
+
|
|
29
|
+
- Remove metadata property for version tolerant and low level client generations #1090
|
|
30
|
+
- Generate SDKs with `--python3-only` defaulting to `True` for version tolerant and low level client #1087
|
|
31
|
+
|
|
32
|
+
**New Features**
|
|
33
|
+
|
|
34
|
+
- Generate a `_patch.py` file if one does not exist. These files are used to customize the generated code #1092
|
|
35
|
+
|
|
36
|
+
**Bug Fixes**
|
|
37
|
+
|
|
38
|
+
- Can now handle body params with names `json`, `content`, `data`, and `files` #1081
|
|
39
|
+
- Improve generated templates for `data` and `files` input body params by adding quotes around the keys #1082
|
|
40
|
+
- Using flag `--python3-only` will get you typed sync client and config files #1085
|
|
41
|
+
- Pin `mistune` dependency to less than `2.x.x` so autorest can be successfully installed #1106
|
|
42
|
+
|
|
43
|
+
### 2021-11-05 - 5.11.2
|
|
44
|
+
|
|
45
|
+
| Library | Min Version
|
|
46
|
+
| --------------- | -------
|
|
47
|
+
|`@autorest/core` | `3.6.2`
|
|
48
|
+
|`@autorest/modelerfour` | `4.19.1`
|
|
49
|
+
|`azure-core` dep of generated code | `1.20.0`
|
|
50
|
+
|`msrest` dep of generated code | `0.6.21`
|
|
51
|
+
|`azure-mgmt-core` dep of generated code (If generating mgmt plane code) | `1.3.0`
|
|
52
|
+
|
|
53
|
+
**Bug Fixes**
|
|
54
|
+
|
|
55
|
+
- Respect no client side validation for low level client generations #1080
|
|
56
|
+
|
|
57
|
+
### 2021-11-05 - 5.11.1
|
|
58
|
+
|
|
59
|
+
| Library | Min Version
|
|
60
|
+
| --------------- | -------
|
|
61
|
+
|`@autorest/core` | `3.6.2`
|
|
62
|
+
|`@autorest/modelerfour` | `4.19.1`
|
|
63
|
+
|`azure-core` dep of generated code | `1.20.0`
|
|
64
|
+
|`msrest` dep of generated code | `0.6.21`
|
|
65
|
+
|`azure-mgmt-core` dep of generated code (If generating mgmt plane code) | `1.3.0`
|
|
66
|
+
|
|
67
|
+
**Bug Fixes**
|
|
68
|
+
|
|
69
|
+
- Hide mixin operations for version tolerant generation #1071
|
|
70
|
+
|
|
3
71
|
### 2021-11-04 - 5.11.0
|
|
4
72
|
|
|
5
73
|
| Library | Min Version
|
|
@@ -60,7 +60,7 @@ def _validate_code_model_options(options: Dict[str, Any]) -> None:
|
|
|
60
60
|
"to 'public' or 'hidden'."
|
|
61
61
|
)
|
|
62
62
|
|
|
63
|
-
if not options["show_operations"] and options["
|
|
63
|
+
if not options["show_operations"] and options["add_python3_operation_files"]:
|
|
64
64
|
raise ValueError(
|
|
65
65
|
"Can not add typed sync operation files if you are not showing operations. "
|
|
66
66
|
"If you want typed synced operation files, you have to add flag "
|
|
@@ -256,7 +256,7 @@ class CodeGenerator(Plugin):
|
|
|
256
256
|
version_tolerant = self._autorestapi.get_boolean_value("version-tolerant", False)
|
|
257
257
|
show_operations = self._autorestapi.get_boolean_value("show-operations", not low_level_client)
|
|
258
258
|
models_mode_default = "none" if low_level_client or version_tolerant else "msrest"
|
|
259
|
-
|
|
259
|
+
python3_only = self._autorestapi.get_boolean_value("python3-only", low_level_client or version_tolerant)
|
|
260
260
|
|
|
261
261
|
options: Dict[str, Any] = {
|
|
262
262
|
"azure_arm": azure_arm,
|
|
@@ -282,13 +282,13 @@ class CodeGenerator(Plugin):
|
|
|
282
282
|
"only_path_and_body_params_positional": self._autorestapi.get_boolean_value(
|
|
283
283
|
"only-path-and-body-params-positional", low_level_client or version_tolerant
|
|
284
284
|
),
|
|
285
|
-
"
|
|
286
|
-
"add-python3-operation-files",
|
|
285
|
+
"add_python3_operation_files": self._autorestapi.get_boolean_value(
|
|
286
|
+
"add-python3-operation-files", python3_only and not low_level_client
|
|
287
287
|
),
|
|
288
288
|
"version_tolerant": version_tolerant,
|
|
289
289
|
"low_level_client": low_level_client,
|
|
290
290
|
"combine_operation_files": self._autorestapi.get_boolean_value("combine-operation-files", version_tolerant),
|
|
291
|
-
"
|
|
291
|
+
"python3_only": python3_only,
|
|
292
292
|
}
|
|
293
293
|
|
|
294
294
|
if options["builders_visibility"] is None:
|
|
@@ -3,7 +3,7 @@
|
|
|
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
|
|
6
|
+
from typing import Any, Dict
|
|
7
7
|
from .base_model import BaseModel
|
|
8
8
|
from .code_model import CodeModel
|
|
9
9
|
from .credential_schema import AzureKeyCredentialSchema, TokenCredentialSchema
|
|
@@ -22,8 +22,7 @@ from .operation import Operation
|
|
|
22
22
|
from .property import Property
|
|
23
23
|
from .operation_group import OperationGroup
|
|
24
24
|
from .schema_response import SchemaResponse
|
|
25
|
-
from .parameter_list import
|
|
26
|
-
from .request_builder_parameter_list import RequestBuilderParameterList
|
|
25
|
+
from .parameter_list import ParameterList, GlobalParameterList
|
|
27
26
|
from .request_builder import RequestBuilder
|
|
28
27
|
from .base_builder import BaseBuilder
|
|
29
28
|
from .lro_paging_operation import LROPagingOperation
|
|
@@ -63,6 +62,7 @@ __all__ = [
|
|
|
63
62
|
"HiddenModelObjectSchema",
|
|
64
63
|
"ParameterStyle",
|
|
65
64
|
"IOSchema",
|
|
65
|
+
"GlobalParameterList",
|
|
66
66
|
]
|
|
67
67
|
|
|
68
68
|
def _generate_as_object_schema(yaml_data: Dict[str, Any]) -> bool:
|
|
@@ -119,23 +119,3 @@ def build_schema(yaml_data: Dict[str, Any], **kwargs) -> BaseSchema:
|
|
|
119
119
|
code_model.primitives[yaml_id] = schema
|
|
120
120
|
|
|
121
121
|
return schema
|
|
122
|
-
|
|
123
|
-
BuilderType = TypeVar(
|
|
124
|
-
"BuilderType",
|
|
125
|
-
bound=Union[
|
|
126
|
-
RequestBuilder,
|
|
127
|
-
Operation,
|
|
128
|
-
LROPagingOperation,
|
|
129
|
-
LROOperation,
|
|
130
|
-
PagingOperation,
|
|
131
|
-
]
|
|
132
|
-
)
|
|
133
|
-
|
|
134
|
-
ParameterListType = TypeVar(
|
|
135
|
-
"ParameterListType",
|
|
136
|
-
bound=Union[
|
|
137
|
-
ParameterList,
|
|
138
|
-
GlobalParameterList,
|
|
139
|
-
RequestBuilderParameterList,
|
|
140
|
-
],
|
|
141
|
-
)
|
|
@@ -3,14 +3,11 @@
|
|
|
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, Callable, Dict, List, Optional, Union
|
|
6
|
+
from typing import Any, Callable, Dict, List, Optional, Union
|
|
7
7
|
from .base_model import BaseModel
|
|
8
8
|
from .schema_response import SchemaResponse
|
|
9
9
|
from .schema_request import SchemaRequest
|
|
10
10
|
|
|
11
|
-
if TYPE_CHECKING:
|
|
12
|
-
from . import ParameterListType
|
|
13
|
-
|
|
14
11
|
|
|
15
12
|
_M4_HEADER_PARAMETERS = ["content_type", "accept"]
|
|
16
13
|
|
|
@@ -70,7 +67,7 @@ class BaseBuilder(BaseModel):
|
|
|
70
67
|
yaml_data: Dict[str, Any],
|
|
71
68
|
name: str,
|
|
72
69
|
description: str,
|
|
73
|
-
parameters
|
|
70
|
+
parameters,
|
|
74
71
|
schema_requests: List[SchemaRequest],
|
|
75
72
|
responses: Optional[List[SchemaResponse]] = None,
|
|
76
73
|
summary: Optional[str] = None,
|
|
@@ -73,7 +73,9 @@ class Client:
|
|
|
73
73
|
)
|
|
74
74
|
file_import.add_from_import("azure.core.rest", "HttpRequest", ImportType.AZURECORE, TypingSection.CONDITIONAL)
|
|
75
75
|
for og in self.code_model.operation_groups:
|
|
76
|
-
file_import.add_from_import(
|
|
76
|
+
file_import.add_from_import(
|
|
77
|
+
f".{self.code_model.operations_folder_name}", og.class_name, ImportType.LOCAL
|
|
78
|
+
)
|
|
77
79
|
|
|
78
80
|
if self.code_model.sorted_schemas:
|
|
79
81
|
path_to_models = ".." if async_mode else "."
|
|
@@ -94,6 +96,6 @@ class Client:
|
|
|
94
96
|
pass
|
|
95
97
|
return file_import
|
|
96
98
|
|
|
97
|
-
def send_request_signature(self, async_mode) -> List[str]:
|
|
99
|
+
def send_request_signature(self, async_mode: bool, is_python3_file: bool) -> List[str]:
|
|
98
100
|
request_signature = ["request: HttpRequest," if async_mode else "request, # type: HttpRequest"]
|
|
99
|
-
return request_signature + self.parameters.method_signature_kwargs(
|
|
101
|
+
return request_signature + self.parameters.method_signature_kwargs(is_python3_file)
|
|
@@ -29,7 +29,7 @@ from .rest import Rest
|
|
|
29
29
|
|
|
30
30
|
_LOGGER = logging.getLogger(__name__)
|
|
31
31
|
|
|
32
|
-
class CodeModel: # pylint: disable=too-many-instance-attributes
|
|
32
|
+
class CodeModel: # pylint: disable=too-many-instance-attributes, too-many-public-methods
|
|
33
33
|
"""Holds all of the information we have parsed out of the yaml file. The CodeModel is what gets
|
|
34
34
|
serialized by the serializers.
|
|
35
35
|
|
|
@@ -203,6 +203,10 @@ class CodeModel: # pylint: disable=too-many-instance-attributes
|
|
|
203
203
|
operation for operation in operation_group.operations if operation not in next_operations
|
|
204
204
|
]
|
|
205
205
|
|
|
206
|
+
@property
|
|
207
|
+
def has_schemas(self):
|
|
208
|
+
return self.schemas or self.enums
|
|
209
|
+
|
|
206
210
|
@property
|
|
207
211
|
def default_authentication_policy(self) -> Type[CredentialSchemaPolicy]:
|
|
208
212
|
return ARMChallengeAuthenticationPolicy if self.options['azure_arm'] else BearerTokenCredentialPolicy
|
|
@@ -238,6 +242,15 @@ class CodeModel: # pylint: disable=too-many-instance-attributes
|
|
|
238
242
|
|
|
239
243
|
return properties
|
|
240
244
|
|
|
245
|
+
@property
|
|
246
|
+
def operations_folder_name(self) -> str:
|
|
247
|
+
name = "operations"
|
|
248
|
+
if self.options["version_tolerant"] and not any(
|
|
249
|
+
og for og in self.operation_groups if not og.is_empty_operation_group
|
|
250
|
+
):
|
|
251
|
+
name = f"_{name}"
|
|
252
|
+
return name
|
|
253
|
+
|
|
241
254
|
def _add_properties_from_inheritance(self) -> None:
|
|
242
255
|
"""Adds properties from base classes to schemas with parents.
|
|
243
256
|
|
|
@@ -56,7 +56,7 @@ class OperationGroup(BaseModel):
|
|
|
56
56
|
file_import.merge(operation.imports_for_multiapi(async_mode))
|
|
57
57
|
return file_import
|
|
58
58
|
|
|
59
|
-
def imports(self, async_mode: bool
|
|
59
|
+
def imports(self, async_mode: bool) -> FileImport:
|
|
60
60
|
file_import = FileImport()
|
|
61
61
|
file_import.add_from_import("azure.core.exceptions", "ClientAuthenticationError", ImportType.AZURECORE)
|
|
62
62
|
file_import.add_from_import("azure.core.exceptions", "ResourceNotFoundError", ImportType.AZURECORE)
|
|
@@ -73,7 +73,7 @@ class OperationGroup(BaseModel):
|
|
|
73
73
|
"azure.core.tracing.decorator", "distributed_trace", ImportType.AZURECORE,
|
|
74
74
|
)
|
|
75
75
|
local_path = "..." if async_mode else ".."
|
|
76
|
-
if has_schemas and self.code_model.options["models_mode"]:
|
|
76
|
+
if self.code_model.has_schemas and self.code_model.options["models_mode"]:
|
|
77
77
|
file_import.add_from_import(local_path, "models", ImportType.LOCAL, alias="_models")
|
|
78
78
|
if self.code_model.options["builders_visibility"] == "embedded" and async_mode:
|
|
79
79
|
if not self.code_model.options["combine_operation_files"]:
|
|
@@ -85,8 +85,11 @@ class OperationGroup(BaseModel):
|
|
|
85
85
|
else:
|
|
86
86
|
operation_group_builders = self.code_model.rest.request_builders
|
|
87
87
|
for request_builder in operation_group_builders:
|
|
88
|
+
python3_only = self.code_model.options["python3_only"]
|
|
89
|
+
typed_sync_operation_file = self.code_model.options["add_python3_operation_files"]
|
|
90
|
+
suffix = "_py3" if typed_sync_operation_file and not python3_only else ""
|
|
88
91
|
file_import.add_from_import(
|
|
89
|
-
f"...
|
|
92
|
+
f"...{self.code_model.operations_folder_name}.{self.filename}{suffix}",
|
|
90
93
|
request_builder.name,
|
|
91
94
|
import_type=ImportType.LOCAL
|
|
92
95
|
)
|
|
@@ -101,14 +104,11 @@ class OperationGroup(BaseModel):
|
|
|
101
104
|
|
|
102
105
|
@property
|
|
103
106
|
def filename(self) -> str:
|
|
104
|
-
if self.code_model.options["combine_operation_files"]:
|
|
105
|
-
return "_operations"
|
|
106
|
-
|
|
107
107
|
basename = self.name
|
|
108
108
|
if self.is_empty_operation_group:
|
|
109
109
|
basename = self.code_model.module_name
|
|
110
110
|
|
|
111
|
-
if basename == "operations":
|
|
111
|
+
if basename == "operations" or self.code_model.options["combine_operation_files"]:
|
|
112
112
|
return f"_operations"
|
|
113
113
|
return f"_{basename}_operations"
|
|
114
114
|
|
|
@@ -97,6 +97,7 @@ class Parameter(BaseModel): # pylint: disable=too-many-instance-attributes, too
|
|
|
97
97
|
self.is_data_input = yaml_data.get("isPartialBody", False) and not self.is_multipart
|
|
98
98
|
self.content_types = content_types or []
|
|
99
99
|
self.body_kwargs: List[Parameter] = []
|
|
100
|
+
self.is_body_kwarg = False
|
|
100
101
|
|
|
101
102
|
def __hash__(self) -> int:
|
|
102
103
|
return hash(self.serialized_name)
|
|
@@ -167,7 +168,7 @@ class Parameter(BaseModel): # pylint: disable=too-many-instance-attributes, too
|
|
|
167
168
|
@property
|
|
168
169
|
def pre_semicolon_content_types(self) -> List[str]:
|
|
169
170
|
"""Splits on semicolon of media types and returns the first half.
|
|
170
|
-
I.e. ["text/plain;
|
|
171
|
+
I.e. ["text/plain; charset=UTF-8"] -> ["text/plain"]
|
|
171
172
|
"""
|
|
172
173
|
return [content_type.split(";")[0] for content_type in self.content_types]
|
|
173
174
|
|
|
@@ -282,8 +283,8 @@ class Parameter(BaseModel): # pylint: disable=too-many-instance-attributes, too
|
|
|
282
283
|
def has_default_value(self):
|
|
283
284
|
return self.default_value is not None or not self.required
|
|
284
285
|
|
|
285
|
-
def method_signature(self,
|
|
286
|
-
if
|
|
286
|
+
def method_signature(self, is_python3_file: bool) -> str:
|
|
287
|
+
if is_python3_file:
|
|
287
288
|
if self.has_default_value:
|
|
288
289
|
return f"{self.serialized_name}: {self.type_annotation} = {self.default_value_declaration},"
|
|
289
290
|
return f"{self.serialized_name}: {self.type_annotation},"
|
|
@@ -12,6 +12,7 @@ from .parameter import Parameter, ParameterLocation
|
|
|
12
12
|
from .base_schema import BaseSchema
|
|
13
13
|
from .dictionary_schema import DictionarySchema
|
|
14
14
|
from .primitive_schemas import AnySchema, StringSchema
|
|
15
|
+
from .utils import JSON_REGEXP
|
|
15
16
|
|
|
16
17
|
if TYPE_CHECKING:
|
|
17
18
|
from .schema_request import SchemaRequest
|
|
@@ -79,7 +80,7 @@ class ParameterList(MutableSequence): # pylint: disable=too-many-public-methods
|
|
|
79
80
|
|
|
80
81
|
@property
|
|
81
82
|
def default_content_type(self) -> str:
|
|
82
|
-
json_content_types = [c for c in self.content_types if
|
|
83
|
+
json_content_types = [c for c in self.content_types if JSON_REGEXP.match(c)]
|
|
83
84
|
if json_content_types:
|
|
84
85
|
if "application/json" in json_content_types:
|
|
85
86
|
return "application/json"
|
|
@@ -172,11 +173,15 @@ class ParameterList(MutableSequence): # pylint: disable=too-many-public-methods
|
|
|
172
173
|
|
|
173
174
|
@property
|
|
174
175
|
def multipart(self) -> List[Parameter]:
|
|
175
|
-
return self.get_from_predicate(
|
|
176
|
+
return self.get_from_predicate(
|
|
177
|
+
lambda parameter: parameter.is_multipart and not parameter.is_body_kwarg
|
|
178
|
+
)
|
|
176
179
|
|
|
177
180
|
@property
|
|
178
181
|
def data_inputs(self) -> List[Parameter]:
|
|
179
|
-
return self.get_from_predicate(
|
|
182
|
+
return self.get_from_predicate(
|
|
183
|
+
lambda parameter: parameter.is_data_input and not parameter.is_body_kwarg
|
|
184
|
+
)
|
|
180
185
|
|
|
181
186
|
def _filter_out_multiple_content_type(self, kwarg_params):
|
|
182
187
|
"""We don't want multiple content type kwargs in the method signature"""
|
|
@@ -214,24 +219,24 @@ class ParameterList(MutableSequence): # pylint: disable=too-many-public-methods
|
|
|
214
219
|
return signature_parameters
|
|
215
220
|
|
|
216
221
|
|
|
217
|
-
def method_signature(self,
|
|
222
|
+
def method_signature(self, is_python3_file: bool) -> List[str]:
|
|
218
223
|
return _method_signature_helper(
|
|
219
|
-
positional=self.method_signature_positional(
|
|
220
|
-
keyword_only=self.method_signature_keyword_only(
|
|
221
|
-
kwarg_params=self.method_signature_kwargs(
|
|
224
|
+
positional=self.method_signature_positional(is_python3_file),
|
|
225
|
+
keyword_only=self.method_signature_keyword_only(is_python3_file),
|
|
226
|
+
kwarg_params=self.method_signature_kwargs(is_python3_file)
|
|
222
227
|
)
|
|
223
228
|
|
|
224
|
-
def method_signature_positional(self,
|
|
225
|
-
return [parameter.method_signature(
|
|
229
|
+
def method_signature_positional(self, is_python3_file: bool) -> List[str]:
|
|
230
|
+
return [parameter.method_signature(is_python3_file) for parameter in self.positional]
|
|
226
231
|
|
|
227
|
-
def method_signature_keyword_only(self,
|
|
228
|
-
if not (self.keyword_only and
|
|
232
|
+
def method_signature_keyword_only(self, is_python3_file: bool) -> List[str]:
|
|
233
|
+
if not (self.keyword_only and is_python3_file):
|
|
229
234
|
return []
|
|
230
|
-
return ["*,"] + [parameter.method_signature(
|
|
235
|
+
return ["*,"] + [parameter.method_signature(is_python3_file) for parameter in self.keyword_only]
|
|
231
236
|
|
|
232
237
|
@staticmethod
|
|
233
|
-
def method_signature_kwargs(
|
|
234
|
-
return ["**kwargs: Any"] if
|
|
238
|
+
def method_signature_kwargs(is_python3_file: bool) -> List[str]:
|
|
239
|
+
return ["**kwargs: Any"] if is_python3_file else ["**kwargs # type: Any"]
|
|
235
240
|
|
|
236
241
|
@property
|
|
237
242
|
def positional(self) -> List[Parameter]:
|
|
@@ -245,9 +250,9 @@ class ParameterList(MutableSequence): # pylint: disable=too-many-public-methods
|
|
|
245
250
|
def kwargs(self) -> List[Parameter]:
|
|
246
251
|
return [p for p in self.method if p.is_kwarg]
|
|
247
252
|
|
|
248
|
-
def kwargs_to_pop(self,
|
|
253
|
+
def kwargs_to_pop(self, is_python3_file: bool) -> List[Parameter]:
|
|
249
254
|
kwargs_to_pop = self.kwargs
|
|
250
|
-
if not
|
|
255
|
+
if not is_python3_file:
|
|
251
256
|
kwargs_to_pop += self.keyword_only
|
|
252
257
|
return kwargs_to_pop
|
|
253
258
|
|
|
@@ -433,41 +438,41 @@ class GlobalParameterList(ParameterList):
|
|
|
433
438
|
return True
|
|
434
439
|
return serialized_name != self.host_variable_name
|
|
435
440
|
|
|
436
|
-
def kwargs_to_pop(self,
|
|
441
|
+
def kwargs_to_pop(self, is_python3_file: bool) -> List[Parameter]:
|
|
437
442
|
return [
|
|
438
|
-
k for k in super().kwargs_to_pop(
|
|
443
|
+
k for k in super().kwargs_to_pop(is_python3_file)
|
|
439
444
|
if not self._param_is_in_config_method(k.serialized_name)
|
|
440
445
|
]
|
|
441
446
|
|
|
442
|
-
def config_kwargs_to_pop(self,
|
|
443
|
-
current_kwargs_to_pop = super().kwargs_to_pop(
|
|
447
|
+
def config_kwargs_to_pop(self, is_python3_file: bool) -> List[Parameter]:
|
|
448
|
+
current_kwargs_to_pop = super().kwargs_to_pop(is_python3_file)
|
|
444
449
|
return [k for k in current_kwargs_to_pop if self._param_is_in_config_method(k.serialized_name)]
|
|
445
450
|
|
|
446
451
|
@property
|
|
447
452
|
def config_method(self) -> List[Parameter]:
|
|
448
453
|
return [p for p in self.method if self._param_is_in_config_method(p.serialized_name)]
|
|
449
454
|
|
|
450
|
-
def client_method_signature(self,
|
|
451
|
-
return self.method_signature(
|
|
455
|
+
def client_method_signature(self, is_python3_file: bool) -> List[str]:
|
|
456
|
+
return self.method_signature(is_python3_file)
|
|
452
457
|
|
|
453
|
-
def config_method_signature(self,
|
|
458
|
+
def config_method_signature(self, is_python3_file: bool) -> List[str]:
|
|
454
459
|
|
|
455
460
|
positional = [
|
|
456
|
-
p.method_signature(
|
|
461
|
+
p.method_signature(is_python3_file)
|
|
457
462
|
for p in self.positional
|
|
458
463
|
if self._param_is_in_config_method(p.serialized_name)
|
|
459
464
|
]
|
|
460
465
|
keyword_only_params = [p for p in self.keyword_only if self._param_is_in_config_method(p.serialized_name)]
|
|
461
466
|
keyword_only_method_signature = []
|
|
462
|
-
if
|
|
467
|
+
if is_python3_file:
|
|
463
468
|
keyword_only_method_signature = (
|
|
464
469
|
["*,"] +
|
|
465
470
|
[
|
|
466
|
-
p.method_signature(
|
|
471
|
+
p.method_signature(is_python3_file) for p in keyword_only_params
|
|
467
472
|
]
|
|
468
473
|
) if keyword_only_params else []
|
|
469
474
|
return _method_signature_helper(
|
|
470
475
|
positional=positional,
|
|
471
476
|
keyword_only=keyword_only_method_signature,
|
|
472
|
-
kwarg_params=self.method_signature_kwargs(
|
|
477
|
+
kwarg_params=self.method_signature_kwargs(is_python3_file)
|
|
473
478
|
)
|
|
@@ -80,13 +80,17 @@ class RequestBuilder(BaseBuilder):
|
|
|
80
80
|
file_import.add_from_import(
|
|
81
81
|
f"{relative_path}_vendor", "_format_url_section", ImportType.LOCAL
|
|
82
82
|
)
|
|
83
|
+
if self.parameters.headers or self.parameters.query:
|
|
84
|
+
file_import.add_from_import(
|
|
85
|
+
"typing", "Dict", ImportType.STDLIB, typing_section=TypingSection.CONDITIONAL
|
|
86
|
+
)
|
|
83
87
|
file_import.add_from_import(
|
|
84
88
|
"typing", "Any", ImportType.STDLIB, typing_section=TypingSection.CONDITIONAL
|
|
85
89
|
)
|
|
86
90
|
file_import.add_from_import("msrest", "Serializer", ImportType.AZURECORE)
|
|
87
91
|
if self.parameters.has_body and (
|
|
88
92
|
self.code_model.options["builders_visibility"] != "embedded" or
|
|
89
|
-
self.code_model.options["
|
|
93
|
+
self.code_model.options["add_python3_operation_files"]
|
|
90
94
|
):
|
|
91
95
|
file_import.define_mypy_type("JSONType", "Any")
|
|
92
96
|
return file_import
|
|
@@ -29,12 +29,13 @@ class RequestBuilderParameter(ParameterOnlyPathAndBodyPositional):
|
|
|
29
29
|
|
|
30
30
|
@property
|
|
31
31
|
def name_in_high_level_operation(self) -> str:
|
|
32
|
+
template = "{}" if self.code_model.options["version_tolerant"] else "_{}"
|
|
32
33
|
if self.is_multipart:
|
|
33
|
-
return "files"
|
|
34
|
+
return template.format("files")
|
|
34
35
|
if self.is_data_input:
|
|
35
|
-
return "data"
|
|
36
|
+
return template.format("data")
|
|
36
37
|
if self.is_body and not self.constant:
|
|
37
|
-
return self.serialized_name
|
|
38
|
+
return f"_{self.serialized_name}"
|
|
38
39
|
name = self.yaml_data["language"]["python"]["name"]
|
|
39
40
|
if self.implementation == "Client" and self.in_method_code:
|
|
40
41
|
# for these, we're passing the client params to the request builder.
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
# Licensed under the MIT License. See License.txt in the project root for
|
|
4
4
|
# license information.
|
|
5
5
|
# --------------------------------------------------------------------------
|
|
6
|
-
import re
|
|
7
6
|
from copy import copy
|
|
8
7
|
from typing import List, Optional, Tuple, TypeVar, Dict
|
|
9
8
|
from .request_builder_parameter import RequestBuilderParameter
|
|
@@ -13,12 +12,11 @@ from .primitive_schemas import AnySchema, JSONSchema
|
|
|
13
12
|
from .dictionary_schema import DictionarySchema
|
|
14
13
|
from .base_schema import BaseSchema
|
|
15
14
|
from .schema_request import SchemaRequest
|
|
15
|
+
from .utils import JSON_REGEXP
|
|
16
16
|
|
|
17
17
|
T = TypeVar('T')
|
|
18
18
|
OrderedSet = Dict[T, None]
|
|
19
19
|
|
|
20
|
-
_REQUEST_BUILDER_BODY_NAMES = ["files", "json", "content", "data"]
|
|
21
|
-
_JSON_REGEXP = re.compile(r'^(application|text)/([0-9a-z+.]+\+)?json$')
|
|
22
20
|
|
|
23
21
|
def _update_content_types(content_types_to_assign: List[str], param: Parameter):
|
|
24
22
|
return [
|
|
@@ -44,6 +42,7 @@ class RequestBuilderParameterList(ParameterList):
|
|
|
44
42
|
def _change_body_param_name(self, parameter: Parameter, name: str) -> None:
|
|
45
43
|
self.body_kwarg_names[name] = None
|
|
46
44
|
parameter.serialized_name = name
|
|
45
|
+
parameter.is_body_kwarg = True
|
|
47
46
|
|
|
48
47
|
def _is_json(self, body_method_param: Parameter) -> bool:
|
|
49
48
|
if 'json' in body_method_param.serialization_formats:
|
|
@@ -59,7 +58,7 @@ class RequestBuilderParameterList(ParameterList):
|
|
|
59
58
|
if sr.yaml_data.get("protocol", {}).get('http', {}).get('knownMediaType') == "json"
|
|
60
59
|
):
|
|
61
60
|
return True
|
|
62
|
-
return any(c for c in self.content_types if
|
|
61
|
+
return any(c for c in self.content_types if JSON_REGEXP.match(c))
|
|
63
62
|
|
|
64
63
|
@property
|
|
65
64
|
def body_kwargs_to_get(self) -> List[Parameter]:
|
|
@@ -97,7 +96,6 @@ class RequestBuilderParameterList(ParameterList):
|
|
|
97
96
|
"Multipart input for files. See the template in our example to find the input shape. " +
|
|
98
97
|
file_kwarg.description
|
|
99
98
|
)
|
|
100
|
-
file_kwarg.is_multipart = False
|
|
101
99
|
file_kwarg.content_types = [
|
|
102
100
|
c for c in content_types_to_assign
|
|
103
101
|
if c == "multipart/form-data"
|
|
@@ -119,7 +117,6 @@ class RequestBuilderParameterList(ParameterList):
|
|
|
119
117
|
"Pass in dictionary that contains form data to include in the body of the request. " +
|
|
120
118
|
data_kwarg.description
|
|
121
119
|
)
|
|
122
|
-
data_kwarg.is_data_input = False
|
|
123
120
|
data_kwarg.content_types = [
|
|
124
121
|
c for c in content_types_to_assign
|
|
125
122
|
if c == "application/x-www-form-urlencoded"
|
|
@@ -140,7 +137,7 @@ class RequestBuilderParameterList(ParameterList):
|
|
|
140
137
|
json_kwarg.schema = JSONSchema(namespace="", yaml_data={})
|
|
141
138
|
json_kwarg.content_types = [
|
|
142
139
|
c for c in content_types_to_assign
|
|
143
|
-
if
|
|
140
|
+
if JSON_REGEXP.match(c)
|
|
144
141
|
]
|
|
145
142
|
content_types_to_assign = _update_content_types(content_types_to_assign, json_kwarg)
|
|
146
143
|
return content_types_to_assign, json_kwarg
|
|
@@ -208,7 +205,7 @@ class RequestBuilderParameterList(ParameterList):
|
|
|
208
205
|
if not self._json_body:
|
|
209
206
|
try:
|
|
210
207
|
json_param = next(
|
|
211
|
-
b for b in self.body if b.
|
|
208
|
+
b for b in self.body if not b.is_body_kwarg and
|
|
212
209
|
b.is_json_parameter
|
|
213
210
|
)
|
|
214
211
|
self._json_body = json_param.schema
|
|
@@ -217,10 +214,10 @@ class RequestBuilderParameterList(ParameterList):
|
|
|
217
214
|
raise ValueError("There is no JSON body in these parameters")
|
|
218
215
|
return self._json_body
|
|
219
216
|
|
|
220
|
-
def kwargs_to_pop(self,
|
|
217
|
+
def kwargs_to_pop(self, is_python3_file: bool) -> List[Parameter]:
|
|
221
218
|
# we don't want to pop the body kwargs in py2.7. We send them straight to HttpRequest
|
|
222
219
|
kwargs_to_pop = self.kwargs
|
|
223
|
-
if not
|
|
220
|
+
if not is_python3_file:
|
|
224
221
|
kwargs_to_pop += [k for k in self.keyword_only if not (k.is_body and not k.constant)]
|
|
225
222
|
return kwargs_to_pop
|
|
226
223
|
|
|
@@ -240,9 +237,19 @@ class RequestBuilderParameterList(ParameterList):
|
|
|
240
237
|
seen_content_type = False
|
|
241
238
|
|
|
242
239
|
for parameter in parameters:
|
|
240
|
+
|
|
241
|
+
if (
|
|
242
|
+
parameter.location == ParameterLocation.Body and
|
|
243
|
+
(parameter.is_data_input or parameter.is_multipart) and
|
|
244
|
+
not parameter.is_body_kwarg
|
|
245
|
+
):
|
|
246
|
+
# if i am a part of files or data, and i'm not the files or
|
|
247
|
+
# data kwarg, ignore me
|
|
248
|
+
continue
|
|
243
249
|
if (
|
|
244
250
|
parameter.location == ParameterLocation.Body and
|
|
245
|
-
parameter.
|
|
251
|
+
not parameter.is_body_kwarg and
|
|
252
|
+
not parameter.constant
|
|
246
253
|
):
|
|
247
254
|
# we keep the original body param from the swagger for documentation purposes
|
|
248
255
|
# we don't want it in the method signature
|
|
@@ -19,10 +19,11 @@ class Rest(BaseModel):
|
|
|
19
19
|
super(Rest, self). __init__(yaml_data=yaml_data)
|
|
20
20
|
self.request_builders = request_builders
|
|
21
21
|
|
|
22
|
-
def imports(self) -> FileImport:
|
|
22
|
+
def imports(self, builder_group_name: str) -> FileImport:
|
|
23
23
|
file_import = FileImport()
|
|
24
24
|
for request_builder in self.request_builders:
|
|
25
|
-
|
|
25
|
+
if request_builder.builder_group_name == builder_group_name:
|
|
26
|
+
file_import.merge(request_builder.imports())
|
|
26
27
|
return file_import
|
|
27
28
|
|
|
28
29
|
@classmethod
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# -------------------------------------------------------------------------
|
|
2
|
+
# Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3
|
+
# Licensed under the MIT License. See License.txt in the project root for
|
|
4
|
+
# license information.
|
|
5
|
+
# --------------------------------------------------------------------------
|
|
6
|
+
import re
|
|
7
|
+
|
|
8
|
+
JSON_REGEXP = re.compile(r'^(application|text)/(.+\+)?json$')
|