@autorest/python 5.15.0 → 5.18.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 (118) hide show
  1. package/ChangeLog.md +98 -4
  2. package/README.md +30 -4
  3. package/autorest/__init__.py +2 -3
  4. package/autorest/black/__init__.py +12 -5
  5. package/autorest/codegen/__init__.py +122 -211
  6. package/autorest/codegen/models/__init__.py +122 -78
  7. package/autorest/codegen/models/base_builder.py +70 -72
  8. package/autorest/codegen/models/base_model.py +7 -5
  9. package/autorest/codegen/models/{base_schema.py → base_type.py} +68 -45
  10. package/autorest/codegen/models/client.py +193 -40
  11. package/autorest/codegen/models/code_model.py +145 -245
  12. package/autorest/codegen/models/combined_type.py +107 -0
  13. package/autorest/codegen/models/constant_type.py +122 -0
  14. package/autorest/codegen/models/credential_types.py +224 -0
  15. package/autorest/codegen/models/dictionary_type.py +131 -0
  16. package/autorest/codegen/models/enum_type.py +195 -0
  17. package/autorest/codegen/models/imports.py +93 -41
  18. package/autorest/codegen/models/list_type.py +149 -0
  19. package/autorest/codegen/models/lro_operation.py +90 -133
  20. package/autorest/codegen/models/lro_paging_operation.py +28 -12
  21. package/autorest/codegen/models/model_type.py +262 -0
  22. package/autorest/codegen/models/operation.py +412 -259
  23. package/autorest/codegen/models/operation_group.py +80 -91
  24. package/autorest/codegen/models/paging_operation.py +101 -117
  25. package/autorest/codegen/models/parameter.py +302 -341
  26. package/autorest/codegen/models/parameter_list.py +373 -357
  27. package/autorest/codegen/models/primitive_types.py +544 -0
  28. package/autorest/codegen/models/property.py +136 -134
  29. package/autorest/codegen/models/request_builder.py +138 -86
  30. package/autorest/codegen/models/request_builder_parameter.py +122 -86
  31. package/autorest/codegen/models/response.py +325 -0
  32. package/autorest/codegen/models/utils.py +13 -17
  33. package/autorest/codegen/serializers/__init__.py +212 -112
  34. package/autorest/codegen/serializers/builder_serializer.py +931 -1040
  35. package/autorest/codegen/serializers/client_serializer.py +140 -84
  36. package/autorest/codegen/serializers/general_serializer.py +26 -50
  37. package/autorest/codegen/serializers/import_serializer.py +96 -31
  38. package/autorest/codegen/serializers/metadata_serializer.py +39 -79
  39. package/autorest/codegen/serializers/model_base_serializer.py +62 -34
  40. package/autorest/codegen/serializers/model_generic_serializer.py +9 -10
  41. package/autorest/codegen/serializers/model_init_serializer.py +4 -2
  42. package/autorest/codegen/serializers/model_python3_serializer.py +29 -22
  43. package/autorest/codegen/serializers/operation_groups_serializer.py +21 -19
  44. package/autorest/codegen/serializers/operations_init_serializer.py +23 -11
  45. package/autorest/codegen/serializers/parameter_serializer.py +174 -0
  46. package/autorest/codegen/serializers/patch_serializer.py +4 -1
  47. package/autorest/codegen/serializers/request_builders_serializer.py +57 -0
  48. package/autorest/codegen/serializers/utils.py +0 -126
  49. package/autorest/codegen/templates/MANIFEST.in.jinja2 +1 -0
  50. package/autorest/codegen/templates/{service_client.py.jinja2 → client.py.jinja2} +7 -7
  51. package/autorest/codegen/templates/config.py.jinja2 +13 -13
  52. package/autorest/codegen/templates/enum.py.jinja2 +4 -4
  53. package/autorest/codegen/templates/enum_container.py.jinja2 +1 -1
  54. package/autorest/codegen/templates/init.py.jinja2 +3 -3
  55. package/autorest/codegen/templates/lro_operation.py.jinja2 +6 -5
  56. package/autorest/codegen/templates/lro_paging_operation.py.jinja2 +6 -5
  57. package/autorest/codegen/templates/metadata.json.jinja2 +36 -35
  58. package/autorest/codegen/templates/model.py.jinja2 +23 -24
  59. package/autorest/codegen/templates/model_container.py.jinja2 +2 -1
  60. package/autorest/codegen/templates/model_init.py.jinja2 +3 -5
  61. package/autorest/codegen/templates/operation.py.jinja2 +10 -14
  62. package/autorest/codegen/templates/operation_group.py.jinja2 +9 -15
  63. package/autorest/codegen/templates/operation_groups_container.py.jinja2 +1 -1
  64. package/autorest/codegen/templates/operation_tools.jinja2 +8 -2
  65. package/autorest/codegen/templates/paging_operation.py.jinja2 +7 -8
  66. package/autorest/codegen/templates/request_builder.py.jinja2 +19 -10
  67. package/autorest/codegen/templates/setup.py.jinja2 +9 -3
  68. package/autorest/codegen/templates/vendor.py.jinja2 +1 -1
  69. package/autorest/jsonrpc/__init__.py +7 -12
  70. package/autorest/jsonrpc/localapi.py +4 -3
  71. package/autorest/jsonrpc/server.py +28 -9
  72. package/autorest/jsonrpc/stdstream.py +13 -6
  73. package/autorest/m2r/__init__.py +5 -8
  74. package/autorest/m4reformatter/__init__.py +1126 -0
  75. package/autorest/multiapi/__init__.py +24 -14
  76. package/autorest/multiapi/models/client.py +21 -11
  77. package/autorest/multiapi/models/code_model.py +23 -10
  78. package/autorest/multiapi/models/config.py +4 -1
  79. package/autorest/multiapi/models/constant_global_parameter.py +1 -0
  80. package/autorest/multiapi/models/global_parameter.py +2 -1
  81. package/autorest/multiapi/models/global_parameters.py +14 -8
  82. package/autorest/multiapi/models/imports.py +24 -17
  83. package/autorest/multiapi/models/mixin_operation.py +5 -5
  84. package/autorest/multiapi/models/operation_group.py +2 -1
  85. package/autorest/multiapi/models/operation_mixin_group.py +21 -10
  86. package/autorest/multiapi/serializers/__init__.py +20 -25
  87. package/autorest/multiapi/serializers/import_serializer.py +47 -17
  88. package/autorest/multiapi/serializers/multiapi_serializer.py +17 -17
  89. package/autorest/multiapi/templates/multiapi_config.py.jinja2 +3 -3
  90. package/autorest/multiapi/templates/multiapi_init.py.jinja2 +2 -2
  91. package/autorest/multiapi/templates/multiapi_operations_mixin.py.jinja2 +4 -4
  92. package/autorest/multiapi/templates/multiapi_service_client.py.jinja2 +9 -9
  93. package/autorest/multiapi/utils.py +3 -3
  94. package/autorest/postprocess/__init__.py +202 -0
  95. package/autorest/postprocess/get_all.py +19 -0
  96. package/autorest/postprocess/venvtools.py +73 -0
  97. package/autorest/preprocess/__init__.py +210 -0
  98. package/autorest/preprocess/helpers.py +54 -0
  99. package/autorest/{namer → preprocess}/python_mappings.py +25 -32
  100. package/package.json +3 -3
  101. package/run-python3.js +2 -3
  102. package/venvtools.py +1 -1
  103. package/autorest/codegen/models/constant_schema.py +0 -101
  104. package/autorest/codegen/models/credential_model.py +0 -47
  105. package/autorest/codegen/models/credential_schema.py +0 -91
  106. package/autorest/codegen/models/credential_schema_policy.py +0 -77
  107. package/autorest/codegen/models/dictionary_schema.py +0 -103
  108. package/autorest/codegen/models/enum_schema.py +0 -215
  109. package/autorest/codegen/models/list_schema.py +0 -123
  110. package/autorest/codegen/models/object_schema.py +0 -253
  111. package/autorest/codegen/models/primitive_schemas.py +0 -466
  112. package/autorest/codegen/models/request_builder_parameter_list.py +0 -280
  113. package/autorest/codegen/models/rest.py +0 -42
  114. package/autorest/codegen/models/schema_request.py +0 -45
  115. package/autorest/codegen/models/schema_response.py +0 -136
  116. package/autorest/codegen/serializers/rest_serializer.py +0 -57
  117. package/autorest/namer/__init__.py +0 -25
  118. package/autorest/namer/name_converter.py +0 -412
@@ -3,25 +3,16 @@
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 cast, List, Dict, Optional, Any, Set
6
+ from typing import List, Dict, Optional, Any, Set, Union
8
7
 
9
- from .base_schema import BaseSchema
10
- from .enum_schema import EnumSchema
11
- from .object_schema import ObjectSchema
8
+ from .base_type import BaseType
9
+ from .enum_type import EnumType
10
+ from .model_type import ModelType
12
11
  from .operation_group import OperationGroup
13
- from .operation import Operation
14
- from .lro_operation import LROOperation
15
- from .paging_operation import PagingOperation
12
+ from .client import Client, Config
13
+ from .request_builder import OverloadedRequestBuilder, RequestBuilder
16
14
  from .parameter import Parameter
17
- from .client import Client
18
- from .parameter_list import GlobalParameterList
19
- from .property import Property
20
- from .request_builder import RequestBuilder
21
- from .rest import Rest
22
- from .credential_model import CredentialModel
23
15
 
24
- _LOGGER = logging.getLogger(__name__)
25
16
 
26
17
  class CodeModel: # pylint: disable=too-many-instance-attributes, too-many-public-methods
27
18
  """Holds all of the information we have parsed out of the yaml file. The CodeModel is what gets
@@ -34,82 +25,117 @@ class CodeModel: # pylint: disable=too-many-instance-attributes, too-many-publi
34
25
  :param str description: The description of the client
35
26
  :param str namespace: The namespace of our module
36
27
  :param schemas: The list of schemas we are going to serialize in the models files. Maps their yaml
37
- id to our created ObjectSchema.
38
- :type schemas: dict[int, ~autorest.models.ObjectSchema]
28
+ id to our created ModelType.
29
+ :type schemas: dict[int, ~autorest.models.ModelType]
39
30
  :param sorted_schemas: Our schemas in order by inheritance and alphabet
40
- :type sorted_schemas: list[~autorest.models.ObjectSchema]
41
- :param enums: The enums, if any, we are going to serialize. Maps their yaml id to our created EnumSchema.
42
- :type enums: Dict[int, ~autorest.models.EnumSchema]
31
+ :type sorted_schemas: list[~autorest.models.ModelType]
32
+ :param enums: The enums, if any, we are going to serialize. Maps their yaml id to our created EnumType.
33
+ :type enums: Dict[int, ~autorest.models.EnumType]
43
34
  :param primitives: List of schemas we've created that are not EnumSchemas or ObjectSchemas. Maps their
44
35
  yaml id to our created schemas.
45
- :type primitives: Dict[int, ~autorest.models.BaseSchema]
36
+ :type primitives: Dict[int, ~autorest.models.BaseType]
46
37
  :param operation_groups: The operation groups we are going to serialize
47
38
  :type operation_groups: list[~autorest.models.OperationGroup]
48
39
  :param package_dependency: All the dependencies needed in setup.py
49
40
  :type package_dependency: Dict[str, str]
50
- :param credential_model: The class contains all the credential info
51
- :type credential_model: CredentialMode
52
41
  """
53
42
 
54
43
  def __init__(
55
44
  self,
45
+ yaml_data: Dict[str, Any],
56
46
  options: Dict[str, Any],
57
47
  ) -> None:
58
- self.send_request_name = "send_request" if options['show_send_request'] else "_send_request"
59
- self.rest_layer_name = "rest" if options["builders_visibility"] == "public" else "_rest"
48
+ self.yaml_data = yaml_data
60
49
  self.options = options
61
- self.module_name: str = ""
62
- self.class_name: str = ""
63
- self.description: str = ""
64
- self.namespace: str = ""
65
- self.namespace_path: str = ""
66
- self.schemas: Dict[int, ObjectSchema] = {}
67
- self.sorted_schemas: List[ObjectSchema] = []
68
- self.enums: Dict[int, EnumSchema] = {}
69
- self.primitives: Dict[int, BaseSchema] = {}
50
+ self.types_map: Dict[int, BaseType] = {} # map yaml id to schema
70
51
  self.operation_groups: List[OperationGroup] = []
71
- params = GlobalParameterList(self)
72
- params.code_model = self
73
- self.service_client: Client = Client(self, params)
74
- self._rest: Optional[Rest] = None
75
- self.request_builder_ids: Dict[int, RequestBuilder] = {}
52
+ self._model_types: List[ModelType] = []
53
+ self._client: Optional[Client] = None
54
+ self._config: Optional[Config] = None
55
+ self.request_builders: List[
56
+ Union[RequestBuilder, OverloadedRequestBuilder]
57
+ ] = []
76
58
  self.package_dependency: Dict[str, str] = {}
77
- self._credential_model: Optional[CredentialModel] = None
59
+ self.namespace: str = yaml_data["client"]["namespace"].lower()
60
+ self.module_name: str = self.yaml_data["client"]["moduleName"]
61
+
62
+ def lookup_type(self, schema_id: int) -> BaseType:
63
+ """Looks to see if the schema has already been created.
64
+
65
+ :param int schema_id: The yaml id of the schema
66
+ :return: If created, we return the created schema, otherwise, we throw.
67
+ :rtype: ~autorest.models.BaseType
68
+ :raises: KeyError if schema is not found
69
+ """
70
+ try:
71
+ return next(type for id, type in self.types_map.items() if id == schema_id)
72
+ except StopIteration:
73
+ raise KeyError(f"Couldn't find schema with id {schema_id}")
78
74
 
79
75
  @property
80
- def global_parameters(self) -> GlobalParameterList:
81
- return self.service_client.parameters
76
+ def credential(self) -> Optional[Parameter]:
77
+ """The credential param, if one exists"""
78
+ return self.client.parameters.credential
79
+
80
+ @property
81
+ def client(self) -> Client:
82
+ if not self._client:
83
+ raise ValueError("You haven't linked the client yet")
84
+ return self._client
85
+
86
+ @client.setter
87
+ def client(self, val: Client) -> None:
88
+ self._client = val
82
89
 
83
- @global_parameters.setter
84
- def global_parameters(self, val: GlobalParameterList) -> None:
85
- self.service_client.parameters = val
90
+ @property
91
+ def config(self) -> Config:
92
+ if not self._config:
93
+ raise ValueError("You haven't linked the config yet")
94
+ return self._config
95
+
96
+ @config.setter
97
+ def config(self, val: Config) -> None:
98
+ self._config = val
99
+
100
+ def lookup_request_builder(
101
+ self, request_builder_id: int
102
+ ) -> Union[RequestBuilder, OverloadedRequestBuilder]:
103
+ """Find the request builder based off of id"""
104
+ try:
105
+ return next(
106
+ rb
107
+ for rb in self.request_builders
108
+ if id(rb.yaml_data) == request_builder_id
109
+ )
110
+ except StopIteration:
111
+ raise KeyError(f"No request builder with id {request_builder_id} found.")
86
112
 
87
113
  @property
88
- def rest(self) -> Rest:
89
- if not self._rest:
90
- raise ValueError("rest is None. Can not call it, you first have to set it.")
91
- return self._rest
114
+ def model_types(self) -> List[ModelType]:
115
+ """All of the model types in this class"""
116
+ if not self._model_types:
117
+ self._model_types = [
118
+ t for t in self.types_map.values() if isinstance(t, ModelType)
119
+ ]
120
+ return self._model_types
92
121
 
93
- @rest.setter
94
- def rest(self, p: Rest) -> None:
95
- self._rest = p
122
+ @model_types.setter
123
+ def model_types(self, val: List[ModelType]) -> None:
124
+ self._model_types = val
96
125
 
97
- def lookup_schema(self, schema_id: int) -> BaseSchema:
98
- """Looks to see if the schema has already been created.
126
+ @property
127
+ def public_model_types(self) -> List[ModelType]:
128
+ return [m for m in self.model_types if m.is_public]
99
129
 
100
- :param int schema_id: The yaml id of the schema
101
- :return: If created, we return the created schema, otherwise, we throw.
102
- :rtype: ~autorest.models.BaseSchema
103
- :raises: KeyError if schema is not found
104
- """
105
- for attr in [self.schemas, self.enums, self.primitives]:
106
- for elt_key, elt_value in attr.items(): # type: ignore
107
- if schema_id == elt_key:
108
- return elt_value
109
- raise KeyError("Didn't find it!!!!!")
130
+ @property
131
+ def enums(self) -> List[EnumType]:
132
+ """All of the enums"""
133
+ return [t for t in self.types_map.values() if isinstance(t, EnumType)]
110
134
 
111
135
  @staticmethod
112
- def _sort_schemas_helper(current, seen_schema_names, seen_schema_yaml_ids):
136
+ def _sort_model_types_helper(
137
+ current: ModelType, seen_schema_names: Set[str], seen_schema_yaml_ids: Set[int]
138
+ ):
113
139
  if current.id in seen_schema_yaml_ids:
114
140
  return []
115
141
  if current.name in seen_schema_names:
@@ -117,20 +143,23 @@ class CodeModel: # pylint: disable=too-many-instance-attributes, too-many-publi
117
143
  f"We have already generated a schema with name {current.name}"
118
144
  )
119
145
  ancestors = [current]
120
- if current.base_models:
121
- for base_model in current.base_models:
122
- parent = cast(ObjectSchema, base_model)
146
+ if current.parents:
147
+ for parent in current.parents:
123
148
  if parent.id in seen_schema_yaml_ids:
124
149
  continue
125
150
  seen_schema_names.add(current.name)
126
151
  seen_schema_yaml_ids.add(current.id)
127
- ancestors = CodeModel._sort_schemas_helper(parent, seen_schema_names, seen_schema_yaml_ids) + ancestors
152
+ ancestors = (
153
+ CodeModel._sort_model_types_helper(
154
+ parent, seen_schema_names, seen_schema_yaml_ids
155
+ )
156
+ + ancestors
157
+ )
128
158
  seen_schema_names.add(current.name)
129
159
  seen_schema_yaml_ids.add(current.id)
130
160
  return ancestors
131
161
 
132
-
133
- def sort_schemas(self) -> None:
162
+ def sort_model_types(self) -> None:
134
163
  """Sorts the final object schemas by inheritance and by alphabetical order.
135
164
 
136
165
  :return: None
@@ -138,29 +167,14 @@ class CodeModel: # pylint: disable=too-many-instance-attributes, too-many-publi
138
167
  """
139
168
  seen_schema_names: Set[str] = set()
140
169
  seen_schema_yaml_ids: Set[int] = set()
141
- sorted_schemas: List[ObjectSchema] = []
142
- for schema in sorted(self.schemas.values(), key=lambda x: x.name.lower()):
143
- sorted_schemas.extend(CodeModel._sort_schemas_helper(schema, seen_schema_names, seen_schema_yaml_ids))
144
- self.sorted_schemas = sorted_schemas
145
-
146
- def setup_client_input_parameters(self, yaml_data: Dict[str, Any]):
147
- dollar_host = [
148
- parameter for parameter in self.global_parameters
149
- if parameter.rest_api_name == "$host"
150
- ]
151
- if not dollar_host:
152
- # We don't want to support multi-api customurl YET (will see if that goes well....)
153
- # So far now, let's get the first one in the first operation
154
- # UGLY as hell.....
155
- if yaml_data.get("operationGroups"):
156
- first_req_of_first_op_of_first_grp = yaml_data["operationGroups"][0]["operations"][0]["requests"][0]
157
- self.service_client.parameterized_host_template = (
158
- first_req_of_first_op_of_first_grp["protocol"]["http"]["uri"]
170
+ sorted_object_schemas: List[ModelType] = []
171
+ for schema in sorted(self.model_types, key=lambda x: x.name.lower()):
172
+ sorted_object_schemas.extend(
173
+ CodeModel._sort_model_types_helper(
174
+ schema, seen_schema_names, seen_schema_yaml_ids
159
175
  )
160
- else:
161
- for host in dollar_host:
162
- self.global_parameters.remove(host)
163
- self.service_client.parameters.add_host(dollar_host[0].yaml_data["clientDefaultValue"])
176
+ )
177
+ self.model_types = sorted_object_schemas
164
178
 
165
179
  def format_lro_operations(self) -> None:
166
180
  """Adds operations and attributes needed for LROs.
@@ -171,188 +185,68 @@ class CodeModel: # pylint: disable=too-many-instance-attributes, too-many-publi
171
185
  i = 0
172
186
  while i < len(operation_group.operations):
173
187
  operation = operation_group.operations[i]
174
- if isinstance(operation, LROOperation):
175
- operation_group.operations.insert(i, operation.initial_operation)
188
+ if operation.operation_type in ("lro", "lropaging"):
189
+ operation_group.operations.insert(i, operation.initial_operation) # type: ignore
176
190
  i += 1
177
191
  i += 1
178
192
 
179
- def remove_next_operation(self) -> None:
180
- """Linking paging operations together.
181
- """
182
- def _lookup_operation(yaml_id: int) -> Operation:
183
- for operation_group in self.operation_groups:
184
- for operation in operation_group.operations:
185
- if operation.id == yaml_id:
186
- return operation
187
- raise KeyError("Didn't find it!!!!!")
188
-
189
- for operation_group in self.operation_groups:
190
- next_operations = []
191
- for operation in operation_group.operations:
192
- # when we add in "LRO" functions we don't include yaml_data, so yaml_data can be empty in these cases
193
- next_link_yaml = None
194
- if operation.yaml_data and operation.yaml_data['language']['python'].get('paging'):
195
- next_link_yaml = operation.yaml_data['language']['python']['paging'].get('nextLinkOperation')
196
- if isinstance(operation, PagingOperation) and next_link_yaml:
197
- next_operation = _lookup_operation(id(next_link_yaml))
198
- operation.next_operation = next_operation
199
- next_operations.append(next_operation)
200
-
201
- operation_group.operations = [
202
- operation for operation in operation_group.operations if operation not in next_operations
203
- ]
204
-
205
- @property
206
- def has_schemas(self):
207
- return self.schemas or self.enums
208
-
209
- @property
210
- def credential_model(self) -> CredentialModel:
211
- if not self._credential_model:
212
- raise ValueError("You want to find the Credential Model, but have not given a value")
213
- return self._credential_model
214
-
215
- @credential_model.setter
216
- def credential_model(self, val: CredentialModel) -> None:
217
- self._credential_model = val
218
-
219
- @staticmethod
220
- def _add_properties_from_inheritance_helper(schema, properties) -> List[Property]:
221
- if not schema.base_models:
222
- return properties
223
- if schema.base_models:
224
- for base_model in schema.base_models:
225
- parent = cast(ObjectSchema, base_model)
226
- # need to make sure that the properties we choose from our parent also don't contain
227
- # any of our own properties
228
- schema_property_names = set([p.name for p in properties] + [p.name for p in schema.properties])
229
- chosen_parent_properties = [
230
- p for p in parent.properties
231
- if p.name not in schema_property_names
232
- ]
233
- properties = (
234
- CodeModel._add_properties_from_inheritance_helper(parent, chosen_parent_properties) +
235
- properties
236
- )
237
-
238
- return properties
239
-
240
193
  @property
241
194
  def operations_folder_name(self) -> str:
195
+ """Get the name of the operations folder that holds operations."""
242
196
  name = "operations"
243
197
  if self.options["version_tolerant"] and not any(
244
- og for og in self.operation_groups if not og.is_empty_operation_group
198
+ og for og in self.operation_groups if not og.is_mixin
245
199
  ):
246
200
  name = f"_{name}"
247
201
  return name
248
202
 
249
- def _add_properties_from_inheritance(self) -> None:
250
- """Adds properties from base classes to schemas with parents.
251
-
252
- :return: None
253
- :rtype: None
254
- """
255
- for schema in self.schemas.values():
256
- schema.properties = CodeModel._add_properties_from_inheritance_helper(schema, schema.properties)
257
-
258
- @staticmethod
259
- def _add_exceptions_from_inheritance_helper(schema) -> bool:
260
- if schema.is_exception:
261
- return True
262
- parent_is_exception: List[bool] = []
263
- for base_model in schema.base_models:
264
- parent = cast(ObjectSchema, base_model)
265
- parent_is_exception.append(CodeModel._add_exceptions_from_inheritance_helper(parent))
266
- return any(parent_is_exception)
267
-
268
- def _add_exceptions_from_inheritance(self) -> None:
269
- """Sets a class as an exception if it's parent is an exception.
270
-
271
- :return: None
272
- :rtype: None
273
- """
274
- for schema in self.schemas.values():
275
- schema.is_exception = CodeModel._add_exceptions_from_inheritance_helper(schema)
276
-
277
- def add_inheritance_to_models(self) -> None:
278
- """Adds base classes and properties from base classes to schemas with parents.
279
-
280
- :return: None
281
- :rtype: None
282
- """
283
- for schema in self.schemas.values():
284
- if schema.base_models:
285
- # right now, the base model property just holds the name of the parent class
286
- schema.base_models = [b for b in self.schemas.values() if b.id in schema.base_models]
287
- self._add_properties_from_inheritance()
288
- self._add_exceptions_from_inheritance()
289
-
290
- def _populate_target_property(self, parameter: Parameter) -> None:
291
- for obj in self.schemas.values():
292
- for prop in obj.properties:
293
- if prop.id == parameter.target_property_name:
294
- parameter.target_property_name = prop.name
295
- return
296
- raise KeyError("Didn't find the target property")
297
-
298
- def generate_single_parameter_from_multiple_content_types_operation(self) -> None:
299
- for operation_group in self.operation_groups:
300
- for operation in operation_group.operations:
301
- if operation.multiple_content_type_parameters:
302
- operation.convert_multiple_content_type_parameters()
303
-
304
203
  def need_vendored_code(self, async_mode: bool) -> bool:
204
+ """Whether we need to vendor code in the _vendor.py file for this SDK"""
305
205
  if async_mode:
306
206
  return self.need_mixin_abc
307
- return self.need_request_converter or self.need_format_url or self.need_mixin_abc
207
+ return (
208
+ self.need_request_converter or self.need_format_url or self.need_mixin_abc
209
+ )
308
210
 
309
211
  @property
310
212
  def need_request_converter(self) -> bool:
213
+ """
214
+ Whether we need to convert our created azure.core.rest.HttpRequests to
215
+ azure.core.pipeline.transport.HttpRequests
216
+ """
311
217
  return (
312
- self.options["show_operations"] and
313
- bool(self.rest.request_builders) and
314
- not self.options["version_tolerant"]
218
+ self.options["show_operations"]
219
+ and bool(self.request_builders)
220
+ and not self.options["version_tolerant"]
315
221
  )
316
222
 
317
223
  @property
318
224
  def need_format_url(self) -> bool:
319
- return any(rq for rq in self.rest.request_builders if rq.parameters.path)
225
+ """Whether we need to format urls. If so, we need to vendor core."""
226
+ return any(rq for rq in self.request_builders if rq.parameters.path)
320
227
 
321
228
  @property
322
229
  def need_mixin_abc(self) -> bool:
323
- return any(o for o in self.operation_groups if o.is_empty_operation_group and self.options["python3_only"])
230
+ """Do we want a mixin ABC class for typing purposes?"""
231
+ return any(
232
+ o
233
+ for o in self.operation_groups
234
+ if o.is_mixin and self.options["python3_only"]
235
+ )
324
236
 
325
237
  @property
326
238
  def has_lro_operations(self) -> bool:
327
- return any([
328
- isinstance(operation, LROOperation)
329
- for operation_group in self.operation_groups
330
- for operation in operation_group.operations
331
- ])
332
-
333
- def _lookup_request_builder(self, schema_id: int) -> RequestBuilder:
334
- """Looks to see if the schema has already been created.
335
-
336
- :param int schema_id: The yaml id of the schema
337
- :return: If created, we return the created schema, otherwise, we throw.
338
- :rtype: ~autorest.models.RequestBuilder
339
- :raises: KeyError if schema is not found
340
- """
341
- for elt_key, elt_value in self.request_builder_ids.items(): # type: ignore
342
- if schema_id == elt_key:
343
- return elt_value
344
- raise KeyError("Didn't find it!!!!!")
345
-
346
- def link_operation_to_request_builder(self) -> None:
347
- for operation_group in self.operation_groups:
348
- for operation in operation_group.operations:
349
- request_builder = self._lookup_request_builder(id(operation.yaml_data))
350
- if isinstance(operation, LROOperation):
351
- request_builder.name = request_builder.name + "_initial"
352
- operation.request_builder = request_builder
353
- operation.link_body_kwargs_to_body_params()
239
+ """Are there any LRO operations in this SDK?"""
240
+ return any(
241
+ [
242
+ operation.operation_type in ("lro", "lropaging")
243
+ for operation_group in self.operation_groups
244
+ for operation in operation_group.operations
245
+ ]
246
+ )
354
247
 
355
248
  def get_models_filename(self, is_python3_file: bool) -> str:
249
+ """Get the names of the model file(s)"""
356
250
  if (
357
251
  self.options["version_tolerant"] or self.options["low_level_client"]
358
252
  ) and self.options["python3_only"]:
@@ -363,6 +257,12 @@ class CodeModel: # pylint: disable=too-many-instance-attributes, too-many-publi
363
257
 
364
258
  @property
365
259
  def enums_filename(self) -> str:
260
+ """The name of the enums file"""
366
261
  if self.options["version_tolerant"] or self.options["low_level_client"]:
367
262
  return "_enums"
368
263
  return f"_{self.module_name}_enums"
264
+
265
+ @property
266
+ def rest_layer_name(self) -> str:
267
+ """If we have a separate rest layer, what is its name?"""
268
+ return "rest" if self.options["builders_visibility"] == "public" else "_rest"
@@ -0,0 +1,107 @@
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, Optional, TYPE_CHECKING
7
+
8
+ from autorest.codegen.models.imports import FileImport, ImportType
9
+ from .base_type import BaseType
10
+
11
+ if TYPE_CHECKING:
12
+ from .code_model import CodeModel
13
+
14
+
15
+ class CombinedType(BaseType):
16
+ """A type that consists of multiple different types.
17
+
18
+ Used by body parameters that have multiple types, i.e. one that can be
19
+ a stream body or a JSON body.
20
+ """
21
+
22
+ def __init__(
23
+ self, yaml_data: Dict[str, Any], code_model: "CodeModel", types: List[BaseType]
24
+ ) -> None:
25
+ super().__init__(yaml_data, code_model)
26
+ self.types = types # the types that this type is combining
27
+
28
+ @property
29
+ def serialization_type(self) -> str:
30
+ """The tag recognized by 'msrest' as a serialization/deserialization.
31
+
32
+ 'str', 'int', 'float', 'bool' or
33
+ https://github.com/Azure/msrest-for-python/blob/b505e3627b547bd8fdc38327e86c70bdb16df061/msrest/serialization.py#L407-L416
34
+
35
+ or the object schema name (e.g. DotSalmon).
36
+
37
+ If list: '[str]'
38
+ If dict: '{str}'
39
+ """
40
+ ...
41
+
42
+ @property
43
+ def client_default_value(self) -> Any:
44
+ return self.yaml_data.get("clientDefaultValue")
45
+
46
+ def description(
47
+ self, *, is_operation_file: bool # pylint: disable=unused-argument
48
+ ) -> str:
49
+ if len(self.types) == 2:
50
+ return (
51
+ f"Is either a {self.types[0].type} type or a {self.types[1].type} type."
52
+ )
53
+ return (
54
+ f"Is one of the following types: {', '.join([t.type for t in self.types])}"
55
+ )
56
+
57
+ def docstring_text(self, **kwargs: Any) -> str:
58
+ return " or ".join(t.docstring_text(**kwargs) for t in self.types)
59
+
60
+ def docstring_type(self, **kwargs: Any) -> str:
61
+ return " or ".join(t.docstring_type(**kwargs) for t in self.types)
62
+
63
+ def type_annotation(self, **kwargs: Any) -> str:
64
+ """The python type used for type annotation
65
+
66
+ Special case for enum, for instance: Union[str, "EnumName"]
67
+ """
68
+ kwargs["is_operation_file"] = True
69
+ return (
70
+ f'Union[{", ".join(type.type_annotation(**kwargs) for type in self.types)}]'
71
+ )
72
+
73
+ def get_json_template_representation(
74
+ self,
75
+ *,
76
+ optional: bool = True,
77
+ client_default_value_declaration: Optional[str] = None,
78
+ description: Optional[str] = None,
79
+ ) -> Any:
80
+ """Template of what this schema would look like as JSON input"""
81
+ raise ValueError(
82
+ "You shouldn't get a JSON template representation of multiple types"
83
+ )
84
+
85
+ @property
86
+ def instance_check_template(self) -> str:
87
+ """Template of what an instance check of a variable for this type would look like"""
88
+ raise ValueError("You shouldn't do instance checks on a multiple type")
89
+
90
+ def imports(self, **kwargs: Any) -> FileImport:
91
+ file_import = FileImport()
92
+ for type in self.types:
93
+ file_import.merge(type.imports(**kwargs))
94
+ file_import.add_submodule_import("typing", "Union", ImportType.STDLIB)
95
+ return file_import
96
+
97
+ @classmethod
98
+ def from_yaml(
99
+ cls, yaml_data: Dict[str, Any], code_model: "CodeModel"
100
+ ) -> "BaseType":
101
+ from . import build_type
102
+
103
+ return cls(
104
+ yaml_data,
105
+ code_model,
106
+ [build_type(t, code_model) for t in yaml_data["types"]],
107
+ )