@autorest/python 6.1.10 → 6.2.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 (73) hide show
  1. package/autorest/_utils.py +2 -1
  2. package/autorest/codegen/__init__.py +87 -80
  3. package/autorest/codegen/models/__init__.py +12 -9
  4. package/autorest/codegen/models/base_builder.py +11 -5
  5. package/autorest/codegen/models/base_model.py +5 -3
  6. package/autorest/codegen/models/base_type.py +7 -5
  7. package/autorest/codegen/models/client.py +131 -32
  8. package/autorest/codegen/models/code_model.py +92 -120
  9. package/autorest/codegen/models/combined_type.py +9 -6
  10. package/autorest/codegen/models/constant_type.py +6 -6
  11. package/autorest/codegen/models/credential_types.py +18 -16
  12. package/autorest/codegen/models/dictionary_type.py +8 -6
  13. package/autorest/codegen/models/enum_type.py +24 -17
  14. package/autorest/codegen/models/imports.py +4 -4
  15. package/autorest/codegen/models/list_type.py +14 -10
  16. package/autorest/codegen/models/lro_operation.py +14 -6
  17. package/autorest/codegen/models/model_type.py +19 -19
  18. package/autorest/codegen/models/operation.py +50 -33
  19. package/autorest/codegen/models/operation_group.py +23 -12
  20. package/autorest/codegen/models/paging_operation.py +15 -20
  21. package/autorest/codegen/models/parameter.py +25 -25
  22. package/autorest/codegen/models/parameter_list.py +22 -16
  23. package/autorest/codegen/models/primitive_types.py +21 -11
  24. package/autorest/codegen/models/property.py +7 -7
  25. package/autorest/codegen/models/request_builder.py +31 -20
  26. package/autorest/codegen/models/request_builder_parameter.py +18 -13
  27. package/autorest/codegen/models/response.py +29 -22
  28. package/autorest/codegen/serializers/__init__.py +196 -139
  29. package/autorest/codegen/serializers/builder_serializer.py +59 -53
  30. package/autorest/codegen/serializers/client_serializer.py +40 -46
  31. package/autorest/codegen/serializers/enum_serializer.py +4 -4
  32. package/autorest/codegen/serializers/general_serializer.py +96 -43
  33. package/autorest/codegen/serializers/metadata_serializer.py +20 -16
  34. package/autorest/codegen/serializers/model_init_serializer.py +10 -6
  35. package/autorest/codegen/serializers/model_serializer.py +8 -8
  36. package/autorest/codegen/serializers/operation_groups_serializer.py +24 -12
  37. package/autorest/codegen/serializers/operations_init_serializer.py +6 -7
  38. package/autorest/codegen/serializers/patch_serializer.py +4 -4
  39. package/autorest/codegen/serializers/request_builders_serializer.py +6 -6
  40. package/autorest/codegen/serializers/sample_serializer.py +146 -0
  41. package/autorest/codegen/templates/client.py.jinja2 +7 -15
  42. package/autorest/codegen/templates/client_container.py.jinja2 +12 -0
  43. package/autorest/codegen/templates/config.py.jinja2 +13 -26
  44. package/autorest/codegen/templates/config_container.py.jinja2 +16 -0
  45. package/autorest/codegen/templates/enum_container.py.jinja2 +3 -3
  46. package/autorest/codegen/templates/init.py.jinja2 +11 -5
  47. package/autorest/codegen/templates/lro_operation.py.jinja2 +2 -2
  48. package/autorest/codegen/templates/lro_paging_operation.py.jinja2 +1 -1
  49. package/autorest/codegen/templates/metadata.json.jinja2 +13 -14
  50. package/autorest/codegen/templates/model_container.py.jinja2 +3 -3
  51. package/autorest/codegen/templates/model_init.py.jinja2 +4 -4
  52. package/autorest/codegen/templates/operation.py.jinja2 +2 -2
  53. package/autorest/codegen/templates/operation_group.py.jinja2 +3 -3
  54. package/autorest/codegen/templates/operation_groups_container.py.jinja2 +7 -7
  55. package/autorest/codegen/templates/operation_tools.jinja2 +3 -3
  56. package/autorest/codegen/templates/operations_folder_init.py.jinja2 +4 -4
  57. package/autorest/codegen/templates/{CHANGELOG.md.jinja2 → packaging_templates/CHANGELOG.md.jinja2} +0 -0
  58. package/autorest/codegen/templates/{LICENSE.jinja2 → packaging_templates/LICENSE.jinja2} +0 -0
  59. package/autorest/codegen/templates/{MANIFEST.in.jinja2 → packaging_templates/MANIFEST.in.jinja2} +0 -0
  60. package/autorest/codegen/templates/{README.md.jinja2 → packaging_templates/README.md.jinja2} +0 -0
  61. package/autorest/codegen/templates/{dev_requirements.txt.jinja2 → packaging_templates/dev_requirements.txt.jinja2} +0 -0
  62. package/autorest/codegen/templates/{setup.py.jinja2 → packaging_templates/setup.py.jinja2} +9 -9
  63. package/autorest/codegen/templates/paging_operation.py.jinja2 +1 -1
  64. package/autorest/codegen/templates/request_builder.py.jinja2 +1 -1
  65. package/autorest/codegen/templates/request_builders.py.jinja2 +3 -3
  66. package/autorest/codegen/templates/rest_init.py.jinja2 +1 -1
  67. package/autorest/codegen/templates/sample.py.jinja2 +44 -0
  68. package/autorest/codegen/templates/validation.py.jinja2 +1 -1
  69. package/autorest/codegen/templates/vendor.py.jinja2 +9 -7
  70. package/autorest/codegen/templates/version.py.jinja2 +2 -2
  71. package/autorest/m4reformatter/__init__.py +20 -7
  72. package/autorest/preprocess/__init__.py +38 -23
  73. package/package.json +1 -1
@@ -34,7 +34,8 @@ def to_snake_case(name: str) -> str:
34
34
 
35
35
  return prefix + match_str
36
36
 
37
- return re.sub("[A-Z]+", replace_upper_characters, name)
37
+ result = re.sub("[A-Z]+", replace_upper_characters, name)
38
+ return result.replace(" ", "_").replace("__", "_").replace("-", "")
38
39
 
39
40
 
40
41
  def parse_args(
@@ -11,29 +11,68 @@ import yaml
11
11
 
12
12
  from .. import Plugin, PluginAutorest
13
13
  from .._utils import parse_args
14
- from .models.client import Client, Config
15
- from .models.code_model import CodeModel
16
- from .models import build_type
14
+ from .models.client import Client
15
+ from .models.code_model import CodeModel, NamespaceModel
17
16
  from .models.request_builder import get_request_builder
17
+
18
18
  from .models.operation_group import OperationGroup
19
19
  from .serializers import JinjaSerializer, JinjaSerializerAutorest
20
20
  from ._utils import DEFAULT_HEADER_TEXT
21
21
 
22
22
 
23
- def _build_convenience_layer(yaml_data: Dict[str, Any], code_model: CodeModel) -> None:
24
- # Create operations
25
- if code_model.options["show_operations"] and yaml_data.get("operationGroups"):
26
- code_model.operation_groups = [
27
- OperationGroup.from_yaml(op_group, code_model)
28
- for op_group in yaml_data["operationGroups"]
23
+ def _build_convenience_layer(code_model: CodeModel) -> None:
24
+ for namespace_model in code_model.namespace_models:
25
+ if namespace_model.options["show_operations"]:
26
+ for client in namespace_model.clients:
27
+ client.operation_groups = [
28
+ OperationGroup.from_yaml(op_group, namespace_model, client)
29
+ for op_group in client.yaml_data.get("operationGroups", [])
30
+ ]
31
+ if namespace_model.options["models_mode"] and namespace_model.model_types:
32
+ namespace_model.sort_model_types()
33
+
34
+ if namespace_model.options["show_operations"]:
35
+ for client in namespace_model.clients:
36
+ client.format_lro_operations()
37
+
38
+
39
+ def _create_code_model(
40
+ yaml_data: Dict[str, Any], options: Dict[str, Union[str, bool]]
41
+ ) -> CodeModel:
42
+ # Create a code model
43
+ code_model = CodeModel(yaml_data, options=options)
44
+ for namespace_model in code_model.namespace_models:
45
+ namespace_model.clients = [
46
+ Client.from_yaml(client_yaml_data, namespace_model)
47
+ for client_yaml_data in namespace_model.yaml_data["clients"]
29
48
  ]
30
- if yaml_data.get("types"):
31
- if code_model.options["models_mode"]:
32
- code_model.sort_model_types()
33
49
 
34
- if code_model.options["show_operations"]:
35
- # LRO operation
36
- code_model.format_lro_operations()
50
+ for client in namespace_model.clients:
51
+ if not client.yaml_data.get("operationGroups"):
52
+ continue
53
+ for og_group in client.yaml_data["operationGroups"]:
54
+ for operation_yaml in og_group["operations"]:
55
+ request_builder = get_request_builder(
56
+ operation_yaml,
57
+ namespace_model=namespace_model,
58
+ client=client,
59
+ )
60
+ if request_builder.overloads:
61
+ client.request_builders.extend(request_builder.overloads) # type: ignore
62
+ client.request_builders.append(request_builder)
63
+ if operation_yaml.get("nextOperation"):
64
+ # i am a paging operation and i have a next operation.
65
+ # Make sure to include my next operation
66
+ client.request_builders.append(
67
+ get_request_builder(
68
+ operation_yaml["nextOperation"],
69
+ namespace_model=namespace_model,
70
+ client=client,
71
+ )
72
+ )
73
+
74
+ _build_convenience_layer(code_model)
75
+ return code_model
37
76
 
38
77
 
39
78
  def _validate_code_model_options(options: Dict[str, Any]) -> None:
@@ -97,21 +136,22 @@ _LOGGER = logging.getLogger(__name__)
97
136
  class CodeGenerator(Plugin):
98
137
  @staticmethod
99
138
  def remove_cloud_errors(yaml_data: Dict[str, Any]) -> None:
100
- for group in yaml_data["operationGroups"]:
101
- for operation in group["operations"]:
102
- if not operation.get("exceptions"):
103
- continue
104
- i = 0
105
- while i < len(operation["exceptions"]):
106
- exception = operation["exceptions"][i]
107
- if (
108
- exception.get("schema")
109
- and exception["schema"]["language"]["default"]["name"]
110
- == "CloudError"
111
- ):
112
- del operation["exceptions"][i]
113
- i -= 1
114
- i += 1
139
+ for client in yaml_data["clients"]:
140
+ for group in client["operationGroups"]:
141
+ for operation in group["operations"]:
142
+ if not operation.get("exceptions"):
143
+ continue
144
+ i = 0
145
+ while i < len(operation["exceptions"]):
146
+ exception = operation["exceptions"][i]
147
+ if (
148
+ exception.get("schema")
149
+ and exception["schema"]["language"]["default"]["name"]
150
+ == "CloudError"
151
+ ):
152
+ del operation["exceptions"][i]
153
+ i -= 1
154
+ i += 1
115
155
  if yaml_data.get("schemas") and yaml_data["schemas"].get("objects"):
116
156
  for i in range(len(yaml_data["schemas"]["objects"])):
117
157
  obj_schema = yaml_data["schemas"]["objects"][i]
@@ -119,48 +159,6 @@ class CodeGenerator(Plugin):
119
159
  del yaml_data["schemas"]["objects"][i]
120
160
  break
121
161
 
122
- @staticmethod
123
- def _build_package_dependency() -> Dict[str, str]:
124
- return {
125
- "dependency_azure_mgmt_core": "azure-mgmt-core<2.0.0,>=1.3.2",
126
- "dependency_azure_core": "azure-core<2.0.0,>=1.24.0",
127
- "dependency_msrest": "msrest>=0.7.1",
128
- }
129
-
130
- def _create_code_model(
131
- self, yaml_data: Dict[str, Any], options: Dict[str, Union[str, bool]]
132
- ) -> CodeModel:
133
- # Create a code model
134
-
135
- code_model = CodeModel(yaml_data, options=options)
136
- for type_yaml in yaml_data.get("types", []):
137
- build_type(yaml_data=type_yaml, code_model=code_model)
138
-
139
- code_model.client = Client.from_yaml(yaml_data["client"], code_model)
140
- code_model.config = Config.from_yaml(yaml_data["client"], code_model)
141
-
142
- # Build request builders
143
- if yaml_data.get("operationGroups"):
144
- for og_group in yaml_data["operationGroups"]:
145
- for operation_yaml in og_group["operations"]:
146
- request_builder = get_request_builder(
147
- operation_yaml, code_model=code_model
148
- )
149
- if request_builder.overloads:
150
- code_model.request_builders.extend(request_builder.overloads) # type: ignore
151
- code_model.request_builders.append(request_builder)
152
- if operation_yaml.get("nextOperation"):
153
- # i am a paging operation and i have a next operation. Make sure to include my next operation
154
- code_model.request_builders.append(
155
- get_request_builder(
156
- operation_yaml["nextOperation"], code_model=code_model
157
- )
158
- )
159
-
160
- _build_convenience_layer(yaml_data=yaml_data, code_model=code_model)
161
- code_model.package_dependency = self._build_package_dependency()
162
- return code_model
163
-
164
162
  def _build_code_model_options(self) -> Dict[str, Any]:
165
163
  """Build en options dict from the user input while running autorest."""
166
164
  azure_arm = self.options.get("azure-arm", False)
@@ -218,6 +216,7 @@ class CodeGenerator(Plugin):
218
216
  "default-optional-constants-to-none",
219
217
  low_level_client or version_tolerant,
220
218
  ),
219
+ "generate_sample": self.options.get("generate-sample", False),
221
220
  }
222
221
 
223
222
  if options["builders_visibility"] is None:
@@ -243,8 +242,10 @@ class CodeGenerator(Plugin):
243
242
  with open(self.options["cadl_file"], "r") as fd:
244
243
  return yaml.safe_load(fd.read())
245
244
 
246
- def get_serializer(self, code_model: CodeModel):
247
- return JinjaSerializer(code_model, output_folder=self.output_folder)
245
+ def get_serializer(self, code_model: CodeModel, namespace_model: NamespaceModel):
246
+ return JinjaSerializer(
247
+ code_model, namespace_model, output_folder=self.output_folder
248
+ )
248
249
 
249
250
  def process(self) -> bool:
250
251
  # List the input file, should be only one
@@ -253,12 +254,14 @@ class CodeGenerator(Plugin):
253
254
  yaml_data = self.get_yaml()
254
255
 
255
256
  if options["azure_arm"]:
256
- self.remove_cloud_errors(yaml_data)
257
+ for namespace in yaml_data.values():
258
+ self.remove_cloud_errors(namespace)
257
259
 
258
- code_model = self._create_code_model(yaml_data=yaml_data, options=options)
260
+ code_model = _create_code_model(yaml_data=yaml_data, options=options)
259
261
 
260
- serializer = self.get_serializer(code_model)
261
- serializer.serialize()
262
+ for namespace_model in code_model.namespace_models:
263
+ serializer = self.get_serializer(code_model, namespace_model)
264
+ serializer.serialize()
262
265
 
263
266
  return True
264
267
 
@@ -330,6 +333,7 @@ class CodeGeneratorAutorest(CodeGenerator, PluginAutorest):
330
333
  "default-optional-constants-to-none": self._autorestapi.get_boolean_value(
331
334
  "default-optional-constants-to-none"
332
335
  ),
336
+ "generate-sample": self._autorestapi.get_boolean_value("generate-sample"),
333
337
  }
334
338
  return {k: v for k, v in options.items() if v is not None}
335
339
 
@@ -353,9 +357,12 @@ class CodeGeneratorAutorest(CodeGenerator, PluginAutorest):
353
357
  # Parse the received YAML
354
358
  return yaml.safe_load(file_content)
355
359
 
356
- def get_serializer(self, code_model: CodeModel): # type: ignore
360
+ def get_serializer(self, code_model: CodeModel, namespace_model: NamespaceModel): # type: ignore
357
361
  return JinjaSerializerAutorest(
358
- self._autorestapi, code_model, output_folder=self.output_folder
362
+ self._autorestapi,
363
+ code_model,
364
+ namespace_model,
365
+ output_folder=self.output_folder,
359
366
  )
360
367
 
361
368
 
@@ -6,7 +6,8 @@
6
6
  import logging
7
7
  from typing import Any, Dict, Union
8
8
  from .base_model import BaseModel
9
- from .code_model import CodeModel
9
+ from .code_model import CodeModel, NamespaceModel
10
+ from .client import Client
10
11
  from .model_type import ModelType
11
12
  from .dictionary_type import DictionaryType
12
13
  from .list_type import ListType
@@ -78,6 +79,8 @@ __all__ = [
78
79
  "BaseModel",
79
80
  "BaseType",
80
81
  "CodeModel",
82
+ "Client",
83
+ "NamespaceModel",
81
84
  "ConstantType",
82
85
  "ModelType",
83
86
  "DictionaryType",
@@ -145,28 +148,28 @@ TYPE_TO_OBJECT = {
145
148
  _LOGGER = logging.getLogger(__name__)
146
149
 
147
150
 
148
- def build_type(yaml_data: Dict[str, Any], code_model: CodeModel) -> BaseType:
151
+ def build_type(yaml_data: Dict[str, Any], namespace_model: NamespaceModel) -> BaseType:
149
152
  yaml_id = id(yaml_data)
150
153
  try:
151
- return code_model.lookup_type(yaml_id)
154
+ return namespace_model.lookup_type(yaml_id)
152
155
  except KeyError:
153
156
  # Not created yet, let's create it and add it to the index
154
157
  pass
155
158
  if yaml_data["type"] == "model":
156
159
  # need to special case model to avoid recursion
157
- response = ModelType(yaml_data, code_model)
158
- code_model.types_map[yaml_id] = response
159
- response.fill_instance_from_yaml(yaml_data, code_model)
160
+ response = ModelType(yaml_data, namespace_model)
161
+ namespace_model.types_map[yaml_id] = response
162
+ response.fill_instance_from_yaml(yaml_data, namespace_model)
160
163
  else:
161
164
  object_type = yaml_data.get("type")
162
- if object_type is None:
165
+ if object_type not in TYPE_TO_OBJECT:
163
166
  _LOGGER.warning(
164
167
  'Unrecognized definition type "%s" is found, falling back it as "string"! ',
165
168
  yaml_data["type"],
166
169
  )
167
170
  object_type = "string"
168
- response = TYPE_TO_OBJECT[object_type].from_yaml(yaml_data, code_model) # type: ignore
169
- code_model.types_map[yaml_id] = response
171
+ response = TYPE_TO_OBJECT[object_type].from_yaml(yaml_data, namespace_model) # type: ignore
172
+ namespace_model.types_map[yaml_id] = response
170
173
  return response
171
174
 
172
175
 
@@ -13,6 +13,7 @@ from .parameter_list import (
13
13
  OverloadedRequestBuilderParameterList,
14
14
  )
15
15
 
16
+
16
17
  ParameterListType = TypeVar(
17
18
  "ParameterListType",
18
19
  bound=Union[
@@ -24,9 +25,10 @@ ParameterListType = TypeVar(
24
25
 
25
26
 
26
27
  if TYPE_CHECKING:
27
- from .code_model import CodeModel
28
+ from .code_model import NamespaceModel
28
29
  from .operation import Operation
29
30
  from .request_builder import RequestBuilder
31
+ from .client import Client
30
32
 
31
33
  _LOGGER = logging.getLogger(__name__)
32
34
 
@@ -39,14 +41,16 @@ class BaseBuilder(
39
41
  def __init__(
40
42
  self,
41
43
  yaml_data: Dict[str, Any],
42
- code_model: "CodeModel",
44
+ namespace_model: "NamespaceModel",
45
+ client: "Client",
43
46
  name: str,
44
47
  parameters: ParameterListType,
45
48
  *,
46
49
  overloads=None,
47
50
  want_tracing: bool = True,
48
51
  ) -> None:
49
- super().__init__(yaml_data=yaml_data, code_model=code_model)
52
+ super().__init__(yaml_data=yaml_data, namespace_model=namespace_model)
53
+ self.client = client
50
54
  self.name = name
51
55
  self._description: str = yaml_data.get("description", "")
52
56
  self.parameters = parameters
@@ -55,12 +59,14 @@ class BaseBuilder(
55
59
  )
56
60
  self._summary: str = yaml_data.get("summary", "")
57
61
  self.want_tracing = want_tracing
58
- self.group_name: str = yaml_data["groupName"]
62
+ self.group_name: str = yaml_data[
63
+ "groupName"
64
+ ] # either operationGroup or client I am on
59
65
  self.is_overload: bool = yaml_data["isOverload"]
60
66
  self.api_versions: List[str] = yaml_data["apiVersions"]
61
67
  self.added_on: Optional[str] = yaml_data.get("addedOn")
62
68
 
63
- if code_model.options["version_tolerant"] and yaml_data.get("abstract"):
69
+ if namespace_model.options["version_tolerant"] and yaml_data.get("abstract"):
64
70
  _LOGGER.warning(
65
71
  'Not going to generate operation "%s" because we are unable to generate this '
66
72
  "type of operation right now. "
@@ -6,7 +6,7 @@
6
6
  from typing import Any, Dict, TYPE_CHECKING
7
7
 
8
8
  if TYPE_CHECKING:
9
- from .code_model import CodeModel
9
+ from .code_model import NamespaceModel
10
10
 
11
11
 
12
12
  class BaseModel:
@@ -16,9 +16,11 @@ class BaseModel:
16
16
  :type yaml_data: dict[str, Any]
17
17
  """
18
18
 
19
- def __init__(self, yaml_data: Dict[str, Any], code_model: "CodeModel") -> None:
19
+ def __init__(
20
+ self, yaml_data: Dict[str, Any], namespace_model: "NamespaceModel"
21
+ ) -> None:
20
22
  self.yaml_data = yaml_data
21
- self.code_model = code_model
23
+ self.namespace_model = namespace_model
22
24
 
23
25
  @property
24
26
  def id(self) -> int:
@@ -10,7 +10,7 @@ from .base_model import BaseModel
10
10
  from .imports import FileImport
11
11
 
12
12
  if TYPE_CHECKING:
13
- from .code_model import CodeModel
13
+ from .code_model import NamespaceModel
14
14
  from .model_type import ModelType
15
15
 
16
16
 
@@ -21,8 +21,10 @@ class BaseType(BaseModel, ABC):
21
21
  :type yaml_data: dict[str, Any]
22
22
  """
23
23
 
24
- def __init__(self, yaml_data: Dict[str, Any], code_model: "CodeModel") -> None:
25
- super().__init__(yaml_data, code_model)
24
+ def __init__(
25
+ self, yaml_data: Dict[str, Any], namespace_model: "NamespaceModel"
26
+ ) -> None:
27
+ super().__init__(yaml_data, namespace_model)
26
28
  self.type = yaml_data["type"] # the type discriminator
27
29
  self.api_versions: List[str] = yaml_data.get(
28
30
  "apiVersions", []
@@ -30,9 +32,9 @@ class BaseType(BaseModel, ABC):
30
32
 
31
33
  @classmethod
32
34
  def from_yaml(
33
- cls, yaml_data: Dict[str, Any], code_model: "CodeModel"
35
+ cls, yaml_data: Dict[str, Any], namespace_model: "NamespaceModel"
34
36
  ) -> "BaseType":
35
- return cls(yaml_data=yaml_data, code_model=code_model)
37
+ return cls(yaml_data=yaml_data, namespace_model=namespace_model)
36
38
 
37
39
  def imports( # pylint: disable=no-self-use
38
40
  self, **kwargs # pylint: disable=unused-argument