@autorest/python 5.13.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.
- package/ChangeLog.md +67 -0
- package/autorest/__init__.py +1 -2
- package/autorest/black/__init__.py +12 -5
- package/autorest/codegen/__init__.py +239 -105
- package/autorest/codegen/models/__init__.py +29 -18
- package/autorest/codegen/models/base_builder.py +48 -11
- package/autorest/codegen/models/base_model.py +6 -4
- package/autorest/codegen/models/base_schema.py +21 -24
- package/autorest/codegen/models/client.py +70 -20
- package/autorest/codegen/models/code_model.py +144 -129
- package/autorest/codegen/models/constant_schema.py +32 -16
- package/autorest/codegen/models/credential_model.py +55 -0
- package/autorest/codegen/models/credential_schema.py +21 -16
- package/autorest/codegen/models/credential_schema_policy.py +11 -15
- package/autorest/codegen/models/dictionary_schema.py +27 -24
- package/autorest/codegen/models/enum_schema.py +41 -62
- package/autorest/codegen/models/imports.py +72 -41
- package/autorest/codegen/models/list_schema.py +40 -18
- package/autorest/codegen/models/lro_operation.py +61 -25
- package/autorest/codegen/models/lro_paging_operation.py +5 -6
- package/autorest/codegen/models/object_schema.py +113 -59
- package/autorest/codegen/models/operation.py +251 -111
- package/autorest/codegen/models/operation_group.py +67 -32
- package/autorest/codegen/models/paging_operation.py +48 -21
- package/autorest/codegen/models/parameter.py +182 -90
- package/autorest/codegen/models/parameter_list.py +184 -163
- package/autorest/codegen/models/primitive_schemas.py +89 -70
- package/autorest/codegen/models/property.py +49 -31
- package/autorest/codegen/models/request_builder.py +67 -32
- package/autorest/codegen/models/request_builder_parameter.py +54 -23
- package/autorest/codegen/models/request_builder_parameter_list.py +77 -108
- package/autorest/codegen/models/schema_request.py +16 -6
- package/autorest/codegen/models/schema_response.py +35 -17
- package/autorest/codegen/models/utils.py +24 -1
- package/autorest/codegen/serializers/__init__.py +273 -89
- package/autorest/codegen/serializers/builder_serializer.py +711 -333
- package/autorest/codegen/serializers/client_serializer.py +114 -43
- package/autorest/codegen/serializers/general_serializer.py +84 -25
- package/autorest/codegen/serializers/import_serializer.py +93 -31
- package/autorest/codegen/serializers/metadata_serializer.py +73 -24
- package/autorest/codegen/serializers/model_base_serializer.py +42 -14
- package/autorest/codegen/serializers/model_generic_serializer.py +1 -4
- package/autorest/codegen/serializers/model_init_serializer.py +5 -1
- package/autorest/codegen/serializers/model_python3_serializer.py +9 -8
- package/autorest/codegen/serializers/operation_groups_serializer.py +20 -8
- package/autorest/codegen/serializers/operations_init_serializer.py +23 -11
- package/autorest/codegen/serializers/patch_serializer.py +14 -2
- package/autorest/codegen/serializers/{rest_serializer.py → request_builders_serializer.py} +29 -12
- package/autorest/codegen/serializers/utils.py +60 -21
- package/autorest/codegen/templates/CHANGELOG.md.jinja2 +6 -0
- package/autorest/codegen/templates/LICENSE.jinja2 +21 -0
- package/autorest/codegen/templates/MANIFEST.in.jinja2 +7 -0
- package/autorest/codegen/templates/README.md.jinja2 +105 -0
- package/autorest/codegen/templates/config.py.jinja2 +4 -4
- package/autorest/codegen/templates/dev_requirements.txt.jinja2 +10 -0
- package/autorest/codegen/templates/enum.py.jinja2 +1 -1
- package/autorest/codegen/templates/enum_container.py.jinja2 +0 -1
- package/autorest/codegen/templates/init.py.jinja2 +9 -6
- package/autorest/codegen/templates/keywords.jinja2 +14 -1
- package/autorest/codegen/templates/lro_operation.py.jinja2 +5 -7
- package/autorest/codegen/templates/lro_paging_operation.py.jinja2 +5 -7
- package/autorest/codegen/templates/metadata.json.jinja2 +10 -9
- package/autorest/codegen/templates/model.py.jinja2 +1 -6
- package/autorest/codegen/templates/model_init.py.jinja2 +7 -4
- package/autorest/codegen/templates/operation.py.jinja2 +8 -11
- package/autorest/codegen/templates/operation_group.py.jinja2 +15 -18
- package/autorest/codegen/templates/operation_groups_container.py.jinja2 +1 -2
- package/autorest/codegen/templates/operations_folder_init.py.jinja2 +4 -0
- package/autorest/codegen/templates/paging_operation.py.jinja2 +7 -8
- package/autorest/codegen/templates/patch.py.jinja2 +18 -29
- package/autorest/codegen/templates/request_builder.py.jinja2 +19 -14
- package/autorest/codegen/templates/setup.py.jinja2 +79 -20
- package/autorest/codegen/templates/vendor.py.jinja2 +12 -2
- package/autorest/jsonrpc/__init__.py +7 -12
- package/autorest/jsonrpc/localapi.py +4 -3
- package/autorest/jsonrpc/server.py +13 -6
- package/autorest/jsonrpc/stdstream.py +13 -6
- package/autorest/m2r/__init__.py +5 -8
- package/autorest/multiapi/__init__.py +24 -14
- package/autorest/multiapi/models/client.py +21 -11
- package/autorest/multiapi/models/code_model.py +23 -10
- package/autorest/multiapi/models/config.py +4 -1
- package/autorest/multiapi/models/constant_global_parameter.py +1 -0
- package/autorest/multiapi/models/global_parameter.py +2 -1
- package/autorest/multiapi/models/global_parameters.py +14 -8
- package/autorest/multiapi/models/imports.py +35 -18
- package/autorest/multiapi/models/mixin_operation.py +5 -5
- package/autorest/multiapi/models/operation_group.py +2 -1
- package/autorest/multiapi/models/operation_mixin_group.py +21 -10
- package/autorest/multiapi/serializers/__init__.py +18 -23
- package/autorest/multiapi/serializers/import_serializer.py +47 -15
- package/autorest/multiapi/serializers/multiapi_serializer.py +17 -17
- package/autorest/multiapi/templates/multiapi_operations_mixin.py.jinja2 +1 -1
- package/autorest/multiapi/utils.py +3 -3
- package/autorest/namer/__init__.py +2 -4
- package/autorest/namer/name_converter.py +200 -103
- package/autorest/namer/python_mappings.py +10 -22
- package/package.json +3 -3
- package/run-python3.js +2 -3
- package/venvtools.py +1 -1
- package/autorest/codegen/models/rest.py +0 -42
|
@@ -7,10 +7,14 @@ from typing import Any
|
|
|
7
7
|
from .base_schema import BaseSchema
|
|
8
8
|
from .imports import FileImport, ImportType, TypingSection
|
|
9
9
|
|
|
10
|
+
|
|
10
11
|
class CredentialSchema(BaseSchema):
|
|
11
12
|
def __init__(self) -> None: # pylint: disable=super-init-not-called
|
|
12
13
|
self.default_value = None
|
|
13
14
|
|
|
15
|
+
def type_annotation(self, *, is_operation_file: bool = False) -> str:
|
|
16
|
+
raise ValueError("Children classes should set their own type annotation")
|
|
17
|
+
|
|
14
18
|
@property
|
|
15
19
|
def docstring_type(self) -> str:
|
|
16
20
|
return self.serialization_type
|
|
@@ -26,20 +30,19 @@ class CredentialSchema(BaseSchema):
|
|
|
26
30
|
pass
|
|
27
31
|
|
|
28
32
|
def get_json_template_representation(self, **kwargs: Any) -> Any:
|
|
29
|
-
raise TypeError(
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
raise TypeError("You should not try to get a files template representation of a CredentialSchema")
|
|
33
|
+
raise TypeError(
|
|
34
|
+
"You should not try to get a JSON template representation of a CredentialSchema"
|
|
35
|
+
)
|
|
33
36
|
|
|
34
37
|
|
|
35
38
|
class AzureKeyCredentialSchema(CredentialSchema):
|
|
36
|
-
|
|
37
39
|
@property
|
|
38
40
|
def serialization_type(self) -> str:
|
|
39
41
|
return "~azure.core.credentials.AzureKeyCredential"
|
|
40
42
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
+
def type_annotation(
|
|
44
|
+
self, *, is_operation_file: bool = False # pylint: disable=unused-argument
|
|
45
|
+
) -> str:
|
|
43
46
|
return "AzureKeyCredential"
|
|
44
47
|
|
|
45
48
|
def imports(self) -> FileImport:
|
|
@@ -48,14 +51,14 @@ class AzureKeyCredentialSchema(CredentialSchema):
|
|
|
48
51
|
"azure.core.credentials",
|
|
49
52
|
"AzureKeyCredential",
|
|
50
53
|
ImportType.AZURECORE,
|
|
51
|
-
typing_section=TypingSection.CONDITIONAL
|
|
54
|
+
typing_section=TypingSection.CONDITIONAL,
|
|
52
55
|
)
|
|
53
56
|
return file_import
|
|
54
57
|
|
|
55
58
|
|
|
56
59
|
class TokenCredentialSchema(CredentialSchema):
|
|
57
60
|
def __init__(self, async_mode) -> None:
|
|
58
|
-
super(
|
|
61
|
+
super().__init__()
|
|
59
62
|
self.async_mode = async_mode
|
|
60
63
|
self.async_type = "~azure.core.credentials_async.AsyncTokenCredential"
|
|
61
64
|
self.sync_type = "~azure.core.credentials.TokenCredential"
|
|
@@ -66,25 +69,27 @@ class TokenCredentialSchema(CredentialSchema):
|
|
|
66
69
|
return self.async_type
|
|
67
70
|
return self.sync_type
|
|
68
71
|
|
|
69
|
-
|
|
70
|
-
|
|
72
|
+
def type_annotation(
|
|
73
|
+
self, *, is_operation_file: bool = False # pylint: disable=unused-argument
|
|
74
|
+
) -> str:
|
|
71
75
|
if self.async_mode:
|
|
72
76
|
return '"AsyncTokenCredential"'
|
|
73
77
|
return '"TokenCredential"'
|
|
74
78
|
|
|
75
|
-
|
|
76
79
|
def imports(self) -> FileImport:
|
|
77
80
|
file_import = FileImport()
|
|
78
81
|
if self.async_mode:
|
|
79
82
|
file_import.add_submodule_import(
|
|
80
|
-
"azure.core.credentials_async",
|
|
83
|
+
"azure.core.credentials_async",
|
|
84
|
+
"AsyncTokenCredential",
|
|
81
85
|
ImportType.AZURECORE,
|
|
82
|
-
typing_section=TypingSection.TYPING
|
|
86
|
+
typing_section=TypingSection.TYPING,
|
|
83
87
|
)
|
|
84
88
|
else:
|
|
85
89
|
file_import.add_submodule_import(
|
|
86
|
-
"azure.core.credentials",
|
|
90
|
+
"azure.core.credentials",
|
|
91
|
+
"TokenCredential",
|
|
87
92
|
ImportType.AZURECORE,
|
|
88
|
-
typing_section=TypingSection.TYPING
|
|
93
|
+
typing_section=TypingSection.TYPING,
|
|
89
94
|
)
|
|
90
95
|
return file_import
|
|
@@ -7,9 +7,9 @@ from abc import abstractmethod
|
|
|
7
7
|
from typing import List
|
|
8
8
|
from .credential_schema import CredentialSchema
|
|
9
9
|
|
|
10
|
-
class CredentialSchemaPolicy:
|
|
11
10
|
|
|
12
|
-
|
|
11
|
+
class CredentialSchemaPolicy:
|
|
12
|
+
def __init__(self, credential: CredentialSchema) -> None:
|
|
13
13
|
self.credential = credential
|
|
14
14
|
|
|
15
15
|
@abstractmethod
|
|
@@ -22,11 +22,8 @@ class CredentialSchemaPolicy:
|
|
|
22
22
|
|
|
23
23
|
|
|
24
24
|
class BearerTokenCredentialPolicy(CredentialSchemaPolicy):
|
|
25
|
-
|
|
26
25
|
def __init__(
|
|
27
|
-
self,
|
|
28
|
-
credential: CredentialSchema,
|
|
29
|
-
credential_scopes: List[str]
|
|
26
|
+
self, credential: CredentialSchema, credential_scopes: List[str]
|
|
30
27
|
) -> None:
|
|
31
28
|
super().__init__(credential)
|
|
32
29
|
self._credential_scopes = credential_scopes
|
|
@@ -41,18 +38,14 @@ class BearerTokenCredentialPolicy(CredentialSchemaPolicy):
|
|
|
41
38
|
|
|
42
39
|
|
|
43
40
|
class ARMChallengeAuthenticationPolicy(BearerTokenCredentialPolicy):
|
|
44
|
-
|
|
45
41
|
def call(self, async_mode: bool) -> str:
|
|
46
42
|
policy_name = f"Async{self.name()}" if async_mode else self.name()
|
|
47
43
|
return f"{policy_name}(self.credential, *self.credential_scopes, **kwargs)"
|
|
48
44
|
|
|
49
45
|
|
|
50
46
|
class AzureKeyCredentialPolicy(CredentialSchemaPolicy):
|
|
51
|
-
|
|
52
47
|
def __init__(
|
|
53
|
-
self,
|
|
54
|
-
credential: CredentialSchema,
|
|
55
|
-
credential_key_header_name: str
|
|
48
|
+
self, credential: CredentialSchema, credential_key_header_name: str
|
|
56
49
|
) -> None:
|
|
57
50
|
super().__init__(credential)
|
|
58
51
|
self._credential_key_header_name = credential_key_header_name
|
|
@@ -64,14 +57,17 @@ class AzureKeyCredentialPolicy(CredentialSchemaPolicy):
|
|
|
64
57
|
def call(self, async_mode: bool) -> str:
|
|
65
58
|
return f'policies.AzureKeyCredentialPolicy(self.credential, "{self.credential_key_header_name}", **kwargs)'
|
|
66
59
|
|
|
60
|
+
|
|
67
61
|
def get_credential_schema_policy_type(name):
|
|
68
|
-
policies = [
|
|
62
|
+
policies = [
|
|
63
|
+
ARMChallengeAuthenticationPolicy,
|
|
64
|
+
BearerTokenCredentialPolicy,
|
|
65
|
+
AzureKeyCredentialPolicy,
|
|
66
|
+
]
|
|
69
67
|
try:
|
|
70
68
|
return next(p for p in policies if p.name().lower() == name.lower())
|
|
71
69
|
except StopIteration:
|
|
72
70
|
raise ValueError(
|
|
73
71
|
"The credential policy you pass in with --credential-default-policy-type must be either "
|
|
74
|
-
"{}".format(
|
|
75
|
-
" or ".join([p.name() for p in policies])
|
|
76
|
-
)
|
|
72
|
+
"{}".format(" or ".join([p.name() for p in policies]))
|
|
77
73
|
)
|
|
@@ -3,10 +3,14 @@
|
|
|
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, Optional
|
|
6
|
+
from typing import Any, Dict, Optional, TYPE_CHECKING
|
|
7
7
|
from .base_schema import BaseSchema
|
|
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 DictionarySchema(BaseSchema):
|
|
11
15
|
"""Schema for dictionaries that will be serialized.
|
|
12
16
|
|
|
@@ -18,11 +22,11 @@ class DictionarySchema(BaseSchema):
|
|
|
18
22
|
|
|
19
23
|
def __init__(
|
|
20
24
|
self,
|
|
21
|
-
namespace: str,
|
|
22
25
|
yaml_data: Dict[str, Any],
|
|
23
|
-
|
|
26
|
+
code_model: "CodeModel",
|
|
27
|
+
element_type: "BaseSchema",
|
|
24
28
|
) -> None:
|
|
25
|
-
super(
|
|
29
|
+
super().__init__(yaml_data=yaml_data, code_model=code_model)
|
|
26
30
|
self.element_type = element_type
|
|
27
31
|
|
|
28
32
|
@property
|
|
@@ -34,18 +38,13 @@ class DictionarySchema(BaseSchema):
|
|
|
34
38
|
"""
|
|
35
39
|
return f"{{{self.element_type.serialization_type}}}"
|
|
36
40
|
|
|
37
|
-
|
|
38
|
-
def type_annotation(self) -> str:
|
|
41
|
+
def type_annotation(self, *, is_operation_file: bool = False) -> str:
|
|
39
42
|
"""The python type used for type annotation
|
|
40
43
|
|
|
41
44
|
:return: The type annotation for this schema
|
|
42
45
|
:rtype: str
|
|
43
46
|
"""
|
|
44
|
-
return f"Dict[str, {self.element_type.type_annotation}]"
|
|
45
|
-
|
|
46
|
-
@property
|
|
47
|
-
def operation_type_annotation(self) -> str:
|
|
48
|
-
return f"Dict[str, {self.element_type.operation_type_annotation}]"
|
|
47
|
+
return f"Dict[str, {self.element_type.type_annotation(is_operation_file=is_operation_file)}]"
|
|
49
48
|
|
|
50
49
|
@property
|
|
51
50
|
def docstring_text(self) -> str:
|
|
@@ -60,20 +59,19 @@ class DictionarySchema(BaseSchema):
|
|
|
60
59
|
return f"dict[str, {self.element_type.docstring_type}]"
|
|
61
60
|
|
|
62
61
|
def xml_serialization_ctxt(self) -> Optional[str]:
|
|
63
|
-
raise NotImplementedError(
|
|
62
|
+
raise NotImplementedError(
|
|
63
|
+
"Dictionary schema does not support XML serialization."
|
|
64
|
+
)
|
|
64
65
|
|
|
65
66
|
def get_json_template_representation(self, **kwargs: Any) -> Any:
|
|
66
67
|
return {
|
|
67
|
-
f'"{"str"}"'
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
def get_files_and_data_template_representation(self, **kwargs: Any) -> Any:
|
|
71
|
-
return {
|
|
72
|
-
f'"{"str"}"' : self.element_type.get_files_and_data_template_representation(**kwargs)
|
|
68
|
+
f'"{"str"}"': self.element_type.get_json_template_representation(**kwargs)
|
|
73
69
|
}
|
|
74
70
|
|
|
75
71
|
@classmethod
|
|
76
|
-
def from_yaml(
|
|
72
|
+
def from_yaml(
|
|
73
|
+
cls, yaml_data: Dict[str, Any], code_model: "CodeModel"
|
|
74
|
+
) -> "DictionarySchema":
|
|
77
75
|
"""Constructs a DictionarySchema from yaml data.
|
|
78
76
|
|
|
79
77
|
:param yaml_data: the yaml data from which we will construct this schema
|
|
@@ -86,18 +84,23 @@ class DictionarySchema(BaseSchema):
|
|
|
86
84
|
|
|
87
85
|
from . import build_schema # pylint: disable=import-outside-toplevel
|
|
88
86
|
|
|
89
|
-
element_type = build_schema(
|
|
90
|
-
yaml_data=element_schema, **kwargs
|
|
91
|
-
)
|
|
87
|
+
element_type = build_schema(yaml_data=element_schema, code_model=code_model)
|
|
92
88
|
|
|
93
89
|
return cls(
|
|
94
|
-
namespace=namespace,
|
|
95
90
|
yaml_data=yaml_data,
|
|
91
|
+
code_model=code_model,
|
|
96
92
|
element_type=element_type,
|
|
97
93
|
)
|
|
98
94
|
|
|
99
95
|
def imports(self) -> FileImport:
|
|
100
96
|
file_import = FileImport()
|
|
101
|
-
file_import.add_submodule_import(
|
|
97
|
+
file_import.add_submodule_import(
|
|
98
|
+
"typing", "Dict", ImportType.STDLIB, TypingSection.CONDITIONAL
|
|
99
|
+
)
|
|
102
100
|
file_import.merge(self.element_type.imports())
|
|
103
101
|
return file_import
|
|
102
|
+
|
|
103
|
+
def model_file_imports(self) -> FileImport:
|
|
104
|
+
file_import = self.imports()
|
|
105
|
+
file_import.merge(self.element_type.model_file_imports())
|
|
106
|
+
return file_import
|
|
@@ -3,11 +3,14 @@
|
|
|
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, List, Optional, Set, Type
|
|
6
|
+
from typing import Any, Dict, List, Optional, Set, Type, TYPE_CHECKING
|
|
7
7
|
from .base_schema import BaseSchema
|
|
8
8
|
from .primitive_schemas import PrimitiveSchema, get_primitive_schema, StringSchema
|
|
9
9
|
from .imports import FileImport, ImportType, TypingSection
|
|
10
10
|
|
|
11
|
+
if TYPE_CHECKING:
|
|
12
|
+
from .code_model import CodeModel
|
|
13
|
+
|
|
11
14
|
|
|
12
15
|
class EnumValue:
|
|
13
16
|
"""Model containing necessary information for a single value of an enum.
|
|
@@ -17,7 +20,9 @@ class EnumValue:
|
|
|
17
20
|
:param str description: Optional. The description for this enum value
|
|
18
21
|
"""
|
|
19
22
|
|
|
20
|
-
def __init__(
|
|
23
|
+
def __init__(
|
|
24
|
+
self, name: str, value: str, description: Optional[str] = None
|
|
25
|
+
) -> None:
|
|
21
26
|
self.name = name
|
|
22
27
|
self.value = value
|
|
23
28
|
self.description = description
|
|
@@ -53,19 +58,17 @@ class EnumSchema(BaseSchema):
|
|
|
53
58
|
|
|
54
59
|
def __init__(
|
|
55
60
|
self,
|
|
56
|
-
namespace: str,
|
|
57
61
|
yaml_data: Dict[str, Any],
|
|
62
|
+
code_model: "CodeModel",
|
|
58
63
|
description: str,
|
|
59
64
|
name: str,
|
|
60
65
|
values: List["EnumValue"],
|
|
61
66
|
enum_type: PrimitiveSchema,
|
|
62
|
-
enum_file_name: str
|
|
63
67
|
) -> None:
|
|
64
|
-
super(
|
|
68
|
+
super().__init__(yaml_data=yaml_data, code_model=code_model)
|
|
65
69
|
self.description = description
|
|
66
70
|
self.name = name
|
|
67
71
|
self.values = values
|
|
68
|
-
self.enum_file_name = enum_file_name
|
|
69
72
|
self.enum_type = enum_type
|
|
70
73
|
|
|
71
74
|
def __lt__(self, other):
|
|
@@ -80,23 +83,13 @@ class EnumSchema(BaseSchema):
|
|
|
80
83
|
"""
|
|
81
84
|
return self.enum_type.serialization_type
|
|
82
85
|
|
|
83
|
-
|
|
84
|
-
def type_annotation(self) -> str:
|
|
86
|
+
def type_annotation(self, *, is_operation_file: bool = False) -> str:
|
|
85
87
|
"""The python type used for type annotation
|
|
86
88
|
|
|
87
89
|
:return: The type annotation for this schema
|
|
88
90
|
:rtype: str
|
|
89
91
|
"""
|
|
90
|
-
return f'Union[{self.enum_type.type_annotation}, "{self.name}"]'
|
|
91
|
-
|
|
92
|
-
@property
|
|
93
|
-
def operation_type_annotation(self) -> str:
|
|
94
|
-
"""The python type used for type annotation
|
|
95
|
-
|
|
96
|
-
:return: The type annotation for this schema
|
|
97
|
-
:rtype: str
|
|
98
|
-
"""
|
|
99
|
-
return f'Union[{self.enum_type.type_annotation}, "_models.{self.name}"]'
|
|
92
|
+
return f'Union[{self.enum_type.type_annotation(is_operation_file=is_operation_file)}, "_models.{self.name}"]'
|
|
100
93
|
|
|
101
94
|
def get_declaration(self, value: Any) -> str:
|
|
102
95
|
return self.enum_type.get_declaration(value)
|
|
@@ -107,9 +100,8 @@ class EnumSchema(BaseSchema):
|
|
|
107
100
|
|
|
108
101
|
@property
|
|
109
102
|
def docstring_type(self) -> str:
|
|
110
|
-
"""The python type used for RST syntax input and type annotation.
|
|
111
|
-
""
|
|
112
|
-
return f"{self.enum_type.type_annotation} or ~{self.namespace}.models.{self.name}"
|
|
103
|
+
"""The python type used for RST syntax input and type annotation."""
|
|
104
|
+
return f"{self.enum_type.type_annotation()} or ~{self.code_model.namespace}.models.{self.name}"
|
|
113
105
|
|
|
114
106
|
@staticmethod
|
|
115
107
|
def _get_enum_values(yaml_data: List[Dict[str, Any]]) -> List["EnumValue"]:
|
|
@@ -133,21 +125,23 @@ class EnumSchema(BaseSchema):
|
|
|
133
125
|
|
|
134
126
|
def _template_kwargs(self, **kwargs: Any) -> Any:
|
|
135
127
|
if len(self.values) == 1 and not kwargs.get("default_value_declaration"):
|
|
136
|
-
kwargs[
|
|
128
|
+
kwargs["default_value_declaration"] = self.enum_type.get_declaration(
|
|
129
|
+
self.values[0].value
|
|
130
|
+
)
|
|
137
131
|
description = kwargs.pop("description", "")
|
|
138
132
|
kwargs["description"] = description
|
|
139
133
|
return kwargs
|
|
140
134
|
|
|
141
|
-
|
|
142
135
|
def get_json_template_representation(self, **kwargs: Any) -> Any:
|
|
143
136
|
# for better display effect, use the only value instead of var type
|
|
144
|
-
return self.enum_type.get_json_template_representation(
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
return self.enum_type.get_files_and_data_template_representation(**self._template_kwargs(**kwargs))
|
|
137
|
+
return self.enum_type.get_json_template_representation(
|
|
138
|
+
**self._template_kwargs(**kwargs)
|
|
139
|
+
)
|
|
148
140
|
|
|
149
141
|
@classmethod
|
|
150
|
-
def from_yaml(
|
|
142
|
+
def from_yaml(
|
|
143
|
+
cls, yaml_data: Dict[str, Any], code_model: "CodeModel"
|
|
144
|
+
) -> "EnumSchema":
|
|
151
145
|
"""Constructs an EnumSchema from yaml data.
|
|
152
146
|
|
|
153
147
|
:param yaml_data: the yaml data from which we will construct this schema
|
|
@@ -160,63 +154,47 @@ class EnumSchema(BaseSchema):
|
|
|
160
154
|
|
|
161
155
|
# choice type doesn't always exist. if there is no choiceType, we default to string
|
|
162
156
|
if yaml_data.get("choiceType"):
|
|
163
|
-
enum_type = get_primitive_schema(
|
|
157
|
+
enum_type = get_primitive_schema(yaml_data["choiceType"], code_model)
|
|
164
158
|
else:
|
|
165
|
-
enum_type = StringSchema(
|
|
159
|
+
enum_type = StringSchema({"type": "str"}, code_model)
|
|
166
160
|
values = EnumSchema._get_enum_values(yaml_data["choices"])
|
|
167
|
-
code_model = kwargs.pop("code_model")
|
|
168
|
-
|
|
169
161
|
return cls(
|
|
170
|
-
namespace=namespace,
|
|
171
162
|
yaml_data=yaml_data,
|
|
163
|
+
code_model=code_model,
|
|
172
164
|
description=yaml_data["language"]["python"]["description"],
|
|
173
165
|
name=name,
|
|
174
166
|
values=values,
|
|
175
167
|
enum_type=enum_type,
|
|
176
|
-
enum_file_name=f"_{code_model.module_name}_enums"
|
|
177
168
|
)
|
|
178
169
|
|
|
179
170
|
def imports(self) -> FileImport:
|
|
180
171
|
file_import = FileImport()
|
|
181
|
-
file_import.add_submodule_import(
|
|
172
|
+
file_import.add_submodule_import(
|
|
173
|
+
"typing", "Union", ImportType.STDLIB, TypingSection.CONDITIONAL
|
|
174
|
+
)
|
|
182
175
|
file_import.merge(self.enum_type.imports())
|
|
183
176
|
return file_import
|
|
184
177
|
|
|
185
|
-
def model_file_imports(self) -> FileImport:
|
|
186
|
-
imports = self.imports()
|
|
187
|
-
# we import every enum since we can get extremely long imports
|
|
188
|
-
# if we import my name
|
|
189
|
-
imports.add_submodule_import("." + self.enum_file_name, "*", ImportType.LOCAL)
|
|
190
|
-
return imports
|
|
191
178
|
|
|
192
179
|
class HiddenModelEnumSchema(EnumSchema):
|
|
193
|
-
|
|
194
180
|
def imports(self) -> FileImport:
|
|
195
181
|
file_import = FileImport()
|
|
196
182
|
file_import.merge(self.enum_type.imports())
|
|
197
183
|
return file_import
|
|
198
184
|
|
|
199
|
-
|
|
200
|
-
def type_annotation(self) -> str:
|
|
201
|
-
"""The python type used for type annotation
|
|
202
|
-
|
|
203
|
-
:return: The type annotation for this schema
|
|
204
|
-
:rtype: str
|
|
205
|
-
"""
|
|
206
|
-
return self.enum_type.type_annotation
|
|
207
|
-
|
|
208
|
-
@property
|
|
209
|
-
def operation_type_annotation(self) -> str:
|
|
185
|
+
def type_annotation(self, *, is_operation_file: bool = False) -> str:
|
|
210
186
|
"""The python type used for type annotation
|
|
211
187
|
|
|
212
188
|
:return: The type annotation for this schema
|
|
213
189
|
:rtype: str
|
|
214
190
|
"""
|
|
215
|
-
return self.enum_type.type_annotation
|
|
191
|
+
return self.enum_type.type_annotation(is_operation_file=is_operation_file)
|
|
216
192
|
|
|
217
193
|
@property
|
|
218
194
|
def docstring_text(self) -> str:
|
|
219
|
-
return
|
|
195
|
+
return (
|
|
196
|
+
f"{self.enum_type.type_annotation()}. {self.extra_description_information}"
|
|
197
|
+
)
|
|
220
198
|
|
|
221
199
|
@property
|
|
222
200
|
def extra_description_information(self):
|
|
@@ -228,17 +206,18 @@ class HiddenModelEnumSchema(EnumSchema):
|
|
|
228
206
|
if len(possible_values) == 2:
|
|
229
207
|
possible_values_str = " or ".join(possible_values)
|
|
230
208
|
else:
|
|
231
|
-
possible_values_str =
|
|
232
|
-
possible_values[: len(possible_values) - 1]
|
|
233
|
-
|
|
209
|
+
possible_values_str = (
|
|
210
|
+
", ".join(possible_values[: len(possible_values) - 1])
|
|
211
|
+
+ f", and {possible_values[-1]}"
|
|
212
|
+
)
|
|
234
213
|
|
|
235
|
-
return "
|
|
214
|
+
return "Known values are: {}.".format(possible_values_str)
|
|
236
215
|
|
|
237
216
|
@property
|
|
238
217
|
def docstring_type(self) -> str:
|
|
239
|
-
"""The python type used for RST syntax input and type annotation.
|
|
240
|
-
|
|
241
|
-
|
|
218
|
+
"""The python type used for RST syntax input and type annotation."""
|
|
219
|
+
return self.enum_type.type_annotation()
|
|
220
|
+
|
|
242
221
|
|
|
243
222
|
def get_enum_schema(code_model) -> Type[EnumSchema]:
|
|
244
223
|
if code_model.options["models_mode"]:
|
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
# license information.
|
|
5
5
|
# --------------------------------------------------------------------------
|
|
6
6
|
from enum import Enum
|
|
7
|
-
from typing import Dict, List, Optional, Tuple, Union, Set
|
|
7
|
+
from typing import Dict, List, Optional, Tuple, Union, Set, Mapping
|
|
8
|
+
|
|
8
9
|
|
|
9
10
|
class ImportType(str, Enum):
|
|
10
11
|
STDLIB = "stdlib"
|
|
@@ -12,11 +13,13 @@ class ImportType(str, Enum):
|
|
|
12
13
|
AZURECORE = "azurecore"
|
|
13
14
|
LOCAL = "local"
|
|
14
15
|
|
|
16
|
+
|
|
15
17
|
class TypingSection(str, Enum):
|
|
16
18
|
REGULAR = "regular" # this import is always a typing import
|
|
17
19
|
CONDITIONAL = "conditional" # is a typing import when we're dealing with files that py2 will use, else regular
|
|
18
20
|
TYPING = "typing" # never a typing import
|
|
19
21
|
|
|
22
|
+
|
|
20
23
|
class ImportModel:
|
|
21
24
|
def __init__(
|
|
22
25
|
self,
|
|
@@ -36,11 +39,11 @@ class ImportModel:
|
|
|
36
39
|
def __eq__(self, other):
|
|
37
40
|
try:
|
|
38
41
|
return (
|
|
39
|
-
self.typing_section == other.typing_section
|
|
40
|
-
self.import_type == other.import_type
|
|
41
|
-
self.module_name == other.module_name
|
|
42
|
-
self.submodule_name == other.submodule_name
|
|
43
|
-
self.alias == other.alias
|
|
42
|
+
self.typing_section == other.typing_section
|
|
43
|
+
and self.import_type == other.import_type
|
|
44
|
+
and self.module_name == other.module_name
|
|
45
|
+
and self.submodule_name == other.submodule_name
|
|
46
|
+
and self.alias == other.alias
|
|
44
47
|
)
|
|
45
48
|
except AttributeError:
|
|
46
49
|
return False
|
|
@@ -52,18 +55,32 @@ class ImportModel:
|
|
|
52
55
|
retval += hash(getattr(self, attr))
|
|
53
56
|
return retval
|
|
54
57
|
|
|
55
|
-
|
|
58
|
+
|
|
59
|
+
class TypeDefinition:
|
|
56
60
|
def __init__(
|
|
57
61
|
self,
|
|
58
|
-
|
|
59
|
-
|
|
62
|
+
sync_definition: str,
|
|
63
|
+
async_definition: str,
|
|
64
|
+
version_imports: Mapping[Optional[Tuple[int, int]], ImportModel] = None,
|
|
65
|
+
):
|
|
66
|
+
# version_imports: a map of "python version -> ImportModel".
|
|
67
|
+
# The python version is in form of (major, minor), for instance (3, 9) stands for py3.9.
|
|
68
|
+
# If the python version is None, it's a default ImportModel.
|
|
69
|
+
self.sync_definition = sync_definition
|
|
70
|
+
self.async_definition = async_definition
|
|
71
|
+
self.version_imports = version_imports
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
class FileImport:
|
|
75
|
+
def __init__(self, imports: List[ImportModel] = None) -> None:
|
|
60
76
|
self.imports = imports or []
|
|
61
77
|
# has sync and async type definitions
|
|
62
|
-
self.type_definitions: Dict[str,
|
|
78
|
+
self.type_definitions: Dict[str, TypeDefinition] = {}
|
|
63
79
|
|
|
64
80
|
def _append_import(self, import_model: ImportModel) -> None:
|
|
65
81
|
if not any(
|
|
66
|
-
i
|
|
82
|
+
i
|
|
83
|
+
for i in self.imports
|
|
67
84
|
if all(
|
|
68
85
|
getattr(i, attr) == getattr(import_model, attr)
|
|
69
86
|
for attr in dir(i)
|
|
@@ -72,7 +89,9 @@ class FileImport:
|
|
|
72
89
|
):
|
|
73
90
|
self.imports.append(import_model)
|
|
74
91
|
|
|
75
|
-
def get_imports_from_section(
|
|
92
|
+
def get_imports_from_section(
|
|
93
|
+
self, typing_section: TypingSection
|
|
94
|
+
) -> List[ImportModel]:
|
|
76
95
|
return [i for i in self.imports if i.typing_section == typing_section]
|
|
77
96
|
|
|
78
97
|
def add_submodule_import(
|
|
@@ -83,32 +102,44 @@ class FileImport:
|
|
|
83
102
|
typing_section: TypingSection = TypingSection.REGULAR,
|
|
84
103
|
alias: Optional[str] = None,
|
|
85
104
|
) -> None:
|
|
86
|
-
"""Add an import to this import block.
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
105
|
+
"""Add an import to this import block."""
|
|
106
|
+
self._append_import(
|
|
107
|
+
ImportModel(
|
|
108
|
+
typing_section=typing_section,
|
|
109
|
+
import_type=import_type,
|
|
110
|
+
module_name=module_name,
|
|
111
|
+
submodule_name=submodule_name,
|
|
112
|
+
alias=alias,
|
|
113
|
+
)
|
|
114
|
+
)
|
|
95
115
|
|
|
96
116
|
def add_import(
|
|
97
117
|
self,
|
|
98
118
|
module_name: str,
|
|
99
119
|
import_type: ImportType,
|
|
100
|
-
typing_section: TypingSection = TypingSection.REGULAR
|
|
120
|
+
typing_section: TypingSection = TypingSection.REGULAR,
|
|
121
|
+
alias: Optional[str] = None,
|
|
101
122
|
) -> None:
|
|
102
123
|
# Implementation detail: a regular import is just a "from" with no from
|
|
103
|
-
self._append_import(
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
124
|
+
self._append_import(
|
|
125
|
+
ImportModel(
|
|
126
|
+
typing_section=typing_section,
|
|
127
|
+
import_type=import_type,
|
|
128
|
+
module_name=module_name,
|
|
129
|
+
alias=alias,
|
|
130
|
+
)
|
|
131
|
+
)
|
|
108
132
|
|
|
109
|
-
def define_mypy_type(
|
|
110
|
-
self
|
|
111
|
-
|
|
133
|
+
def define_mypy_type(
|
|
134
|
+
self,
|
|
135
|
+
type_name: str,
|
|
136
|
+
type_value: str,
|
|
137
|
+
async_type_value: Optional[str] = None,
|
|
138
|
+
version_imports: Mapping[Optional[Tuple[int, int]], ImportModel] = None,
|
|
139
|
+
):
|
|
140
|
+
self.type_definitions[type_name] = TypeDefinition(
|
|
141
|
+
type_value, async_type_value or type_value, version_imports
|
|
142
|
+
)
|
|
112
143
|
|
|
113
144
|
def merge(self, file_import: "FileImport") -> None:
|
|
114
145
|
"""Merge the given file import format."""
|
|
@@ -116,23 +147,23 @@ class FileImport:
|
|
|
116
147
|
self._append_import(i)
|
|
117
148
|
self.type_definitions.update(file_import.type_definitions)
|
|
118
149
|
|
|
119
|
-
def to_dict(
|
|
150
|
+
def to_dict(
|
|
151
|
+
self,
|
|
152
|
+
) -> Dict[
|
|
120
153
|
TypingSection,
|
|
121
|
-
Dict[ImportType, Dict[str, Set[Optional[Union[str, Tuple[str, str]]]]]]
|
|
154
|
+
Dict[ImportType, Dict[str, Set[Optional[Union[str, Tuple[str, str]]]]]],
|
|
122
155
|
]:
|
|
123
156
|
retval: Dict[
|
|
124
157
|
TypingSection,
|
|
125
|
-
Dict[ImportType, Dict[str, Set[Optional[Union[str, Tuple[str, str]]]]]]
|
|
158
|
+
Dict[ImportType, Dict[str, Set[Optional[Union[str, Tuple[str, str]]]]]],
|
|
126
159
|
] = dict()
|
|
127
160
|
for i in self.imports:
|
|
128
161
|
name_import: Optional[Union[str, Tuple[str, str]]] = None
|
|
129
162
|
if i.submodule_name:
|
|
130
|
-
name_import = (
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
i.module_name, set()
|
|
137
|
-
).add(name_import)
|
|
163
|
+
name_import = (
|
|
164
|
+
(i.submodule_name, i.alias) if i.alias else i.submodule_name
|
|
165
|
+
)
|
|
166
|
+
retval.setdefault(i.typing_section, dict()).setdefault(
|
|
167
|
+
i.import_type, dict()
|
|
168
|
+
).setdefault(i.module_name, set()).add(name_import)
|
|
138
169
|
return retval
|