@autorest/python 6.4.0 → 6.4.2

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 (27) hide show
  1. package/autorest/codegen/models/__init__.py +1 -0
  2. package/autorest/codegen/models/base_builder.py +1 -2
  3. package/autorest/codegen/models/client.py +32 -13
  4. package/autorest/codegen/models/code_model.py +4 -0
  5. package/autorest/codegen/models/combined_type.py +16 -2
  6. package/autorest/codegen/models/enum_type.py +7 -1
  7. package/autorest/codegen/models/lro_operation.py +18 -24
  8. package/autorest/codegen/models/model_type.py +8 -2
  9. package/autorest/codegen/models/operation.py +11 -7
  10. package/autorest/codegen/models/operation_group.py +3 -2
  11. package/autorest/codegen/models/paging_operation.py +0 -4
  12. package/autorest/codegen/models/parameter.py +8 -1
  13. package/autorest/codegen/models/property.py +4 -24
  14. package/autorest/codegen/models/request_builder.py +18 -8
  15. package/autorest/codegen/models/response.py +9 -1
  16. package/autorest/codegen/serializers/__init__.py +6 -0
  17. package/autorest/codegen/serializers/client_serializer.py +1 -1
  18. package/autorest/codegen/serializers/metadata_serializer.py +8 -2
  19. package/autorest/codegen/serializers/types_serializer.py +38 -0
  20. package/autorest/codegen/templates/lro_operation.py.jinja2 +1 -1
  21. package/autorest/codegen/templates/lro_paging_operation.py.jinja2 +1 -1
  22. package/autorest/codegen/templates/operation.py.jinja2 +2 -2
  23. package/autorest/codegen/templates/paging_operation.py.jinja2 +2 -2
  24. package/autorest/codegen/templates/types.py.jinja2 +8 -0
  25. package/autorest/m4reformatter/__init__.py +44 -22
  26. package/autorest/preprocess/__init__.py +8 -0
  27. package/package.json +1 -1
@@ -183,3 +183,4 @@ RequestBuilderType = Union[RequestBuilder, OverloadedRequestBuilder]
183
183
  ParameterType = Union[
184
184
  Parameter, RequestBuilderParameter, ClientParameter, ConfigParameter
185
185
  ]
186
+ OperationType = Union[Operation, LROOperation, PagingOperation, LROPagingOperation]
@@ -45,7 +45,6 @@ class BaseBuilder(
45
45
  parameters: ParameterListType,
46
46
  *,
47
47
  overloads=None,
48
- want_tracing: bool = True,
49
48
  ) -> None:
50
49
  super().__init__(yaml_data=yaml_data, code_model=code_model)
51
50
  self.client = client
@@ -56,7 +55,7 @@ class BaseBuilder(
56
55
  overloads or []
57
56
  )
58
57
  self._summary: str = yaml_data.get("summary", "")
59
- self.want_tracing = want_tracing
58
+ self.want_tracing: bool = yaml_data.get("wantTracing", True)
60
59
  self.group_name: str = yaml_data[
61
60
  "groupName"
62
61
  ] # either operationGroup or client I am on
@@ -16,6 +16,8 @@ from .request_builder import (
16
16
  get_request_builder,
17
17
  )
18
18
  from .parameter import Parameter, ParameterMethodLocation
19
+ from .lro_operation import LROOperation
20
+ from .lro_paging_operation import LROPagingOperation
19
21
 
20
22
  ParameterListType = TypeVar(
21
23
  "ParameterListType",
@@ -24,6 +26,7 @@ ParameterListType = TypeVar(
24
26
 
25
27
  if TYPE_CHECKING:
26
28
  from .code_model import CodeModel
29
+ from . import OperationType
27
30
 
28
31
 
29
32
  class _ClientConfigBase(Generic[ParameterListType], BaseModel):
@@ -72,7 +75,7 @@ class Client(_ClientConfigBase[ClientGlobalParameterList]):
72
75
  OperationGroup.from_yaml(op_group, code_model, self)
73
76
  for op_group in self.yaml_data.get("operationGroups", [])
74
77
  ]
75
- self.format_lro_operations()
78
+ self.link_lro_initial_operations()
76
79
 
77
80
  def _build_request_builders(
78
81
  self,
@@ -80,11 +83,21 @@ class Client(_ClientConfigBase[ClientGlobalParameterList]):
80
83
  request_builders: List[Union[RequestBuilder, OverloadedRequestBuilder]] = []
81
84
  for og_group in self.yaml_data["operationGroups"]:
82
85
  for operation_yaml in og_group["operations"]:
86
+ if operation_yaml["discriminator"] in ("lro", "lropaging"):
87
+ continue
83
88
  request_builder = get_request_builder(
84
89
  operation_yaml,
85
90
  code_model=self.code_model,
86
91
  client=self,
87
92
  )
93
+ if operation_yaml.get("isLroInitialOperation"):
94
+ # we want to change the name
95
+ request_builder.name = request_builder.get_name(
96
+ request_builder.yaml_data["name"][1 : -len("_initial")],
97
+ request_builder.yaml_data,
98
+ request_builder.code_model,
99
+ request_builder.client,
100
+ )
88
101
  if request_builder.overloads:
89
102
  request_builders.extend(request_builder.overloads)
90
103
  request_builders.append(request_builder)
@@ -160,6 +173,17 @@ class Client(_ClientConfigBase[ClientGlobalParameterList]):
160
173
  f"No request builder with id {request_builder_id} found."
161
174
  ) from exc
162
175
 
176
+ def lookup_operation(self, operation_id: int) -> "OperationType":
177
+ try:
178
+ return next(
179
+ o
180
+ for og in self.operation_groups
181
+ for o in og.operations
182
+ if id(o.yaml_data) == operation_id
183
+ )
184
+ except StopIteration as exc:
185
+ raise KeyError(f"No operation with id {operation_id} found.") from exc
186
+
163
187
  def _imports_shared(self, async_mode: bool) -> FileImport:
164
188
  file_import = FileImport()
165
189
 
@@ -221,19 +245,14 @@ class Client(_ClientConfigBase[ClientGlobalParameterList]):
221
245
  for operation_group in self.operation_groups
222
246
  )
223
247
 
224
- def format_lro_operations(self) -> None:
225
- """Adds operations and attributes needed for LROs.
226
- If there are LRO functions in here, will add initial LRO function. Will also set the return
227
- type of the LRO operation
228
- """
248
+ def link_lro_initial_operations(self) -> None:
249
+ """Link each LRO operation to its initial operation"""
229
250
  for operation_group in self.operation_groups:
230
- i = 0
231
- while i < len(operation_group.operations):
232
- operation = operation_group.operations[i]
233
- if operation.operation_type in ("lro", "lropaging"):
234
- operation_group.operations.insert(i, operation.initial_operation) # type: ignore
235
- i += 1
236
- i += 1
251
+ for operation in operation_group.operations:
252
+ if isinstance(operation, (LROOperation, LROPagingOperation)):
253
+ operation.initial_operation = self.lookup_operation(
254
+ id(operation.yaml_data["initialOperation"])
255
+ )
237
256
 
238
257
  @property
239
258
  def need_request_converter(self) -> bool:
@@ -8,6 +8,7 @@ from typing import List, Dict, Any, Set, Union
8
8
  from .base import BaseType
9
9
  from .enum_type import EnumType
10
10
  from .model_type import ModelType
11
+ from .combined_type import CombinedType
11
12
  from .client import Client
12
13
  from .request_builder import RequestBuilder, OverloadedRequestBuilder
13
14
  from .constant_type import ConstantType
@@ -72,6 +73,9 @@ class CodeModel: # pylint: disable=too-many-public-methods
72
73
  if self.options["models_mode"] and self.model_types:
73
74
  self.sort_model_types()
74
75
  self.is_subnamespace = is_subnamespace
76
+ self.named_unions: List[CombinedType] = [
77
+ t for t in self.types_map.values() if isinstance(t, CombinedType) and t.name
78
+ ]
75
79
 
76
80
  @property
77
81
  def has_operations(self) -> bool:
@@ -5,7 +5,7 @@
5
5
  # --------------------------------------------------------------------------
6
6
  from typing import Any, Dict, List, Optional, TYPE_CHECKING
7
7
  import re
8
- from autorest.codegen.models.imports import FileImport, ImportType
8
+ from autorest.codegen.models.imports import FileImport, ImportType, TypingSection
9
9
  from .base import BaseType
10
10
  from .model_type import JSONModelType
11
11
 
@@ -29,6 +29,7 @@ class CombinedType(BaseType):
29
29
  ) -> None:
30
30
  super().__init__(yaml_data, code_model)
31
31
  self.types = types # the types that this type is combining
32
+ self.name = yaml_data.get("name")
32
33
 
33
34
  @property
34
35
  def serialization_type(self) -> str:
@@ -62,11 +63,16 @@ class CombinedType(BaseType):
62
63
  return " or ".join(t.docstring_type(**kwargs) for t in self.types)
63
64
 
64
65
  def type_annotation(self, **kwargs: Any) -> str:
66
+ if self.name:
67
+ ret = f"_types.{self.name}"
68
+ return ret if kwargs.get("is_operation_file") else f'"{ret}"'
69
+ return self.type_definition(**kwargs)
70
+
71
+ def type_definition(self, **kwargs: Any) -> str:
65
72
  """The python type used for type annotation
66
73
 
67
74
  Special case for enum, for instance: Union[str, "EnumName"]
68
75
  """
69
- kwargs["is_operation_file"] = True
70
76
  inside_types = [type.type_annotation(**kwargs) for type in self.types]
71
77
 
72
78
  # If the inside types has been a Union, peel first and then re-union
@@ -96,6 +102,14 @@ class CombinedType(BaseType):
96
102
 
97
103
  def imports(self, **kwargs: Any) -> FileImport:
98
104
  file_import = FileImport()
105
+ if self.name and not kwargs.get("is_types_file"):
106
+ file_import.add_submodule_import(
107
+ kwargs.pop("relative_path"),
108
+ "_types",
109
+ ImportType.LOCAL,
110
+ TypingSection.TYPING,
111
+ )
112
+ return file_import
99
113
  for type in self.types:
100
114
  file_import.merge(type.imports(**kwargs))
101
115
  file_import.add_submodule_import("typing", "Union", ImportType.STDLIB)
@@ -194,6 +194,12 @@ class EnumType(BaseType):
194
194
  if self.code_model.options["models_mode"] and relative_path:
195
195
  # add import for enums in operations file
196
196
  file_import.add_submodule_import(
197
- relative_path, "models", ImportType.LOCAL, alias="_models"
197
+ relative_path,
198
+ "models",
199
+ ImportType.LOCAL,
200
+ alias="_models",
201
+ typing_section=TypingSection.TYPING
202
+ if kwargs.get("model_typing")
203
+ else TypingSection.REGULAR,
198
204
  )
199
205
  return file_import
@@ -14,6 +14,7 @@ from .parameter_list import ParameterList
14
14
  if TYPE_CHECKING:
15
15
  from .code_model import CodeModel
16
16
  from .client import Client
17
+ from . import OperationType
17
18
 
18
19
  LROResponseType = TypeVar(
19
20
  "LROResponseType", bound=Union[LROResponse, LROPagingResponse]
@@ -33,8 +34,6 @@ class LROOperationBase(OperationBase[LROResponseType]):
33
34
  exceptions: List[Response],
34
35
  *,
35
36
  overloads: Optional[List[Operation]] = None,
36
- public: bool = True,
37
- want_tracing: bool = True,
38
37
  ) -> None:
39
38
  super().__init__(
40
39
  code_model=code_model,
@@ -46,11 +45,22 @@ class LROOperationBase(OperationBase[LROResponseType]):
46
45
  responses=responses,
47
46
  exceptions=exceptions,
48
47
  overloads=overloads,
49
- public=public,
50
- want_tracing=want_tracing,
51
48
  )
52
49
  self.name = "begin_" + self.name
53
50
  self.lro_options: Dict[str, Any] = self.yaml_data.get("lroOptions", {})
51
+ self._initial_operation: Optional["OperationType"] = None
52
+
53
+ @property
54
+ def initial_operation(self) -> "OperationType":
55
+ if not self._initial_operation:
56
+ raise ValueError(
57
+ "You need to first call client.link_lro_initial_operations before accessing"
58
+ )
59
+ return self._initial_operation
60
+
61
+ @initial_operation.setter
62
+ def initial_operation(self, val: "OperationType") -> None:
63
+ self._initial_operation = val
54
64
 
55
65
  @property
56
66
  def operation_type(self) -> str:
@@ -93,26 +103,6 @@ class LROOperationBase(OperationBase[LROResponseType]):
93
103
  """We don't want the poller to show up in ClsType, so we call super() on resposne type annotation"""
94
104
  return f"ClsType[{Response.type_annotation(self.responses[0], async_mode=async_mode)}]"
95
105
 
96
- @property
97
- def initial_operation(self) -> Operation:
98
- """Initial operation that creates the first call for LRO polling"""
99
- return Operation(
100
- yaml_data=self.yaml_data,
101
- code_model=self.code_model,
102
- client=self.client,
103
- request_builder=self.client.lookup_request_builder(id(self.yaml_data)),
104
- name=self.name[5:] + "_initial",
105
- overloads=self.overloads,
106
- parameters=self.parameters,
107
- responses=[
108
- Response(r.yaml_data, self.code_model, headers=r.headers, type=r.type)
109
- for r in self.responses
110
- ],
111
- exceptions=self.exceptions,
112
- public=False,
113
- want_tracing=False,
114
- )
115
-
116
106
  def get_poller(self, async_mode: bool) -> str:
117
107
  return self.responses[0].get_poller(async_mode)
118
108
 
@@ -144,6 +134,10 @@ class LROOperationBase(OperationBase[LROResponseType]):
144
134
  file_import.add_submodule_import("typing", "cast", ImportType.STDLIB)
145
135
  return file_import
146
136
 
137
+ @classmethod
138
+ def get_request_builder(cls, yaml_data: Dict[str, Any], client: "Client"):
139
+ return client.lookup_request_builder(id(yaml_data["initialOperation"]))
140
+
147
141
 
148
142
  class LROOperation(LROOperationBase[LROResponse]):
149
143
  ...
@@ -303,9 +303,15 @@ class GeneratedModelType(ModelType): # pylint: disable=abstract-method
303
303
  file_import = super().imports(**kwargs)
304
304
  relative_path = kwargs.pop("relative_path", None)
305
305
  if relative_path:
306
- # add import for models in operations file
306
+ # add import for models in operations or _types file
307
307
  file_import.add_submodule_import(
308
- relative_path, "models", ImportType.LOCAL, alias="_models"
308
+ relative_path,
309
+ "models",
310
+ ImportType.LOCAL,
311
+ alias="_models",
312
+ typing_section=TypingSection.TYPING
313
+ if kwargs.get("model_typing")
314
+ else TypingSection.REGULAR,
309
315
  )
310
316
  return file_import
311
317
 
@@ -41,6 +41,7 @@ from .request_builder import OverloadedRequestBuilder, RequestBuilder
41
41
  if TYPE_CHECKING:
42
42
  from .code_model import CodeModel
43
43
  from .client import Client
44
+ from . import OperationType
44
45
 
45
46
  ResponseType = TypeVar(
46
47
  "ResponseType",
@@ -63,8 +64,6 @@ class OperationBase( # pylint: disable=too-many-public-methods
63
64
  exceptions: List[Response],
64
65
  *,
65
66
  overloads: Optional[List["Operation"]] = None,
66
- public: bool = True,
67
- want_tracing: bool = True,
68
67
  ) -> None:
69
68
  super().__init__(
70
69
  code_model=code_model,
@@ -73,14 +72,16 @@ class OperationBase( # pylint: disable=too-many-public-methods
73
72
  name=name,
74
73
  parameters=parameters,
75
74
  overloads=overloads,
76
- want_tracing=want_tracing,
77
75
  )
78
76
  self.overloads: List["Operation"] = overloads or []
79
77
  self.responses = responses
80
- self.public = public
81
78
  self.request_builder = request_builder
82
79
  self.deprecated = False
83
80
  self.exceptions = exceptions
81
+ self.is_lro_initial_operation: bool = self.yaml_data.get(
82
+ "isLroInitialOperation", False
83
+ )
84
+ self.include_documentation: bool = not self.is_lro_initial_operation
84
85
 
85
86
  @property
86
87
  def operation_type(self) -> str:
@@ -438,6 +439,10 @@ class OperationBase( # pylint: disable=too-many-public-methods
438
439
  def has_stream_response(self) -> bool:
439
440
  return any(r.is_stream_response for r in self.responses)
440
441
 
442
+ @classmethod
443
+ def get_request_builder(cls, yaml_data: Dict[str, Any], client: "Client"):
444
+ return client.lookup_request_builder(id(yaml_data))
445
+
441
446
  @classmethod
442
447
  def from_yaml(
443
448
  cls,
@@ -446,7 +451,7 @@ class OperationBase( # pylint: disable=too-many-public-methods
446
451
  client: "Client",
447
452
  ):
448
453
  name = yaml_data["name"]
449
- request_builder = client.lookup_request_builder(id(yaml_data))
454
+ request_builder = cls.get_request_builder(yaml_data, client)
450
455
  responses = [
451
456
  cast(ResponseType, get_response(r, code_model))
452
457
  for r in yaml_data["responses"]
@@ -470,7 +475,6 @@ class OperationBase( # pylint: disable=too-many-public-methods
470
475
  overloads=overloads,
471
476
  responses=responses,
472
477
  exceptions=exceptions,
473
- want_tracing=not yaml_data["isOverload"],
474
478
  )
475
479
 
476
480
 
@@ -510,7 +514,7 @@ class Operation(OperationBase[Response]):
510
514
 
511
515
  def get_operation(
512
516
  yaml_data: Dict[str, Any], code_model: "CodeModel", client: "Client"
513
- ) -> OperationBase:
517
+ ) -> "OperationType":
514
518
  if yaml_data["discriminator"] == "lropaging":
515
519
  from .lro_paging_operation import LROPagingOperation as OperationCls
516
520
  elif yaml_data["discriminator"] == "lro":
@@ -8,13 +8,14 @@ from typing import Dict, List, Any, TYPE_CHECKING
8
8
  from autorest.codegen.models.utils import OrderedSet
9
9
 
10
10
  from .base import BaseModel
11
- from .operation import OperationBase, get_operation
11
+ from .operation import get_operation
12
12
  from .imports import FileImport, ImportType, TypingSection
13
13
  from .utils import add_to_pylint_disable
14
14
 
15
15
  if TYPE_CHECKING:
16
16
  from .code_model import CodeModel
17
17
  from .client import Client
18
+ from . import OperationType
18
19
 
19
20
 
20
21
  class OperationGroup(BaseModel):
@@ -25,7 +26,7 @@ class OperationGroup(BaseModel):
25
26
  yaml_data: Dict[str, Any],
26
27
  code_model: "CodeModel",
27
28
  client: "Client",
28
- operations: List[OperationBase],
29
+ operations: List["OperationType"],
29
30
  api_versions: List[str],
30
31
  ) -> None:
31
32
  super().__init__(yaml_data, code_model)
@@ -38,8 +38,6 @@ class PagingOperationBase(OperationBase[PagingResponseType]):
38
38
  exceptions: List[Response],
39
39
  *,
40
40
  overloads: Optional[List[Operation]] = None,
41
- public: bool = True,
42
- want_tracing: bool = True,
43
41
  override_success_response_to_200: bool = False,
44
42
  ) -> None:
45
43
  super().__init__(
@@ -52,8 +50,6 @@ class PagingOperationBase(OperationBase[PagingResponseType]):
52
50
  responses=responses,
53
51
  exceptions=exceptions,
54
52
  overloads=overloads,
55
- public=public,
56
- want_tracing=want_tracing,
57
53
  )
58
54
  self.next_request_builder: Optional[
59
55
  Union[RequestBuilder, OverloadedRequestBuilder]
@@ -17,7 +17,7 @@ from typing import (
17
17
  Generic,
18
18
  )
19
19
 
20
- from .imports import FileImport, ImportType
20
+ from .imports import FileImport, ImportType, TypingSection
21
21
  from .base import BaseModel
22
22
  from .base import BaseType
23
23
  from .constant_type import ConstantType
@@ -165,6 +165,13 @@ class _ParameterBase(
165
165
  "api_version_validation",
166
166
  ImportType.LOCAL,
167
167
  )
168
+ if isinstance(self.type, CombinedType) and self.type.name:
169
+ file_import.add_submodule_import(
170
+ "..",
171
+ "_types",
172
+ ImportType.LOCAL,
173
+ TypingSection.TYPING,
174
+ )
168
175
  return file_import
169
176
 
170
177
  def imports(self, async_mode: bool, **kwargs: Any) -> FileImport:
@@ -8,7 +8,7 @@ from typing import Any, Dict, Optional, TYPE_CHECKING, List
8
8
  from .base import BaseModel
9
9
  from .constant_type import ConstantType
10
10
  from .base import BaseType
11
- from .imports import FileImport, ImportType, TypingSection
11
+ from .imports import FileImport, ImportType
12
12
  from .utils import add_to_description, add_to_pylint_disable
13
13
 
14
14
  if TYPE_CHECKING:
@@ -129,32 +129,12 @@ class Property(BaseModel): # pylint: disable=too-many-instance-attributes
129
129
  retval.update(self.type.validation or {})
130
130
  return retval or None
131
131
 
132
- @staticmethod
133
- def contain_model_type(t: BaseType) -> bool:
134
- from . import ListType, DictionaryType, ModelType
135
-
136
- if isinstance(t, ModelType):
137
- return True
138
- if isinstance(t, ListType):
139
- return Property.contain_model_type(t.element_type)
140
- if isinstance(t, DictionaryType):
141
- return Property.contain_model_type(t.element_type)
142
- if isinstance(t, ConstantType):
143
- return Property.contain_model_type(t.value_type)
144
- return False
145
-
146
132
  def imports(self, **kwargs) -> FileImport:
147
- file_import = self.type.imports(**kwargs, is_operation_file=False)
133
+ file_import = self.type.imports(
134
+ **kwargs, is_operation_file=False, relative_path="..", model_typing=True
135
+ )
148
136
  if self.optional and self.client_default_value is None:
149
137
  file_import.add_submodule_import("typing", "Optional", ImportType.STDLIB)
150
- if self.contain_model_type(self.type):
151
- file_import.add_submodule_import(
152
- "..",
153
- "models",
154
- ImportType.LOCAL,
155
- TypingSection.TYPING,
156
- alias="_models",
157
- )
158
138
  if self.code_model.options["models_mode"] == "dpg":
159
139
  file_import.add_submodule_import(
160
140
  ".._model_base",
@@ -50,11 +50,11 @@ class RequestBuilderBase(BaseBuilder[ParameterListType]):
50
50
  name=name,
51
51
  parameters=parameters,
52
52
  overloads=overloads,
53
- want_tracing=False,
54
53
  )
55
54
  self.overloads: List["RequestBuilder"] = overloads or []
56
55
  self.url: str = yaml_data["url"]
57
56
  self.method: str = yaml_data["method"]
57
+ self.want_tracing = False
58
58
 
59
59
  def response_type_annotation(self, **kwargs) -> str:
60
60
  return "HttpRequest"
@@ -127,14 +127,13 @@ class RequestBuilderBase(BaseBuilder[ParameterListType]):
127
127
  ...
128
128
 
129
129
  @classmethod
130
- def from_yaml(
130
+ def get_name(
131
131
  cls,
132
+ name: str,
132
133
  yaml_data: Dict[str, Any],
133
134
  code_model: "CodeModel",
134
135
  client: "Client",
135
- ):
136
- # when combine embedded builders into one operation file, we need to avoid duplicated build function name.
137
- # So add operation group name is effective method
136
+ ) -> str:
138
137
  additional_mark = ""
139
138
  if (
140
139
  code_model.options["combine_operation_files"]
@@ -146,10 +145,21 @@ class RequestBuilderBase(BaseBuilder[ParameterListType]):
146
145
  names = [
147
146
  "build",
148
147
  additional_mark,
149
- yaml_data["name"],
148
+ name,
150
149
  "request",
151
150
  ]
152
- name = "_".join([n for n in names if n])
151
+ return "_".join([n for n in names if n])
152
+
153
+ @classmethod
154
+ def from_yaml(
155
+ cls,
156
+ yaml_data: Dict[str, Any],
157
+ code_model: "CodeModel",
158
+ client: "Client",
159
+ ):
160
+ # when combine embedded builders into one operation file, we need to avoid duplicated build function name.
161
+ # So add operation group name is effective method
162
+
153
163
  overloads = [
154
164
  RequestBuilder.from_yaml(rb_yaml_data, code_model, client)
155
165
  for rb_yaml_data in yaml_data.get("overloads", [])
@@ -160,7 +170,7 @@ class RequestBuilderBase(BaseBuilder[ParameterListType]):
160
170
  yaml_data=yaml_data,
161
171
  code_model=code_model,
162
172
  client=client,
163
- name=name,
173
+ name=cls.get_name(yaml_data["name"], yaml_data, code_model, client),
164
174
  parameters=parameter_list,
165
175
  overloads=overloads,
166
176
  )
@@ -7,11 +7,12 @@ from typing import Dict, Optional, List, Any, TYPE_CHECKING, Union
7
7
 
8
8
  from .base import BaseModel
9
9
  from .base import BaseType
10
- from .imports import FileImport, ImportType
10
+ from .imports import FileImport, ImportType, TypingSection
11
11
  from .primitive_types import BinaryType, BinaryIteratorType
12
12
  from .dictionary_type import DictionaryType
13
13
  from .list_type import ListType
14
14
  from .model_type import ModelType
15
+ from .combined_type import CombinedType
15
16
 
16
17
  if TYPE_CHECKING:
17
18
  from .code_model import CodeModel
@@ -105,6 +106,13 @@ class Response(BaseModel):
105
106
  file_import.merge(self.type.imports(is_operation_file=True, **kwargs))
106
107
  if self.nullable:
107
108
  file_import.add_submodule_import("typing", "Optional", ImportType.STDLIB)
109
+ if isinstance(self.type, CombinedType) and self.type.name:
110
+ file_import.add_submodule_import(
111
+ "..",
112
+ "_types",
113
+ ImportType.LOCAL,
114
+ TypingSection.TYPING,
115
+ )
108
116
  return file_import
109
117
 
110
118
  def imports(self, **kwargs: Any) -> FileImport:
@@ -27,6 +27,7 @@ from .metadata_serializer import MetadataSerializer
27
27
  from .request_builders_serializer import RequestBuildersSerializer
28
28
  from .patch_serializer import PatchSerializer
29
29
  from .sample_serializer import SampleSerializer
30
+ from .types_serializer import TypesSerializer
30
31
  from ..._utils import to_snake_case
31
32
  from .utils import extract_sample_name
32
33
 
@@ -192,6 +193,11 @@ class JinjaSerializer(ReaderAndWriter): # pylint: disable=abstract-method
192
193
  namespace_path / Path("models.py"),
193
194
  self.read_file(namespace_path / Path("models.py")),
194
195
  )
196
+ if self.code_model.named_unions:
197
+ self.write_file(
198
+ namespace_path / Path("_types.py"),
199
+ TypesSerializer(code_model=self.code_model, env=env).serialize(),
200
+ )
195
201
 
196
202
  def _serialize_and_write_package_files(self, namespace_path: Path) -> None:
197
203
  root_of_sdk = self._package_root_folder(namespace_path)
@@ -110,7 +110,7 @@ class ClientSerializer:
110
110
  def initialize_pipeline_client(self, async_mode: bool) -> str:
111
111
  pipeline_client_name = self.client.pipeline_class(async_mode)
112
112
  return (
113
- f"self._client = {pipeline_client_name}(base_url={self.host_variable_name}, "
113
+ f"self._client: {pipeline_client_name} = {pipeline_client_name}(base_url={self.host_variable_name}, "
114
114
  "config=self._config, **kwargs)"
115
115
  )
116
116
 
@@ -5,7 +5,7 @@
5
5
  # --------------------------------------------------------------------------
6
6
  import functools
7
7
  import json
8
- from typing import List, Optional, Set, Tuple, Dict, Union
8
+ from typing import List, Optional, Set, Tuple, Dict, Union, Any
9
9
  from jinja2 import Environment
10
10
  from ..models import (
11
11
  OperationGroup,
@@ -18,6 +18,12 @@ from ..models import (
18
18
  from .builder_serializer import get_operation_serializer
19
19
 
20
20
 
21
+ def _to_string(data: Union[Tuple[Any], List[Any], str]) -> str:
22
+ if isinstance(data, (list, tuple)):
23
+ return "".join([_to_string(item) for item in data])
24
+ return str(data)
25
+
26
+
21
27
  def _json_serialize_imports(
22
28
  imports: Dict[
23
29
  TypingSection,
@@ -59,7 +65,7 @@ def _json_serialize_imports(
59
65
  if name_imports:
60
66
  name_import_ordered_list = list(name_imports)
61
67
  name_import_ordered_list.sort(
62
- key=lambda e: "".join(e) # type: ignore
68
+ key=lambda e: _to_string(e) # type: ignore
63
69
  if isinstance(e, (list, tuple))
64
70
  else e
65
71
  if isinstance(e, str)
@@ -0,0 +1,38 @@
1
+ # -------------------------------------------------------------------------
2
+ # Copyright (c) Microsoft Corporation. All rights reserved.
3
+ # Licensed under the MIT License. See License.txt in the project root for
4
+ # license information.
5
+ # --------------------------------------------------------------------------
6
+ from jinja2 import Environment
7
+ from ..models import CodeModel
8
+ from ..models.imports import FileImport, ImportType
9
+ from .import_serializer import FileImportSerializer
10
+
11
+
12
+ class TypesSerializer:
13
+ def __init__(self, code_model: CodeModel, env: Environment) -> None:
14
+ self.code_model = code_model
15
+ self.env = env
16
+
17
+ def imports(self) -> FileImport:
18
+ file_import = FileImport()
19
+ if self.code_model.named_unions:
20
+ file_import.add_submodule_import(
21
+ "typing",
22
+ "Union",
23
+ ImportType.STDLIB,
24
+ )
25
+ for nu in self.code_model.named_unions:
26
+ file_import.merge(
27
+ nu.imports(relative_path=".", model_typing=True, is_types_file=True)
28
+ )
29
+ return file_import
30
+
31
+ def serialize(self) -> str:
32
+ # Generate the models
33
+ template = self.env.get_template("types.py.jinja2")
34
+ return template.render(
35
+ code_model=self.code_model,
36
+ imports=FileImportSerializer(self.imports()),
37
+ serializer=self,
38
+ )
@@ -1,6 +1,6 @@
1
1
  {% import 'operation_tools.jinja2' as op_tools with context %}
2
2
  {# actual template starts here #}
3
- {% if operation.overloads and operation.public %}
3
+ {% if operation.overloads and operation.include_documentation %}
4
4
  {{ op_tools.generate_overloads(operation_serializer, operation) }}
5
5
  {% endif %}
6
6
  {{ operation_serializer.method_signature_and_response_type_annotation(operation) }}
@@ -1,7 +1,7 @@
1
1
  {% import 'operation_tools.jinja2' as op_tools with context %}
2
2
  {% import 'keywords.jinja2' as keywords with context %}
3
3
  {# actual template starts here #}
4
- {% if operation.overloads and operation.public %}
4
+ {% if operation.overloads and operation.include_documentation %}
5
5
  {{ op_tools.generate_overloads(operation_serializer, operation) }}
6
6
  {% endif %}
7
7
  {{ operation_serializer.method_signature_and_response_type_annotation(operation) }}
@@ -1,11 +1,11 @@
1
1
  {% import 'keywords.jinja2' as keywords with context %}
2
2
  {% import 'operation_tools.jinja2' as op_tools %}
3
3
  {# actual template starts here #}
4
- {% if operation.overloads and operation.public %}
4
+ {% if operation.overloads and operation.include_documentation %}
5
5
  {{ op_tools.generate_overloads(operation_serializer, operation) }}
6
6
  {% endif %}
7
7
  {{ operation_serializer.method_signature_and_response_type_annotation(operation) }}
8
- {% if operation.public %}
8
+ {% if operation.include_documentation %}
9
9
  {{ op_tools.description(operation, operation_serializer) | indent }}{% endif %}
10
10
  {% if not operation.abstract %}
11
11
  {% if operation.deprecated %}
@@ -1,10 +1,10 @@
1
1
  {% import 'operation_tools.jinja2' as op_tools with context %}
2
2
  {# actual template starts here #}
3
- {% if operation.overloads and operation.public %}
3
+ {% if operation.overloads and operation.include_documentation %}
4
4
  {{ op_tools.generate_overloads(operation_serializer, operation) }}
5
5
  {% endif %}
6
6
  {{ operation_serializer.method_signature_and_response_type_annotation(operation) }}
7
- {% if operation.public %}
7
+ {% if operation.include_documentation %}
8
8
  {{ op_tools.description(operation, operation_serializer) | indent }}{% endif %}
9
9
  {% if not operation.abstract %}
10
10
  {% if operation.deprecated %}
@@ -0,0 +1,8 @@
1
+ # coding=utf-8
2
+ # pylint: disable=too-many-lines
3
+ {{ code_model.options['license_header'] }}
4
+
5
+ {{ imports }}
6
+ {% for nu in code_model.named_unions %}
7
+ {{nu.name}} = {{nu.type_definition()}}
8
+ {% endfor %}
@@ -299,10 +299,15 @@ def get_all_body_types(yaml_data: Dict[str, Any]) -> List[Dict[str, Any]]:
299
299
  return list(seen_body_types.values())
300
300
 
301
301
 
302
- def add_lro_information(operation: Dict[str, Any], yaml_data: Dict[str, Any]) -> None:
302
+ def add_lro_information(
303
+ operation: Dict[str, Any],
304
+ initial_operation: Dict[str, Any],
305
+ yaml_data: Dict[str, Any],
306
+ ) -> None:
303
307
  operation["discriminator"] = "lro"
304
308
  extensions = yaml_data["extensions"]
305
309
  operation["lroOptions"] = extensions.get("x-ms-long-running-operation-options")
310
+ operation["initialOperation"] = initial_operation
306
311
  for response in operation["responses"]:
307
312
  response["pollerSync"] = extensions.get("x-python-custom-poller-sync")
308
313
  response["pollerAsync"] = extensions.get("x-python-custom-poller-async")
@@ -551,7 +556,7 @@ class M4Reformatter(
551
556
 
552
557
  def get_operation_creator(
553
558
  self, yaml_data: Dict[str, Any]
554
- ) -> Callable[[str, Dict[str, Any]], Dict[str, Any]]:
559
+ ) -> Callable[[str, Dict[str, Any]], List[Dict[str, Any]]]:
555
560
  lro_operation = yaml_data.get("extensions", {}).get(
556
561
  "x-ms-long-running-operation"
557
562
  )
@@ -566,7 +571,7 @@ class M4Reformatter(
566
571
 
567
572
  def update_operation(
568
573
  self, group_name: str, yaml_data: Dict[str, Any]
569
- ) -> Dict[str, Any]:
574
+ ) -> List[Dict[str, Any]]:
570
575
  body_parameter = (
571
576
  self.update_body_parameter(yaml_data["requestMediaTypes"])
572
577
  if yaml_data.get("requestMediaTypes")
@@ -578,7 +583,7 @@ class M4Reformatter(
578
583
  group_name, yaml_data, body_parameter, content_types=content_types
579
584
  )
580
585
  operation["samples"] = yaml_data.get("extensions", {}).get("x-ms-examples", {})
581
- return operation
586
+ return [operation]
582
587
 
583
588
  def add_paging_information(
584
589
  self, group_name: str, operation: Dict[str, Any], yaml_data: Dict[str, Any]
@@ -596,7 +601,7 @@ class M4Reformatter(
596
601
  yaml_data=yaml_data["language"]["default"]["paging"][
597
602
  "nextLinkOperation"
598
603
  ],
599
- )
604
+ )[0]
600
605
  extensions = yaml_data["extensions"]
601
606
  for response in operation["responses"]:
602
607
  response["pagerSync"] = extensions.get("x-python-custom-pager-sync")
@@ -604,27 +609,43 @@ class M4Reformatter(
604
609
 
605
610
  def update_paging_operation(
606
611
  self, group_name: str, yaml_data: Dict[str, Any]
607
- ) -> Dict[str, Any]:
608
- base_operation = self.update_operation(group_name, yaml_data)
609
- self.add_paging_information(group_name, base_operation, yaml_data)
610
- return base_operation
612
+ ) -> List[Dict[str, Any]]:
613
+ retval: List[Dict[str, Any]] = []
614
+ for base_operation in self.update_operation(group_name, yaml_data):
615
+ self.add_paging_information(group_name, base_operation, yaml_data)
616
+ retval.append(base_operation)
617
+ return retval
611
618
 
612
619
  def update_lro_paging_operation(
613
620
  self, group_name: str, yaml_data: Dict[str, Any]
614
- ) -> Dict[str, Any]:
615
- operation = self.update_lro_operation(group_name, yaml_data)
616
- self.add_paging_information(group_name, operation, yaml_data)
617
- operation["discriminator"] = "lropaging"
618
- return operation
621
+ ) -> List[Dict[str, Any]]:
622
+ retval: List[Dict[str, Any]] = []
623
+ for operation in self.update_lro_operation(group_name, yaml_data):
624
+ if operation.get("discriminator") == "lro":
625
+ self.add_paging_information(group_name, operation, yaml_data)
626
+ operation["discriminator"] = "lropaging"
627
+ retval.append(operation)
628
+ return retval
629
+
630
+ def update_lro_initial_operation(self, initial_operation: Dict[str, Any]):
631
+ initial_operation["name"] = f"_{initial_operation['name']}_initial"
632
+ initial_operation["isLroInitialOperation"] = True
633
+ initial_operation["wantTracing"] = False
634
+ return initial_operation
619
635
 
620
636
  def update_lro_operation(
621
637
  self, group_name: str, yaml_data: Dict[str, Any]
622
- ) -> Dict[str, Any]:
623
- base_operation = self.update_operation(group_name, yaml_data)
624
- add_lro_information(base_operation, yaml_data)
625
- for overload in base_operation["overloads"]:
626
- add_lro_information(overload, yaml_data)
627
- return base_operation
638
+ ) -> List[Dict[str, Any]]:
639
+ retval: List[Dict[str, Any]] = []
640
+ for base_operation in self.update_operation(group_name, yaml_data):
641
+ initial_operation = self.update_operation(group_name, yaml_data)[0]
642
+ self.update_lro_initial_operation(initial_operation)
643
+ add_lro_information(base_operation, initial_operation, yaml_data)
644
+ for overload in base_operation["overloads"]:
645
+ add_lro_information(overload, initial_operation, yaml_data)
646
+ retval.append(initial_operation)
647
+ retval.append(base_operation)
648
+ return retval
628
649
 
629
650
  def update_overload(
630
651
  self,
@@ -648,8 +669,9 @@ class M4Reformatter(
648
669
  "className": property_name,
649
670
  "operations": filter_out_paging_next_operation(
650
671
  [
651
- self.get_operation_creator(o)(property_name, o)
652
- for o in yaml_data["operations"]
672
+ o
673
+ for ydo in yaml_data["operations"]
674
+ for o in self.get_operation_creator(ydo)(property_name, ydo)
653
675
  ]
654
676
  ),
655
677
  }
@@ -68,6 +68,8 @@ def add_overload(
68
68
  overload["bodyParameter"]["type"] = body_type
69
69
  overload["bodyParameter"]["defaultToUnsetSentinel"] = False
70
70
  overload["overloads"] = []
71
+ if yaml_data.get("initialOperation"):
72
+ overload["initialOperation"] = yaml_data["initialOperation"]
71
73
 
72
74
  if for_flatten_params:
73
75
  overload["bodyParameter"]["flattened"] = True
@@ -320,9 +322,15 @@ class PreProcessPlugin(YamlUpdatePlugin): # pylint: disable=abstract-method
320
322
  is_overload: bool = False,
321
323
  ) -> None:
322
324
  self.update_operation(code_model, yaml_data, is_overload=is_overload)
325
+ self.update_operation(
326
+ code_model, yaml_data["initialOperation"], is_overload=is_overload
327
+ )
323
328
  self._update_lro_operation_helper(yaml_data)
324
329
  for overload in yaml_data.get("overloads", []):
325
330
  self._update_lro_operation_helper(overload)
331
+ self.update_operation(
332
+ code_model, overload["initialOperation"], is_overload=True
333
+ )
326
334
 
327
335
  def update_paging_operation(
328
336
  self,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@autorest/python",
3
- "version": "6.4.0",
3
+ "version": "6.4.2",
4
4
  "description": "The Python extension for generators in AutoRest.",
5
5
  "main": "index.js",
6
6
  "repository": {