@autorest/python 6.1.11 → 6.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. package/autorest/_utils.py +2 -1
  2. package/autorest/codegen/__init__.py +23 -81
  3. package/autorest/codegen/models/__init__.py +5 -3
  4. package/autorest/codegen/models/{base_type.py → base.py} +24 -3
  5. package/autorest/codegen/models/base_builder.py +9 -5
  6. package/autorest/codegen/models/client.py +183 -13
  7. package/autorest/codegen/models/code_model.py +154 -141
  8. package/autorest/codegen/models/combined_type.py +5 -2
  9. package/autorest/codegen/models/constant_type.py +38 -4
  10. package/autorest/codegen/models/credential_types.py +1 -1
  11. package/autorest/codegen/models/dictionary_type.py +1 -1
  12. package/autorest/codegen/models/enum_type.py +5 -3
  13. package/autorest/codegen/models/imports.py +78 -29
  14. package/autorest/codegen/models/list_type.py +1 -1
  15. package/autorest/codegen/models/lro_operation.py +5 -1
  16. package/autorest/codegen/models/model_type.py +1 -2
  17. package/autorest/codegen/models/operation.py +34 -10
  18. package/autorest/codegen/models/operation_group.py +16 -5
  19. package/autorest/codegen/models/paging_operation.py +5 -4
  20. package/autorest/codegen/models/parameter.py +19 -6
  21. package/autorest/codegen/models/primitive_types.py +1 -2
  22. package/autorest/codegen/models/property.py +4 -4
  23. package/autorest/codegen/models/request_builder.py +17 -6
  24. package/autorest/codegen/models/request_builder_parameter.py +5 -2
  25. package/autorest/codegen/models/response.py +6 -3
  26. package/autorest/codegen/serializers/__init__.py +207 -135
  27. package/autorest/codegen/serializers/builder_serializer.py +2 -4
  28. package/autorest/codegen/serializers/client_serializer.py +41 -45
  29. package/autorest/codegen/serializers/general_serializer.py +80 -37
  30. package/autorest/codegen/serializers/import_serializer.py +30 -36
  31. package/autorest/codegen/serializers/metadata_serializer.py +36 -14
  32. package/autorest/codegen/serializers/model_serializer.py +34 -19
  33. package/autorest/codegen/serializers/operation_groups_serializer.py +22 -6
  34. package/autorest/codegen/serializers/operations_init_serializer.py +10 -4
  35. package/autorest/codegen/serializers/sample_serializer.py +144 -0
  36. package/autorest/codegen/templates/client.py.jinja2 +7 -15
  37. package/autorest/codegen/templates/client_container.py.jinja2 +12 -0
  38. package/autorest/codegen/templates/config.py.jinja2 +13 -26
  39. package/autorest/codegen/templates/config_container.py.jinja2 +16 -0
  40. package/autorest/codegen/templates/enum_container.py.jinja2 +1 -1
  41. package/autorest/codegen/templates/init.py.jinja2 +9 -3
  42. package/autorest/codegen/templates/lro_operation.py.jinja2 +1 -1
  43. package/autorest/codegen/templates/metadata.json.jinja2 +13 -14
  44. package/autorest/codegen/templates/model_dpg.py.jinja2 +4 -4
  45. package/autorest/codegen/templates/model_init.py.jinja2 +1 -1
  46. package/autorest/codegen/templates/operation.py.jinja2 +1 -1
  47. package/autorest/codegen/templates/operation_group.py.jinja2 +2 -2
  48. package/autorest/codegen/templates/operation_groups_container.py.jinja2 +5 -5
  49. package/autorest/codegen/templates/operation_tools.jinja2 +2 -2
  50. package/autorest/codegen/templates/operations_folder_init.py.jinja2 +4 -4
  51. package/autorest/codegen/templates/{CHANGELOG.md.jinja2 → packaging_templates/CHANGELOG.md.jinja2} +0 -0
  52. package/autorest/codegen/templates/{LICENSE.jinja2 → packaging_templates/LICENSE.jinja2} +0 -0
  53. package/autorest/codegen/templates/{MANIFEST.in.jinja2 → packaging_templates/MANIFEST.in.jinja2} +0 -0
  54. package/autorest/codegen/templates/{README.md.jinja2 → packaging_templates/README.md.jinja2} +0 -0
  55. package/autorest/codegen/templates/{dev_requirements.txt.jinja2 → packaging_templates/dev_requirements.txt.jinja2} +0 -0
  56. package/autorest/codegen/templates/{setup.py.jinja2 → packaging_templates/setup.py.jinja2} +12 -9
  57. package/autorest/codegen/templates/request_builders.py.jinja2 +2 -2
  58. package/autorest/codegen/templates/sample.py.jinja2 +44 -0
  59. package/autorest/codegen/templates/vendor.py.jinja2 +4 -2
  60. package/autorest/m4reformatter/__init__.py +18 -4
  61. package/autorest/multiapi/models/imports.py +89 -18
  62. package/autorest/multiapi/serializers/import_serializer.py +88 -7
  63. package/autorest/multiapi/utils.py +6 -0
  64. package/autorest/preprocess/__init__.py +20 -8
  65. package/package.json +1 -1
  66. package/run_cadl.py +0 -1
  67. package/autorest/cadlflags/__init__.py +0 -130
  68. package/autorest/codegen/models/base_model.py +0 -28
@@ -34,7 +34,8 @@ def to_snake_case(name: str) -> str:
34
34
 
35
35
  return prefix + match_str
36
36
 
37
- return re.sub("[A-Z]+", replace_upper_characters, name)
37
+ result = re.sub("[A-Z]+", replace_upper_characters, name)
38
+ return result.replace(" ", "_").replace("__", "_").replace("-", "")
38
39
 
39
40
 
40
41
  def parse_args(
@@ -4,38 +4,18 @@
4
4
  # license information.
5
5
  # --------------------------------------------------------------------------
6
6
  import logging
7
- from typing import Dict, Any, Union, cast
7
+ from typing import Dict, Any, cast
8
8
  from pathlib import Path
9
9
  import yaml
10
10
 
11
11
 
12
12
  from .. import Plugin, PluginAutorest
13
13
  from .._utils import parse_args
14
- from .models.client import Client, Config
15
14
  from .models.code_model import CodeModel
16
- from .models import build_type
17
- from .models.request_builder import get_request_builder
18
- from .models.operation_group import OperationGroup
19
15
  from .serializers import JinjaSerializer, JinjaSerializerAutorest
20
16
  from ._utils import DEFAULT_HEADER_TEXT
21
17
 
22
18
 
23
- def _build_convenience_layer(yaml_data: Dict[str, Any], code_model: CodeModel) -> None:
24
- # Create operations
25
- if code_model.options["show_operations"] and yaml_data.get("operationGroups"):
26
- code_model.operation_groups = [
27
- OperationGroup.from_yaml(op_group, code_model)
28
- for op_group in yaml_data["operationGroups"]
29
- ]
30
- if yaml_data.get("types"):
31
- if code_model.options["models_mode"]:
32
- code_model.sort_model_types()
33
-
34
- if code_model.options["show_operations"]:
35
- # LRO operation
36
- code_model.format_lro_operations()
37
-
38
-
39
19
  def _validate_code_model_options(options: Dict[str, Any]) -> None:
40
20
 
41
21
  if options["builders_visibility"] not in ["public", "hidden", "embedded"]:
@@ -97,21 +77,22 @@ _LOGGER = logging.getLogger(__name__)
97
77
  class CodeGenerator(Plugin):
98
78
  @staticmethod
99
79
  def remove_cloud_errors(yaml_data: Dict[str, Any]) -> None:
100
- for group in yaml_data["operationGroups"]:
101
- for operation in group["operations"]:
102
- if not operation.get("exceptions"):
103
- continue
104
- i = 0
105
- while i < len(operation["exceptions"]):
106
- exception = operation["exceptions"][i]
107
- if (
108
- exception.get("schema")
109
- and exception["schema"]["language"]["default"]["name"]
110
- == "CloudError"
111
- ):
112
- del operation["exceptions"][i]
113
- i -= 1
114
- i += 1
80
+ for client in yaml_data["clients"]:
81
+ for group in client["operationGroups"]:
82
+ for operation in group["operations"]:
83
+ if not operation.get("exceptions"):
84
+ continue
85
+ i = 0
86
+ while i < len(operation["exceptions"]):
87
+ exception = operation["exceptions"][i]
88
+ if (
89
+ exception.get("schema")
90
+ and exception["schema"]["language"]["default"]["name"]
91
+ == "CloudError"
92
+ ):
93
+ del operation["exceptions"][i]
94
+ i -= 1
95
+ i += 1
115
96
  if yaml_data.get("schemas") and yaml_data["schemas"].get("objects"):
116
97
  for i in range(len(yaml_data["schemas"]["objects"])):
117
98
  obj_schema = yaml_data["schemas"]["objects"][i]
@@ -119,48 +100,6 @@ class CodeGenerator(Plugin):
119
100
  del yaml_data["schemas"]["objects"][i]
120
101
  break
121
102
 
122
- @staticmethod
123
- def _build_package_dependency() -> Dict[str, str]:
124
- return {
125
- "dependency_azure_mgmt_core": "azure-mgmt-core<2.0.0,>=1.3.2",
126
- "dependency_azure_core": "azure-core<2.0.0,>=1.24.0",
127
- "dependency_msrest": "msrest>=0.7.1",
128
- }
129
-
130
- def _create_code_model(
131
- self, yaml_data: Dict[str, Any], options: Dict[str, Union[str, bool]]
132
- ) -> CodeModel:
133
- # Create a code model
134
-
135
- code_model = CodeModel(yaml_data, options=options)
136
- for type_yaml in yaml_data.get("types", []):
137
- build_type(yaml_data=type_yaml, code_model=code_model)
138
-
139
- code_model.client = Client.from_yaml(yaml_data["client"], code_model)
140
- code_model.config = Config.from_yaml(yaml_data["client"], code_model)
141
-
142
- # Build request builders
143
- if yaml_data.get("operationGroups"):
144
- for og_group in yaml_data["operationGroups"]:
145
- for operation_yaml in og_group["operations"]:
146
- request_builder = get_request_builder(
147
- operation_yaml, code_model=code_model
148
- )
149
- if request_builder.overloads:
150
- code_model.request_builders.extend(request_builder.overloads) # type: ignore
151
- code_model.request_builders.append(request_builder)
152
- if operation_yaml.get("nextOperation"):
153
- # i am a paging operation and i have a next operation. Make sure to include my next operation
154
- code_model.request_builders.append(
155
- get_request_builder(
156
- operation_yaml["nextOperation"], code_model=code_model
157
- )
158
- )
159
-
160
- _build_convenience_layer(yaml_data=yaml_data, code_model=code_model)
161
- code_model.package_dependency = self._build_package_dependency()
162
- return code_model
163
-
164
103
  def _build_code_model_options(self) -> Dict[str, Any]:
165
104
  """Build en options dict from the user input while running autorest."""
166
105
  azure_arm = self.options.get("azure-arm", False)
@@ -218,6 +157,7 @@ class CodeGenerator(Plugin):
218
157
  "default-optional-constants-to-none",
219
158
  low_level_client or version_tolerant,
220
159
  ),
160
+ "generate_sample": self.options.get("generate-sample", False),
221
161
  }
222
162
 
223
163
  if options["builders_visibility"] is None:
@@ -255,8 +195,7 @@ class CodeGenerator(Plugin):
255
195
  if options["azure_arm"]:
256
196
  self.remove_cloud_errors(yaml_data)
257
197
 
258
- code_model = self._create_code_model(yaml_data=yaml_data, options=options)
259
-
198
+ code_model = CodeModel(yaml_data=yaml_data, options=options)
260
199
  serializer = self.get_serializer(code_model)
261
200
  serializer.serialize()
262
201
 
@@ -330,6 +269,7 @@ class CodeGeneratorAutorest(CodeGenerator, PluginAutorest):
330
269
  "default-optional-constants-to-none": self._autorestapi.get_boolean_value(
331
270
  "default-optional-constants-to-none"
332
271
  ),
272
+ "generate-sample": self._autorestapi.get_boolean_value("generate-sample"),
333
273
  }
334
274
  return {k: v for k, v in options.items() if v is not None}
335
275
 
@@ -355,7 +295,9 @@ class CodeGeneratorAutorest(CodeGenerator, PluginAutorest):
355
295
 
356
296
  def get_serializer(self, code_model: CodeModel): # type: ignore
357
297
  return JinjaSerializerAutorest(
358
- self._autorestapi, code_model, output_folder=self.output_folder
298
+ self._autorestapi,
299
+ code_model,
300
+ output_folder=self.output_folder,
359
301
  )
360
302
 
361
303
 
@@ -5,8 +5,10 @@
5
5
  # --------------------------------------------------------------------------
6
6
  import logging
7
7
  from typing import Any, Dict, Union
8
- from .base_model import BaseModel
8
+ from .base import BaseModel
9
+ from .base_builder import BaseBuilder
9
10
  from .code_model import CodeModel
11
+ from .client import Client
10
12
  from .model_type import ModelType
11
13
  from .dictionary_type import DictionaryType
12
14
  from .list_type import ListType
@@ -28,7 +30,7 @@ from .primitive_types import (
28
30
  UnixTimeType,
29
31
  )
30
32
  from .enum_type import EnumType
31
- from .base_type import BaseType
33
+ from .base import BaseType
32
34
  from .constant_type import ConstantType
33
35
  from .imports import FileImport, ImportType, TypingSection
34
36
  from .lro_operation import LROOperation
@@ -57,7 +59,6 @@ from .request_builder import (
57
59
  OverloadedRequestBuilder,
58
60
  RequestBuilderBase,
59
61
  )
60
- from .base_builder import BaseBuilder
61
62
  from .lro_paging_operation import LROPagingOperation
62
63
  from .request_builder_parameter import (
63
64
  RequestBuilderParameter,
@@ -78,6 +79,7 @@ __all__ = [
78
79
  "BaseModel",
79
80
  "BaseType",
80
81
  "CodeModel",
82
+ "Client",
81
83
  "ConstantType",
82
84
  "ModelType",
83
85
  "DictionaryType",
@@ -3,17 +3,35 @@
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, List, Optional
6
7
  from abc import ABC, abstractmethod
7
- from typing import Any, Dict, List, Optional, TYPE_CHECKING
8
-
9
- from .base_model import BaseModel
10
8
  from .imports import FileImport
11
9
 
10
+
12
11
  if TYPE_CHECKING:
13
12
  from .code_model import CodeModel
14
13
  from .model_type import ModelType
15
14
 
16
15
 
16
+ class BaseModel:
17
+ """This is the base class for model representations that are based on some YAML data.
18
+
19
+ :param yaml_data: the yaml data for this schema
20
+ :type yaml_data: dict[str, Any]
21
+ """
22
+
23
+ def __init__(self, yaml_data: Dict[str, Any], code_model: "CodeModel") -> None:
24
+ self.yaml_data = yaml_data
25
+ self.code_model = code_model
26
+
27
+ @property
28
+ def id(self) -> int:
29
+ return id(self.yaml_data)
30
+
31
+ def __repr__(self):
32
+ return f"<{self.__class__.__name__}>"
33
+
34
+
17
35
  class BaseType(BaseModel, ABC):
18
36
  """This is the base class for all types.
19
37
 
@@ -39,6 +57,9 @@ class BaseType(BaseModel, ABC):
39
57
  ) -> FileImport:
40
58
  return FileImport()
41
59
 
60
+ def imports_for_multiapi(self, **kwargs: Any) -> FileImport:
61
+ return self.imports(**kwargs)
62
+
42
63
  @property
43
64
  def xml_metadata(self) -> Dict[str, Any]:
44
65
  """XML metadata for the type, if the type has it."""
@@ -4,9 +4,10 @@
4
4
  # license information.
5
5
  # --------------------------------------------------------------------------
6
6
  import logging
7
+ from typing import List, Dict, Any, Generic, TypeVar, Optional, Union, TYPE_CHECKING
7
8
  from abc import abstractmethod
8
- from typing import Any, Dict, List, Optional, TypeVar, Union, TYPE_CHECKING, Generic
9
- from .base_model import BaseModel
9
+
10
+ from .base import BaseModel
10
11
  from .parameter_list import (
11
12
  ParameterList,
12
13
  RequestBuilderParameterList,
@@ -21,10 +22,9 @@ ParameterListType = TypeVar(
21
22
  OverloadedRequestBuilderParameterList,
22
23
  ],
23
24
  )
24
-
25
-
26
25
  if TYPE_CHECKING:
27
26
  from .code_model import CodeModel
27
+ from .client import Client
28
28
  from .operation import Operation
29
29
  from .request_builder import RequestBuilder
30
30
 
@@ -40,6 +40,7 @@ class BaseBuilder(
40
40
  self,
41
41
  yaml_data: Dict[str, Any],
42
42
  code_model: "CodeModel",
43
+ client: "Client",
43
44
  name: str,
44
45
  parameters: ParameterListType,
45
46
  *,
@@ -47,6 +48,7 @@ class BaseBuilder(
47
48
  want_tracing: bool = True,
48
49
  ) -> None:
49
50
  super().__init__(yaml_data=yaml_data, code_model=code_model)
51
+ self.client = client
50
52
  self.name = name
51
53
  self._description: str = yaml_data.get("description", "")
52
54
  self.parameters = parameters
@@ -55,7 +57,9 @@ class BaseBuilder(
55
57
  )
56
58
  self._summary: str = yaml_data.get("summary", "")
57
59
  self.want_tracing = want_tracing
58
- self.group_name: str = yaml_data["groupName"]
60
+ self.group_name: str = yaml_data[
61
+ "groupName"
62
+ ] # either operationGroup or client I am on
59
63
  self.is_overload: bool = yaml_data["isOverload"]
60
64
  self.api_versions: List[str] = yaml_data["apiVersions"]
61
65
  self.added_on: Optional[str] = yaml_data.get("addedOn")
@@ -3,12 +3,19 @@
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
- from .base_model import BaseModel
8
+ from .base 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
+ get_request_builder,
17
+ )
18
+ from .parameter import Parameter, ParameterMethodLocation
12
19
 
13
20
  ParameterListType = TypeVar(
14
21
  "ParameterListType",
@@ -33,6 +40,7 @@ class _ClientConfigBase(Generic[ParameterListType], BaseModel):
33
40
  self.url: str = self.yaml_data[
34
41
  "url"
35
42
  ] # the base endpoint of the client. Can be parameterized or not
43
+ self.legacy_filename: str = self.yaml_data.get("legacyFilename", "client")
36
44
 
37
45
  @property
38
46
  def description(self) -> str:
@@ -46,6 +54,50 @@ class _ClientConfigBase(Generic[ParameterListType], BaseModel):
46
54
  class Client(_ClientConfigBase[ClientGlobalParameterList]):
47
55
  """Model representing our service client"""
48
56
 
57
+ def __init__(
58
+ self,
59
+ yaml_data: Dict[str, Any],
60
+ code_model: "CodeModel",
61
+ parameters: ClientGlobalParameterList,
62
+ *,
63
+ is_subclient: bool = False,
64
+ ):
65
+ super().__init__(yaml_data, code_model, parameters)
66
+ self.operation_groups: List[OperationGroup] = []
67
+ self.config = Config.from_yaml(yaml_data, self.code_model)
68
+ self.is_subclient = is_subclient
69
+ self.request_builders = self._build_request_builders()
70
+ if self.code_model.options["show_operations"]:
71
+ self.operation_groups = [
72
+ OperationGroup.from_yaml(op_group, code_model, self)
73
+ for op_group in self.yaml_data.get("operationGroups", [])
74
+ ]
75
+ self.format_lro_operations()
76
+
77
+ def _build_request_builders(self):
78
+ request_builders: List[Union[RequestBuilder, OverloadedRequestBuilder]] = []
79
+ for og_group in self.yaml_data["operationGroups"]:
80
+ for operation_yaml in og_group["operations"]:
81
+ request_builder = get_request_builder(
82
+ operation_yaml,
83
+ code_model=self.code_model,
84
+ client=self,
85
+ )
86
+ if request_builder.overloads:
87
+ request_builders.extend(request_builder.overloads) # type: ignore
88
+ request_builders.append(request_builder)
89
+ if operation_yaml.get("nextOperation"):
90
+ # i am a paging operation and i have a next operation.
91
+ # Make sure to include my next operation
92
+ request_builders.append(
93
+ get_request_builder(
94
+ operation_yaml["nextOperation"],
95
+ code_model=self.code_model,
96
+ client=self,
97
+ )
98
+ )
99
+ return request_builders
100
+
49
101
  def pipeline_class(self, async_mode: bool) -> str:
50
102
  if self.code_model.options["azure_arm"]:
51
103
  if async_mode:
@@ -55,6 +107,11 @@ class Client(_ClientConfigBase[ClientGlobalParameterList]):
55
107
  return "AsyncPipelineClient"
56
108
  return "PipelineClient"
57
109
 
110
+ @property
111
+ def credential(self) -> Optional[Parameter]:
112
+ """The credential param, if one exists"""
113
+ return self.parameters.credential
114
+
58
115
  @property
59
116
  def send_request_name(self) -> str:
60
117
  """Name of the send request function"""
@@ -72,7 +129,7 @@ class Client(_ClientConfigBase[ClientGlobalParameterList]):
72
129
  @property
73
130
  def pylint_disable(self) -> str:
74
131
  retval = add_to_pylint_disable("", "client-accepts-api-version-keyword")
75
- if len(self.code_model.operation_groups) > 6:
132
+ if len(self.operation_groups) > 6:
76
133
  retval = add_to_pylint_disable(retval, "too-many-instance-attributes")
77
134
  return retval
78
135
 
@@ -84,7 +141,20 @@ class Client(_ClientConfigBase[ClientGlobalParameterList]):
84
141
  or self.code_model.options["low_level_client"]
85
142
  ):
86
143
  return "_client"
87
- return f"_{self.code_model.module_name}"
144
+ return f"_{self.legacy_filename}"
145
+
146
+ def lookup_request_builder(
147
+ self, request_builder_id: int
148
+ ) -> Union[RequestBuilder, OverloadedRequestBuilder]:
149
+ """Find the request builder based off of id"""
150
+ try:
151
+ return next(
152
+ rb
153
+ for rb in self.request_builders
154
+ if id(rb.yaml_data) == request_builder_id
155
+ )
156
+ except StopIteration:
157
+ raise KeyError(f"No request builder with id {request_builder_id} found.")
88
158
 
89
159
  def _imports_shared(self, async_mode: bool) -> FileImport:
90
160
  file_import = FileImport()
@@ -102,10 +172,15 @@ class Client(_ClientConfigBase[ClientGlobalParameterList]):
102
172
  )
103
173
 
104
174
  for gp in self.parameters:
175
+ if (
176
+ gp.method_location == ParameterMethodLocation.KWARG
177
+ and gp not in self.parameters.kwargs_to_pop
178
+ ):
179
+ continue
105
180
  file_import.merge(gp.imports(async_mode))
106
181
  file_import.add_submodule_import(
107
182
  "._configuration",
108
- f"{self.code_model.client.name}Configuration",
183
+ f"{self.name}Configuration",
109
184
  ImportType.LOCAL,
110
185
  )
111
186
  file_import.add_msrest_import(
@@ -117,6 +192,67 @@ class Client(_ClientConfigBase[ClientGlobalParameterList]):
117
192
 
118
193
  return file_import
119
194
 
195
+ @property
196
+ def has_mixin(self) -> bool:
197
+ """Do we want a mixin ABC class for typing purposes?"""
198
+ return any(o for o in self.operation_groups if o.is_mixin)
199
+
200
+ @property
201
+ def need_format_url(self) -> bool:
202
+ """Whether we need to format urls. If so, we need to vendor core."""
203
+ return any(rq for rq in self.request_builders if rq.parameters.path)
204
+
205
+ @property
206
+ def has_lro_operations(self) -> bool:
207
+ """Are there any LRO operations in this SDK?"""
208
+ return any(
209
+ [
210
+ operation.operation_type in ("lro", "lropaging")
211
+ for operation_group in self.operation_groups
212
+ for operation in operation_group.operations
213
+ ]
214
+ )
215
+
216
+ @property
217
+ def has_operations(self) -> bool:
218
+ return any(
219
+ [
220
+ bool(operation_group.operations)
221
+ for operation_group in self.operation_groups
222
+ ]
223
+ )
224
+
225
+ def format_lro_operations(self) -> None:
226
+ """Adds operations and attributes needed for LROs.
227
+ If there are LRO functions in here, will add initial LRO function. Will also set the return
228
+ type of the LRO operation
229
+ """
230
+ for operation_group in self.operation_groups:
231
+ i = 0
232
+ while i < len(operation_group.operations):
233
+ operation = operation_group.operations[i]
234
+ if operation.operation_type in ("lro", "lropaging"):
235
+ operation_group.operations.insert(i, operation.initial_operation) # type: ignore
236
+ i += 1
237
+ i += 1
238
+
239
+ @property
240
+ def need_request_converter(self) -> bool:
241
+ """
242
+ Whether we need to convert our created azure.core.rest.HttpRequests to
243
+ azure.core.pipeline.transport.HttpRequests
244
+ """
245
+ return (
246
+ self.code_model.options["show_operations"]
247
+ and bool(self.request_builders)
248
+ and not self.code_model.options["version_tolerant"]
249
+ )
250
+
251
+ @property
252
+ def has_abstract_operations(self) -> bool:
253
+ """Whether there is abstract operation in any operation group."""
254
+ return any(og.has_abstract_operations for og in self.operation_groups)
255
+
120
256
  def imports(self, async_mode: bool) -> FileImport:
121
257
  file_import = self._imports_shared(async_mode)
122
258
  if async_mode:
@@ -140,7 +276,7 @@ class Client(_ClientConfigBase[ClientGlobalParameterList]):
140
276
  ImportType.AZURECORE,
141
277
  TypingSection.CONDITIONAL,
142
278
  )
143
- for og in self.code_model.operation_groups:
279
+ for og in self.operation_groups:
144
280
  file_import.add_submodule_import(
145
281
  f".{self.code_model.operations_folder_name}",
146
282
  og.class_name,
@@ -184,9 +320,7 @@ class Client(_ClientConfigBase[ClientGlobalParameterList]):
184
320
  "typing", "Optional", ImportType.STDLIB, TypingSection.CONDITIONAL
185
321
  )
186
322
  try:
187
- mixin_operation = next(
188
- og for og in self.code_model.operation_groups if og.is_mixin
189
- )
323
+ mixin_operation = next(og for og in self.operation_groups if og.is_mixin)
190
324
  file_import.add_submodule_import(
191
325
  "._operations_mixin", mixin_operation.class_name, ImportType.LOCAL
192
326
  )
@@ -206,11 +340,18 @@ class Client(_ClientConfigBase[ClientGlobalParameterList]):
206
340
  return file_import
207
341
 
208
342
  @classmethod
209
- def from_yaml(cls, yaml_data: Dict[str, Any], code_model: "CodeModel") -> "Client":
343
+ def from_yaml(
344
+ cls,
345
+ yaml_data: Dict[str, Any],
346
+ code_model: "CodeModel",
347
+ *,
348
+ is_subclient: bool = False,
349
+ ) -> "Client":
210
350
  return cls(
211
351
  yaml_data=yaml_data,
212
352
  code_model=code_model,
213
353
  parameters=ClientGlobalParameterList.from_yaml(yaml_data, code_model),
354
+ is_subclient=is_subclient,
214
355
  )
215
356
 
216
357
 
@@ -224,11 +365,18 @@ class Config(_ClientConfigBase[ConfigGlobalParameterList]):
224
365
  "Note that all parameters used to create this instance are saved as instance attributes."
225
366
  )
226
367
 
368
+ @property
369
+ def sdk_moniker(self) -> str:
370
+ package_name = self.code_model.options["package_name"]
371
+ if package_name and package_name.startswith("azure-"):
372
+ package_name = package_name[len("azure-") :]
373
+ return package_name if package_name else self.yaml_data["name"].lower()
374
+
227
375
  @property
228
376
  def name(self) -> str:
229
377
  return f"{super().name}Configuration"
230
378
 
231
- def imports(self, async_mode: bool) -> FileImport:
379
+ def _imports_shared(self, async_mode: bool) -> FileImport:
232
380
  file_import = FileImport()
233
381
  file_import.add_submodule_import(
234
382
  "azure.core.configuration", "Configuration", ImportType.AZURECORE
@@ -243,8 +391,6 @@ class Config(_ClientConfigBase[ConfigGlobalParameterList]):
243
391
  file_import.add_submodule_import(
244
392
  ".._version" if async_mode else "._version", "VERSION", ImportType.LOCAL
245
393
  )
246
- for gp in self.parameters:
247
- file_import.merge(gp.imports(async_mode=async_mode))
248
394
  if self.code_model.options["azure_arm"]:
249
395
  policy = (
250
396
  "AsyncARMChallengeAuthenticationPolicy"
@@ -257,6 +403,30 @@ class Config(_ClientConfigBase[ConfigGlobalParameterList]):
257
403
  file_import.add_submodule_import(
258
404
  "azure.mgmt.core.policies", policy, ImportType.AZURECORE
259
405
  )
406
+
407
+ return file_import
408
+
409
+ def imports(self, async_mode: bool) -> FileImport:
410
+ file_import = self._imports_shared(async_mode)
411
+ for gp in self.parameters:
412
+ if (
413
+ gp.method_location == ParameterMethodLocation.KWARG
414
+ and gp not in self.parameters.kwargs_to_pop
415
+ ):
416
+ continue
417
+ file_import.merge(gp.imports(async_mode=async_mode))
418
+ return file_import
419
+
420
+ def imports_for_multiapi(self, async_mode: bool) -> FileImport:
421
+ file_import = self._imports_shared(async_mode)
422
+ for gp in self.parameters:
423
+ if (
424
+ gp.method_location == ParameterMethodLocation.KWARG
425
+ and gp not in self.parameters.kwargs_to_pop
426
+ and gp.client_name == "api_version"
427
+ ):
428
+ continue
429
+ file_import.merge(gp.imports_for_multiapi(async_mode=async_mode))
260
430
  return file_import
261
431
 
262
432
  @classmethod