@autorest/python 5.16.0 → 5.17.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 (92) hide show
  1. package/ChangeLog.md +43 -3
  2. package/README.md +30 -4
  3. package/autorest/__init__.py +1 -1
  4. package/autorest/codegen/__init__.py +48 -209
  5. package/autorest/codegen/models/__init__.py +116 -83
  6. package/autorest/codegen/models/base_builder.py +49 -88
  7. package/autorest/codegen/models/base_model.py +1 -1
  8. package/autorest/codegen/models/{base_schema.py → base_type.py} +56 -40
  9. package/autorest/codegen/models/client.py +157 -48
  10. package/autorest/codegen/models/code_model.py +108 -254
  11. package/autorest/codegen/models/combined_type.py +107 -0
  12. package/autorest/codegen/models/{constant_schema.py → constant_type.py} +49 -40
  13. package/autorest/codegen/models/credential_types.py +224 -0
  14. package/autorest/codegen/models/{dictionary_schema.py → dictionary_type.py} +41 -31
  15. package/autorest/codegen/models/enum_type.py +195 -0
  16. package/autorest/codegen/models/imports.py +23 -0
  17. package/autorest/codegen/models/list_type.py +134 -0
  18. package/autorest/codegen/models/lro_operation.py +77 -156
  19. package/autorest/codegen/models/lro_paging_operation.py +28 -11
  20. package/autorest/codegen/models/model_type.py +239 -0
  21. package/autorest/codegen/models/operation.py +303 -269
  22. package/autorest/codegen/models/operation_group.py +48 -89
  23. package/autorest/codegen/models/paging_operation.py +80 -123
  24. package/autorest/codegen/models/parameter.py +289 -396
  25. package/autorest/codegen/models/parameter_list.py +348 -360
  26. package/autorest/codegen/models/primitive_types.py +544 -0
  27. package/autorest/codegen/models/property.py +109 -139
  28. package/autorest/codegen/models/request_builder.py +105 -88
  29. package/autorest/codegen/models/request_builder_parameter.py +112 -100
  30. package/autorest/codegen/models/response.py +325 -0
  31. package/autorest/codegen/models/utils.py +12 -19
  32. package/autorest/codegen/serializers/__init__.py +46 -37
  33. package/autorest/codegen/serializers/builder_serializer.py +604 -1146
  34. package/autorest/codegen/serializers/client_serializer.py +83 -88
  35. package/autorest/codegen/serializers/general_serializer.py +5 -64
  36. package/autorest/codegen/serializers/import_serializer.py +7 -4
  37. package/autorest/codegen/serializers/metadata_serializer.py +15 -104
  38. package/autorest/codegen/serializers/model_base_serializer.py +40 -32
  39. package/autorest/codegen/serializers/model_generic_serializer.py +8 -6
  40. package/autorest/codegen/serializers/model_init_serializer.py +2 -4
  41. package/autorest/codegen/serializers/model_python3_serializer.py +22 -16
  42. package/autorest/codegen/serializers/operation_groups_serializer.py +4 -13
  43. package/autorest/codegen/serializers/parameter_serializer.py +174 -0
  44. package/autorest/codegen/serializers/request_builders_serializer.py +12 -29
  45. package/autorest/codegen/serializers/utils.py +0 -142
  46. package/autorest/codegen/templates/MANIFEST.in.jinja2 +1 -0
  47. package/autorest/codegen/templates/{service_client.py.jinja2 → client.py.jinja2} +7 -7
  48. package/autorest/codegen/templates/config.py.jinja2 +13 -13
  49. package/autorest/codegen/templates/enum.py.jinja2 +4 -4
  50. package/autorest/codegen/templates/enum_container.py.jinja2 +1 -1
  51. package/autorest/codegen/templates/init.py.jinja2 +2 -2
  52. package/autorest/codegen/templates/lro_operation.py.jinja2 +4 -1
  53. package/autorest/codegen/templates/lro_paging_operation.py.jinja2 +4 -1
  54. package/autorest/codegen/templates/metadata.json.jinja2 +33 -33
  55. package/autorest/codegen/templates/model.py.jinja2 +23 -24
  56. package/autorest/codegen/templates/model_container.py.jinja2 +2 -1
  57. package/autorest/codegen/templates/model_init.py.jinja2 +3 -5
  58. package/autorest/codegen/templates/operation.py.jinja2 +6 -8
  59. package/autorest/codegen/templates/operation_group.py.jinja2 +7 -7
  60. package/autorest/codegen/templates/operation_groups_container.py.jinja2 +1 -1
  61. package/autorest/codegen/templates/operation_tools.jinja2 +8 -2
  62. package/autorest/codegen/templates/paging_operation.py.jinja2 +2 -2
  63. package/autorest/codegen/templates/request_builder.py.jinja2 +13 -11
  64. package/autorest/codegen/templates/setup.py.jinja2 +9 -3
  65. package/autorest/codegen/templates/vendor.py.jinja2 +1 -1
  66. package/autorest/jsonrpc/server.py +15 -3
  67. package/autorest/m4reformatter/__init__.py +1108 -0
  68. package/autorest/multiapi/models/code_model.py +1 -1
  69. package/autorest/multiapi/serializers/__init__.py +4 -4
  70. package/autorest/multiapi/templates/multiapi_config.py.jinja2 +3 -3
  71. package/autorest/multiapi/templates/multiapi_init.py.jinja2 +2 -2
  72. package/autorest/multiapi/templates/multiapi_operations_mixin.py.jinja2 +3 -3
  73. package/autorest/multiapi/templates/multiapi_service_client.py.jinja2 +9 -9
  74. package/autorest/postprocess/__init__.py +202 -0
  75. package/autorest/postprocess/get_all.py +19 -0
  76. package/autorest/postprocess/venvtools.py +73 -0
  77. package/autorest/preprocess/__init__.py +209 -0
  78. package/autorest/preprocess/helpers.py +54 -0
  79. package/autorest/{namer → preprocess}/python_mappings.py +21 -16
  80. package/package.json +2 -2
  81. package/autorest/codegen/models/credential_model.py +0 -55
  82. package/autorest/codegen/models/credential_schema.py +0 -95
  83. package/autorest/codegen/models/credential_schema_policy.py +0 -73
  84. package/autorest/codegen/models/enum_schema.py +0 -225
  85. package/autorest/codegen/models/list_schema.py +0 -135
  86. package/autorest/codegen/models/object_schema.py +0 -303
  87. package/autorest/codegen/models/primitive_schemas.py +0 -495
  88. package/autorest/codegen/models/request_builder_parameter_list.py +0 -249
  89. package/autorest/codegen/models/schema_request.py +0 -55
  90. package/autorest/codegen/models/schema_response.py +0 -141
  91. package/autorest/namer/__init__.py +0 -23
  92. package/autorest/namer/name_converter.py +0 -509
@@ -0,0 +1,195 @@
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 typing import Any, Dict, List, TYPE_CHECKING, Optional
7
+
8
+ from .base_type import BaseType
9
+ from .imports import FileImport, ImportType, TypingSection
10
+ from .base_model import BaseModel
11
+
12
+ if TYPE_CHECKING:
13
+ from .code_model import CodeModel
14
+
15
+
16
+ class EnumValue(BaseModel):
17
+ """Model containing necessary information for a single value of an enum.
18
+
19
+ :param str name: The name of this enum value
20
+ :param str value: The value of this enum value
21
+ :param str description: Optional. The description for this enum value
22
+ """
23
+
24
+ def __init__(self, yaml_data: Dict[str, Any], code_model: "CodeModel") -> None:
25
+ super().__init__(yaml_data=yaml_data, code_model=code_model)
26
+ self.name: str = self.yaml_data["name"]
27
+ self.value: str = self.yaml_data["value"]
28
+ self.description: Optional[str] = self.yaml_data.get("description")
29
+
30
+ @classmethod
31
+ def from_yaml(
32
+ cls, yaml_data: Dict[str, Any], code_model: "CodeModel"
33
+ ) -> "EnumValue":
34
+ """Constructs an EnumValue from yaml data.
35
+
36
+ :param yaml_data: the yaml data from which we will construct this object
37
+ :type yaml_data: dict[str, Any]
38
+
39
+ :return: A created EnumValue
40
+ :rtype: ~autorest.models.EnumValue
41
+ """
42
+ return cls(
43
+ yaml_data=yaml_data,
44
+ code_model=code_model,
45
+ )
46
+
47
+
48
+ class EnumType(BaseType):
49
+ """Schema for enums that will be serialized.
50
+
51
+ :param yaml_data: the yaml data for this schema
52
+ :type yaml_data: dict[str, Any]
53
+ :param str description: The description of this enum
54
+ :param str name: The name of the enum.
55
+ :type element_type: ~autorest.models.PrimitiveType
56
+ :param values: List of the values for this enum
57
+ :type values: list[~autorest.models.EnumValue]
58
+ """
59
+
60
+ def __init__(
61
+ self,
62
+ yaml_data: Dict[str, Any],
63
+ code_model: "CodeModel",
64
+ values: List["EnumValue"],
65
+ value_type: BaseType,
66
+ ) -> None:
67
+ super().__init__(yaml_data=yaml_data, code_model=code_model)
68
+ self.name: str = yaml_data["name"]
69
+ self.values = values
70
+ self.value_type = value_type
71
+
72
+ def __lt__(self, other):
73
+ return self.name.lower() < other.name.lower()
74
+
75
+ @property
76
+ def serialization_type(self) -> str:
77
+ """Returns the serialization value for msrest.
78
+
79
+ :return: The serialization value for msrest
80
+ :rtype: str
81
+ """
82
+ return self.value_type.serialization_type
83
+
84
+ def description(
85
+ self, *, is_operation_file: bool # pylint: disable=unused-argument
86
+ ) -> str:
87
+ possible_values = [self.get_declaration(v.value) for v in self.values]
88
+ if not possible_values:
89
+ return ""
90
+ if len(possible_values) == 1:
91
+ return possible_values[0]
92
+ if len(possible_values) == 2:
93
+ possible_values_str = " and ".join(possible_values)
94
+ else:
95
+ possible_values_str = (
96
+ ", ".join(possible_values[: len(possible_values) - 1])
97
+ + f", and {possible_values[-1]}"
98
+ )
99
+
100
+ enum_description = f"Known values are: {possible_values_str}."
101
+ return enum_description
102
+
103
+ def type_annotation(self, **kwargs: Any) -> str:
104
+ """The python type used for type annotation
105
+
106
+ :return: The type annotation for this schema
107
+ :rtype: str
108
+ """
109
+ if self.code_model.options["models_mode"]:
110
+ return (
111
+ f"Union[{self.value_type.type_annotation(**kwargs)},"
112
+ f' "_models.{self.name}"]'
113
+ )
114
+ return self.value_type.type_annotation(**kwargs)
115
+
116
+ def get_declaration(self, value: Any) -> str:
117
+ return self.value_type.get_declaration(value)
118
+
119
+ def docstring_text(self, **kwargs: Any) -> str:
120
+ if self.code_model.options["models_mode"]:
121
+ return self.name
122
+ return self.value_type.type_annotation(**kwargs)
123
+
124
+ def docstring_type(self, **kwargs: Any) -> str:
125
+ """The python type used for RST syntax input and type annotation."""
126
+ if self.code_model.options["models_mode"]:
127
+ return f"{self.value_type.type_annotation(**kwargs)} or ~{self.code_model.namespace}.models.{self.name}"
128
+ return self.value_type.type_annotation(**kwargs)
129
+
130
+ def get_json_template_representation(
131
+ self,
132
+ *,
133
+ optional: bool = True,
134
+ client_default_value_declaration: Optional[str] = None,
135
+ description: Optional[str] = None,
136
+ ) -> Any:
137
+ # for better display effect, use the only value instead of var type
138
+ return self.value_type.get_json_template_representation(
139
+ optional=optional,
140
+ client_default_value_declaration=client_default_value_declaration,
141
+ description=description,
142
+ )
143
+
144
+ @property
145
+ def instance_check_template(self) -> str:
146
+ return self.value_type.instance_check_template
147
+
148
+ @classmethod
149
+ def from_yaml(
150
+ cls, yaml_data: Dict[str, Any], code_model: "CodeModel"
151
+ ) -> "EnumType":
152
+ """Constructs an EnumType from yaml data.
153
+
154
+ :param yaml_data: the yaml data from which we will construct this schema
155
+ :type yaml_data: dict[str, Any]
156
+
157
+ :return: A created EnumType
158
+ :rtype: ~autorest.models.EnumType
159
+ """
160
+ from . import build_type
161
+
162
+ return cls(
163
+ yaml_data=yaml_data,
164
+ code_model=code_model,
165
+ value_type=build_type(yaml_data["valueType"], code_model),
166
+ values=[
167
+ EnumValue.from_yaml(value, code_model) for value in yaml_data["values"]
168
+ ],
169
+ )
170
+
171
+ def imports(self, **kwargs: Any) -> FileImport:
172
+ is_operation_file = kwargs.pop("is_operation_file", False)
173
+ file_import = FileImport()
174
+ if self.code_model.options["models_mode"]:
175
+ file_import.add_submodule_import(
176
+ "typing", "Union", ImportType.STDLIB, TypingSection.CONDITIONAL
177
+ )
178
+ if not is_operation_file:
179
+ file_import.add_submodule_import(
180
+ "..",
181
+ "models",
182
+ ImportType.LOCAL,
183
+ TypingSection.TYPING,
184
+ alias="_models",
185
+ )
186
+ file_import.merge(
187
+ self.value_type.imports(is_operation_file=is_operation_file, **kwargs)
188
+ )
189
+ relative_path = kwargs.pop("relative_path", None)
190
+ if self.code_model.options["models_mode"] and relative_path:
191
+ # add import for enums in operations file
192
+ file_import.add_submodule_import(
193
+ relative_path, "models", ImportType.LOCAL, alias="_models"
194
+ )
195
+ return file_import
@@ -147,6 +147,29 @@ class FileImport:
147
147
  self._append_import(i)
148
148
  self.type_definitions.update(file_import.type_definitions)
149
149
 
150
+ def define_mutable_mapping_type(self) -> None:
151
+ """Helper function for defining the mutable mapping type"""
152
+ self.define_mypy_type(
153
+ "JSON",
154
+ "MutableMapping[str, Any] # pylint: disable=unsubscriptable-object",
155
+ None,
156
+ {
157
+ (3, 9): ImportModel(
158
+ TypingSection.CONDITIONAL,
159
+ ImportType.STDLIB,
160
+ "collections.abc",
161
+ submodule_name="MutableMapping",
162
+ ),
163
+ None: ImportModel(
164
+ TypingSection.CONDITIONAL,
165
+ ImportType.STDLIB,
166
+ "typing",
167
+ submodule_name="MutableMapping",
168
+ ),
169
+ },
170
+ )
171
+ self.add_submodule_import("typing", "Any", ImportType.STDLIB)
172
+
150
173
  def to_dict(
151
174
  self,
152
175
  ) -> Dict[
@@ -0,0 +1,134 @@
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 typing import Any, Dict, Optional, Union, TYPE_CHECKING
7
+ from .base_type import BaseType
8
+ from .imports import FileImport, ImportType, TypingSection
9
+
10
+ if TYPE_CHECKING:
11
+ from .code_model import CodeModel
12
+
13
+
14
+ class ListType(BaseType):
15
+ def __init__(
16
+ self,
17
+ yaml_data: Dict[str, Any],
18
+ code_model: "CodeModel",
19
+ element_type: BaseType,
20
+ ) -> None:
21
+ super().__init__(yaml_data=yaml_data, code_model=code_model)
22
+ self.element_type = element_type
23
+ self.max_items: Optional[int] = yaml_data.get("maxItems")
24
+ self.min_items: Optional[int] = yaml_data.get("minItems")
25
+ self.unique_items: bool = yaml_data.get("uniqueItems", False)
26
+
27
+ @property
28
+ def serialization_type(self) -> str:
29
+ return f"[{self.element_type.serialization_type}]"
30
+
31
+ def type_annotation(self, **kwargs: Any) -> str:
32
+ if self.code_model.options["version_tolerant"] and self.element_type.is_xml:
33
+ # this means we're version tolerant XML, we just return the XML element
34
+ return self.element_type.type_annotation(**kwargs)
35
+ return f"List[{self.element_type.type_annotation(**kwargs)}]"
36
+
37
+ def description(self, *, is_operation_file: bool) -> str:
38
+ return "" if is_operation_file else self.yaml_data.get("description", "")
39
+
40
+ @property
41
+ def xml_serialization_ctxt(self) -> Optional[str]:
42
+ attrs_list = []
43
+ base_xml_map = super().xml_serialization_ctxt
44
+ if base_xml_map:
45
+ attrs_list.append(base_xml_map)
46
+
47
+ # Attribute at the list level
48
+ if self.xml_metadata.get("wrapped", False):
49
+ attrs_list.append("'wrapped': True")
50
+
51
+ # Attributes of the items
52
+ item_xml_metadata = self.element_type.xml_metadata
53
+ if item_xml_metadata.get("name"):
54
+ attrs_list.append(f"'itemsName': '{item_xml_metadata['name']}'")
55
+ if item_xml_metadata.get("prefix", False):
56
+ attrs_list.append(f"'itemsPrefix': '{item_xml_metadata['prefix']}'")
57
+ if item_xml_metadata.get("namespace", False):
58
+ attrs_list.append(f"'itemsNs': '{item_xml_metadata['namespace']}'")
59
+
60
+ return ", ".join(attrs_list)
61
+
62
+ def docstring_type(self, **kwargs: Any) -> str:
63
+ if (
64
+ self.code_model.options["version_tolerant"]
65
+ and self.element_type.xml_metadata
66
+ ):
67
+ # this means we're version tolerant XML, we just return the XML element
68
+ return self.element_type.docstring_type(**kwargs)
69
+ return f"list[{self.element_type.docstring_type(**kwargs)}]"
70
+
71
+ def docstring_text(self, **kwargs: Any) -> str:
72
+ if (
73
+ self.code_model.options["version_tolerant"]
74
+ and self.element_type.xml_metadata
75
+ ):
76
+ # this means we're version tolerant XML, we just return the XML element
77
+ return self.element_type.docstring_text(**kwargs)
78
+ return f"list of {self.element_type.docstring_text(**kwargs)}"
79
+
80
+ @property
81
+ def validation(self) -> Optional[Dict[str, Union[bool, int, str]]]:
82
+ validation: Dict[str, Union[bool, int, str]] = {}
83
+ if self.max_items:
84
+ validation["max_items"] = self.max_items
85
+ validation["min_items"] = self.min_items or 0
86
+ if self.min_items:
87
+ validation["min_items"] = self.min_items
88
+ if self.unique_items:
89
+ validation["unique"] = True
90
+ return validation or None
91
+
92
+ def get_json_template_representation(
93
+ self,
94
+ *,
95
+ optional: bool = True,
96
+ client_default_value_declaration: Optional[str] = None,
97
+ description: Optional[str] = None,
98
+ ) -> Any:
99
+ return [
100
+ self.element_type.get_json_template_representation(
101
+ optional=optional,
102
+ client_default_value_declaration=client_default_value_declaration,
103
+ description=description,
104
+ )
105
+ ]
106
+
107
+ @property
108
+ def instance_check_template(self) -> str:
109
+ return "isinstance({}, list)"
110
+
111
+ @classmethod
112
+ def from_yaml(
113
+ cls, yaml_data: Dict[str, Any], code_model: "CodeModel"
114
+ ) -> "ListType":
115
+ from . import build_type
116
+
117
+ return cls(
118
+ yaml_data=yaml_data,
119
+ code_model=code_model,
120
+ element_type=build_type(
121
+ yaml_data=yaml_data["elementType"], code_model=code_model
122
+ ),
123
+ )
124
+
125
+ def imports(self, **kwargs: Any) -> FileImport:
126
+ file_import = FileImport()
127
+ if not (
128
+ self.code_model.options["version_tolerant"] and self.element_type.is_xml
129
+ ):
130
+ file_import.add_submodule_import(
131
+ "typing", "List", ImportType.STDLIB, TypingSection.CONDITIONAL
132
+ )
133
+ file_import.merge(self.element_type.imports(**kwargs))
134
+ return file_import
@@ -3,218 +3,139 @@
3
3
  # Licensed under the MIT License. See License.txt in the project root for
4
4
  # license information.
5
5
  # --------------------------------------------------------------------------
6
- import logging
7
- from typing import Dict, List, Any, Optional, Set, cast, TYPE_CHECKING
6
+ from typing import Any, Dict, Optional, List, TYPE_CHECKING, TypeVar, Union
8
7
  from .imports import FileImport
9
- from .operation import Operation
10
- from .parameter_list import ParameterList
11
- from .schema_response import SchemaResponse
8
+ from .operation import OperationBase, Operation
9
+ from .response import LROPagingResponse, LROResponse, Response
12
10
  from .imports import ImportType, TypingSection
13
- from .base_schema import BaseSchema
14
- from .schema_request import SchemaRequest
15
11
  from .request_builder import RequestBuilder
12
+ from .parameter_list import ParameterList
16
13
 
17
14
  if TYPE_CHECKING:
18
15
  from .code_model import CodeModel
19
16
 
20
- _LOGGER = logging.getLogger(__name__)
17
+ LROResponseType = TypeVar(
18
+ "LROResponseType", bound=Union[LROResponse, LROPagingResponse]
19
+ )
21
20
 
22
21
 
23
- class LROOperation(Operation):
22
+ class LROOperationBase(OperationBase[LROResponseType]):
24
23
  def __init__(
25
24
  self,
26
25
  yaml_data: Dict[str, Any],
27
26
  code_model: "CodeModel",
28
- request_builder: RequestBuilder,
29
27
  name: str,
30
- description: str,
31
- api_versions: Set[str],
28
+ request_builder: RequestBuilder,
32
29
  parameters: ParameterList,
33
- multiple_content_type_parameters: ParameterList,
34
- schema_requests: List[SchemaRequest],
35
- summary: Optional[str] = None,
36
- responses: Optional[List[SchemaResponse]] = None,
37
- exceptions: Optional[List[SchemaResponse]] = None,
38
- want_description_docstring: bool = True,
39
- want_tracing: bool = True,
30
+ responses: List[LROResponseType],
31
+ exceptions: List[Response],
40
32
  *,
33
+ overloads: Optional[List[Operation]] = None,
34
+ public: bool = True,
35
+ want_tracing: bool = True,
41
36
  abstract: bool = False,
42
37
  ) -> None:
43
38
  super().__init__(
44
- yaml_data,
45
- code_model,
46
- request_builder,
47
- name,
48
- description,
49
- api_versions,
50
- parameters,
51
- multiple_content_type_parameters,
52
- schema_requests,
53
- summary,
54
- responses,
55
- exceptions,
56
- want_description_docstring,
39
+ code_model=code_model,
40
+ yaml_data=yaml_data,
41
+ name=name,
42
+ request_builder=request_builder,
43
+ parameters=parameters,
44
+ responses=responses,
45
+ exceptions=exceptions,
46
+ overloads=overloads,
47
+ public=public,
57
48
  want_tracing=want_tracing,
58
49
  abstract=abstract,
59
50
  )
60
- self.lro_options = yaml_data.get("extensions", {}).get(
61
- "x-ms-long-running-operation-options", {}
62
- )
63
51
  self.name = "begin_" + self.name
52
+ self.lro_options: Dict[str, Any] = self.yaml_data.get("lroOptions", {})
64
53
 
65
54
  @property
66
- def lro_response(self) -> Optional[SchemaResponse]:
67
- if not self.responses:
68
- return None
69
- responses_with_bodies = [r for r in self.responses if r.has_body]
70
- num_response_schemas = {r.schema for r in responses_with_bodies}
55
+ def operation_type(self) -> str:
56
+ return "lro"
57
+
58
+ @property
59
+ def has_optional_return_type(self) -> bool:
60
+ return False
61
+
62
+ @property
63
+ def lro_response(self) -> Optional[LROResponseType]:
64
+ responses_with_bodies = [r for r in self.responses if r.type]
65
+ num_response_schemas = {
66
+ id(r.type.yaml_data) for r in responses_with_bodies if r.type
67
+ }
71
68
  response = None
72
69
  if len(num_response_schemas) > 1:
73
70
  # choose the response that has a status code of 200
74
- responses_with_200_status_codes = [
75
- r for r in responses_with_bodies if 200 in r.status_codes
76
- ]
77
71
  try:
78
- response = responses_with_200_status_codes[0]
79
- schema_types = {r.schema for r in responses_with_bodies}
80
- response_schema = cast(BaseSchema, response.schema).serialization_type
81
- _LOGGER.warning(
82
- "Multiple schema types in responses: %s. Choosing: %s",
83
- schema_types,
84
- response_schema,
72
+ response = next(
73
+ r for r in responses_with_bodies if 200 in r.status_codes
85
74
  )
86
- except IndexError:
75
+ except StopIteration:
87
76
  raise ValueError(
88
77
  f"Your swagger is invalid because you have multiple response schemas for LRO"
89
- + f" method {self.python_name} and none of them have a 200 status code."
78
+ + f" method {self.name} and none of them have a 200 status code."
90
79
  )
91
80
 
92
81
  elif num_response_schemas:
93
82
  response = responses_with_bodies[0]
94
83
  return response
95
84
 
85
+ def cls_type_annotation(self, *, async_mode: bool) -> str:
86
+ """We don't want the poller to show up in ClsType, so we call super() on resposne type annotation"""
87
+ return f"ClsType[{Response.type_annotation(self.responses[0], async_mode=async_mode)}]"
88
+
96
89
  @property
97
90
  def initial_operation(self) -> Operation:
98
- operation = Operation(
99
- yaml_data={},
91
+ """Initial operation that creates the first call for LRO polling"""
92
+ return Operation(
93
+ yaml_data=self.yaml_data,
100
94
  code_model=self.code_model,
101
95
  request_builder=self.code_model.lookup_request_builder(id(self.yaml_data)),
102
96
  name=self.name[5:] + "_initial",
103
- description="",
104
- api_versions=self.api_versions,
97
+ overloads=self.overloads,
105
98
  parameters=self.parameters,
106
- schema_requests=self.schema_requests,
107
- multiple_content_type_parameters=self.multiple_content_type_parameters,
108
- summary=self.summary,
109
- responses=self.responses,
110
- want_description_docstring=False,
99
+ responses=[
100
+ Response(r.yaml_data, self.code_model, headers=r.headers, type=r.type)
101
+ for r in self.responses
102
+ ],
103
+ exceptions=self.exceptions,
104
+ public=False,
111
105
  want_tracing=False,
112
106
  )
113
- operation.request_builder = self.request_builder
114
- return operation
115
-
116
- @property
117
- def has_optional_return_type(self) -> bool:
118
- """An LROOperation will never have an optional return type, we will always return a poller"""
119
- return False
120
-
121
- def _get_lro_extension(self, extension_base, async_mode, *, azure_arm=None):
122
- extension_name = extension_base + ("-async" if async_mode else "-sync")
123
- extension = self.yaml_data["extensions"][extension_name]
124
- arm_extension = None
125
- if azure_arm is not None:
126
- arm_extension = "azure-arm" if azure_arm else "data-plane"
127
- return extension[arm_extension] if arm_extension else extension
128
-
129
- def get_poller_path(self, async_mode: bool) -> str:
130
- return self._get_lro_extension("poller", async_mode)
131
107
 
132
108
  def get_poller(self, async_mode: bool) -> str:
133
- return self.get_poller_path(async_mode).split(".")[-1]
134
-
135
- def get_default_polling_method_path(self, async_mode: bool, azure_arm: bool) -> str:
136
- return self._get_lro_extension(
137
- "default-polling-method", async_mode, azure_arm=azure_arm
138
- )
109
+ return self.responses[0].get_poller(async_mode)
139
110
 
140
- def get_default_polling_method(self, async_mode: bool, azure_arm: bool) -> str:
141
- return self.get_default_polling_method_path(async_mode, azure_arm).split(".")[
142
- -1
143
- ]
144
-
145
- def get_default_no_polling_method_path(self, async_mode: bool) -> str:
146
- return self._get_lro_extension("default-no-polling-method", async_mode)
147
-
148
- def get_default_no_polling_method(self, async_mode: bool) -> str:
149
- return self.get_default_no_polling_method_path(async_mode).split(".")[-1]
150
-
151
- def get_base_polling_method_path(self, async_mode: bool) -> str:
152
- return self._get_lro_extension("base-polling-method", async_mode)
111
+ def get_polling_method(self, async_mode: bool) -> str:
112
+ return self.responses[0].get_polling_method(async_mode)
153
113
 
154
114
  def get_base_polling_method(self, async_mode: bool) -> str:
155
- return self.get_base_polling_method_path(async_mode).split(".")[-1]
115
+ return self.responses[0].get_base_polling_method(async_mode)
156
116
 
157
- def imports_for_multiapi(self, async_mode: bool) -> FileImport:
158
- file_import = super().imports_for_multiapi(async_mode)
159
- poller_import_path = ".".join(self.get_poller_path(async_mode).split(".")[:-1])
160
- poller = self.get_poller(async_mode)
161
- file_import.add_submodule_import(
162
- poller_import_path, poller, ImportType.AZURECORE, TypingSection.CONDITIONAL
163
- )
164
- return file_import
165
-
166
- def imports(self, async_mode: bool, is_python3_file: bool) -> FileImport:
167
- file_import = self._imports_base(async_mode, is_python3_file)
168
- file_import.add_submodule_import(
169
- "typing", "Union", ImportType.STDLIB, TypingSection.CONDITIONAL
170
- )
171
-
172
- poller_import_path = ".".join(self.get_poller_path(async_mode).split(".")[:-1])
173
- poller = self.get_poller(async_mode)
174
- file_import.add_submodule_import(
175
- poller_import_path, poller, ImportType.AZURECORE
176
- )
177
-
178
- default_polling_method_import_path = ".".join(
179
- self.get_default_polling_method_path(
180
- async_mode, self.code_model.options["azure_arm"]
181
- ).split(".")[:-1]
182
- )
183
- default_polling_method = self.get_default_polling_method(
184
- async_mode, self.code_model.options["azure_arm"]
185
- )
186
- file_import.add_submodule_import(
187
- default_polling_method_import_path,
188
- default_polling_method,
189
- ImportType.AZURECORE,
190
- )
117
+ def get_base_polling_method_path(self, async_mode: bool) -> str:
118
+ return self.responses[0].get_base_polling_method_path(async_mode)
191
119
 
192
- default_no_polling_method_import_path = ".".join(
193
- self.get_default_no_polling_method_path(async_mode).split(".")[:-1]
194
- )
195
- default_no_polling_method = self.get_default_no_polling_method(async_mode)
196
- file_import.add_submodule_import(
197
- default_no_polling_method_import_path,
198
- default_no_polling_method,
199
- ImportType.AZURECORE,
200
- )
120
+ def get_no_polling_method(self, async_mode: bool) -> str:
121
+ return self.responses[0].get_no_polling_method(async_mode)
201
122
 
202
- base_polling_method_import_path = ".".join(
203
- self.get_base_polling_method_path(async_mode).split(".")[:-1]
204
- )
205
- base_polling_method = self.get_base_polling_method(async_mode)
206
- file_import.add_submodule_import(
207
- base_polling_method_import_path, base_polling_method, ImportType.AZURECORE
208
- )
209
- file_import.add_submodule_import("typing", "cast", ImportType.STDLIB)
123
+ def imports(
124
+ self, async_mode: bool, is_python3_file: bool, **kwargs: Any
125
+ ) -> FileImport:
126
+ file_import = super().imports(async_mode, is_python3_file, **kwargs)
210
127
  if async_mode:
211
128
  file_import.add_submodule_import(
212
- "typing", "Optional", ImportType.STDLIB, TypingSection.CONDITIONAL
213
- )
214
- if self.code_model.options["tracing"] and self.want_tracing:
215
- file_import.add_submodule_import(
216
- f"azure.core.tracing.decorator{'_async' if async_mode else ''}",
217
- f"distributed_trace{'_async' if async_mode else ''}",
129
+ f"azure.core.tracing.decorator_async",
130
+ f"distributed_trace_async",
218
131
  ImportType.AZURECORE,
219
132
  )
133
+ file_import.add_submodule_import(
134
+ "typing", "Union", ImportType.STDLIB, TypingSection.CONDITIONAL
135
+ )
136
+ file_import.add_submodule_import("typing", "cast", ImportType.STDLIB)
220
137
  return file_import
138
+
139
+
140
+ class LROOperation(LROOperationBase[LROResponse]):
141
+ ...