@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.
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 +7 -83
  18. package/{autorest → generator/pygen}/codegen/models/client.py +2 -1
  19. package/{autorest → generator/pygen}/codegen/models/combined_type.py +1 -1
  20. package/{autorest → generator/pygen}/codegen/models/model_type.py +1 -1
  21. package/{autorest → generator/pygen}/codegen/models/operation.py +2 -0
  22. package/{autorest → generator/pygen}/codegen/models/operation_group.py +1 -1
  23. package/{autorest → generator/pygen}/codegen/serializers/__init__.py +16 -30
  24. package/{autorest → generator/pygen}/codegen/serializers/builder_serializer.py +37 -18
  25. package/{autorest → generator/pygen}/codegen/serializers/client_serializer.py +1 -1
  26. package/{autorest → generator/pygen}/codegen/serializers/operations_init_serializer.py +1 -1
  27. package/{autorest → generator/pygen}/codegen/serializers/parameter_serializer.py +1 -1
  28. package/{autorest → generator/pygen}/codegen/serializers/sample_serializer.py +2 -2
  29. package/{autorest → generator/pygen}/codegen/serializers/test_serializer.py +48 -24
  30. package/{autorest → generator/pygen}/codegen/templates/conftest.py.jinja2 +1 -1
  31. package/{autorest → generator/pygen}/codegen/templates/request_builder.py.jinja2 +2 -2
  32. package/generator/pygen/codegen/templates/test.py.jinja2 +50 -0
  33. package/{autorest/m2r/__init__.py → generator/pygen/m2r.py} +5 -10
  34. package/{autorest → generator/pygen}/postprocess/__init__.py +1 -6
  35. package/{autorest → generator/pygen}/preprocess/__init__.py +12 -16
  36. package/{autorest → generator/pygen}/preprocess/python_mappings.py +6 -4
  37. package/{autorest/_utils.py → generator/pygen/utils.py} +4 -0
  38. package/generator/pygen.egg-info/PKG-INFO +25 -0
  39. package/generator/pygen.egg-info/SOURCES.txt +66 -0
  40. package/generator/pygen.egg-info/dependency_links.txt +1 -0
  41. package/generator/pygen.egg-info/requires.txt +4 -0
  42. package/generator/pygen.egg-info/top_level.txt +1 -0
  43. package/generator/requirements.txt +12 -0
  44. package/generator/setup.py +55 -0
  45. package/package.json +11 -12
  46. package/requirements.txt +1 -1
  47. package/scripts/__pycache__/venvtools.cpython-38.pyc +0 -0
  48. package/scripts/copy-generator.js +19 -0
  49. package/{install.py → scripts/install.py} +3 -5
  50. package/{prepare.py → scripts/prepare.py} +7 -4
  51. package/{start.py → scripts/start.py} +1 -1
  52. package/{venvtools.py → scripts/venvtools.py} +1 -1
  53. package/autorest/codegen/templates/test.py.jinja2 +0 -26
  54. package/run_cadl.py +0 -40
  55. /package/{autorest → generator/pygen}/codegen/_utils.py +0 -0
  56. /package/{autorest → generator/pygen}/codegen/models/__init__.py +0 -0
  57. /package/{autorest → generator/pygen}/codegen/models/base.py +0 -0
  58. /package/{autorest → generator/pygen}/codegen/models/base_builder.py +0 -0
  59. /package/{autorest → generator/pygen}/codegen/models/code_model.py +0 -0
  60. /package/{autorest → generator/pygen}/codegen/models/constant_type.py +0 -0
  61. /package/{autorest → generator/pygen}/codegen/models/credential_types.py +0 -0
  62. /package/{autorest → generator/pygen}/codegen/models/dictionary_type.py +0 -0
  63. /package/{autorest → generator/pygen}/codegen/models/enum_type.py +0 -0
  64. /package/{autorest → generator/pygen}/codegen/models/imports.py +0 -0
  65. /package/{autorest → generator/pygen}/codegen/models/list_type.py +0 -0
  66. /package/{autorest → generator/pygen}/codegen/models/lro_operation.py +0 -0
  67. /package/{autorest → generator/pygen}/codegen/models/lro_paging_operation.py +0 -0
  68. /package/{autorest → generator/pygen}/codegen/models/paging_operation.py +0 -0
  69. /package/{autorest → generator/pygen}/codegen/models/parameter.py +0 -0
  70. /package/{autorest → generator/pygen}/codegen/models/parameter_list.py +0 -0
  71. /package/{autorest → generator/pygen}/codegen/models/primitive_types.py +0 -0
  72. /package/{autorest → generator/pygen}/codegen/models/property.py +0 -0
  73. /package/{autorest → generator/pygen}/codegen/models/request_builder.py +0 -0
  74. /package/{autorest → generator/pygen}/codegen/models/request_builder_parameter.py +0 -0
  75. /package/{autorest → generator/pygen}/codegen/models/response.py +0 -0
  76. /package/{autorest → generator/pygen}/codegen/models/utils.py +0 -0
  77. /package/{autorest → generator/pygen}/codegen/serializers/base_serializer.py +0 -0
  78. /package/{autorest → generator/pygen}/codegen/serializers/enum_serializer.py +0 -0
  79. /package/{autorest → generator/pygen}/codegen/serializers/general_serializer.py +0 -0
  80. /package/{autorest → generator/pygen}/codegen/serializers/import_serializer.py +0 -0
  81. /package/{autorest → generator/pygen}/codegen/serializers/metadata_serializer.py +0 -0
  82. /package/{autorest → generator/pygen}/codegen/serializers/model_init_serializer.py +0 -0
  83. /package/{autorest → generator/pygen}/codegen/serializers/model_serializer.py +0 -0
  84. /package/{autorest → generator/pygen}/codegen/serializers/operation_groups_serializer.py +0 -0
  85. /package/{autorest → generator/pygen}/codegen/serializers/patch_serializer.py +0 -0
  86. /package/{autorest → generator/pygen}/codegen/serializers/request_builders_serializer.py +0 -0
  87. /package/{autorest → generator/pygen}/codegen/serializers/types_serializer.py +0 -0
  88. /package/{autorest → generator/pygen}/codegen/serializers/utils.py +0 -0
  89. /package/{autorest → generator/pygen}/codegen/templates/client.py.jinja2 +0 -0
  90. /package/{autorest → generator/pygen}/codegen/templates/client_container.py.jinja2 +0 -0
  91. /package/{autorest → generator/pygen}/codegen/templates/config.py.jinja2 +0 -0
  92. /package/{autorest → generator/pygen}/codegen/templates/config_container.py.jinja2 +0 -0
  93. /package/{autorest → generator/pygen}/codegen/templates/enum.py.jinja2 +0 -0
  94. /package/{autorest → generator/pygen}/codegen/templates/enum_container.py.jinja2 +0 -0
  95. /package/{autorest → generator/pygen}/codegen/templates/init.py.jinja2 +0 -0
  96. /package/{autorest → generator/pygen}/codegen/templates/keywords.jinja2 +0 -0
  97. /package/{autorest → generator/pygen}/codegen/templates/lro_operation.py.jinja2 +0 -0
  98. /package/{autorest → generator/pygen}/codegen/templates/lro_paging_operation.py.jinja2 +0 -0
  99. /package/{autorest → generator/pygen}/codegen/templates/macros.jinja2 +0 -0
  100. /package/{autorest → generator/pygen}/codegen/templates/metadata.json.jinja2 +0 -0
  101. /package/{autorest → generator/pygen}/codegen/templates/model_base.py.jinja2 +0 -0
  102. /package/{autorest → generator/pygen}/codegen/templates/model_container.py.jinja2 +0 -0
  103. /package/{autorest → generator/pygen}/codegen/templates/model_dpg.py.jinja2 +0 -0
  104. /package/{autorest → generator/pygen}/codegen/templates/model_init.py.jinja2 +0 -0
  105. /package/{autorest → generator/pygen}/codegen/templates/model_msrest.py.jinja2 +0 -0
  106. /package/{autorest → generator/pygen}/codegen/templates/operation.py.jinja2 +0 -0
  107. /package/{autorest → generator/pygen}/codegen/templates/operation_group.py.jinja2 +0 -0
  108. /package/{autorest → generator/pygen}/codegen/templates/operation_groups_container.py.jinja2 +0 -0
  109. /package/{autorest → generator/pygen}/codegen/templates/operation_tools.jinja2 +0 -0
  110. /package/{autorest → generator/pygen}/codegen/templates/operations_folder_init.py.jinja2 +0 -0
  111. /package/{autorest → generator/pygen}/codegen/templates/packaging_templates/CHANGELOG.md.jinja2 +0 -0
  112. /package/{autorest → generator/pygen}/codegen/templates/packaging_templates/LICENSE.jinja2 +0 -0
  113. /package/{autorest → generator/pygen}/codegen/templates/packaging_templates/MANIFEST.in.jinja2 +0 -0
  114. /package/{autorest → generator/pygen}/codegen/templates/packaging_templates/README.md.jinja2 +0 -0
  115. /package/{autorest → generator/pygen}/codegen/templates/packaging_templates/dev_requirements.txt.jinja2 +0 -0
  116. /package/{autorest → generator/pygen}/codegen/templates/packaging_templates/setup.py.jinja2 +0 -0
  117. /package/{autorest → generator/pygen}/codegen/templates/paging_operation.py.jinja2 +0 -0
  118. /package/{autorest → generator/pygen}/codegen/templates/patch.py.jinja2 +0 -0
  119. /package/{autorest → generator/pygen}/codegen/templates/pkgutil_init.py.jinja2 +0 -0
  120. /package/{autorest → generator/pygen}/codegen/templates/request_builders.py.jinja2 +0 -0
  121. /package/{autorest → generator/pygen}/codegen/templates/rest_init.py.jinja2 +0 -0
  122. /package/{autorest → generator/pygen}/codegen/templates/sample.py.jinja2 +0 -0
  123. /package/{autorest → generator/pygen}/codegen/templates/serialization.py.jinja2 +0 -0
  124. /package/{autorest → generator/pygen}/codegen/templates/testpreparer.py.jinja2 +0 -0
  125. /package/{autorest → generator/pygen}/codegen/templates/types.py.jinja2 +0 -0
  126. /package/{autorest → generator/pygen}/codegen/templates/validation.py.jinja2 +0 -0
  127. /package/{autorest → generator/pygen}/codegen/templates/vendor.py.jinja2 +0 -0
  128. /package/{autorest → generator/pygen}/codegen/templates/version.py.jinja2 +0 -0
  129. /package/{autorest → generator/pygen}/postprocess/get_all.py +0 -0
  130. /package/{autorest → generator/pygen}/postprocess/venvtools.py +0 -0
  131. /package/{autorest → generator/pygen}/preprocess/helpers.py +0 -0
  132. /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"][1 : -len("_initial")],
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 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
  )
@@ -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 autorest.codegen.models.utils import OrderedSet
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, ReaderAndWriterAutorest
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 ..._utils import to_snake_case
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("autorest.codegen", "templates"),
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("autorest.codegen", "templates/packaging_templates"),
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
- for is_async in (True, False):
550
- async_suffix = "_async" if is_async else ""
551
- general_serializer.is_async = is_async
552
- self.write_file(
553
- out_path / f"testpreparer{async_suffix}.py",
554
- general_serializer.serialize_testpreparer(),
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 ..._utils import JSON_REGEXP
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 declare_non_inputtable_constants(builder: RequestBuilderType) -> List[str]:
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}', {param.get_declaration()})"
418
- return f"{param.get_declaration()}"
418
+ return f"_{kwarg_dict}.pop('{param.wire_name}', {declaration})"
419
+ return declaration
419
420
 
420
- return [f"{p.client_name} = {_get_value(p)}" for p in builder.parameters.constant if not p.in_method_signature]
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
- return [
566
- f"_stream = {builder.stream_value}",
567
- f"pipeline_response: PipelineResponse = {self._call_method}self._client.{self.pipeline_name}.run( "
568
- + f"{'# type: ignore' if type_ignore else ''} # pylint: disable=protected-access",
569
- " _request,",
570
- " stream=_stream,",
571
- " **kwargs",
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 = f"response.stream_download(self._client.{self.pipeline_name})"
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 = f" {async_await}response.read() # Load the body in memory and close the socket"
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.append(response_read)
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.extend([" if _stream:", f" {response_read}"])
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 ..._utils import build_policies
11
+ from ...utils import build_policies
12
12
 
13
13
 
14
14
  class ClientSerializer:
@@ -6,7 +6,7 @@
6
6
  from typing import List
7
7
  from jinja2 import Environment
8
8
 
9
- from autorest.codegen.models.operation_group import OperationGroup
9
+ from ..models.operation_group import OperationGroup
10
10
  from ..models import CodeModel, Client
11
11
 
12
12
 
@@ -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 autorest.codegen.models.operation import OperationBase
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 ..._utils import to_snake_case
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 == "lropaging":
92
+ if is_lro(self.operation.operation_type):
75
93
  return "response = await (await "
76
- return "response = await "
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 == "lropaging":
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.is_async:
93
- if self.operation.operation_type == "lro":
94
- return f"result = await response.result(){self.lro_comment}"
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
- for client in self.code_model.clients:
144
- imports.add_submodule_import(namespace + self.aio_str, client.name, ImportType.STDLIB)
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("testpreparer", test_name.preparer_name, ImportType.LOCAL)
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.declare_non_inputtable_constants(request_builder) %}
12
- {{ op_tools.serialize(request_builder_serializer.declare_non_inputtable_constants(request_builder)) | indent }}
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 autorest MD to RST plugin.
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 .. import YamlUpdatePluginAutorest, YamlUpdatePlugin
14
- from .._utils import parse_args
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 AutorestRender(m2r2.RestRenderer):
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=AutorestRender()).strip()
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, PluginAutorest
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")}