@autorest/python 6.14.3 → 6.15.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 (132) hide show
  1. package/autorest/__init__.py +2 -93
  2. package/autorest/black.py +13 -0
  3. package/autorest/codegen.py +117 -0
  4. package/autorest/m2r.py +16 -0
  5. package/autorest/m4reformatter/__init__.py +1 -1
  6. package/autorest/multiapi/__init__.py +2 -1
  7. package/autorest/multiapi/serializers/__init__.py +5 -3
  8. package/autorest/multiclient/__init__.py +2 -1
  9. package/autorest/postprocess.py +14 -0
  10. package/autorest/preprocess.py +20 -0
  11. package/generator/LICENSE +21 -0
  12. package/generator/README.md +1 -0
  13. package/generator/dev_requirements.txt +5 -0
  14. package/generator/pygen/__init__.py +107 -0
  15. package/generator/pygen/_version.py +7 -0
  16. package/{autorest/black/__init__.py → generator/pygen/black.py} +2 -7
  17. package/{autorest → generator/pygen}/codegen/__init__.py +3 -83
  18. package/{autorest → generator/pygen}/codegen/models/combined_type.py +1 -1
  19. package/{autorest → generator/pygen}/codegen/models/model_type.py +1 -1
  20. package/{autorest → generator/pygen}/codegen/models/operation_group.py +1 -1
  21. package/{autorest → generator/pygen}/codegen/serializers/__init__.py +12 -30
  22. package/{autorest → generator/pygen}/codegen/serializers/builder_serializer.py +1 -1
  23. package/{autorest → generator/pygen}/codegen/serializers/client_serializer.py +1 -1
  24. package/{autorest → generator/pygen}/codegen/serializers/operations_init_serializer.py +1 -1
  25. package/{autorest → generator/pygen}/codegen/serializers/sample_serializer.py +2 -2
  26. package/{autorest → generator/pygen}/codegen/serializers/test_serializer.py +48 -24
  27. package/{autorest → generator/pygen}/codegen/templates/conftest.py.jinja2 +1 -1
  28. package/generator/pygen/codegen/templates/test.py.jinja2 +50 -0
  29. package/{autorest/m2r/__init__.py → generator/pygen/m2r.py} +5 -10
  30. package/{autorest → generator/pygen}/postprocess/__init__.py +1 -6
  31. package/{autorest → generator/pygen}/preprocess/__init__.py +3 -13
  32. package/{autorest → generator/pygen}/preprocess/python_mappings.py +1 -1
  33. package/generator/pygen.egg-info/PKG-INFO +25 -0
  34. package/generator/pygen.egg-info/SOURCES.txt +66 -0
  35. package/generator/pygen.egg-info/dependency_links.txt +1 -0
  36. package/generator/pygen.egg-info/requires.txt +4 -0
  37. package/generator/pygen.egg-info/top_level.txt +1 -0
  38. package/generator/requirements.txt +12 -0
  39. package/generator/setup.py +55 -0
  40. package/package.json +11 -12
  41. package/requirements.txt +1 -1
  42. package/scripts/__pycache__/venvtools.cpython-38.pyc +0 -0
  43. package/scripts/copy-generator.js +19 -0
  44. package/{install.py → scripts/install.py} +3 -5
  45. package/{prepare.py → scripts/prepare.py} +7 -4
  46. package/{start.py → scripts/start.py} +1 -1
  47. package/{venvtools.py → scripts/venvtools.py} +1 -1
  48. package/autorest/codegen/templates/test.py.jinja2 +0 -26
  49. package/run_cadl.py +0 -40
  50. /package/{autorest → generator/pygen}/codegen/_utils.py +0 -0
  51. /package/{autorest → generator/pygen}/codegen/models/__init__.py +0 -0
  52. /package/{autorest → generator/pygen}/codegen/models/base.py +0 -0
  53. /package/{autorest → generator/pygen}/codegen/models/base_builder.py +0 -0
  54. /package/{autorest → generator/pygen}/codegen/models/client.py +0 -0
  55. /package/{autorest → generator/pygen}/codegen/models/code_model.py +0 -0
  56. /package/{autorest → generator/pygen}/codegen/models/constant_type.py +0 -0
  57. /package/{autorest → generator/pygen}/codegen/models/credential_types.py +0 -0
  58. /package/{autorest → generator/pygen}/codegen/models/dictionary_type.py +0 -0
  59. /package/{autorest → generator/pygen}/codegen/models/enum_type.py +0 -0
  60. /package/{autorest → generator/pygen}/codegen/models/imports.py +0 -0
  61. /package/{autorest → generator/pygen}/codegen/models/list_type.py +0 -0
  62. /package/{autorest → generator/pygen}/codegen/models/lro_operation.py +0 -0
  63. /package/{autorest → generator/pygen}/codegen/models/lro_paging_operation.py +0 -0
  64. /package/{autorest → generator/pygen}/codegen/models/operation.py +0 -0
  65. /package/{autorest → generator/pygen}/codegen/models/paging_operation.py +0 -0
  66. /package/{autorest → generator/pygen}/codegen/models/parameter.py +0 -0
  67. /package/{autorest → generator/pygen}/codegen/models/parameter_list.py +0 -0
  68. /package/{autorest → generator/pygen}/codegen/models/primitive_types.py +0 -0
  69. /package/{autorest → generator/pygen}/codegen/models/property.py +0 -0
  70. /package/{autorest → generator/pygen}/codegen/models/request_builder.py +0 -0
  71. /package/{autorest → generator/pygen}/codegen/models/request_builder_parameter.py +0 -0
  72. /package/{autorest → generator/pygen}/codegen/models/response.py +0 -0
  73. /package/{autorest → generator/pygen}/codegen/models/utils.py +0 -0
  74. /package/{autorest → generator/pygen}/codegen/serializers/base_serializer.py +0 -0
  75. /package/{autorest → generator/pygen}/codegen/serializers/enum_serializer.py +0 -0
  76. /package/{autorest → generator/pygen}/codegen/serializers/general_serializer.py +0 -0
  77. /package/{autorest → generator/pygen}/codegen/serializers/import_serializer.py +0 -0
  78. /package/{autorest → generator/pygen}/codegen/serializers/metadata_serializer.py +0 -0
  79. /package/{autorest → generator/pygen}/codegen/serializers/model_init_serializer.py +0 -0
  80. /package/{autorest → generator/pygen}/codegen/serializers/model_serializer.py +0 -0
  81. /package/{autorest → generator/pygen}/codegen/serializers/operation_groups_serializer.py +0 -0
  82. /package/{autorest → generator/pygen}/codegen/serializers/parameter_serializer.py +0 -0
  83. /package/{autorest → generator/pygen}/codegen/serializers/patch_serializer.py +0 -0
  84. /package/{autorest → generator/pygen}/codegen/serializers/request_builders_serializer.py +0 -0
  85. /package/{autorest → generator/pygen}/codegen/serializers/types_serializer.py +0 -0
  86. /package/{autorest → generator/pygen}/codegen/serializers/utils.py +0 -0
  87. /package/{autorest → generator/pygen}/codegen/templates/client.py.jinja2 +0 -0
  88. /package/{autorest → generator/pygen}/codegen/templates/client_container.py.jinja2 +0 -0
  89. /package/{autorest → generator/pygen}/codegen/templates/config.py.jinja2 +0 -0
  90. /package/{autorest → generator/pygen}/codegen/templates/config_container.py.jinja2 +0 -0
  91. /package/{autorest → generator/pygen}/codegen/templates/enum.py.jinja2 +0 -0
  92. /package/{autorest → generator/pygen}/codegen/templates/enum_container.py.jinja2 +0 -0
  93. /package/{autorest → generator/pygen}/codegen/templates/init.py.jinja2 +0 -0
  94. /package/{autorest → generator/pygen}/codegen/templates/keywords.jinja2 +0 -0
  95. /package/{autorest → generator/pygen}/codegen/templates/lro_operation.py.jinja2 +0 -0
  96. /package/{autorest → generator/pygen}/codegen/templates/lro_paging_operation.py.jinja2 +0 -0
  97. /package/{autorest → generator/pygen}/codegen/templates/macros.jinja2 +0 -0
  98. /package/{autorest → generator/pygen}/codegen/templates/metadata.json.jinja2 +0 -0
  99. /package/{autorest → generator/pygen}/codegen/templates/model_base.py.jinja2 +0 -0
  100. /package/{autorest → generator/pygen}/codegen/templates/model_container.py.jinja2 +0 -0
  101. /package/{autorest → generator/pygen}/codegen/templates/model_dpg.py.jinja2 +0 -0
  102. /package/{autorest → generator/pygen}/codegen/templates/model_init.py.jinja2 +0 -0
  103. /package/{autorest → generator/pygen}/codegen/templates/model_msrest.py.jinja2 +0 -0
  104. /package/{autorest → generator/pygen}/codegen/templates/operation.py.jinja2 +0 -0
  105. /package/{autorest → generator/pygen}/codegen/templates/operation_group.py.jinja2 +0 -0
  106. /package/{autorest → generator/pygen}/codegen/templates/operation_groups_container.py.jinja2 +0 -0
  107. /package/{autorest → generator/pygen}/codegen/templates/operation_tools.jinja2 +0 -0
  108. /package/{autorest → generator/pygen}/codegen/templates/operations_folder_init.py.jinja2 +0 -0
  109. /package/{autorest → generator/pygen}/codegen/templates/packaging_templates/CHANGELOG.md.jinja2 +0 -0
  110. /package/{autorest → generator/pygen}/codegen/templates/packaging_templates/LICENSE.jinja2 +0 -0
  111. /package/{autorest → generator/pygen}/codegen/templates/packaging_templates/MANIFEST.in.jinja2 +0 -0
  112. /package/{autorest → generator/pygen}/codegen/templates/packaging_templates/README.md.jinja2 +0 -0
  113. /package/{autorest → generator/pygen}/codegen/templates/packaging_templates/dev_requirements.txt.jinja2 +0 -0
  114. /package/{autorest → generator/pygen}/codegen/templates/packaging_templates/setup.py.jinja2 +0 -0
  115. /package/{autorest → generator/pygen}/codegen/templates/paging_operation.py.jinja2 +0 -0
  116. /package/{autorest → generator/pygen}/codegen/templates/patch.py.jinja2 +0 -0
  117. /package/{autorest → generator/pygen}/codegen/templates/pkgutil_init.py.jinja2 +0 -0
  118. /package/{autorest → generator/pygen}/codegen/templates/request_builder.py.jinja2 +0 -0
  119. /package/{autorest → generator/pygen}/codegen/templates/request_builders.py.jinja2 +0 -0
  120. /package/{autorest → generator/pygen}/codegen/templates/rest_init.py.jinja2 +0 -0
  121. /package/{autorest → generator/pygen}/codegen/templates/sample.py.jinja2 +0 -0
  122. /package/{autorest → generator/pygen}/codegen/templates/serialization.py.jinja2 +0 -0
  123. /package/{autorest → generator/pygen}/codegen/templates/testpreparer.py.jinja2 +0 -0
  124. /package/{autorest → generator/pygen}/codegen/templates/types.py.jinja2 +0 -0
  125. /package/{autorest → generator/pygen}/codegen/templates/validation.py.jinja2 +0 -0
  126. /package/{autorest → generator/pygen}/codegen/templates/vendor.py.jinja2 +0 -0
  127. /package/{autorest → generator/pygen}/codegen/templates/version.py.jinja2 +0 -0
  128. /package/{autorest → generator/pygen}/postprocess/get_all.py +0 -0
  129. /package/{autorest → generator/pygen}/postprocess/venvtools.py +0 -0
  130. /package/{autorest → generator/pygen}/preprocess/helpers.py +0 -0
  131. /package/{autorest/_utils.py → generator/pygen/utils.py} +0 -0
  132. /package/{run-python3.js → scripts/run-python3.js} +0 -0
@@ -5,59 +5,18 @@
5
5
  # --------------------------------------------------------------------------
6
6
  import logging
7
7
  from pathlib import Path
8
- import json
9
- from abc import ABC, abstractmethod
8
+ from abc import abstractmethod
10
9
  from typing import Any, Dict, Union, List
11
10
 
12
11
  import yaml
13
12
 
13
+ from pygen import ReaderAndWriter, Plugin, YamlUpdatePlugin
14
14
  from .jsonrpc import AutorestAPI
15
- from ._version import VERSION
16
15
 
17
16
 
18
- __version__ = VERSION
19
17
  _LOGGER = logging.getLogger(__name__)
20
18
 
21
19
 
22
- class ReaderAndWriter:
23
- def __init__(self, *, output_folder: Union[str, Path], **kwargs: Any) -> None:
24
- self.output_folder = Path(output_folder)
25
- self._list_file: List[str] = []
26
- try:
27
- with open(
28
- Path(self.output_folder) / Path("..") / Path("python.json"),
29
- "r",
30
- encoding="utf-8-sig",
31
- ) as fd:
32
- python_json = json.load(fd)
33
- except Exception: # pylint: disable=broad-except
34
- python_json = {}
35
- self.options = kwargs
36
- if python_json:
37
- _LOGGER.warning("Loading python.json file. This behavior will be depreacted")
38
- self.options.update(python_json)
39
-
40
- def read_file(self, path: Union[str, Path]) -> str:
41
- """Directly reading from disk"""
42
- # make path relative to output folder
43
- try:
44
- with open(self.output_folder / Path(path), "r", encoding="utf-8-sig") as fd:
45
- return fd.read()
46
- except FileNotFoundError:
47
- return ""
48
-
49
- def write_file(self, filename: Union[str, Path], file_content: str) -> None:
50
- """Directly writing to disk"""
51
- file_folder = Path(filename).parent
52
- if not Path.is_dir(self.output_folder / file_folder):
53
- Path.mkdir(self.output_folder / file_folder, parents=True)
54
- with open(self.output_folder / Path(filename), "w", encoding="utf-8") as fd:
55
- fd.write(file_content)
56
-
57
- def list_file(self) -> List[str]:
58
- return [str(f) for f in self.output_folder.glob("**/*") if f.is_file()]
59
-
60
-
61
20
  class ReaderAndWriterAutorest(ReaderAndWriter):
62
21
  def __init__(self, *, output_folder: Union[str, Path], autorestapi: AutorestAPI) -> None:
63
22
  super().__init__(output_folder=output_folder)
@@ -73,23 +32,6 @@ class ReaderAndWriterAutorest(ReaderAndWriter):
73
32
  return self._autorestapi.list_inputs()
74
33
 
75
34
 
76
- class Plugin(ReaderAndWriter, ABC):
77
- """A base class for autorest plugin.
78
-
79
- :param autorestapi: An autorest API instance
80
- """
81
-
82
- @abstractmethod
83
- def process(self) -> bool:
84
- """The plugin process.
85
-
86
- :rtype: bool
87
- :returns: True if everything's ok, False optherwise
88
- :raises Exception: Could raise any exception, stacktrace will be sent to autorest API
89
- """
90
- raise NotImplementedError()
91
-
92
-
93
35
  class PluginAutorest(Plugin, ReaderAndWriterAutorest):
94
36
  """For our Autorest plugins, we want to take autorest api as input as options, then pass it to the Plugin"""
95
37
 
@@ -102,39 +44,6 @@ class PluginAutorest(Plugin, ReaderAndWriterAutorest):
102
44
  """Get the options bag using the AutorestAPI that we send to the parent plugin"""
103
45
 
104
46
 
105
- class YamlUpdatePlugin(Plugin):
106
- """A plugin that update the YAML as input."""
107
-
108
- def get_yaml(self) -> Dict[str, Any]:
109
- # cadl file doesn't have to be relative to output folder
110
- with open(self.options["cadl_file"], "r", encoding="utf-8-sig") as fd:
111
- return yaml.safe_load(fd.read())
112
-
113
- def write_yaml(self, yaml_string: str) -> None:
114
- with open(self.options["cadl_file"], "w", encoding="utf-8-sig") as fd:
115
- fd.write(yaml_string)
116
-
117
- def process(self) -> bool:
118
- # List the input file, should be only one
119
- yaml_data = self.get_yaml()
120
-
121
- self.update_yaml(yaml_data)
122
-
123
- yaml_string = yaml.safe_dump(yaml_data)
124
-
125
- self.write_yaml(yaml_string)
126
- return True
127
-
128
- @abstractmethod
129
- def update_yaml(self, yaml_data: Dict[str, Any]) -> None:
130
- """The code-model-v4-no-tags yaml model tree.
131
-
132
- :rtype: updated yaml
133
- :raises Exception: Could raise any exception, stacktrace will be sent to autorest API
134
- """
135
- raise NotImplementedError()
136
-
137
-
138
47
  class YamlUpdatePluginAutorest(YamlUpdatePlugin, PluginAutorest): # pylint: disable=abstract-method
139
48
  def get_yaml(self) -> Dict[str, Any]:
140
49
  return yaml.safe_load(self.read_file("code-model-v4-no-tags.yaml"))
@@ -0,0 +1,13 @@
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 Dict, Any
7
+ from pygen.black import BlackScriptPlugin
8
+ from . import PluginAutorest
9
+
10
+
11
+ class BlackScriptPluginAutorest(BlackScriptPlugin, PluginAutorest):
12
+ def get_options(self) -> Dict[str, Any]:
13
+ return {"output_folder": self._autorestapi.get_value("outputFolderUri")}
@@ -0,0 +1,117 @@
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
+ import logging
7
+ from typing import Dict, Any, Union
8
+ from pathlib import Path
9
+ import yaml
10
+
11
+ from pygen.codegen import CodeGenerator
12
+ from pygen.codegen.models import CodeModel
13
+ from pygen.codegen.serializers import JinjaSerializer
14
+
15
+ from . import ReaderAndWriterAutorest
16
+ from .jsonrpc import AutorestAPI
17
+ from . import PluginAutorest
18
+
19
+
20
+ _LOGGER = logging.getLogger(__name__)
21
+
22
+
23
+ class JinjaSerializerAutorest(JinjaSerializer, ReaderAndWriterAutorest):
24
+ def __init__(
25
+ self,
26
+ autorestapi: AutorestAPI,
27
+ code_model: CodeModel,
28
+ *,
29
+ output_folder: Union[str, Path],
30
+ **kwargs: Any,
31
+ ) -> None:
32
+ super().__init__( # type: ignore
33
+ autorestapi=autorestapi,
34
+ code_model=code_model,
35
+ output_folder=output_folder,
36
+ **kwargs,
37
+ )
38
+
39
+
40
+ class CodeGeneratorAutorest(CodeGenerator, PluginAutorest):
41
+ def get_options(self) -> Dict[str, Any]:
42
+ if self._autorestapi.get_boolean_value("python3-only") is False:
43
+ _LOGGER.warning("You have passed in --python3-only=False. We have force overriden this to True.")
44
+ if self._autorestapi.get_boolean_value("add-python3-operation-files"):
45
+ _LOGGER.warning(
46
+ "You have passed in --add-python3-operation-files. "
47
+ "This flag no longer has an effect bc all SDKs are now Python3 only."
48
+ )
49
+ if self._autorestapi.get_boolean_value("reformat-next-link"):
50
+ _LOGGER.warning(
51
+ "You have passed in --reformat-next-link. We have force overriden "
52
+ "this to False because we no longer reformat initial query parameters into next "
53
+ "calls unless explicitly defined in the service definition."
54
+ )
55
+ options = {
56
+ "azure-arm": self._autorestapi.get_boolean_value("azure-arm"),
57
+ "header-text": self._autorestapi.get_value("header-text"),
58
+ "low-level-client": self._autorestapi.get_boolean_value("low-level-client", False),
59
+ "version-tolerant": self._autorestapi.get_boolean_value("version-tolerant", True),
60
+ "show-operations": self._autorestapi.get_boolean_value("show-operations"),
61
+ "python3-only": self._autorestapi.get_boolean_value("python3-only"),
62
+ "head-as-boolean": self._autorestapi.get_boolean_value("head-as-boolean", False),
63
+ "keep-version-file": self._autorestapi.get_boolean_value("keep-version-file"),
64
+ "no-async": self._autorestapi.get_boolean_value("no-async"),
65
+ "no-namespace-folders": self._autorestapi.get_boolean_value("no-namespace-folders"),
66
+ "basic-setup-py": self._autorestapi.get_boolean_value("basic-setup-py"),
67
+ "package-name": self._autorestapi.get_value("package-name"),
68
+ "package-version": self._autorestapi.get_value("package-version"),
69
+ "client-side-validation": self._autorestapi.get_boolean_value("client-side-validation"),
70
+ "tracing": self._autorestapi.get_boolean_value("trace"),
71
+ "multiapi": self._autorestapi.get_boolean_value("multiapi", False),
72
+ "polymorphic-examples": self._autorestapi.get_value("polymorphic-examples"),
73
+ "models-mode": self._autorestapi.get_value("models-mode"),
74
+ "builders-visibility": self._autorestapi.get_value("builders-visibility"),
75
+ "show-send-request": self._autorestapi.get_boolean_value("show-send-request"),
76
+ "only-path-and-body-params-positional": self._autorestapi.get_boolean_value(
77
+ "only-path-and-body-params-positional"
78
+ ),
79
+ "combine-operation-files": self._autorestapi.get_boolean_value("combine-operation-files"),
80
+ "package-mode": self._autorestapi.get_value("package-mode"),
81
+ "package-pprint-name": self._autorestapi.get_value("package-pprint-name"),
82
+ "packaging-files-config": self._autorestapi.get_value("package-configuration"),
83
+ "default-optional-constants-to-none": self._autorestapi.get_boolean_value(
84
+ "default-optional-constants-to-none"
85
+ ),
86
+ "generate-sample": self._autorestapi.get_boolean_value("generate-sample"),
87
+ "generate-test": self._autorestapi.get_boolean_value("generate-test"),
88
+ "default-api-version": self._autorestapi.get_value("default-api-version"),
89
+ }
90
+ return {k: v for k, v in options.items() if v is not None}
91
+
92
+ def get_yaml(self) -> Dict[str, Any]:
93
+ inputs = self._autorestapi.list_inputs()
94
+ _LOGGER.debug("Possible Inputs: %s", inputs)
95
+ if "code-model-v4-no-tags.yaml" not in inputs:
96
+ raise ValueError("code-model-v4-no-tags.yaml must be a possible input")
97
+
98
+ if self._autorestapi.get_value("input-yaml"):
99
+ input_yaml = self._autorestapi.get_value("input-yaml")
100
+ file_content = self._autorestapi.read_file(input_yaml)
101
+ else:
102
+ inputs = self._autorestapi.list_inputs()
103
+ _LOGGER.debug("Possible Inputs: %s", inputs)
104
+ if "code-model-v4-no-tags.yaml" not in inputs:
105
+ raise ValueError("code-model-v4-no-tags.yaml must be a possible input")
106
+
107
+ file_content = self._autorestapi.read_file("code-model-v4-no-tags.yaml")
108
+
109
+ # Parse the received YAML
110
+ return yaml.safe_load(file_content)
111
+
112
+ def get_serializer(self, code_model: CodeModel):
113
+ return JinjaSerializerAutorest(
114
+ self._autorestapi,
115
+ code_model,
116
+ output_folder=self.output_folder,
117
+ )
@@ -0,0 +1,16 @@
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
+ """An autorest MD to RST plugin.
7
+ """
8
+ from typing import Any, Dict
9
+
10
+ from pygen.m2r import M2R
11
+ from . import YamlUpdatePluginAutorest
12
+
13
+
14
+ class M2RAutorest(YamlUpdatePluginAutorest, M2R):
15
+ def get_options(self) -> Dict[str, Any]:
16
+ return {}
@@ -11,7 +11,7 @@ import copy
11
11
  import logging
12
12
  from typing import Callable, Dict, Any, Iterable, List, Optional, Set
13
13
 
14
- from .._utils import (
14
+ from pygen.utils import (
15
15
  to_snake_case,
16
16
  KNOWN_TYPES,
17
17
  get_body_type_for_description,
@@ -10,12 +10,13 @@ import json
10
10
  from collections import defaultdict
11
11
  from pathlib import Path
12
12
  from typing import Dict, List, Optional, cast, Any
13
+ from pygen import Plugin, ReaderAndWriter
13
14
 
14
15
  from .serializers import MultiAPISerializer, MultiAPISerializerAutorest
15
16
  from .models import CodeModel
16
17
  from .utils import _get_default_api_version_from_list
17
18
 
18
- from .. import Plugin, PluginAutorest, ReaderAndWriter, ReaderAndWriterAutorest
19
+ from .. import PluginAutorest, ReaderAndWriterAutorest
19
20
 
20
21
  _LOGGER = logging.getLogger(__name__)
21
22
 
@@ -6,13 +6,15 @@
6
6
  from pathlib import Path
7
7
  from typing import Any, Optional, Union, List
8
8
  from jinja2 import PackageLoader, Environment
9
+ from pygen import ReaderAndWriter
10
+ from pygen.utils import build_policies
9
11
 
10
12
  from .import_serializer import FileImportSerializer
11
13
 
12
14
  from ...jsonrpc import AutorestAPI
13
15
  from ..models import CodeModel, GlobalParameter
14
- from ... import ReaderAndWriter, ReaderAndWriterAutorest
15
- from ..._utils import build_policies
16
+ from ... import ReaderAndWriterAutorest
17
+
16
18
 
17
19
  __all__ = [
18
20
  "MultiAPISerializer",
@@ -123,7 +125,7 @@ class MultiAPISerializer(ReaderAndWriter): # pylint: disable=abstract-method
123
125
 
124
126
  if not code_model.client.client_side_validation:
125
127
  codegen_env = Environment(
126
- loader=PackageLoader("autorest.codegen", "templates"),
128
+ loader=PackageLoader("pygen.codegen", "templates"),
127
129
  keep_trailing_newline=True,
128
130
  line_statement_prefix="##",
129
131
  line_comment_prefix="###",
@@ -7,7 +7,8 @@ import logging
7
7
  from typing import Any, Dict
8
8
  from pathlib import Path
9
9
  from jinja2 import Environment, PackageLoader
10
- from .. import Plugin, PluginAutorest
10
+ from pygen import Plugin
11
+ from .. import PluginAutorest
11
12
 
12
13
  _LOGGER = logging.getLogger(__name__)
13
14
 
@@ -0,0 +1,14 @@
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
7
+
8
+ from pygen.postprocess import PostProcessPlugin
9
+ from . import PluginAutorest
10
+
11
+
12
+ class PostProcessPluginAutorest(PostProcessPlugin, PluginAutorest):
13
+ def get_options(self) -> Dict[str, Any]:
14
+ return {"outputFolderUri": self._autorestapi.get_value("outputFolderUri")}
@@ -0,0 +1,20 @@
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
+ """The preprocessing autorest plugin.
7
+ """
8
+ from typing import Dict, Any
9
+ from pygen.preprocess import PreProcessPlugin
10
+ from . import YamlUpdatePluginAutorest
11
+
12
+
13
+ class PreProcessPluginAutorest(YamlUpdatePluginAutorest, PreProcessPlugin):
14
+ def get_options(self) -> Dict[str, Any]:
15
+ options = {
16
+ "version-tolerant": self._autorestapi.get_boolean_value("version-tolerant"),
17
+ "azure-arm": self._autorestapi.get_boolean_value("azure-arm"),
18
+ "models-mode": self._autorestapi.get_value("models-mode"),
19
+ }
20
+ return {k: v for k, v in options.items() if v is not None}
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) Microsoft Corporation. All rights reserved.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE
@@ -0,0 +1 @@
1
+ # Core Library for Python Generation
@@ -0,0 +1,5 @@
1
+ -e ./generator
2
+ -r ../../../eng/requirements.txt
3
+ -r ../../../eng/dev_requirements.txt
4
+ ptvsd==4.3.2
5
+ types-PyYAML==6.0.12.8
@@ -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
+ import logging
7
+ from pathlib import Path
8
+ import json
9
+ from abc import ABC, abstractmethod
10
+ from typing import Any, Dict, Union, List
11
+
12
+ import yaml
13
+
14
+ from ._version import VERSION
15
+
16
+
17
+ __version__ = VERSION
18
+ _LOGGER = logging.getLogger(__name__)
19
+
20
+
21
+ class ReaderAndWriter:
22
+ def __init__(self, *, output_folder: Union[str, Path], **kwargs: Any) -> None:
23
+ self.output_folder = Path(output_folder)
24
+ self._list_file: List[str] = []
25
+ try:
26
+ with open(
27
+ Path(self.output_folder) / Path("..") / Path("python.json"),
28
+ "r",
29
+ encoding="utf-8-sig",
30
+ ) as fd:
31
+ python_json = json.load(fd)
32
+ except Exception: # pylint: disable=broad-except
33
+ python_json = {}
34
+ self.options = kwargs
35
+ if python_json:
36
+ _LOGGER.warning("Loading python.json file. This behavior will be depreacted")
37
+ self.options.update(python_json)
38
+
39
+ def read_file(self, path: Union[str, Path]) -> str:
40
+ """Directly reading from disk"""
41
+ # make path relative to output folder
42
+ try:
43
+ with open(self.output_folder / Path(path), "r", encoding="utf-8-sig") as fd:
44
+ return fd.read()
45
+ except FileNotFoundError:
46
+ return ""
47
+
48
+ def write_file(self, filename: Union[str, Path], file_content: str) -> None:
49
+ """Directly writing to disk"""
50
+ file_folder = Path(filename).parent
51
+ if not Path.is_dir(self.output_folder / file_folder):
52
+ Path.mkdir(self.output_folder / file_folder, parents=True)
53
+ with open(self.output_folder / Path(filename), "w", encoding="utf-8") as fd:
54
+ fd.write(file_content)
55
+
56
+ def list_file(self) -> List[str]:
57
+ return [str(f) for f in self.output_folder.glob("**/*") if f.is_file()]
58
+
59
+
60
+ class Plugin(ReaderAndWriter, ABC):
61
+ """A base class for autorest plugin.
62
+
63
+ :param autorestapi: An autorest API instance
64
+ """
65
+
66
+ @abstractmethod
67
+ def process(self) -> bool:
68
+ """The plugin process.
69
+
70
+ :rtype: bool
71
+ :returns: True if everything's ok, False optherwise
72
+ :raises Exception: Could raise any exception, stacktrace will be sent to autorest API
73
+ """
74
+ raise NotImplementedError()
75
+
76
+
77
+ class YamlUpdatePlugin(Plugin):
78
+ """A plugin that update the YAML as input."""
79
+
80
+ def get_yaml(self) -> Dict[str, Any]:
81
+ # cadl file doesn't have to be relative to output folder
82
+ with open(self.options["cadl_file"], "r", encoding="utf-8-sig") as fd:
83
+ return yaml.safe_load(fd.read())
84
+
85
+ def write_yaml(self, yaml_string: str) -> None:
86
+ with open(self.options["cadl_file"], "w", encoding="utf-8-sig") as fd:
87
+ fd.write(yaml_string)
88
+
89
+ def process(self) -> bool:
90
+ # List the input file, should be only one
91
+ yaml_data = self.get_yaml()
92
+
93
+ self.update_yaml(yaml_data)
94
+
95
+ yaml_string = yaml.safe_dump(yaml_data)
96
+
97
+ self.write_yaml(yaml_string)
98
+ return True
99
+
100
+ @abstractmethod
101
+ def update_yaml(self, yaml_data: Dict[str, Any]) -> None:
102
+ """The code-model-v4-no-tags yaml model tree.
103
+
104
+ :rtype: updated yaml
105
+ :raises Exception: Could raise any exception, stacktrace will be sent to autorest API
106
+ """
107
+ raise NotImplementedError()
@@ -0,0 +1,7 @@
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
+
7
+ VERSION = "0.1.0"
@@ -10,8 +10,8 @@ from typing import Any, Dict
10
10
  import black
11
11
  from black.report import NothingChanged
12
12
 
13
- from .. import Plugin, PluginAutorest
14
- from .._utils import parse_args
13
+ from . import Plugin
14
+ from .utils import parse_args
15
15
 
16
16
  _LOGGER = logging.getLogger("blib2to3")
17
17
 
@@ -65,11 +65,6 @@ class BlackScriptPlugin(Plugin): # pylint: disable=abstract-method
65
65
  self.write_file(file, file_content)
66
66
 
67
67
 
68
- class BlackScriptPluginAutorest(BlackScriptPlugin, PluginAutorest):
69
- def get_options(self) -> Dict[str, Any]:
70
- return {"output_folder": self._autorestapi.get_value("outputFolderUri")}
71
-
72
-
73
68
  if __name__ == "__main__":
74
69
  # CADL pipeline will call this
75
70
  args, unknown_args = parse_args(need_cadl_file=False)
@@ -9,10 +9,10 @@ from pathlib import Path
9
9
  import yaml
10
10
 
11
11
 
12
- from .. import Plugin, PluginAutorest
13
- from .._utils import parse_args
12
+ from .. import Plugin
13
+ from ..utils import parse_args
14
14
  from .models.code_model import CodeModel
15
- from .serializers import JinjaSerializer, JinjaSerializerAutorest
15
+ from .serializers import JinjaSerializer
16
16
  from ._utils import DEFAULT_HEADER_TEXT, VALID_PACKAGE_MODE, TYPESPEC_PACKAGE_MODE
17
17
 
18
18
 
@@ -324,86 +324,6 @@ class CodeGenerator(Plugin):
324
324
  return True
325
325
 
326
326
 
327
- class CodeGeneratorAutorest(CodeGenerator, PluginAutorest):
328
- def get_options(self) -> Dict[str, Any]:
329
- if self._autorestapi.get_boolean_value("python3-only") is False:
330
- _LOGGER.warning("You have passed in --python3-only=False. We have force overriden this to True.")
331
- if self._autorestapi.get_boolean_value("add-python3-operation-files"):
332
- _LOGGER.warning(
333
- "You have passed in --add-python3-operation-files. "
334
- "This flag no longer has an effect bc all SDKs are now Python3 only."
335
- )
336
- if self._autorestapi.get_boolean_value("reformat-next-link"):
337
- _LOGGER.warning(
338
- "You have passed in --reformat-next-link. We have force overriden "
339
- "this to False because we no longer reformat initial query parameters into next "
340
- "calls unless explicitly defined in the service definition."
341
- )
342
- options = {
343
- "azure-arm": self._autorestapi.get_boolean_value("azure-arm"),
344
- "header-text": self._autorestapi.get_value("header-text"),
345
- "low-level-client": self._autorestapi.get_boolean_value("low-level-client", False),
346
- "version-tolerant": self._autorestapi.get_boolean_value("version-tolerant", True),
347
- "show-operations": self._autorestapi.get_boolean_value("show-operations"),
348
- "python3-only": self._autorestapi.get_boolean_value("python3-only"),
349
- "head-as-boolean": self._autorestapi.get_boolean_value("head-as-boolean", False),
350
- "keep-version-file": self._autorestapi.get_boolean_value("keep-version-file"),
351
- "no-async": self._autorestapi.get_boolean_value("no-async"),
352
- "no-namespace-folders": self._autorestapi.get_boolean_value("no-namespace-folders"),
353
- "basic-setup-py": self._autorestapi.get_boolean_value("basic-setup-py"),
354
- "package-name": self._autorestapi.get_value("package-name"),
355
- "package-version": self._autorestapi.get_value("package-version"),
356
- "client-side-validation": self._autorestapi.get_boolean_value("client-side-validation"),
357
- "tracing": self._autorestapi.get_boolean_value("trace"),
358
- "multiapi": self._autorestapi.get_boolean_value("multiapi", False),
359
- "polymorphic-examples": self._autorestapi.get_value("polymorphic-examples"),
360
- "models-mode": self._autorestapi.get_value("models-mode"),
361
- "builders-visibility": self._autorestapi.get_value("builders-visibility"),
362
- "show-send-request": self._autorestapi.get_boolean_value("show-send-request"),
363
- "only-path-and-body-params-positional": self._autorestapi.get_boolean_value(
364
- "only-path-and-body-params-positional"
365
- ),
366
- "combine-operation-files": self._autorestapi.get_boolean_value("combine-operation-files"),
367
- "package-mode": self._autorestapi.get_value("package-mode"),
368
- "package-pprint-name": self._autorestapi.get_value("package-pprint-name"),
369
- "packaging-files-config": self._autorestapi.get_value("package-configuration"),
370
- "default-optional-constants-to-none": self._autorestapi.get_boolean_value(
371
- "default-optional-constants-to-none"
372
- ),
373
- "generate-sample": self._autorestapi.get_boolean_value("generate-sample"),
374
- "generate-test": self._autorestapi.get_boolean_value("generate-test"),
375
- "default-api-version": self._autorestapi.get_value("default-api-version"),
376
- }
377
- return {k: v for k, v in options.items() if v is not None}
378
-
379
- def get_yaml(self) -> Dict[str, Any]:
380
- inputs = self._autorestapi.list_inputs()
381
- _LOGGER.debug("Possible Inputs: %s", inputs)
382
- if "code-model-v4-no-tags.yaml" not in inputs:
383
- raise ValueError("code-model-v4-no-tags.yaml must be a possible input")
384
-
385
- if self._autorestapi.get_value("input-yaml"):
386
- input_yaml = self._autorestapi.get_value("input-yaml")
387
- file_content = self._autorestapi.read_file(input_yaml)
388
- else:
389
- inputs = self._autorestapi.list_inputs()
390
- _LOGGER.debug("Possible Inputs: %s", inputs)
391
- if "code-model-v4-no-tags.yaml" not in inputs:
392
- raise ValueError("code-model-v4-no-tags.yaml must be a possible input")
393
-
394
- file_content = self._autorestapi.read_file("code-model-v4-no-tags.yaml")
395
-
396
- # Parse the received YAML
397
- return yaml.safe_load(file_content)
398
-
399
- def get_serializer(self, code_model: CodeModel):
400
- return JinjaSerializerAutorest(
401
- self._autorestapi,
402
- code_model,
403
- output_folder=self.output_folder,
404
- )
405
-
406
-
407
327
  if __name__ == "__main__":
408
328
  # CADL pipeline will call this
409
329
  parsed_args, unknown_args = parse_args()
@@ -5,7 +5,7 @@
5
5
  # --------------------------------------------------------------------------
6
6
  from typing import Any, Dict, List, Optional, TYPE_CHECKING, Type, Tuple, Union
7
7
  import re
8
- from autorest.codegen.models.imports import FileImport, ImportType, TypingSection
8
+ from .imports import FileImport, ImportType, TypingSection
9
9
  from .base import BaseType
10
10
  from .model_type import ModelType
11
11
 
@@ -7,7 +7,7 @@ from enum import Enum
7
7
  from collections import OrderedDict
8
8
  from typing import Any, Dict, List, Optional, TYPE_CHECKING, cast
9
9
  import sys
10
- from autorest.codegen.models.utils import (
10
+ from .utils import (
11
11
  add_to_pylint_disable,
12
12
  NAME_LENGTH_LIMIT,
13
13
  )