@autorest/python 6.2.11 → 6.2.12

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.
@@ -9,7 +9,7 @@ from .base import BaseModel
9
9
  from .base_builder import BaseBuilder
10
10
  from .code_model import CodeModel
11
11
  from .client import Client
12
- from .model_type import ModelType
12
+ from .model_type import ModelType, JSONModelType, DPGModelType, MsrestModelType
13
13
  from .dictionary_type import DictionaryType
14
14
  from .list_type import ListType
15
15
  from .combined_type import CombinedType
@@ -156,7 +156,13 @@ def build_type(yaml_data: Dict[str, Any], code_model: CodeModel) -> BaseType:
156
156
  pass
157
157
  if yaml_data["type"] == "model":
158
158
  # need to special case model to avoid recursion
159
- response = ModelType(yaml_data, code_model)
159
+ if yaml_data["base"] == "json" or not code_model.options["models_mode"]:
160
+ model_type = JSONModelType
161
+ elif yaml_data["base"] == "dpg":
162
+ model_type = DPGModelType # type: ignore
163
+ else:
164
+ model_type = MsrestModelType # type: ignore
165
+ response = model_type(yaml_data, code_model)
160
166
  code_model.types_map[yaml_id] = response
161
167
  response.fill_instance_from_yaml(yaml_data, code_model)
162
168
  else:
@@ -190,7 +190,7 @@ class CodeModel: # pylint: disable=too-many-public-methods
190
190
 
191
191
  @property
192
192
  def public_model_types(self) -> List[ModelType]:
193
- return [m for m in self.model_types if m.is_public]
193
+ return [m for m in self.model_types if m.is_public and not m.base == "json"]
194
194
 
195
195
  @property
196
196
  def enums(self) -> List[EnumType]:
@@ -79,9 +79,10 @@ class CombinedType(BaseType):
79
79
  client_default_value_declaration: Optional[str] = None,
80
80
  description: Optional[str] = None,
81
81
  ) -> Any:
82
- """Template of what this schema would look like as JSON input"""
83
- raise ValueError(
84
- "You shouldn't get a JSON template representation of multiple types"
82
+ return self.types[0].get_json_template_representation(
83
+ optional=optional,
84
+ client_default_value_declaration=client_default_value_declaration,
85
+ description=description,
85
86
  )
86
87
 
87
88
  def get_polymorphic_subtypes(self, polymorphic_subtypes: List["ModelType"]) -> None:
@@ -5,13 +5,20 @@
5
5
  # --------------------------------------------------------------------------
6
6
  from collections import OrderedDict
7
7
  from typing import Any, Dict, List, Optional, TYPE_CHECKING, cast
8
-
8
+ import sys
9
9
  from autorest.codegen.models.utils import add_to_pylint_disable
10
10
  from .base import BaseType
11
11
  from .constant_type import ConstantType
12
12
  from .property import Property
13
13
  from .imports import FileImport, ImportType, TypingSection
14
14
 
15
+
16
+ if sys.version_info >= (3, 8):
17
+ from typing import Literal # pylint: disable=no-name-in-module, ungrouped-imports
18
+ else:
19
+ from typing_extensions import Literal # type: ignore # pylint: disable=ungrouped-imports
20
+
21
+
15
22
  if TYPE_CHECKING:
16
23
  from .code_model import CodeModel
17
24
 
@@ -33,7 +40,7 @@ def _get_properties(type: "ModelType", properties: List[Property]) -> List[Prope
33
40
  return properties
34
41
 
35
42
 
36
- class ModelType(
43
+ class ModelType( # pylint: disable=abstract-method
37
44
  BaseType
38
45
  ): # pylint: disable=too-many-instance-attributes, too-many-public-methods
39
46
  """Represents a class ready to be serialized in Python.
@@ -44,6 +51,8 @@ class ModelType(
44
51
  :type properties: dict(str, str)
45
52
  """
46
53
 
54
+ base: Literal["msrest", "dpg", "json"]
55
+
47
56
  def __init__(
48
57
  self,
49
58
  yaml_data: Dict[str, Any],
@@ -72,15 +81,6 @@ class ModelType(
72
81
  def is_xml(self) -> bool:
73
82
  return self.yaml_data.get("isXml", False)
74
83
 
75
- @property
76
- def serialization_type(self) -> str:
77
- if self.code_model.options["models_mode"] == "msrest":
78
- private_model_path = f"_models.{self.code_model.models_filename}."
79
- return f"{'' if self.is_public else private_model_path}{self.name}"
80
- if self.code_model.options["models_mode"] == "dpg":
81
- return f"{'' if self.is_public else '_models.'}_models.{self.name}"
82
- return "object"
83
-
84
84
  @property
85
85
  def msrest_deserialization_key(self) -> str:
86
86
  return self.name
@@ -89,28 +89,9 @@ class ModelType(
89
89
  def is_polymorphic(self) -> bool:
90
90
  return any(p.is_polymorphic for p in self.properties)
91
91
 
92
- def type_annotation(self, **kwargs: Any) -> str:
93
- if self.code_model.options["models_mode"]:
94
- is_operation_file = kwargs.pop("is_operation_file", False)
95
- retval = f"_models.{self.name}"
96
- if not self.is_public:
97
- retval = f"{self.code_model.models_filename}.{retval}"
98
- return retval if is_operation_file else f'"{retval}"'
99
- return "ET.Element" if self.is_xml else "JSON"
100
-
101
- def docstring_type(self, **kwargs: Any) -> str:
102
- if self.code_model.options["models_mode"]:
103
- return f"~{self.code_model.namespace}.models.{self.name}"
104
- return "ET.Element" if self.is_xml else "JSON"
105
-
106
92
  def description(self, *, is_operation_file: bool = False) -> str:
107
93
  return "" if is_operation_file else self.yaml_data.get("description", self.name)
108
94
 
109
- def docstring_text(self, **kwargs: Any) -> str:
110
- if self.code_model.options["models_mode"]:
111
- return self.name
112
- return "XML Element" if self.is_xml else "JSON object"
113
-
114
95
  def get_declaration(self, value: Any) -> str:
115
96
  return f"{self.name}()"
116
97
 
@@ -252,15 +233,6 @@ class ModelType(
252
233
  except StopIteration:
253
234
  return None
254
235
 
255
- @property
256
- def instance_check_template(self) -> str:
257
- models_mode = self.code_model.options["models_mode"]
258
- if models_mode == "msrest":
259
- return "isinstance({}, msrest.Model)"
260
- if models_mode == "dpg":
261
- return "isinstance({}, _model_base.Model)"
262
- return "isinstance({}, MutableMapping)"
263
-
264
236
  @property
265
237
  def pylint_disable(self) -> str:
266
238
  retval: str = ""
@@ -277,20 +249,87 @@ class ModelType(
277
249
 
278
250
  def imports(self, **kwargs: Any) -> FileImport:
279
251
  file_import = FileImport()
280
- relative_path = kwargs.pop("relative_path", None)
281
- if self.code_model.options["models_mode"] and relative_path:
282
- # add import for models in operations file
283
- file_import.add_submodule_import(
284
- relative_path, "models", ImportType.LOCAL, alias="_models"
285
- )
286
- if self.code_model.options["models_mode"] == "msrest":
287
- return file_import
288
252
  file_import.add_submodule_import(
289
253
  "typing", "Any", ImportType.STDLIB, TypingSection.CONDITIONAL
290
254
  )
255
+ return file_import
256
+
257
+
258
+ class JSONModelType(ModelType):
259
+ base = "json"
260
+
261
+ def type_annotation(self, **kwargs: Any) -> str:
262
+ return "ET.Element" if self.is_xml else "JSON"
263
+
264
+ @property
265
+ def serialization_type(self) -> str:
266
+ return "object"
267
+
268
+ def docstring_type(self, **kwargs: Any) -> str:
269
+ return "ET.Element" if self.is_xml else "JSON"
270
+
271
+ def docstring_text(self, **kwargs: Any) -> str:
272
+ return "XML Element" if self.is_xml else "JSON object"
273
+
274
+ @property
275
+ def instance_check_template(self) -> str:
276
+ return "isinstance({}, MutableMapping)"
277
+
278
+ def imports(self, **kwargs: Any) -> FileImport:
279
+ file_import = super().imports(**kwargs)
291
280
  file_import.define_mutable_mapping_type()
292
281
  if self.is_xml:
293
282
  file_import.add_submodule_import(
294
283
  "xml.etree", "ElementTree", ImportType.STDLIB, alias="ET"
295
284
  )
296
285
  return file_import
286
+
287
+
288
+ class GeneratedModelType(ModelType): # pylint: disable=abstract-method
289
+ def type_annotation(self, **kwargs: Any) -> str:
290
+ is_operation_file = kwargs.pop("is_operation_file", False)
291
+ retval = f"_models.{self.name}"
292
+ if not self.is_public:
293
+ retval = f"{self.code_model.models_filename}.{retval}"
294
+ return retval if is_operation_file else f'"{retval}"'
295
+
296
+ def docstring_type(self, **kwargs: Any) -> str:
297
+ return f"~{self.code_model.namespace}.models.{self.name}"
298
+
299
+ def docstring_text(self, **kwargs: Any) -> str:
300
+ return self.name
301
+
302
+ def imports(self, **kwargs: Any) -> FileImport:
303
+ file_import = super().imports(**kwargs)
304
+ relative_path = kwargs.pop("relative_path", None)
305
+ if relative_path:
306
+ # add import for models in operations file
307
+ file_import.add_submodule_import(
308
+ relative_path, "models", ImportType.LOCAL, alias="_models"
309
+ )
310
+ return file_import
311
+
312
+
313
+ class MsrestModelType(GeneratedModelType):
314
+ base = "msrest"
315
+
316
+ @property
317
+ def serialization_type(self) -> str:
318
+ private_model_path = f"_models.{self.code_model.models_filename}."
319
+ return f"{'' if self.is_public else private_model_path}{self.name}"
320
+
321
+ @property
322
+ def instance_check_template(self) -> str:
323
+ return "isinstance({}, msrest.Model)"
324
+
325
+
326
+ class DPGModelType(GeneratedModelType):
327
+ base = "dpg"
328
+
329
+ @property
330
+ def serialization_type(self) -> str:
331
+ return f"{'' if self.is_public else '_models.'}_models.{self.name}"
332
+
333
+ @property
334
+ def instance_check_template(self) -> str:
335
+ return "isinstance({}, _model_base.Model)"
@@ -314,9 +314,6 @@ class _BuilderBaseSerializer(Generic[BuilderType]): # pylint: disable=abstract-
314
314
 
315
315
  def _json_input_example_template(self, builder: BuilderType) -> List[str]:
316
316
  template: List[str] = []
317
- if self.code_model.options["models_mode"]:
318
- # No input template if we have models
319
- return template
320
317
  if (
321
318
  not builder.parameters.has_body
322
319
  or builder.parameters.body_parameter.flattened
@@ -331,6 +328,15 @@ class _BuilderBaseSerializer(Generic[BuilderType]): # pylint: disable=abstract-
331
328
  if not isinstance(body_param.type, (ListType, DictionaryType, ModelType)):
332
329
  return template
333
330
 
331
+ if (
332
+ isinstance(body_param.type, (ListType, DictionaryType))
333
+ and self.code_model.options["models_mode"]
334
+ ):
335
+ return template
336
+
337
+ if isinstance(body_param.type, ModelType) and body_param.type.base != "json":
338
+ return template
339
+
334
340
  polymorphic_subtypes: List[ModelType] = []
335
341
  body_param.type.get_polymorphic_subtypes(polymorphic_subtypes)
336
342
  if polymorphic_subtypes:
@@ -4,9 +4,9 @@
4
4
 
5
5
  {{ imports }}
6
6
  {% for model in code_model.model_types %}
7
- {% if code_model.options["models_mode"] == "dpg" %}
7
+ {% if model.base == "dpg" %}
8
8
  {% include "model_dpg.py.jinja2" %}
9
- {% else %}
9
+ {% elif model.base == "msrest" %}
10
10
  {% include "model_msrest.py.jinja2" %}
11
11
  {% endif %}
12
12
  {% endfor %}
@@ -65,8 +65,8 @@
65
65
  {% for param_signature in serializer.init_line(model) %}
66
66
  {{ param_signature }}
67
67
  {% endfor %}
68
- **kwargs
69
- ):
68
+ **kwargs: Any
69
+ ) -> None:
70
70
  """
71
71
  {% if model.properties %}
72
72
  {% for p in model.properties %}
@@ -38,7 +38,20 @@ import logging
38
38
  import re
39
39
  import sys
40
40
  import codecs
41
- from typing import Optional, Union, AnyStr, IO, Mapping
41
+ from typing import (
42
+ Dict,
43
+ Any,
44
+ cast,
45
+ Optional,
46
+ Union,
47
+ AnyStr,
48
+ IO,
49
+ Mapping,
50
+ Callable,
51
+ TypeVar,
52
+ MutableMapping,
53
+ Type
54
+ )
42
55
 
43
56
  try:
44
57
  from urllib import quote # type: ignore
@@ -48,12 +61,13 @@ import xml.etree.ElementTree as ET
48
61
 
49
62
  import isodate # type: ignore
50
63
 
51
- from typing import Dict, Any, cast
52
-
53
64
  from azure.core.exceptions import DeserializationError, SerializationError, raise_with_traceback
54
65
 
55
66
  _BOM = codecs.BOM_UTF8.decode(encoding="utf-8")
56
67
 
68
+ ModelType = TypeVar("ModelType", bound="Model")
69
+ JSON = MutableMapping[str, Any]
70
+
57
71
 
58
72
  class RawDeserializer:
59
73
 
@@ -277,8 +291,8 @@ class Model(object):
277
291
  _attribute_map: Dict[str, Dict[str, Any]] = {}
278
292
  _validation: Dict[str, Dict[str, Any]] = {}
279
293
 
280
- def __init__(self, **kwargs):
281
- self.additional_properties = {}
294
+ def __init__(self, **kwargs: Any) -> None:
295
+ self.additional_properties: Dict[str, Any] = {}
282
296
  for k in kwargs:
283
297
  if k not in self._attribute_map:
284
298
  _LOGGER.warning("%s is not a known attribute of class %s and will be ignored", k, self.__class__)
@@ -287,25 +301,25 @@ class Model(object):
287
301
  else:
288
302
  setattr(self, k, kwargs[k])
289
303
 
290
- def __eq__(self, other):
304
+ def __eq__(self, other: Any) -> bool:
291
305
  """Compare objects by comparing all attributes."""
292
306
  if isinstance(other, self.__class__):
293
307
  return self.__dict__ == other.__dict__
294
308
  return False
295
309
 
296
- def __ne__(self, other):
310
+ def __ne__(self, other: Any) -> bool:
297
311
  """Compare objects by comparing all attributes."""
298
312
  return not self.__eq__(other)
299
313
 
300
- def __str__(self):
314
+ def __str__(self) -> str:
301
315
  return str(self.__dict__)
302
316
 
303
317
  @classmethod
304
- def enable_additional_properties_sending(cls):
318
+ def enable_additional_properties_sending(cls) -> None:
305
319
  cls._attribute_map["additional_properties"] = {"key": "", "type": "{object}"}
306
320
 
307
321
  @classmethod
308
- def is_xml_model(cls):
322
+ def is_xml_model(cls) -> bool:
309
323
  try:
310
324
  cls._xml_map # type: ignore
311
325
  except AttributeError:
@@ -322,7 +336,7 @@ class Model(object):
322
336
 
323
337
  return _create_xml_node(xml_map.get("name", cls.__name__), xml_map.get("prefix", None), xml_map.get("ns", None))
324
338
 
325
- def serialize(self, keep_readonly=False, **kwargs):
339
+ def serialize(self, keep_readonly: bool = False, **kwargs: Any) -> JSON:
326
340
  """Return the JSON that would be sent to azure from this model.
327
341
 
328
342
  This is an alias to `as_dict(full_restapi_key_transformer, keep_readonly=False)`.
@@ -336,7 +350,14 @@ class Model(object):
336
350
  serializer = Serializer(self._infer_class_models())
337
351
  return serializer._serialize(self, keep_readonly=keep_readonly, **kwargs)
338
352
 
339
- def as_dict(self, keep_readonly=True, key_transformer=attribute_transformer, **kwargs):
353
+ def as_dict(
354
+ self,
355
+ keep_readonly: bool = True,
356
+ key_transformer: Callable[
357
+ [str, Dict[str, Any], Any], Any
358
+ ] = attribute_transformer,
359
+ **kwargs: Any
360
+ ) -> JSON:
340
361
  """Return a dict that can be JSONify using json.dump.
341
362
 
342
363
  Advanced usage might optionally use a callback as parameter:
@@ -384,7 +405,7 @@ class Model(object):
384
405
  return client_models
385
406
 
386
407
  @classmethod
387
- def deserialize(cls, data, content_type=None):
408
+ def deserialize(cls: Type[ModelType], data: Any, content_type: Optional[str] = None) -> ModelType:
388
409
  """Parse a str using the RestAPI syntax and return a model.
389
410
 
390
411
  :param str data: A str using RestAPI structure. JSON by default.
@@ -396,7 +417,12 @@ class Model(object):
396
417
  return deserializer(cls.__name__, data, content_type=content_type)
397
418
 
398
419
  @classmethod
399
- def from_dict(cls, data, key_extractors=None, content_type=None):
420
+ def from_dict(
421
+ cls: Type[ModelType],
422
+ data: Any,
423
+ key_extractors: Optional[Callable[[str, Dict[str, Any], Any], Any]] = None,
424
+ content_type: Optional[str] = None,
425
+ ) -> ModelType:
400
426
  """Parse a dict using given key extractor return a model.
401
427
 
402
428
  By default consider key
@@ -409,7 +435,7 @@ class Model(object):
409
435
  :raises: DeserializationError if something went wrong
410
436
  """
411
437
  deserializer = Deserializer(cls._infer_class_models())
412
- deserializer.key_extractors = (
438
+ deserializer.key_extractors = ( # type: ignore
413
439
  [
414
440
  attribute_key_case_insensitive_extractor,
415
441
  rest_key_case_insensitive_extractor,
@@ -143,6 +143,7 @@ def create_model(yaml_data: Dict[str, Any]) -> Dict[str, Any]:
143
143
  base["name"] = yaml_data["language"]["default"]["name"]
144
144
  base["description"] = yaml_data["language"]["default"]["description"]
145
145
  base["isXml"] = "xml" in yaml_data.get("serializationFormats", [])
146
+ base["base"] = "msrest"
146
147
  return base
147
148
 
148
149
 
@@ -23,7 +23,6 @@ from .._utils import parse_args, get_body_type_for_description, JSON_REGEXP, KNO
23
23
  def add_body_param_type(
24
24
  code_model: Dict[str, Any],
25
25
  body_parameter: Dict[str, Any],
26
- models_mode: Optional[str],
27
26
  ):
28
27
  if (
29
28
  body_parameter
@@ -35,11 +34,12 @@ def add_body_param_type(
35
34
  and not any(t for t in ["flattened", "groupedBy"] if body_parameter.get(t))
36
35
  ):
37
36
  origin_type = body_parameter["type"]["type"]
37
+ is_dpg_model = body_parameter["type"].get("base") == "dpg"
38
38
  body_parameter["type"] = {
39
39
  "type": "combined",
40
40
  "types": [body_parameter["type"], KNOWN_TYPES["binary"]],
41
41
  }
42
- if origin_type == "model" and models_mode == "dpg":
42
+ if origin_type == "model" and is_dpg_model:
43
43
  body_parameter["type"]["types"].insert(1, KNOWN_TYPES["any-object"])
44
44
  code_model["types"].append(body_parameter["type"])
45
45
 
@@ -257,7 +257,7 @@ class PreProcessPlugin(YamlUpdatePlugin): # pylint: disable=abstract-method
257
257
  response["discriminator"] = "operation"
258
258
  if body_parameter and not is_overload:
259
259
  # if we have a JSON body, we add a binary overload
260
- add_body_param_type(code_model, body_parameter, self.models_mode)
260
+ add_body_param_type(code_model, body_parameter)
261
261
  add_overloads_for_body_param(yaml_data)
262
262
 
263
263
  def _update_lro_operation_helper(self, yaml_data: Dict[str, Any]) -> None:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@autorest/python",
3
- "version": "6.2.11",
3
+ "version": "6.2.12",
4
4
  "description": "The Python extension for generators in AutoRest.",
5
5
  "repository": {
6
6
  "type": "git",