@autorest/python 5.15.0 → 5.16.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 (86) hide show
  1. package/ChangeLog.md +20 -0
  2. package/autorest/__init__.py +1 -2
  3. package/autorest/black/__init__.py +12 -5
  4. package/autorest/codegen/__init__.py +145 -73
  5. package/autorest/codegen/models/__init__.py +29 -18
  6. package/autorest/codegen/models/base_builder.py +48 -11
  7. package/autorest/codegen/models/base_model.py +6 -4
  8. package/autorest/codegen/models/base_schema.py +19 -18
  9. package/autorest/codegen/models/client.py +65 -21
  10. package/autorest/codegen/models/code_model.py +107 -61
  11. package/autorest/codegen/models/constant_schema.py +25 -13
  12. package/autorest/codegen/models/credential_model.py +23 -15
  13. package/autorest/codegen/models/credential_schema.py +18 -14
  14. package/autorest/codegen/models/credential_schema_policy.py +11 -15
  15. package/autorest/codegen/models/dictionary_schema.py +20 -17
  16. package/autorest/codegen/models/enum_schema.py +35 -25
  17. package/autorest/codegen/models/imports.py +70 -41
  18. package/autorest/codegen/models/list_schema.py +25 -13
  19. package/autorest/codegen/models/lro_operation.py +58 -22
  20. package/autorest/codegen/models/lro_paging_operation.py +2 -3
  21. package/autorest/codegen/models/object_schema.py +99 -49
  22. package/autorest/codegen/models/operation.py +236 -117
  23. package/autorest/codegen/models/operation_group.py +64 -34
  24. package/autorest/codegen/models/paging_operation.py +45 -18
  25. package/autorest/codegen/models/parameter.py +151 -83
  26. package/autorest/codegen/models/parameter_list.py +183 -162
  27. package/autorest/codegen/models/primitive_schemas.py +84 -55
  28. package/autorest/codegen/models/property.py +44 -26
  29. package/autorest/codegen/models/request_builder.py +65 -30
  30. package/autorest/codegen/models/request_builder_parameter.py +47 -23
  31. package/autorest/codegen/models/request_builder_parameter_list.py +77 -108
  32. package/autorest/codegen/models/schema_request.py +16 -6
  33. package/autorest/codegen/models/schema_response.py +18 -13
  34. package/autorest/codegen/models/utils.py +5 -2
  35. package/autorest/codegen/serializers/__init__.py +182 -91
  36. package/autorest/codegen/serializers/builder_serializer.py +667 -331
  37. package/autorest/codegen/serializers/client_serializer.py +98 -37
  38. package/autorest/codegen/serializers/general_serializer.py +61 -26
  39. package/autorest/codegen/serializers/import_serializer.py +93 -31
  40. package/autorest/codegen/serializers/metadata_serializer.py +73 -24
  41. package/autorest/codegen/serializers/model_base_serializer.py +35 -15
  42. package/autorest/codegen/serializers/model_generic_serializer.py +1 -4
  43. package/autorest/codegen/serializers/model_init_serializer.py +5 -1
  44. package/autorest/codegen/serializers/model_python3_serializer.py +7 -6
  45. package/autorest/codegen/serializers/operation_groups_serializer.py +20 -9
  46. package/autorest/codegen/serializers/operations_init_serializer.py +23 -11
  47. package/autorest/codegen/serializers/patch_serializer.py +4 -1
  48. package/autorest/codegen/serializers/{rest_serializer.py → request_builders_serializer.py} +29 -12
  49. package/autorest/codegen/serializers/utils.py +35 -21
  50. package/autorest/codegen/templates/init.py.jinja2 +2 -2
  51. package/autorest/codegen/templates/lro_operation.py.jinja2 +5 -7
  52. package/autorest/codegen/templates/lro_paging_operation.py.jinja2 +5 -7
  53. package/autorest/codegen/templates/metadata.json.jinja2 +7 -6
  54. package/autorest/codegen/templates/operation.py.jinja2 +7 -9
  55. package/autorest/codegen/templates/operation_group.py.jinja2 +2 -8
  56. package/autorest/codegen/templates/operation_groups_container.py.jinja2 +1 -1
  57. package/autorest/codegen/templates/paging_operation.py.jinja2 +7 -8
  58. package/autorest/codegen/templates/request_builder.py.jinja2 +18 -11
  59. package/autorest/jsonrpc/__init__.py +7 -12
  60. package/autorest/jsonrpc/localapi.py +4 -3
  61. package/autorest/jsonrpc/server.py +13 -6
  62. package/autorest/jsonrpc/stdstream.py +13 -6
  63. package/autorest/m2r/__init__.py +5 -8
  64. package/autorest/multiapi/__init__.py +24 -14
  65. package/autorest/multiapi/models/client.py +21 -11
  66. package/autorest/multiapi/models/code_model.py +23 -10
  67. package/autorest/multiapi/models/config.py +4 -1
  68. package/autorest/multiapi/models/constant_global_parameter.py +1 -0
  69. package/autorest/multiapi/models/global_parameter.py +2 -1
  70. package/autorest/multiapi/models/global_parameters.py +14 -8
  71. package/autorest/multiapi/models/imports.py +24 -17
  72. package/autorest/multiapi/models/mixin_operation.py +5 -5
  73. package/autorest/multiapi/models/operation_group.py +2 -1
  74. package/autorest/multiapi/models/operation_mixin_group.py +21 -10
  75. package/autorest/multiapi/serializers/__init__.py +18 -23
  76. package/autorest/multiapi/serializers/import_serializer.py +47 -17
  77. package/autorest/multiapi/serializers/multiapi_serializer.py +17 -17
  78. package/autorest/multiapi/templates/multiapi_operations_mixin.py.jinja2 +1 -1
  79. package/autorest/multiapi/utils.py +3 -3
  80. package/autorest/namer/__init__.py +2 -4
  81. package/autorest/namer/name_converter.py +200 -103
  82. package/autorest/namer/python_mappings.py +10 -22
  83. package/package.json +2 -2
  84. package/run-python3.js +2 -3
  85. package/venvtools.py +1 -1
  86. package/autorest/codegen/models/rest.py +0 -42
@@ -4,8 +4,10 @@
4
4
  # license information.
5
5
  # --------------------------------------------------------------------------
6
6
  from typing import List
7
+
7
8
  from . import utils
8
9
  from ..models import CodeModel
10
+ from ..models.parameter import ParameterMethodLocation
9
11
 
10
12
 
11
13
  class ClientSerializer:
@@ -43,7 +45,9 @@ class ClientSerializer:
43
45
 
44
46
  def class_definition(self, async_mode) -> str:
45
47
  class_name = self.code_model.class_name
46
- has_mixin_og = any(og for og in self.code_model.operation_groups if og.is_empty_operation_group)
48
+ has_mixin_og = any(
49
+ og for og in self.code_model.operation_groups if og.is_empty_operation_group
50
+ )
47
51
  base_class = ""
48
52
  if has_mixin_og:
49
53
  base_class = f"{class_name}OperationsMixin"
@@ -59,12 +63,22 @@ class ClientSerializer:
59
63
  def property_descriptions(self, async_mode: bool) -> List[str]:
60
64
  retval: List[str] = []
61
65
  operations_folder = ".aio.operations." if async_mode else ".operations."
62
- for og in [og for og in self.code_model.operation_groups if not og.is_empty_operation_group]:
66
+ for og in [
67
+ og
68
+ for og in self.code_model.operation_groups
69
+ if not og.is_empty_operation_group
70
+ ]:
63
71
  retval.append(f":ivar {og.name}: {og.class_name} operations")
64
- retval.append(f":vartype {og.name}: {self.code_model.namespace}{operations_folder}{og.class_name}")
72
+ retval.append(
73
+ f":vartype {og.name}: {self.code_model.namespace}{operations_folder}{og.class_name}"
74
+ )
65
75
  for param in self.code_model.service_client.parameters.client_method:
66
- retval.append(f":{param.description_keyword} {param.serialized_name}: {param.description}")
67
- retval.append(f":{param.docstring_type_keyword} {param.serialized_name}: {param.docstring_type}")
76
+ retval.append(
77
+ f":{param.description_keyword} {param.serialized_name}: {param.description}"
78
+ )
79
+ retval.append(
80
+ f":{param.docstring_type_keyword} {param.serialized_name}: {param.docstring_type}"
81
+ )
68
82
  if self.code_model.has_lro_operations:
69
83
  retval.append(
70
84
  ":keyword int polling_interval: Default waiting time between two polls for LRO operations "
@@ -79,38 +93,57 @@ class ClientSerializer:
79
93
  [
80
94
  f"{p.serialized_name}={p.serialized_name}"
81
95
  for p in self.code_model.service_client.parameters.config_method
82
- if not p.is_kwarg
83
- ] + [
84
- "**kwargs"
85
- ])
96
+ if not p.method_location
97
+ in (ParameterMethodLocation.KWARG, ParameterMethodLocation.HIDDEN_KWARG)
98
+ ]
99
+ + ["**kwargs"]
100
+ )
86
101
  return f"self._config = {config_name}({config_call})"
87
102
 
88
103
  def initialize_pipeline_client(self, async_mode: bool) -> str:
89
- host_variable_name = self.code_model.service_client.parameters.host_variable_name
104
+ host_variable_name = (
105
+ self.code_model.service_client.parameters.host_variable_name
106
+ )
90
107
  if self.code_model.service_client.has_parameterized_host:
91
- host_variable_name = "_" + host_variable_name # we don't want potential conflicts with input params
108
+ host_variable_name = (
109
+ "_" + host_variable_name
110
+ ) # we don't want potential conflicts with input params
92
111
  pipeline_client_name = self.code_model.service_client.pipeline_class(async_mode)
93
112
  return f"self._client = {pipeline_client_name}(base_url={host_variable_name}, config=self._config, **kwargs)"
94
113
 
95
114
  def serializers_and_operation_groups_properties(self) -> List[str]:
96
115
  retval = []
97
116
  if self.code_model.sorted_schemas:
98
- client_models_value = "{k: v for k, v in models.__dict__.items() if isinstance(v, type)}"
117
+ client_models_value = (
118
+ "{k: v for k, v in models.__dict__.items() if isinstance(v, type)}"
119
+ )
99
120
  else:
100
121
  client_models_value = "{} # type: Dict[str, Any]"
101
122
  if self.code_model.options["models_mode"]:
102
123
  retval.append(f"client_models = {client_models_value}")
103
- client_models_str = "client_models" if self.code_model.options["models_mode"] else ""
124
+ client_models_str = (
125
+ "client_models" if self.code_model.options["models_mode"] else ""
126
+ )
104
127
  retval.append(f"self._serialize = Serializer({client_models_str})")
105
128
  retval.append(f"self._deserialize = Deserializer({client_models_str})")
106
129
  if not self.code_model.options["client_side_validation"]:
107
130
  retval.append("self._serialize.client_side_validation = False")
108
- operation_groups = [og for og in self.code_model.operation_groups if not og.is_empty_operation_group]
109
- if operation_groups:
131
+ operation_groups = [
132
+ og
133
+ for og in self.code_model.operation_groups
134
+ if not og.is_empty_operation_group
135
+ ]
136
+ for og in operation_groups:
137
+ disable_check = (
138
+ " # type: ignore # pylint: disable=abstract-class-instantiated"
139
+ if og.has_abstract_operations
140
+ else ""
141
+ )
110
142
  retval.extend(
111
143
  [
112
- f"self.{og.name} = {og.class_name}(self._client, self._config, self._serialize, self._deserialize)"
113
- for og in operation_groups
144
+ f"self.{og.name} = {og.class_name}({disable_check}",
145
+ " self._client, self._config, self._serialize, self._deserialize",
146
+ ")",
114
147
  ]
115
148
  )
116
149
  return retval
@@ -125,12 +158,16 @@ class ClientSerializer:
125
158
  ),
126
159
  )
127
160
 
128
- def send_request_signature_and_response_type_annotation(self, async_mode: bool) -> str:
161
+ def send_request_signature_and_response_type_annotation(
162
+ self, async_mode: bool
163
+ ) -> str:
129
164
  send_request_signature = self._send_request_signature(async_mode)
130
165
  return utils.method_signature_and_response_type_annotation_template(
131
166
  is_python3_file=async_mode or self.is_python3_file,
132
167
  method_signature=send_request_signature,
133
- response_type_annotation="Awaitable[AsyncHttpResponse]" if async_mode else "HttpResponse",
168
+ response_type_annotation="Awaitable[AsyncHttpResponse]"
169
+ if async_mode
170
+ else "HttpResponse",
134
171
  )
135
172
 
136
173
  def _example_make_call(self, async_mode: bool) -> List[str]:
@@ -143,23 +180,35 @@ class ClientSerializer:
143
180
 
144
181
  def _request_builder_example(self, async_mode: bool) -> List[str]:
145
182
  retval = [
146
- "We have helper methods to create requests specific to this service in " +
147
- f"`{self.code_model.namespace}.{self.code_model.rest_layer_name}`."
183
+ "We have helper methods to create requests specific to this service in "
184
+ + f"`{self.code_model.namespace}.{self.code_model.rest_layer_name}`."
148
185
  ]
149
- retval.append("Use these helper methods to create the request you pass to this method.")
186
+ retval.append(
187
+ "Use these helper methods to create the request you pass to this method."
188
+ )
150
189
  retval.append("")
151
190
 
152
- request_builder = self.code_model.rest.request_builders[0]
153
- request_builder_signature = ", ".join(request_builder.parameters.call)
191
+ request_builder = self.code_model.request_builders[0]
192
+ request_builder_signature = ", ".join(
193
+ request_builder.parameters.call(async_mode)
194
+ )
154
195
  if request_builder.builder_group_name:
155
196
  rest_imported = request_builder.builder_group_name
156
- request_builder_name = f"{request_builder.builder_group_name}.{request_builder.name}"
197
+ request_builder_name = (
198
+ f"{request_builder.builder_group_name}.{request_builder.name}"
199
+ )
157
200
  else:
158
201
  rest_imported = request_builder.name
159
202
  request_builder_name = request_builder.name
160
- retval.append(f">>> from {self.code_model.namespace}.{self.code_model.rest_layer_name} import {rest_imported}")
161
- retval.append(f">>> request = {request_builder_name}({request_builder_signature})")
162
- retval.append(f"<HttpRequest [{request_builder.method}], url: '{request_builder.url}'>")
203
+ retval.append(
204
+ f">>> from {self.code_model.namespace}.{self.code_model.rest_layer_name} import {rest_imported}"
205
+ )
206
+ retval.append(
207
+ f">>> request = {request_builder_name}({request_builder_signature})"
208
+ )
209
+ retval.append(
210
+ f"<HttpRequest [{request_builder.method}], url: '{request_builder.url}'>"
211
+ )
163
212
  retval.extend(self._example_make_call(async_mode))
164
213
  return retval
165
214
 
@@ -178,22 +227,30 @@ class ClientSerializer:
178
227
  else:
179
228
  retval.extend(self._rest_request_example(async_mode))
180
229
  retval.append("")
181
- retval.append("For more information on this code flow, see https://aka.ms/azsdk/python/protocol/quickstart")
230
+ retval.append(
231
+ "For more information on this code flow, see https://aka.ms/azsdk/python/protocol/quickstart"
232
+ )
182
233
  retval.append(f"")
183
234
  retval.append(":param request: The network request you want to make. Required.")
184
235
  retval.append(f":type request: ~azure.core.rest.HttpRequest")
185
- retval.append(":keyword bool stream: Whether the response payload will be streamed. Defaults to False.")
186
- retval.append(":return: The response of your network call. Does not do error handling on your response.")
236
+ retval.append(
237
+ ":keyword bool stream: Whether the response payload will be streamed. Defaults to False."
238
+ )
239
+ retval.append(
240
+ ":return: The response of your network call. Does not do error handling on your response."
241
+ )
187
242
  http_response = "AsyncHttpResponse" if async_mode else "HttpResponse"
188
243
  retval.append(f":rtype: ~azure.core.rest.{http_response}")
189
244
  retval.append('"""')
190
245
  return retval
191
246
 
192
247
  def serialize_path(self) -> List[str]:
193
- return utils.serialize_path(self.code_model.global_parameters.path, "self._serialize")
248
+ return utils.serialize_path(
249
+ self.code_model.global_parameters.path, "self._serialize"
250
+ )
194
251
 
195
- class ConfigSerializer:
196
252
 
253
+ class ConfigSerializer:
197
254
  def __init__(self, code_model: CodeModel, is_python3_file: bool) -> None:
198
255
  self.code_model = code_model
199
256
  self.is_python3_file = is_python3_file
@@ -235,8 +292,8 @@ class ConfigSerializer:
235
292
 
236
293
  def check_required_parameters(self) -> List[str]:
237
294
  return [
238
- f'if {p.serialized_name} is None:\n'
239
- f' raise ValueError("Parameter \'{p.serialized_name}\' must not be None.")'
295
+ f"if {p.serialized_name} is None:\n"
296
+ f" raise ValueError(\"Parameter '{p.serialized_name}' must not be None.\")"
240
297
  for p in self.code_model.global_parameters.config_method
241
298
  if p.required and not p.constant
242
299
  ]
@@ -244,7 +301,11 @@ class ConfigSerializer:
244
301
  def property_descriptions(self) -> List[str]:
245
302
  retval: List[str] = []
246
303
  for p in self.code_model.global_parameters.config_method:
247
- retval.append(f":{p.description_keyword} {p.serialized_name}: {p.description}")
248
- retval.append(f":{p.docstring_type_keyword} {p.serialized_name}: {p.docstring_type}")
304
+ retval.append(
305
+ f":{p.description_keyword} {p.serialized_name}: {p.description}"
306
+ )
307
+ retval.append(
308
+ f":{p.docstring_type_keyword} {p.serialized_name}: {p.docstring_type}"
309
+ )
249
310
  retval.append('"""')
250
311
  return retval
@@ -5,27 +5,54 @@
5
5
  # --------------------------------------------------------------------------
6
6
  from jinja2 import Environment
7
7
  from .import_serializer import FileImportSerializer, TypingSection
8
- from ..models import FileImport, ImportType, CodeModel, TokenCredentialSchema, ParameterList
8
+ from ..models import (
9
+ FileImport,
10
+ ImportType,
11
+ CodeModel,
12
+ TokenCredentialSchema,
13
+ ParameterList,
14
+ )
9
15
  from .client_serializer import ClientSerializer, ConfigSerializer
10
16
 
11
- def config_imports(code_model, global_parameters: ParameterList, async_mode: bool) -> FileImport:
17
+
18
+ def config_imports(
19
+ code_model, global_parameters: ParameterList, async_mode: bool
20
+ ) -> FileImport:
12
21
  file_import = FileImport()
13
- file_import.add_submodule_import("azure.core.configuration", "Configuration", ImportType.AZURECORE)
14
- file_import.add_submodule_import("azure.core.pipeline", "policies", ImportType.AZURECORE)
15
- file_import.add_submodule_import("typing", "Any", ImportType.STDLIB, TypingSection.CONDITIONAL)
22
+ file_import.add_submodule_import(
23
+ "azure.core.configuration", "Configuration", ImportType.AZURECORE
24
+ )
25
+ file_import.add_submodule_import(
26
+ "azure.core.pipeline", "policies", ImportType.AZURECORE
27
+ )
28
+ file_import.add_submodule_import(
29
+ "typing", "Any", ImportType.STDLIB, TypingSection.CONDITIONAL
30
+ )
16
31
  if code_model.options["package_version"]:
17
- file_import.add_submodule_import(".._version" if async_mode else "._version", "VERSION", ImportType.LOCAL)
32
+ file_import.add_submodule_import(
33
+ ".._version" if async_mode else "._version", "VERSION", ImportType.LOCAL
34
+ )
18
35
  for gp in global_parameters:
19
36
  file_import.merge(gp.imports())
20
37
  if code_model.options["azure_arm"]:
21
- policy = "AsyncARMChallengeAuthenticationPolicy" if async_mode else "ARMChallengeAuthenticationPolicy"
22
- file_import.add_submodule_import("azure.mgmt.core.policies", "ARMHttpLoggingPolicy", ImportType.AZURECORE)
23
- file_import.add_submodule_import("azure.mgmt.core.policies", policy, ImportType.AZURECORE)
38
+ policy = (
39
+ "AsyncARMChallengeAuthenticationPolicy"
40
+ if async_mode
41
+ else "ARMChallengeAuthenticationPolicy"
42
+ )
43
+ file_import.add_submodule_import(
44
+ "azure.mgmt.core.policies", "ARMHttpLoggingPolicy", ImportType.AZURECORE
45
+ )
46
+ file_import.add_submodule_import(
47
+ "azure.mgmt.core.policies", policy, ImportType.AZURECORE
48
+ )
24
49
  return file_import
25
50
 
26
51
 
27
52
  class GeneralSerializer:
28
- def __init__(self, code_model: CodeModel, env: Environment, async_mode: bool) -> None:
53
+ def __init__(
54
+ self, code_model: CodeModel, env: Environment, async_mode: bool
55
+ ) -> None:
29
56
  self.code_model = code_model
30
57
  self.env = env
31
58
  self.async_mode = async_mode
@@ -40,7 +67,9 @@ class GeneralSerializer:
40
67
 
41
68
  def _correct_credential_parameter(self):
42
69
  credential_param = [
43
- gp for gp in self.code_model.global_parameters.parameters if isinstance(gp.schema, TokenCredentialSchema)
70
+ gp
71
+ for gp in self.code_model.global_parameters.parameters
72
+ if isinstance(gp.schema, TokenCredentialSchema)
44
73
  ][0]
45
74
  credential_param.schema = TokenCredentialSchema(async_mode=self.async_mode)
46
75
 
@@ -48,9 +77,9 @@ class GeneralSerializer:
48
77
 
49
78
  template = self.env.get_template("service_client.py.jinja2")
50
79
 
51
- if (
52
- self.code_model.options['credential'] and
53
- isinstance(self.code_model.credential_model.credential_schema_policy.credential, TokenCredentialSchema)
80
+ if self.code_model.options["credential"] and isinstance(
81
+ self.code_model.credential_model.credential_schema_policy.credential,
82
+ TokenCredentialSchema,
54
83
  ):
55
84
  self._correct_credential_parameter()
56
85
 
@@ -61,7 +90,7 @@ class GeneralSerializer:
61
90
  serializer=ClientSerializer(self.code_model, is_python3_file=python3_only),
62
91
  imports=FileImportSerializer(
63
92
  self.code_model.service_client.imports(self.async_mode),
64
- is_python3_file=self.async_mode or python3_only
93
+ is_python3_file=self.async_mode or python3_only,
65
94
  ),
66
95
  )
67
96
 
@@ -92,10 +121,14 @@ class GeneralSerializer:
92
121
  file_import.add_submodule_import(
93
122
  "._configuration",
94
123
  f"{self.code_model.class_name}Configuration",
95
- ImportType.LOCAL
124
+ ImportType.LOCAL,
125
+ )
126
+ file_import.add_submodule_import(
127
+ "msrest", "Serializer", ImportType.THIRDPARTY, TypingSection.TYPING
128
+ )
129
+ file_import.add_submodule_import(
130
+ "msrest", "Deserializer", ImportType.THIRDPARTY, TypingSection.TYPING
96
131
  )
97
- file_import.add_submodule_import("msrest", "Serializer", ImportType.THIRDPARTY, TypingSection.TYPING)
98
- file_import.add_submodule_import("msrest", "Deserializer", ImportType.THIRDPARTY, TypingSection.TYPING)
99
132
 
100
133
  return template.render(
101
134
  code_model=self.code_model,
@@ -106,17 +139,18 @@ class GeneralSerializer:
106
139
  async_mode=self.async_mode,
107
140
  )
108
141
 
109
-
110
142
  def serialize_config_file(self) -> str:
111
143
 
112
- package_name = self.code_model.options['package_name']
144
+ package_name = self.code_model.options["package_name"]
113
145
  if package_name and package_name.startswith("azure-"):
114
- package_name = package_name[len("azure-"):]
115
- sdk_moniker = package_name if package_name else self.code_model.class_name.lower()
146
+ package_name = package_name[len("azure-") :]
147
+ sdk_moniker = (
148
+ package_name if package_name else self.code_model.class_name.lower()
149
+ )
116
150
 
117
- if (
118
- self.code_model.options['credential'] and
119
- isinstance(self.code_model.credential_model.credential_schema_policy.credential, TokenCredentialSchema)
151
+ if self.code_model.options["credential"] and isinstance(
152
+ self.code_model.credential_model.credential_schema_policy.credential,
153
+ TokenCredentialSchema,
120
154
  ):
121
155
  self._correct_credential_parameter()
122
156
 
@@ -128,7 +162,8 @@ class GeneralSerializer:
128
162
  imports=FileImportSerializer(
129
163
  config_imports(
130
164
  self.code_model, self.code_model.global_parameters, self.async_mode
131
- ), is_python3_file=self.async_mode or python3_only
165
+ ),
166
+ is_python3_file=self.async_mode or python3_only,
132
167
  ),
133
168
  serializer=ConfigSerializer(self.code_model, is_python3_file=python3_only),
134
169
  sdk_moniker=sdk_moniker,
@@ -5,49 +5,68 @@
5
5
  # --------------------------------------------------------------------------
6
6
  from copy import deepcopy
7
7
  from typing import List
8
- from ..models.imports import ImportType, FileImport, ImportModel, TypingSection
8
+ from ..models.imports import (
9
+ ImportType,
10
+ FileImport,
11
+ ImportModel,
12
+ TypingSection,
13
+ TypeDefinition,
14
+ )
9
15
 
10
- def _serialize_package(
11
- imports: List[ImportModel], delimiter: str
12
- ) -> str:
16
+
17
+ def _serialize_package(imports: List[ImportModel], delimiter: str) -> str:
13
18
  buffer = []
14
19
  if any(i for i in imports if i.submodule_name is None):
15
- buffer.append(f"import {imports[0].module_name}{f' as {imports[0].alias}' if imports[0].alias else ''}")
20
+ buffer.append(
21
+ f"import {imports[0].module_name}{f' as {imports[0].alias}' if imports[0].alias else ''}"
22
+ )
16
23
  else:
17
- import_str = ", ".join(sorted([
18
- f"{i.submodule_name} as {i.alias}" if i.alias else i.submodule_name for i in imports # type: ignore
19
- ]))
24
+ import_str = ", ".join(
25
+ sorted(
26
+ [
27
+ f"{i.submodule_name} as {i.alias}" if i.alias else i.submodule_name for i in imports # type: ignore
28
+ ]
29
+ )
30
+ )
20
31
  buffer.append(f"from {imports[0].module_name} import {import_str}")
21
32
  return delimiter.join(buffer)
22
33
 
34
+
23
35
  def _serialize_import_type(imports: List[ImportModel], delimiter: str) -> str:
24
36
  """Serialize a given import type."""
25
37
  import_list = []
26
38
  for module_name in sorted(set(i.module_name for i in imports)):
27
39
 
28
- import_list.append(_serialize_package([
29
- i for i in imports if i.module_name == module_name
30
- ], delimiter))
40
+ import_list.append(
41
+ _serialize_package(
42
+ [i for i in imports if i.module_name == module_name], delimiter
43
+ )
44
+ )
31
45
  return delimiter.join(import_list)
32
46
 
33
- def _get_import_clauses(
34
- imports: List[ImportModel], delimiter: str
35
- ) -> List[str]:
47
+
48
+ def _get_import_clauses(imports: List[ImportModel], delimiter: str) -> List[str]:
36
49
  import_clause = []
37
50
  for import_type in ImportType:
38
51
  imports_with_import_type = [i for i in imports if i.import_type == import_type]
39
52
  if imports_with_import_type:
40
- import_clause.append(_serialize_import_type(imports_with_import_type, delimiter))
53
+ import_clause.append(
54
+ _serialize_import_type(imports_with_import_type, delimiter)
55
+ )
41
56
  return import_clause
42
57
 
43
58
 
44
59
  class FileImportSerializer:
45
- def __init__(self, file_import: FileImport, is_python3_file: bool, async_mode: bool = False) -> None:
60
+ def __init__(
61
+ self, file_import: FileImport, is_python3_file: bool, async_mode: bool = False
62
+ ) -> None:
46
63
  self.file_import = file_import
47
64
  self.is_python3_file = is_python3_file
48
65
  self.async_mode = async_mode
49
66
 
50
- def _get_imports_list(self, baseline_typing_section: TypingSection, add_conditional_typing: bool):
67
+ def _get_imports_list(
68
+ self, baseline_typing_section: TypingSection, add_conditional_typing: bool
69
+ ):
51
70
  # If this is a python 3 file, our regular imports include the CONDITIONAL category
52
71
  # If this is not a python 3 file, our typing imports include the CONDITIONAL category
53
72
  file_import_copy = deepcopy(self.file_import)
@@ -62,33 +81,73 @@ class FileImportSerializer:
62
81
  return file_import_copy.get_imports_from_section(baseline_typing_section)
63
82
 
64
83
  def _add_type_checking_import(self):
65
- any_typing = any(self.file_import.get_imports_from_section(TypingSection.TYPING))
84
+ any_typing = any(
85
+ self.file_import.get_imports_from_section(TypingSection.TYPING)
86
+ )
66
87
  conditional_and_not_py3 = not self.is_python3_file and any(
67
88
  self.file_import.get_imports_from_section(TypingSection.CONDITIONAL)
68
89
  )
69
90
  if any_typing or conditional_and_not_py3:
70
- self.file_import.add_submodule_import("typing", "TYPE_CHECKING", ImportType.STDLIB)
91
+ self.file_import.add_submodule_import(
92
+ "typing", "TYPE_CHECKING", ImportType.STDLIB
93
+ )
71
94
 
72
95
  def _get_typing_definitions(self) -> str:
96
+ def declare_defintion(
97
+ spacing: str, type_name: str, type_definition: TypeDefinition
98
+ ) -> List[str]:
99
+ ret: List[str] = []
100
+ definition_value = (
101
+ type_definition.async_definition
102
+ if self.async_mode
103
+ else type_definition.sync_definition
104
+ )
105
+ if type_definition.version_imports is not None:
106
+ versions = type_definition.version_imports.keys()
107
+ for i, version in enumerate(
108
+ sorted(
109
+ versions, key=lambda x: x if x is not None else (), reverse=True
110
+ )
111
+ ):
112
+ if version is not None:
113
+ ret.append(
114
+ "{}{} sys.version_info >= {}:".format(
115
+ spacing, "if" if i == 0 else "elif", version
116
+ )
117
+ )
118
+ elif i > 0:
119
+ ret.append("{}else:".format(spacing))
120
+ for import_clause in _get_import_clauses(
121
+ [type_definition.version_imports[version]], "\n"
122
+ ):
123
+ ret.append(
124
+ "{}{}{}".format(
125
+ " "
126
+ if len(versions) > 1 or version is not None
127
+ else "",
128
+ spacing,
129
+ import_clause,
130
+ )
131
+ )
132
+ if i > 0:
133
+ ret[-1] += " # type: ignore"
134
+ ret.append("{}{} = {}".format(spacing, type_name, definition_value))
135
+ return ret
136
+
73
137
  if not self.file_import.type_definitions:
74
138
  return ""
75
139
  spacing = "" if self.is_python3_file else " "
76
- declarations: List[str] = [f"\n{spacing}T = TypeVar('T')"]
77
- declarations.extend([
78
- "{}{} = {}".format(
79
- spacing,
80
- type_name,
81
- values[1] if self.async_mode else values[0]
82
- )
83
- for type_name, values in self.file_import.type_definitions.items()
84
- ])
140
+ declarations: List[str] = [""]
141
+ for type_name, value in self.file_import.type_definitions.items():
142
+ declarations.extend(declare_defintion(spacing, type_name, value))
85
143
  return "\n".join(declarations)
86
144
 
87
145
  def __str__(self) -> str:
88
146
  self._add_type_checking_import()
89
147
  regular_imports = ""
90
148
  regular_imports_list = self._get_imports_list(
91
- baseline_typing_section=TypingSection.REGULAR, add_conditional_typing=self.is_python3_file
149
+ baseline_typing_section=TypingSection.REGULAR,
150
+ add_conditional_typing=self.is_python3_file,
92
151
  )
93
152
 
94
153
  if regular_imports_list:
@@ -98,9 +157,12 @@ class FileImportSerializer:
98
157
 
99
158
  typing_imports = ""
100
159
  typing_imports_list = self._get_imports_list(
101
- baseline_typing_section=TypingSection.TYPING, add_conditional_typing=not self.is_python3_file
160
+ baseline_typing_section=TypingSection.TYPING,
161
+ add_conditional_typing=not self.is_python3_file,
102
162
  )
103
163
  if typing_imports_list:
104
164
  typing_imports += "\n\nif TYPE_CHECKING:\n # pylint: disable=unused-import,ungrouped-imports\n "
105
- typing_imports += "\n\n ".join(_get_import_clauses(typing_imports_list, "\n "))
165
+ typing_imports += "\n\n ".join(
166
+ _get_import_clauses(typing_imports_list, "\n ")
167
+ )
106
168
  return regular_imports + typing_imports + self._get_typing_definitions()