@autorest/python 5.15.0 → 5.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 (86) hide show
  1. package/ChangeLog.md +20 -0
  2. package/autorest/__init__.py +1 -2
  3. package/autorest/black/__init__.py +12 -5
  4. package/autorest/codegen/__init__.py +145 -73
  5. package/autorest/codegen/models/__init__.py +29 -18
  6. package/autorest/codegen/models/base_builder.py +48 -11
  7. package/autorest/codegen/models/base_model.py +6 -4
  8. package/autorest/codegen/models/base_schema.py +19 -18
  9. package/autorest/codegen/models/client.py +65 -21
  10. package/autorest/codegen/models/code_model.py +107 -61
  11. package/autorest/codegen/models/constant_schema.py +25 -13
  12. package/autorest/codegen/models/credential_model.py +23 -15
  13. package/autorest/codegen/models/credential_schema.py +18 -14
  14. package/autorest/codegen/models/credential_schema_policy.py +11 -15
  15. package/autorest/codegen/models/dictionary_schema.py +20 -17
  16. package/autorest/codegen/models/enum_schema.py +35 -25
  17. package/autorest/codegen/models/imports.py +70 -41
  18. package/autorest/codegen/models/list_schema.py +25 -13
  19. package/autorest/codegen/models/lro_operation.py +58 -22
  20. package/autorest/codegen/models/lro_paging_operation.py +2 -3
  21. package/autorest/codegen/models/object_schema.py +99 -49
  22. package/autorest/codegen/models/operation.py +236 -117
  23. package/autorest/codegen/models/operation_group.py +64 -34
  24. package/autorest/codegen/models/paging_operation.py +45 -18
  25. package/autorest/codegen/models/parameter.py +151 -83
  26. package/autorest/codegen/models/parameter_list.py +183 -162
  27. package/autorest/codegen/models/primitive_schemas.py +84 -55
  28. package/autorest/codegen/models/property.py +44 -26
  29. package/autorest/codegen/models/request_builder.py +65 -30
  30. package/autorest/codegen/models/request_builder_parameter.py +47 -23
  31. package/autorest/codegen/models/request_builder_parameter_list.py +77 -108
  32. package/autorest/codegen/models/schema_request.py +16 -6
  33. package/autorest/codegen/models/schema_response.py +18 -13
  34. package/autorest/codegen/models/utils.py +5 -2
  35. package/autorest/codegen/serializers/__init__.py +182 -91
  36. package/autorest/codegen/serializers/builder_serializer.py +667 -331
  37. package/autorest/codegen/serializers/client_serializer.py +98 -37
  38. package/autorest/codegen/serializers/general_serializer.py +61 -26
  39. package/autorest/codegen/serializers/import_serializer.py +93 -31
  40. package/autorest/codegen/serializers/metadata_serializer.py +73 -24
  41. package/autorest/codegen/serializers/model_base_serializer.py +35 -15
  42. package/autorest/codegen/serializers/model_generic_serializer.py +1 -4
  43. package/autorest/codegen/serializers/model_init_serializer.py +5 -1
  44. package/autorest/codegen/serializers/model_python3_serializer.py +7 -6
  45. package/autorest/codegen/serializers/operation_groups_serializer.py +20 -9
  46. package/autorest/codegen/serializers/operations_init_serializer.py +23 -11
  47. package/autorest/codegen/serializers/patch_serializer.py +4 -1
  48. package/autorest/codegen/serializers/{rest_serializer.py → request_builders_serializer.py} +29 -12
  49. package/autorest/codegen/serializers/utils.py +35 -21
  50. package/autorest/codegen/templates/init.py.jinja2 +2 -2
  51. package/autorest/codegen/templates/lro_operation.py.jinja2 +5 -7
  52. package/autorest/codegen/templates/lro_paging_operation.py.jinja2 +5 -7
  53. package/autorest/codegen/templates/metadata.json.jinja2 +7 -6
  54. package/autorest/codegen/templates/operation.py.jinja2 +7 -9
  55. package/autorest/codegen/templates/operation_group.py.jinja2 +2 -8
  56. package/autorest/codegen/templates/operation_groups_container.py.jinja2 +1 -1
  57. package/autorest/codegen/templates/paging_operation.py.jinja2 +7 -8
  58. package/autorest/codegen/templates/request_builder.py.jinja2 +18 -11
  59. package/autorest/jsonrpc/__init__.py +7 -12
  60. package/autorest/jsonrpc/localapi.py +4 -3
  61. package/autorest/jsonrpc/server.py +13 -6
  62. package/autorest/jsonrpc/stdstream.py +13 -6
  63. package/autorest/m2r/__init__.py +5 -8
  64. package/autorest/multiapi/__init__.py +24 -14
  65. package/autorest/multiapi/models/client.py +21 -11
  66. package/autorest/multiapi/models/code_model.py +23 -10
  67. package/autorest/multiapi/models/config.py +4 -1
  68. package/autorest/multiapi/models/constant_global_parameter.py +1 -0
  69. package/autorest/multiapi/models/global_parameter.py +2 -1
  70. package/autorest/multiapi/models/global_parameters.py +14 -8
  71. package/autorest/multiapi/models/imports.py +24 -17
  72. package/autorest/multiapi/models/mixin_operation.py +5 -5
  73. package/autorest/multiapi/models/operation_group.py +2 -1
  74. package/autorest/multiapi/models/operation_mixin_group.py +21 -10
  75. package/autorest/multiapi/serializers/__init__.py +18 -23
  76. package/autorest/multiapi/serializers/import_serializer.py +47 -17
  77. package/autorest/multiapi/serializers/multiapi_serializer.py +17 -17
  78. package/autorest/multiapi/templates/multiapi_operations_mixin.py.jinja2 +1 -1
  79. package/autorest/multiapi/utils.py +3 -3
  80. package/autorest/namer/__init__.py +2 -4
  81. package/autorest/namer/name_converter.py +200 -103
  82. package/autorest/namer/python_mappings.py +10 -22
  83. package/package.json +2 -2
  84. package/run-python3.js +2 -3
  85. package/venvtools.py +1 -1
  86. package/autorest/codegen/models/rest.py +0 -42
@@ -3,14 +3,18 @@
3
3
  # Licensed under the MIT License. See License.txt in the project root for
4
4
  # license information.
5
5
  # --------------------------------------------------------------------------
6
- from typing import Any, Callable, Dict, List, Optional, Union
6
+ from typing import Any, Callable, Dict, List, Optional, Union, TYPE_CHECKING
7
7
  from .base_model import BaseModel
8
8
  from .schema_response import SchemaResponse
9
9
  from .schema_request import SchemaRequest
10
10
 
11
+ if TYPE_CHECKING:
12
+ from .code_model import CodeModel
13
+
11
14
 
12
15
  _M4_HEADER_PARAMETERS = ["content_type", "accept"]
13
16
 
17
+
14
18
  def create_parameters(
15
19
  yaml_data: Dict[str, Any], code_model, parameter_creator: Callable
16
20
  ):
@@ -40,9 +44,8 @@ def create_parameters(
40
44
  )
41
45
  if len(body_parameters_name_set) > 1:
42
46
  raise ValueError(
43
- f"The body parameter with multiple media types has different names: {body_parameters_name_set}"
44
- )
45
-
47
+ f"The body parameter with multiple media types has different names: {body_parameters_name_set}"
48
+ )
46
49
 
47
50
  parameters_index = {id(parameter.yaml_data): parameter for parameter in parameters}
48
51
 
@@ -58,34 +61,58 @@ def create_parameters(
58
61
 
59
62
  return parameters, multiple_content_type_parameters
60
63
 
64
+
61
65
  class BaseBuilder(BaseModel):
62
66
  """Base class for Operations and Request Builders"""
63
67
 
64
68
  def __init__(
65
69
  self,
66
- code_model,
67
70
  yaml_data: Dict[str, Any],
71
+ code_model: "CodeModel",
68
72
  name: str,
69
73
  description: str,
70
74
  parameters,
71
75
  schema_requests: List[SchemaRequest],
72
76
  responses: Optional[List[SchemaResponse]] = None,
73
77
  summary: Optional[str] = None,
78
+ *,
79
+ abstract: bool = False,
80
+ want_tracing: bool = True,
74
81
  ) -> None:
75
- super().__init__(yaml_data=yaml_data)
76
- self.code_model = code_model
82
+ super().__init__(yaml_data=yaml_data, code_model=code_model)
77
83
  self.name = name
78
- self.description = description
84
+ self._description = description
79
85
  self.parameters = parameters
80
86
  self.responses = responses or []
81
- self.summary = summary
87
+ self._summary = summary
82
88
  self.schema_requests = schema_requests
89
+ # for operations where we don't know what to do, we mark them as abstract so users implement
90
+ # in patch.py
91
+ self.abstract = abstract
92
+ self.want_tracing = want_tracing
93
+
94
+ @property
95
+ def summary(self) -> Optional[str]:
96
+ if self.abstract:
97
+ return None
98
+ return self._summary
99
+
100
+ @property
101
+ def description(self) -> str:
102
+ if self.abstract:
103
+ return (
104
+ f'You need to write a custom operation for "{self.name}". Please refer to '
105
+ "https://aka.ms/azsdk/python/dpcodegen/python/customize to learn how to customize."
106
+ )
107
+ return self._description
83
108
 
84
109
  @property
85
110
  def default_content_type_declaration(self) -> str:
86
111
  return f'"{self.parameters.default_content_type}"'
87
112
 
88
- def get_response_from_status(self, status_code: Optional[Union[str, int]]) -> SchemaResponse:
113
+ def get_response_from_status(
114
+ self, status_code: Optional[Union[str, int]]
115
+ ) -> SchemaResponse:
89
116
  for response in self.responses:
90
117
  if status_code in response.status_codes:
91
118
  return response
@@ -94,4 +121,14 @@ class BaseBuilder(BaseModel):
94
121
  @property
95
122
  def success_status_code(self) -> List[Union[str, int]]:
96
123
  """The list of all successfull status code."""
97
- return [code for response in self.responses for code in response.status_codes if code != "default"]
124
+ return [
125
+ code
126
+ for response in self.responses
127
+ for code in response.status_codes
128
+ if code != "default"
129
+ ]
130
+
131
+ def method_signature(self, is_python3_file: bool) -> List[str]:
132
+ if self.abstract:
133
+ return ["*args,", "**kwargs"]
134
+ return self.parameters.method_signature(is_python3_file)
@@ -3,7 +3,10 @@
3
3
  # Licensed under the MIT License. See License.txt in the project root for
4
4
  # license information.
5
5
  # --------------------------------------------------------------------------
6
- from typing import Any, Dict
6
+ from typing import Any, Dict, TYPE_CHECKING
7
+
8
+ if TYPE_CHECKING:
9
+ from .code_model import CodeModel
7
10
 
8
11
 
9
12
  class BaseModel:
@@ -13,10 +16,9 @@ class BaseModel:
13
16
  :type yaml_data: dict[str, Any]
14
17
  """
15
18
 
16
- def __init__(
17
- self, yaml_data: Dict[str, Any],
18
- ) -> None:
19
+ def __init__(self, yaml_data: Dict[str, Any], code_model: "CodeModel") -> None:
19
20
  self.yaml_data = yaml_data
21
+ self.code_model = code_model
20
22
 
21
23
  @property
22
24
  def id(self) -> int:
@@ -4,11 +4,14 @@
4
4
  # license information.
5
5
  # --------------------------------------------------------------------------
6
6
  from abc import ABC, abstractmethod
7
- from typing import Any, Dict, List, Optional, Union
7
+ from typing import Any, Dict, List, Optional, Union, TYPE_CHECKING
8
8
 
9
9
  from .base_model import BaseModel
10
10
  from .imports import FileImport
11
11
 
12
+ if TYPE_CHECKING:
13
+ from .code_model import CodeModel
14
+
12
15
 
13
16
  class BaseSchema(BaseModel, ABC):
14
17
  """This is the base class for all schema models.
@@ -17,18 +20,19 @@ class BaseSchema(BaseModel, ABC):
17
20
  :type yaml_data: dict[str, Any]
18
21
  """
19
22
 
20
- def __init__(self, namespace: str, yaml_data: Dict[str, Any]) -> None:
21
- super().__init__(yaml_data)
22
- self.namespace = namespace
23
+ def __init__(self, yaml_data: Dict[str, Any], code_model: "CodeModel") -> None:
24
+ super().__init__(yaml_data, code_model)
23
25
  self.default_value = yaml_data.get("defaultValue", None)
24
26
  self.xml_metadata = yaml_data.get("serialization", {}).get("xml", {})
25
- self.api_versions = set(value_dict["version"] for value_dict in yaml_data.get("apiVersions", []))
27
+ self.api_versions = set(
28
+ value_dict["version"] for value_dict in yaml_data.get("apiVersions", [])
29
+ )
26
30
 
27
31
  @classmethod
28
32
  def from_yaml(
29
- cls, namespace: str, yaml_data: Dict[str, Any], **kwargs # pylint: disable=unused-argument
33
+ cls, yaml_data: Dict[str, Any], code_model: "CodeModel"
30
34
  ) -> "BaseSchema":
31
- return cls(namespace=namespace, yaml_data=yaml_data)
35
+ return cls(yaml_data=yaml_data, code_model=code_model)
32
36
 
33
37
  @property
34
38
  def extra_description_information(self) -> str:
@@ -77,8 +81,7 @@ class BaseSchema(BaseModel, ABC):
77
81
  @property
78
82
  @abstractmethod
79
83
  def docstring_text(self) -> str:
80
- """The names used in rtype documentation
81
- """
84
+ """The names used in rtype documentation"""
82
85
  ...
83
86
 
84
87
  @property
@@ -113,26 +116,24 @@ class BaseSchema(BaseModel, ABC):
113
116
 
114
117
  @property
115
118
  def default_value_declaration(self) -> str:
116
- """Return the default value as string using get_declaration.
117
- """
119
+ """Return the default value as string using get_declaration."""
118
120
  if self.default_value is None:
119
121
  return "None"
120
122
  return self.get_declaration(self.default_value)
121
123
 
122
124
  @property
123
- def validation_map(self) -> Optional[Dict[str, Union[bool, int, str]]]: # pylint: disable=no-self-use
125
+ def validation_map(
126
+ self,
127
+ ) -> Optional[Dict[str, Union[bool, int, str]]]: # pylint: disable=no-self-use
124
128
  return None
125
129
 
126
130
  @property
127
- def serialization_constraints(self) -> Optional[List[str]]: # pylint: disable=no-self-use
131
+ def serialization_constraints(
132
+ self,
133
+ ) -> Optional[List[str]]: # pylint: disable=no-self-use
128
134
  return None
129
135
 
130
136
  @abstractmethod
131
137
  def get_json_template_representation(self, **kwargs: Any) -> Any:
132
138
  """Template of what this schema would look like as JSON input"""
133
139
  ...
134
-
135
- @abstractmethod
136
- def get_files_and_data_template_representation(self, **kwargs: Any) -> Any:
137
- """Template of what this schema would look like as files input"""
138
- ...
@@ -3,15 +3,18 @@
3
3
  # Licensed under the MIT License. See License.txt in the project root for
4
4
  # license information.
5
5
  # --------------------------------------------------------------------------
6
- from typing import List, Optional
6
+ from typing import List, Optional, TYPE_CHECKING
7
7
  from .parameter_list import GlobalParameterList
8
8
  from .imports import FileImport, ImportType, TypingSection
9
9
 
10
+ if TYPE_CHECKING:
11
+ from .code_model import CodeModel
12
+
13
+
10
14
  class Client:
11
- """A service client.
12
- """
15
+ """A service client."""
13
16
 
14
- def __init__(self, code_model, parameters: GlobalParameterList):
17
+ def __init__(self, code_model: "CodeModel", parameters: GlobalParameterList):
15
18
  self.code_model = code_model
16
19
  self.parameters = parameters
17
20
  self.parameterized_host_template: Optional[str] = None
@@ -34,14 +37,26 @@ class Client:
34
37
  file_import = FileImport()
35
38
 
36
39
  file_import.add_submodule_import("msrest", "Serializer", ImportType.THIRDPARTY)
37
- file_import.add_submodule_import("msrest", "Deserializer", ImportType.THIRDPARTY)
38
- file_import.add_submodule_import("typing", "Any", ImportType.STDLIB, TypingSection.CONDITIONAL)
40
+ file_import.add_submodule_import(
41
+ "msrest", "Deserializer", ImportType.THIRDPARTY
42
+ )
43
+ file_import.add_submodule_import(
44
+ "typing", "Any", ImportType.STDLIB, TypingSection.CONDITIONAL
45
+ )
39
46
 
40
47
  any_optional_gp = any(not gp.required for gp in self.parameters)
41
48
 
42
- legacy = not any(g for g in ["low_level_client", "version_tolerant"] if g in self.code_model.options)
43
- if any_optional_gp or (legacy and self.code_model.service_client.parameters.host):
44
- file_import.add_submodule_import("typing", "Optional", ImportType.STDLIB, TypingSection.CONDITIONAL)
49
+ legacy = not any(
50
+ g
51
+ for g in ["low_level_client", "version_tolerant"]
52
+ if g in self.code_model.options
53
+ )
54
+ if any_optional_gp or (
55
+ legacy and self.code_model.service_client.parameters.host
56
+ ):
57
+ file_import.add_submodule_import(
58
+ "typing", "Optional", ImportType.STDLIB, TypingSection.CONDITIONAL
59
+ )
45
60
 
46
61
  if self.code_model.options["azure_arm"]:
47
62
  file_import.add_submodule_import(
@@ -55,8 +70,9 @@ class Client:
55
70
  for gp in self.code_model.global_parameters:
56
71
  file_import.merge(gp.imports())
57
72
  file_import.add_submodule_import(
58
- "._configuration", f"{self.code_model.class_name}Configuration",
59
- ImportType.LOCAL
73
+ "._configuration",
74
+ f"{self.code_model.class_name}Configuration",
75
+ ImportType.LOCAL,
60
76
  )
61
77
 
62
78
  return file_import
@@ -66,18 +82,29 @@ class Client:
66
82
  if async_mode:
67
83
  file_import.add_submodule_import("typing", "Awaitable", ImportType.STDLIB)
68
84
  file_import.add_submodule_import(
69
- "azure.core.rest", "AsyncHttpResponse", ImportType.AZURECORE, TypingSection.CONDITIONAL
85
+ "azure.core.rest",
86
+ "AsyncHttpResponse",
87
+ ImportType.AZURECORE,
88
+ TypingSection.CONDITIONAL,
70
89
  )
71
90
  else:
72
91
  file_import.add_submodule_import(
73
- "azure.core.rest", "HttpResponse", ImportType.AZURECORE, TypingSection.CONDITIONAL
92
+ "azure.core.rest",
93
+ "HttpResponse",
94
+ ImportType.AZURECORE,
95
+ TypingSection.CONDITIONAL,
74
96
  )
75
97
  file_import.add_submodule_import(
76
- "azure.core.rest", "HttpRequest", ImportType.AZURECORE, TypingSection.CONDITIONAL
98
+ "azure.core.rest",
99
+ "HttpRequest",
100
+ ImportType.AZURECORE,
101
+ TypingSection.CONDITIONAL,
77
102
  )
78
103
  for og in self.code_model.operation_groups:
79
104
  file_import.add_submodule_import(
80
- f".{self.code_model.operations_folder_name}", og.class_name, ImportType.LOCAL
105
+ f".{self.code_model.operations_folder_name}",
106
+ og.class_name,
107
+ ImportType.LOCAL,
81
108
  )
82
109
 
83
110
  if self.code_model.sorted_schemas:
@@ -86,25 +113,42 @@ class Client:
86
113
  else:
87
114
  # in this case, we have client_models = {} in the service client, which needs a type annotation
88
115
  # this import will always be commented, so will always add it to the typing section
89
- file_import.add_submodule_import("typing", "Dict", ImportType.STDLIB, TypingSection.TYPING)
116
+ file_import.add_submodule_import(
117
+ "typing", "Dict", ImportType.STDLIB, TypingSection.TYPING
118
+ )
90
119
  file_import.add_submodule_import("copy", "deepcopy", ImportType.STDLIB)
91
120
  return file_import
92
121
 
93
122
  def imports_for_multiapi(self, async_mode: bool) -> FileImport:
94
123
  file_import = self._imports_shared(async_mode)
95
124
  try:
96
- mixin_operation = next(og for og in self.code_model.operation_groups if og.is_empty_operation_group)
97
- file_import.add_submodule_import("._operations_mixin", mixin_operation.class_name, ImportType.LOCAL)
125
+ mixin_operation = next(
126
+ og
127
+ for og in self.code_model.operation_groups
128
+ if og.is_empty_operation_group
129
+ )
130
+ file_import.add_submodule_import(
131
+ "._operations_mixin", mixin_operation.class_name, ImportType.LOCAL
132
+ )
98
133
  except StopIteration:
99
134
  pass
100
135
  return file_import
101
136
 
102
137
  def send_request_signature(self, is_python3_file: bool) -> List[str]:
103
- request_signature = ["request: HttpRequest," if is_python3_file else "request, # type: HttpRequest"]
104
- return request_signature + self.parameters.method_signature_kwargs(is_python3_file)
138
+ request_signature = [
139
+ "request: HttpRequest,"
140
+ if is_python3_file
141
+ else "request, # type: HttpRequest"
142
+ ]
143
+ return request_signature + self.parameters.method_signature_kwargs(
144
+ is_python3_file
145
+ )
105
146
 
106
147
  @property
107
148
  def filename(self) -> str:
108
- if self.code_model.options["version_tolerant"] or self.code_model.options["low_level_client"]:
149
+ if (
150
+ self.code_model.options["version_tolerant"]
151
+ or self.code_model.options["low_level_client"]
152
+ ):
109
153
  return "_client"
110
154
  return f"_{self.code_model.module_name}"