@autorest/python 6.28.0 → 6.28.2
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.
- package/autorest/codegen.py +2 -2
- package/autorest/jsonrpc/__init__.py +2 -2
- package/autorest/m4reformatter/__init__.py +13 -13
- package/autorest/multiapi/templates/multiapi_service_client.py.jinja2 +1 -1
- package/generator/build/lib/pygen/codegen/models/code_model.py +5 -1
- package/generator/build/lib/pygen/codegen/models/combined_type.py +4 -3
- package/generator/build/lib/pygen/codegen/models/credential_types.py +4 -0
- package/generator/build/lib/pygen/codegen/models/operation.py +9 -3
- package/generator/build/lib/pygen/codegen/models/operation_group.py +26 -1
- package/generator/build/lib/pygen/codegen/models/paging_operation.py +1 -1
- package/generator/build/lib/pygen/codegen/models/property.py +2 -2
- package/generator/build/lib/pygen/codegen/serializers/__init__.py +22 -7
- package/generator/build/lib/pygen/codegen/serializers/builder_serializer.py +14 -3
- package/generator/build/lib/pygen/codegen/serializers/model_serializer.py +2 -1
- package/generator/build/lib/pygen/codegen/serializers/operation_groups_serializer.py +1 -0
- package/generator/build/lib/pygen/codegen/templates/model_base.py.jinja2 +61 -0
- package/generator/build/lib/pygen/codegen/templates/operation_group.py.jinja2 +4 -4
- package/generator/build/lib/pygen/codegen/templates/operation_groups_container.py.jinja2 +2 -0
- package/generator/build/lib/pygen/codegen/templates/serialization.py.jinja2 +39 -107
- package/generator/build/lib/pygen/preprocess/__init__.py +1 -1
- package/generator/dist/pygen-0.1.0-py3-none-any.whl +0 -0
- package/generator/pygen/codegen/models/code_model.py +5 -1
- package/generator/pygen/codegen/models/combined_type.py +4 -3
- package/generator/pygen/codegen/models/credential_types.py +4 -0
- package/generator/pygen/codegen/models/operation.py +9 -3
- package/generator/pygen/codegen/models/operation_group.py +26 -1
- package/generator/pygen/codegen/models/paging_operation.py +1 -1
- package/generator/pygen/codegen/models/property.py +2 -2
- package/generator/pygen/codegen/serializers/__init__.py +22 -7
- package/generator/pygen/codegen/serializers/builder_serializer.py +14 -3
- package/generator/pygen/codegen/serializers/model_serializer.py +2 -1
- package/generator/pygen/codegen/serializers/operation_groups_serializer.py +1 -0
- package/generator/pygen/codegen/templates/model_base.py.jinja2 +61 -0
- package/generator/pygen/codegen/templates/operation_group.py.jinja2 +4 -4
- package/generator/pygen/codegen/templates/operation_groups_container.py.jinja2 +2 -0
- package/generator/pygen/codegen/templates/serialization.py.jinja2 +39 -107
- package/generator/pygen/preprocess/__init__.py +1 -1
- package/package.json +2 -2
- package/scripts/__pycache__/venvtools.cpython-310.pyc +0 -0
- package/scripts/eng/mypy.ini +1 -1
- package/scripts/mypy.ini +1 -1
- package/scripts/prepare.py +2 -2
- package/scripts/start.py +2 -2
- package/scripts/venvtools.py +2 -2
package/autorest/codegen.py
CHANGED
|
@@ -40,7 +40,7 @@ class JinjaSerializerAutorest(JinjaSerializer, ReaderAndWriterAutorest):
|
|
|
40
40
|
class CodeGeneratorAutorest(CodeGenerator, PluginAutorest):
|
|
41
41
|
def get_options(self) -> Dict[str, Any]:
|
|
42
42
|
if self._autorestapi.get_boolean_value("python3-only") is False:
|
|
43
|
-
_LOGGER.warning("You have passed in --python3-only=False. We have force
|
|
43
|
+
_LOGGER.warning("You have passed in --python3-only=False. We have force overridden this to True.")
|
|
44
44
|
if self._autorestapi.get_boolean_value("add-python3-operation-files"):
|
|
45
45
|
_LOGGER.warning(
|
|
46
46
|
"You have passed in --add-python3-operation-files. "
|
|
@@ -48,7 +48,7 @@ class CodeGeneratorAutorest(CodeGenerator, PluginAutorest):
|
|
|
48
48
|
)
|
|
49
49
|
if self._autorestapi.get_boolean_value("reformat-next-link"):
|
|
50
50
|
_LOGGER.warning(
|
|
51
|
-
"You have passed in --reformat-next-link. We have force
|
|
51
|
+
"You have passed in --reformat-next-link. We have force overridden "
|
|
52
52
|
"this to False because we no longer reformat initial query parameters into next "
|
|
53
53
|
"calls unless explicitly defined in the service definition."
|
|
54
54
|
)
|
|
@@ -12,7 +12,7 @@ from pathlib import Path
|
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
class Channel(Enum):
|
|
15
|
-
# Information is considered the mildest of responses; not
|
|
15
|
+
# Information is considered the mildest of responses; not necessarily actionable.
|
|
16
16
|
Information = "information"
|
|
17
17
|
|
|
18
18
|
# Warnings are considered important for best practices, but not catastrophic in nature.
|
|
@@ -27,7 +27,7 @@ class Channel(Enum):
|
|
|
27
27
|
# Verbose messages give the user additional clarity on the process.
|
|
28
28
|
Verbose = "verbose"
|
|
29
29
|
|
|
30
|
-
# Catastrophic failure, likely
|
|
30
|
+
# Catastrophic failure, likely ending the process.
|
|
31
31
|
Fatal = "fatal"
|
|
32
32
|
|
|
33
33
|
|
|
@@ -492,7 +492,7 @@ class M4Reformatter(YamlUpdatePluginAutorest): # pylint: disable=too-many-publi
|
|
|
492
492
|
*,
|
|
493
493
|
is_overload: bool = False,
|
|
494
494
|
) -> Dict[str, Any]:
|
|
495
|
-
|
|
495
|
+
in_overridden = body_parameter["type"]["type"] == "combined" if body_parameter else False
|
|
496
496
|
abstract = False
|
|
497
497
|
if body_parameter and (body_parameter.get("entries") or len(body_parameter["type"].get("types", [])) > 2):
|
|
498
498
|
# this means it's formdata or urlencoded, or there are more than 2 types of body
|
|
@@ -507,7 +507,7 @@ class M4Reformatter(YamlUpdatePluginAutorest): # pylint: disable=too-many-publi
|
|
|
507
507
|
yaml_data,
|
|
508
508
|
body_parameter,
|
|
509
509
|
in_overload=is_overload,
|
|
510
|
-
|
|
510
|
+
in_overridden=in_overridden,
|
|
511
511
|
),
|
|
512
512
|
"bodyParameter": body_parameter,
|
|
513
513
|
"responses": [update_response(r) for r in yaml_data.get("responses", [])],
|
|
@@ -723,7 +723,7 @@ class M4Reformatter(YamlUpdatePluginAutorest): # pylint: disable=too-many-publi
|
|
|
723
723
|
request_media_types: List[str],
|
|
724
724
|
*,
|
|
725
725
|
in_overload: bool = False,
|
|
726
|
-
|
|
726
|
+
in_overridden: bool = False,
|
|
727
727
|
) -> Dict[str, Any]:
|
|
728
728
|
# override content type type to string
|
|
729
729
|
if not body_parameter:
|
|
@@ -737,14 +737,14 @@ class M4Reformatter(YamlUpdatePluginAutorest): # pylint: disable=too-many-publi
|
|
|
737
737
|
description = param["language"]["default"]["description"]
|
|
738
738
|
if description and description[-1] != ".":
|
|
739
739
|
description += "."
|
|
740
|
-
if not (
|
|
740
|
+
if not (in_overridden or in_overload):
|
|
741
741
|
param["inDocstring"] = False
|
|
742
742
|
elif in_overload:
|
|
743
743
|
description += " Content type parameter for " f"{get_body_type_for_description(body_parameter)} body."
|
|
744
744
|
if not in_overload or (body_parameter["type"]["type"] == "binary" and len(request_media_types) > 1):
|
|
745
745
|
content_types = "'" + "', '".join(request_media_types) + "'"
|
|
746
746
|
description += f" Known values are: {content_types}."
|
|
747
|
-
if not in_overload and not
|
|
747
|
+
if not in_overload and not in_overridden:
|
|
748
748
|
param["clientDefaultValue"] = body_parameter["defaultContentType"]
|
|
749
749
|
param["language"]["default"]["description"] = description
|
|
750
750
|
return param
|
|
@@ -758,7 +758,7 @@ class M4Reformatter(YamlUpdatePluginAutorest): # pylint: disable=too-many-publi
|
|
|
758
758
|
request_media_types: List[str],
|
|
759
759
|
*,
|
|
760
760
|
in_overload: bool = False,
|
|
761
|
-
|
|
761
|
+
in_overridden: bool = False,
|
|
762
762
|
) -> List[Dict[str, Any]]:
|
|
763
763
|
retval: List[Dict[str, Any]] = []
|
|
764
764
|
has_flattened_body = body_parameter and body_parameter.get("flattened")
|
|
@@ -785,9 +785,9 @@ class M4Reformatter(YamlUpdatePluginAutorest): # pylint: disable=too-many-publi
|
|
|
785
785
|
body_parameter,
|
|
786
786
|
request_media_types,
|
|
787
787
|
in_overload=in_overload,
|
|
788
|
-
|
|
788
|
+
in_overridden=in_overridden,
|
|
789
789
|
)
|
|
790
|
-
updated_param = self.update_parameter(param, in_overload=in_overload,
|
|
790
|
+
updated_param = self.update_parameter(param, in_overload=in_overload, in_overridden=in_overridden)
|
|
791
791
|
retval.append(updated_param)
|
|
792
792
|
return retval
|
|
793
793
|
|
|
@@ -797,7 +797,7 @@ class M4Reformatter(YamlUpdatePluginAutorest): # pylint: disable=too-many-publi
|
|
|
797
797
|
body_parameter: Optional[Dict[str, Any]],
|
|
798
798
|
*,
|
|
799
799
|
in_overload: bool = False,
|
|
800
|
-
|
|
800
|
+
in_overridden: bool = False,
|
|
801
801
|
) -> List[Dict[str, Any]]:
|
|
802
802
|
retval: List[Dict[str, Any]] = []
|
|
803
803
|
seen_client_names: Set[str] = set()
|
|
@@ -812,7 +812,7 @@ class M4Reformatter(YamlUpdatePluginAutorest): # pylint: disable=too-many-publi
|
|
|
812
812
|
groupers,
|
|
813
813
|
request_media_types,
|
|
814
814
|
in_overload=in_overload,
|
|
815
|
-
|
|
815
|
+
in_overridden=in_overridden,
|
|
816
816
|
)
|
|
817
817
|
)
|
|
818
818
|
# now we handle content type and accept headers.
|
|
@@ -831,7 +831,7 @@ class M4Reformatter(YamlUpdatePluginAutorest): # pylint: disable=too-many-publi
|
|
|
831
831
|
groupers,
|
|
832
832
|
request_media_types,
|
|
833
833
|
in_overload=in_overload,
|
|
834
|
-
|
|
834
|
+
in_overridden=in_overridden,
|
|
835
835
|
)
|
|
836
836
|
)
|
|
837
837
|
all_params = (retval + [body_parameter]) if body_parameter else retval
|
|
@@ -853,7 +853,7 @@ class M4Reformatter(YamlUpdatePluginAutorest): # pylint: disable=too-many-publi
|
|
|
853
853
|
*,
|
|
854
854
|
override_client_name: Optional[str] = None,
|
|
855
855
|
in_overload: bool = False,
|
|
856
|
-
|
|
856
|
+
in_overridden: bool = False,
|
|
857
857
|
) -> Dict[str, Any]:
|
|
858
858
|
param_base = self.update_parameter_base(yaml_data, override_client_name=override_client_name)
|
|
859
859
|
type = get_type(yaml_data["schema"])
|
|
@@ -869,7 +869,7 @@ class M4Reformatter(YamlUpdatePluginAutorest): # pylint: disable=too-many-publi
|
|
|
869
869
|
"inOverload": in_overload,
|
|
870
870
|
"skipUrlEncoding": yaml_data.get("extensions", {}).get("x-ms-skip-url-encoding", False),
|
|
871
871
|
"inDocstring": yaml_data.get("inDocstring", True),
|
|
872
|
-
"
|
|
872
|
+
"inOverridden": in_overridden,
|
|
873
873
|
"delimiter": update_parameter_delimiter(protocol_http.get("style")),
|
|
874
874
|
}
|
|
875
875
|
)
|
|
@@ -33,7 +33,7 @@ def __init__(
|
|
|
33
33
|
|
|
34
34
|
class _SDKClient(object):
|
|
35
35
|
def __init__(self, *args, **kwargs):
|
|
36
|
-
"""This is a fake class to support current
|
|
36
|
+
"""This is a fake class to support current implementation of MultiApiClientMixin."
|
|
37
37
|
Will be removed in final version of multiapi azure-core based client
|
|
38
38
|
"""
|
|
39
39
|
pass
|
|
@@ -313,7 +313,7 @@ class CodeModel: # pylint: disable=too-many-public-methods, disable=too-many-in
|
|
|
313
313
|
:param int schema_id: The yaml id of the schema
|
|
314
314
|
:return: If created, we return the created schema, otherwise, we throw.
|
|
315
315
|
:rtype: ~autorest.models.BaseType
|
|
316
|
-
:raises
|
|
316
|
+
:raises KeyError: if schema is not found
|
|
317
317
|
"""
|
|
318
318
|
try:
|
|
319
319
|
return next(type for id, type in self.types_map.items() if id == schema_id)
|
|
@@ -402,3 +402,7 @@ class CodeModel: # pylint: disable=too-many-public-methods, disable=too-many-in
|
|
|
402
402
|
@property
|
|
403
403
|
def is_legacy(self) -> bool:
|
|
404
404
|
return _is_legacy(self.options)
|
|
405
|
+
|
|
406
|
+
@staticmethod
|
|
407
|
+
def has_non_json_models(models: List[ModelType]) -> bool:
|
|
408
|
+
return any(m for m in models if m.base != "json")
|
|
@@ -53,9 +53,10 @@ class CombinedType(BaseType):
|
|
|
53
53
|
return self.yaml_data.get("clientDefaultValue")
|
|
54
54
|
|
|
55
55
|
def description(self, *, is_operation_file: bool) -> str:
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
56
|
+
type_descriptions = list({t.type_description: None for t in self.types}.keys())
|
|
57
|
+
if len(type_descriptions) == 2:
|
|
58
|
+
return f"Is either a {type_descriptions[0]} type or a {type_descriptions[1]} type."
|
|
59
|
+
return f"Is one of the following types: {', '.join(t for t in type_descriptions)}"
|
|
59
60
|
|
|
60
61
|
def docstring_text(self, **kwargs: Any) -> str:
|
|
61
62
|
return " or ".join(t.docstring_text(**kwargs) for t in self.types)
|
|
@@ -198,6 +198,10 @@ class KeyCredentialType(CredentialType[KeyCredentialPolicyType]):
|
|
|
198
198
|
def type_annotation(self, **kwargs: Any) -> str:
|
|
199
199
|
return self.policy.credential_name
|
|
200
200
|
|
|
201
|
+
@property
|
|
202
|
+
def type_description(self) -> str:
|
|
203
|
+
return "key credential"
|
|
204
|
+
|
|
201
205
|
@property
|
|
202
206
|
def instance_check_template(self) -> str:
|
|
203
207
|
return "isinstance({}, " + f"{self.policy.credential_name})"
|
|
@@ -35,6 +35,7 @@ from .parameter import (
|
|
|
35
35
|
)
|
|
36
36
|
from .parameter_list import ParameterList
|
|
37
37
|
from .model_type import ModelType
|
|
38
|
+
from .primitive_types import BinaryIteratorType, BinaryType
|
|
38
39
|
from .base import BaseType
|
|
39
40
|
from .combined_type import CombinedType
|
|
40
41
|
from .request_builder import OverloadedRequestBuilder, RequestBuilder
|
|
@@ -313,6 +314,10 @@ class OperationBase( # pylint: disable=too-many-public-methods,too-many-instanc
|
|
|
313
314
|
)
|
|
314
315
|
return file_import
|
|
315
316
|
|
|
317
|
+
@property
|
|
318
|
+
def need_deserialize(self) -> bool:
|
|
319
|
+
return any(r.type and not isinstance(r.type, BinaryIteratorType) for r in self.responses)
|
|
320
|
+
|
|
316
321
|
def imports( # pylint: disable=too-many-branches, disable=too-many-statements
|
|
317
322
|
self, async_mode: bool, **kwargs: Any
|
|
318
323
|
) -> FileImport:
|
|
@@ -432,7 +437,8 @@ class OperationBase( # pylint: disable=too-many-public-methods,too-many-instanc
|
|
|
432
437
|
file_import.add_submodule_import("typing", "overload", ImportType.STDLIB)
|
|
433
438
|
if self.code_model.options["models_mode"] == "dpg":
|
|
434
439
|
relative_path = self.code_model.get_relative_import_path(serialize_namespace, module_name="_model_base")
|
|
435
|
-
if self.parameters.has_body
|
|
440
|
+
body_param = self.parameters.body_parameter if self.parameters.has_body else None
|
|
441
|
+
if body_param and not isinstance(body_param.type, BinaryType):
|
|
436
442
|
if self.has_form_data_body:
|
|
437
443
|
file_import.add_submodule_import(
|
|
438
444
|
self.code_model.get_relative_import_path(serialize_namespace), "_model_base", ImportType.LOCAL
|
|
@@ -450,9 +456,9 @@ class OperationBase( # pylint: disable=too-many-public-methods,too-many-instanc
|
|
|
450
456
|
ImportType.LOCAL,
|
|
451
457
|
)
|
|
452
458
|
file_import.add_import("json", ImportType.STDLIB)
|
|
453
|
-
if any(xml_serializable(str(r.default_content_type)) for r in self.responses):
|
|
459
|
+
if any(xml_serializable(str(r.default_content_type)) for r in self.responses + self.exceptions):
|
|
454
460
|
file_import.add_submodule_import(relative_path, "_deserialize_xml", ImportType.LOCAL)
|
|
455
|
-
elif
|
|
461
|
+
elif self.need_deserialize:
|
|
456
462
|
file_import.add_submodule_import(relative_path, "_deserialize", ImportType.LOCAL)
|
|
457
463
|
if self.default_error_deserialization or self.non_default_errors:
|
|
458
464
|
file_import.add_submodule_import(relative_path, "_failsafe_deserialize", ImportType.LOCAL)
|
|
@@ -9,7 +9,7 @@ from .utils import OrderedSet
|
|
|
9
9
|
|
|
10
10
|
from .base import BaseModel
|
|
11
11
|
from .operation import get_operation
|
|
12
|
-
from .imports import FileImport, ImportType, TypingSection
|
|
12
|
+
from .imports import FileImport, ImportType, TypingSection, MsrestImportType
|
|
13
13
|
from .utils import add_to_pylint_disable, NamespaceType
|
|
14
14
|
from .lro_operation import LROOperation
|
|
15
15
|
from .lro_paging_operation import LROPagingOperation
|
|
@@ -152,6 +152,31 @@ class OperationGroup(BaseModel):
|
|
|
152
152
|
f"{self.client.name}MixinABC",
|
|
153
153
|
ImportType.LOCAL,
|
|
154
154
|
)
|
|
155
|
+
else:
|
|
156
|
+
file_import.add_submodule_import(
|
|
157
|
+
"" if self.code_model.is_azure_flavor else "runtime",
|
|
158
|
+
f"{'Async' if async_mode else ''}PipelineClient",
|
|
159
|
+
ImportType.SDKCORE,
|
|
160
|
+
)
|
|
161
|
+
file_import.add_submodule_import(
|
|
162
|
+
self.code_model.get_relative_import_path(
|
|
163
|
+
serialize_namespace,
|
|
164
|
+
self.code_model.get_imported_namespace_for_client(self.client.client_namespace, async_mode),
|
|
165
|
+
module_name="_configuration",
|
|
166
|
+
),
|
|
167
|
+
f"{self.client.name}Configuration",
|
|
168
|
+
ImportType.LOCAL,
|
|
169
|
+
)
|
|
170
|
+
file_import.add_msrest_import(
|
|
171
|
+
serialize_namespace=kwargs.get("serialize_namespace", self.code_model.namespace),
|
|
172
|
+
msrest_import_type=MsrestImportType.Serializer,
|
|
173
|
+
typing_section=TypingSection.REGULAR,
|
|
174
|
+
)
|
|
175
|
+
file_import.add_msrest_import(
|
|
176
|
+
serialize_namespace=kwargs.get("serialize_namespace", self.code_model.namespace),
|
|
177
|
+
msrest_import_type=MsrestImportType.SerializerDeserializer,
|
|
178
|
+
typing_section=TypingSection.REGULAR,
|
|
179
|
+
)
|
|
155
180
|
if self.has_abstract_operations:
|
|
156
181
|
file_import.add_submodule_import(
|
|
157
182
|
# raise_if_not_implemented is always defined in _vendor of top namespace
|
|
@@ -150,7 +150,7 @@ class PagingOperationBase(OperationBase[PagingResponseType]):
|
|
|
150
150
|
if self.code_model.options["models_mode"] == "dpg":
|
|
151
151
|
relative_path = self.code_model.get_relative_import_path(serialize_namespace, module_name="_model_base")
|
|
152
152
|
file_import.merge(self.item_type.imports(**kwargs))
|
|
153
|
-
if self.default_error_deserialization or
|
|
153
|
+
if self.default_error_deserialization or self.need_deserialize:
|
|
154
154
|
file_import.add_submodule_import(relative_path, "_deserialize", ImportType.LOCAL)
|
|
155
155
|
return file_import
|
|
156
156
|
|
|
@@ -102,7 +102,7 @@ class Property(BaseModel): # pylint: disable=too-many-instance-attributes
|
|
|
102
102
|
if self.is_base_discriminator:
|
|
103
103
|
return "str"
|
|
104
104
|
types_type_annotation = self.type.type_annotation(is_operation_file=is_operation_file, **kwargs)
|
|
105
|
-
if self.optional and self.client_default_value is None:
|
|
105
|
+
if (self.optional and self.client_default_value is None) or self.readonly:
|
|
106
106
|
return f"Optional[{types_type_annotation}]"
|
|
107
107
|
return types_type_annotation
|
|
108
108
|
|
|
@@ -144,7 +144,7 @@ class Property(BaseModel): # pylint: disable=too-many-instance-attributes
|
|
|
144
144
|
if self.is_discriminator and isinstance(self.type, EnumType):
|
|
145
145
|
return file_import
|
|
146
146
|
file_import.merge(self.type.imports(**kwargs))
|
|
147
|
-
if self.optional and self.client_default_value is None:
|
|
147
|
+
if (self.optional and self.client_default_value is None) or self.readonly:
|
|
148
148
|
file_import.add_submodule_import("typing", "Optional", ImportType.STDLIB)
|
|
149
149
|
if self.code_model.options["models_mode"] == "dpg":
|
|
150
150
|
serialize_namespace = kwargs.get("serialize_namespace", self.code_model.namespace)
|
|
@@ -130,10 +130,10 @@ class JinjaSerializer(ReaderAndWriter):
|
|
|
130
130
|
if self.code_model.options["package_mode"]:
|
|
131
131
|
self._serialize_and_write_package_files(client_namespace)
|
|
132
132
|
|
|
133
|
-
# write
|
|
133
|
+
# write apiview-properties.json
|
|
134
134
|
if self.code_model.options.get("emit_cross_language_definition_file"):
|
|
135
135
|
self.write_file(
|
|
136
|
-
exec_path / Path("
|
|
136
|
+
exec_path / Path("apiview-properties.json"),
|
|
137
137
|
general_serializer.serialize_cross_language_definition_file(),
|
|
138
138
|
)
|
|
139
139
|
|
|
@@ -159,7 +159,9 @@ class JinjaSerializer(ReaderAndWriter):
|
|
|
159
159
|
self._serialize_and_write_top_level_folder(env=env, namespace=client_namespace)
|
|
160
160
|
|
|
161
161
|
# add models folder if there are models in this namespace
|
|
162
|
-
if (
|
|
162
|
+
if (
|
|
163
|
+
self.code_model.has_non_json_models(client_namespace_type.models) or client_namespace_type.enums
|
|
164
|
+
) and self.code_model.options["models_mode"]:
|
|
163
165
|
self._serialize_and_write_models_folder(
|
|
164
166
|
env=env,
|
|
165
167
|
namespace=client_namespace,
|
|
@@ -181,6 +183,14 @@ class JinjaSerializer(ReaderAndWriter):
|
|
|
181
183
|
if self.code_model.options["multiapi"]:
|
|
182
184
|
self._serialize_and_write_metadata(env=env, namespace=client_namespace)
|
|
183
185
|
|
|
186
|
+
# if there are only operations under this namespace, we need to add general __init__.py into `aio` folder
|
|
187
|
+
# to make sure all generated files could be packed into .zip/.whl/.tgz package
|
|
188
|
+
if not client_namespace_type.clients and client_namespace_type.operation_groups and self.has_aio_folder:
|
|
189
|
+
self.write_file(
|
|
190
|
+
exec_path / Path("aio/__init__.py"),
|
|
191
|
+
general_serializer.serialize_pkgutil_init_file(),
|
|
192
|
+
)
|
|
193
|
+
|
|
184
194
|
def _serialize_and_write_package_files(self, client_namespace: str) -> None:
|
|
185
195
|
root_of_sdk = self.exec_path(client_namespace)
|
|
186
196
|
if self.code_model.options["package_mode"] in VALID_PACKAGE_MODE:
|
|
@@ -228,9 +238,9 @@ class JinjaSerializer(ReaderAndWriter):
|
|
|
228
238
|
self, env: Environment, namespace: str, models: List[ModelType], enums: List[EnumType]
|
|
229
239
|
) -> None:
|
|
230
240
|
# Write the models folder
|
|
231
|
-
models_path = self.exec_path(namespace
|
|
241
|
+
models_path = self.exec_path(namespace) / "models"
|
|
232
242
|
serializer = DpgModelSerializer if self.code_model.options["models_mode"] == "dpg" else MsrestModelSerializer
|
|
233
|
-
if models:
|
|
243
|
+
if self.code_model.has_non_json_models(models):
|
|
234
244
|
self.write_file(
|
|
235
245
|
models_path / Path(f"{self.code_model.models_filename}.py"),
|
|
236
246
|
serializer(code_model=self.code_model, env=env, client_namespace=namespace, models=models).serialize(),
|
|
@@ -469,7 +479,12 @@ class JinjaSerializer(ReaderAndWriter):
|
|
|
469
479
|
else Path(".")
|
|
470
480
|
)
|
|
471
481
|
|
|
482
|
+
def exec_path_for_test_sample(self, namespace: str) -> Path:
|
|
483
|
+
return self.exec_path_compensation / Path(*namespace.split("."))
|
|
484
|
+
|
|
472
485
|
def exec_path(self, namespace: str) -> Path:
|
|
486
|
+
if self.code_model.options["no_namespace_folders"] and not self.code_model.options["multiapi"]:
|
|
487
|
+
return Path(".")
|
|
473
488
|
return self.exec_path_compensation / Path(*namespace.split("."))
|
|
474
489
|
|
|
475
490
|
@property
|
|
@@ -482,7 +497,7 @@ class JinjaSerializer(ReaderAndWriter):
|
|
|
482
497
|
return Path("")
|
|
483
498
|
|
|
484
499
|
def _serialize_and_write_sample(self, env: Environment, namespace: str):
|
|
485
|
-
out_path = self.
|
|
500
|
+
out_path = self.exec_path_for_test_sample(namespace) / Path("generated_samples")
|
|
486
501
|
for client in self.code_model.clients:
|
|
487
502
|
for op_group in client.operation_groups:
|
|
488
503
|
for operation in op_group.operations:
|
|
@@ -516,7 +531,7 @@ class JinjaSerializer(ReaderAndWriter):
|
|
|
516
531
|
|
|
517
532
|
def _serialize_and_write_test(self, env: Environment, namespace: str):
|
|
518
533
|
self.code_model.for_test = True
|
|
519
|
-
out_path = self.
|
|
534
|
+
out_path = self.exec_path_for_test_sample(namespace) / Path("generated_tests")
|
|
520
535
|
general_serializer = TestGeneralSerializer(code_model=self.code_model, env=env)
|
|
521
536
|
self.write_file(out_path / "conftest.py", general_serializer.serialize_conftest())
|
|
522
537
|
if not self.code_model.options["azure_arm"]:
|
|
@@ -498,7 +498,11 @@ class RequestBuilderSerializer(_BuilderBaseSerializer[RequestBuilderType]):
|
|
|
498
498
|
url_value = _escape_str(builder.url)
|
|
499
499
|
else:
|
|
500
500
|
url_value = f'kwargs.pop("template_url", {_escape_str(builder.url)})'
|
|
501
|
-
|
|
501
|
+
result = "_url = " + url_value
|
|
502
|
+
# there will be always 4 spaces before the url
|
|
503
|
+
if len(result) + 4 > 120:
|
|
504
|
+
return result + " # pylint: disable=line-too-long"
|
|
505
|
+
return result
|
|
502
506
|
|
|
503
507
|
|
|
504
508
|
############################## NORMAL OPERATIONS ##############################
|
|
@@ -1001,7 +1005,7 @@ class _OperationSerializer(_BuilderBaseSerializer[OperationType]):
|
|
|
1001
1005
|
retval.extend(deserialize_code)
|
|
1002
1006
|
return retval
|
|
1003
1007
|
|
|
1004
|
-
def handle_error_response(self, builder: OperationType) -> List[str]:
|
|
1008
|
+
def handle_error_response(self, builder: OperationType) -> List[str]: # pylint: disable=too-many-statements, too-many-branches
|
|
1005
1009
|
async_await = "await " if self.async_mode else ""
|
|
1006
1010
|
retval = [f"if response.status_code not in {str(builder.success_status_codes)}:"]
|
|
1007
1011
|
response_read = [
|
|
@@ -1075,7 +1079,14 @@ class _OperationSerializer(_BuilderBaseSerializer[OperationType]):
|
|
|
1075
1079
|
is_operation_file=True, skip_quote=True, serialize_namespace=self.serialize_namespace
|
|
1076
1080
|
)
|
|
1077
1081
|
if self.code_model.options["models_mode"] == "dpg":
|
|
1078
|
-
|
|
1082
|
+
if xml_serializable(str(e.default_content_type)):
|
|
1083
|
+
retval.append(
|
|
1084
|
+
f" error = _failsafe_deserialize_xml({type_annotation}, response.text())"
|
|
1085
|
+
)
|
|
1086
|
+
else:
|
|
1087
|
+
retval.append(
|
|
1088
|
+
f" error = _failsafe_deserialize({type_annotation}, response.json())"
|
|
1089
|
+
)
|
|
1079
1090
|
else:
|
|
1080
1091
|
retval.append(
|
|
1081
1092
|
f" error = self._deserialize.failsafe_deserialize({type_annotation}, "
|
|
@@ -192,7 +192,8 @@ class MsrestModelSerializer(_ModelSerializer):
|
|
|
192
192
|
if prop.is_discriminator:
|
|
193
193
|
init_args.append(self.initialize_discriminator_property(model, prop))
|
|
194
194
|
elif prop.readonly:
|
|
195
|
-
|
|
195
|
+
# we want typing for readonly since typing isn't provided from the command line
|
|
196
|
+
init_args.append(f"self.{prop.client_name}: {prop.type_annotation()} = None")
|
|
196
197
|
elif not prop.constant:
|
|
197
198
|
init_args.append(f"self.{prop.client_name} = {prop.client_name}")
|
|
198
199
|
return init_args
|
|
@@ -372,15 +372,34 @@ class _MyMutableMapping(MutableMapping[str, typing.Any]): # pylint: disable=uns
|
|
|
372
372
|
return not self.__eq__(other)
|
|
373
373
|
|
|
374
374
|
def keys(self) -> typing.KeysView[str]:
|
|
375
|
+
"""
|
|
376
|
+
:returns: a set-like object providing a view on D's keys
|
|
377
|
+
:rtype: ~typing.KeysView
|
|
378
|
+
"""
|
|
375
379
|
return self._data.keys()
|
|
376
380
|
|
|
377
381
|
def values(self) -> typing.ValuesView[typing.Any]:
|
|
382
|
+
"""
|
|
383
|
+
:returns: an object providing a view on D's values
|
|
384
|
+
:rtype: ~typing.ValuesView
|
|
385
|
+
"""
|
|
378
386
|
return self._data.values()
|
|
379
387
|
|
|
380
388
|
def items(self) -> typing.ItemsView[str, typing.Any]:
|
|
389
|
+
"""
|
|
390
|
+
:returns: set-like object providing a view on D's items
|
|
391
|
+
:rtype: ~typing.ItemsView
|
|
392
|
+
"""
|
|
381
393
|
return self._data.items()
|
|
382
394
|
|
|
383
395
|
def get(self, key: str, default: typing.Any = None) -> typing.Any:
|
|
396
|
+
"""
|
|
397
|
+
Get the value for key if key is in the dictionary, else default.
|
|
398
|
+
:param str key: The key to look up.
|
|
399
|
+
:param any default: The value to return if key is not in the dictionary. Defaults to None
|
|
400
|
+
:returns: D[k] if k in D, else d.
|
|
401
|
+
:rtype: any
|
|
402
|
+
"""
|
|
384
403
|
try:
|
|
385
404
|
return self[key]
|
|
386
405
|
except KeyError:
|
|
@@ -396,17 +415,38 @@ class _MyMutableMapping(MutableMapping[str, typing.Any]): # pylint: disable=uns
|
|
|
396
415
|
def pop(self, key: str, default: typing.Any) -> typing.Any: ...
|
|
397
416
|
|
|
398
417
|
def pop(self, key: str, default: typing.Any = _UNSET) -> typing.Any:
|
|
418
|
+
"""
|
|
419
|
+
Removes specified key and return the corresponding value.
|
|
420
|
+
:param str key: The key to pop.
|
|
421
|
+
:param any default: The value to return if key is not in the dictionary
|
|
422
|
+
:returns: The value corresponding to the key.
|
|
423
|
+
:rtype: any
|
|
424
|
+
:raises KeyError: If key is not found and default is not given.
|
|
425
|
+
"""
|
|
399
426
|
if default is _UNSET:
|
|
400
427
|
return self._data.pop(key)
|
|
401
428
|
return self._data.pop(key, default)
|
|
402
429
|
|
|
403
430
|
def popitem(self) -> typing.Tuple[str, typing.Any]:
|
|
431
|
+
"""
|
|
432
|
+
Removes and returns some (key, value) pair
|
|
433
|
+
:returns: The (key, value) pair.
|
|
434
|
+
:rtype: tuple
|
|
435
|
+
:raises KeyError: if D is empty.
|
|
436
|
+
"""
|
|
404
437
|
return self._data.popitem()
|
|
405
438
|
|
|
406
439
|
def clear(self) -> None:
|
|
440
|
+
"""
|
|
441
|
+
Remove all items from D.
|
|
442
|
+
"""
|
|
407
443
|
self._data.clear()
|
|
408
444
|
|
|
409
445
|
def update(self, *args: typing.Any, **kwargs: typing.Any) -> None:
|
|
446
|
+
"""
|
|
447
|
+
Updates D from mapping/iterable E and F.
|
|
448
|
+
:param any args: Either a mapping object or an iterable of key-value pairs.
|
|
449
|
+
"""
|
|
410
450
|
self._data.update(*args, **kwargs)
|
|
411
451
|
|
|
412
452
|
@typing.overload
|
|
@@ -416,6 +456,13 @@ class _MyMutableMapping(MutableMapping[str, typing.Any]): # pylint: disable=uns
|
|
|
416
456
|
def setdefault(self, key: str, default: typing.Any) -> typing.Any: ...
|
|
417
457
|
|
|
418
458
|
def setdefault(self, key: str, default: typing.Any = _UNSET) -> typing.Any:
|
|
459
|
+
"""
|
|
460
|
+
Same as calling D.get(k, d), and setting D[k]=d if k not found
|
|
461
|
+
:param str key: The key to look up.
|
|
462
|
+
:param any default: The value to set if key is not in the dictionary
|
|
463
|
+
:returns: D[k] if k in D, else d.
|
|
464
|
+
:rtype: any
|
|
465
|
+
"""
|
|
419
466
|
if default is _UNSET:
|
|
420
467
|
return self._data.setdefault(key)
|
|
421
468
|
return self._data.setdefault(key, default)
|
|
@@ -909,6 +956,20 @@ def _failsafe_deserialize(
|
|
|
909
956
|
return None
|
|
910
957
|
|
|
911
958
|
|
|
959
|
+
def _failsafe_deserialize_xml(
|
|
960
|
+
deserializer: typing.Any,
|
|
961
|
+
value: typing.Any,
|
|
962
|
+
) -> typing.Any:
|
|
963
|
+
try:
|
|
964
|
+
return _deserialize_xml(deserializer, value)
|
|
965
|
+
except DeserializationError:
|
|
966
|
+
_LOGGER.warning(
|
|
967
|
+
"Ran into a deserialization error. Ignoring since this is failsafe deserialization",
|
|
968
|
+
exc_info=True
|
|
969
|
+
)
|
|
970
|
+
return None
|
|
971
|
+
|
|
972
|
+
|
|
912
973
|
class _RestField:
|
|
913
974
|
def __init__(
|
|
914
975
|
self,
|
|
@@ -31,10 +31,10 @@ class {{ operation_group.class_name }}: {{ operation_group.pylint_disable() }}
|
|
|
31
31
|
{% endif %}
|
|
32
32
|
def __init__(self, *args, **kwargs){{ return_none_type_annotation }}:
|
|
33
33
|
input_args = list(args)
|
|
34
|
-
self._client = input_args.pop(0) if input_args else kwargs.pop("client")
|
|
35
|
-
self._config = input_args.pop(0) if input_args else kwargs.pop("config")
|
|
36
|
-
self._serialize = input_args.pop(0) if input_args else kwargs.pop("serializer")
|
|
37
|
-
self._deserialize = input_args.pop(0) if input_args else kwargs.pop("deserializer")
|
|
34
|
+
self._client: {{ 'Async' if async_mode else ''}}PipelineClient = input_args.pop(0) if input_args else kwargs.pop("client")
|
|
35
|
+
self._config: {{ operation_group.client.name }}Configuration = input_args.pop(0) if input_args else kwargs.pop("config")
|
|
36
|
+
self._serialize: Serializer = input_args.pop(0) if input_args else kwargs.pop("serializer")
|
|
37
|
+
self._deserialize: Deserializer = input_args.pop(0) if input_args else kwargs.pop("deserializer")
|
|
38
38
|
{% if code_model.options["multiapi"] %}
|
|
39
39
|
self._api_version = input_args.pop(0) if input_args else kwargs.pop("api_version")
|
|
40
40
|
{% endif %}
|
|
@@ -6,7 +6,9 @@
|
|
|
6
6
|
{{ imports }}
|
|
7
7
|
{{ unset }}
|
|
8
8
|
{% if code_model.options["builders_visibility"] == "embedded" and not async_mode %}
|
|
9
|
+
{% if need_declare_serializer %}
|
|
9
10
|
{{ op_tools.declare_serializer(code_model) }}
|
|
11
|
+
{% endif %}
|
|
10
12
|
{% for operation_group in operation_groups %}
|
|
11
13
|
{% for request_builder in get_request_builders(operation_group) %}
|
|
12
14
|
|