@autorest/python 5.13.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 (101) hide show
  1. package/ChangeLog.md +67 -0
  2. package/autorest/__init__.py +1 -2
  3. package/autorest/black/__init__.py +12 -5
  4. package/autorest/codegen/__init__.py +239 -105
  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 +21 -24
  9. package/autorest/codegen/models/client.py +70 -20
  10. package/autorest/codegen/models/code_model.py +144 -129
  11. package/autorest/codegen/models/constant_schema.py +32 -16
  12. package/autorest/codegen/models/credential_model.py +55 -0
  13. package/autorest/codegen/models/credential_schema.py +21 -16
  14. package/autorest/codegen/models/credential_schema_policy.py +11 -15
  15. package/autorest/codegen/models/dictionary_schema.py +27 -24
  16. package/autorest/codegen/models/enum_schema.py +41 -62
  17. package/autorest/codegen/models/imports.py +72 -41
  18. package/autorest/codegen/models/list_schema.py +40 -18
  19. package/autorest/codegen/models/lro_operation.py +61 -25
  20. package/autorest/codegen/models/lro_paging_operation.py +5 -6
  21. package/autorest/codegen/models/object_schema.py +113 -59
  22. package/autorest/codegen/models/operation.py +251 -111
  23. package/autorest/codegen/models/operation_group.py +67 -32
  24. package/autorest/codegen/models/paging_operation.py +48 -21
  25. package/autorest/codegen/models/parameter.py +182 -90
  26. package/autorest/codegen/models/parameter_list.py +184 -163
  27. package/autorest/codegen/models/primitive_schemas.py +89 -70
  28. package/autorest/codegen/models/property.py +49 -31
  29. package/autorest/codegen/models/request_builder.py +67 -32
  30. package/autorest/codegen/models/request_builder_parameter.py +54 -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 +35 -17
  34. package/autorest/codegen/models/utils.py +24 -1
  35. package/autorest/codegen/serializers/__init__.py +273 -89
  36. package/autorest/codegen/serializers/builder_serializer.py +711 -333
  37. package/autorest/codegen/serializers/client_serializer.py +114 -43
  38. package/autorest/codegen/serializers/general_serializer.py +84 -25
  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 +42 -14
  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 +9 -8
  45. package/autorest/codegen/serializers/operation_groups_serializer.py +20 -8
  46. package/autorest/codegen/serializers/operations_init_serializer.py +23 -11
  47. package/autorest/codegen/serializers/patch_serializer.py +14 -2
  48. package/autorest/codegen/serializers/{rest_serializer.py → request_builders_serializer.py} +29 -12
  49. package/autorest/codegen/serializers/utils.py +60 -21
  50. package/autorest/codegen/templates/CHANGELOG.md.jinja2 +6 -0
  51. package/autorest/codegen/templates/LICENSE.jinja2 +21 -0
  52. package/autorest/codegen/templates/MANIFEST.in.jinja2 +7 -0
  53. package/autorest/codegen/templates/README.md.jinja2 +105 -0
  54. package/autorest/codegen/templates/config.py.jinja2 +4 -4
  55. package/autorest/codegen/templates/dev_requirements.txt.jinja2 +10 -0
  56. package/autorest/codegen/templates/enum.py.jinja2 +1 -1
  57. package/autorest/codegen/templates/enum_container.py.jinja2 +0 -1
  58. package/autorest/codegen/templates/init.py.jinja2 +9 -6
  59. package/autorest/codegen/templates/keywords.jinja2 +14 -1
  60. package/autorest/codegen/templates/lro_operation.py.jinja2 +5 -7
  61. package/autorest/codegen/templates/lro_paging_operation.py.jinja2 +5 -7
  62. package/autorest/codegen/templates/metadata.json.jinja2 +10 -9
  63. package/autorest/codegen/templates/model.py.jinja2 +1 -6
  64. package/autorest/codegen/templates/model_init.py.jinja2 +7 -4
  65. package/autorest/codegen/templates/operation.py.jinja2 +8 -11
  66. package/autorest/codegen/templates/operation_group.py.jinja2 +15 -18
  67. package/autorest/codegen/templates/operation_groups_container.py.jinja2 +1 -2
  68. package/autorest/codegen/templates/operations_folder_init.py.jinja2 +4 -0
  69. package/autorest/codegen/templates/paging_operation.py.jinja2 +7 -8
  70. package/autorest/codegen/templates/patch.py.jinja2 +18 -29
  71. package/autorest/codegen/templates/request_builder.py.jinja2 +19 -14
  72. package/autorest/codegen/templates/setup.py.jinja2 +79 -20
  73. package/autorest/codegen/templates/vendor.py.jinja2 +12 -2
  74. package/autorest/jsonrpc/__init__.py +7 -12
  75. package/autorest/jsonrpc/localapi.py +4 -3
  76. package/autorest/jsonrpc/server.py +13 -6
  77. package/autorest/jsonrpc/stdstream.py +13 -6
  78. package/autorest/m2r/__init__.py +5 -8
  79. package/autorest/multiapi/__init__.py +24 -14
  80. package/autorest/multiapi/models/client.py +21 -11
  81. package/autorest/multiapi/models/code_model.py +23 -10
  82. package/autorest/multiapi/models/config.py +4 -1
  83. package/autorest/multiapi/models/constant_global_parameter.py +1 -0
  84. package/autorest/multiapi/models/global_parameter.py +2 -1
  85. package/autorest/multiapi/models/global_parameters.py +14 -8
  86. package/autorest/multiapi/models/imports.py +35 -18
  87. package/autorest/multiapi/models/mixin_operation.py +5 -5
  88. package/autorest/multiapi/models/operation_group.py +2 -1
  89. package/autorest/multiapi/models/operation_mixin_group.py +21 -10
  90. package/autorest/multiapi/serializers/__init__.py +18 -23
  91. package/autorest/multiapi/serializers/import_serializer.py +47 -15
  92. package/autorest/multiapi/serializers/multiapi_serializer.py +17 -17
  93. package/autorest/multiapi/templates/multiapi_operations_mixin.py.jinja2 +1 -1
  94. package/autorest/multiapi/utils.py +3 -3
  95. package/autorest/namer/__init__.py +2 -4
  96. package/autorest/namer/name_converter.py +200 -103
  97. package/autorest/namer/python_mappings.py +10 -22
  98. package/package.json +3 -3
  99. package/run-python3.js +2 -3
  100. package/venvtools.py +1 -1
  101. package/autorest/codegen/models/rest.py +0 -42
@@ -3,23 +3,26 @@
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, Optional, Union
6
+ from typing import Any, Dict, Optional, Union, TYPE_CHECKING
7
7
  from .base_schema import BaseSchema
8
8
  from .imports import FileImport, ImportType, TypingSection
9
9
 
10
+ if TYPE_CHECKING:
11
+ from .code_model import CodeModel
12
+
10
13
 
11
14
  class ListSchema(BaseSchema):
12
15
  def __init__(
13
16
  self,
14
- namespace: str,
15
17
  yaml_data: Dict[str, Any],
18
+ code_model: "CodeModel",
16
19
  element_type: BaseSchema,
17
20
  *,
18
21
  max_items: Optional[int] = None,
19
22
  min_items: Optional[int] = None,
20
23
  unique_items: Optional[int] = None,
21
24
  ) -> None:
22
- super(ListSchema, self).__init__(namespace=namespace, yaml_data=yaml_data)
25
+ super().__init__(yaml_data=yaml_data, code_model=code_model)
23
26
  self.element_type = element_type
24
27
  self.max_items = max_items
25
28
  self.min_items = min_items
@@ -29,20 +32,26 @@ class ListSchema(BaseSchema):
29
32
  def serialization_type(self) -> str:
30
33
  return f"[{self.element_type.serialization_type}]"
31
34
 
32
- @property
33
- def type_annotation(self) -> str:
34
- return f"List[{self.element_type.type_annotation}]"
35
-
36
- @property
37
- def operation_type_annotation(self) -> str:
38
- return f"List[{self.element_type.operation_type_annotation}]"
35
+ def type_annotation(self, *, is_operation_file: bool = False) -> str:
36
+ if self.element_type.type_annotation() == "ET.Element":
37
+ # this means we're version tolerant XML, we just return the XML element
38
+ return self.element_type.type_annotation(
39
+ is_operation_file=is_operation_file
40
+ )
41
+ return f"List[{self.element_type.type_annotation(is_operation_file=is_operation_file)}]"
39
42
 
40
43
  @property
41
44
  def docstring_type(self) -> str:
45
+ if self.element_type.docstring_type == "ET.Element":
46
+ # this means we're version tolerant XML, we just return the XML element
47
+ return self.element_type.docstring_type
42
48
  return f"list[{self.element_type.docstring_type}]"
43
49
 
44
50
  @property
45
51
  def docstring_text(self) -> str:
52
+ if self.element_type.docstring_text == "XML Element":
53
+ # this means we're version tolerant XML, we just return the XML element
54
+ return self.element_type.docstring_text
46
55
  return f"list of {self.element_type.docstring_text}"
47
56
 
48
57
  @property
@@ -59,14 +68,14 @@ class ListSchema(BaseSchema):
59
68
 
60
69
  @property
61
70
  def has_xml_serialization_ctxt(self) -> bool:
62
- return super().has_xml_serialization_ctxt or self.element_type.has_xml_serialization_ctxt
71
+ return (
72
+ super().has_xml_serialization_ctxt
73
+ or self.element_type.has_xml_serialization_ctxt
74
+ )
63
75
 
64
76
  def get_json_template_representation(self, **kwargs: Any) -> Any:
65
77
  return [self.element_type.get_json_template_representation(**kwargs)]
66
78
 
67
- def get_files_and_data_template_representation(self, **kwargs: Any) -> Any:
68
- return [self.element_type.get_files_and_data_template_representation(**kwargs)]
69
-
70
79
  def xml_serialization_ctxt(self) -> Optional[str]:
71
80
  attrs_list = []
72
81
  base_xml_map = super().xml_serialization_ctxt()
@@ -89,17 +98,19 @@ class ListSchema(BaseSchema):
89
98
  return ", ".join(attrs_list)
90
99
 
91
100
  @classmethod
92
- def from_yaml(cls, namespace: str, yaml_data: Dict[str, Any], **kwargs) -> "ListSchema":
101
+ def from_yaml(
102
+ cls, yaml_data: Dict[str, Any], code_model: "CodeModel"
103
+ ) -> "ListSchema":
93
104
  # TODO: for items, if the type is a primitive is it listed in type instead of $ref?
94
105
  element_schema = yaml_data["elementType"]
95
106
 
96
107
  from . import build_schema # pylint: disable=import-outside-toplevel
97
108
 
98
- element_type = build_schema(yaml_data=element_schema, **kwargs)
109
+ element_type = build_schema(yaml_data=element_schema, code_model=code_model)
99
110
 
100
111
  return cls(
101
- namespace=namespace,
102
112
  yaml_data=yaml_data,
113
+ code_model=code_model,
103
114
  element_type=element_type,
104
115
  max_items=yaml_data.get("maxItems"),
105
116
  min_items=yaml_data.get("minItems"),
@@ -108,6 +119,17 @@ class ListSchema(BaseSchema):
108
119
 
109
120
  def imports(self) -> FileImport:
110
121
  file_import = FileImport()
111
- file_import.add_submodule_import("typing", "List", ImportType.STDLIB, TypingSection.CONDITIONAL)
122
+ if (
123
+ not self.element_type.type_annotation(is_operation_file=True)
124
+ == "ET.Element"
125
+ ):
126
+ file_import.add_submodule_import(
127
+ "typing", "List", ImportType.STDLIB, TypingSection.CONDITIONAL
128
+ )
112
129
  file_import.merge(self.element_type.imports())
113
130
  return file_import
131
+
132
+ def model_file_imports(self) -> FileImport:
133
+ file_import = self.imports()
134
+ file_import.merge(self.element_type.model_file_imports())
135
+ return file_import
@@ -4,7 +4,7 @@
4
4
  # license information.
5
5
  # --------------------------------------------------------------------------
6
6
  import logging
7
- from typing import Dict, List, Any, Optional, Set, cast
7
+ from typing import Dict, List, Any, Optional, Set, cast, TYPE_CHECKING
8
8
  from .imports import FileImport
9
9
  from .operation import Operation
10
10
  from .parameter_list import ParameterList
@@ -12,6 +12,10 @@ from .schema_response import SchemaResponse
12
12
  from .imports import ImportType, TypingSection
13
13
  from .base_schema import BaseSchema
14
14
  from .schema_request import SchemaRequest
15
+ from .request_builder import RequestBuilder
16
+
17
+ if TYPE_CHECKING:
18
+ from .code_model import CodeModel
15
19
 
16
20
  _LOGGER = logging.getLogger(__name__)
17
21
 
@@ -19,8 +23,9 @@ _LOGGER = logging.getLogger(__name__)
19
23
  class LROOperation(Operation):
20
24
  def __init__(
21
25
  self,
22
- code_model,
23
26
  yaml_data: Dict[str, Any],
27
+ code_model: "CodeModel",
28
+ request_builder: RequestBuilder,
24
29
  name: str,
25
30
  description: str,
26
31
  api_versions: Set[str],
@@ -31,11 +36,14 @@ class LROOperation(Operation):
31
36
  responses: Optional[List[SchemaResponse]] = None,
32
37
  exceptions: Optional[List[SchemaResponse]] = None,
33
38
  want_description_docstring: bool = True,
34
- want_tracing: bool = True
39
+ want_tracing: bool = True,
40
+ *,
41
+ abstract: bool = False,
35
42
  ) -> None:
36
- super(LROOperation, self).__init__(
37
- code_model,
43
+ super().__init__(
38
44
  yaml_data,
45
+ code_model,
46
+ request_builder,
39
47
  name,
40
48
  description,
41
49
  api_versions,
@@ -46,9 +54,12 @@ class LROOperation(Operation):
46
54
  responses,
47
55
  exceptions,
48
56
  want_description_docstring,
49
- want_tracing,
57
+ want_tracing=want_tracing,
58
+ abstract=abstract,
59
+ )
60
+ self.lro_options = yaml_data.get("extensions", {}).get(
61
+ "x-ms-long-running-operation-options", {}
50
62
  )
51
- self.lro_options = yaml_data.get("extensions", {}).get("x-ms-long-running-operation-options", {})
52
63
  self.name = "begin_" + self.name
53
64
 
54
65
  @property
@@ -68,12 +79,14 @@ class LROOperation(Operation):
68
79
  schema_types = {r.schema for r in responses_with_bodies}
69
80
  response_schema = cast(BaseSchema, response.schema).serialization_type
70
81
  _LOGGER.warning(
71
- "Multiple schema types in responses: %s. Choosing: %s", schema_types, response_schema
82
+ "Multiple schema types in responses: %s. Choosing: %s",
83
+ schema_types,
84
+ response_schema,
72
85
  )
73
86
  except IndexError:
74
87
  raise ValueError(
75
- f"Your swagger is invalid because you have multiple response schemas for LRO" +
76
- f" method {self.python_name} and none of them have a 200 status code."
88
+ f"Your swagger is invalid because you have multiple response schemas for LRO"
89
+ + f" method {self.python_name} and none of them have a 200 status code."
77
90
  )
78
91
 
79
92
  elif num_response_schemas:
@@ -83,8 +96,9 @@ class LROOperation(Operation):
83
96
  @property
84
97
  def initial_operation(self) -> Operation:
85
98
  operation = Operation(
86
- self.code_model,
87
99
  yaml_data={},
100
+ code_model=self.code_model,
101
+ request_builder=self.code_model.lookup_request_builder(id(self.yaml_data)),
88
102
  name=self.name[5:] + "_initial",
89
103
  description="",
90
104
  api_versions=self.api_versions,
@@ -119,10 +133,14 @@ class LROOperation(Operation):
119
133
  return self.get_poller_path(async_mode).split(".")[-1]
120
134
 
121
135
  def get_default_polling_method_path(self, async_mode: bool, azure_arm: bool) -> str:
122
- return self._get_lro_extension("default-polling-method", async_mode, azure_arm=azure_arm)
136
+ return self._get_lro_extension(
137
+ "default-polling-method", async_mode, azure_arm=azure_arm
138
+ )
123
139
 
124
140
  def get_default_polling_method(self, async_mode: bool, azure_arm: bool) -> str:
125
- return self.get_default_polling_method_path(async_mode, azure_arm).split(".")[-1]
141
+ return self.get_default_polling_method_path(async_mode, azure_arm).split(".")[
142
+ -1
143
+ ]
126
144
 
127
145
  def get_default_no_polling_method_path(self, async_mode: bool) -> str:
128
146
  return self._get_lro_extension("default-no-polling-method", async_mode)
@@ -140,23 +158,35 @@ class LROOperation(Operation):
140
158
  file_import = super().imports_for_multiapi(async_mode)
141
159
  poller_import_path = ".".join(self.get_poller_path(async_mode).split(".")[:-1])
142
160
  poller = self.get_poller(async_mode)
143
- file_import.add_submodule_import(poller_import_path, poller, ImportType.AZURECORE, TypingSection.CONDITIONAL)
161
+ file_import.add_submodule_import(
162
+ poller_import_path, poller, ImportType.AZURECORE, TypingSection.CONDITIONAL
163
+ )
144
164
  return file_import
145
165
 
146
- def imports(self, async_mode: bool) -> FileImport:
147
- file_import = super().imports(async_mode)
148
- file_import.add_submodule_import("typing", "Union", ImportType.STDLIB, TypingSection.CONDITIONAL)
166
+ def imports(self, async_mode: bool, is_python3_file: bool) -> FileImport:
167
+ file_import = self._imports_base(async_mode, is_python3_file)
168
+ file_import.add_submodule_import(
169
+ "typing", "Union", ImportType.STDLIB, TypingSection.CONDITIONAL
170
+ )
149
171
 
150
172
  poller_import_path = ".".join(self.get_poller_path(async_mode).split(".")[:-1])
151
173
  poller = self.get_poller(async_mode)
152
- file_import.add_submodule_import(poller_import_path, poller, ImportType.AZURECORE)
174
+ file_import.add_submodule_import(
175
+ poller_import_path, poller, ImportType.AZURECORE
176
+ )
153
177
 
154
178
  default_polling_method_import_path = ".".join(
155
- self.get_default_polling_method_path(async_mode, self.code_model.options['azure_arm']).split(".")[:-1]
179
+ self.get_default_polling_method_path(
180
+ async_mode, self.code_model.options["azure_arm"]
181
+ ).split(".")[:-1]
182
+ )
183
+ default_polling_method = self.get_default_polling_method(
184
+ async_mode, self.code_model.options["azure_arm"]
156
185
  )
157
- default_polling_method = self.get_default_polling_method(async_mode, self.code_model.options['azure_arm'])
158
186
  file_import.add_submodule_import(
159
- default_polling_method_import_path, default_polling_method, ImportType.AZURECORE
187
+ default_polling_method_import_path,
188
+ default_polling_method,
189
+ ImportType.AZURECORE,
160
190
  )
161
191
 
162
192
  default_no_polling_method_import_path = ".".join(
@@ -164,17 +194,23 @@ class LROOperation(Operation):
164
194
  )
165
195
  default_no_polling_method = self.get_default_no_polling_method(async_mode)
166
196
  file_import.add_submodule_import(
167
- default_no_polling_method_import_path, default_no_polling_method, ImportType.AZURECORE
197
+ default_no_polling_method_import_path,
198
+ default_no_polling_method,
199
+ ImportType.AZURECORE,
168
200
  )
169
201
 
170
202
  base_polling_method_import_path = ".".join(
171
203
  self.get_base_polling_method_path(async_mode).split(".")[:-1]
172
204
  )
173
205
  base_polling_method = self.get_base_polling_method(async_mode)
174
- file_import.add_submodule_import(base_polling_method_import_path, base_polling_method, ImportType.AZURECORE)
175
-
206
+ file_import.add_submodule_import(
207
+ base_polling_method_import_path, base_polling_method, ImportType.AZURECORE
208
+ )
209
+ file_import.add_submodule_import("typing", "cast", ImportType.STDLIB)
176
210
  if async_mode:
177
- file_import.add_submodule_import("typing", "Optional", ImportType.STDLIB, TypingSection.CONDITIONAL)
211
+ file_import.add_submodule_import(
212
+ "typing", "Optional", ImportType.STDLIB, TypingSection.CONDITIONAL
213
+ )
178
214
  if self.code_model.options["tracing"] and self.want_tracing:
179
215
  file_import.add_submodule_import(
180
216
  f"azure.core.tracing.decorator{'_async' if async_mode else ''}",
@@ -7,11 +7,11 @@ from .imports import FileImport
7
7
  from .lro_operation import LROOperation
8
8
  from .paging_operation import PagingOperation
9
9
 
10
- class LROPagingOperation(PagingOperation, LROOperation):
11
10
 
12
- def imports(self, async_mode: bool) -> FileImport:
13
- lro_imports = LROOperation.imports(self, async_mode)
14
- paging_imports = PagingOperation.imports(self, async_mode)
11
+ class LROPagingOperation(PagingOperation, LROOperation):
12
+ def imports(self, async_mode: bool, is_python3_file: bool) -> FileImport:
13
+ lro_imports = LROOperation.imports(self, async_mode, is_python3_file)
14
+ paging_imports = PagingOperation.imports(self, async_mode, is_python3_file)
15
15
 
16
16
  file_import = lro_imports
17
17
  file_import.merge(paging_imports)
@@ -19,6 +19,5 @@ class LROPagingOperation(PagingOperation, LROOperation):
19
19
 
20
20
  @property
21
21
  def success_status_code(self):
22
- """The list of all successfull status code.
23
- """
22
+ """The list of all successfull status code."""
24
23
  return [200]
@@ -3,11 +3,14 @@
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, Optional, Union, Type
6
+ from typing import Any, Dict, List, Optional, Union, Type, TYPE_CHECKING
7
7
  from .base_schema import BaseSchema
8
8
  from .dictionary_schema import DictionarySchema
9
9
  from .property import Property
10
- from .imports import FileImport, ImportType, TypingSection
10
+ from .imports import FileImport, ImportModel, ImportType, TypingSection
11
+
12
+ if TYPE_CHECKING:
13
+ from .code_model import CodeModel
11
14
 
12
15
 
13
16
  class ObjectSchema(BaseSchema): # pylint: disable=too-many-instance-attributes
@@ -20,36 +23,41 @@ class ObjectSchema(BaseSchema): # pylint: disable=too-many-instance-attributes
20
23
  """
21
24
 
22
25
  def __init__(
23
- self, namespace: str, yaml_data: Dict[str, Any], name: str, description: str = "", **kwargs
26
+ self,
27
+ yaml_data: Dict[str, Any],
28
+ code_model: "CodeModel",
29
+ name: str,
30
+ description: str = "",
31
+ **kwargs,
24
32
  ) -> None:
25
- super(ObjectSchema, self).__init__(namespace=namespace, yaml_data=yaml_data)
33
+ super().__init__(yaml_data=yaml_data, code_model=code_model)
26
34
  self.name = name
27
35
  self.description = description
28
36
  self.max_properties: Optional[int] = kwargs.pop("max_properties", None)
29
37
  self.min_properties: Optional[int] = kwargs.pop("min_properties", None)
30
38
  self.properties: List[Property] = kwargs.pop("properties", [])
31
39
  self.is_exception: bool = kwargs.pop("is_exception", False)
32
- self.base_models: Union[List[int], List["ObjectSchema"]] = kwargs.pop("base_models", [])
40
+ self.base_models: Union[List[int], List["ObjectSchema"]] = kwargs.pop(
41
+ "base_models", []
42
+ )
33
43
  self.subtype_map: Optional[Dict[str, str]] = kwargs.pop("subtype_map", None)
34
44
  self.discriminator_name: Optional[str] = kwargs.pop("discriminator_name", None)
35
- self.discriminator_value: Optional[str] = kwargs.pop("discriminator_value", None)
45
+ self.discriminator_value: Optional[str] = kwargs.pop(
46
+ "discriminator_value", None
47
+ )
36
48
  self._created_json_template_representation = False
37
49
 
38
50
  @property
39
51
  def serialization_type(self) -> str:
40
52
  return self.name
41
53
 
42
- @property
43
- def type_annotation(self) -> str:
44
- return f'"{self.name}"'
45
-
46
- @property
47
- def operation_type_annotation(self) -> str:
48
- return f'"_models.{self.name}"'
54
+ def type_annotation(self, *, is_operation_file: bool = False) -> str:
55
+ retval = f"_models.{self.name}"
56
+ return retval if is_operation_file else f'"{retval}"'
49
57
 
50
58
  @property
51
59
  def docstring_type(self) -> str:
52
- return f"~{self.namespace}.models.{self.name}"
60
+ return f"~{self.code_model.namespace}.models.{self.name}"
53
61
 
54
62
  @property
55
63
  def docstring_text(self) -> str:
@@ -83,18 +91,21 @@ class ObjectSchema(BaseSchema): # pylint: disable=too-many-instance-attributes
83
91
  # don't add additional properties, because there's not really a concept of
84
92
  # additional properties in the template
85
93
  representation = {
86
- f'"{prop.original_swagger_name}"': prop.get_json_template_representation(**kwargs)
94
+ f'"{prop.original_swagger_name}"': prop.get_json_template_representation(
95
+ **kwargs
96
+ )
87
97
  for prop in [
88
- p for p in self.properties
98
+ p
99
+ for p in self.properties
89
100
  if not (p.is_discriminator or p.name == "additional_properties")
90
101
  ]
91
102
  }
92
103
  try:
93
104
  # add discriminator prop if there is one
94
105
  discriminator = next(p for p in self.properties if p.is_discriminator)
95
- representation[
96
- discriminator.original_swagger_name
97
- ] = self.discriminator_value or discriminator.original_swagger_name
106
+ representation[discriminator.original_swagger_name] = (
107
+ self.discriminator_value or discriminator.original_swagger_name
108
+ )
98
109
  except StopIteration:
99
110
  pass
100
111
 
@@ -103,20 +114,10 @@ class ObjectSchema(BaseSchema): # pylint: disable=too-many-instance-attributes
103
114
  self._created_json_template_representation = False
104
115
  return representation
105
116
 
106
- def get_files_and_data_template_representation(self, **kwargs: Any) -> Any:
107
- object_schema_names = kwargs.get("object_schema_names", [])
108
- object_schema_names.append(self.name) # do tis to avoid circular
109
- kwargs["object_schema_names"] = object_schema_names
110
- return {
111
- "{}".format(
112
- prop.original_swagger_name
113
- ): prop.get_files_and_data_template_representation(**kwargs)
114
- for prop in self.properties
115
- }
116
-
117
-
118
117
  @classmethod
119
- def from_yaml(cls, namespace: str, yaml_data: Dict[str, Any], **kwargs) -> "ObjectSchema":
118
+ def from_yaml(
119
+ cls, yaml_data: Dict[str, Any], code_model: "CodeModel"
120
+ ) -> "ObjectSchema":
120
121
  """Returns a ClassType from the dict object constructed from a yaml file.
121
122
 
122
123
  WARNING: This guy might create an infinite loop.
@@ -127,11 +128,13 @@ class ObjectSchema(BaseSchema): # pylint: disable=too-many-instance-attributes
127
128
  :returns: A ClassType.
128
129
  :rtype: ~autorest.models.schema.ClassType
129
130
  """
130
- obj = cls(namespace, yaml_data, "", description="")
131
- obj.fill_instance_from_yaml(namespace, yaml_data)
131
+ obj = cls(yaml_data, code_model, "", description="")
132
+ obj.fill_instance_from_yaml(yaml_data, code_model)
132
133
  return obj
133
134
 
134
- def fill_instance_from_yaml(self, namespace: str, yaml_data: Dict[str, Any], **kwargs) -> None:
135
+ def fill_instance_from_yaml(
136
+ self, yaml_data: Dict[str, Any], code_model: "CodeModel"
137
+ ) -> None:
135
138
  properties = []
136
139
  base_models = []
137
140
 
@@ -145,20 +148,24 @@ class ObjectSchema(BaseSchema): # pylint: disable=too-many-instance-attributes
145
148
  for immediate_parent in immediate_parents:
146
149
  if immediate_parent["type"] == "dictionary":
147
150
  additional_properties_schema = DictionarySchema.from_yaml(
148
- namespace=namespace, yaml_data=immediate_parent, **kwargs
151
+ yaml_data=immediate_parent, code_model=code_model
149
152
  )
150
153
  properties.append(
151
154
  Property(
155
+ yaml_data={},
156
+ code_model=code_model,
152
157
  name="additional_properties",
153
158
  schema=additional_properties_schema,
154
159
  original_swagger_name="",
155
- yaml_data={},
156
- description="Unmatched properties from the message are deserialized to this collection."
160
+ description=(
161
+ "Unmatched properties from the message are "
162
+ "deserialized to this collection."
163
+ ),
157
164
  )
158
165
  )
159
166
  elif (
160
- immediate_parent["language"]["default"]["name"] != name and
161
- immediate_parent['type'] == "object"
167
+ immediate_parent["language"]["default"]["name"] != name
168
+ and immediate_parent["type"] == "object"
162
169
  ):
163
170
  base_models.append(id(immediate_parent))
164
171
 
@@ -168,21 +175,22 @@ class ObjectSchema(BaseSchema): # pylint: disable=too-many-instance-attributes
168
175
  subtype_map = {}
169
176
  # map of discriminator value to child's name
170
177
  for children_yaml in yaml_data["discriminator"]["immediate"].values():
171
- subtype_map[children_yaml["discriminatorValue"]] = children_yaml["language"]["python"]["name"]
178
+ subtype_map[children_yaml["discriminatorValue"]] = children_yaml[
179
+ "language"
180
+ ]["python"]["name"]
172
181
  if yaml_data.get("properties"):
173
182
  properties += [
174
- Property.from_yaml(p, has_additional_properties=len(properties) > 0, **kwargs)
183
+ Property.from_yaml(
184
+ p, code_model, has_additional_properties=len(properties) > 0
185
+ )
175
186
  for p in yaml_data["properties"]
176
187
  ]
177
188
  # this is to ensure that the attribute map type and property type are generated correctly
178
189
 
179
-
180
-
181
190
  description = yaml_data["language"]["python"]["description"]
182
191
  is_exception = False
183
- exceptions_set = kwargs.pop("exceptions_set", None)
184
- if exceptions_set:
185
- if id(yaml_data) in exceptions_set:
192
+ if code_model.exception_ids:
193
+ if id(yaml_data) in code_model.exception_ids:
186
194
  is_exception = True
187
195
 
188
196
  self.yaml_data = yaml_data
@@ -206,43 +214,89 @@ class ObjectSchema(BaseSchema): # pylint: disable=too-many-instance-attributes
206
214
  @property
207
215
  def property_with_discriminator(self) -> Any:
208
216
  try:
209
- return next(p for p in self.properties if getattr(p.schema, "discriminator_name", None))
217
+ return next(
218
+ p
219
+ for p in self.properties
220
+ if getattr(p.schema, "discriminator_name", None)
221
+ )
210
222
  except StopIteration:
211
223
  return None
212
224
 
213
225
  def imports(self) -> FileImport:
214
226
  file_import = FileImport()
215
227
  if self.is_exception:
216
- file_import.add_submodule_import("azure.core.exceptions", "HttpResponseError", ImportType.AZURECORE)
228
+ file_import.add_submodule_import(
229
+ "azure.core.exceptions", "HttpResponseError", ImportType.AZURECORE
230
+ )
231
+ return file_import
232
+
233
+ def model_file_imports(self) -> FileImport:
234
+ file_import = self.imports()
235
+ file_import.add_import(
236
+ "__init__",
237
+ ImportType.LOCAL,
238
+ typing_section=TypingSection.TYPING,
239
+ alias="_models",
240
+ )
217
241
  return file_import
218
242
 
219
- class HiddenModelObjectSchema(ObjectSchema):
220
243
 
244
+ class HiddenModelObjectSchema(ObjectSchema):
221
245
  @property
222
246
  def serialization_type(self) -> str:
223
247
  return "object"
224
248
 
225
- @property
226
- def type_annotation(self) -> str:
227
- return "JSONType"
228
-
229
- @property
230
- def operation_type_annotation(self) -> str:
231
- return "JSONType"
249
+ def type_annotation(
250
+ self, *, is_operation_file: bool = False # pylint: disable=unused-argument
251
+ ) -> str:
252
+ if self.xml_metadata:
253
+ return "ET.Element"
254
+ return "JSON"
232
255
 
233
256
  @property
234
257
  def docstring_type(self) -> str:
235
- return "JSONType"
258
+ if self.xml_metadata:
259
+ return "ET.Element"
260
+ return "JSON"
236
261
 
237
262
  @property
238
263
  def docstring_text(self) -> str:
264
+ if self.xml_metadata:
265
+ return "XML Element"
239
266
  return "JSON object"
240
267
 
241
268
  def imports(self) -> FileImport:
242
269
  file_import = FileImport()
243
- file_import.add_submodule_import("typing", "Any", ImportType.STDLIB, TypingSection.CONDITIONAL)
270
+ file_import.add_submodule_import(
271
+ "typing", "Any", ImportType.STDLIB, TypingSection.CONDITIONAL
272
+ )
273
+ if self.xml_metadata:
274
+ file_import.add_submodule_import(
275
+ "xml.etree", "ElementTree", ImportType.STDLIB, alias="ET"
276
+ )
277
+ file_import.add_import("sys", ImportType.STDLIB)
278
+ file_import.define_mypy_type(
279
+ "JSON",
280
+ "MutableMapping[str, Any] # pylint: disable=unsubscriptable-object",
281
+ None,
282
+ {
283
+ (3, 9): ImportModel(
284
+ TypingSection.CONDITIONAL,
285
+ ImportType.STDLIB,
286
+ "collections.abc",
287
+ submodule_name="MutableMapping",
288
+ ),
289
+ None: ImportModel(
290
+ TypingSection.CONDITIONAL,
291
+ ImportType.STDLIB,
292
+ "typing",
293
+ submodule_name="MutableMapping",
294
+ ),
295
+ },
296
+ )
244
297
  return file_import
245
298
 
299
+
246
300
  def get_object_schema(code_model) -> Type[ObjectSchema]:
247
301
  if code_model.options["models_mode"]:
248
302
  return ObjectSchema