@autorest/python 5.14.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 (120) hide show
  1. package/ChangeLog.md +91 -2
  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 +130 -179
  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} +62 -49
  10. package/autorest/codegen/models/client.py +195 -36
  11. package/autorest/codegen/models/code_model.py +165 -299
  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 +116 -0
  16. package/autorest/codegen/models/enum_type.py +195 -0
  17. package/autorest/codegen/models/imports.py +95 -41
  18. package/autorest/codegen/models/list_type.py +134 -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 +239 -0
  22. package/autorest/codegen/models/operation.py +415 -241
  23. package/autorest/codegen/models/operation_group.py +82 -88
  24. package/autorest/codegen/models/paging_operation.py +101 -117
  25. package/autorest/codegen/models/parameter.py +307 -322
  26. package/autorest/codegen/models/parameter_list.py +366 -357
  27. package/autorest/codegen/models/primitive_types.py +544 -0
  28. package/autorest/codegen/models/property.py +122 -134
  29. package/autorest/codegen/models/request_builder.py +138 -86
  30. package/autorest/codegen/models/request_builder_parameter.py +122 -79
  31. package/autorest/codegen/models/response.py +325 -0
  32. package/autorest/codegen/models/utils.py +17 -1
  33. package/autorest/codegen/serializers/__init__.py +242 -118
  34. package/autorest/codegen/serializers/builder_serializer.py +863 -1027
  35. package/autorest/codegen/serializers/client_serializer.py +148 -82
  36. package/autorest/codegen/serializers/general_serializer.py +44 -47
  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 +65 -29
  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 -18
  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 +14 -2
  47. package/autorest/codegen/serializers/request_builders_serializer.py +57 -0
  48. package/autorest/codegen/serializers/utils.py +0 -103
  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 -2
  54. package/autorest/codegen/templates/init.py.jinja2 +9 -6
  55. package/autorest/codegen/templates/keywords.jinja2 +14 -1
  56. package/autorest/codegen/templates/lro_operation.py.jinja2 +6 -5
  57. package/autorest/codegen/templates/lro_paging_operation.py.jinja2 +6 -5
  58. package/autorest/codegen/templates/metadata.json.jinja2 +36 -35
  59. package/autorest/codegen/templates/model.py.jinja2 +23 -29
  60. package/autorest/codegen/templates/model_container.py.jinja2 +2 -1
  61. package/autorest/codegen/templates/model_init.py.jinja2 +9 -8
  62. package/autorest/codegen/templates/operation.py.jinja2 +10 -15
  63. package/autorest/codegen/templates/operation_group.py.jinja2 +14 -13
  64. package/autorest/codegen/templates/operation_groups_container.py.jinja2 +1 -2
  65. package/autorest/codegen/templates/operation_tools.jinja2 +8 -2
  66. package/autorest/codegen/templates/operations_folder_init.py.jinja2 +4 -0
  67. package/autorest/codegen/templates/paging_operation.py.jinja2 +7 -8
  68. package/autorest/codegen/templates/patch.py.jinja2 +18 -29
  69. package/autorest/codegen/templates/request_builder.py.jinja2 +20 -13
  70. package/autorest/codegen/templates/setup.py.jinja2 +9 -3
  71. package/autorest/codegen/templates/vendor.py.jinja2 +12 -2
  72. package/autorest/jsonrpc/__init__.py +7 -12
  73. package/autorest/jsonrpc/localapi.py +4 -3
  74. package/autorest/jsonrpc/server.py +28 -9
  75. package/autorest/jsonrpc/stdstream.py +13 -6
  76. package/autorest/m2r/__init__.py +5 -8
  77. package/autorest/m4reformatter/__init__.py +1108 -0
  78. package/autorest/multiapi/__init__.py +24 -14
  79. package/autorest/multiapi/models/client.py +21 -11
  80. package/autorest/multiapi/models/code_model.py +23 -10
  81. package/autorest/multiapi/models/config.py +4 -1
  82. package/autorest/multiapi/models/constant_global_parameter.py +1 -0
  83. package/autorest/multiapi/models/global_parameter.py +2 -1
  84. package/autorest/multiapi/models/global_parameters.py +14 -8
  85. package/autorest/multiapi/models/imports.py +35 -18
  86. package/autorest/multiapi/models/mixin_operation.py +5 -5
  87. package/autorest/multiapi/models/operation_group.py +2 -1
  88. package/autorest/multiapi/models/operation_mixin_group.py +21 -10
  89. package/autorest/multiapi/serializers/__init__.py +20 -25
  90. package/autorest/multiapi/serializers/import_serializer.py +47 -15
  91. package/autorest/multiapi/serializers/multiapi_serializer.py +17 -17
  92. package/autorest/multiapi/templates/multiapi_config.py.jinja2 +3 -3
  93. package/autorest/multiapi/templates/multiapi_init.py.jinja2 +2 -2
  94. package/autorest/multiapi/templates/multiapi_operations_mixin.py.jinja2 +4 -4
  95. package/autorest/multiapi/templates/multiapi_service_client.py.jinja2 +9 -9
  96. package/autorest/multiapi/utils.py +3 -3
  97. package/autorest/postprocess/__init__.py +202 -0
  98. package/autorest/postprocess/get_all.py +19 -0
  99. package/autorest/postprocess/venvtools.py +73 -0
  100. package/autorest/preprocess/__init__.py +209 -0
  101. package/autorest/preprocess/helpers.py +54 -0
  102. package/autorest/{namer → preprocess}/python_mappings.py +25 -32
  103. package/package.json +3 -3
  104. package/run-python3.js +2 -3
  105. package/venvtools.py +1 -1
  106. package/autorest/codegen/models/constant_schema.py +0 -97
  107. package/autorest/codegen/models/credential_schema.py +0 -90
  108. package/autorest/codegen/models/credential_schema_policy.py +0 -77
  109. package/autorest/codegen/models/dictionary_schema.py +0 -103
  110. package/autorest/codegen/models/enum_schema.py +0 -246
  111. package/autorest/codegen/models/list_schema.py +0 -113
  112. package/autorest/codegen/models/object_schema.py +0 -249
  113. package/autorest/codegen/models/primitive_schemas.py +0 -476
  114. package/autorest/codegen/models/request_builder_parameter_list.py +0 -280
  115. package/autorest/codegen/models/rest.py +0 -42
  116. package/autorest/codegen/models/schema_request.py +0 -45
  117. package/autorest/codegen/models/schema_response.py +0 -123
  118. package/autorest/codegen/serializers/rest_serializer.py +0 -57
  119. package/autorest/namer/__init__.py +0 -25
  120. package/autorest/namer/name_converter.py +0 -412
@@ -3,32 +3,17 @@
3
3
  # Licensed under the MIT License. See License.txt in the project root for
4
4
  # license information.
5
5
  # --------------------------------------------------------------------------
6
- from itertools import chain
7
- import logging
8
- from typing import cast, List, Dict, Optional, Any, Set, Type
6
+ from typing import List, Dict, Optional, Any, Set, Union
9
7
 
10
- from .base_schema import BaseSchema
11
- from .credential_schema_policy import (
12
- ARMChallengeAuthenticationPolicy, BearerTokenCredentialPolicy, CredentialSchemaPolicy
13
- )
14
- from .enum_schema import EnumSchema
15
- from .object_schema import ObjectSchema
8
+ from .base_type import BaseType
9
+ from .enum_type import EnumType
10
+ from .model_type import ModelType
16
11
  from .operation_group import OperationGroup
17
- from .operation import Operation
18
- from .lro_operation import LROOperation
19
- from .paging_operation import PagingOperation
12
+ from .client import Client, Config
13
+ from .request_builder import OverloadedRequestBuilder, RequestBuilder
20
14
  from .parameter import Parameter
21
- from .client import Client
22
- from .parameter_list import GlobalParameterList
23
- from .schema_response import SchemaResponse
24
- from .property import Property
25
- from .primitive_schemas import IOSchema
26
- from .request_builder import RequestBuilder
27
- from .rest import Rest
28
15
 
29
16
 
30
- _LOGGER = logging.getLogger(__name__)
31
-
32
17
  class CodeModel: # pylint: disable=too-many-instance-attributes, too-many-public-methods
33
18
  """Holds all of the information we have parsed out of the yaml file. The CodeModel is what gets
34
19
  serialized by the serializers.
@@ -40,15 +25,15 @@ class CodeModel: # pylint: disable=too-many-instance-attributes, too-many-publi
40
25
  :param str description: The description of the client
41
26
  :param str namespace: The namespace of our module
42
27
  :param schemas: The list of schemas we are going to serialize in the models files. Maps their yaml
43
- id to our created ObjectSchema.
44
- :type schemas: dict[int, ~autorest.models.ObjectSchema]
28
+ id to our created ModelType.
29
+ :type schemas: dict[int, ~autorest.models.ModelType]
45
30
  :param sorted_schemas: Our schemas in order by inheritance and alphabet
46
- :type sorted_schemas: list[~autorest.models.ObjectSchema]
47
- :param enums: The enums, if any, we are going to serialize. Maps their yaml id to our created EnumSchema.
48
- :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]
49
34
  :param primitives: List of schemas we've created that are not EnumSchemas or ObjectSchemas. Maps their
50
35
  yaml id to our created schemas.
51
- :type primitives: Dict[int, ~autorest.models.BaseSchema]
36
+ :type primitives: Dict[int, ~autorest.models.BaseType]
52
37
  :param operation_groups: The operation groups we are going to serialize
53
38
  :type operation_groups: list[~autorest.models.OperationGroup]
54
39
  :param package_dependency: All the dependencies needed in setup.py
@@ -57,63 +42,100 @@ class CodeModel: # pylint: disable=too-many-instance-attributes, too-many-publi
57
42
 
58
43
  def __init__(
59
44
  self,
45
+ yaml_data: Dict[str, Any],
60
46
  options: Dict[str, Any],
61
47
  ) -> None:
62
- self.send_request_name = "send_request" if options['show_send_request'] else "_send_request"
63
- self.rest_layer_name = "rest" if options["builders_visibility"] == "public" else "_rest"
48
+ self.yaml_data = yaml_data
64
49
  self.options = options
65
- self.module_name: str = ""
66
- self.class_name: str = ""
67
- self.description: str = ""
68
- self.namespace: str = ""
69
- self.namespace_path: str = ""
70
- self.schemas: Dict[int, ObjectSchema] = {}
71
- self.sorted_schemas: List[ObjectSchema] = []
72
- self.enums: Dict[int, EnumSchema] = {}
73
- self.primitives: Dict[int, BaseSchema] = {}
50
+ self.types_map: Dict[int, BaseType] = {} # map yaml id to schema
74
51
  self.operation_groups: List[OperationGroup] = []
75
- params = GlobalParameterList(self)
76
- params.code_model = self
77
- self.service_client: Client = Client(self, params)
78
- self._rest: Optional[Rest] = None
79
- self.request_builder_ids: Dict[int, RequestBuilder] = {}
80
- self._credential_schema_policy: Optional[CredentialSchemaPolicy] = None
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
+ ] = []
81
58
  self.package_dependency: Dict[str, str] = {}
59
+ self.namespace: str = yaml_data["client"]["namespace"].lower()
60
+ self.module_name: str = self.yaml_data["client"]["moduleName"]
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}")
82
74
 
83
75
  @property
84
- def global_parameters(self) -> GlobalParameterList:
85
- 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
86
89
 
87
- @global_parameters.setter
88
- def global_parameters(self, val: GlobalParameterList) -> None:
89
- 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.")
90
112
 
91
113
  @property
92
- def rest(self) -> Rest:
93
- if not self._rest:
94
- raise ValueError("rest is None. Can not call it, you first have to set it.")
95
- 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
96
121
 
97
- @rest.setter
98
- def rest(self, p: Rest) -> None:
99
- self._rest = p
122
+ @model_types.setter
123
+ def model_types(self, val: List[ModelType]) -> None:
124
+ self._model_types = val
100
125
 
101
- def lookup_schema(self, schema_id: int) -> BaseSchema:
102
- """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]
103
129
 
104
- :param int schema_id: The yaml id of the schema
105
- :return: If created, we return the created schema, otherwise, we throw.
106
- :rtype: ~autorest.models.BaseSchema
107
- :raises: KeyError if schema is not found
108
- """
109
- for attr in [self.schemas, self.enums, self.primitives]:
110
- for elt_key, elt_value in attr.items(): # type: ignore
111
- if schema_id == elt_key:
112
- return elt_value
113
- 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)]
114
134
 
115
135
  @staticmethod
116
- 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
+ ):
117
139
  if current.id in seen_schema_yaml_ids:
118
140
  return []
119
141
  if current.name in seen_schema_names:
@@ -121,20 +143,23 @@ class CodeModel: # pylint: disable=too-many-instance-attributes, too-many-publi
121
143
  f"We have already generated a schema with name {current.name}"
122
144
  )
123
145
  ancestors = [current]
124
- if current.base_models:
125
- for base_model in current.base_models:
126
- parent = cast(ObjectSchema, base_model)
146
+ if current.parents:
147
+ for parent in current.parents:
127
148
  if parent.id in seen_schema_yaml_ids:
128
149
  continue
129
150
  seen_schema_names.add(current.name)
130
151
  seen_schema_yaml_ids.add(current.id)
131
- 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
+ )
132
158
  seen_schema_names.add(current.name)
133
159
  seen_schema_yaml_ids.add(current.id)
134
160
  return ancestors
135
161
 
136
-
137
- def sort_schemas(self) -> None:
162
+ def sort_model_types(self) -> None:
138
163
  """Sorts the final object schemas by inheritance and by alphabetical order.
139
164
 
140
165
  :return: None
@@ -142,29 +167,14 @@ class CodeModel: # pylint: disable=too-many-instance-attributes, too-many-publi
142
167
  """
143
168
  seen_schema_names: Set[str] = set()
144
169
  seen_schema_yaml_ids: Set[int] = set()
145
- sorted_schemas: List[ObjectSchema] = []
146
- for schema in sorted(self.schemas.values(), key=lambda x: x.name.lower()):
147
- sorted_schemas.extend(CodeModel._sort_schemas_helper(schema, seen_schema_names, seen_schema_yaml_ids))
148
- self.sorted_schemas = sorted_schemas
149
-
150
- def setup_client_input_parameters(self, yaml_data: Dict[str, Any]):
151
- dollar_host = [
152
- parameter for parameter in self.global_parameters
153
- if parameter.rest_api_name == "$host"
154
- ]
155
- if not dollar_host:
156
- # We don't want to support multi-api customurl YET (will see if that goes well....)
157
- # So far now, let's get the first one in the first operation
158
- # UGLY as hell.....
159
- if yaml_data.get("operationGroups"):
160
- first_req_of_first_op_of_first_grp = yaml_data["operationGroups"][0]["operations"][0]["requests"][0]
161
- self.service_client.parameterized_host_template = (
162
- 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
163
175
  )
164
- else:
165
- for host in dollar_host:
166
- self.global_parameters.remove(host)
167
- self.service_client.parameters.add_host(dollar_host[0].yaml_data["clientDefaultValue"])
176
+ )
177
+ self.model_types = sorted_object_schemas
168
178
 
169
179
  def format_lro_operations(self) -> None:
170
180
  """Adds operations and attributes needed for LROs.
@@ -175,228 +185,84 @@ class CodeModel: # pylint: disable=too-many-instance-attributes, too-many-publi
175
185
  i = 0
176
186
  while i < len(operation_group.operations):
177
187
  operation = operation_group.operations[i]
178
- if isinstance(operation, LROOperation):
179
- 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
180
190
  i += 1
181
191
  i += 1
182
192
 
183
- def remove_next_operation(self) -> None:
184
- """Linking paging operations together.
185
- """
186
- def _lookup_operation(yaml_id: int) -> Operation:
187
- for operation_group in self.operation_groups:
188
- for operation in operation_group.operations:
189
- if operation.id == yaml_id:
190
- return operation
191
- raise KeyError("Didn't find it!!!!!")
192
-
193
- for operation_group in self.operation_groups:
194
- next_operations = []
195
- for operation in operation_group.operations:
196
- # when we add in "LRO" functions we don't include yaml_data, so yaml_data can be empty in these cases
197
- next_link_yaml = None
198
- if operation.yaml_data and operation.yaml_data['language']['python'].get('paging'):
199
- next_link_yaml = operation.yaml_data['language']['python']['paging'].get('nextLinkOperation')
200
- if isinstance(operation, PagingOperation) and next_link_yaml:
201
- next_operation = _lookup_operation(id(next_link_yaml))
202
- operation.next_operation = next_operation
203
- next_operations.append(next_operation)
204
-
205
- operation_group.operations = [
206
- operation for operation in operation_group.operations if operation not in next_operations
207
- ]
208
-
209
- @property
210
- def has_schemas(self):
211
- return self.schemas or self.enums
212
-
213
- @property
214
- def default_authentication_policy(self) -> Type[CredentialSchemaPolicy]:
215
- return ARMChallengeAuthenticationPolicy if self.options['azure_arm'] else BearerTokenCredentialPolicy
216
-
217
- @property
218
- def credential_schema_policy(self) -> CredentialSchemaPolicy:
219
- if not self._credential_schema_policy:
220
- raise ValueError("You want to find the Credential Schema Policy, but have not given a value")
221
- return self._credential_schema_policy
222
-
223
- @credential_schema_policy.setter
224
- def credential_schema_policy(self, val: CredentialSchemaPolicy) -> None:
225
- self._credential_schema_policy = val
226
-
227
- @staticmethod
228
- def _add_properties_from_inheritance_helper(schema, properties) -> List[Property]:
229
- if not schema.base_models:
230
- return properties
231
- if schema.base_models:
232
- for base_model in schema.base_models:
233
- parent = cast(ObjectSchema, base_model)
234
- # need to make sure that the properties we choose from our parent also don't contain
235
- # any of our own properties
236
- schema_property_names = set([p.name for p in properties] + [p.name for p in schema.properties])
237
- chosen_parent_properties = [
238
- p for p in parent.properties
239
- if p.name not in schema_property_names
240
- ]
241
- properties = (
242
- CodeModel._add_properties_from_inheritance_helper(parent, chosen_parent_properties) +
243
- properties
244
- )
245
-
246
- return properties
247
-
248
193
  @property
249
194
  def operations_folder_name(self) -> str:
195
+ """Get the name of the operations folder that holds operations."""
250
196
  name = "operations"
251
197
  if self.options["version_tolerant"] and not any(
252
- 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
253
199
  ):
254
200
  name = f"_{name}"
255
201
  return name
256
202
 
257
- def _add_properties_from_inheritance(self) -> None:
258
- """Adds properties from base classes to schemas with parents.
259
-
260
- :return: None
261
- :rtype: None
262
- """
263
- for schema in self.schemas.values():
264
- schema.properties = CodeModel._add_properties_from_inheritance_helper(schema, schema.properties)
265
-
266
- @staticmethod
267
- def _add_exceptions_from_inheritance_helper(schema) -> bool:
268
- if schema.is_exception:
269
- return True
270
- parent_is_exception: List[bool] = []
271
- for base_model in schema.base_models:
272
- parent = cast(ObjectSchema, base_model)
273
- parent_is_exception.append(CodeModel._add_exceptions_from_inheritance_helper(parent))
274
- return any(parent_is_exception)
275
-
276
- def _add_exceptions_from_inheritance(self) -> None:
277
- """Sets a class as an exception if it's parent is an exception.
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"""
205
+ if async_mode:
206
+ return self.need_mixin_abc
207
+ return (
208
+ self.need_request_converter or self.need_format_url or self.need_mixin_abc
209
+ )
278
210
 
279
- :return: None
280
- :rtype: None
211
+ @property
212
+ def need_request_converter(self) -> bool:
281
213
  """
282
- for schema in self.schemas.values():
283
- schema.is_exception = CodeModel._add_exceptions_from_inheritance_helper(schema)
284
-
285
- def add_inheritance_to_models(self) -> None:
286
- """Adds base classes and properties from base classes to schemas with parents.
287
-
288
- :return: None
289
- :rtype: None
214
+ Whether we need to convert our created azure.core.rest.HttpRequests to
215
+ azure.core.pipeline.transport.HttpRequests
290
216
  """
291
- for schema in self.schemas.values():
292
- if schema.base_models:
293
- # right now, the base model property just holds the name of the parent class
294
- schema.base_models = [b for b in self.schemas.values() if b.id in schema.base_models]
295
- self._add_properties_from_inheritance()
296
- self._add_exceptions_from_inheritance()
297
-
298
- def _populate_target_property(self, parameter: Parameter) -> None:
299
- for obj in self.schemas.values():
300
- for prop in obj.properties:
301
- if prop.id == parameter.target_property_name:
302
- parameter.target_property_name = prop.name
303
- return
304
- raise KeyError("Didn't find the target property")
305
-
306
- def _populate_schema(self, obj: Any) -> None:
307
- schema_obj = obj.schema
308
- if schema_obj and not isinstance(schema_obj, dict):
309
- return
310
-
311
- if schema_obj:
312
- schema_obj_id = id(obj.schema)
313
- _LOGGER.debug("Looking for id %s for member %s", schema_obj_id, obj)
314
- try:
315
- obj.schema = self.lookup_schema(schema_obj_id)
316
- except KeyError:
317
- _LOGGER.critical("Unable to ref the object")
318
- raise
319
- if isinstance(obj, Parameter) and obj.target_property_name:
320
- self._populate_target_property(obj)
321
- if isinstance(obj, SchemaResponse) and obj.is_stream_response:
322
- obj.schema = IOSchema(namespace=None, yaml_data={})
323
-
324
- def add_schema_link_to_operation(self) -> None:
325
- """Puts created schemas into operation classes `schema` property
326
-
327
- :return: None
328
- :rtype: None
329
- """
330
- # Index schemas
331
- for operation_group in self.operation_groups:
332
- for operation in operation_group.operations:
333
- for obj in chain(
334
- operation.parameters,
335
- operation.multiple_content_type_parameters or [],
336
- operation.responses,
337
- operation.exceptions,
338
- chain.from_iterable(response.headers for response in operation.responses),
339
- ):
340
- self._populate_schema(obj)
341
-
342
- def add_schema_link_to_request_builder(self) -> None:
343
- for request_builder in self.rest.request_builders:
344
- for obj in chain(
345
- request_builder.parameters,
346
- chain.from_iterable(request.parameters for request in request_builder.schema_requests),
347
- request_builder.responses,
348
- ):
349
- self._populate_schema(obj)
350
-
351
-
352
- def add_schema_link_to_global_parameters(self) -> None:
353
- for parameter in self.global_parameters:
354
- self._populate_schema(parameter)
355
-
356
- def generate_single_parameter_from_multiple_content_types_operation(self) -> None:
357
- for operation_group in self.operation_groups:
358
- for operation in operation_group.operations:
359
- if operation.multiple_content_type_parameters:
360
- operation.convert_multiple_content_type_parameters()
217
+ return (
218
+ self.options["show_operations"]
219
+ and bool(self.request_builders)
220
+ and not self.options["version_tolerant"]
221
+ )
361
222
 
362
223
  @property
363
- def need_vendored_code(self) -> bool:
364
- return self.need_request_converter or self.need_format_url
365
-
366
- @property
367
- def need_request_converter(self) -> bool:
368
- return self.options["show_operations"] and not self.options["version_tolerant"]
224
+ def need_format_url(self) -> bool:
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)
369
227
 
370
228
  @property
371
- def need_format_url(self) -> bool:
372
- return any(rq for rq in self.rest.request_builders if rq.parameters.path)
229
+ def need_mixin_abc(self) -> bool:
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
+ )
373
236
 
374
237
  @property
375
238
  def has_lro_operations(self) -> bool:
376
- return any([
377
- isinstance(operation, LROOperation)
378
- for operation_group in self.operation_groups
379
- for operation in operation_group.operations
380
- ])
381
-
382
- def _lookup_request_builder(self, schema_id: int) -> RequestBuilder:
383
- """Looks to see if the schema has already been created.
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
+ )
247
+
248
+ def get_models_filename(self, is_python3_file: bool) -> str:
249
+ """Get the names of the model file(s)"""
250
+ if (
251
+ self.options["version_tolerant"] or self.options["low_level_client"]
252
+ ) and self.options["python3_only"]:
253
+ return "_models"
254
+ if is_python3_file:
255
+ return "_models_py3"
256
+ return "_models"
384
257
 
385
- :param int schema_id: The yaml id of the schema
386
- :return: If created, we return the created schema, otherwise, we throw.
387
- :rtype: ~autorest.models.RequestBuilder
388
- :raises: KeyError if schema is not found
389
- """
390
- for elt_key, elt_value in self.request_builder_ids.items(): # type: ignore
391
- if schema_id == elt_key:
392
- return elt_value
393
- raise KeyError("Didn't find it!!!!!")
258
+ @property
259
+ def enums_filename(self) -> str:
260
+ """The name of the enums file"""
261
+ if self.options["version_tolerant"] or self.options["low_level_client"]:
262
+ return "_enums"
263
+ return f"_{self.module_name}_enums"
394
264
 
395
- def link_operation_to_request_builder(self) -> None:
396
- for operation_group in self.operation_groups:
397
- for operation in operation_group.operations:
398
- request_builder = self._lookup_request_builder(id(operation.yaml_data))
399
- if isinstance(operation, LROOperation):
400
- request_builder.name = request_builder.name + "_initial"
401
- operation.request_builder = request_builder
402
- operation.link_body_kwargs_to_body_params()
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
+ )