@autorest/python 6.1.11 → 6.2.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 (73) hide show
  1. package/autorest/_utils.py +2 -1
  2. package/autorest/codegen/__init__.py +87 -80
  3. package/autorest/codegen/models/__init__.py +11 -8
  4. package/autorest/codegen/models/base_builder.py +11 -5
  5. package/autorest/codegen/models/base_model.py +5 -3
  6. package/autorest/codegen/models/base_type.py +7 -5
  7. package/autorest/codegen/models/client.py +131 -32
  8. package/autorest/codegen/models/code_model.py +92 -120
  9. package/autorest/codegen/models/combined_type.py +9 -6
  10. package/autorest/codegen/models/constant_type.py +6 -6
  11. package/autorest/codegen/models/credential_types.py +18 -16
  12. package/autorest/codegen/models/dictionary_type.py +8 -6
  13. package/autorest/codegen/models/enum_type.py +24 -17
  14. package/autorest/codegen/models/imports.py +4 -4
  15. package/autorest/codegen/models/list_type.py +14 -10
  16. package/autorest/codegen/models/lro_operation.py +14 -6
  17. package/autorest/codegen/models/model_type.py +19 -19
  18. package/autorest/codegen/models/operation.py +50 -33
  19. package/autorest/codegen/models/operation_group.py +23 -12
  20. package/autorest/codegen/models/paging_operation.py +14 -11
  21. package/autorest/codegen/models/parameter.py +25 -25
  22. package/autorest/codegen/models/parameter_list.py +22 -16
  23. package/autorest/codegen/models/primitive_types.py +21 -11
  24. package/autorest/codegen/models/property.py +7 -7
  25. package/autorest/codegen/models/request_builder.py +31 -20
  26. package/autorest/codegen/models/request_builder_parameter.py +18 -13
  27. package/autorest/codegen/models/response.py +29 -22
  28. package/autorest/codegen/serializers/__init__.py +196 -139
  29. package/autorest/codegen/serializers/builder_serializer.py +50 -49
  30. package/autorest/codegen/serializers/client_serializer.py +40 -46
  31. package/autorest/codegen/serializers/enum_serializer.py +4 -4
  32. package/autorest/codegen/serializers/general_serializer.py +96 -43
  33. package/autorest/codegen/serializers/metadata_serializer.py +20 -16
  34. package/autorest/codegen/serializers/model_init_serializer.py +10 -6
  35. package/autorest/codegen/serializers/model_serializer.py +8 -8
  36. package/autorest/codegen/serializers/operation_groups_serializer.py +24 -12
  37. package/autorest/codegen/serializers/operations_init_serializer.py +6 -7
  38. package/autorest/codegen/serializers/patch_serializer.py +4 -4
  39. package/autorest/codegen/serializers/request_builders_serializer.py +6 -6
  40. package/autorest/codegen/serializers/sample_serializer.py +146 -0
  41. package/autorest/codegen/templates/client.py.jinja2 +7 -15
  42. package/autorest/codegen/templates/client_container.py.jinja2 +12 -0
  43. package/autorest/codegen/templates/config.py.jinja2 +13 -26
  44. package/autorest/codegen/templates/config_container.py.jinja2 +16 -0
  45. package/autorest/codegen/templates/enum_container.py.jinja2 +3 -3
  46. package/autorest/codegen/templates/init.py.jinja2 +11 -5
  47. package/autorest/codegen/templates/lro_operation.py.jinja2 +2 -2
  48. package/autorest/codegen/templates/lro_paging_operation.py.jinja2 +1 -1
  49. package/autorest/codegen/templates/metadata.json.jinja2 +13 -14
  50. package/autorest/codegen/templates/model_container.py.jinja2 +3 -3
  51. package/autorest/codegen/templates/model_init.py.jinja2 +4 -4
  52. package/autorest/codegen/templates/operation.py.jinja2 +2 -2
  53. package/autorest/codegen/templates/operation_group.py.jinja2 +3 -3
  54. package/autorest/codegen/templates/operation_groups_container.py.jinja2 +7 -7
  55. package/autorest/codegen/templates/operation_tools.jinja2 +3 -3
  56. package/autorest/codegen/templates/operations_folder_init.py.jinja2 +4 -4
  57. package/autorest/codegen/templates/{CHANGELOG.md.jinja2 → packaging_templates/CHANGELOG.md.jinja2} +0 -0
  58. package/autorest/codegen/templates/{LICENSE.jinja2 → packaging_templates/LICENSE.jinja2} +0 -0
  59. package/autorest/codegen/templates/{MANIFEST.in.jinja2 → packaging_templates/MANIFEST.in.jinja2} +0 -0
  60. package/autorest/codegen/templates/{README.md.jinja2 → packaging_templates/README.md.jinja2} +0 -0
  61. package/autorest/codegen/templates/{dev_requirements.txt.jinja2 → packaging_templates/dev_requirements.txt.jinja2} +0 -0
  62. package/autorest/codegen/templates/{setup.py.jinja2 → packaging_templates/setup.py.jinja2} +9 -9
  63. package/autorest/codegen/templates/paging_operation.py.jinja2 +1 -1
  64. package/autorest/codegen/templates/request_builder.py.jinja2 +1 -1
  65. package/autorest/codegen/templates/request_builders.py.jinja2 +3 -3
  66. package/autorest/codegen/templates/rest_init.py.jinja2 +1 -1
  67. package/autorest/codegen/templates/sample.py.jinja2 +44 -0
  68. package/autorest/codegen/templates/validation.py.jinja2 +1 -1
  69. package/autorest/codegen/templates/vendor.py.jinja2 +9 -7
  70. package/autorest/codegen/templates/version.py.jinja2 +2 -2
  71. package/autorest/m4reformatter/__init__.py +20 -7
  72. package/autorest/preprocess/__init__.py +38 -23
  73. package/package.json +1 -1
@@ -3,12 +3,18 @@
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, TYPE_CHECKING, TypeVar, Generic, Union
6
+ from typing import Any, Dict, TYPE_CHECKING, TypeVar, Generic, Union, List, Optional
7
7
 
8
8
  from .base_model import BaseModel
9
9
  from .parameter_list import ClientGlobalParameterList, ConfigGlobalParameterList
10
10
  from .imports import FileImport, ImportType, TypingSection, MsrestImportType
11
11
  from .utils import add_to_pylint_disable
12
+ from .operation_group import OperationGroup
13
+ from .request_builder import (
14
+ RequestBuilder,
15
+ OverloadedRequestBuilder,
16
+ )
17
+ from .parameter import Parameter
12
18
 
13
19
  ParameterListType = TypeVar(
14
20
  "ParameterListType",
@@ -16,7 +22,7 @@ ParameterListType = TypeVar(
16
22
  )
17
23
 
18
24
  if TYPE_CHECKING:
19
- from .code_model import CodeModel
25
+ from .code_model import NamespaceModel
20
26
 
21
27
 
22
28
  class _ClientConfigBase(Generic[ParameterListType], BaseModel):
@@ -25,14 +31,15 @@ class _ClientConfigBase(Generic[ParameterListType], BaseModel):
25
31
  def __init__(
26
32
  self,
27
33
  yaml_data: Dict[str, Any],
28
- code_model: "CodeModel",
34
+ namespace_model: "NamespaceModel",
29
35
  parameters: ParameterListType,
30
36
  ):
31
- super().__init__(yaml_data, code_model)
37
+ super().__init__(yaml_data, namespace_model)
32
38
  self.parameters = parameters
33
39
  self.url: str = self.yaml_data[
34
40
  "url"
35
41
  ] # the base endpoint of the client. Can be parameterized or not
42
+ self.legacy_filename: str = self.yaml_data.get("legacyFilename", "client")
36
43
 
37
44
  @property
38
45
  def description(self) -> str:
@@ -46,8 +53,21 @@ class _ClientConfigBase(Generic[ParameterListType], BaseModel):
46
53
  class Client(_ClientConfigBase[ClientGlobalParameterList]):
47
54
  """Model representing our service client"""
48
55
 
56
+ def __init__(
57
+ self,
58
+ yaml_data: Dict[str, Any],
59
+ namespace_model: "NamespaceModel",
60
+ parameters: ClientGlobalParameterList,
61
+ ):
62
+ super().__init__(yaml_data, namespace_model, parameters)
63
+ self.operation_groups: List[OperationGroup] = []
64
+ self.request_builders: List[
65
+ Union[RequestBuilder, OverloadedRequestBuilder]
66
+ ] = []
67
+ self.config = Config.from_yaml(yaml_data, self.namespace_model)
68
+
49
69
  def pipeline_class(self, async_mode: bool) -> str:
50
- if self.code_model.options["azure_arm"]:
70
+ if self.namespace_model.options["azure_arm"]:
51
71
  if async_mode:
52
72
  return "AsyncARMPipelineClient"
53
73
  return "ARMPipelineClient"
@@ -55,12 +75,17 @@ class Client(_ClientConfigBase[ClientGlobalParameterList]):
55
75
  return "AsyncPipelineClient"
56
76
  return "PipelineClient"
57
77
 
78
+ @property
79
+ def credential(self) -> Optional[Parameter]:
80
+ """The credential param, if one exists"""
81
+ return self.parameters.credential
82
+
58
83
  @property
59
84
  def send_request_name(self) -> str:
60
85
  """Name of the send request function"""
61
86
  return (
62
87
  "send_request"
63
- if self.code_model.options["show_send_request"]
88
+ if self.namespace_model.options["show_send_request"]
64
89
  else "_send_request"
65
90
  )
66
91
 
@@ -72,7 +97,7 @@ class Client(_ClientConfigBase[ClientGlobalParameterList]):
72
97
  @property
73
98
  def pylint_disable(self) -> str:
74
99
  retval = add_to_pylint_disable("", "client-accepts-api-version-keyword")
75
- if len(self.code_model.operation_groups) > 6:
100
+ if len(self.operation_groups) > 6:
76
101
  retval = add_to_pylint_disable(retval, "too-many-instance-attributes")
77
102
  return retval
78
103
 
@@ -80,11 +105,24 @@ class Client(_ClientConfigBase[ClientGlobalParameterList]):
80
105
  def filename(self) -> str:
81
106
  """Name of the file for the client"""
82
107
  if (
83
- self.code_model.options["version_tolerant"]
84
- or self.code_model.options["low_level_client"]
108
+ self.namespace_model.options["version_tolerant"]
109
+ or self.namespace_model.options["low_level_client"]
85
110
  ):
86
111
  return "_client"
87
- return f"_{self.code_model.module_name}"
112
+ return f"_{self.legacy_filename}"
113
+
114
+ def lookup_request_builder(
115
+ self, request_builder_id: int
116
+ ) -> Union[RequestBuilder, OverloadedRequestBuilder]:
117
+ """Find the request builder based off of id"""
118
+ try:
119
+ return next(
120
+ rb
121
+ for rb in self.request_builders
122
+ if id(rb.yaml_data) == request_builder_id
123
+ )
124
+ except StopIteration:
125
+ raise KeyError(f"No request builder with id {request_builder_id} found.")
88
126
 
89
127
  def _imports_shared(self, async_mode: bool) -> FileImport:
90
128
  file_import = FileImport()
@@ -92,7 +130,7 @@ class Client(_ClientConfigBase[ClientGlobalParameterList]):
92
130
  file_import.add_submodule_import(
93
131
  "typing", "Any", ImportType.STDLIB, TypingSection.CONDITIONAL
94
132
  )
95
- if self.code_model.options["azure_arm"]:
133
+ if self.namespace_model.options["azure_arm"]:
96
134
  file_import.add_submodule_import(
97
135
  "azure.mgmt.core", self.pipeline_class(async_mode), ImportType.AZURECORE
98
136
  )
@@ -105,11 +143,11 @@ class Client(_ClientConfigBase[ClientGlobalParameterList]):
105
143
  file_import.merge(gp.imports(async_mode))
106
144
  file_import.add_submodule_import(
107
145
  "._configuration",
108
- f"{self.code_model.client.name}Configuration",
146
+ f"{self.name}Configuration",
109
147
  ImportType.LOCAL,
110
148
  )
111
149
  file_import.add_msrest_import(
112
- self.code_model,
150
+ self.namespace_model,
113
151
  ".." if async_mode else ".",
114
152
  MsrestImportType.SerializerDeserializer,
115
153
  TypingSection.REGULAR,
@@ -117,6 +155,58 @@ class Client(_ClientConfigBase[ClientGlobalParameterList]):
117
155
 
118
156
  return file_import
119
157
 
158
+ @property
159
+ def has_mixin(self) -> bool:
160
+ """Do we want a mixin ABC class for typing purposes?"""
161
+ return any(o for o in self.operation_groups if o.is_mixin)
162
+
163
+ @property
164
+ def need_format_url(self) -> bool:
165
+ """Whether we need to format urls. If so, we need to vendor core."""
166
+ return any(rq for rq in self.request_builders if rq.parameters.path)
167
+
168
+ @property
169
+ def has_lro_operations(self) -> bool:
170
+ """Are there any LRO operations in this SDK?"""
171
+ return any(
172
+ [
173
+ operation.operation_type in ("lro", "lropaging")
174
+ for operation_group in self.operation_groups
175
+ for operation in operation_group.operations
176
+ ]
177
+ )
178
+
179
+ def format_lro_operations(self) -> None:
180
+ """Adds operations and attributes needed for LROs.
181
+ If there are LRO functions in here, will add initial LRO function. Will also set the return
182
+ type of the LRO operation
183
+ """
184
+ for operation_group in self.operation_groups:
185
+ i = 0
186
+ while i < len(operation_group.operations):
187
+ operation = operation_group.operations[i]
188
+ if operation.operation_type in ("lro", "lropaging"):
189
+ operation_group.operations.insert(i, operation.initial_operation) # type: ignore
190
+ i += 1
191
+ i += 1
192
+
193
+ @property
194
+ def need_request_converter(self) -> bool:
195
+ """
196
+ Whether we need to convert our created azure.core.rest.HttpRequests to
197
+ azure.core.pipeline.transport.HttpRequests
198
+ """
199
+ return (
200
+ self.namespace_model.options["show_operations"]
201
+ and bool(self.request_builders)
202
+ and not self.namespace_model.options["version_tolerant"]
203
+ )
204
+
205
+ @property
206
+ def has_abstract_operations(self) -> bool:
207
+ """Whether there is abstract operation in any operation group."""
208
+ return any(og.has_abstract_operations for og in self.operation_groups)
209
+
120
210
  def imports(self, async_mode: bool) -> FileImport:
121
211
  file_import = self._imports_shared(async_mode)
122
212
  if async_mode:
@@ -140,20 +230,20 @@ class Client(_ClientConfigBase[ClientGlobalParameterList]):
140
230
  ImportType.AZURECORE,
141
231
  TypingSection.CONDITIONAL,
142
232
  )
143
- for og in self.code_model.operation_groups:
233
+ for og in self.operation_groups:
144
234
  file_import.add_submodule_import(
145
- f".{self.code_model.operations_folder_name}",
235
+ f".{self.namespace_model.operations_folder_name}",
146
236
  og.class_name,
147
237
  ImportType.LOCAL,
148
238
  )
149
239
 
150
240
  if (
151
- self.code_model.model_types
152
- and self.code_model.options["models_mode"] == "msrest"
241
+ self.namespace_model.model_types
242
+ and self.namespace_model.options["models_mode"] == "msrest"
153
243
  ):
154
244
  path_to_models = ".." if async_mode else "."
155
- if len(self.code_model.model_types) != len(
156
- self.code_model.public_model_types
245
+ if len(self.namespace_model.model_types) != len(
246
+ self.namespace_model.public_model_types
157
247
  ):
158
248
  # this means we have hidden models. In that case, we import directly from the models
159
249
  # file, not the module, bc we don't expose the hidden models in the models module
@@ -161,7 +251,7 @@ class Client(_ClientConfigBase[ClientGlobalParameterList]):
161
251
  # Also in this case, we're in version tolerant, so python3 only is true
162
252
  file_import.add_submodule_import(
163
253
  f"{path_to_models}models",
164
- self.code_model.models_filename,
254
+ self.namespace_model.models_filename,
165
255
  ImportType.LOCAL,
166
256
  alias="models",
167
257
  )
@@ -169,7 +259,7 @@ class Client(_ClientConfigBase[ClientGlobalParameterList]):
169
259
  file_import.add_submodule_import(
170
260
  path_to_models, "models", ImportType.LOCAL
171
261
  )
172
- elif self.code_model.options["models_mode"] == "msrest":
262
+ elif self.namespace_model.options["models_mode"] == "msrest":
173
263
  # in this case, we have client_models = {} in the service client, which needs a type annotation
174
264
  # this import will always be commented, so will always add it to the typing section
175
265
  file_import.add_submodule_import(
@@ -184,9 +274,7 @@ class Client(_ClientConfigBase[ClientGlobalParameterList]):
184
274
  "typing", "Optional", ImportType.STDLIB, TypingSection.CONDITIONAL
185
275
  )
186
276
  try:
187
- mixin_operation = next(
188
- og for og in self.code_model.operation_groups if og.is_mixin
189
- )
277
+ mixin_operation = next(og for og in self.operation_groups if og.is_mixin)
190
278
  file_import.add_submodule_import(
191
279
  "._operations_mixin", mixin_operation.class_name, ImportType.LOCAL
192
280
  )
@@ -206,11 +294,13 @@ class Client(_ClientConfigBase[ClientGlobalParameterList]):
206
294
  return file_import
207
295
 
208
296
  @classmethod
209
- def from_yaml(cls, yaml_data: Dict[str, Any], code_model: "CodeModel") -> "Client":
297
+ def from_yaml(
298
+ cls, yaml_data: Dict[str, Any], namespace_model: "NamespaceModel"
299
+ ) -> "Client":
210
300
  return cls(
211
301
  yaml_data=yaml_data,
212
- code_model=code_model,
213
- parameters=ClientGlobalParameterList.from_yaml(yaml_data, code_model),
302
+ namespace_model=namespace_model,
303
+ parameters=ClientGlobalParameterList.from_yaml(yaml_data, namespace_model),
214
304
  )
215
305
 
216
306
 
@@ -224,6 +314,13 @@ class Config(_ClientConfigBase[ConfigGlobalParameterList]):
224
314
  "Note that all parameters used to create this instance are saved as instance attributes."
225
315
  )
226
316
 
317
+ @property
318
+ def sdk_moniker(self) -> str:
319
+ package_name = self.namespace_model.options["package_name"]
320
+ if package_name and package_name.startswith("azure-"):
321
+ package_name = package_name[len("azure-") :]
322
+ return package_name if package_name else self.yaml_data["name"].lower()
323
+
227
324
  @property
228
325
  def name(self) -> str:
229
326
  return f"{super().name}Configuration"
@@ -239,13 +336,13 @@ class Config(_ClientConfigBase[ConfigGlobalParameterList]):
239
336
  file_import.add_submodule_import(
240
337
  "typing", "Any", ImportType.STDLIB, TypingSection.CONDITIONAL
241
338
  )
242
- if self.code_model.options["package_version"]:
339
+ if self.namespace_model.options["package_version"]:
243
340
  file_import.add_submodule_import(
244
341
  ".._version" if async_mode else "._version", "VERSION", ImportType.LOCAL
245
342
  )
246
343
  for gp in self.parameters:
247
344
  file_import.merge(gp.imports(async_mode=async_mode))
248
- if self.code_model.options["azure_arm"]:
345
+ if self.namespace_model.options["azure_arm"]:
249
346
  policy = (
250
347
  "AsyncARMChallengeAuthenticationPolicy"
251
348
  if async_mode
@@ -260,9 +357,11 @@ class Config(_ClientConfigBase[ConfigGlobalParameterList]):
260
357
  return file_import
261
358
 
262
359
  @classmethod
263
- def from_yaml(cls, yaml_data: Dict[str, Any], code_model: "CodeModel") -> "Config":
360
+ def from_yaml(
361
+ cls, yaml_data: Dict[str, Any], namespace_model: "NamespaceModel"
362
+ ) -> "Config":
264
363
  return cls(
265
364
  yaml_data=yaml_data,
266
- code_model=code_model,
267
- parameters=ConfigGlobalParameterList.from_yaml(yaml_data, code_model),
365
+ namespace_model=namespace_model,
366
+ parameters=ConfigGlobalParameterList.from_yaml(yaml_data, namespace_model),
268
367
  )
@@ -3,18 +3,21 @@
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 List, Dict, Optional, Any, Set, Union
6
+ from typing import List, Dict, Any, Set, Union
7
7
 
8
8
  from .base_type import BaseType
9
9
  from .enum_type import EnumType
10
10
  from .model_type import ModelType
11
+ from .client import Client
12
+ from .request_builder import RequestBuilder, OverloadedRequestBuilder
11
13
  from .operation_group import OperationGroup
12
- from .client import Client, Config
13
- from .request_builder import OverloadedRequestBuilder, RequestBuilder
14
- from .parameter import Parameter
15
14
 
16
15
 
17
- class CodeModel: # pylint: disable=too-many-instance-attributes, too-many-public-methods
16
+ def _is_legacy(options) -> bool:
17
+ return not (options["version_tolerant"] or options["low_level_client"])
18
+
19
+
20
+ class CodeModel:
18
21
  """Holds all of the information we have parsed out of the yaml file. The CodeModel is what gets
19
22
  serialized by the serializers.
20
23
 
@@ -47,17 +50,34 @@ class CodeModel: # pylint: disable=too-many-instance-attributes, too-many-publi
47
50
  ) -> None:
48
51
  self.yaml_data = yaml_data
49
52
  self.options = options
53
+ self.namespace_models: List["NamespaceModel"] = [
54
+ NamespaceModel(namespace_yaml_data, self.options, namespace)
55
+ for namespace, namespace_yaml_data in yaml_data.items()
56
+ ]
57
+
58
+ @property
59
+ def is_legacy(self) -> bool:
60
+ return _is_legacy(self.options)
61
+
62
+ @property
63
+ def description(self) -> str:
64
+ return self.namespace_models[0].clients[0].description
65
+
66
+
67
+ class NamespaceModel:
68
+ def __init__(
69
+ self, yaml_data: Dict[str, Any], options: Dict[str, Any], namespace: str
70
+ ):
71
+ self.yaml_data = yaml_data
50
72
  self.types_map: Dict[int, BaseType] = {} # map yaml id to schema
51
- self.operation_groups: List[OperationGroup] = []
52
73
  self._model_types: List[ModelType] = []
53
- self._client: Optional[Client] = None
54
- self._config: Optional[Config] = None
55
- self.request_builders: List[
56
- Union[RequestBuilder, OverloadedRequestBuilder]
57
- ] = []
58
- self.package_dependency: Dict[str, str] = {}
59
- self.namespace: str = yaml_data["client"]["namespace"].lower()
60
- self.module_name: str = self.yaml_data["client"]["moduleName"]
74
+ self.options = options
75
+ from . import build_type
76
+
77
+ for type_yaml in yaml_data.get("types", []):
78
+ build_type(yaml_data=type_yaml, namespace_model=self)
79
+ self.clients: List[Client] = []
80
+ self.namespace = namespace
61
81
 
62
82
  def lookup_type(self, schema_id: int) -> BaseType:
63
83
  """Looks to see if the schema has already been created.
@@ -72,43 +92,24 @@ class CodeModel: # pylint: disable=too-many-instance-attributes, too-many-publi
72
92
  except StopIteration:
73
93
  raise KeyError(f"Couldn't find schema with id {schema_id}")
74
94
 
75
- @property
76
- def credential(self) -> Optional[Parameter]:
77
- """The credential param, if one exists"""
78
- return self.client.parameters.credential
79
-
80
- @property
81
- def client(self) -> Client:
82
- if not self._client:
83
- raise ValueError("You haven't linked the client yet")
84
- return self._client
85
-
86
- @client.setter
87
- def client(self, val: Client) -> None:
88
- self._client = val
89
-
90
- @property
91
- def config(self) -> Config:
92
- if not self._config:
93
- raise ValueError("You haven't linked the config yet")
94
- return self._config
95
-
96
- @config.setter
97
- def config(self, val: Config) -> None:
98
- self._config = val
99
-
100
95
  def lookup_request_builder(
101
96
  self, request_builder_id: int
102
97
  ) -> Union[RequestBuilder, OverloadedRequestBuilder]:
103
98
  """Find the request builder based off of id"""
104
- try:
105
- return next(
106
- rb
107
- for rb in self.request_builders
108
- if id(rb.yaml_data) == request_builder_id
109
- )
110
- except StopIteration:
111
- raise KeyError(f"No request builder with id {request_builder_id} found.")
99
+ for client in self.clients:
100
+ try:
101
+ return client.lookup_request_builder(request_builder_id)
102
+ except KeyError:
103
+ pass
104
+ raise KeyError(f"No request builder with id {request_builder_id} found.")
105
+
106
+ @property
107
+ def operation_groups(self) -> List[OperationGroup]:
108
+ return [og for client in self.clients for og in client.operation_groups]
109
+
110
+ @property
111
+ def request_builders(self) -> List[Union[RequestBuilder, OverloadedRequestBuilder]]:
112
+ return [rb for client in self.clients for rb in client.request_builders]
112
113
 
113
114
  @property
114
115
  def model_types(self) -> List[ModelType]:
@@ -132,9 +133,11 @@ class CodeModel: # pylint: disable=too-many-instance-attributes, too-many-publi
132
133
  """All of the enums"""
133
134
  return [t for t in self.types_map.values() if isinstance(t, EnumType)]
134
135
 
135
- @staticmethod
136
136
  def _sort_model_types_helper(
137
- current: ModelType, seen_schema_names: Set[str], seen_schema_yaml_ids: Set[int]
137
+ self,
138
+ current: ModelType,
139
+ seen_schema_names: Set[str],
140
+ seen_schema_yaml_ids: Set[int],
138
141
  ):
139
142
  if current.id in seen_schema_yaml_ids:
140
143
  return []
@@ -150,7 +153,7 @@ class CodeModel: # pylint: disable=too-many-instance-attributes, too-many-publi
150
153
  seen_schema_names.add(current.name)
151
154
  seen_schema_yaml_ids.add(current.id)
152
155
  ancestors = (
153
- CodeModel._sort_model_types_helper(
156
+ self._sort_model_types_helper(
154
157
  parent, seen_schema_names, seen_schema_yaml_ids
155
158
  )
156
159
  + ancestors
@@ -170,40 +173,38 @@ class CodeModel: # pylint: disable=too-many-instance-attributes, too-many-publi
170
173
  sorted_object_schemas: List[ModelType] = []
171
174
  for schema in sorted(self.model_types, key=lambda x: x.name.lower()):
172
175
  sorted_object_schemas.extend(
173
- CodeModel._sort_model_types_helper(
176
+ self._sort_model_types_helper(
174
177
  schema, seen_schema_names, seen_schema_yaml_ids
175
178
  )
176
179
  )
177
180
  self.model_types = sorted_object_schemas
178
181
 
179
- def format_lro_operations(self) -> None:
180
- """Adds operations and attributes needed for LROs.
181
- If there are LRO functions in here, will add initial LRO function. Will also set the return
182
- type of the LRO operation
183
- """
184
- for operation_group in self.operation_groups:
185
- i = 0
186
- while i < len(operation_group.operations):
187
- operation = operation_group.operations[i]
188
- if operation.operation_type in ("lro", "lropaging"):
189
- operation_group.operations.insert(i, operation.initial_operation) # type: ignore
190
- i += 1
191
- i += 1
182
+ @property
183
+ def is_legacy(self) -> bool:
184
+ return _is_legacy(self.options)
192
185
 
193
186
  @property
194
- def operations_folder_name(self) -> str:
195
- """Get the name of the operations folder that holds operations."""
196
- name = "operations"
197
- if self.options["version_tolerant"] and not any(
198
- og for og in self.operation_groups if not og.is_mixin
199
- ):
200
- name = f"_{name}"
201
- return name
187
+ def rest_layer_name(self) -> str:
188
+ """If we have a separate rest layer, what is its name?"""
189
+ return "rest" if self.options["builders_visibility"] == "public" else "_rest"
202
190
 
203
191
  @property
204
- def has_abstract_operations(self) -> bool:
205
- """Whether there is abstract operation in any operation group."""
206
- return any(og.has_abstract_operations for og in self.operation_groups)
192
+ def models_filename(self) -> str:
193
+ """Get the names of the model file(s)"""
194
+ if self.is_legacy:
195
+ return "_models_py3"
196
+ return "_models"
197
+
198
+ @property
199
+ def client_filename(self) -> str:
200
+ return self.clients[0].filename
201
+
202
+ @property
203
+ def enums_filename(self) -> str:
204
+ """The name of the enums file"""
205
+ if self.is_legacy:
206
+ return f"_{self.clients[0].legacy_filename}_enums"
207
+ return "_enums"
207
208
 
208
209
  def need_vendored_code(self, async_mode: bool) -> bool:
209
210
  """Whether we need to vendor code in the _vendor.py file for this SDK"""
@@ -217,58 +218,29 @@ class CodeModel: # pylint: disable=too-many-instance-attributes, too-many-publi
217
218
 
218
219
  @property
219
220
  def need_request_converter(self) -> bool:
220
- """
221
- Whether we need to convert our created azure.core.rest.HttpRequests to
222
- azure.core.pipeline.transport.HttpRequests
223
- """
224
- return (
225
- self.options["show_operations"]
226
- and bool(self.request_builders)
227
- and not self.options["version_tolerant"]
228
- )
221
+ return any(c for c in self.clients if c.need_request_converter)
229
222
 
230
223
  @property
231
224
  def need_format_url(self) -> bool:
232
- """Whether we need to format urls. If so, we need to vendor core."""
233
- return any(rq for rq in self.request_builders if rq.parameters.path)
225
+ return any(c for c in self.clients if c.need_format_url)
234
226
 
235
227
  @property
236
228
  def need_mixin_abc(self) -> bool:
237
- """Do we want a mixin ABC class for typing purposes?"""
238
- return any(o for o in self.operation_groups if o.is_mixin)
229
+ return any(c for c in self.clients if c.has_mixin)
239
230
 
240
231
  @property
241
- def has_lro_operations(self) -> bool:
242
- """Are there any LRO operations in this SDK?"""
243
- return any(
244
- [
245
- operation.operation_type in ("lro", "lropaging")
246
- for operation_group in self.operation_groups
247
- for operation in operation_group.operations
248
- ]
249
- )
250
-
251
- @property
252
- def models_filename(self) -> str:
253
- """Get the names of the model file(s)"""
254
- if self.is_legacy:
255
- return "_models_py3"
256
- return "_models"
257
-
258
- @property
259
- def enums_filename(self) -> str:
260
- """The name of the enums file"""
261
- if self.is_legacy:
262
- return f"_{self.module_name}_enums"
263
- return "_enums"
264
-
265
- @property
266
- def is_legacy(self) -> bool:
267
- return not (
268
- self.options["version_tolerant"] or self.options["low_level_client"]
269
- )
232
+ def has_abstract_operations(self) -> bool:
233
+ return any(c for c in self.clients if c.has_abstract_operations)
270
234
 
271
235
  @property
272
- def rest_layer_name(self) -> str:
273
- """If we have a separate rest layer, what is its name?"""
274
- return "rest" if self.options["builders_visibility"] == "public" else "_rest"
236
+ def operations_folder_name(self) -> str:
237
+ """Get the name of the operations folder that holds operations."""
238
+ name = "operations"
239
+ if self.options["version_tolerant"] and not any(
240
+ og
241
+ for client in self.clients
242
+ for og in client.operation_groups
243
+ if not og.is_mixin
244
+ ):
245
+ name = f"_{name}"
246
+ return name
@@ -9,7 +9,7 @@ from autorest.codegen.models.imports import FileImport, ImportType
9
9
  from .base_type import BaseType
10
10
 
11
11
  if TYPE_CHECKING:
12
- from .code_model import CodeModel
12
+ from .code_model import NamespaceModel
13
13
  from .model_type import ModelType
14
14
 
15
15
 
@@ -21,9 +21,12 @@ class CombinedType(BaseType):
21
21
  """
22
22
 
23
23
  def __init__(
24
- self, yaml_data: Dict[str, Any], code_model: "CodeModel", types: List[BaseType]
24
+ self,
25
+ yaml_data: Dict[str, Any],
26
+ namespace_model: "NamespaceModel",
27
+ types: List[BaseType],
25
28
  ) -> None:
26
- super().__init__(yaml_data, code_model)
29
+ super().__init__(yaml_data, namespace_model)
27
30
  self.types = types # the types that this type is combining
28
31
 
29
32
  @property
@@ -102,12 +105,12 @@ class CombinedType(BaseType):
102
105
 
103
106
  @classmethod
104
107
  def from_yaml(
105
- cls, yaml_data: Dict[str, Any], code_model: "CodeModel"
108
+ cls, yaml_data: Dict[str, Any], namespace_model: "NamespaceModel"
106
109
  ) -> "BaseType":
107
110
  from . import build_type
108
111
 
109
112
  return cls(
110
113
  yaml_data,
111
- code_model,
112
- [build_type(t, code_model) for t in yaml_data["types"]],
114
+ namespace_model,
115
+ [build_type(t, namespace_model) for t in yaml_data["types"]],
113
116
  )