@autorest/python 5.15.0 → 5.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. package/ChangeLog.md +20 -0
  2. package/autorest/__init__.py +1 -2
  3. package/autorest/black/__init__.py +12 -5
  4. package/autorest/codegen/__init__.py +145 -73
  5. package/autorest/codegen/models/__init__.py +29 -18
  6. package/autorest/codegen/models/base_builder.py +48 -11
  7. package/autorest/codegen/models/base_model.py +6 -4
  8. package/autorest/codegen/models/base_schema.py +19 -18
  9. package/autorest/codegen/models/client.py +65 -21
  10. package/autorest/codegen/models/code_model.py +107 -61
  11. package/autorest/codegen/models/constant_schema.py +25 -13
  12. package/autorest/codegen/models/credential_model.py +23 -15
  13. package/autorest/codegen/models/credential_schema.py +18 -14
  14. package/autorest/codegen/models/credential_schema_policy.py +11 -15
  15. package/autorest/codegen/models/dictionary_schema.py +20 -17
  16. package/autorest/codegen/models/enum_schema.py +35 -25
  17. package/autorest/codegen/models/imports.py +70 -41
  18. package/autorest/codegen/models/list_schema.py +25 -13
  19. package/autorest/codegen/models/lro_operation.py +58 -22
  20. package/autorest/codegen/models/lro_paging_operation.py +2 -3
  21. package/autorest/codegen/models/object_schema.py +99 -49
  22. package/autorest/codegen/models/operation.py +236 -117
  23. package/autorest/codegen/models/operation_group.py +64 -34
  24. package/autorest/codegen/models/paging_operation.py +45 -18
  25. package/autorest/codegen/models/parameter.py +151 -83
  26. package/autorest/codegen/models/parameter_list.py +183 -162
  27. package/autorest/codegen/models/primitive_schemas.py +84 -55
  28. package/autorest/codegen/models/property.py +44 -26
  29. package/autorest/codegen/models/request_builder.py +65 -30
  30. package/autorest/codegen/models/request_builder_parameter.py +47 -23
  31. package/autorest/codegen/models/request_builder_parameter_list.py +77 -108
  32. package/autorest/codegen/models/schema_request.py +16 -6
  33. package/autorest/codegen/models/schema_response.py +18 -13
  34. package/autorest/codegen/models/utils.py +5 -2
  35. package/autorest/codegen/serializers/__init__.py +182 -91
  36. package/autorest/codegen/serializers/builder_serializer.py +667 -331
  37. package/autorest/codegen/serializers/client_serializer.py +98 -37
  38. package/autorest/codegen/serializers/general_serializer.py +61 -26
  39. package/autorest/codegen/serializers/import_serializer.py +93 -31
  40. package/autorest/codegen/serializers/metadata_serializer.py +73 -24
  41. package/autorest/codegen/serializers/model_base_serializer.py +35 -15
  42. package/autorest/codegen/serializers/model_generic_serializer.py +1 -4
  43. package/autorest/codegen/serializers/model_init_serializer.py +5 -1
  44. package/autorest/codegen/serializers/model_python3_serializer.py +7 -6
  45. package/autorest/codegen/serializers/operation_groups_serializer.py +20 -9
  46. package/autorest/codegen/serializers/operations_init_serializer.py +23 -11
  47. package/autorest/codegen/serializers/patch_serializer.py +4 -1
  48. package/autorest/codegen/serializers/{rest_serializer.py → request_builders_serializer.py} +29 -12
  49. package/autorest/codegen/serializers/utils.py +35 -21
  50. package/autorest/codegen/templates/init.py.jinja2 +2 -2
  51. package/autorest/codegen/templates/lro_operation.py.jinja2 +5 -7
  52. package/autorest/codegen/templates/lro_paging_operation.py.jinja2 +5 -7
  53. package/autorest/codegen/templates/metadata.json.jinja2 +7 -6
  54. package/autorest/codegen/templates/operation.py.jinja2 +7 -9
  55. package/autorest/codegen/templates/operation_group.py.jinja2 +2 -8
  56. package/autorest/codegen/templates/operation_groups_container.py.jinja2 +1 -1
  57. package/autorest/codegen/templates/paging_operation.py.jinja2 +7 -8
  58. package/autorest/codegen/templates/request_builder.py.jinja2 +18 -11
  59. package/autorest/jsonrpc/__init__.py +7 -12
  60. package/autorest/jsonrpc/localapi.py +4 -3
  61. package/autorest/jsonrpc/server.py +13 -6
  62. package/autorest/jsonrpc/stdstream.py +13 -6
  63. package/autorest/m2r/__init__.py +5 -8
  64. package/autorest/multiapi/__init__.py +24 -14
  65. package/autorest/multiapi/models/client.py +21 -11
  66. package/autorest/multiapi/models/code_model.py +23 -10
  67. package/autorest/multiapi/models/config.py +4 -1
  68. package/autorest/multiapi/models/constant_global_parameter.py +1 -0
  69. package/autorest/multiapi/models/global_parameter.py +2 -1
  70. package/autorest/multiapi/models/global_parameters.py +14 -8
  71. package/autorest/multiapi/models/imports.py +24 -17
  72. package/autorest/multiapi/models/mixin_operation.py +5 -5
  73. package/autorest/multiapi/models/operation_group.py +2 -1
  74. package/autorest/multiapi/models/operation_mixin_group.py +21 -10
  75. package/autorest/multiapi/serializers/__init__.py +18 -23
  76. package/autorest/multiapi/serializers/import_serializer.py +47 -17
  77. package/autorest/multiapi/serializers/multiapi_serializer.py +17 -17
  78. package/autorest/multiapi/templates/multiapi_operations_mixin.py.jinja2 +1 -1
  79. package/autorest/multiapi/utils.py +3 -3
  80. package/autorest/namer/__init__.py +2 -4
  81. package/autorest/namer/name_converter.py +200 -103
  82. package/autorest/namer/python_mappings.py +10 -22
  83. package/package.json +2 -2
  84. package/run-python3.js +2 -3
  85. package/venvtools.py +1 -1
  86. package/autorest/codegen/models/rest.py +0 -42
@@ -6,21 +6,24 @@
6
6
  import logging
7
7
  import datetime
8
8
  from enum import Enum
9
- from typing import cast, Any, Dict, List, Optional, Union
9
+ from typing import cast, Any, Dict, List, Optional, Union, TYPE_CHECKING
10
10
 
11
11
  from .base_schema import BaseSchema
12
12
  from .imports import FileImport, ImportType, TypingSection
13
13
 
14
+ if TYPE_CHECKING:
15
+ from .code_model import CodeModel
16
+
14
17
 
15
18
  _LOGGER = logging.getLogger(__name__)
16
19
 
20
+
17
21
  class RawString(object):
18
22
  def __init__(self, string: str) -> None:
19
23
  self.string = string
20
24
 
21
25
  def __repr__(self) -> str:
22
- return "r'{}'".format(self.string.replace('\'', '\\\''))
23
-
26
+ return "r'{}'".format(self.string.replace("'", "\\'"))
24
27
 
25
28
 
26
29
  class PrimitiveSchema(BaseSchema):
@@ -39,7 +42,9 @@ class PrimitiveSchema(BaseSchema):
39
42
  def docstring_type(self) -> str:
40
43
  return self._to_python_type()
41
44
 
42
- def type_annotation(self, *, is_operation_file: bool = False) -> str: # pylint: disable=unused-argument
45
+ def type_annotation(
46
+ self, *, is_operation_file: bool = False # pylint: disable=unused-argument
47
+ ) -> str:
43
48
  return self.docstring_type
44
49
 
45
50
  @property
@@ -69,28 +74,18 @@ class PrimitiveSchema(BaseSchema):
69
74
  def get_json_template_representation(self, **kwargs: Any) -> Any:
70
75
  if self.default_value:
71
76
  kwargs["default_value_declaration"] = kwargs.get(
72
- "default_value_declaration",
73
- self.get_declaration(self.default_value)
77
+ "default_value_declaration", self.get_declaration(self.default_value)
74
78
  )
75
- return self._add_optional_and_default_value_template_representation(
76
- **kwargs
77
- )
79
+ return self._add_optional_and_default_value_template_representation(**kwargs)
78
80
 
79
81
  @property
80
82
  def default_template_representation_declaration(self) -> str:
81
83
  return self.get_declaration(self.docstring_type)
82
84
 
83
- def get_files_and_data_template_representation(self, **kwargs: Any) -> Any:
84
- """Template of what the files input should look like
85
- """
86
- return self._add_optional_and_default_value_template_representation(
87
- **kwargs
88
- )
89
85
 
90
86
  class IOSchema(PrimitiveSchema):
91
-
92
- def __init__(self, namespace, yaml_data) -> None:
93
- super(IOSchema, self).__init__(namespace=namespace, yaml_data=yaml_data)
87
+ def __init__(self, yaml_data: Dict[str, Any], code_model: "CodeModel") -> None:
88
+ super().__init__(yaml_data=yaml_data, code_model=code_model)
94
89
  self.type = "IO"
95
90
 
96
91
  @property
@@ -101,7 +96,9 @@ class IOSchema(PrimitiveSchema):
101
96
  def docstring_type(self) -> str:
102
97
  return self.type
103
98
 
104
- def type_annotation(self, *, is_operation_file: bool = False) -> str: # pylint: disable=unused-argument
99
+ def type_annotation(
100
+ self, *, is_operation_file: bool = False # pylint: disable=unused-argument
101
+ ) -> str:
105
102
  return self.docstring_type
106
103
 
107
104
  @property
@@ -114,9 +111,12 @@ class IOSchema(PrimitiveSchema):
114
111
 
115
112
  def imports(self) -> FileImport:
116
113
  file_import = FileImport()
117
- file_import.add_submodule_import("typing", "IO", ImportType.STDLIB, TypingSection.CONDITIONAL)
114
+ file_import.add_submodule_import(
115
+ "typing", "IO", ImportType.STDLIB, TypingSection.CONDITIONAL
116
+ )
118
117
  return file_import
119
118
 
119
+
120
120
  class AnySchema(PrimitiveSchema):
121
121
  @property
122
122
  def serialization_type(self) -> str:
@@ -126,7 +126,9 @@ class AnySchema(PrimitiveSchema):
126
126
  def docstring_type(self) -> str:
127
127
  return "any"
128
128
 
129
- def type_annotation(self, *, is_operation_file: bool = False) -> str: # pylint: disable=unused-argument
129
+ def type_annotation(
130
+ self, *, is_operation_file: bool = False # pylint: disable=unused-argument
131
+ ) -> str:
130
132
  return "Any"
131
133
 
132
134
  @property
@@ -135,22 +137,15 @@ class AnySchema(PrimitiveSchema):
135
137
 
136
138
  def imports(self) -> FileImport:
137
139
  file_import = FileImport()
138
- file_import.add_submodule_import("typing", "Any", ImportType.STDLIB, TypingSection.CONDITIONAL)
140
+ file_import.add_submodule_import(
141
+ "typing", "Any", ImportType.STDLIB, TypingSection.CONDITIONAL
142
+ )
139
143
  return file_import
140
144
 
141
- class JSONSchema(AnySchema):
142
-
143
- @property
144
- def docstring_type(self) -> str:
145
- return "JSONType"
146
-
147
- def type_annotation(self, *, is_operation_file: bool = False) -> str: # pylint: disable=unused-argument
148
- return "JSONType"
149
-
150
145
 
151
146
  class NumberSchema(PrimitiveSchema):
152
- def __init__(self, namespace: str, yaml_data: Dict[str, Any]) -> None:
153
- super(NumberSchema, self).__init__(namespace=namespace, yaml_data=yaml_data)
147
+ def __init__(self, yaml_data: Dict[str, Any], code_model: "CodeModel") -> None:
148
+ super().__init__(yaml_data=yaml_data, code_model=code_model)
154
149
  self.precision = cast(int, yaml_data["precision"])
155
150
  self.multiple = cast(int, yaml_data.get("multipleOf"))
156
151
  self.maximum = cast(int, yaml_data.get("maximum"))
@@ -161,10 +156,18 @@ class NumberSchema(PrimitiveSchema):
161
156
  @property
162
157
  def serialization_constraints(self) -> List[str]:
163
158
  validation_constraints = [
164
- f"maximum_ex={self.maximum}" if self.maximum is not None and self.exclusive_maximum else None,
165
- f"maximum={self.maximum}" if self.maximum is not None and not self.exclusive_maximum else None,
166
- f"minimum_ex={self.minimum}" if self.minimum is not None and self.exclusive_minimum else None,
167
- f"minimum={self.minimum}" if self.minimum is not None and not self.exclusive_minimum else None,
159
+ f"maximum_ex={self.maximum}"
160
+ if self.maximum is not None and self.exclusive_maximum
161
+ else None,
162
+ f"maximum={self.maximum}"
163
+ if self.maximum is not None and not self.exclusive_maximum
164
+ else None,
165
+ f"minimum_ex={self.minimum}"
166
+ if self.minimum is not None and self.exclusive_minimum
167
+ else None,
168
+ f"minimum={self.minimum}"
169
+ if self.minimum is not None and not self.exclusive_minimum
170
+ else None,
168
171
  f"multiple={self.multiple}" if self.multiple else None,
169
172
  ]
170
173
  return [x for x in validation_constraints if x is not None]
@@ -202,7 +205,9 @@ class NumberSchema(PrimitiveSchema):
202
205
  return "int"
203
206
  return "float"
204
207
 
205
- def type_annotation(self, *, is_operation_file: bool = False) -> str: # pylint: disable=unused-argument
208
+ def type_annotation(
209
+ self, *, is_operation_file: bool = False # pylint: disable=unused-argument
210
+ ) -> str:
206
211
  python_type = self.docstring_type
207
212
  if python_type == "long":
208
213
  return "int"
@@ -213,13 +218,18 @@ class NumberSchema(PrimitiveSchema):
213
218
  default_value = 0 if self.docstring_type == "int" else 0.0
214
219
  return self.get_declaration(default_value)
215
220
 
216
- class StringSchema(PrimitiveSchema):
217
221
 
218
- def __init__(self, namespace: str, yaml_data: Dict[str, Any]) -> None:
219
- super(StringSchema, self).__init__(namespace=namespace, yaml_data=yaml_data)
222
+ class StringSchema(PrimitiveSchema):
223
+ def __init__(self, yaml_data: Dict[str, Any], code_model: "CodeModel") -> None:
224
+ super().__init__(yaml_data=yaml_data, code_model=code_model)
220
225
  self.max_length = cast(int, yaml_data.get("maxLength"))
221
226
  self.min_length = cast(
222
- int, (yaml_data.get("minLength", 0) if yaml_data.get("maxLength") else yaml_data.get("minLength"))
227
+ int,
228
+ (
229
+ yaml_data.get("minLength", 0)
230
+ if yaml_data.get("maxLength")
231
+ else yaml_data.get("minLength")
232
+ ),
223
233
  )
224
234
  self.pattern = cast(str, yaml_data.get("pattern"))
225
235
 
@@ -249,8 +259,8 @@ class StringSchema(PrimitiveSchema):
249
259
 
250
260
 
251
261
  class DatetimeSchema(PrimitiveSchema):
252
- def __init__(self, namespace: str, yaml_data: Dict[str, Any]) -> None:
253
- super(DatetimeSchema, self).__init__(namespace=namespace, yaml_data=yaml_data)
262
+ def __init__(self, yaml_data: Dict[str, Any], code_model: "CodeModel") -> None:
263
+ super().__init__(yaml_data=yaml_data, code_model=code_model)
254
264
  self.format = self.Formats(yaml_data["format"])
255
265
 
256
266
  class Formats(str, Enum):
@@ -259,14 +269,19 @@ class DatetimeSchema(PrimitiveSchema):
259
269
 
260
270
  @property
261
271
  def serialization_type(self) -> str:
262
- formats_to_attribute_type = {self.Formats.datetime: "iso-8601", self.Formats.rfc1123: "rfc-1123"}
272
+ formats_to_attribute_type = {
273
+ self.Formats.datetime: "iso-8601",
274
+ self.Formats.rfc1123: "rfc-1123",
275
+ }
263
276
  return formats_to_attribute_type[self.format]
264
277
 
265
278
  @property
266
279
  def docstring_type(self) -> str:
267
280
  return "~" + self.type_annotation()
268
281
 
269
- def type_annotation(self, *, is_operation_file: bool = False) -> str: # pylint: disable=unused-argument
282
+ def type_annotation(
283
+ self, *, is_operation_file: bool = False # pylint: disable=unused-argument
284
+ ) -> str:
270
285
  return "datetime.datetime"
271
286
 
272
287
  @property
@@ -288,6 +303,7 @@ class DatetimeSchema(PrimitiveSchema):
288
303
  def default_template_representation_declaration(self):
289
304
  return self.get_declaration(datetime.datetime(2020, 2, 20))
290
305
 
306
+
291
307
  class TimeSchema(PrimitiveSchema):
292
308
  @property
293
309
  def serialization_type(self) -> str:
@@ -297,7 +313,9 @@ class TimeSchema(PrimitiveSchema):
297
313
  def docstring_type(self) -> str:
298
314
  return "~" + self.type_annotation()
299
315
 
300
- def type_annotation(self, *, is_operation_file: bool = False) -> str: # pylint: disable=unused-argument
316
+ def type_annotation(
317
+ self, *, is_operation_file: bool = False # pylint: disable=unused-argument
318
+ ) -> str:
301
319
  return "datetime.time"
302
320
 
303
321
  @property
@@ -329,7 +347,9 @@ class UnixTimeSchema(PrimitiveSchema):
329
347
  def docstring_type(self) -> str:
330
348
  return "~" + self.type_annotation()
331
349
 
332
- def type_annotation(self, *, is_operation_file: bool = False) -> str: # pylint: disable=unused-argument
350
+ def type_annotation(
351
+ self, *, is_operation_file: bool = False # pylint: disable=unused-argument
352
+ ) -> str:
333
353
  return "datetime.datetime"
334
354
 
335
355
  @property
@@ -361,7 +381,9 @@ class DateSchema(PrimitiveSchema):
361
381
  def docstring_type(self) -> str:
362
382
  return "~" + self.type_annotation()
363
383
 
364
- def type_annotation(self, *, is_operation_file: bool = False) -> str: # pylint: disable=unused-argument
384
+ def type_annotation(
385
+ self, *, is_operation_file: bool = False # pylint: disable=unused-argument
386
+ ) -> str:
365
387
  return "datetime.date"
366
388
 
367
389
  @property
@@ -393,7 +415,9 @@ class DurationSchema(PrimitiveSchema):
393
415
  def docstring_type(self) -> str:
394
416
  return "~" + self.type_annotation()
395
417
 
396
- def type_annotation(self, *, is_operation_file: bool = False) -> str: # pylint: disable=unused-argument
418
+ def type_annotation(
419
+ self, *, is_operation_file: bool = False # pylint: disable=unused-argument
420
+ ) -> str:
397
421
  return "datetime.timedelta"
398
422
 
399
423
  @property
@@ -417,8 +441,8 @@ class DurationSchema(PrimitiveSchema):
417
441
 
418
442
 
419
443
  class ByteArraySchema(PrimitiveSchema):
420
- def __init__(self, namespace: str, yaml_data: Dict[str, Any]) -> None:
421
- super(ByteArraySchema, self).__init__(namespace=namespace, yaml_data=yaml_data)
444
+ def __init__(self, yaml_data: Dict[str, Any], code_model: "CodeModel") -> None:
445
+ super().__init__(yaml_data=yaml_data, code_model=code_model)
422
446
  self.format = self.Formats(yaml_data["format"])
423
447
 
424
448
  class Formats(str, Enum):
@@ -443,7 +467,9 @@ class ByteArraySchema(PrimitiveSchema):
443
467
  return f'bytearray("{value}", encoding="utf-8")'
444
468
 
445
469
 
446
- def get_primitive_schema(namespace: str, yaml_data: Dict[str, Any]) -> "PrimitiveSchema":
470
+ def get_primitive_schema(
471
+ yaml_data: Dict[str, Any], code_model: "CodeModel"
472
+ ) -> "PrimitiveSchema":
447
473
  mapping = {
448
474
  "integer": NumberSchema,
449
475
  "number": NumberSchema,
@@ -457,10 +483,13 @@ def get_primitive_schema(namespace: str, yaml_data: Dict[str, Any]) -> "Primitiv
457
483
  "byte-array": ByteArraySchema,
458
484
  "any": AnySchema,
459
485
  "any-object": AnySchema,
460
- "binary": IOSchema
486
+ "binary": IOSchema,
461
487
  }
462
488
  schema_type = yaml_data["type"]
463
489
  primitive_schema = cast(
464
- PrimitiveSchema, mapping.get(schema_type, PrimitiveSchema).from_yaml(namespace=namespace, yaml_data=yaml_data)
490
+ PrimitiveSchema,
491
+ mapping.get(schema_type, PrimitiveSchema).from_yaml(
492
+ yaml_data=yaml_data, code_model=code_model
493
+ ),
465
494
  )
466
495
  return primitive_schema
@@ -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 cast, Any, Dict, Union, List, Optional
6
+ from typing import cast, Any, Dict, Union, List, Optional, TYPE_CHECKING
7
7
 
8
8
  from .base_model import BaseModel
9
9
  from .constant_schema import ConstantSchema
@@ -11,19 +11,24 @@ from .imports import FileImport, ImportType, TypingSection
11
11
  from .base_schema import BaseSchema
12
12
  from .enum_schema import EnumSchema
13
13
 
14
+ if TYPE_CHECKING:
15
+ from .code_model import CodeModel
16
+
17
+
14
18
  class Property(BaseModel): # pylint: disable=too-many-instance-attributes
15
19
  def __init__(
16
20
  self,
17
21
  yaml_data: Dict[str, Any],
22
+ code_model: "CodeModel",
18
23
  name: str,
19
24
  schema: BaseSchema,
20
25
  original_swagger_name: str,
21
26
  *,
22
27
  flattened_names: Optional[List[str]] = None,
23
28
  description: Optional[str] = None,
24
- client_default_value: Optional[Any] = None
29
+ client_default_value: Optional[Any] = None,
25
30
  ) -> None:
26
- super().__init__(yaml_data)
31
+ super().__init__(yaml_data, code_model)
27
32
  self.name = name
28
33
  self.schema = schema
29
34
  self.original_swagger_name = original_swagger_name
@@ -35,15 +40,18 @@ class Property(BaseModel): # pylint: disable=too-many-instance-attributes
35
40
  self.client_default_value = client_default_value
36
41
  self.description = self._create_description(description, yaml_data)
37
42
 
38
-
39
- def _create_description(self, description_input: Optional[str], yaml_data: Dict[str, Any]) -> str:
40
- description: str = description_input or yaml_data["language"]["python"]["description"]
43
+ def _create_description(
44
+ self, description_input: Optional[str], yaml_data: Dict[str, Any]
45
+ ) -> str:
46
+ description: str = (
47
+ description_input or yaml_data["language"]["python"]["description"]
48
+ )
41
49
  if description and description[-1] != ".":
42
50
  description += "."
43
51
  if self.name == "tags":
44
52
  description = "A set of tags. " + description
45
53
  if self.constant:
46
- description += f' Has constant value: {self.constant_declaration}.'
54
+ description += f" Has constant value: {self.constant_declaration}."
47
55
  elif self.required:
48
56
  if description:
49
57
  description = "Required. " + description
@@ -51,13 +59,16 @@ class Property(BaseModel): # pylint: disable=too-many-instance-attributes
51
59
  description = "Required. "
52
60
  elif isinstance(self.schema, ConstantSchema):
53
61
  description += (
54
- f" The only acceptable values to pass in are None and {self.constant_declaration}. " +
55
- f"The default value is {self.default_value_declaration}."
62
+ f" The only acceptable values to pass in are None and {self.constant_declaration}. "
63
+ + f"The default value is {self.default_value_declaration}."
56
64
  )
57
65
  if self.is_discriminator:
58
66
  description += "Constant filled by server. "
59
67
  if isinstance(self.schema, EnumSchema):
60
- values = [self.schema.enum_type.get_declaration(v.value) for v in self.schema.values]
68
+ values = [
69
+ self.schema.enum_type.get_declaration(v.value)
70
+ for v in self.schema.values
71
+ ]
61
72
  if description and description[-1] != " ":
62
73
  description += " "
63
74
  description += "Known values are: {}.".format(", ".join(values))
@@ -70,9 +81,9 @@ class Property(BaseModel): # pylint: disable=too-many-instance-attributes
70
81
  # this bool doesn't consider you to be constant if you are a discriminator
71
82
  # you also have to be required to be considered a constant
72
83
  return (
73
- isinstance(self.schema, ConstantSchema) and
74
- self.required and
75
- not self.is_discriminator
84
+ isinstance(self.schema, ConstantSchema)
85
+ and self.required
86
+ and not self.is_discriminator
76
87
  )
77
88
 
78
89
  @property
@@ -85,29 +96,36 @@ class Property(BaseModel): # pylint: disable=too-many-instance-attributes
85
96
  if self.constant:
86
97
  retval["constant"] = True
87
98
  if self.schema.validation_map:
88
- validation_map_from_schema = cast(Dict[str, Union[bool, int, str]], self.schema.validation_map)
99
+ validation_map_from_schema = cast(
100
+ Dict[str, Union[bool, int, str]], self.schema.validation_map
101
+ )
89
102
  retval.update(validation_map_from_schema)
90
103
  return retval or None
91
104
 
92
105
  @property
93
106
  def escaped_swagger_name(self) -> str:
94
- """Return the RestAPI name correctly escaped for serialization.
95
- """
107
+ """Return the RestAPI name correctly escaped for serialization."""
96
108
  if self.flattened_names:
97
109
  return ".".join(n.replace(".", "\\\\.") for n in self.flattened_names)
98
110
  return self.original_swagger_name.replace(".", "\\\\.")
99
111
 
100
112
  @classmethod
101
- def from_yaml(cls, yaml_data: Dict[str, Any], **kwargs) -> "Property":
113
+ def from_yaml(
114
+ cls,
115
+ yaml_data: Dict[str, Any],
116
+ code_model: "CodeModel",
117
+ *,
118
+ has_additional_properties: Optional[bool] = None,
119
+ ) -> "Property":
102
120
  from . import build_schema # pylint: disable=import-outside-toplevel
103
121
 
104
122
  name = yaml_data["language"]["python"]["name"]
105
- has_additional_properties = kwargs.pop("has_additional_properties", None)
106
123
  if name == "additional_properties" and has_additional_properties:
107
124
  name = "additional_properties1"
108
- schema = build_schema(yaml_data=yaml_data["schema"], **kwargs)
125
+ schema = build_schema(yaml_data=yaml_data["schema"], code_model=code_model)
109
126
  return cls(
110
127
  yaml_data=yaml_data,
128
+ code_model=code_model,
111
129
  name=name,
112
130
  schema=schema,
113
131
  original_swagger_name=yaml_data["serializedName"],
@@ -126,7 +144,7 @@ class Property(BaseModel): # pylint: disable=too-many-instance-attributes
126
144
  return self.schema.get_declaration(self.schema.value)
127
145
  raise ValueError(
128
146
  "Trying to get constant declaration for a schema that is not ConstantSchema"
129
- )
147
+ )
130
148
  raise ValueError("Trying to get a declaration for a schema that doesn't exist")
131
149
 
132
150
  @property
@@ -157,18 +175,18 @@ class Property(BaseModel): # pylint: disable=too-many-instance-attributes
157
175
  def get_json_template_representation(self, **kwargs: Any) -> Any:
158
176
  kwargs["optional"] = not self.required
159
177
  if self.default_value:
160
- kwargs["default_value_declaration"] = self.schema.get_declaration(self.default_value)
178
+ kwargs["default_value_declaration"] = self.schema.get_declaration(
179
+ self.default_value
180
+ )
161
181
  if self.description:
162
182
  kwargs["description"] = self.description
163
183
  return self.schema.get_json_template_representation(**kwargs)
164
184
 
165
- def get_files_and_data_template_representation(self, **kwargs: Any) -> Any:
166
- kwargs["optional"] = not self.required
167
- return self.schema.get_files_and_data_template_representation(**kwargs)
168
-
169
185
  def model_file_imports(self) -> FileImport:
170
186
  file_import = self.schema.model_file_imports()
171
187
  if not self.required:
172
- file_import.add_submodule_import("typing", "Optional", ImportType.STDLIB, TypingSection.CONDITIONAL)
188
+ file_import.add_submodule_import(
189
+ "typing", "Optional", ImportType.STDLIB, TypingSection.CONDITIONAL
190
+ )
173
191
  file_import.merge(self.schema.model_file_imports())
174
192
  return file_import
@@ -3,7 +3,8 @@
3
3
  # Licensed under the MIT License. See License.txt in the project root for
4
4
  # license information.
5
5
  # --------------------------------------------------------------------------
6
- from typing import Any, Dict, List, TypeVar, Optional
6
+ from typing import Any, Dict, List, TypeVar, Optional, TYPE_CHECKING
7
+ import logging
7
8
 
8
9
  from .base_builder import BaseBuilder, create_parameters
9
10
  from .request_builder_parameter import RequestBuilderParameter
@@ -13,15 +14,20 @@ from .schema_response import SchemaResponse
13
14
  from .imports import FileImport, ImportType, TypingSection
14
15
  from .parameter import Parameter
15
16
 
17
+ if TYPE_CHECKING:
18
+ from .code_model import CodeModel
16
19
 
17
- T = TypeVar('T')
20
+ _LOGGER = logging.getLogger(__name__)
21
+
22
+ T = TypeVar("T")
18
23
  OrderedSet = Dict[T, None]
19
24
 
25
+
20
26
  class RequestBuilder(BaseBuilder):
21
27
  def __init__(
22
28
  self,
23
- code_model,
24
29
  yaml_data: Dict[str, Any],
30
+ code_model: "CodeModel",
25
31
  name: str,
26
32
  url: str,
27
33
  method: str,
@@ -31,16 +37,20 @@ class RequestBuilder(BaseBuilder):
31
37
  description: str,
32
38
  summary: str,
33
39
  responses: Optional[List[SchemaResponse]] = None,
40
+ *,
41
+ abstract: bool = False,
34
42
  ):
35
43
  super().__init__(
36
- code_model=code_model,
37
44
  yaml_data=yaml_data,
45
+ code_model=code_model,
38
46
  name=name,
39
47
  description=description,
40
48
  parameters=parameters,
41
49
  responses=responses,
42
50
  schema_requests=schema_requests,
43
51
  summary=summary,
52
+ abstract=abstract,
53
+ want_tracing=False,
44
54
  )
45
55
  self.url = url
46
56
  self.method = method
@@ -65,62 +75,86 @@ class RequestBuilder(BaseBuilder):
65
75
 
66
76
  def imports(self) -> FileImport:
67
77
  file_import = FileImport()
68
- for parameter in self.parameters:
69
- if parameter.need_import:
70
- file_import.merge(parameter.imports())
78
+ for parameter in self.parameters.method:
79
+ if self.abstract and (parameter.is_multipart or parameter.is_data_input):
80
+ continue
81
+ file_import.merge(parameter.imports())
71
82
 
72
83
  file_import.add_submodule_import(
73
84
  "azure.core.rest",
74
85
  "HttpRequest",
75
86
  ImportType.AZURECORE,
76
87
  )
77
- if self.parameters.path:
78
- relative_path = ".."
79
- if not self.code_model.options["builders_visibility"] == "embedded" and self.operation_group_name:
80
- relative_path = "..." if self.operation_group_name else ".."
81
- file_import.add_submodule_import(
82
- f"{relative_path}_vendor", "_format_url_section", ImportType.LOCAL
83
- )
84
- if self.parameters.headers or self.parameters.query:
85
- file_import.add_submodule_import("azure.core.utils", "case_insensitive_dict", ImportType.AZURECORE)
88
+ if not self.abstract:
89
+ if self.parameters.path:
90
+ relative_path = ".."
91
+ if (
92
+ not self.code_model.options["builders_visibility"] == "embedded"
93
+ and self.operation_group_name
94
+ ):
95
+ relative_path = "..." if self.operation_group_name else ".."
96
+ file_import.add_submodule_import(
97
+ f"{relative_path}_vendor", "_format_url_section", ImportType.LOCAL
98
+ )
99
+ if self.parameters.headers or self.parameters.query:
100
+ file_import.add_submodule_import(
101
+ "azure.core.utils", "case_insensitive_dict", ImportType.AZURECORE
102
+ )
86
103
  file_import.add_submodule_import(
87
104
  "typing", "Any", ImportType.STDLIB, typing_section=TypingSection.CONDITIONAL
88
105
  )
89
106
  file_import.add_submodule_import("msrest", "Serializer", ImportType.THIRDPARTY)
90
- if self.parameters.has_body and (
91
- self.code_model.options["builders_visibility"] != "embedded" or
92
- self.code_model.options["add_python3_operation_files"]
93
- ):
94
- file_import.define_mypy_type("JSONType", "Any")
95
107
  return file_import
96
108
 
97
109
  @classmethod
98
- def from_yaml(cls, yaml_data: Dict[str, Any], *, code_model) -> "RequestBuilder":
110
+ def from_yaml(
111
+ cls, yaml_data: Dict[str, Any], code_model: "CodeModel"
112
+ ) -> "RequestBuilder":
99
113
 
100
114
  # when combine embeded builders into one operation file, we need to avoid duplicated build function name.
101
115
  # So add operation group name is effective method
102
116
  additional_mark = ""
103
- if code_model.options["combine_operation_files"] and code_model.options["builders_visibility"] == "embedded":
117
+ if (
118
+ code_model.options["combine_operation_files"]
119
+ and code_model.options["builders_visibility"] == "embedded"
120
+ ):
104
121
  additional_mark = yaml_data["language"]["python"]["builderGroupName"]
105
122
  names = [
106
123
  "build",
107
124
  additional_mark,
108
125
  yaml_data["language"]["python"]["name"],
109
- "request"
126
+ "request",
110
127
  ]
111
128
  name = "_".join([n for n in names if n])
112
129
 
113
130
  first_request = yaml_data["requests"][0]
114
- schema_requests = [SchemaRequest.from_yaml(yaml, code_model=code_model) for yaml in yaml_data["requests"]]
115
- parameters, multiple_content_type_parameters = (
116
- create_parameters(yaml_data, code_model, RequestBuilderParameter.from_yaml)
131
+ schema_requests = [
132
+ SchemaRequest.from_yaml(yaml, code_model=code_model)
133
+ for yaml in yaml_data["requests"]
134
+ ]
135
+ parameters, multiple_content_type_parameters = create_parameters(
136
+ yaml_data, code_model, RequestBuilderParameter.from_yaml
117
137
  )
118
138
  parameter_list = RequestBuilderParameterList(
119
139
  code_model, parameters + multiple_content_type_parameters, schema_requests
120
140
  )
141
+ abstract = False
142
+ if (
143
+ code_model.options["version_tolerant"]
144
+ or code_model.options["low_level_client"]
145
+ ) and any(p for p in parameter_list if p.is_multipart or p.is_data_input):
146
+ _LOGGER.warning(
147
+ 'Not going to generate request_builder "%s" because it has multipart / urlencoded '
148
+ "body parameters. Multipart / urlencoded body parameters are not supported for version "
149
+ "tolerant and low level generations right now. Please write your own custom operation "
150
+ "in the _patch.py file following https://aka.ms/azsdk/python/dpcodegen/python/customize.",
151
+ name,
152
+ )
153
+ abstract = True
154
+
121
155
  request_builder_class = cls(
122
- code_model=code_model,
123
156
  yaml_data=yaml_data,
157
+ code_model=code_model,
124
158
  name=name,
125
159
  url=first_request["protocol"]["http"]["path"],
126
160
  method=first_request["protocol"]["http"]["method"].upper(),
@@ -129,10 +163,11 @@ class RequestBuilder(BaseBuilder):
129
163
  parameters=parameter_list,
130
164
  description=yaml_data["language"]["python"]["description"],
131
165
  responses=[
132
- SchemaResponse.from_yaml(yaml, code_model=code_model) for yaml in yaml_data.get("responses", [])
166
+ SchemaResponse.from_yaml(yaml, code_model=code_model)
167
+ for yaml in yaml_data.get("responses", [])
133
168
  ],
134
169
  summary=yaml_data["language"]["python"].get("summary"),
170
+ abstract=abstract,
135
171
  )
136
- code_model.request_builder_ids[id(yaml_data)] = request_builder_class
137
172
  parameter_list.add_body_kwargs()
138
173
  return request_builder_class