@autorest/python 5.19.0 → 6.0.1

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 (52) hide show
  1. package/ChangeLog.md +61 -2
  2. package/README.md +9 -0
  3. package/autorest/__init__.py +54 -13
  4. package/autorest/black/__init__.py +14 -8
  5. package/autorest/codegen/__init__.py +126 -89
  6. package/autorest/codegen/models/base_builder.py +17 -6
  7. package/autorest/codegen/models/client.py +1 -1
  8. package/autorest/codegen/models/code_model.py +7 -12
  9. package/autorest/codegen/models/lro_operation.py +2 -6
  10. package/autorest/codegen/models/lro_paging_operation.py +3 -9
  11. package/autorest/codegen/models/model_type.py +1 -6
  12. package/autorest/codegen/models/operation.py +6 -37
  13. package/autorest/codegen/models/operation_group.py +4 -7
  14. package/autorest/codegen/models/paging_operation.py +17 -7
  15. package/autorest/codegen/models/parameter.py +3 -7
  16. package/autorest/codegen/models/parameter_list.py +20 -36
  17. package/autorest/codegen/models/request_builder.py +0 -22
  18. package/autorest/codegen/serializers/__init__.py +46 -98
  19. package/autorest/codegen/serializers/builder_serializer.py +53 -36
  20. package/autorest/codegen/serializers/client_serializer.py +20 -31
  21. package/autorest/codegen/serializers/general_serializer.py +2 -7
  22. package/autorest/codegen/serializers/import_serializer.py +11 -22
  23. package/autorest/codegen/serializers/metadata_serializer.py +0 -2
  24. package/autorest/codegen/serializers/{model_base_serializer.py → model_serializer.py} +47 -38
  25. package/autorest/codegen/serializers/operation_groups_serializer.py +0 -7
  26. package/autorest/codegen/serializers/operations_init_serializer.py +2 -23
  27. package/autorest/codegen/serializers/patch_serializer.py +1 -3
  28. package/autorest/codegen/serializers/request_builders_serializer.py +1 -4
  29. package/autorest/codegen/serializers/utils.py +1 -4
  30. package/autorest/codegen/templates/client.py.jinja2 +3 -3
  31. package/autorest/codegen/templates/config.py.jinja2 +2 -2
  32. package/autorest/codegen/templates/metadata.json.jinja2 +4 -4
  33. package/autorest/codegen/templates/model_init.py.jinja2 +5 -12
  34. package/autorest/codegen/templates/operation_group.py.jinja2 +1 -1
  35. package/autorest/codegen/templates/operation_groups_container.py.jinja2 +0 -6
  36. package/autorest/codegen/templates/patch.py.jinja2 +1 -2
  37. package/autorest/codegen/templates/request_builders.py.jinja2 +0 -3
  38. package/autorest/codegen/templates/rest_init.py.jinja2 +3 -8
  39. package/autorest/codegen/templates/serialization.py.jinja2 +3 -3
  40. package/autorest/codegen/templates/setup.py.jinja2 +1 -1
  41. package/autorest/jsonrpc/server.py +7 -7
  42. package/autorest/m2r/__init__.py +7 -2
  43. package/autorest/m4reformatter/__init__.py +13 -5
  44. package/autorest/multiapi/__init__.py +56 -29
  45. package/autorest/multiapi/serializers/__init__.py +26 -31
  46. package/autorest/multiapi/serializers/import_serializer.py +4 -8
  47. package/autorest/multiapi/serializers/multiapi_serializer.py +33 -26
  48. package/autorest/postprocess/__init__.py +14 -11
  49. package/autorest/preprocess/__init__.py +36 -7
  50. package/package.json +2 -2
  51. package/autorest/codegen/serializers/model_generic_serializer.py +0 -32
  52. package/autorest/codegen/serializers/model_python3_serializer.py +0 -72
package/ChangeLog.md CHANGED
@@ -1,6 +1,64 @@
1
1
  # Release History
2
2
 
3
- ### 2022-07-13 - 5.19.0
3
+ ### 2022-06-29 - 6.0.1
4
+
5
+ | Library | Min Version |
6
+ | ----------------------------------------------------------------------- | ----------- |
7
+ | `@autorest/core` | `3.8.1` |
8
+ | `@autorest/modelerfour` | `4.23.5` |
9
+ | `azure-core` dep of generated code | `1.24.0` |
10
+ | `isodate` dep of generated code | `0.6.1` |
11
+ | `msrest` dep of generated code (If generating legacy code) | `0.7.1` |
12
+ | `azure-mgmt-core` dep of generated code (If generating mgmt plane code) | `1.3.0` |
13
+
14
+ **Bug Fixes**
15
+
16
+ - Ignore linting error for clients with no credentials #1333
17
+
18
+ ### 2022-06-24 - 6.0.0
19
+
20
+ | Library | Min Version |
21
+ | ----------------------------------------------------------------------- | ----------- |
22
+ | `@autorest/core` | `3.8.1` |
23
+ | `@autorest/modelerfour` | `4.23.5` |
24
+ | `azure-core` dep of generated code | `1.24.0` |
25
+ | `isodate` dep of generated code | `0.6.1` |
26
+ | `msrest` dep of generated code (If generating legacy code) | `0.7.1` |
27
+ | `azure-mgmt-core` dep of generated code (If generating mgmt plane code) | `1.3.0` |
28
+
29
+ **Breaking Changes**
30
+
31
+ - Don't generate paging variables `maxpagesize` for DPG generations. Users should pass in `maxpagesize` to the `by_page` method of their
32
+ pager #1320
33
+
34
+ ### 2022-06-17 - 6.0.0-rc.1
35
+
36
+ | Library | Min Version |
37
+ | ----------------------------------------------------------------------- | ----------- |
38
+ | `@autorest/core` | `3.8.1` |
39
+ | `@autorest/modelerfour` | `4.23.5` |
40
+ | `azure-core` dep of generated code | `1.24.0` |
41
+ | `isodate` dep of generated code | `0.6.1` |
42
+ | `msrest` dep of generated code (If generating legacy code) | `0.7.1` |
43
+ | `azure-mgmt-core` dep of generated code (If generating mgmt plane code) | `1.3.0` |
44
+
45
+ **Breaking Changes**
46
+
47
+ - Default to generating DPG SDKs with `--version-tolerant` now defaulting to `true`. For a list of flag default changes, please
48
+ see [here](https://github.com/Azure/autorest.python/issues/1186) #1304
49
+ - Only generate Python3 SDKs #1297
50
+ - Don't reformat initial query parameters into the next link. However, we do append `api-version` parameters if they are not present in the next link #1297 #1309
51
+ - Don't generate operations with more than two body types. SDK authors need to implement this operation themselves #1300
52
+
53
+ **New Features**
54
+
55
+ - Automatically format generated code with `black`. To not format, pass in `--black=false` #1304
56
+
57
+ **Other**
58
+
59
+ - Remove testing support for `--low-level-client` SDKs #1303
60
+
61
+ ### 2022-06-13 - 5.19.0
4
62
 
5
63
  | Library | Min Version |
6
64
  | ----------------------------------------------------------------------- | ----------- |
@@ -11,9 +69,10 @@
11
69
  | `azure-mgmt-core` dep of generated code (If generating mgmt plane code) | `1.3.0` |
12
70
 
13
71
  **New Features**
72
+
14
73
  - Add _serialization.py for `--client-side-validation=false` generation, and migrate serilization from msrest to _serialization.py #1236
15
74
 
16
- ### 2022-07-13 - 5.18.0
75
+ ### 2022-06-09 - 5.18.0
17
76
 
18
77
  | Library | Min Version |
19
78
  | ----------------------------------------------------------------------- | ----------- |
package/README.md CHANGED
@@ -23,6 +23,15 @@ contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additio
23
23
 
24
24
  #### Python code gen
25
25
 
26
+ ```yaml !$(multiapiscript)
27
+ # default values for version tolerant and black
28
+ black: true
29
+ ```
30
+
31
+ ```yaml !$(low-level-client)
32
+ version-tolerant: true
33
+ ```
34
+
26
35
  ```yaml !$(low-level-client) && !$(version-tolerant)
27
36
  modelerfour:
28
37
  group-parameters: true
@@ -4,8 +4,9 @@
4
4
  # license information.
5
5
  # --------------------------------------------------------------------------
6
6
  import logging
7
+ from pathlib import Path
7
8
  from abc import ABC, abstractmethod
8
- from typing import Any, Dict
9
+ from typing import Any, Dict, Union
9
10
 
10
11
  import yaml
11
12
 
@@ -17,14 +18,40 @@ __version__ = VERSION
17
18
  _LOGGER = logging.getLogger(__name__)
18
19
 
19
20
 
20
- class Plugin(ABC):
21
+ class ReaderAndWriter:
22
+ def __init__(self, **kwargs: Any) -> None:
23
+ pass
24
+
25
+ def read_file(self, path: Union[str, Path]) -> str:
26
+ """How does one read a file in cadl?"""
27
+ raise NotImplementedError("Haven't plugged in Cadl yet")
28
+
29
+ def write_file(self, filename: Union[str, Path], file_content: str) -> None:
30
+ """How does writing work in cadl?"""
31
+ raise NotImplementedError("Haven't plugged in Cadl yet")
32
+
33
+
34
+ class ReaderAndWriterAutorest(ReaderAndWriter):
35
+ def __init__(self, *, autorestapi: AutorestAPI) -> None:
36
+ super().__init__()
37
+ self._autorestapi = autorestapi
38
+
39
+ def read_file(self, path: Union[str, Path]) -> str:
40
+ return self._autorestapi.read_file(path)
41
+
42
+ def write_file(self, filename: Union[str, Path], file_content: str) -> None:
43
+ return self._autorestapi.write_file(filename, file_content)
44
+
45
+
46
+ class Plugin(ReaderAndWriter, ABC):
21
47
  """A base class for autorest plugin.
22
48
 
23
49
  :param autorestapi: An autorest API instance
24
50
  """
25
51
 
26
- def __init__(self, autorestapi: AutorestAPI) -> None:
27
- self._autorestapi = autorestapi
52
+ def __init__(self, **kwargs: Any) -> None:
53
+ super().__init__(**kwargs)
54
+ self.options: Dict[str, Any] = {}
28
55
 
29
56
  @abstractmethod
30
57
  def process(self) -> bool:
@@ -37,24 +64,30 @@ class Plugin(ABC):
37
64
  raise NotImplementedError()
38
65
 
39
66
 
67
+ class PluginAutorest(Plugin, ReaderAndWriterAutorest):
68
+ """For our Autorest plugins, we want to take autorest api as input as options, then pass it to the Plugin"""
69
+
70
+ def __init__(self, autorestapi: AutorestAPI) -> None:
71
+ super().__init__(autorestapi=autorestapi)
72
+ self.options = self.get_options()
73
+
74
+ @abstractmethod
75
+ def get_options(self) -> Dict[str, Any]:
76
+ """Get the options bag using the AutorestAPI that we send to the parent plugin"""
77
+
78
+
40
79
  class YamlUpdatePlugin(Plugin):
41
80
  """A plugin that update the YAML as input."""
42
81
 
43
82
  def process(self) -> bool:
44
83
  # List the input file, should be only one
45
- inputs = self._autorestapi.list_inputs()
46
- _LOGGER.debug("Possible Inputs: %s", inputs)
47
- if "code-model-v4-no-tags.yaml" not in inputs:
48
- raise ValueError("code-model-v4-no-tags.yaml must be a possible input")
49
-
50
- file_content = self._autorestapi.read_file("code-model-v4-no-tags.yaml")
51
- yaml_data = yaml.safe_load(file_content)
84
+ yaml_data = yaml.safe_load(self.read_file("code-model-v4-no-tags.yaml"))
52
85
 
53
86
  self.update_yaml(yaml_data)
54
87
 
55
88
  yaml_string = yaml.safe_dump(yaml_data)
56
89
 
57
- self._autorestapi.write_file("code-model-v4-no-tags.yaml", yaml_string)
90
+ self.write_file("code-model-v4-no-tags.yaml", yaml_string)
58
91
  return True
59
92
 
60
93
  @abstractmethod
@@ -67,4 +100,12 @@ class YamlUpdatePlugin(Plugin):
67
100
  raise NotImplementedError()
68
101
 
69
102
 
70
- __all__ = ["Plugin", "YamlUpdatePlugin"]
103
+ class YamlUpdatePluginAutorest( # pylint: disable=abstract-method
104
+ YamlUpdatePlugin, PluginAutorest
105
+ ):
106
+ def get_options(self) -> Dict[str, Any]:
107
+ inputs = self._autorestapi.list_inputs()
108
+ _LOGGER.debug("Possible Inputs: %s", inputs)
109
+ if "code-model-v4-no-tags.yaml" not in inputs:
110
+ raise ValueError("code-model-v4-no-tags.yaml must be a possible input")
111
+ return {}
@@ -6,9 +6,10 @@
6
6
  import logging
7
7
  from pathlib import Path
8
8
  import os
9
+ from typing import Any, Dict
9
10
  import black
10
11
 
11
- from .. import Plugin
12
+ from .. import Plugin, PluginAutorest
12
13
 
13
14
  _LOGGER = logging.getLogger(__name__)
14
15
 
@@ -16,10 +17,10 @@ _BLACK_MODE = black.Mode()
16
17
  _BLACK_MODE.line_length = 120
17
18
 
18
19
 
19
- class BlackScriptPlugin(Plugin):
20
- def __init__(self, autorestapi):
21
- super().__init__(autorestapi)
22
- output_folder_uri = self._autorestapi.get_value("outputFolderUri")
20
+ class BlackScriptPlugin(Plugin): # pylint: disable=abstract-method
21
+ def __init__(self, **kwargs):
22
+ super().__init__(**kwargs)
23
+ output_folder_uri = self.options["outputFolderUri"]
23
24
  if output_folder_uri.startswith("file:"):
24
25
  output_folder_uri = output_folder_uri[5:]
25
26
  if os.name == "nt" and output_folder_uri.startswith("///"):
@@ -38,9 +39,9 @@ class BlackScriptPlugin(Plugin):
38
39
 
39
40
  def format_file(self, full_path) -> None:
40
41
  file = full_path.relative_to(self.output_folder)
41
- file_content = self._autorestapi.read_file(file)
42
+ file_content = self.read_file(file)
42
43
  if not file.suffix == ".py":
43
- self._autorestapi.write_file(file, file_content)
44
+ self.write_file(file, file_content)
44
45
  return
45
46
  try:
46
47
  file_content = black.format_file_contents(
@@ -48,4 +49,9 @@ class BlackScriptPlugin(Plugin):
48
49
  )
49
50
  except black.NothingChanged:
50
51
  pass
51
- self._autorestapi.write_file(file, file_content)
52
+ self.write_file(file, file_content)
53
+
54
+
55
+ class BlackScriptPluginAutorest(BlackScriptPlugin, PluginAutorest):
56
+ def get_options(self) -> Dict[str, Any]:
57
+ return {"outputFolderUri": self._autorestapi.get_value("outputFolderUri")}
@@ -10,13 +10,13 @@ from pathlib import Path
10
10
  import yaml
11
11
 
12
12
 
13
- from .. import Plugin
13
+ from .. import Plugin, PluginAutorest
14
14
  from .models.client import Client, Config
15
15
  from .models.code_model import CodeModel
16
16
  from .models import build_type
17
17
  from .models.request_builder import get_request_builder
18
18
  from .models.operation_group import OperationGroup
19
- from .serializers import JinjaSerializer
19
+ from .serializers import JinjaSerializer, JinjaSerializerAutorest
20
20
 
21
21
 
22
22
  def _build_convenience_layer(yaml_data: Dict[str, Any], code_model: CodeModel) -> None:
@@ -57,13 +57,6 @@ def _validate_code_model_options(options: Dict[str, Any]) -> None:
57
57
  "to 'public' or 'hidden'."
58
58
  )
59
59
 
60
- if not options["show_operations"] and options["add_python3_operation_files"]:
61
- raise ValueError(
62
- "Can not add typed sync operation files if you are not showing operations. "
63
- "If you want typed synced operation files, you have to add flag "
64
- "--show-operations"
65
- )
66
-
67
60
  if options["basic_setup_py"] and not options["package_version"]:
68
61
  raise ValueError("--basic-setup-py must be used with --package-version")
69
62
 
@@ -85,12 +78,6 @@ def _validate_code_model_options(options: Dict[str, Any]) -> None:
85
78
  "--package-mode can only be 'mgmtplane' or 'dataplane' or directory which contains template files"
86
79
  )
87
80
 
88
- if options["reformat_next_link"] and options["version_tolerant"]:
89
- raise ValueError(
90
- "--reformat-next-link can not be true for version tolerant generations. "
91
- "Please remove --reformat-next-link from your call for version tolerant generations."
92
- )
93
-
94
81
  if options["multiapi"] and options["version_tolerant"]:
95
82
  raise ValueError(
96
83
  "Can not currently generate version tolerant multiapi SDKs. "
@@ -136,7 +123,7 @@ class CodeGenerator(Plugin):
136
123
  return {
137
124
  "dependency_azure_mgmt_core": "azure-mgmt-core<2.0.0,>=1.3.0",
138
125
  "dependency_azure_core": "azure-core<2.0.0,>=1.24.0",
139
- "dependency_msrest": "msrest>=0.7.0",
126
+ "dependency_msrest": "msrest>=0.7.1",
140
127
  }
141
128
 
142
129
  def _create_code_model(
@@ -175,8 +162,8 @@ class CodeGenerator(Plugin):
175
162
 
176
163
  def _build_code_model_options(self) -> Dict[str, Any]:
177
164
  """Build en options dict from the user input while running autorest."""
178
- azure_arm = self._autorestapi.get_boolean_value("azure-arm", False)
179
- license_header = self._autorestapi.get_value("header-text")
165
+ azure_arm = self.options.get("azure-arm", False)
166
+ license_header = self.options["header-text"]
180
167
  if license_header:
181
168
  license_header = license_header.replace("\n", "\n# ")
182
169
  license_header = (
@@ -185,84 +172,49 @@ class CodeGenerator(Plugin):
185
172
  )
186
173
  license_header += "\n# --------------------------------------------------------------------------"
187
174
 
188
- low_level_client = cast(
189
- bool, self._autorestapi.get_boolean_value("low-level-client", False)
190
- )
191
- version_tolerant = cast(
192
- bool, self._autorestapi.get_boolean_value("version-tolerant", False)
193
- )
194
- show_operations = self._autorestapi.get_boolean_value(
195
- "show-operations", not low_level_client
196
- )
175
+ low_level_client = cast(bool, self.options.get("low-level-client", False))
176
+ version_tolerant = cast(bool, self.options.get("version-tolerant", True))
177
+ show_operations = self.options.get("show-operations", not low_level_client)
197
178
  models_mode_default = (
198
179
  "none" if low_level_client or version_tolerant else "msrest"
199
180
  )
200
- python3_only = cast(
201
- bool,
202
- self._autorestapi.get_boolean_value(
203
- "python3-only", low_level_client or version_tolerant
204
- ),
205
- )
206
181
 
207
182
  options: Dict[str, Any] = {
208
183
  "azure_arm": azure_arm,
209
- "head_as_boolean": self._autorestapi.get_boolean_value(
210
- "head-as-boolean", False
211
- ),
184
+ "head_as_boolean": self.options.get("head-as-boolean", True),
212
185
  "license_header": license_header,
213
- "keep_version_file": self._autorestapi.get_boolean_value(
214
- "keep-version-file", False
215
- ),
216
- "no_async": self._autorestapi.get_boolean_value("no-async", False),
217
- "no_namespace_folders": self._autorestapi.get_boolean_value(
218
- "no-namespace-folders", False
219
- ),
220
- "basic_setup_py": self._autorestapi.get_boolean_value(
221
- "basic-setup-py", False
222
- ),
223
- "package_name": self._autorestapi.get_value("package-name"),
224
- "package_version": self._autorestapi.get_value("package-version"),
225
- "client_side_validation": self._autorestapi.get_boolean_value(
226
- "client-side-validation", False
227
- ),
228
- "tracing": self._autorestapi.get_boolean_value("trace", show_operations),
229
- "multiapi": self._autorestapi.get_boolean_value("multiapi", False),
230
- "polymorphic_examples": self._autorestapi.get_value("polymorphic-examples")
231
- or 5,
232
- "models_mode": (
233
- self._autorestapi.get_value("models-mode") or models_mode_default
234
- ).lower(),
235
- "builders_visibility": self._autorestapi.get_value("builders-visibility"),
186
+ "keep_version_file": self.options.get("keep-version-file", False),
187
+ "no_async": self.options.get("no-async", False),
188
+ "no_namespace_folders": self.options.get("no-namespace-folders", False),
189
+ "basic_setup_py": self.options.get("basic-setup-py", False),
190
+ "package_name": self.options.get("package-name"),
191
+ "package_version": self.options.get("package-version"),
192
+ "client_side_validation": self.options.get("client-side-validation", False),
193
+ "tracing": self.options.get("tracing", show_operations),
194
+ "multiapi": self.options.get("multiapi", False),
195
+ "polymorphic_examples": self.options.get("polymorphic-examples", 5),
196
+ "models_mode": self.options.get("models-mode", models_mode_default).lower(),
197
+ "builders_visibility": self.options.get("builders-visibility"),
236
198
  "show_operations": show_operations,
237
- "show_send_request": self._autorestapi.get_boolean_value(
199
+ "show_send_request": self.options.get(
238
200
  "show-send-request", low_level_client or version_tolerant
239
201
  ),
240
- "only_path_and_body_params_positional": self._autorestapi.get_boolean_value(
202
+ "only_path_and_body_params_positional": self.options.get(
241
203
  "only-path-and-body-params-positional",
242
204
  low_level_client or version_tolerant,
243
205
  ),
244
- "add_python3_operation_files": self._autorestapi.get_boolean_value(
245
- "add-python3-operation-files",
246
- python3_only and not (low_level_client or version_tolerant),
247
- ),
248
206
  "version_tolerant": version_tolerant,
249
207
  "low_level_client": low_level_client,
250
- "combine_operation_files": self._autorestapi.get_boolean_value(
208
+ "combine_operation_files": self.options.get(
251
209
  "combine-operation-files", version_tolerant
252
210
  ),
253
- "python3_only": python3_only,
254
- "package_mode": self._autorestapi.get_value("package-mode"),
255
- "package_pprint_name": self._autorestapi.get_value("package-pprint-name"),
256
- "package_configuration": self._autorestapi.get_value(
257
- "package-configuration"
258
- ),
259
- "default_optional_constants_to_none": self._autorestapi.get_boolean_value(
211
+ "package_mode": self.options.get("package-mode"),
212
+ "package_pprint_name": self.options.get("package-pprint-name"),
213
+ "package_configuration": self.options.get("package-configuration"),
214
+ "default_optional_constants_to_none": self.options.get(
260
215
  "default-optional-constants-to-none",
261
216
  low_level_client or version_tolerant,
262
217
  ),
263
- "reformat_next_link": self._autorestapi.get_boolean_value(
264
- "reformat-next-link", not version_tolerant
265
- ),
266
218
  }
267
219
 
268
220
  if options["builders_visibility"] is None:
@@ -283,8 +235,102 @@ class CodeGenerator(Plugin):
283
235
  options["head_as_boolean"] = True
284
236
  return options
285
237
 
238
+ def get_yaml(self) -> Dict[str, Any]:
239
+ # cadl should call this one
240
+ raise NotImplementedError()
241
+
242
+ @staticmethod
243
+ def get_serializer(code_model: CodeModel):
244
+ return JinjaSerializer(code_model)
245
+
286
246
  def process(self) -> bool:
287
247
  # List the input file, should be only one
248
+
249
+ options = self._build_code_model_options()
250
+ yaml_data = self.get_yaml()
251
+
252
+ if options["azure_arm"]:
253
+ self.remove_cloud_errors(yaml_data)
254
+
255
+ code_model = self._create_code_model(yaml_data=yaml_data, options=options)
256
+
257
+ serializer = self.get_serializer(code_model)
258
+ serializer.serialize()
259
+
260
+ return True
261
+
262
+
263
+ class CodeGeneratorAutorest(CodeGenerator, PluginAutorest):
264
+ def get_options(self) -> Dict[str, Any]:
265
+ if self._autorestapi.get_boolean_value("python3-only") is False:
266
+ _LOGGER.warning(
267
+ "You have passed in --python3-only=False. We have force overriden "
268
+ "this to True."
269
+ )
270
+ if self._autorestapi.get_boolean_value("add-python3-operation-files"):
271
+ _LOGGER.warning(
272
+ "You have passed in --add-python3-operation-files. "
273
+ "This flag no longer has an effect bc all SDKs are now Python3 only."
274
+ )
275
+ if self._autorestapi.get_boolean_value("reformat-next-link"):
276
+ _LOGGER.warning(
277
+ "You have passed in --reformat-next-link. We have force overriden "
278
+ "this to False because we no longer reformat initial query parameters into next "
279
+ "calls unless explicitly defined in the service definition."
280
+ )
281
+ options = {
282
+ "azure-arm": self._autorestapi.get_boolean_value("azure-arm"),
283
+ "header-text": self._autorestapi.get_value("header-text"),
284
+ "low-level-client": self._autorestapi.get_boolean_value(
285
+ "low-level-client", False
286
+ ),
287
+ "version-tolerant": self._autorestapi.get_boolean_value(
288
+ "version-tolerant", True
289
+ ),
290
+ "show-operations": self._autorestapi.get_boolean_value("show-operations"),
291
+ "python3-only": self._autorestapi.get_boolean_value("python3-only"),
292
+ "head-as-boolean": self._autorestapi.get_boolean_value(
293
+ "head-as-boolean", False
294
+ ),
295
+ "keep-version-file": self._autorestapi.get_boolean_value(
296
+ "keep-version-file"
297
+ ),
298
+ "no-async": self._autorestapi.get_boolean_value("no-async"),
299
+ "no-namespace-folders": self._autorestapi.get_boolean_value(
300
+ "no-namespace-folders"
301
+ ),
302
+ "basic-setup-py": self._autorestapi.get_boolean_value("basic-setup-py"),
303
+ "package-name": self._autorestapi.get_value("package-name"),
304
+ "package-version": self._autorestapi.get_value("package-version"),
305
+ "client-side-validation": self._autorestapi.get_boolean_value(
306
+ "client-side-validation"
307
+ ),
308
+ "tracing": self._autorestapi.get_boolean_value("trace"),
309
+ "multiapi": self._autorestapi.get_boolean_value("multiapi", False),
310
+ "polymorphic-examples": self._autorestapi.get_value("polymorphic-examples"),
311
+ "models-mode": self._autorestapi.get_value("models-mode"),
312
+ "builders-visibility": self._autorestapi.get_value("builders-visibility"),
313
+ "show-send-request": self._autorestapi.get_boolean_value(
314
+ "show-send-request"
315
+ ),
316
+ "only-path-and-body-params-positional": self._autorestapi.get_boolean_value(
317
+ "only-path-and-body-params-positional"
318
+ ),
319
+ "combine-operation-files": self._autorestapi.get_boolean_value(
320
+ "combine-operation-files"
321
+ ),
322
+ "package-mode": self._autorestapi.get_value("package-mode"),
323
+ "package-pprint-name": self._autorestapi.get_value("package-pprint-name"),
324
+ "package-configuration": self._autorestapi.get_value(
325
+ "package-configuration"
326
+ ),
327
+ "default-optional-constants-to-none": self._autorestapi.get_boolean_value(
328
+ "default-optional-constants-to-none"
329
+ ),
330
+ }
331
+ return {k: v for k, v in options.items() if v is not None}
332
+
333
+ def get_yaml(self) -> Dict[str, Any]:
288
334
  inputs = self._autorestapi.list_inputs()
289
335
  _LOGGER.debug("Possible Inputs: %s", inputs)
290
336
  if "code-model-v4-no-tags.yaml" not in inputs:
@@ -302,19 +348,10 @@ class CodeGenerator(Plugin):
302
348
  file_content = self._autorestapi.read_file("code-model-v4-no-tags.yaml")
303
349
 
304
350
  # Parse the received YAML
305
- yaml_data = yaml.safe_load(file_content)
306
-
307
- options = self._build_code_model_options()
351
+ return yaml.safe_load(file_content)
308
352
 
309
- if options["azure_arm"]:
310
- self.remove_cloud_errors(yaml_data)
311
-
312
- code_model = self._create_code_model(yaml_data=yaml_data, options=options)
313
-
314
- serializer = JinjaSerializer(self._autorestapi, code_model)
315
- serializer.serialize()
316
-
317
- return True
353
+ def get_serializer(self, code_model: CodeModel): # type: ignore
354
+ return JinjaSerializerAutorest(self._autorestapi, code_model)
318
355
 
319
356
 
320
357
  def main(yaml_model_file: str) -> None:
@@ -322,7 +359,7 @@ def main(yaml_model_file: str) -> None:
322
359
  LocalAutorestAPI,
323
360
  )
324
361
 
325
- code_generator = CodeGenerator(
362
+ code_generator = CodeGeneratorAutorest(
326
363
  autorestapi=LocalAutorestAPI(reachable_files=[yaml_model_file])
327
364
  )
328
365
  if not code_generator.process():
@@ -3,6 +3,7 @@
3
3
  # Licensed under the MIT License. See License.txt in the project root for
4
4
  # license information.
5
5
  # --------------------------------------------------------------------------
6
+ import logging
6
7
  from abc import abstractmethod
7
8
  from typing import Any, Dict, List, Optional, TypeVar, Union, TYPE_CHECKING, Generic
8
9
  from .base_model import BaseModel
@@ -27,6 +28,8 @@ if TYPE_CHECKING:
27
28
  from .operation import Operation
28
29
  from .request_builder import RequestBuilder
29
30
 
31
+ _LOGGER = logging.getLogger(__name__)
32
+
30
33
 
31
34
  class BaseBuilder(Generic[ParameterListType], BaseModel):
32
35
  """Base class for Operations and Request Builders"""
@@ -39,7 +42,6 @@ class BaseBuilder(Generic[ParameterListType], BaseModel):
39
42
  parameters: ParameterListType,
40
43
  *,
41
44
  overloads=None,
42
- abstract: bool = False,
43
45
  want_tracing: bool = True,
44
46
  ) -> None:
45
47
  super().__init__(yaml_data=yaml_data, code_model=code_model)
@@ -50,14 +52,23 @@ class BaseBuilder(Generic[ParameterListType], BaseModel):
50
52
  overloads or []
51
53
  )
52
54
  self._summary: str = yaml_data.get("summary", "")
53
- # for operations where we don't know what to do, we mark them as abstract so users implement
54
- # in patch.py
55
- self.abstract = abstract
56
55
  self.want_tracing = want_tracing
57
56
  self.group_name: str = yaml_data["groupName"]
58
57
  self.is_overload: bool = yaml_data["isOverload"]
59
58
  self.api_versions: List[str] = yaml_data["apiVersions"]
60
59
 
60
+ if code_model.options["version_tolerant"] and yaml_data.get("abstract"):
61
+ _LOGGER.warning(
62
+ 'Not going to generate operation "%s" because we are unable to generate this '
63
+ "type of operation right now. "
64
+ 'Please write your own custom operation in the "_patch.py" file '
65
+ "following https://aka.ms/azsdk/python/dpcodegen/python/customize",
66
+ name,
67
+ )
68
+ self.abstract = True
69
+ else:
70
+ self.abstract = False
71
+
61
72
  @property
62
73
  def summary(self) -> Optional[str]:
63
74
  if self.abstract:
@@ -89,7 +100,7 @@ class BaseBuilder(Generic[ParameterListType], BaseModel):
89
100
  )
90
101
  return self._description or self.name
91
102
 
92
- def method_signature(self, is_python3_file: bool, async_mode: bool) -> List[str]:
103
+ def method_signature(self, async_mode: bool) -> List[str]:
93
104
  if self.abstract:
94
105
  return ["*args,", "**kwargs"]
95
- return self.parameters.method_signature(is_python3_file, async_mode)
106
+ return self.parameters.method_signature(async_mode)
@@ -159,7 +159,7 @@ class Client(_ClientConfigBase[ClientGlobalParameterList]):
159
159
  # Also in this case, we're in version tolerant, so python3 only is true
160
160
  file_import.add_submodule_import(
161
161
  f"{path_to_models}models",
162
- f"{self.code_model.get_models_filename(is_python3_file=True)}",
162
+ self.code_model.models_filename,
163
163
  ImportType.LOCAL,
164
164
  alias="models",
165
165
  )
@@ -235,11 +235,7 @@ class CodeModel: # pylint: disable=too-many-instance-attributes, too-many-publi
235
235
  @property
236
236
  def need_mixin_abc(self) -> bool:
237
237
  """Do we want a mixin ABC class for typing purposes?"""
238
- return any(
239
- o
240
- for o in self.operation_groups
241
- if o.is_mixin and self.options["python3_only"]
242
- )
238
+ return any(o for o in self.operation_groups if o.is_mixin)
243
239
 
244
240
  @property
245
241
  def has_lro_operations(self) -> bool:
@@ -252,20 +248,19 @@ class CodeModel: # pylint: disable=too-many-instance-attributes, too-many-publi
252
248
  ]
253
249
  )
254
250
 
255
- def get_models_filename(self, is_python3_file: bool) -> str:
251
+ @property
252
+ def models_filename(self) -> str:
256
253
  """Get the names of the model file(s)"""
257
- if not self.is_legacy and self.options["python3_only"]:
258
- return "_models"
259
- if is_python3_file:
254
+ if self.is_legacy:
260
255
  return "_models_py3"
261
256
  return "_models"
262
257
 
263
258
  @property
264
259
  def enums_filename(self) -> str:
265
260
  """The name of the enums file"""
266
- if not self.is_legacy:
267
- return "_enums"
268
- return f"_{self.module_name}_enums"
261
+ if self.is_legacy:
262
+ return f"_{self.module_name}_enums"
263
+ return "_enums"
269
264
 
270
265
  @property
271
266
  def is_legacy(self) -> bool: