@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
@@ -32,7 +32,7 @@ class MultiApiScriptPlugin(Plugin):
32
32
  output_folder,
33
33
  self._autorestapi,
34
34
  no_async,
35
- user_specified_default_api
35
+ user_specified_default_api,
36
36
  )
37
37
  return generator.process()
38
38
 
@@ -44,10 +44,12 @@ class MultiAPI:
44
44
  output_folder: str,
45
45
  autorestapi: AutorestAPI,
46
46
  no_async: Optional[bool] = False,
47
- user_specified_default_api: Optional[str] = None
47
+ user_specified_default_api: Optional[str] = None,
48
48
  ) -> None:
49
49
  if input_package_name is None:
50
- raise ValueError("package-name is required, either provide it as args or check your readme configuration")
50
+ raise ValueError(
51
+ "package-name is required, either provide it as args or check your readme configuration"
52
+ )
51
53
  self.input_package_name = input_package_name
52
54
  _LOGGER.debug("Received package name %s", input_package_name)
53
55
 
@@ -64,7 +66,7 @@ class MultiAPI:
64
66
  self.mod_to_api_version,
65
67
  [p.name for p in self.paths_to_versions],
66
68
  self.preview_mode,
67
- self.user_specified_default_api
69
+ self.user_specified_default_api,
68
70
  )
69
71
 
70
72
  @property
@@ -75,7 +77,9 @@ class MultiAPI:
75
77
  if self.default_api_version.replace("-", "_") == path_to_version.stem:
76
78
  path_to_default_version = path_to_version
77
79
  break
78
- return json.loads(self._autorestapi.read_file(path_to_default_version / "_metadata.json"))
80
+ return json.loads(
81
+ self._autorestapi.read_file(path_to_default_version / "_metadata.json")
82
+ )
79
83
 
80
84
  @property
81
85
  def module_name(self) -> str:
@@ -96,7 +100,11 @@ class MultiAPI:
96
100
  def preview_mode(self) -> bool:
97
101
  # If True, means the auto-profile will consider preview versions.
98
102
  # If not, if it exists a stable API version for a global or RT, will always be used
99
- return cast(bool, self.user_specified_default_api and "preview" in self.user_specified_default_api)
103
+ return cast(
104
+ bool,
105
+ self.user_specified_default_api
106
+ and "preview" in self.user_specified_default_api,
107
+ )
100
108
 
101
109
  @property
102
110
  def paths_to_versions(self) -> List[Path]:
@@ -105,14 +113,16 @@ class MultiAPI:
105
113
  directory.sort()
106
114
  for child in directory:
107
115
  child_dir = (self.output_folder / child).resolve()
108
- if Path(child_dir / '_metadata.json') in child_dir.iterdir():
116
+ if Path(child_dir / "_metadata.json") in child_dir.iterdir():
109
117
  paths_to_versions.append(Path(child.stem))
110
118
  return paths_to_versions
111
119
 
112
120
  @property
113
121
  def version_path_to_metadata(self) -> Dict[Path, Dict[str, Any]]:
114
122
  return {
115
- version_path: json.loads(self._autorestapi.read_file(version_path / "_metadata.json"))
123
+ version_path: json.loads(
124
+ self._autorestapi.read_file(version_path / "_metadata.json")
125
+ )
116
126
  for version_path in self.paths_to_versions
117
127
  }
118
128
 
@@ -120,18 +130,18 @@ class MultiAPI:
120
130
  def mod_to_api_version(self) -> Dict[str, str]:
121
131
  mod_to_api_version: Dict[str, str] = defaultdict(str)
122
132
  for version_path in self.paths_to_versions:
123
- metadata_json = json.loads(self._autorestapi.read_file(version_path / "_metadata.json"))
124
- version = metadata_json['chosen_version']
125
- total_api_version_list = metadata_json['total_api_version_list']
133
+ metadata_json = json.loads(
134
+ self._autorestapi.read_file(version_path / "_metadata.json")
135
+ )
136
+ version = metadata_json["chosen_version"]
137
+ total_api_version_list = metadata_json["total_api_version_list"]
126
138
  if not version:
127
139
  if total_api_version_list:
128
140
  sys.exit(
129
141
  f"Unable to match {total_api_version_list} to label {version_path.stem}"
130
142
  )
131
143
  else:
132
- sys.exit(
133
- f"Unable to extract api version of {version_path.stem}"
134
- )
144
+ sys.exit(f"Unable to extract api version of {version_path.stem}")
135
145
  mod_to_api_version[version_path.name] = version
136
146
  return mod_to_api_version
137
147
 
@@ -9,54 +9,64 @@ from typing import Any, Dict, List
9
9
  from pathlib import Path
10
10
  from .imports import FileImport
11
11
 
12
+
12
13
  def _extract_version(metadata_json: Dict[str, Any], version_path: Path) -> str:
13
- version = metadata_json['chosen_version']
14
- total_api_version_list = metadata_json['total_api_version_list']
14
+ version = metadata_json["chosen_version"]
15
+ total_api_version_list = metadata_json["total_api_version_list"]
15
16
  if not version:
16
17
  if total_api_version_list:
17
18
  sys.exit(
18
19
  f"Unable to match {total_api_version_list} to label {version_path.stem}"
19
20
  )
20
21
  else:
21
- sys.exit(
22
- f"Unable to extract api version of {version_path.stem}"
23
- )
22
+ sys.exit(f"Unable to extract api version of {version_path.stem}")
24
23
  return version
25
24
 
25
+
26
26
  class Client:
27
27
  def __init__(
28
28
  self,
29
29
  azure_arm: bool,
30
30
  default_version_metadata: Dict[str, Any],
31
- version_path_to_metadata: Dict[Path, Dict[str, Any]]
31
+ version_path_to_metadata: Dict[Path, Dict[str, Any]],
32
32
  ):
33
33
  self.name = default_version_metadata["client"]["name"]
34
34
  self.pipeline_client = "ARMPipelineClient" if azure_arm else "PipelineClient"
35
35
  self.filename = default_version_metadata["client"]["filename"]
36
36
  self.host_value = default_version_metadata["client"]["host_value"]
37
37
  self.description = default_version_metadata["client"]["description"]
38
- self.client_side_validation = default_version_metadata["client"]["client_side_validation"]
38
+ self.client_side_validation = default_version_metadata["client"][
39
+ "client_side_validation"
40
+ ]
39
41
  self.default_version_metadata = default_version_metadata
40
42
  self.version_path_to_metadata = version_path_to_metadata
41
43
 
42
44
  def imports(self, async_mode: bool) -> FileImport:
43
45
  imports_to_load = "async_imports" if async_mode else "sync_imports"
44
- return FileImport(json.loads(self.default_version_metadata['client'][imports_to_load]))
46
+ return FileImport(
47
+ json.loads(self.default_version_metadata["client"][imports_to_load])
48
+ )
45
49
 
46
50
  @property
47
51
  def parameterized_host_template_to_api_version(self) -> Dict[str, List[str]]:
48
52
  parameterized_host_template_to_api_version: Dict[str, List[str]] = {}
49
53
  for version_path, metadata_json in self.version_path_to_metadata.items():
50
- parameterized_host_template = metadata_json["client"]["parameterized_host_template"]
54
+ parameterized_host_template = metadata_json["client"][
55
+ "parameterized_host_template"
56
+ ]
51
57
  version = _extract_version(metadata_json, version_path)
52
- parameterized_host_template_to_api_version.setdefault(parameterized_host_template, []).append(version)
58
+ parameterized_host_template_to_api_version.setdefault(
59
+ parameterized_host_template, []
60
+ ).append(version)
53
61
  return parameterized_host_template_to_api_version
54
62
 
55
63
  @property
56
64
  def has_lro_operations(self) -> bool:
57
65
  has_lro_operations = False
58
66
  for _, metadata_json in self.version_path_to_metadata.items():
59
- current_client_has_lro_operations = metadata_json["client"]["has_lro_operations"]
67
+ current_client_has_lro_operations = metadata_json["client"][
68
+ "has_lro_operations"
69
+ ]
60
70
  if current_client_has_lro_operations:
61
71
  has_lro_operations = True
62
72
  return has_lro_operations
@@ -13,6 +13,7 @@ from .operation_mixin_group import OperationMixinGroup
13
13
  from .global_parameters import GlobalParameters
14
14
  from ..utils import _get_default_api_version_from_list
15
15
 
16
+
16
17
  class CodeModel: # pylint: disable=too-many-instance-attributes
17
18
  def __init__(
18
19
  self,
@@ -23,7 +24,7 @@ class CodeModel: # pylint: disable=too-many-instance-attributes
23
24
  default_version_metadata: Dict[str, Any],
24
25
  mod_to_api_version: Dict[str, str],
25
26
  version_path_to_metadata: Dict[Path, Dict[str, Any]],
26
- user_specified_default_api: Optional[str] = None
27
+ user_specified_default_api: Optional[str] = None,
27
28
  ):
28
29
  self.module_name = module_name
29
30
  self.package_name = package_name
@@ -33,9 +34,13 @@ class CodeModel: # pylint: disable=too-many-instance-attributes
33
34
  self.azure_arm = default_version_metadata["client"]["azure_arm"]
34
35
  self.default_version_metadata = default_version_metadata
35
36
  self.version_path_to_metadata = version_path_to_metadata
36
- self.service_client = Client(self.azure_arm, default_version_metadata, version_path_to_metadata)
37
+ self.client = Client(
38
+ self.azure_arm, default_version_metadata, version_path_to_metadata
39
+ )
37
40
  self.config = Config(default_version_metadata)
38
- self.operation_mixin_group = OperationMixinGroup(version_path_to_metadata, default_api_version)
41
+ self.operation_mixin_group = OperationMixinGroup(
42
+ version_path_to_metadata, default_api_version
43
+ )
39
44
  self.global_parameters = GlobalParameters(
40
45
  default_version_metadata["global_parameters"]
41
46
  )
@@ -45,17 +50,24 @@ class CodeModel: # pylint: disable=too-many-instance-attributes
45
50
  def operation_groups(self) -> List[OperationGroup]:
46
51
  operation_groups: List[OperationGroup] = []
47
52
  for version_path, metadata_json in self.version_path_to_metadata.items():
48
- if not metadata_json.get('operation_groups'):
53
+ if not metadata_json.get("operation_groups"):
49
54
  continue
50
- operation_groups_metadata = metadata_json['operation_groups']
51
- for operation_group_name, operation_group_class_name in operation_groups_metadata.items():
55
+ operation_groups_metadata = metadata_json["operation_groups"]
56
+ for (
57
+ operation_group_name,
58
+ operation_group_class_name,
59
+ ) in operation_groups_metadata.items():
52
60
  try:
53
- operation_group = [og for og in operation_groups if og.name == operation_group_name][0]
61
+ operation_group = [
62
+ og for og in operation_groups if og.name == operation_group_name
63
+ ][0]
54
64
  except IndexError:
55
65
  operation_group = OperationGroup(operation_group_name)
56
66
  operation_groups.append(operation_group)
57
67
  operation_group.append_available_api(version_path.name)
58
- operation_group.append_api_class_name_pair(version_path.name, operation_group_class_name)
68
+ operation_group.append_api_class_name_pair(
69
+ version_path.name, operation_group_class_name
70
+ )
59
71
  operation_groups.sort(key=lambda x: x.name)
60
72
  return operation_groups
61
73
 
@@ -110,7 +122,7 @@ class CodeModel: # pylint: disable=too-many-instance-attributes
110
122
  self.mod_to_api_version,
111
123
  api_versions_list,
112
124
  self.preview_mode,
113
- self.user_specified_default_api
125
+ self.user_specified_default_api,
114
126
  )
115
127
  if local_default_api_version == self.default_api_version:
116
128
  continue
@@ -129,5 +141,6 @@ class CodeModel: # pylint: disable=too-many-instance-attributes
129
141
  @property
130
142
  def default_models(self):
131
143
  return sorted(
132
- {self.default_api_version} | {versions for _, versions in self.last_rt_list.items()}
144
+ {self.default_api_version}
145
+ | {versions for _, versions in self.last_rt_list.items()}
133
146
  )
@@ -7,6 +7,7 @@ import json
7
7
  from typing import Any, Dict
8
8
  from .imports import FileImport
9
9
 
10
+
10
11
  class Config:
11
12
  def __init__(self, default_version_metadata: Dict[str, Any]):
12
13
  self.credential = default_version_metadata["config"]["credential"]
@@ -15,7 +16,9 @@ class Config:
15
16
 
16
17
  def imports(self, async_mode: bool) -> FileImport:
17
18
  imports_to_load = "async_imports" if async_mode else "sync_imports"
18
- return FileImport(json.loads(self.default_version_metadata['config'][imports_to_load]))
19
+ return FileImport(
20
+ json.loads(self.default_version_metadata["config"][imports_to_load])
21
+ )
19
22
 
20
23
  def credential_call(self, async_mode: bool) -> str:
21
24
  if async_mode:
@@ -4,6 +4,7 @@
4
4
  # license information.
5
5
  # --------------------------------------------------------------------------
6
6
 
7
+
7
8
  class ConstantGlobalParameter:
8
9
  def __init__(self, name: str, value: str):
9
10
  self.name = name
@@ -5,12 +5,13 @@
5
5
  # --------------------------------------------------------------------------
6
6
  from typing import Any, Dict
7
7
 
8
+
8
9
  class GlobalParameter:
9
10
  def __init__(
10
11
  self,
11
12
  name: str,
12
13
  global_parameter_metadata_sync: Dict[str, Any],
13
- global_parameter_metadata_async: Dict[str, Any]
14
+ global_parameter_metadata_async: Dict[str, Any],
14
15
  ):
15
16
  self.name = name
16
17
  self.global_parameter_metadata_sync = global_parameter_metadata_sync
@@ -7,17 +7,19 @@ from typing import Any, Dict, List
7
7
  from .global_parameter import GlobalParameter
8
8
  from .constant_global_parameter import ConstantGlobalParameter
9
9
 
10
+
10
11
  def _convert_global_parameters(sync_metadata, async_metadata):
11
12
  global_parameters = [
12
13
  GlobalParameter(
13
14
  name=parameter_name,
14
15
  global_parameter_metadata_sync=gp_sync,
15
- global_parameter_metadata_async=async_metadata[parameter_name]
16
+ global_parameter_metadata_async=async_metadata[parameter_name],
16
17
  )
17
18
  for parameter_name, gp_sync in sync_metadata.items()
18
19
  ]
19
20
  return global_parameters
20
21
 
22
+
21
23
  class GlobalParameters:
22
24
  def __init__(
23
25
  self,
@@ -31,12 +33,15 @@ class GlobalParameters:
31
33
  """Return global params specific to multiapi service client + config
32
34
  api_version, endpoint (re-adding it in specific are), and profile
33
35
  """
34
- service_client_params_sync = self.global_parameters_metadata["service_client_specific"]["sync"]
35
- service_client_params_async = self.global_parameters_metadata["service_client_specific"]["async"]
36
+ service_client_params_sync = self.global_parameters_metadata[
37
+ "service_client_specific"
38
+ ]["sync"]
39
+ service_client_params_async = self.global_parameters_metadata[
40
+ "service_client_specific"
41
+ ]["async"]
36
42
 
37
43
  return _convert_global_parameters(
38
- service_client_params_sync,
39
- service_client_params_async
44
+ service_client_params_sync, service_client_params_async
40
45
  )
41
46
 
42
47
  @property
@@ -45,13 +50,14 @@ class GlobalParameters:
45
50
  global_parameters_metadata_async = self.global_parameters_metadata["async"]
46
51
 
47
52
  return _convert_global_parameters(
48
- global_parameters_metadata_sync,
49
- global_parameters_metadata_async
53
+ global_parameters_metadata_sync, global_parameters_metadata_async
50
54
  )
51
55
 
52
56
  @property
53
57
  def constant_parameters(self) -> List[ConstantGlobalParameter]:
54
58
  return [
55
59
  ConstantGlobalParameter(constant_name, constant_value)
56
- for constant_name, constant_value in self.global_parameters_metadata["constant"].items()
60
+ for constant_name, constant_value in self.global_parameters_metadata[
61
+ "constant"
62
+ ].items()
57
63
  ]
@@ -4,7 +4,7 @@
4
4
  # license information.
5
5
  # --------------------------------------------------------------------------
6
6
  from enum import Enum
7
- from typing import Dict, Optional, Set
7
+ from typing import Dict, Optional, Set, Union, Tuple
8
8
 
9
9
 
10
10
  class ImportType(str, Enum):
@@ -13,6 +13,7 @@ class ImportType(str, Enum):
13
13
  AZURECORE = "azurecore"
14
14
  LOCAL = "local"
15
15
 
16
+
16
17
  class TypingSection(str, Enum):
17
18
  REGULAR = "regular" # this import is always a typing import
18
19
  CONDITIONAL = "conditional" # is a typing import when we're dealing with files that py2 will use, else regular
@@ -21,52 +22,66 @@ class TypingSection(str, Enum):
21
22
 
22
23
  class FileImport:
23
24
  def __init__(
24
- self, imports: Dict[TypingSection, Dict[ImportType, Dict[str, Set[Optional[str]]]]] = None
25
+ self,
26
+ imports: Dict[
27
+ TypingSection,
28
+ Dict[ImportType, Dict[str, Set[Optional[Union[str, Tuple[str, str]]]]]],
29
+ ] = None,
25
30
  ) -> None:
26
31
  # Basic implementation
27
32
  # First level dict: TypingSection
28
33
  # Second level dict: ImportType
29
34
  # Third level dict: the package name.
30
35
  # Fourth level set: None if this import is a "import", the name to import if it's a "from"
31
- self._imports: Dict[TypingSection, Dict[ImportType, Dict[str, Set[Optional[str]]]]] = imports or dict()
36
+ self._imports: Dict[
37
+ TypingSection,
38
+ Dict[ImportType, Dict[str, Set[Optional[Union[str, Tuple[str, str]]]]]],
39
+ ] = (
40
+ imports or dict()
41
+ )
32
42
 
33
43
  def _add_import(
34
44
  self,
35
45
  from_section: str,
36
46
  import_type: ImportType,
37
- name_import: Optional[str] = None,
38
- typing_section: TypingSection = TypingSection.REGULAR
47
+ name_import: Optional[Union[str, Tuple[str, str]]] = None,
48
+ typing_section: TypingSection = TypingSection.REGULAR,
39
49
  ) -> None:
40
- self._imports.setdefault(
41
- typing_section, dict()
42
- ).setdefault(
43
- import_type, dict()
44
- ).setdefault(
45
- from_section, set()
46
- ).add(name_import)
50
+ name_input: Optional[Union[str, Tuple[str, str]]] = None
51
+ if isinstance(name_import, list):
52
+ name_input = tuple(name_import)
53
+ else:
54
+ name_input = name_import
55
+ self._imports.setdefault(typing_section, dict()).setdefault(
56
+ import_type, dict()
57
+ ).setdefault(from_section, set()).add(name_input)
47
58
 
48
59
  def add_submodule_import(
49
60
  self,
50
61
  from_section: str,
51
62
  name_import: str,
52
63
  import_type: ImportType,
53
- typing_section: TypingSection = TypingSection.REGULAR
64
+ typing_section: TypingSection = TypingSection.REGULAR,
54
65
  ) -> None:
55
- """Add an import to this import block.
56
- """
66
+ """Add an import to this import block."""
57
67
  self._add_import(from_section, import_type, name_import, typing_section)
58
68
 
59
69
  def add_import(
60
70
  self,
61
71
  name_import: str,
62
72
  import_type: ImportType,
63
- typing_section: TypingSection = TypingSection.REGULAR
73
+ typing_section: TypingSection = TypingSection.REGULAR,
64
74
  ) -> None:
65
75
  # Implementation detail: a regular import is just a "from" with no from
66
76
  self._add_import(name_import, import_type, None, typing_section)
67
77
 
68
78
  @property
69
- def imports(self) -> Dict[TypingSection, Dict[ImportType, Dict[str, Set[Optional[str]]]]]:
79
+ def imports(
80
+ self,
81
+ ) -> Dict[
82
+ TypingSection,
83
+ Dict[ImportType, Dict[str, Set[Optional[Union[str, Tuple[str, str]]]]]],
84
+ ]:
70
85
  return self._imports
71
86
 
72
87
  def merge(self, file_import: "FileImport") -> None:
@@ -75,4 +90,6 @@ class FileImport:
75
90
  for import_type, package_list in import_type_dict.items():
76
91
  for package_name, module_list in package_list.items():
77
92
  for module_name in module_list:
78
- self._add_import(package_name, import_type, module_name, typing_section)
93
+ self._add_import(
94
+ package_name, import_type, module_name, typing_section
95
+ )
@@ -6,15 +6,19 @@
6
6
  from typing import Any, Dict, List, TypeVar
7
7
  from ..utils import _sync_or_async
8
8
 
9
- T = TypeVar('T')
9
+ T = TypeVar("T")
10
10
  OrderedSet = Dict[T, None]
11
11
 
12
+
12
13
  class MixinOperation:
13
14
  def __init__(self, name: str, mixin_operation_metadata: Dict[str, Any]):
14
15
  self.name = name
15
16
  self.mixin_operation_metadata = mixin_operation_metadata
16
17
  self._available_apis: OrderedSet[str] = {}
17
18
 
19
+ def call(self, async_mode: bool) -> str:
20
+ return self.mixin_operation_metadata[_sync_or_async(async_mode)]["call"]
21
+
18
22
  def signature(self, async_mode: bool) -> str:
19
23
  return self.mixin_operation_metadata[_sync_or_async(async_mode)]["signature"]
20
24
 
@@ -26,10 +30,6 @@ class MixinOperation:
26
30
  return False
27
31
  return self.mixin_operation_metadata["async"]["coroutine"]
28
32
 
29
- @property
30
- def call(self) -> str:
31
- return self.mixin_operation_metadata["call"]
32
-
33
33
  @property
34
34
  def available_apis(self) -> List[str]:
35
35
  return list(self._available_apis.keys())
@@ -5,9 +5,10 @@
5
5
  # --------------------------------------------------------------------------
6
6
  from typing import Dict, List, TypeVar
7
7
 
8
- T = TypeVar('T')
8
+ T = TypeVar("T")
9
9
  OrderedSet = Dict[T, None]
10
10
 
11
+
11
12
  class OperationGroup:
12
13
  def __init__(self, name: str):
13
14
  self.name = name
@@ -9,11 +9,12 @@ from pathlib import Path
9
9
  from .imports import FileImport
10
10
  from .mixin_operation import MixinOperation
11
11
 
12
+
12
13
  class OperationMixinGroup:
13
14
  def __init__(
14
15
  self,
15
16
  version_path_to_metadata: Dict[Path, Dict[str, Any]],
16
- default_api_version: str
17
+ default_api_version: str,
17
18
  ):
18
19
  self.default_api_version = default_api_version
19
20
  self.version_path_to_metadata = version_path_to_metadata
@@ -22,9 +23,9 @@ class OperationMixinGroup:
22
23
  imports = FileImport()
23
24
  imports_to_load = "async_imports" if async_mode else "sync_imports"
24
25
  for metadata_json in self.version_path_to_metadata.values():
25
- if not metadata_json.get('operation_mixins'):
26
+ if not metadata_json.get("operation_mixins"):
26
27
  continue
27
- mixin_imports = metadata_json['operation_mixins'][imports_to_load]
28
+ mixin_imports = metadata_json["operation_mixins"][imports_to_load]
28
29
  if mixin_imports != "None":
29
30
  current_version_imports = FileImport(json.loads(mixin_imports))
30
31
  imports.merge(current_version_imports)
@@ -34,20 +35,24 @@ class OperationMixinGroup:
34
35
  self, mixin_operations: List[MixinOperation]
35
36
  ) -> List[MixinOperation]:
36
37
  default_api_version_path = [
37
- version_path for version_path in self.version_path_to_metadata.keys()
38
+ version_path
39
+ for version_path in self.version_path_to_metadata.keys()
38
40
  if version_path.name == self.default_api_version
39
41
  ][0]
40
- default_version_metadata = self.version_path_to_metadata[default_api_version_path]
42
+ default_version_metadata = self.version_path_to_metadata[
43
+ default_api_version_path
44
+ ]
41
45
  if not default_version_metadata.get("operation_mixins"):
42
46
  return mixin_operations
43
- for name, metadata in default_version_metadata["operation_mixins"]["operations"].items():
47
+ for name, metadata in default_version_metadata["operation_mixins"][
48
+ "operations"
49
+ ].items():
44
50
  if name.startswith("_"):
45
51
  continue
46
52
  mixin_operation = [mo for mo in mixin_operations if mo.name == name][0]
47
53
  mixin_operation.mixin_operation_metadata = metadata
48
54
  return mixin_operations
49
55
 
50
-
51
56
  @property
52
57
  def mixin_operations(self) -> List[MixinOperation]:
53
58
  mixin_operations: List[MixinOperation] = []
@@ -55,14 +60,20 @@ class OperationMixinGroup:
55
60
  if not metadata_json.get("operation_mixins"):
56
61
  continue
57
62
  mixin_operations_metadata = metadata_json["operation_mixins"]["operations"]
58
- for mixin_operation_name, mixin_operation_metadata in mixin_operations_metadata.items():
63
+ for (
64
+ mixin_operation_name,
65
+ mixin_operation_metadata,
66
+ ) in mixin_operations_metadata.items():
59
67
  if mixin_operation_name.startswith("_"):
60
68
  continue
61
69
  try:
62
- mixin_operation = [mo for mo in mixin_operations if mo.name == mixin_operation_name][0]
70
+ mixin_operation = [
71
+ mo for mo in mixin_operations if mo.name == mixin_operation_name
72
+ ][0]
63
73
  except IndexError:
64
74
  mixin_operation = MixinOperation(
65
- name=mixin_operation_name, mixin_operation_metadata=mixin_operation_metadata
75
+ name=mixin_operation_name,
76
+ mixin_operation_metadata=mixin_operation_metadata,
66
77
  )
67
78
  mixin_operations.append(mixin_operation)
68
79
  mixin_operation.append_available_api(version_path.name)