@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.
Files changed (101) hide show
  1. package/ChangeLog.md +67 -0
  2. package/autorest/__init__.py +1 -2
  3. package/autorest/black/__init__.py +12 -5
  4. package/autorest/codegen/__init__.py +239 -105
  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 +21 -24
  9. package/autorest/codegen/models/client.py +70 -20
  10. package/autorest/codegen/models/code_model.py +144 -129
  11. package/autorest/codegen/models/constant_schema.py +32 -16
  12. package/autorest/codegen/models/credential_model.py +55 -0
  13. package/autorest/codegen/models/credential_schema.py +21 -16
  14. package/autorest/codegen/models/credential_schema_policy.py +11 -15
  15. package/autorest/codegen/models/dictionary_schema.py +27 -24
  16. package/autorest/codegen/models/enum_schema.py +41 -62
  17. package/autorest/codegen/models/imports.py +72 -41
  18. package/autorest/codegen/models/list_schema.py +40 -18
  19. package/autorest/codegen/models/lro_operation.py +61 -25
  20. package/autorest/codegen/models/lro_paging_operation.py +5 -6
  21. package/autorest/codegen/models/object_schema.py +113 -59
  22. package/autorest/codegen/models/operation.py +251 -111
  23. package/autorest/codegen/models/operation_group.py +67 -32
  24. package/autorest/codegen/models/paging_operation.py +48 -21
  25. package/autorest/codegen/models/parameter.py +182 -90
  26. package/autorest/codegen/models/parameter_list.py +184 -163
  27. package/autorest/codegen/models/primitive_schemas.py +89 -70
  28. package/autorest/codegen/models/property.py +49 -31
  29. package/autorest/codegen/models/request_builder.py +67 -32
  30. package/autorest/codegen/models/request_builder_parameter.py +54 -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 +35 -17
  34. package/autorest/codegen/models/utils.py +24 -1
  35. package/autorest/codegen/serializers/__init__.py +273 -89
  36. package/autorest/codegen/serializers/builder_serializer.py +711 -333
  37. package/autorest/codegen/serializers/client_serializer.py +114 -43
  38. package/autorest/codegen/serializers/general_serializer.py +84 -25
  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 +42 -14
  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 +9 -8
  45. package/autorest/codegen/serializers/operation_groups_serializer.py +20 -8
  46. package/autorest/codegen/serializers/operations_init_serializer.py +23 -11
  47. package/autorest/codegen/serializers/patch_serializer.py +14 -2
  48. package/autorest/codegen/serializers/{rest_serializer.py → request_builders_serializer.py} +29 -12
  49. package/autorest/codegen/serializers/utils.py +60 -21
  50. package/autorest/codegen/templates/CHANGELOG.md.jinja2 +6 -0
  51. package/autorest/codegen/templates/LICENSE.jinja2 +21 -0
  52. package/autorest/codegen/templates/MANIFEST.in.jinja2 +7 -0
  53. package/autorest/codegen/templates/README.md.jinja2 +105 -0
  54. package/autorest/codegen/templates/config.py.jinja2 +4 -4
  55. package/autorest/codegen/templates/dev_requirements.txt.jinja2 +10 -0
  56. package/autorest/codegen/templates/enum.py.jinja2 +1 -1
  57. package/autorest/codegen/templates/enum_container.py.jinja2 +0 -1
  58. package/autorest/codegen/templates/init.py.jinja2 +9 -6
  59. package/autorest/codegen/templates/keywords.jinja2 +14 -1
  60. package/autorest/codegen/templates/lro_operation.py.jinja2 +5 -7
  61. package/autorest/codegen/templates/lro_paging_operation.py.jinja2 +5 -7
  62. package/autorest/codegen/templates/metadata.json.jinja2 +10 -9
  63. package/autorest/codegen/templates/model.py.jinja2 +1 -6
  64. package/autorest/codegen/templates/model_init.py.jinja2 +7 -4
  65. package/autorest/codegen/templates/operation.py.jinja2 +8 -11
  66. package/autorest/codegen/templates/operation_group.py.jinja2 +15 -18
  67. package/autorest/codegen/templates/operation_groups_container.py.jinja2 +1 -2
  68. package/autorest/codegen/templates/operations_folder_init.py.jinja2 +4 -0
  69. package/autorest/codegen/templates/paging_operation.py.jinja2 +7 -8
  70. package/autorest/codegen/templates/patch.py.jinja2 +18 -29
  71. package/autorest/codegen/templates/request_builder.py.jinja2 +19 -14
  72. package/autorest/codegen/templates/setup.py.jinja2 +79 -20
  73. package/autorest/codegen/templates/vendor.py.jinja2 +12 -2
  74. package/autorest/jsonrpc/__init__.py +7 -12
  75. package/autorest/jsonrpc/localapi.py +4 -3
  76. package/autorest/jsonrpc/server.py +13 -6
  77. package/autorest/jsonrpc/stdstream.py +13 -6
  78. package/autorest/m2r/__init__.py +5 -8
  79. package/autorest/multiapi/__init__.py +24 -14
  80. package/autorest/multiapi/models/client.py +21 -11
  81. package/autorest/multiapi/models/code_model.py +23 -10
  82. package/autorest/multiapi/models/config.py +4 -1
  83. package/autorest/multiapi/models/constant_global_parameter.py +1 -0
  84. package/autorest/multiapi/models/global_parameter.py +2 -1
  85. package/autorest/multiapi/models/global_parameters.py +14 -8
  86. package/autorest/multiapi/models/imports.py +35 -18
  87. package/autorest/multiapi/models/mixin_operation.py +5 -5
  88. package/autorest/multiapi/models/operation_group.py +2 -1
  89. package/autorest/multiapi/models/operation_mixin_group.py +21 -10
  90. package/autorest/multiapi/serializers/__init__.py +18 -23
  91. package/autorest/multiapi/serializers/import_serializer.py +47 -15
  92. package/autorest/multiapi/serializers/multiapi_serializer.py +17 -17
  93. package/autorest/multiapi/templates/multiapi_operations_mixin.py.jinja2 +1 -1
  94. package/autorest/multiapi/utils.py +3 -3
  95. package/autorest/namer/__init__.py +2 -4
  96. package/autorest/namer/name_converter.py +200 -103
  97. package/autorest/namer/python_mappings.py +10 -22
  98. package/package.json +3 -3
  99. package/run-python3.js +2 -3
  100. package/venvtools.py +1 -1
  101. 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("You should not try to get a JSON template representation of a CredentialSchema")
30
-
31
- def get_files_and_data_template_representation(self, **kwargs: Any) -> Any:
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
- @property
42
- def type_annotation(self) -> str:
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(TokenCredentialSchema, self).__init__()
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
- @property
70
- def type_annotation(self) -> str:
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", "AsyncTokenCredential",
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", "TokenCredential",
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
- def __init__(self, credential: CredentialSchema, *args, **kwargs) -> None: # pylint: disable=unused-argument
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 = [ARMChallengeAuthenticationPolicy, BearerTokenCredentialPolicy, AzureKeyCredentialPolicy]
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
- element_type: "BaseSchema"
26
+ code_model: "CodeModel",
27
+ element_type: "BaseSchema",
24
28
  ) -> None:
25
- super(DictionarySchema, self).__init__(namespace=namespace, yaml_data=yaml_data)
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
- @property
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("Dictionary schema does not support XML serialization.")
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"}"' : self.element_type.get_json_template_representation(**kwargs)
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(cls, namespace: str, yaml_data: Dict[str, Any], **kwargs: Any) -> "DictionarySchema":
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("typing", "Dict", ImportType.STDLIB, TypingSection.CONDITIONAL)
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__(self, name: str, value: str, description: Optional[str] = None) -> None:
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(EnumSchema, self).__init__(namespace=namespace, yaml_data=yaml_data)
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
- @property
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['default_value_declaration'] = self.enum_type.get_declaration(self.values[0].value)
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(**self._template_kwargs(**kwargs))
145
-
146
- def get_files_and_data_template_representation(self, **kwargs: Any) -> Any:
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(cls, namespace: str, yaml_data: Dict[str, Any], **kwargs: Any) -> "EnumSchema":
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(namespace, yaml_data["choiceType"])
157
+ enum_type = get_primitive_schema(yaml_data["choiceType"], code_model)
164
158
  else:
165
- enum_type = StringSchema(namespace, {"type": "str"})
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("typing", "Union", ImportType.STDLIB, TypingSection.CONDITIONAL)
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
- @property
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 f"{self.enum_type.type_annotation}. {self.extra_description_information}"
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 = ", ".join(
232
- possible_values[: len(possible_values) - 1]
233
- ) + f", and {possible_values[-1]}"
209
+ possible_values_str = (
210
+ ", ".join(possible_values[: len(possible_values) - 1])
211
+ + f", and {possible_values[-1]}"
212
+ )
234
213
 
235
- return "Possible values are: {}.".format(possible_values_str)
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
- return self.enum_type.type_annotation
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 and
40
- self.import_type == other.import_type and
41
- self.module_name == other.module_name and
42
- self.submodule_name == other.submodule_name and
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
- class FileImport:
58
+
59
+ class TypeDefinition:
56
60
  def __init__(
57
61
  self,
58
- imports: List[ImportModel] = None
59
- ) -> None:
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, Tuple[str, 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 for i in self.imports
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(self, typing_section: TypingSection) -> List[ImportModel]:
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
- self._append_import(ImportModel(
89
- typing_section=typing_section,
90
- import_type=import_type,
91
- module_name=module_name,
92
- submodule_name=submodule_name,
93
- alias=alias,
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(ImportModel(
104
- typing_section=typing_section,
105
- import_type=import_type,
106
- module_name=module_name,
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(self, type_name: str, type_value: str, async_type_value: Optional[str] = None):
110
- self.add_submodule_import("typing", "TypeVar", ImportType.STDLIB, TypingSection.CONDITIONAL)
111
- self.type_definitions[type_name] = (type_value, async_type_value or type_value)
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(self) -> 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 = (i.submodule_name, i.alias) if i.alias else i.submodule_name
131
- retval.setdefault(
132
- i.typing_section, dict()
133
- ).setdefault(
134
- i.import_type, dict()
135
- ).setdefault(
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