@autorest/python 6.14.3 → 6.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.
- package/autorest/__init__.py +2 -93
- package/autorest/black.py +13 -0
- package/autorest/codegen.py +117 -0
- package/autorest/m2r.py +16 -0
- package/autorest/m4reformatter/__init__.py +1 -1
- package/autorest/multiapi/__init__.py +2 -1
- package/autorest/multiapi/serializers/__init__.py +5 -3
- package/autorest/multiclient/__init__.py +2 -1
- package/autorest/postprocess.py +14 -0
- package/autorest/preprocess.py +20 -0
- package/generator/LICENSE +21 -0
- package/generator/README.md +1 -0
- package/generator/dev_requirements.txt +5 -0
- package/generator/pygen/__init__.py +107 -0
- package/generator/pygen/_version.py +7 -0
- package/{autorest/black/__init__.py → generator/pygen/black.py} +2 -7
- package/{autorest → generator/pygen}/codegen/__init__.py +7 -83
- package/{autorest → generator/pygen}/codegen/models/client.py +2 -1
- package/{autorest → generator/pygen}/codegen/models/combined_type.py +1 -1
- package/{autorest → generator/pygen}/codegen/models/model_type.py +1 -1
- package/{autorest → generator/pygen}/codegen/models/operation.py +2 -0
- package/{autorest → generator/pygen}/codegen/models/operation_group.py +1 -1
- package/{autorest → generator/pygen}/codegen/serializers/__init__.py +16 -30
- package/{autorest → generator/pygen}/codegen/serializers/builder_serializer.py +37 -18
- package/{autorest → generator/pygen}/codegen/serializers/client_serializer.py +1 -1
- package/{autorest → generator/pygen}/codegen/serializers/operations_init_serializer.py +1 -1
- package/{autorest → generator/pygen}/codegen/serializers/parameter_serializer.py +1 -1
- package/{autorest → generator/pygen}/codegen/serializers/sample_serializer.py +2 -2
- package/{autorest → generator/pygen}/codegen/serializers/test_serializer.py +48 -24
- package/{autorest → generator/pygen}/codegen/templates/conftest.py.jinja2 +1 -1
- package/{autorest → generator/pygen}/codegen/templates/request_builder.py.jinja2 +2 -2
- package/generator/pygen/codegen/templates/test.py.jinja2 +50 -0
- package/{autorest/m2r/__init__.py → generator/pygen/m2r.py} +5 -10
- package/{autorest → generator/pygen}/postprocess/__init__.py +1 -6
- package/{autorest → generator/pygen}/preprocess/__init__.py +12 -16
- package/{autorest → generator/pygen}/preprocess/python_mappings.py +6 -4
- package/{autorest/_utils.py → generator/pygen/utils.py} +4 -0
- package/generator/pygen.egg-info/PKG-INFO +25 -0
- package/generator/pygen.egg-info/SOURCES.txt +66 -0
- package/generator/pygen.egg-info/dependency_links.txt +1 -0
- package/generator/pygen.egg-info/requires.txt +4 -0
- package/generator/pygen.egg-info/top_level.txt +1 -0
- package/generator/requirements.txt +12 -0
- package/generator/setup.py +55 -0
- package/package.json +11 -12
- package/requirements.txt +1 -1
- package/scripts/__pycache__/venvtools.cpython-38.pyc +0 -0
- package/scripts/copy-generator.js +19 -0
- package/{install.py → scripts/install.py} +3 -5
- package/{prepare.py → scripts/prepare.py} +7 -4
- package/{start.py → scripts/start.py} +1 -1
- package/{venvtools.py → scripts/venvtools.py} +1 -1
- package/autorest/codegen/templates/test.py.jinja2 +0 -26
- package/run_cadl.py +0 -40
- /package/{autorest → generator/pygen}/codegen/_utils.py +0 -0
- /package/{autorest → generator/pygen}/codegen/models/__init__.py +0 -0
- /package/{autorest → generator/pygen}/codegen/models/base.py +0 -0
- /package/{autorest → generator/pygen}/codegen/models/base_builder.py +0 -0
- /package/{autorest → generator/pygen}/codegen/models/code_model.py +0 -0
- /package/{autorest → generator/pygen}/codegen/models/constant_type.py +0 -0
- /package/{autorest → generator/pygen}/codegen/models/credential_types.py +0 -0
- /package/{autorest → generator/pygen}/codegen/models/dictionary_type.py +0 -0
- /package/{autorest → generator/pygen}/codegen/models/enum_type.py +0 -0
- /package/{autorest → generator/pygen}/codegen/models/imports.py +0 -0
- /package/{autorest → generator/pygen}/codegen/models/list_type.py +0 -0
- /package/{autorest → generator/pygen}/codegen/models/lro_operation.py +0 -0
- /package/{autorest → generator/pygen}/codegen/models/lro_paging_operation.py +0 -0
- /package/{autorest → generator/pygen}/codegen/models/paging_operation.py +0 -0
- /package/{autorest → generator/pygen}/codegen/models/parameter.py +0 -0
- /package/{autorest → generator/pygen}/codegen/models/parameter_list.py +0 -0
- /package/{autorest → generator/pygen}/codegen/models/primitive_types.py +0 -0
- /package/{autorest → generator/pygen}/codegen/models/property.py +0 -0
- /package/{autorest → generator/pygen}/codegen/models/request_builder.py +0 -0
- /package/{autorest → generator/pygen}/codegen/models/request_builder_parameter.py +0 -0
- /package/{autorest → generator/pygen}/codegen/models/response.py +0 -0
- /package/{autorest → generator/pygen}/codegen/models/utils.py +0 -0
- /package/{autorest → generator/pygen}/codegen/serializers/base_serializer.py +0 -0
- /package/{autorest → generator/pygen}/codegen/serializers/enum_serializer.py +0 -0
- /package/{autorest → generator/pygen}/codegen/serializers/general_serializer.py +0 -0
- /package/{autorest → generator/pygen}/codegen/serializers/import_serializer.py +0 -0
- /package/{autorest → generator/pygen}/codegen/serializers/metadata_serializer.py +0 -0
- /package/{autorest → generator/pygen}/codegen/serializers/model_init_serializer.py +0 -0
- /package/{autorest → generator/pygen}/codegen/serializers/model_serializer.py +0 -0
- /package/{autorest → generator/pygen}/codegen/serializers/operation_groups_serializer.py +0 -0
- /package/{autorest → generator/pygen}/codegen/serializers/patch_serializer.py +0 -0
- /package/{autorest → generator/pygen}/codegen/serializers/request_builders_serializer.py +0 -0
- /package/{autorest → generator/pygen}/codegen/serializers/types_serializer.py +0 -0
- /package/{autorest → generator/pygen}/codegen/serializers/utils.py +0 -0
- /package/{autorest → generator/pygen}/codegen/templates/client.py.jinja2 +0 -0
- /package/{autorest → generator/pygen}/codegen/templates/client_container.py.jinja2 +0 -0
- /package/{autorest → generator/pygen}/codegen/templates/config.py.jinja2 +0 -0
- /package/{autorest → generator/pygen}/codegen/templates/config_container.py.jinja2 +0 -0
- /package/{autorest → generator/pygen}/codegen/templates/enum.py.jinja2 +0 -0
- /package/{autorest → generator/pygen}/codegen/templates/enum_container.py.jinja2 +0 -0
- /package/{autorest → generator/pygen}/codegen/templates/init.py.jinja2 +0 -0
- /package/{autorest → generator/pygen}/codegen/templates/keywords.jinja2 +0 -0
- /package/{autorest → generator/pygen}/codegen/templates/lro_operation.py.jinja2 +0 -0
- /package/{autorest → generator/pygen}/codegen/templates/lro_paging_operation.py.jinja2 +0 -0
- /package/{autorest → generator/pygen}/codegen/templates/macros.jinja2 +0 -0
- /package/{autorest → generator/pygen}/codegen/templates/metadata.json.jinja2 +0 -0
- /package/{autorest → generator/pygen}/codegen/templates/model_base.py.jinja2 +0 -0
- /package/{autorest → generator/pygen}/codegen/templates/model_container.py.jinja2 +0 -0
- /package/{autorest → generator/pygen}/codegen/templates/model_dpg.py.jinja2 +0 -0
- /package/{autorest → generator/pygen}/codegen/templates/model_init.py.jinja2 +0 -0
- /package/{autorest → generator/pygen}/codegen/templates/model_msrest.py.jinja2 +0 -0
- /package/{autorest → generator/pygen}/codegen/templates/operation.py.jinja2 +0 -0
- /package/{autorest → generator/pygen}/codegen/templates/operation_group.py.jinja2 +0 -0
- /package/{autorest → generator/pygen}/codegen/templates/operation_groups_container.py.jinja2 +0 -0
- /package/{autorest → generator/pygen}/codegen/templates/operation_tools.jinja2 +0 -0
- /package/{autorest → generator/pygen}/codegen/templates/operations_folder_init.py.jinja2 +0 -0
- /package/{autorest → generator/pygen}/codegen/templates/packaging_templates/CHANGELOG.md.jinja2 +0 -0
- /package/{autorest → generator/pygen}/codegen/templates/packaging_templates/LICENSE.jinja2 +0 -0
- /package/{autorest → generator/pygen}/codegen/templates/packaging_templates/MANIFEST.in.jinja2 +0 -0
- /package/{autorest → generator/pygen}/codegen/templates/packaging_templates/README.md.jinja2 +0 -0
- /package/{autorest → generator/pygen}/codegen/templates/packaging_templates/dev_requirements.txt.jinja2 +0 -0
- /package/{autorest → generator/pygen}/codegen/templates/packaging_templates/setup.py.jinja2 +0 -0
- /package/{autorest → generator/pygen}/codegen/templates/paging_operation.py.jinja2 +0 -0
- /package/{autorest → generator/pygen}/codegen/templates/patch.py.jinja2 +0 -0
- /package/{autorest → generator/pygen}/codegen/templates/pkgutil_init.py.jinja2 +0 -0
- /package/{autorest → generator/pygen}/codegen/templates/request_builders.py.jinja2 +0 -0
- /package/{autorest → generator/pygen}/codegen/templates/rest_init.py.jinja2 +0 -0
- /package/{autorest → generator/pygen}/codegen/templates/sample.py.jinja2 +0 -0
- /package/{autorest → generator/pygen}/codegen/templates/serialization.py.jinja2 +0 -0
- /package/{autorest → generator/pygen}/codegen/templates/testpreparer.py.jinja2 +0 -0
- /package/{autorest → generator/pygen}/codegen/templates/types.py.jinja2 +0 -0
- /package/{autorest → generator/pygen}/codegen/templates/validation.py.jinja2 +0 -0
- /package/{autorest → generator/pygen}/codegen/templates/vendor.py.jinja2 +0 -0
- /package/{autorest → generator/pygen}/codegen/templates/version.py.jinja2 +0 -0
- /package/{autorest → generator/pygen}/postprocess/get_all.py +0 -0
- /package/{autorest → generator/pygen}/postprocess/venvtools.py +0 -0
- /package/{autorest → generator/pygen}/preprocess/helpers.py +0 -0
- /package/{run-python3.js → scripts/run-python3.js} +0 -0
|
@@ -18,6 +18,7 @@ from .request_builder import (
|
|
|
18
18
|
from .parameter import Parameter, ParameterMethodLocation
|
|
19
19
|
from .lro_operation import LROOperation
|
|
20
20
|
from .lro_paging_operation import LROPagingOperation
|
|
21
|
+
from ...utils import extract_original_name
|
|
21
22
|
|
|
22
23
|
ParameterListType = TypeVar(
|
|
23
24
|
"ParameterListType",
|
|
@@ -92,7 +93,7 @@ class Client(_ClientConfigBase[ClientGlobalParameterList]):
|
|
|
92
93
|
if operation_yaml.get("isLroInitialOperation"):
|
|
93
94
|
# we want to change the name
|
|
94
95
|
request_builder.name = request_builder.get_name(
|
|
95
|
-
request_builder.yaml_data["name"]
|
|
96
|
+
extract_original_name(request_builder.yaml_data["name"]),
|
|
96
97
|
request_builder.yaml_data,
|
|
97
98
|
request_builder.code_model,
|
|
98
99
|
request_builder.client,
|
|
@@ -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
|
|
8
|
+
from .imports import FileImport, ImportType, TypingSection
|
|
9
9
|
from .base import BaseType
|
|
10
10
|
from .model_type import ModelType
|
|
11
11
|
|
|
@@ -343,6 +343,8 @@ class OperationBase( # pylint: disable=too-many-public-methods,too-many-instanc
|
|
|
343
343
|
"ResourceExistsError",
|
|
344
344
|
"ResourceNotModifiedError",
|
|
345
345
|
]
|
|
346
|
+
if self.stream_value:
|
|
347
|
+
errors.extend(["StreamConsumedError", "StreamClosedError"])
|
|
346
348
|
for error in errors:
|
|
347
349
|
file_import.add_submodule_import("exceptions", error, ImportType.SDKCORE)
|
|
348
350
|
if self.code_model.options["azure_arm"]:
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
# --------------------------------------------------------------------------
|
|
6
6
|
from typing import Dict, List, Any, TYPE_CHECKING
|
|
7
7
|
|
|
8
|
-
from
|
|
8
|
+
from .utils import OrderedSet
|
|
9
9
|
|
|
10
10
|
from .base import BaseModel
|
|
11
11
|
from .operation import get_operation
|
|
@@ -8,8 +8,7 @@ from typing import List, Optional, Any, Union
|
|
|
8
8
|
from pathlib import Path
|
|
9
9
|
from jinja2 import PackageLoader, Environment, FileSystemLoader, StrictUndefined
|
|
10
10
|
|
|
11
|
-
from ... import ReaderAndWriter
|
|
12
|
-
from ...jsonrpc import AutorestAPI
|
|
11
|
+
from ... import ReaderAndWriter
|
|
13
12
|
from ..models import (
|
|
14
13
|
OperationGroup,
|
|
15
14
|
RequestBuilder,
|
|
@@ -29,7 +28,7 @@ from .patch_serializer import PatchSerializer
|
|
|
29
28
|
from .sample_serializer import SampleSerializer
|
|
30
29
|
from .test_serializer import TestSerializer, TestGeneralSerializer
|
|
31
30
|
from .types_serializer import TypesSerializer
|
|
32
|
-
from ...
|
|
31
|
+
from ...utils import to_snake_case
|
|
33
32
|
from .._utils import VALID_PACKAGE_MODE
|
|
34
33
|
from .utils import (
|
|
35
34
|
extract_sample_name,
|
|
@@ -132,13 +131,12 @@ class JinjaSerializer(ReaderAndWriter): # pylint: disable=abstract-method
|
|
|
132
131
|
self.code_model.options["show_operations"]
|
|
133
132
|
and self.code_model.has_operations
|
|
134
133
|
and self.code_model.options["generate_test"]
|
|
135
|
-
and not self.code_model.options["azure_arm"]
|
|
136
134
|
):
|
|
137
135
|
self._serialize_and_write_test(env, namespace_path)
|
|
138
136
|
|
|
139
137
|
def serialize(self) -> None:
|
|
140
138
|
env = Environment(
|
|
141
|
-
loader=PackageLoader("
|
|
139
|
+
loader=PackageLoader("pygen.codegen", "templates"),
|
|
142
140
|
keep_trailing_newline=True,
|
|
143
141
|
line_statement_prefix="##",
|
|
144
142
|
line_comment_prefix="###",
|
|
@@ -196,7 +194,7 @@ class JinjaSerializer(ReaderAndWriter): # pylint: disable=abstract-method
|
|
|
196
194
|
root_of_sdk = self._package_root_folder(namespace_path)
|
|
197
195
|
if self.code_model.options["package_mode"] in VALID_PACKAGE_MODE:
|
|
198
196
|
env = Environment(
|
|
199
|
-
loader=PackageLoader("
|
|
197
|
+
loader=PackageLoader("pygen.codegen", "templates/packaging_templates"),
|
|
200
198
|
undefined=StrictUndefined,
|
|
201
199
|
)
|
|
202
200
|
|
|
@@ -546,16 +544,21 @@ class JinjaSerializer(ReaderAndWriter): # pylint: disable=abstract-method
|
|
|
546
544
|
out_path = self._package_root_folder(namespace_path) / Path("generated_tests")
|
|
547
545
|
general_serializer = TestGeneralSerializer(code_model=self.code_model, env=env)
|
|
548
546
|
self.write_file(out_path / "conftest.py", general_serializer.serialize_conftest())
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
547
|
+
if not self.code_model.options["azure_arm"]:
|
|
548
|
+
for is_async in (True, False):
|
|
549
|
+
async_suffix = "_async" if is_async else ""
|
|
550
|
+
general_serializer.is_async = is_async
|
|
551
|
+
self.write_file(
|
|
552
|
+
out_path / f"testpreparer{async_suffix}.py",
|
|
553
|
+
general_serializer.serialize_testpreparer(),
|
|
554
|
+
)
|
|
556
555
|
|
|
557
556
|
for client in self.code_model.clients:
|
|
558
557
|
for og in client.operation_groups:
|
|
558
|
+
if self.code_model.options["multiapi"] and any(
|
|
559
|
+
o.api_versions[0] != self.code_model.options["default_api_version"] for o in og.operations
|
|
560
|
+
):
|
|
561
|
+
continue
|
|
559
562
|
test_serializer = TestSerializer(self.code_model, env, client=client, operation_group=og)
|
|
560
563
|
for is_async in (True, False):
|
|
561
564
|
try:
|
|
@@ -569,20 +572,3 @@ class JinjaSerializer(ReaderAndWriter): # pylint: disable=abstract-method
|
|
|
569
572
|
log_error = f"error happens in test generation for operation group {og.class_name}: {e}"
|
|
570
573
|
_LOGGER.error(log_error)
|
|
571
574
|
self.code_model.for_test = False
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
class JinjaSerializerAutorest(JinjaSerializer, ReaderAndWriterAutorest):
|
|
575
|
-
def __init__(
|
|
576
|
-
self,
|
|
577
|
-
autorestapi: AutorestAPI,
|
|
578
|
-
code_model: CodeModel,
|
|
579
|
-
*,
|
|
580
|
-
output_folder: Union[str, Path],
|
|
581
|
-
**kwargs: Any,
|
|
582
|
-
) -> None:
|
|
583
|
-
super().__init__(
|
|
584
|
-
autorestapi=autorestapi,
|
|
585
|
-
code_model=code_model,
|
|
586
|
-
output_folder=output_folder,
|
|
587
|
-
**kwargs,
|
|
588
|
-
)
|
|
@@ -36,7 +36,7 @@ from ..models import (
|
|
|
36
36
|
from .parameter_serializer import ParameterSerializer, PopKwargType
|
|
37
37
|
from ..models.parameter_list import ParameterType
|
|
38
38
|
from . import utils
|
|
39
|
-
from ...
|
|
39
|
+
from ...utils import JSON_REGEXP
|
|
40
40
|
|
|
41
41
|
T = TypeVar("T")
|
|
42
42
|
OrderedSet = Dict[T, None]
|
|
@@ -410,14 +410,19 @@ class RequestBuilderSerializer(_BuilderBaseSerializer[RequestBuilderType]): # p
|
|
|
410
410
|
return "response.json()"
|
|
411
411
|
|
|
412
412
|
@staticmethod
|
|
413
|
-
def
|
|
413
|
+
def declare_non_inputtable_headers_queries(builder: RequestBuilderType) -> List[str]:
|
|
414
414
|
def _get_value(param):
|
|
415
|
+
declaration = param.get_declaration() if param.constant else None
|
|
415
416
|
if param.location in [ParameterLocation.HEADER, ParameterLocation.QUERY]:
|
|
416
417
|
kwarg_dict = "headers" if param.location == ParameterLocation.HEADER else "params"
|
|
417
|
-
return f"_{kwarg_dict}.pop('{param.wire_name}', {
|
|
418
|
-
return
|
|
418
|
+
return f"_{kwarg_dict}.pop('{param.wire_name}', {declaration})"
|
|
419
|
+
return declaration
|
|
419
420
|
|
|
420
|
-
return [
|
|
421
|
+
return [
|
|
422
|
+
f"{p.client_name} = {_get_value(p)}"
|
|
423
|
+
for p in (builder.parameters.headers + builder.parameters.query)
|
|
424
|
+
if not p.in_method_signature
|
|
425
|
+
]
|
|
421
426
|
|
|
422
427
|
@property
|
|
423
428
|
def _function_def(self) -> str:
|
|
@@ -561,16 +566,22 @@ class _OperationSerializer(_BuilderBaseSerializer[OperationType]): # pylint: di
|
|
|
561
566
|
return retval
|
|
562
567
|
|
|
563
568
|
def make_pipeline_call(self, builder: OperationType) -> List[str]:
|
|
569
|
+
retval = []
|
|
564
570
|
type_ignore = self.async_mode and builder.group_name == "" # is in a mixin
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
571
|
+
if builder.stream_value is True and not self.code_model.options["version_tolerant"]:
|
|
572
|
+
retval.append("_decompress = kwargs.pop('decompress', True)")
|
|
573
|
+
retval.extend(
|
|
574
|
+
[
|
|
575
|
+
f"_stream = {builder.stream_value}",
|
|
576
|
+
f"pipeline_response: PipelineResponse = {self._call_method}self._client.{self.pipeline_name}.run( "
|
|
577
|
+
+ f"{'# type: ignore' if type_ignore else ''} # pylint: disable=protected-access",
|
|
578
|
+
" _request,",
|
|
579
|
+
" stream=_stream,",
|
|
580
|
+
" **kwargs",
|
|
581
|
+
")",
|
|
582
|
+
]
|
|
583
|
+
)
|
|
584
|
+
return retval
|
|
574
585
|
|
|
575
586
|
@property
|
|
576
587
|
def _function_def(self) -> str:
|
|
@@ -913,7 +924,9 @@ class _OperationSerializer(_BuilderBaseSerializer[OperationType]): # pylint: di
|
|
|
913
924
|
if self.code_model.options["version_tolerant"]:
|
|
914
925
|
deserialized = "response.iter_bytes()"
|
|
915
926
|
else:
|
|
916
|
-
deserialized =
|
|
927
|
+
deserialized = (
|
|
928
|
+
f"response.stream_download(self._client.{self.pipeline_name}, decompress=_decompress)"
|
|
929
|
+
)
|
|
917
930
|
deserialize_code.append(f"deserialized = {deserialized}")
|
|
918
931
|
elif response.type:
|
|
919
932
|
pylint_disable = ""
|
|
@@ -961,11 +974,17 @@ class _OperationSerializer(_BuilderBaseSerializer[OperationType]): # pylint: di
|
|
|
961
974
|
def handle_error_response(self, builder: OperationType) -> List[str]:
|
|
962
975
|
async_await = "await " if self.async_mode else ""
|
|
963
976
|
retval = [f"if response.status_code not in {str(builder.success_status_codes)}:"]
|
|
964
|
-
response_read =
|
|
977
|
+
response_read = [
|
|
978
|
+
" try:",
|
|
979
|
+
f" {async_await}response.read() # Load the body in memory and close the socket",
|
|
980
|
+
" except (StreamConsumedError, StreamClosedError):",
|
|
981
|
+
" pass",
|
|
982
|
+
]
|
|
965
983
|
if builder.stream_value is True: # _stream is True so no need to judge it
|
|
966
|
-
retval.
|
|
984
|
+
retval.extend(response_read)
|
|
967
985
|
elif isinstance(builder.stream_value, str): # _stream is not sure, so we need to judge it
|
|
968
|
-
retval.
|
|
986
|
+
retval.append(" if _stream:")
|
|
987
|
+
retval.extend([f" {l}" for l in response_read])
|
|
969
988
|
type_ignore = " # type: ignore" if _need_type_ignore(builder) else ""
|
|
970
989
|
retval.append(
|
|
971
990
|
f" map_error(status_code=response.status_code, response=response, error_map=error_map){type_ignore}"
|
|
@@ -8,7 +8,7 @@ from typing import List
|
|
|
8
8
|
from . import utils
|
|
9
9
|
from ..models import Client, ParameterMethodLocation
|
|
10
10
|
from .parameter_serializer import ParameterSerializer, PopKwargType
|
|
11
|
-
from ...
|
|
11
|
+
from ...utils import build_policies
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
class ClientSerializer:
|
|
@@ -148,7 +148,7 @@ class ParameterSerializer:
|
|
|
148
148
|
param.wire_name,
|
|
149
149
|
ParameterSerializer.serialize_parameter(param, serializer_name),
|
|
150
150
|
)
|
|
151
|
-
if not param.optional:
|
|
151
|
+
if not param.optional and (param.in_method_signature or param.constant):
|
|
152
152
|
retval = [set_parameter]
|
|
153
153
|
else:
|
|
154
154
|
retval = [
|
|
@@ -8,7 +8,7 @@ import logging
|
|
|
8
8
|
from typing import Dict, Any, Union, Tuple
|
|
9
9
|
from jinja2 import Environment
|
|
10
10
|
|
|
11
|
-
from
|
|
11
|
+
from ..models.operation import OperationBase
|
|
12
12
|
from .import_serializer import FileImportSerializer
|
|
13
13
|
from .base_serializer import BaseSerializer
|
|
14
14
|
from ..models import (
|
|
@@ -22,7 +22,7 @@ from ..models import (
|
|
|
22
22
|
FileImport,
|
|
23
23
|
)
|
|
24
24
|
from .utils import get_namespace_config, get_namespace_from_package_name
|
|
25
|
-
from ...
|
|
25
|
+
from ...utils import to_snake_case
|
|
26
26
|
|
|
27
27
|
_LOGGER = logging.getLogger(__name__)
|
|
28
28
|
|
|
@@ -18,12 +18,26 @@ from ..models import (
|
|
|
18
18
|
ModelType,
|
|
19
19
|
BaseType,
|
|
20
20
|
CombinedType,
|
|
21
|
+
FileImport,
|
|
21
22
|
)
|
|
22
23
|
from .utils import get_namespace_from_package_name, json_dumps_template
|
|
23
24
|
|
|
24
25
|
|
|
26
|
+
def is_lro(operation_type: str) -> bool:
|
|
27
|
+
return operation_type in ("lro", "lropaging")
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def is_paging(operation_type: str) -> bool:
|
|
31
|
+
return operation_type in ("paging", "lropaging")
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def is_common_operation(operation_type: str) -> bool:
|
|
35
|
+
return operation_type == "operation"
|
|
36
|
+
|
|
37
|
+
|
|
25
38
|
class TestName:
|
|
26
|
-
def __init__(self, client_name: str, *, is_async: bool = False) -> None:
|
|
39
|
+
def __init__(self, code_model: CodeModel, client_name: str, *, is_async: bool = False) -> None:
|
|
40
|
+
self.code_model = code_model
|
|
27
41
|
self.client_name = client_name
|
|
28
42
|
self.is_async = is_async
|
|
29
43
|
|
|
@@ -41,10 +55,14 @@ class TestName:
|
|
|
41
55
|
|
|
42
56
|
@property
|
|
43
57
|
def preparer_name(self) -> str:
|
|
58
|
+
if self.code_model.options["azure_arm"]:
|
|
59
|
+
return "RandomNameResourceGroupPreparer"
|
|
44
60
|
return self.prefix + "Preparer"
|
|
45
61
|
|
|
46
62
|
@property
|
|
47
63
|
def base_test_class_name(self) -> str:
|
|
64
|
+
if self.code_model.options["azure_arm"]:
|
|
65
|
+
return "AzureMgmtRecordedTestCase"
|
|
48
66
|
return f"{self.client_name}TestBase{self.async_suffix_capt}"
|
|
49
67
|
|
|
50
68
|
|
|
@@ -71,40 +89,35 @@ class TestCase:
|
|
|
71
89
|
@property
|
|
72
90
|
def response(self) -> str:
|
|
73
91
|
if self.is_async:
|
|
74
|
-
if self.operation.operation_type
|
|
92
|
+
if is_lro(self.operation.operation_type):
|
|
75
93
|
return "response = await (await "
|
|
76
|
-
|
|
94
|
+
if is_common_operation(self.operation.operation_type):
|
|
95
|
+
return "response = await "
|
|
77
96
|
return "response = "
|
|
78
97
|
|
|
79
98
|
@property
|
|
80
99
|
def lro_comment(self) -> str:
|
|
81
|
-
return " # poll until service return final result"
|
|
100
|
+
return " # call '.result()' to poll until service return final result"
|
|
82
101
|
|
|
83
102
|
@property
|
|
84
103
|
def operation_suffix(self) -> str:
|
|
85
|
-
if self.operation.operation_type
|
|
104
|
+
if is_lro(self.operation.operation_type):
|
|
86
105
|
extra = ")" if self.is_async else ""
|
|
87
106
|
return f"{extra}.result(){self.lro_comment}"
|
|
88
107
|
return ""
|
|
89
108
|
|
|
90
109
|
@property
|
|
91
110
|
def extra_operation(self) -> str:
|
|
92
|
-
if self.
|
|
93
|
-
if self.
|
|
94
|
-
|
|
95
|
-
if self.operation.operation_type == ("lropaging", "paging"):
|
|
96
|
-
return "result = [r async for r in response]"
|
|
97
|
-
else:
|
|
98
|
-
if self.operation.operation_type == "lro":
|
|
99
|
-
return f"result = response.result(){self.lro_comment}"
|
|
100
|
-
if self.operation.operation_type in ("lropaging", "paging"):
|
|
101
|
-
return "result = [r for r in response]"
|
|
111
|
+
if is_paging(self.operation.operation_type):
|
|
112
|
+
async_str = "async " if self.is_async else ""
|
|
113
|
+
return f"result = [r {async_str}for r in response]"
|
|
102
114
|
return ""
|
|
103
115
|
|
|
104
116
|
|
|
105
117
|
class Test(TestName):
|
|
106
118
|
def __init__(
|
|
107
119
|
self,
|
|
120
|
+
code_model: CodeModel,
|
|
108
121
|
client_name: str,
|
|
109
122
|
operation_group: OperationGroup,
|
|
110
123
|
testcases: List[TestCase],
|
|
@@ -112,7 +125,7 @@ class Test(TestName):
|
|
|
112
125
|
*,
|
|
113
126
|
is_async: bool = False,
|
|
114
127
|
) -> None:
|
|
115
|
-
super().__init__(client_name, is_async=is_async)
|
|
128
|
+
super().__init__(code_model, client_name, is_async=is_async)
|
|
116
129
|
self.operation_group = operation_group
|
|
117
130
|
self.testcases = testcases
|
|
118
131
|
self.test_class_name = test_class_name
|
|
@@ -129,19 +142,23 @@ class TestGeneralSerializer(BaseSerializer):
|
|
|
129
142
|
|
|
130
143
|
@property
|
|
131
144
|
def test_names(self) -> List[TestName]:
|
|
132
|
-
return [TestName(c.name, is_async=self.is_async) for c in self.code_model.clients]
|
|
145
|
+
return [TestName(self.code_model, c.name, is_async=self.is_async) for c in self.code_model.clients]
|
|
146
|
+
|
|
147
|
+
def add_import_client(self, imports: FileImport) -> None:
|
|
148
|
+
namespace = get_namespace_from_package_name(self.code_model.options["package_name"])
|
|
149
|
+
for client in self.code_model.clients:
|
|
150
|
+
imports.add_submodule_import(namespace + self.aio_str, client.name, ImportType.STDLIB)
|
|
133
151
|
|
|
134
152
|
@property
|
|
135
153
|
def import_clients(self) -> FileImportSerializer:
|
|
136
154
|
imports = self.init_file_import()
|
|
137
|
-
namespace = get_namespace_from_package_name(self.code_model.options["package_name"])
|
|
138
155
|
|
|
139
156
|
imports.add_submodule_import("devtools_testutils", "AzureRecordedTestCase", ImportType.STDLIB)
|
|
140
157
|
if not self.is_async:
|
|
141
158
|
imports.add_import("functools", ImportType.STDLIB)
|
|
142
159
|
imports.add_submodule_import("devtools_testutils", "PowerShellPreparer", ImportType.STDLIB)
|
|
143
|
-
|
|
144
|
-
|
|
160
|
+
self.add_import_client(imports)
|
|
161
|
+
|
|
145
162
|
return FileImportSerializer(imports, self.is_async)
|
|
146
163
|
|
|
147
164
|
def serialize_conftest(self) -> str:
|
|
@@ -175,19 +192,25 @@ class TestSerializer(TestGeneralSerializer):
|
|
|
175
192
|
@property
|
|
176
193
|
def import_test(self) -> FileImportSerializer:
|
|
177
194
|
imports = self.init_file_import()
|
|
178
|
-
test_name = TestName(self.client.name, is_async=self.is_async)
|
|
195
|
+
test_name = TestName(self.code_model, self.client.name, is_async=self.is_async)
|
|
179
196
|
async_suffix = "_async" if self.is_async else ""
|
|
180
197
|
imports.add_submodule_import(
|
|
181
|
-
"testpreparer" + async_suffix,
|
|
198
|
+
"devtools_testutils" if self.code_model.options["azure_arm"] else "testpreparer" + async_suffix,
|
|
182
199
|
test_name.base_test_class_name,
|
|
183
200
|
ImportType.LOCAL,
|
|
184
201
|
)
|
|
185
|
-
imports.add_submodule_import(
|
|
202
|
+
imports.add_submodule_import(
|
|
203
|
+
"devtools_testutils" if self.code_model.options["azure_arm"] else "testpreparer",
|
|
204
|
+
test_name.preparer_name,
|
|
205
|
+
ImportType.LOCAL,
|
|
206
|
+
)
|
|
186
207
|
imports.add_submodule_import(
|
|
187
208
|
"devtools_testutils" + self.aio_str,
|
|
188
209
|
"recorded_by_proxy" + async_suffix,
|
|
189
210
|
ImportType.LOCAL,
|
|
190
211
|
)
|
|
212
|
+
if self.code_model.options["azure_arm"]:
|
|
213
|
+
self.add_import_client(imports)
|
|
191
214
|
return FileImportSerializer(imports, self.is_async)
|
|
192
215
|
|
|
193
216
|
@property
|
|
@@ -242,6 +265,7 @@ class TestSerializer(TestGeneralSerializer):
|
|
|
242
265
|
raise Exception("no public operation to test") # pylint: disable=broad-exception-raised
|
|
243
266
|
|
|
244
267
|
return Test(
|
|
268
|
+
code_model=self.code_model,
|
|
245
269
|
client_name=self.client.name,
|
|
246
270
|
operation_group=self.operation_group,
|
|
247
271
|
testcases=testcases,
|
|
@@ -251,7 +275,7 @@ class TestSerializer(TestGeneralSerializer):
|
|
|
251
275
|
|
|
252
276
|
@property
|
|
253
277
|
def test_class_name(self) -> str:
|
|
254
|
-
test_name = TestName(self.client.name, is_async=self.is_async)
|
|
278
|
+
test_name = TestName(self.code_model, self.client.name, is_async=self.is_async)
|
|
255
279
|
class_name = "" if self.operation_group.is_mixin else self.operation_group.class_name
|
|
256
280
|
return f"Test{test_name.prefix}{class_name}{test_name.async_suffix_capt}"
|
|
257
281
|
|
|
@@ -11,7 +11,7 @@ load_dotenv()
|
|
|
11
11
|
@pytest.fixture(scope="session", autouse=True)
|
|
12
12
|
def add_sanitizers(test_proxy):
|
|
13
13
|
{% for test_name in test_names %}
|
|
14
|
-
{% set prefix_upper = test_name.prefix|upper %}
|
|
14
|
+
{% set prefix_upper = "AZURE" if code_model.options["azure_arm"] else test_name.prefix|upper %}
|
|
15
15
|
{% set prefix_lower = test_name.prefix|lower %}
|
|
16
16
|
{{ prefix_lower }}_subscription_id = os.environ.get("{{ prefix_upper }}_SUBSCRIPTION_ID", "00000000-0000-0000-0000-000000000000")
|
|
17
17
|
{{ prefix_lower }}_tenant_id = os.environ.get("{{ prefix_upper }}_TENANT_ID", "00000000-0000-0000-0000-000000000000")
|
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
{% if request_builder_serializer.pop_kwargs_from_signature(request_builder) %}
|
|
9
9
|
{{ op_tools.serialize(request_builder_serializer.pop_kwargs_from_signature(request_builder)) | indent }}
|
|
10
10
|
{%- endif -%}
|
|
11
|
-
{% if request_builder_serializer.
|
|
12
|
-
{{ op_tools.serialize(request_builder_serializer.
|
|
11
|
+
{% if request_builder_serializer.declare_non_inputtable_headers_queries(request_builder) %}
|
|
12
|
+
{{ op_tools.serialize(request_builder_serializer.declare_non_inputtable_headers_queries(request_builder)) | indent }}
|
|
13
13
|
{% endif %}
|
|
14
14
|
# Construct URL
|
|
15
15
|
{{ request_builder_serializer.construct_url(request_builder) }}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{% set prefix_lower = test.prefix|lower %}
|
|
2
|
+
{% set client_var = "self.client" if code_model.options["azure_arm"] else "client" %}
|
|
3
|
+
{% set async = "async " if test.is_async else "" %}
|
|
4
|
+
{% set async_suffix = "_async" if test.is_async else "" %}
|
|
5
|
+
# coding=utf-8
|
|
6
|
+
{{ code_model.options['license_header'] }}
|
|
7
|
+
import pytest
|
|
8
|
+
{{ imports }}
|
|
9
|
+
|
|
10
|
+
{% if code_model.options["azure_arm"] %}
|
|
11
|
+
AZURE_LOCATION = "eastus"
|
|
12
|
+
{% endif %}
|
|
13
|
+
|
|
14
|
+
@pytest.mark.skip("you may need to update the auto-generated test case before run it")
|
|
15
|
+
class {{ test.test_class_name }}({{ test.base_test_class_name }}):
|
|
16
|
+
{% if code_model.options["azure_arm"] %}
|
|
17
|
+
def setup_method(self, method):
|
|
18
|
+
{% if test.is_async %}
|
|
19
|
+
self.client = self.create_mgmt_client({{ test.client_name }}, is_async=True)
|
|
20
|
+
{% else %}
|
|
21
|
+
self.client = self.create_mgmt_client({{ test.client_name }})
|
|
22
|
+
{% endif %}
|
|
23
|
+
{% endif %}
|
|
24
|
+
{% for testcase in test.testcases %}
|
|
25
|
+
{% if code_model.options["azure_arm"] %}
|
|
26
|
+
@{{ test.preparer_name }}(location=AZURE_LOCATION)
|
|
27
|
+
{% else %}
|
|
28
|
+
@{{ test.preparer_name }}()
|
|
29
|
+
{% endif %}
|
|
30
|
+
@recorded_by_proxy{{ async_suffix }}
|
|
31
|
+
{% if code_model.options["azure_arm"] %}
|
|
32
|
+
{{ async }}def test_{{ testcase.operation.name }}(self, resource_group):
|
|
33
|
+
{% else %}
|
|
34
|
+
{{ async }}def test_{{ testcase.operation.name }}(self, {{ prefix_lower }}_endpoint):
|
|
35
|
+
{{ client_var }} = self.{{ test.create_client_name }}(endpoint={{ prefix_lower }}_endpoint)
|
|
36
|
+
{% endif %}
|
|
37
|
+
{{testcase.response }}{{ client_var }}{{ testcase.operation_group_prefix }}.{{ testcase.operation.name }}(
|
|
38
|
+
{% for key, value in testcase.params.items() %}
|
|
39
|
+
{% if code_model.options["azure_arm"] and key == "resource_group_name" %}
|
|
40
|
+
{{ key }}=resource_group.name,
|
|
41
|
+
{% else %}
|
|
42
|
+
{{ key }}={{ value|indent(12) }},
|
|
43
|
+
{% endif %}
|
|
44
|
+
{% endfor %}
|
|
45
|
+
){{ testcase.operation_suffix }}
|
|
46
|
+
{{ testcase.extra_operation }}
|
|
47
|
+
# please add some check logic here by yourself
|
|
48
|
+
# ...
|
|
49
|
+
|
|
50
|
+
{% endfor %}
|
|
@@ -3,21 +3,21 @@
|
|
|
3
3
|
# Licensed under the MIT License. See License.txt in the project root for
|
|
4
4
|
# license information.
|
|
5
5
|
# --------------------------------------------------------------------------
|
|
6
|
-
"""An
|
|
6
|
+
"""An MD to RST plugin.
|
|
7
7
|
"""
|
|
8
8
|
import logging
|
|
9
9
|
from typing import Any, Dict, Set, Union
|
|
10
10
|
|
|
11
11
|
import m2r2
|
|
12
12
|
|
|
13
|
-
from
|
|
14
|
-
from
|
|
13
|
+
from . import YamlUpdatePlugin
|
|
14
|
+
from .utils import parse_args
|
|
15
15
|
|
|
16
16
|
|
|
17
17
|
_LOGGER = logging.getLogger(__name__)
|
|
18
18
|
|
|
19
19
|
|
|
20
|
-
class
|
|
20
|
+
class GeneratorRenderer(m2r2.RestRenderer):
|
|
21
21
|
"""Redefine the concept of inline HTML in the renderer, we don't want to define a new format
|
|
22
22
|
in the description/summary.
|
|
23
23
|
"""
|
|
@@ -54,16 +54,11 @@ class M2R(YamlUpdatePlugin): # pylint: disable=abstract-method
|
|
|
54
54
|
def convert_to_rst(string_to_convert: str) -> str:
|
|
55
55
|
"""Convert that string from MD to RST."""
|
|
56
56
|
try:
|
|
57
|
-
return m2r2.convert(string_to_convert, renderer=
|
|
57
|
+
return m2r2.convert(string_to_convert, renderer=GeneratorRenderer()).strip()
|
|
58
58
|
except Exception: # pylint: disable=broad-except
|
|
59
59
|
return string_to_convert
|
|
60
60
|
|
|
61
61
|
|
|
62
|
-
class M2RAutorest(YamlUpdatePluginAutorest, M2R):
|
|
63
|
-
def get_options(self) -> Dict[str, Any]:
|
|
64
|
-
return {}
|
|
65
|
-
|
|
66
|
-
|
|
67
62
|
if __name__ == "__main__":
|
|
68
63
|
# CADL pipeline will call this
|
|
69
64
|
args, unknown_args = parse_args()
|
|
@@ -12,7 +12,7 @@ import black
|
|
|
12
12
|
from black.report import NothingChanged
|
|
13
13
|
from .venvtools import ExtendedEnvBuilder, python_run
|
|
14
14
|
|
|
15
|
-
from .. import Plugin
|
|
15
|
+
from .. import Plugin
|
|
16
16
|
|
|
17
17
|
_BLACK_MODE = black.Mode() # pyright: ignore [reportPrivateImportUsage]
|
|
18
18
|
_BLACK_MODE.line_length = 120
|
|
@@ -181,8 +181,3 @@ class PostProcessPlugin(Plugin): # pylint: disable=abstract-method
|
|
|
181
181
|
file_content = file_content.replace("__all__ = [", f"__all__ = [\n{added_objs_all}", 1)
|
|
182
182
|
formatted_file = format_file(file, file_content)
|
|
183
183
|
self.write_file(file, formatted_file)
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
class PostProcessPluginAutorest(PostProcessPlugin, PluginAutorest):
|
|
187
|
-
def get_options(self) -> Dict[str, Any]:
|
|
188
|
-
return {"outputFolderUri": self._autorestapi.get_value("outputFolderUri")}
|