@autorest/python 5.14.0 → 5.17.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 (120) hide show
  1. package/ChangeLog.md +91 -2
  2. package/README.md +30 -4
  3. package/autorest/__init__.py +2 -3
  4. package/autorest/black/__init__.py +12 -5
  5. package/autorest/codegen/__init__.py +130 -179
  6. package/autorest/codegen/models/__init__.py +122 -78
  7. package/autorest/codegen/models/base_builder.py +70 -72
  8. package/autorest/codegen/models/base_model.py +7 -5
  9. package/autorest/codegen/models/{base_schema.py → base_type.py} +62 -49
  10. package/autorest/codegen/models/client.py +195 -36
  11. package/autorest/codegen/models/code_model.py +165 -299
  12. package/autorest/codegen/models/combined_type.py +107 -0
  13. package/autorest/codegen/models/constant_type.py +122 -0
  14. package/autorest/codegen/models/credential_types.py +224 -0
  15. package/autorest/codegen/models/dictionary_type.py +116 -0
  16. package/autorest/codegen/models/enum_type.py +195 -0
  17. package/autorest/codegen/models/imports.py +95 -41
  18. package/autorest/codegen/models/list_type.py +134 -0
  19. package/autorest/codegen/models/lro_operation.py +90 -133
  20. package/autorest/codegen/models/lro_paging_operation.py +28 -12
  21. package/autorest/codegen/models/model_type.py +239 -0
  22. package/autorest/codegen/models/operation.py +415 -241
  23. package/autorest/codegen/models/operation_group.py +82 -88
  24. package/autorest/codegen/models/paging_operation.py +101 -117
  25. package/autorest/codegen/models/parameter.py +307 -322
  26. package/autorest/codegen/models/parameter_list.py +366 -357
  27. package/autorest/codegen/models/primitive_types.py +544 -0
  28. package/autorest/codegen/models/property.py +122 -134
  29. package/autorest/codegen/models/request_builder.py +138 -86
  30. package/autorest/codegen/models/request_builder_parameter.py +122 -79
  31. package/autorest/codegen/models/response.py +325 -0
  32. package/autorest/codegen/models/utils.py +17 -1
  33. package/autorest/codegen/serializers/__init__.py +242 -118
  34. package/autorest/codegen/serializers/builder_serializer.py +863 -1027
  35. package/autorest/codegen/serializers/client_serializer.py +148 -82
  36. package/autorest/codegen/serializers/general_serializer.py +44 -47
  37. package/autorest/codegen/serializers/import_serializer.py +96 -31
  38. package/autorest/codegen/serializers/metadata_serializer.py +39 -79
  39. package/autorest/codegen/serializers/model_base_serializer.py +65 -29
  40. package/autorest/codegen/serializers/model_generic_serializer.py +9 -10
  41. package/autorest/codegen/serializers/model_init_serializer.py +4 -2
  42. package/autorest/codegen/serializers/model_python3_serializer.py +29 -22
  43. package/autorest/codegen/serializers/operation_groups_serializer.py +21 -18
  44. package/autorest/codegen/serializers/operations_init_serializer.py +23 -11
  45. package/autorest/codegen/serializers/parameter_serializer.py +174 -0
  46. package/autorest/codegen/serializers/patch_serializer.py +14 -2
  47. package/autorest/codegen/serializers/request_builders_serializer.py +57 -0
  48. package/autorest/codegen/serializers/utils.py +0 -103
  49. package/autorest/codegen/templates/MANIFEST.in.jinja2 +1 -0
  50. package/autorest/codegen/templates/{service_client.py.jinja2 → client.py.jinja2} +7 -7
  51. package/autorest/codegen/templates/config.py.jinja2 +13 -13
  52. package/autorest/codegen/templates/enum.py.jinja2 +4 -4
  53. package/autorest/codegen/templates/enum_container.py.jinja2 +1 -2
  54. package/autorest/codegen/templates/init.py.jinja2 +9 -6
  55. package/autorest/codegen/templates/keywords.jinja2 +14 -1
  56. package/autorest/codegen/templates/lro_operation.py.jinja2 +6 -5
  57. package/autorest/codegen/templates/lro_paging_operation.py.jinja2 +6 -5
  58. package/autorest/codegen/templates/metadata.json.jinja2 +36 -35
  59. package/autorest/codegen/templates/model.py.jinja2 +23 -29
  60. package/autorest/codegen/templates/model_container.py.jinja2 +2 -1
  61. package/autorest/codegen/templates/model_init.py.jinja2 +9 -8
  62. package/autorest/codegen/templates/operation.py.jinja2 +10 -15
  63. package/autorest/codegen/templates/operation_group.py.jinja2 +14 -13
  64. package/autorest/codegen/templates/operation_groups_container.py.jinja2 +1 -2
  65. package/autorest/codegen/templates/operation_tools.jinja2 +8 -2
  66. package/autorest/codegen/templates/operations_folder_init.py.jinja2 +4 -0
  67. package/autorest/codegen/templates/paging_operation.py.jinja2 +7 -8
  68. package/autorest/codegen/templates/patch.py.jinja2 +18 -29
  69. package/autorest/codegen/templates/request_builder.py.jinja2 +20 -13
  70. package/autorest/codegen/templates/setup.py.jinja2 +9 -3
  71. package/autorest/codegen/templates/vendor.py.jinja2 +12 -2
  72. package/autorest/jsonrpc/__init__.py +7 -12
  73. package/autorest/jsonrpc/localapi.py +4 -3
  74. package/autorest/jsonrpc/server.py +28 -9
  75. package/autorest/jsonrpc/stdstream.py +13 -6
  76. package/autorest/m2r/__init__.py +5 -8
  77. package/autorest/m4reformatter/__init__.py +1108 -0
  78. package/autorest/multiapi/__init__.py +24 -14
  79. package/autorest/multiapi/models/client.py +21 -11
  80. package/autorest/multiapi/models/code_model.py +23 -10
  81. package/autorest/multiapi/models/config.py +4 -1
  82. package/autorest/multiapi/models/constant_global_parameter.py +1 -0
  83. package/autorest/multiapi/models/global_parameter.py +2 -1
  84. package/autorest/multiapi/models/global_parameters.py +14 -8
  85. package/autorest/multiapi/models/imports.py +35 -18
  86. package/autorest/multiapi/models/mixin_operation.py +5 -5
  87. package/autorest/multiapi/models/operation_group.py +2 -1
  88. package/autorest/multiapi/models/operation_mixin_group.py +21 -10
  89. package/autorest/multiapi/serializers/__init__.py +20 -25
  90. package/autorest/multiapi/serializers/import_serializer.py +47 -15
  91. package/autorest/multiapi/serializers/multiapi_serializer.py +17 -17
  92. package/autorest/multiapi/templates/multiapi_config.py.jinja2 +3 -3
  93. package/autorest/multiapi/templates/multiapi_init.py.jinja2 +2 -2
  94. package/autorest/multiapi/templates/multiapi_operations_mixin.py.jinja2 +4 -4
  95. package/autorest/multiapi/templates/multiapi_service_client.py.jinja2 +9 -9
  96. package/autorest/multiapi/utils.py +3 -3
  97. package/autorest/postprocess/__init__.py +202 -0
  98. package/autorest/postprocess/get_all.py +19 -0
  99. package/autorest/postprocess/venvtools.py +73 -0
  100. package/autorest/preprocess/__init__.py +209 -0
  101. package/autorest/preprocess/helpers.py +54 -0
  102. package/autorest/{namer → preprocess}/python_mappings.py +25 -32
  103. package/package.json +3 -3
  104. package/run-python3.js +2 -3
  105. package/venvtools.py +1 -1
  106. package/autorest/codegen/models/constant_schema.py +0 -97
  107. package/autorest/codegen/models/credential_schema.py +0 -90
  108. package/autorest/codegen/models/credential_schema_policy.py +0 -77
  109. package/autorest/codegen/models/dictionary_schema.py +0 -103
  110. package/autorest/codegen/models/enum_schema.py +0 -246
  111. package/autorest/codegen/models/list_schema.py +0 -113
  112. package/autorest/codegen/models/object_schema.py +0 -249
  113. package/autorest/codegen/models/primitive_schemas.py +0 -476
  114. package/autorest/codegen/models/request_builder_parameter_list.py +0 -280
  115. package/autorest/codegen/models/rest.py +0 -42
  116. package/autorest/codegen/models/schema_request.py +0 -45
  117. package/autorest/codegen/models/schema_response.py +0 -123
  118. package/autorest/codegen/serializers/rest_serializer.py +0 -57
  119. package/autorest/namer/__init__.py +0 -25
  120. package/autorest/namer/name_converter.py +0 -412
@@ -5,49 +5,69 @@
5
5
  # --------------------------------------------------------------------------
6
6
  from copy import deepcopy
7
7
  from typing import List
8
- from ..models.imports import ImportType, FileImport, ImportModel, TypingSection
8
+ from ..models.imports import (
9
+ ImportType,
10
+ FileImport,
11
+ ImportModel,
12
+ TypingSection,
13
+ TypeDefinition,
14
+ )
9
15
 
10
- def _serialize_package(
11
- imports: List[ImportModel], delimiter: str
12
- ) -> str:
16
+
17
+ def _serialize_package(imports: List[ImportModel], delimiter: str) -> str:
13
18
  buffer = []
14
19
  if any(i for i in imports if i.submodule_name is None):
15
- buffer.append(f"import {imports[0].module_name}")
20
+ buffer.append(
21
+ f"import {imports[0].module_name}{f' as {imports[0].alias}' if imports[0].alias else ''}"
22
+ )
16
23
  else:
17
- import_str = ", ".join(sorted([
18
- f"{i.submodule_name} as {i.alias}" if i.alias else i.submodule_name for i in imports # type: ignore
19
- ]))
24
+ import_str = ", ".join(
25
+ sorted(
26
+ set(
27
+ f"{i.submodule_name} as {i.alias}" if i.alias else i.submodule_name # type: ignore
28
+ for i in imports
29
+ )
30
+ )
31
+ )
20
32
  buffer.append(f"from {imports[0].module_name} import {import_str}")
21
33
  return delimiter.join(buffer)
22
34
 
35
+
23
36
  def _serialize_import_type(imports: List[ImportModel], delimiter: str) -> str:
24
37
  """Serialize a given import type."""
25
38
  import_list = []
26
39
  for module_name in sorted(set(i.module_name for i in imports)):
27
40
 
28
- import_list.append(_serialize_package([
29
- i for i in imports if i.module_name == module_name
30
- ], delimiter))
41
+ import_list.append(
42
+ _serialize_package(
43
+ [i for i in imports if i.module_name == module_name], delimiter
44
+ )
45
+ )
31
46
  return delimiter.join(import_list)
32
47
 
33
- def _get_import_clauses(
34
- imports: List[ImportModel], delimiter: str
35
- ) -> List[str]:
48
+
49
+ def _get_import_clauses(imports: List[ImportModel], delimiter: str) -> List[str]:
36
50
  import_clause = []
37
51
  for import_type in ImportType:
38
52
  imports_with_import_type = [i for i in imports if i.import_type == import_type]
39
53
  if imports_with_import_type:
40
- import_clause.append(_serialize_import_type(imports_with_import_type, delimiter))
54
+ import_clause.append(
55
+ _serialize_import_type(imports_with_import_type, delimiter)
56
+ )
41
57
  return import_clause
42
58
 
43
59
 
44
60
  class FileImportSerializer:
45
- def __init__(self, file_import: FileImport, is_python3_file: bool, async_mode: bool = False) -> None:
61
+ def __init__(
62
+ self, file_import: FileImport, is_python3_file: bool, async_mode: bool = False
63
+ ) -> None:
46
64
  self.file_import = file_import
47
65
  self.is_python3_file = is_python3_file
48
66
  self.async_mode = async_mode
49
67
 
50
- def _get_imports_list(self, baseline_typing_section: TypingSection, add_conditional_typing: bool):
68
+ def _get_imports_list(
69
+ self, baseline_typing_section: TypingSection, add_conditional_typing: bool
70
+ ):
51
71
  # If this is a python 3 file, our regular imports include the CONDITIONAL category
52
72
  # If this is not a python 3 file, our typing imports include the CONDITIONAL category
53
73
  file_import_copy = deepcopy(self.file_import)
@@ -62,33 +82,75 @@ class FileImportSerializer:
62
82
  return file_import_copy.get_imports_from_section(baseline_typing_section)
63
83
 
64
84
  def _add_type_checking_import(self):
65
- any_typing = any(self.file_import.get_imports_from_section(TypingSection.TYPING))
85
+ any_typing = any(
86
+ self.file_import.get_imports_from_section(TypingSection.TYPING)
87
+ )
66
88
  conditional_and_not_py3 = not self.is_python3_file and any(
67
89
  self.file_import.get_imports_from_section(TypingSection.CONDITIONAL)
68
90
  )
69
91
  if any_typing or conditional_and_not_py3:
70
- self.file_import.add_submodule_import("typing", "TYPE_CHECKING", ImportType.STDLIB)
92
+ self.file_import.add_submodule_import(
93
+ "typing", "TYPE_CHECKING", ImportType.STDLIB
94
+ )
71
95
 
72
96
  def _get_typing_definitions(self) -> str:
97
+ def declare_defintion(
98
+ spacing: str, type_name: str, type_definition: TypeDefinition
99
+ ) -> List[str]:
100
+ ret: List[str] = []
101
+ definition_value = (
102
+ type_definition.async_definition
103
+ if self.async_mode
104
+ else type_definition.sync_definition
105
+ )
106
+ if type_definition.version_imports is not None:
107
+ versions = type_definition.version_imports.keys()
108
+ for i, version in enumerate(
109
+ sorted(
110
+ versions, key=lambda x: x if x is not None else (), reverse=True
111
+ )
112
+ ):
113
+ if version is not None:
114
+ ret.append(
115
+ "{}{} sys.version_info >= {}:".format(
116
+ spacing, "if" if i == 0 else "elif", version
117
+ )
118
+ )
119
+ elif i > 0:
120
+ ret.append("{}else:".format(spacing))
121
+ for import_clause in _get_import_clauses(
122
+ [type_definition.version_imports[version]], "\n"
123
+ ):
124
+ ret.append(
125
+ "{}{}{}".format(
126
+ " "
127
+ if len(versions) > 1 or version is not None
128
+ else "",
129
+ spacing,
130
+ import_clause,
131
+ )
132
+ )
133
+ if i > 0:
134
+ ret[
135
+ -1
136
+ ] += " # type: ignore # pylint: disable=ungrouped-imports"
137
+ ret.append("{}{} = {}".format(spacing, type_name, definition_value))
138
+ return ret
139
+
73
140
  if not self.file_import.type_definitions:
74
141
  return ""
75
142
  spacing = "" if self.is_python3_file else " "
76
- declarations: List[str] = [f"\n{spacing}T = TypeVar('T')"]
77
- declarations.extend([
78
- "{}{} = {}".format(
79
- spacing,
80
- type_name,
81
- values[1] if self.async_mode else values[0]
82
- )
83
- for type_name, values in self.file_import.type_definitions.items()
84
- ])
143
+ declarations: List[str] = [""]
144
+ for type_name, value in self.file_import.type_definitions.items():
145
+ declarations.extend(declare_defintion(spacing, type_name, value))
85
146
  return "\n".join(declarations)
86
147
 
87
148
  def __str__(self) -> str:
88
149
  self._add_type_checking_import()
89
150
  regular_imports = ""
90
151
  regular_imports_list = self._get_imports_list(
91
- baseline_typing_section=TypingSection.REGULAR, add_conditional_typing=self.is_python3_file
152
+ baseline_typing_section=TypingSection.REGULAR,
153
+ add_conditional_typing=self.is_python3_file,
92
154
  )
93
155
 
94
156
  if regular_imports_list:
@@ -98,9 +160,12 @@ class FileImportSerializer:
98
160
 
99
161
  typing_imports = ""
100
162
  typing_imports_list = self._get_imports_list(
101
- baseline_typing_section=TypingSection.TYPING, add_conditional_typing=not self.is_python3_file
163
+ baseline_typing_section=TypingSection.TYPING,
164
+ add_conditional_typing=not self.is_python3_file,
102
165
  )
103
166
  if typing_imports_list:
104
167
  typing_imports += "\n\nif TYPE_CHECKING:\n # pylint: disable=unused-import,ungrouped-imports\n "
105
- typing_imports += "\n\n ".join(_get_import_clauses(typing_imports_list, "\n "))
168
+ typing_imports += "\n\n ".join(
169
+ _get_import_clauses(typing_imports_list, "\n ")
170
+ )
106
171
  return regular_imports + typing_imports + self._get_typing_definitions()
@@ -4,36 +4,28 @@
4
4
  # license information.
5
5
  # --------------------------------------------------------------------------
6
6
  import functools
7
- import copy
8
7
  import json
9
8
  from typing import List, Optional, Set, Tuple, Dict, Union
10
9
  from jinja2 import Environment
11
- from .general_serializer import config_imports
12
10
  from ..models import (
13
11
  CodeModel,
14
- FileImport,
15
12
  OperationGroup,
16
13
  LROOperation,
17
14
  PagingOperation,
18
- TokenCredentialSchema,
19
- ParameterList,
20
15
  TypingSection,
21
16
  ImportType,
22
- GlobalParameterList,
23
17
  )
24
18
  from .builder_serializer import get_operation_serializer
25
19
 
26
20
 
27
- def _correct_credential_parameter(global_parameters: ParameterList, async_mode: bool) -> None:
28
- credential_param = [gp for gp in global_parameters.parameters if isinstance(gp.schema, TokenCredentialSchema)][0]
29
- credential_param.schema = TokenCredentialSchema(async_mode=async_mode)
30
-
31
-
32
21
  def _json_serialize_imports(
33
- imports: Dict[TypingSection, Dict[ImportType, Dict[str, Set[Optional[Union[str, Tuple[str, str]]]]]]]
34
- ):
22
+ imports: Dict[
23
+ TypingSection,
24
+ Dict[ImportType, Dict[str, Set[Optional[Union[str, Tuple[str, str]]]]]],
25
+ ]
26
+ ) -> str:
35
27
  if not imports:
36
- return None
28
+ return ""
37
29
 
38
30
  json_serialize_imports = {}
39
31
  # need to make name_import set -> list to make the dictionary json serializable
@@ -55,14 +47,18 @@ def _json_serialize_imports(
55
47
  return json.dumps(json_serialize_imports)
56
48
 
57
49
 
58
- def _mixin_imports(mixin_operation_group: Optional[OperationGroup]) -> Tuple[Optional[str], Optional[str]]:
50
+ def _mixin_imports(
51
+ mixin_operation_group: Optional[OperationGroup],
52
+ ) -> Tuple[Optional[str], Optional[str]]:
59
53
  if not mixin_operation_group:
60
54
  return None, None
61
55
 
62
56
  sync_mixin_imports = mixin_operation_group.imports_for_multiapi(async_mode=False)
63
57
  async_mixin_imports = mixin_operation_group.imports_for_multiapi(async_mode=True)
64
58
 
65
- return _json_serialize_imports(sync_mixin_imports.to_dict()), _json_serialize_imports(async_mixin_imports.to_dict())
59
+ return _json_serialize_imports(
60
+ sync_mixin_imports.to_dict()
61
+ ), _json_serialize_imports(async_mixin_imports.to_dict())
66
62
 
67
63
 
68
64
  class MetadataSerializer:
@@ -80,7 +76,9 @@ class MetadataSerializer:
80
76
  total_api_version_list.sort()
81
77
 
82
78
  # switching ' to " so json can decode the dict we end up writing to file
83
- total_api_version_list = [str(api_version).replace("'", '"') for api_version in total_api_version_list]
79
+ total_api_version_list = [
80
+ str(api_version).replace("'", '"') for api_version in total_api_version_list
81
+ ]
84
82
  if len(total_api_version_list) == 1:
85
83
  chosen_version = total_api_version_list[0]
86
84
  elif len(total_api_version_list) > 1:
@@ -91,34 +89,6 @@ class MetadataSerializer:
91
89
 
92
90
  return chosen_version, total_api_version_list
93
91
 
94
- def _make_async_copy_of_global_parameters(self) -> GlobalParameterList:
95
- global_parameters = copy.deepcopy(self.code_model.global_parameters)
96
- _correct_credential_parameter(global_parameters, True)
97
- return global_parameters
98
-
99
- def _service_client_imports(
100
- self, global_parameters: ParameterList, mixin_operation_group: Optional[OperationGroup], async_mode: bool
101
- ) -> str:
102
- file_import = FileImport()
103
- for gp in global_parameters:
104
- file_import.merge(gp.imports())
105
- file_import.add_submodule_import("azure.profiles", "KnownProfiles", import_type=ImportType.AZURECORE)
106
- file_import.add_submodule_import("azure.profiles", "ProfileDefinition", import_type=ImportType.AZURECORE)
107
- file_import.add_submodule_import(
108
- "azure.profiles.multiapiclient", "MultiApiClientMixin", import_type=ImportType.AZURECORE
109
- )
110
- file_import.add_submodule_import(
111
- "._configuration", f"{self.code_model.class_name}Configuration", ImportType.LOCAL
112
- )
113
- # api_version and potentially endpoint require Optional typing
114
- file_import.add_submodule_import("typing", "Optional", ImportType.STDLIB, TypingSection.CONDITIONAL)
115
- if mixin_operation_group:
116
- file_import.add_submodule_import(
117
- "._operations_mixin", f"{self.code_model.class_name}OperationsMixin", ImportType.LOCAL
118
- )
119
- file_import.merge(self.code_model.service_client.imports_for_multiapi(async_mode=async_mode))
120
- return _json_serialize_imports(file_import.to_dict())
121
-
122
92
  def serialize(self) -> str:
123
93
  def _is_lro(operation):
124
94
  return isinstance(operation, LROOperation)
@@ -130,47 +100,26 @@ class MetadataSerializer:
130
100
  (
131
101
  operation_group
132
102
  for operation_group in self.code_model.operation_groups
133
- if operation_group.is_empty_operation_group
103
+ if operation_group.is_mixin
134
104
  ),
135
105
  None,
136
106
  )
137
- mixin_operations = mixin_operation_group.operations if mixin_operation_group else []
107
+ mixin_operations = (
108
+ mixin_operation_group.operations if mixin_operation_group else []
109
+ )
138
110
  sync_mixin_imports, async_mixin_imports = _mixin_imports(mixin_operation_group)
139
111
 
140
112
  chosen_version, total_api_version_list = self._choose_api_version()
141
113
 
142
- # we separate out async and sync for the case of credentials.
143
- # In this case, we need two copies of the credential global parameter
144
- # for typing purposes.
145
- async_global_parameters = self.code_model.global_parameters
146
- if (
147
- self.code_model.options['credential'] and
148
- isinstance(self.code_model.credential_schema_policy.credential, TokenCredentialSchema)
149
- ):
150
- # this ensures that the TokenCredentialSchema showing up in the list of code model's global parameters
151
- # is sync. This way we only have to make a copy for an async_credential
152
- _correct_credential_parameter(self.code_model.global_parameters, False)
153
- async_global_parameters = self._make_async_copy_of_global_parameters()
154
-
155
- sync_client_imports = self._service_client_imports(
156
- self.code_model.global_parameters, mixin_operation_group, async_mode=False
157
- )
158
- async_client_imports = self._service_client_imports(
159
- async_global_parameters, mixin_operation_group, async_mode=True
160
- )
161
-
162
- template = self.env.get_template("metadata.json.jinja2")
163
-
164
114
  # setting to true, because for multiapi we always generate with a version file with version 0.1.0
165
115
  self.code_model.options["package_version"] = "0.1.0"
166
- if self.code_model.options["azure_arm"] and not self.code_model.service_client.parameters.host:
167
- self.code_model.service_client.parameters.add_host("https://management.azure.com")
116
+ template = self.env.get_template("metadata.json.jinja2")
117
+
168
118
  return template.render(
169
119
  chosen_version=chosen_version,
170
120
  total_api_version_list=total_api_version_list,
171
121
  code_model=self.code_model,
172
- sync_global_parameters=self.code_model.global_parameters,
173
- async_global_parameters=async_global_parameters,
122
+ global_parameters=self.code_model.client.parameters,
174
123
  mixin_operations=mixin_operations,
175
124
  any=any,
176
125
  is_lro=_is_lro,
@@ -178,18 +127,29 @@ class MetadataSerializer:
178
127
  str=str,
179
128
  sync_mixin_imports=sync_mixin_imports,
180
129
  async_mixin_imports=async_mixin_imports,
181
- sync_client_imports=sync_client_imports,
182
- async_client_imports=async_client_imports,
130
+ sync_client_imports=_json_serialize_imports(
131
+ self.code_model.client.imports_for_multiapi(async_mode=False).to_dict()
132
+ ),
133
+ async_client_imports=_json_serialize_imports(
134
+ self.code_model.client.imports_for_multiapi(async_mode=True).to_dict()
135
+ ),
183
136
  sync_config_imports=_json_serialize_imports(
184
- config_imports(self.code_model, self.code_model.global_parameters, async_mode=False).to_dict()
137
+ self.code_model.config.imports(async_mode=False).to_dict()
185
138
  ),
186
139
  async_config_imports=_json_serialize_imports(
187
- config_imports(self.code_model, async_global_parameters, async_mode=True).to_dict()
140
+ self.code_model.config.imports(async_mode=True).to_dict()
188
141
  ),
189
142
  get_async_operation_serializer=functools.partial(
190
- get_operation_serializer, code_model=self.code_model, async_mode=True, is_python3_file=True
143
+ get_operation_serializer,
144
+ code_model=self.code_model,
145
+ async_mode=True,
146
+ is_python3_file=True,
191
147
  ),
192
148
  get_sync_operation_serializer=functools.partial(
193
- get_operation_serializer, code_model=self.code_model, async_mode=False, is_python3_file=False
149
+ get_operation_serializer,
150
+ code_model=self.code_model,
151
+ async_mode=False,
152
+ is_python3_file=False,
194
153
  ),
154
+ has_credential=bool(self.code_model.credential),
195
155
  )
@@ -6,25 +6,31 @@
6
6
  from abc import abstractmethod
7
7
  from typing import cast, List
8
8
  from jinja2 import Environment
9
- from ..models import ObjectSchema, CodeModel, Property
9
+ from ..models import ModelType, CodeModel, Property
10
10
  from ..models.imports import FileImport, ImportType
11
11
  from .import_serializer import FileImportSerializer
12
12
 
13
+
13
14
  def _documentation_string(
14
15
  prop: Property, description_keyword: str, docstring_type_keyword: str
15
16
  ) -> List[str]:
16
17
  retval: List[str] = []
17
- sphinx_prefix = f":{description_keyword} {prop.name}:"
18
+ sphinx_prefix = f":{description_keyword} {prop.client_name}:"
18
19
  retval.append(
19
- f"{sphinx_prefix} {prop.description}" if prop.description
20
+ f"{sphinx_prefix} {prop.description(is_operation_file=False)}"
21
+ if prop.description(is_operation_file=False)
20
22
  else sphinx_prefix
21
23
  )
22
- retval.append(f":{docstring_type_keyword} {prop.name}: {prop.schema.docstring_type}")
24
+ retval.append(
25
+ f":{docstring_type_keyword} {prop.client_name}: {prop.type.docstring_type()}"
26
+ )
23
27
  return retval
24
28
 
25
29
 
26
30
  class ModelBaseSerializer:
27
- def __init__(self, code_model: CodeModel, env: Environment, is_python3_file: bool) -> None:
31
+ def __init__(
32
+ self, code_model: CodeModel, env: Environment, is_python3_file: bool
33
+ ) -> None:
28
34
  self.code_model = code_model
29
35
  self.env = env
30
36
  self.is_python3_file = is_python3_file
@@ -34,34 +40,44 @@ class ModelBaseSerializer:
34
40
  template = self.env.get_template("model_container.py.jinja2")
35
41
  return template.render(
36
42
  code_model=self.code_model,
37
- imports=FileImportSerializer(self.imports(), is_python3_file=self.is_python3_file),
43
+ imports=FileImportSerializer(
44
+ self.imports(), is_python3_file=self.is_python3_file
45
+ ),
38
46
  str=str,
39
- init_line=self.init_line,
40
- init_args=self.init_args,
41
- input_documentation_string=ModelBaseSerializer.input_documentation_string,
42
- variable_documentation_string=ModelBaseSerializer.variable_documentation_string,
47
+ serializer=self,
43
48
  )
44
49
 
45
50
  def imports(self) -> FileImport:
46
51
  file_import = FileImport()
47
52
  file_import.add_import("msrest.serialization", ImportType.AZURECORE)
48
- for model in self.code_model.sorted_schemas:
49
- file_import.merge(model.imports())
53
+ for model in self.code_model.model_types:
54
+ file_import.merge(model.imports(is_operation_file=False))
50
55
  return file_import
51
56
 
52
57
  @staticmethod
53
- def get_properties_to_initialize(model: ObjectSchema) -> List[Property]:
54
- if model.base_models:
55
- properties_to_initialize = list({
56
- p.name: p
57
- for bm in model.base_models
58
- for p in model.properties
59
- if p not in cast(ObjectSchema, bm).properties or p.is_discriminator or p.constant
60
- }.values())
58
+ def get_properties_to_initialize(model: ModelType) -> List[Property]:
59
+ if model.parents:
60
+ properties_to_initialize = list(
61
+ {
62
+ p.client_name: p
63
+ for bm in model.parents
64
+ for p in model.properties
65
+ if p not in cast(ModelType, bm).properties
66
+ or p.is_discriminator
67
+ or p.constant
68
+ }.values()
69
+ )
61
70
  else:
62
71
  properties_to_initialize = model.properties
63
72
  return properties_to_initialize
64
73
 
74
+ @staticmethod
75
+ def declare_model(model: ModelType) -> str:
76
+ basename = "msrest.serialization.Model"
77
+ if model.parents:
78
+ basename = ", ".join([cast(ModelType, m).name for m in model.parents])
79
+ return f"class {model.name}({basename}):{model.pylint_disable}"
80
+
65
81
  @staticmethod
66
82
  def input_documentation_string(prop: Property) -> List[str]:
67
83
  # building the param line of the property doc
@@ -71,35 +87,55 @@ class ModelBaseSerializer:
71
87
  def variable_documentation_string(prop: Property) -> List[str]:
72
88
  return _documentation_string(prop, "ivar", "vartype")
73
89
 
74
- def init_args(self, model: ObjectSchema) -> List[str]:
90
+ @abstractmethod
91
+ def super_call_template(self, model: ModelType) -> str:
92
+ ...
93
+
94
+ def super_call(self, model: ModelType):
95
+ return self.super_call_template(model).format(
96
+ self.properties_to_pass_to_super(model)
97
+ )
98
+
99
+ def initialize_properties(self, model: ModelType) -> List[str]:
75
100
  init_args = []
76
- properties_to_pass_to_super = self.properties_to_pass_to_super(model)
77
- init_args.append(f"super({model.name}, self).__init__({properties_to_pass_to_super})")
78
101
  for prop in ModelBaseSerializer.get_properties_to_initialize(model):
79
102
  if prop.is_discriminator:
80
- discriminator_value = f"'{model.discriminator_value}'" if model.discriminator_value else None
103
+ discriminator_value = (
104
+ f"'{model.discriminator_value}'"
105
+ if model.discriminator_value
106
+ else None
107
+ )
81
108
  if not discriminator_value:
82
109
  typing = "Optional[str]"
83
110
  else:
84
111
  typing = "str"
85
- init_args.append(f"self.{prop.name} = {discriminator_value} # type: {typing}")
112
+ init_args.append(
113
+ f"self.{prop.client_name} = {discriminator_value} # type: {typing}"
114
+ )
86
115
  elif prop.readonly:
87
- init_args.append(f"self.{prop.name} = None")
116
+ init_args.append(f"self.{prop.client_name} = None")
88
117
  elif not prop.constant:
89
118
  init_args.append(self.initialize_standard_arg(prop))
90
119
  return init_args
91
120
 
92
121
  def initialize_standard_property(self, prop: Property):
93
- if prop.required and not prop.default_value:
122
+ if not (prop.optional or prop.client_default_value is not None):
94
123
  return self.required_property_no_default_init(prop)
95
124
  return self.optional_property_init(prop)
96
125
 
126
+ @staticmethod
127
+ def discriminator_docstring(model: ModelType) -> str:
128
+ return (
129
+ "You probably want to use the sub-classes and not this class directly. "
130
+ f"Known sub-classes are: {', '.join(model.discriminated_subtypes.values())}"
131
+ )
132
+
97
133
  @abstractmethod
98
- def init_line(self, model: ObjectSchema) -> List[str]:
134
+ def init_line(self, model: ModelType) -> List[str]:
99
135
  ...
100
136
 
101
137
  @abstractmethod
102
- def properties_to_pass_to_super(self, model: ObjectSchema) -> str:
138
+ def properties_to_pass_to_super(self, model: ModelType) -> str:
103
139
  ...
104
140
 
105
141
  @abstractmethod
@@ -6,28 +6,27 @@
6
6
  from typing import List
7
7
  from jinja2 import Environment
8
8
  from .model_base_serializer import ModelBaseSerializer
9
- from ..models import ObjectSchema, CodeModel, Property
9
+ from ..models import ModelType, CodeModel, Property
10
10
 
11
11
 
12
12
  class ModelGenericSerializer(ModelBaseSerializer):
13
-
14
13
  def __init__(self, code_model: CodeModel, env: Environment) -> None:
15
- super(ModelGenericSerializer, self).__init__(
16
- code_model=code_model, env=env, is_python3_file=False
17
- )
14
+ super().__init__(code_model=code_model, env=env, is_python3_file=False)
18
15
 
19
- def init_line(self, model: ObjectSchema) -> List[str]:
16
+ def init_line(self, model: ModelType) -> List[str]:
20
17
  return []
21
18
 
22
- def properties_to_pass_to_super(self, model: ObjectSchema) -> str:
19
+ def properties_to_pass_to_super(self, model: ModelType) -> str:
23
20
  return "**kwargs"
24
21
 
25
22
  def required_property_no_default_init(self, prop: Property) -> str:
26
- return f"self.{prop.name} = kwargs['{prop.name}']"
23
+ return f"self.{prop.client_name} = kwargs['{prop.client_name}']"
27
24
 
28
25
  def optional_property_init(self, prop: Property) -> str:
29
- default = prop.default_value_declaration
30
- return f"self.{prop.name} = kwargs.get('{prop.name}', {default})"
26
+ return f"self.{prop.client_name} = kwargs.get('{prop.client_name}', {prop.client_default_value_declaration})"
31
27
 
32
28
  def initialize_standard_arg(self, prop: Property) -> str:
33
29
  return self.initialize_standard_property(prop)
30
+
31
+ def super_call_template(self, model: ModelType) -> str:
32
+ return "super(" + model.name + ", self).__init__({})"
@@ -13,9 +13,11 @@ class ModelInitSerializer:
13
13
  self.env = env
14
14
 
15
15
  def serialize(self) -> str:
16
- schemas = [s.name for s in self.code_model.sorted_schemas]
16
+ schemas = [s.name for s in self.code_model.public_model_types]
17
17
  schemas.sort()
18
- enums = [e.name for e in self.code_model.enums.values()] if self.code_model.enums else None
18
+ enums = (
19
+ [e.name for e in self.code_model.enums] if self.code_model.enums else None
20
+ )
19
21
 
20
22
  if enums:
21
23
  enums.sort()