@autorest/python 5.11.2 → 5.12.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/ChangeLog.md +69 -0
  2. package/autorest/codegen/__init__.py +5 -5
  3. package/autorest/codegen/models/__init__.py +3 -23
  4. package/autorest/codegen/models/base_builder.py +2 -5
  5. package/autorest/codegen/models/client.py +2 -2
  6. package/autorest/codegen/models/code_model.py +5 -1
  7. package/autorest/codegen/models/operation_group.py +5 -3
  8. package/autorest/codegen/models/parameter.py +7 -8
  9. package/autorest/codegen/models/parameter_list.py +32 -27
  10. package/autorest/codegen/models/request_builder.py +5 -1
  11. package/autorest/codegen/models/request_builder_parameter.py +4 -5
  12. package/autorest/codegen/models/request_builder_parameter_list.py +18 -11
  13. package/autorest/codegen/models/rest.py +3 -2
  14. package/autorest/codegen/models/utils.py +8 -0
  15. package/autorest/codegen/serializers/__init__.py +48 -48
  16. package/autorest/codegen/serializers/builder_serializer.py +150 -146
  17. package/autorest/codegen/serializers/client_serializer.py +37 -9
  18. package/autorest/codegen/serializers/general_serializer.py +7 -5
  19. package/autorest/codegen/serializers/import_serializer.py +6 -6
  20. package/autorest/codegen/serializers/metadata_serializer.py +2 -2
  21. package/autorest/codegen/serializers/model_base_serializer.py +3 -3
  22. package/autorest/codegen/serializers/model_generic_serializer.py +1 -1
  23. package/autorest/codegen/serializers/model_python3_serializer.py +1 -1
  24. package/autorest/codegen/serializers/{operation_group_serializer.py → operation_groups_serializer.py} +27 -29
  25. package/autorest/codegen/serializers/operations_init_serializer.py +34 -2
  26. package/autorest/codegen/serializers/patch_serializer.py +15 -0
  27. package/autorest/codegen/serializers/rest_serializer.py +9 -4
  28. package/autorest/codegen/serializers/utils.py +2 -2
  29. package/autorest/codegen/templates/config.py.jinja2 +1 -11
  30. package/autorest/codegen/templates/init.py.jinja2 +4 -5
  31. package/autorest/codegen/templates/metadata.json.jinja2 +5 -5
  32. package/autorest/codegen/templates/model_init.py.jinja2 +1 -1
  33. package/autorest/codegen/templates/{operations_class.py.jinja2 → operation_group.py.jinja2} +2 -0
  34. package/autorest/codegen/templates/{operations_container.py.jinja2 → operation_groups_container.py.jinja2} +7 -21
  35. package/autorest/codegen/templates/operations_folder_init.py.jinja2 +13 -0
  36. package/autorest/codegen/templates/patch.py.jinja2 +31 -0
  37. package/autorest/codegen/templates/request_builder.py.jinja2 +7 -2
  38. package/autorest/codegen/templates/request_builders.py.jinja2 +1 -1
  39. package/autorest/codegen/templates/setup.py.jinja2 +1 -1
  40. package/autorest/multiapi/serializers/__init__.py +3 -3
  41. package/autorest/multiapi/serializers/import_serializer.py +5 -5
  42. package/autorest/namer/name_converter.py +3 -1
  43. package/install.py +1 -0
  44. package/package.json +4 -3
  45. package/requirements.txt +14 -0
  46. package/setup.py +1 -0
  47. package/autorest/codegen/templates/operations_class_mixin.py.jinja2 +0 -16
  48. package/autorest/codegen/templates/operations_container_init.py.jinja2 +0 -24
  49. package/autorest/codegen/templates/operations_container_mixin.py.jinja2 +0 -21
  50. package/autorest/codegen/templates/operations_init.py.jinja2 +0 -26
package/ChangeLog.md CHANGED
@@ -1,5 +1,74 @@
1
1
  # Change Log
2
2
 
3
+ ### 2022-01-13 - 5.12.3
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
+ - Unify multiapi constant behavior with single API version #1119
16
+ - Clean up docstrings by removing descriptions for client constants on methods and request builders #1119
17
+
18
+ ### 2022-01-11 - 5.12.2
19
+
20
+ | Library | Min Version
21
+ | --------------- | -------
22
+ |`@autorest/core` | `3.6.2`
23
+ |`@autorest/modelerfour` | `4.19.1`
24
+ |`azure-core` dep of generated code | `1.20.1`
25
+ |`msrest` dep of generated code | `0.6.21`
26
+ |`azure-mgmt-core` dep of generated code (If generating mgmt plane code) | `1.3.0`
27
+
28
+ **Bug Fixes**
29
+
30
+ - Fix installation of autorest python package #1118
31
+
32
+ ### 2022-01-10 - 5.12.1
33
+
34
+ | Library | Min Version
35
+ | --------------- | -------
36
+ |`@autorest/core` | `3.6.2`
37
+ |`@autorest/modelerfour` | `4.19.1`
38
+ |`azure-core` dep of generated code | `1.20.1`
39
+ |`msrest` dep of generated code | `0.6.21`
40
+ |`azure-mgmt-core` dep of generated code (If generating mgmt plane code) | `1.3.0`
41
+
42
+ **Bug Fixes**
43
+
44
+ - Fix support for json merge patch #1117
45
+
46
+ ### 2021-12-06 - 5.12.0
47
+
48
+ | Library | Min Version
49
+ | --------------- | -------
50
+ |`@autorest/core` | `3.6.2`
51
+ |`@autorest/modelerfour` | `4.19.1`
52
+ |`azure-core` dep of generated code | `1.20.1`
53
+ |`msrest` dep of generated code | `0.6.21`
54
+ |`azure-mgmt-core` dep of generated code (If generating mgmt plane code) | `1.3.0`
55
+
56
+ **Breaking Changes in Version Tolerant Generation**
57
+
58
+ - Remove metadata property for version tolerant and low level client generations #1090
59
+ - Generate SDKs with `--python3-only` defaulting to `True` for version tolerant and low level client #1087
60
+
61
+ **New Features**
62
+
63
+ - Generate a `_patch.py` file if one does not exist. These files are used to customize the generated code #1092
64
+
65
+ **Bug Fixes**
66
+
67
+ - Can now handle body params with names `json`, `content`, `data`, and `files` #1081
68
+ - Improve generated templates for `data` and `files` input body params by adding quotes around the keys #1082
69
+ - Using flag `--python3-only` will get you typed sync client and config files #1085
70
+ - Pin `mistune` dependency to less than `2.x.x` so autorest can be successfully installed #1106
71
+
3
72
  ### 2021-11-05 - 5.11.2
4
73
 
5
74
  | 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["add_python_3_operation_files"]:
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
- python_3_only = self._autorestapi.get_boolean_value("python3-only", False)
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
- "add_python_3_operation_files": self._autorestapi.get_boolean_value(
286
- "add-python3-operation-files", python_3_only
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
- "python_3_only": python_3_only,
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, TypeVar, Union
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 GlobalParameterList, ParameterList
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, TYPE_CHECKING
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: "ParameterListType",
70
+ parameters,
74
71
  schema_requests: List[SchemaRequest],
75
72
  responses: Optional[List[SchemaResponse]] = None,
76
73
  summary: Optional[str] = None,
@@ -96,6 +96,6 @@ class Client:
96
96
  pass
97
97
  return file_import
98
98
 
99
- def send_request_signature(self, async_mode) -> List[str]:
99
+ def send_request_signature(self, async_mode: bool, is_python3_file: bool) -> List[str]:
100
100
  request_signature = ["request: HttpRequest," if async_mode else "request, # type: HttpRequest"]
101
- return request_signature + self.parameters.method_signature_kwargs(async_mode)
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
@@ -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, has_schemas: bool) -> FileImport:
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,7 +85,9 @@ 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
- suffix = "_py3" if self.code_model.options["python_3_only"] else ""
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 ""
89
91
  file_import.add_from_import(
90
92
  f"...{self.code_model.operations_folder_name}.{self.filename}{suffix}",
91
93
  request_builder.name,
@@ -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; encoding=UTF-8"] -> ["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
 
@@ -176,8 +177,6 @@ class Parameter(BaseModel): # pylint: disable=too-many-instance-attributes, too
176
177
  return not(
177
178
  # don't put accept in signature
178
179
  self.rest_api_name == "Accept"
179
- # if i'm multiapi, don't add constants
180
- or (self.code_model.options["multiapi"] and self.constant)
181
180
  # If i'm not in the method code, no point in being in signature
182
181
  or not self.in_method_code
183
182
  # If I'm grouped, my grouper will be on signature, not me
@@ -282,8 +281,8 @@ class Parameter(BaseModel): # pylint: disable=too-many-instance-attributes, too
282
281
  def has_default_value(self):
283
282
  return self.default_value is not None or not self.required
284
283
 
285
- def method_signature(self, is_python_3_file: bool) -> str:
286
- if is_python_3_file:
284
+ def method_signature(self, is_python3_file: bool) -> str:
285
+ if is_python3_file:
287
286
  if self.has_default_value:
288
287
  return f"{self.serialized_name}: {self.type_annotation} = {self.default_value_declaration},"
289
288
  return f"{self.serialized_name}: {self.type_annotation},"
@@ -301,8 +300,6 @@ class Parameter(BaseModel): # pylint: disable=too-many-instance-attributes, too
301
300
  @property
302
301
  def is_kwarg(self) -> bool:
303
302
  # this means "am I in **kwargs?"
304
- if self.code_model.options["multiapi"]:
305
- return self.rest_api_name == "Content-Type"
306
303
  return self.rest_api_name == "Content-Type" or (self.constant and self.rest_api_name != "Accept")
307
304
 
308
305
  @property
@@ -312,7 +309,9 @@ class Parameter(BaseModel): # pylint: disable=too-many-instance-attributes, too
312
309
 
313
310
  @property
314
311
  def is_hidden(self) -> bool:
315
- return self.serialized_name in _HIDDEN_KWARGS
312
+ return self.serialized_name in _HIDDEN_KWARGS or (
313
+ self.yaml_data["implementation"] == "Client" and self.constant
314
+ )
316
315
 
317
316
  @property
318
317
  def is_positional(self) -> bool:
@@ -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 "json" in c]
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(lambda parameter: parameter.is_multipart)
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(lambda parameter: parameter.is_data_input)
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, is_python_3_file: bool) -> List[str]:
222
+ def method_signature(self, is_python3_file: bool) -> List[str]:
218
223
  return _method_signature_helper(
219
- positional=self.method_signature_positional(is_python_3_file),
220
- keyword_only=self.method_signature_keyword_only(is_python_3_file),
221
- kwarg_params=self.method_signature_kwargs(is_python_3_file)
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, is_python_3_file: bool) -> List[str]:
225
- return [parameter.method_signature(is_python_3_file) for parameter in self.positional]
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, is_python_3_file: bool) -> List[str]:
228
- if not (self.keyword_only and is_python_3_file):
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(is_python_3_file) for parameter in self.keyword_only]
235
+ return ["*,"] + [parameter.method_signature(is_python3_file) for parameter in self.keyword_only]
231
236
 
232
237
  @staticmethod
233
- def method_signature_kwargs(is_python_3_file: bool) -> List[str]:
234
- return ["**kwargs: Any"] if is_python_3_file else ["**kwargs # type: Any"]
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, is_python_3_file: bool) -> List[Parameter]:
253
+ def kwargs_to_pop(self, is_python3_file: bool) -> List[Parameter]:
249
254
  kwargs_to_pop = self.kwargs
250
- if not is_python_3_file:
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, is_python_3_file: bool) -> List[Parameter]:
441
+ def kwargs_to_pop(self, is_python3_file: bool) -> List[Parameter]:
437
442
  return [
438
- k for k in super().kwargs_to_pop(is_python_3_file)
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, is_python_3_file: bool) -> List[Parameter]:
443
- current_kwargs_to_pop = super().kwargs_to_pop(is_python_3_file)
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, is_python_3_file: bool) -> List[str]:
451
- return self.method_signature(is_python_3_file)
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, is_python_3_file: bool) -> List[str]:
458
+ def config_method_signature(self, is_python3_file: bool) -> List[str]:
454
459
 
455
460
  positional = [
456
- p.method_signature(is_python_3_file)
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 is_python_3_file:
467
+ if is_python3_file:
463
468
  keyword_only_method_signature = (
464
469
  ["*,"] +
465
470
  [
466
- p.method_signature(is_python_3_file) for p in keyword_only_params
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(is_python_3_file)
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["add_python_3_operation_files"]
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
@@ -18,8 +18,6 @@ class RequestBuilderParameter(ParameterOnlyPathAndBodyPositional):
18
18
  return not(
19
19
  # don't put accept in method signature
20
20
  self.rest_api_name == "Accept"
21
- # if i'm multiapi, don't add constants
22
- or (self.code_model.options["multiapi"] and self.constant)
23
21
  # If i'm not in the method code, no point in being in signature
24
22
  or not self.in_method_code
25
23
  # If I'm a flattened property of a body, don't want me, want the body param
@@ -29,12 +27,13 @@ class RequestBuilderParameter(ParameterOnlyPathAndBodyPositional):
29
27
 
30
28
  @property
31
29
  def name_in_high_level_operation(self) -> str:
30
+ template = "{}" if self.code_model.options["version_tolerant"] else "_{}"
32
31
  if self.is_multipart:
33
- return "files"
32
+ return template.format("files")
34
33
  if self.is_data_input:
35
- return "data"
34
+ return template.format("data")
36
35
  if self.is_body and not self.constant:
37
- return self.serialized_name
36
+ return f"_{self.serialized_name}"
38
37
  name = self.yaml_data["language"]["python"]["name"]
39
38
  if self.implementation == "Client" and self.in_method_code:
40
39
  # 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 _JSON_REGEXP.match(c))
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 _JSON_REGEXP.match(c)
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.serialized_name not in _REQUEST_BUILDER_BODY_NAMES and
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, is_python_3_file: bool) -> List[Parameter]:
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 is_python_3_file:
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.serialized_name not in _REQUEST_BUILDER_BODY_NAMES
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
- file_import.merge(request_builder.imports())
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$')