@autorest/python 5.17.0 → 6.0.0-rc.1

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 (56) hide show
  1. package/ChangeLog.md +63 -1
  2. package/README.md +9 -0
  3. package/autorest/codegen/__init__.py +24 -30
  4. package/autorest/codegen/models/base_builder.py +17 -6
  5. package/autorest/codegen/models/base_type.py +6 -0
  6. package/autorest/codegen/models/client.py +9 -6
  7. package/autorest/codegen/models/code_model.py +20 -14
  8. package/autorest/codegen/models/dictionary_type.py +16 -1
  9. package/autorest/codegen/models/imports.py +57 -2
  10. package/autorest/codegen/models/list_type.py +16 -1
  11. package/autorest/codegen/models/lro_operation.py +4 -6
  12. package/autorest/codegen/models/lro_paging_operation.py +3 -9
  13. package/autorest/codegen/models/model_type.py +34 -16
  14. package/autorest/codegen/models/operation.py +47 -79
  15. package/autorest/codegen/models/operation_group.py +10 -9
  16. package/autorest/codegen/models/paging_operation.py +4 -6
  17. package/autorest/codegen/models/parameter.py +3 -7
  18. package/autorest/codegen/models/parameter_list.py +26 -35
  19. package/autorest/codegen/models/property.py +14 -0
  20. package/autorest/codegen/models/request_builder.py +32 -43
  21. package/autorest/codegen/serializers/__init__.py +12 -50
  22. package/autorest/codegen/serializers/builder_serializer.py +136 -49
  23. package/autorest/codegen/serializers/client_serializer.py +23 -32
  24. package/autorest/codegen/serializers/general_serializer.py +12 -12
  25. package/autorest/codegen/serializers/import_serializer.py +11 -22
  26. package/autorest/codegen/serializers/metadata_serializer.py +0 -2
  27. package/autorest/codegen/serializers/{model_base_serializer.py → model_serializer.py} +58 -44
  28. package/autorest/codegen/serializers/operation_groups_serializer.py +3 -7
  29. package/autorest/codegen/serializers/operations_init_serializer.py +2 -23
  30. package/autorest/codegen/serializers/patch_serializer.py +1 -3
  31. package/autorest/codegen/serializers/request_builders_serializer.py +2 -5
  32. package/autorest/codegen/serializers/utils.py +3 -4
  33. package/autorest/codegen/templates/client.py.jinja2 +6 -3
  34. package/autorest/codegen/templates/config.py.jinja2 +2 -2
  35. package/autorest/codegen/templates/metadata.json.jinja2 +4 -4
  36. package/autorest/codegen/templates/model.py.jinja2 +1 -1
  37. package/autorest/codegen/templates/model_init.py.jinja2 +5 -12
  38. package/autorest/codegen/templates/operation_group.py.jinja2 +16 -3
  39. package/autorest/codegen/templates/operation_groups_container.py.jinja2 +2 -8
  40. package/autorest/codegen/templates/operation_tools.jinja2 +3 -1
  41. package/autorest/codegen/templates/patch.py.jinja2 +1 -2
  42. package/autorest/codegen/templates/request_builder.py.jinja2 +0 -7
  43. package/autorest/codegen/templates/request_builders.py.jinja2 +1 -4
  44. package/autorest/codegen/templates/rest_init.py.jinja2 +3 -8
  45. package/autorest/codegen/templates/serialization.py.jinja2 +2006 -0
  46. package/autorest/codegen/templates/setup.py.jinja2 +4 -0
  47. package/autorest/codegen/templates/vendor.py.jinja2 +10 -0
  48. package/autorest/m4reformatter/__init__.py +82 -58
  49. package/autorest/multiapi/models/client.py +12 -2
  50. package/autorest/multiapi/serializers/__init__.py +17 -8
  51. package/autorest/multiapi/serializers/import_serializer.py +4 -8
  52. package/autorest/multiapi/templates/multiapi_operations_mixin.py.jinja2 +1 -1
  53. package/autorest/preprocess/__init__.py +1 -0
  54. package/package.json +2 -2
  55. package/autorest/codegen/serializers/model_generic_serializer.py +0 -32
  56. package/autorest/codegen/serializers/model_python3_serializer.py +0 -72
@@ -82,7 +82,11 @@ setup(
82
82
  include_package_data=True,
83
83
  {% endif %}
84
84
  install_requires=[
85
+ {% if code_model.is_legacy %}
85
86
  "{{ dependency_msrest }}",
87
+ {% else %}
88
+ "isodate>=0.6.1",
89
+ {% endif %}
86
90
  {% if azure_arm %}
87
91
  "{{ dependency_azure_mgmt_core }}",
88
92
  {% else %}
@@ -34,3 +34,13 @@ class MixinABC(ABC):
34
34
  _serialize: "Serializer"
35
35
  _deserialize: "Deserializer"
36
36
  {% endif %}
37
+ {% if code_model.has_abstract_operations %}
38
+
39
+ def raise_if_not_implemented(cls, abstract_methods):
40
+ not_implemented = [f for f in abstract_methods if not callable(getattr(cls, f, None))]
41
+ if not_implemented:
42
+ raise NotImplementedError("The following methods on operation group '{}' are not implemented: '{}'."
43
+ " Please refer to https://aka.ms/azsdk/python/dpcodegen/python/customize to learn how to customize.".format(
44
+ cls.__name__, '\', \''.join(not_implemented))
45
+ )
46
+ {% endif %}
@@ -134,7 +134,7 @@ def update_property(
134
134
 
135
135
  def update_discriminated_subtypes(yaml_data: Dict[str, Any]) -> Dict[str, Any]:
136
136
  return {
137
- obj["discriminatorValue"]: obj["language"]["default"]["name"]
137
+ obj["discriminatorValue"]: update_type(obj)
138
138
  for obj in yaml_data.get("discriminator", {}).get("immediate", {}).values()
139
139
  }
140
140
 
@@ -431,39 +431,6 @@ def update_client_url(yaml_data: Dict[str, Any]) -> str:
431
431
  ]["uri"]
432
432
 
433
433
 
434
- def update_content_type_parameter(
435
- yaml_data: Dict[str, Any],
436
- body_parameter: Optional[Dict[str, Any]],
437
- request_media_types: List[str],
438
- *,
439
- in_overload: bool = False,
440
- in_overriden: bool = False,
441
- ) -> Dict[str, Any]:
442
- # override content type type to string
443
- if not body_parameter:
444
- return yaml_data
445
- param = copy.deepcopy(yaml_data)
446
- param["schema"] = KNOWN_TYPES["string"] # override to string type
447
- param["required"] = False
448
- description = param["language"]["default"]["description"]
449
- if description and description[-1] != ".":
450
- description += "."
451
- if not (in_overriden or in_overload):
452
- param["inDocstring"] = False
453
- elif in_overload:
454
- description += (
455
- " Content type parameter for "
456
- f"{get_body_type_for_description(body_parameter)} body."
457
- )
458
- elif not in_overload:
459
- content_types = "'" + "', '".join(request_media_types) + "'"
460
- description += f" Known values are: {content_types}."
461
- if not in_overload and not in_overriden:
462
- param["clientDefaultValue"] = body_parameter["defaultContentType"]
463
- param["language"]["default"]["description"] = description
464
- return param
465
-
466
-
467
434
  class M4Reformatter(YamlUpdatePlugin): # pylint: disable=too-many-public-methods
468
435
  """Add Python naming information."""
469
436
 
@@ -471,11 +438,23 @@ class M4Reformatter(YamlUpdatePlugin): # pylint: disable=too-many-public-method
471
438
  def azure_arm(self) -> bool:
472
439
  return bool(self._autorestapi.get_boolean_value("azure-arm"))
473
440
 
441
+ @property
442
+ def version_tolerant(self) -> bool:
443
+ return bool(self._autorestapi.get_boolean_value("version-tolerant"))
444
+
445
+ @property
446
+ def low_level_client(self) -> bool:
447
+ return bool(self._autorestapi.get_boolean_value("low-level-client"))
448
+
449
+ @property
450
+ def legacy(self) -> bool:
451
+ return not (self.version_tolerant or self.low_level_client)
452
+
474
453
  @property
475
454
  def default_optional_constants_to_none(self) -> bool:
476
455
  return bool(
477
456
  self._autorestapi.get_boolean_value("default-optional-constants-to-none")
478
- or self._autorestapi.get_boolean_value("version-tolerant")
457
+ or self.version_tolerant
479
458
  )
480
459
 
481
460
  def update_overloads(
@@ -515,6 +494,13 @@ class M4Reformatter(YamlUpdatePlugin): # pylint: disable=too-many-public-method
515
494
  in_overriden = (
516
495
  body_parameter["type"]["type"] == "combined" if body_parameter else False
517
496
  )
497
+ abstract = False
498
+ if body_parameter and (
499
+ body_parameter.get("entries")
500
+ or len(body_parameter["type"].get("types", [])) > 2
501
+ ):
502
+ # this means it's formdata or urlencoded, or there are more than 2 types of body
503
+ abstract = True
518
504
  return {
519
505
  "name": yaml_data["language"]["default"]["name"],
520
506
  "description": yaml_data["language"]["default"]["description"],
@@ -541,6 +527,7 @@ class M4Reformatter(YamlUpdatePlugin): # pylint: disable=too-many-public-method
541
527
  "discriminator": "operation",
542
528
  "isOverload": is_overload,
543
529
  "apiVersions": _get_api_versions(yaml_data.get("apiVersions", [])),
530
+ "abstract": abstract,
544
531
  }
545
532
 
546
533
  def get_operation_creator(
@@ -689,6 +676,9 @@ class M4Reformatter(YamlUpdatePlugin): # pylint: disable=too-many-public-method
689
676
  body_param["defaultContentType"] = _get_default_content_type(
690
677
  body_param["contentTypes"]
691
678
  )
679
+ # python supports IO input with all kinds of content_types
680
+ if body_type["type"] == "binary":
681
+ body_param["contentTypes"] = content_types or list(yaml_data.keys())
692
682
  if body_param["type"]["type"] == "constant":
693
683
  if not body_param["optional"] or (
694
684
  body_param["optional"] and not self.default_optional_constants_to_none
@@ -771,11 +761,53 @@ class M4Reformatter(YamlUpdatePlugin): # pylint: disable=too-many-public-method
771
761
  param["inFlattenedBody"] = True
772
762
  return param
773
763
 
764
+ def _update_content_type_parameter(
765
+ self,
766
+ yaml_data: Dict[str, Any],
767
+ body_parameter: Optional[Dict[str, Any]],
768
+ request_media_types: List[str],
769
+ *,
770
+ in_overload: bool = False,
771
+ in_overriden: bool = False,
772
+ ) -> Dict[str, Any]:
773
+ # override content type type to string
774
+ if not body_parameter:
775
+ return yaml_data
776
+ param = copy.deepcopy(yaml_data)
777
+ param["schema"] = KNOWN_TYPES["string"] # override to string type
778
+ if (
779
+ body_parameter["type"]["type"] == "binary"
780
+ and not body_parameter["defaultContentType"]
781
+ and not self.legacy
782
+ ):
783
+ param["required"] = True
784
+ else:
785
+ param["required"] = False
786
+ description = param["language"]["default"]["description"]
787
+ if description and description[-1] != ".":
788
+ description += "."
789
+ if not (in_overriden or in_overload):
790
+ param["inDocstring"] = False
791
+ elif in_overload:
792
+ description += (
793
+ " Content type parameter for "
794
+ f"{get_body_type_for_description(body_parameter)} body."
795
+ )
796
+ if not in_overload or (
797
+ body_parameter["type"]["type"] == "binary" and len(request_media_types) > 1
798
+ ):
799
+ content_types = "'" + "', '".join(request_media_types) + "'"
800
+ description += f" Known values are: {content_types}."
801
+ if not in_overload and not in_overriden:
802
+ param["clientDefaultValue"] = body_parameter["defaultContentType"]
803
+ param["language"]["default"]["description"] = description
804
+ return param
805
+
774
806
  def _update_parameters_helper(
775
807
  self,
776
808
  parameters: List[Dict[str, Any]],
777
809
  body_parameter: Optional[Dict[str, Any]],
778
- seen_rest_api_names: Set[str],
810
+ seen_client_names: Set[str],
779
811
  groupers: Dict[str, Dict[str, Any]],
780
812
  request_media_types: List[str],
781
813
  *,
@@ -785,15 +817,17 @@ class M4Reformatter(YamlUpdatePlugin): # pylint: disable=too-many-public-method
785
817
  retval: List[Dict[str, Any]] = []
786
818
  has_flattened_body = body_parameter and body_parameter.get("flattened")
787
819
  for param in parameters:
788
- serialized_name = param["language"]["default"].get("serializedName")
820
+ client_name = param["language"]["default"]["name"]
789
821
  if param["language"]["default"]["name"] == "$host" or (
790
- serialized_name and serialized_name in seen_rest_api_names
822
+ client_name in seen_client_names
791
823
  ):
792
824
  continue
825
+ seen_client_names.add(client_name)
793
826
  if param.get("origin") == "modelerfour:synthesized/api-version":
794
827
  param["inDocstring"] = False
795
- param["implementation"] = "Method"
796
- param["checkClientInput"] = True
828
+ if self.legacy:
829
+ param["implementation"] = "Method"
830
+ param["checkClientInput"] = True
797
831
  if has_flattened_body and param.get("targetProperty"):
798
832
  retval.append(self.update_flattened_parameter(param, body_parameter))
799
833
  continue
@@ -806,8 +840,8 @@ class M4Reformatter(YamlUpdatePlugin): # pylint: disable=too-many-public-method
806
840
  continue
807
841
  if is_body(param):
808
842
  continue
809
- if serialized_name == "Content-Type":
810
- param = update_content_type_parameter(
843
+ if param["language"]["default"].get("serializedName") == "Content-Type":
844
+ param = self._update_content_type_parameter(
811
845
  param,
812
846
  body_parameter,
813
847
  request_media_types,
@@ -818,7 +852,6 @@ class M4Reformatter(YamlUpdatePlugin): # pylint: disable=too-many-public-method
818
852
  param, in_overload=in_overload, in_overriden=in_overriden
819
853
  )
820
854
  retval.append(updated_param)
821
- seen_rest_api_names.add(updated_param["restApiName"])
822
855
  return retval
823
856
 
824
857
  def update_parameters(
@@ -830,7 +863,7 @@ class M4Reformatter(YamlUpdatePlugin): # pylint: disable=too-many-public-method
830
863
  in_overriden: bool = False,
831
864
  ) -> List[Dict[str, Any]]:
832
865
  retval: List[Dict[str, Any]] = []
833
- seen_rest_api_names: Set[str] = set()
866
+ seen_client_names: Set[str] = set()
834
867
  groupers: Dict[str, Dict[str, Any]] = {}
835
868
  # first update top level parameters
836
869
  request_media_types = yaml_data.get("requestMediaTypes", [])
@@ -838,7 +871,7 @@ class M4Reformatter(YamlUpdatePlugin): # pylint: disable=too-many-public-method
838
871
  self._update_parameters_helper(
839
872
  yaml_data["parameters"],
840
873
  body_parameter,
841
- seen_rest_api_names,
874
+ seen_client_names,
842
875
  groupers,
843
876
  request_media_types,
844
877
  in_overload=in_overload,
@@ -857,7 +890,7 @@ class M4Reformatter(YamlUpdatePlugin): # pylint: disable=too-many-public-method
857
890
  self._update_parameters_helper(
858
891
  request.get("parameters", []),
859
892
  body_parameter,
860
- seen_rest_api_names,
893
+ seen_client_names,
861
894
  groupers,
862
895
  request_media_types,
863
896
  in_overload=in_overload,
@@ -921,15 +954,8 @@ class M4Reformatter(YamlUpdatePlugin): # pylint: disable=too-many-public-method
921
954
  name = global_parameter["language"]["default"]["name"]
922
955
  if name == "$host":
923
956
  # I am the non-parameterized endpoint. Modify name based off of flag
924
- version_tolerant = self._autorestapi.get_boolean_value(
925
- "version-tolerant", False
926
- )
927
- low_level_client = self._autorestapi.get_boolean_value(
928
- "low-level-client", False
929
- )
930
- client_name = (
931
- "endpoint" if (version_tolerant or low_level_client) else "base_url"
932
- )
957
+
958
+ client_name = "base_url" if self.legacy else "endpoint"
933
959
  global_parameter["language"]["default"]["description"] = "Service URL."
934
960
  global_params.append(
935
961
  self.update_parameter(
@@ -1054,9 +1080,7 @@ class M4Reformatter(YamlUpdatePlugin): # pylint: disable=too-many-public-method
1054
1080
  "skipUrlEncoding": True,
1055
1081
  "inOverload": False,
1056
1082
  }
1057
- if self._autorestapi.get_boolean_value(
1058
- "version-tolerant"
1059
- ) or self._autorestapi.get_boolean_value("low-level-client"):
1083
+ if self.version_tolerant or self.low_level_client:
1060
1084
  parameters.append(credential)
1061
1085
  else:
1062
1086
  parameters.insert(0, credential)
@@ -5,9 +5,10 @@
5
5
  # --------------------------------------------------------------------------
6
6
  import sys
7
7
  import json
8
+ import re
8
9
  from typing import Any, Dict, List
9
10
  from pathlib import Path
10
- from .imports import FileImport
11
+ from .imports import FileImport, TypingSection, ImportType
11
12
 
12
13
 
13
14
  def _extract_version(metadata_json: Dict[str, Any], version_path: Path) -> str:
@@ -43,9 +44,18 @@ class Client:
43
44
 
44
45
  def imports(self, async_mode: bool) -> FileImport:
45
46
  imports_to_load = "async_imports" if async_mode else "sync_imports"
46
- return FileImport(
47
+ file_import = FileImport(
47
48
  json.loads(self.default_version_metadata["client"][imports_to_load])
48
49
  )
50
+ local_imports = file_import.imports.get(TypingSection.REGULAR, {}).get(
51
+ ImportType.LOCAL, {}
52
+ )
53
+ for key in local_imports:
54
+ if re.search("^\\.*_serialization$", key):
55
+ relative_path = ".." if async_mode else "."
56
+ local_imports[f"{relative_path}_serialization"] = local_imports.pop(key)
57
+ break
58
+ return file_import
49
59
 
50
60
  @property
51
61
  def parameterized_host_template_to_api_version(self) -> Dict[str, List[str]]:
@@ -57,18 +57,14 @@ class MultiAPISerializer(object):
57
57
  )
58
58
 
59
59
  # serialize service client file
60
- imports = FileImportSerializer(
61
- code_model.client.imports(async_mode), is_python3_file=async_mode
62
- )
60
+ imports = FileImportSerializer(code_model.client.imports(async_mode))
63
61
  self._autorestapi.write_file(
64
62
  _get_file_path(code_model.client.filename, async_mode),
65
63
  _render_template("client", imports=imports),
66
64
  )
67
65
 
68
66
  # serialize config file
69
- imports = FileImportSerializer(
70
- code_model.config.imports(async_mode), is_python3_file=async_mode
71
- )
67
+ imports = FileImportSerializer(code_model.config.imports(async_mode))
72
68
  self._autorestapi.write_file(
73
69
  _get_file_path("_configuration", async_mode),
74
70
  _render_template("config", imports=imports),
@@ -77,8 +73,7 @@ class MultiAPISerializer(object):
77
73
  # serialize mixins
78
74
  if code_model.operation_mixin_group.mixin_operations:
79
75
  imports = FileImportSerializer(
80
- code_model.operation_mixin_group.imports(async_mode),
81
- is_python3_file=async_mode,
76
+ code_model.operation_mixin_group.imports(async_mode)
82
77
  )
83
78
  self._autorestapi.write_file(
84
79
  _get_file_path("_operations_mixin", async_mode),
@@ -115,3 +110,17 @@ class MultiAPISerializer(object):
115
110
  )
116
111
 
117
112
  self._autorestapi.write_file(Path("py.typed"), "# Marker file for PEP 561.")
113
+
114
+ if not code_model.client.client_side_validation:
115
+ codegen_env = Environment(
116
+ loader=PackageLoader("autorest.codegen", "templates"),
117
+ keep_trailing_newline=True,
118
+ line_statement_prefix="##",
119
+ line_comment_prefix="###",
120
+ trim_blocks=True,
121
+ lstrip_blocks=True,
122
+ )
123
+ self._autorestapi.write_file(
124
+ Path("_serialization.py"),
125
+ codegen_env.get_template("serialization.py.jinja2").render(),
126
+ )
@@ -54,9 +54,8 @@ def _get_import_clauses(
54
54
 
55
55
 
56
56
  class FileImportSerializer:
57
- def __init__(self, file_import: FileImport, is_python3_file: bool) -> None:
57
+ def __init__(self, file_import: FileImport) -> None:
58
58
  self._file_import = file_import
59
- self.is_python3_file = is_python3_file
60
59
 
61
60
  def _switch_typing_section_key(self, new_key: TypingSection):
62
61
  switched_dictionary = {}
@@ -84,10 +83,7 @@ class FileImportSerializer:
84
83
  return file_import_copy.imports.get(baseline_typing_section, {})
85
84
 
86
85
  def _add_type_checking_import(self):
87
- if self._file_import.imports.get(TypingSection.TYPING) or (
88
- not self.is_python3_file
89
- and self._file_import.imports.get(TypingSection.CONDITIONAL)
90
- ):
86
+ if self._file_import.imports.get(TypingSection.TYPING):
91
87
  self._file_import.add_submodule_import(
92
88
  "typing", "TYPE_CHECKING", ImportType.STDLIB
93
89
  )
@@ -97,7 +93,7 @@ class FileImportSerializer:
97
93
  regular_imports = ""
98
94
  regular_imports_dict = self._get_imports_dict(
99
95
  baseline_typing_section=TypingSection.REGULAR,
100
- add_conditional_typing=self.is_python3_file,
96
+ add_conditional_typing=True,
101
97
  )
102
98
 
103
99
  if regular_imports_dict:
@@ -108,7 +104,7 @@ class FileImportSerializer:
108
104
  typing_imports = ""
109
105
  typing_imports_dict = self._get_imports_dict(
110
106
  baseline_typing_section=TypingSection.TYPING,
111
- add_conditional_typing=not self.is_python3_file,
107
+ add_conditional_typing=False,
112
108
  )
113
109
  if typing_imports_dict:
114
110
  typing_imports += "\n\nif TYPE_CHECKING:\n # pylint: disable=unused-import,ungrouped-imports\n "
@@ -8,7 +8,7 @@
8
8
  # Changes may cause incorrect behavior and will be lost if the code is
9
9
  # regenerated.
10
10
  # --------------------------------------------------------------------------
11
- from msrest import Serializer, Deserializer
11
+ from {{ ".." if async_mode else "." }}_serialization import Serializer, Deserializer
12
12
  {% if imports %}
13
13
  {{ imports }}
14
14
  {% endif %}
@@ -62,6 +62,7 @@ def update_types(yaml_data: List[Dict[str, Any]]) -> None:
62
62
  add_redefined_builtin_info(property["clientName"], property)
63
63
  if type.get("name"):
64
64
  type["description"] = update_description(type["description"], type["name"])
65
+ type["snakeCaseName"] = to_snake_case(type["name"])
65
66
 
66
67
 
67
68
  def update_client(yaml_data: Dict[str, Any]) -> None:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@autorest/python",
3
- "version": "5.17.0",
3
+ "version": "6.0.0-rc.1",
4
4
  "description": "The Python extension for generators in AutoRest.",
5
5
  "scripts": {
6
6
  "prepare": "node run-python3.js prepare.py",
@@ -27,7 +27,7 @@
27
27
  "@autorest/system-requirements": "~1.0.0"
28
28
  },
29
29
  "devDependencies": {
30
- "@microsoft.azure/autorest.testserver": "^3.3.26"
30
+ "@microsoft.azure/autorest.testserver": "^3.3.29"
31
31
  },
32
32
  "files": [
33
33
  "autorest/**/*.py",
@@ -1,32 +0,0 @@
1
- # -------------------------------------------------------------------------
2
- # Copyright (c) Microsoft Corporation. All rights reserved.
3
- # Licensed under the MIT License. See License.txt in the project root for
4
- # license information.
5
- # --------------------------------------------------------------------------
6
- from typing import List
7
- from jinja2 import Environment
8
- from .model_base_serializer import ModelBaseSerializer
9
- from ..models import ModelType, CodeModel, Property
10
-
11
-
12
- class ModelGenericSerializer(ModelBaseSerializer):
13
- def __init__(self, code_model: CodeModel, env: Environment) -> None:
14
- super().__init__(code_model=code_model, env=env, is_python3_file=False)
15
-
16
- def init_line(self, model: ModelType) -> List[str]:
17
- return []
18
-
19
- def properties_to_pass_to_super(self, model: ModelType) -> str:
20
- return "**kwargs"
21
-
22
- def required_property_no_default_init(self, prop: Property) -> str:
23
- return f"self.{prop.client_name} = kwargs['{prop.client_name}']"
24
-
25
- def optional_property_init(self, prop: Property) -> str:
26
- return f"self.{prop.client_name} = kwargs.get('{prop.client_name}', {prop.client_default_value_declaration})"
27
-
28
- def initialize_standard_arg(self, prop: Property) -> str:
29
- return self.initialize_standard_property(prop)
30
-
31
- def super_call_template(self, model: ModelType) -> str:
32
- return "super(" + model.name + ", self).__init__({})"
@@ -1,72 +0,0 @@
1
- # -------------------------------------------------------------------------
2
- # Copyright (c) Microsoft Corporation. All rights reserved.
3
- # Licensed under the MIT License. See License.txt in the project root for
4
- # license information.
5
- # --------------------------------------------------------------------------
6
- from typing import List
7
- from jinja2 import Environment
8
- from .model_base_serializer import ModelBaseSerializer
9
- from ..models import ModelType, CodeModel, Property
10
- from ..models.imports import FileImport
11
-
12
-
13
- class ModelPython3Serializer(ModelBaseSerializer):
14
- def __init__(self, code_model: CodeModel, env: Environment) -> None:
15
- super().__init__(code_model=code_model, env=env, is_python3_file=True)
16
-
17
- def init_line(self, model: ModelType) -> List[str]:
18
- init_properties_declaration = []
19
- init_line_parameters = [
20
- p
21
- for p in model.properties
22
- if not p.readonly and not p.is_discriminator and not p.constant
23
- ]
24
- init_line_parameters.sort(key=lambda x: x.optional)
25
- if init_line_parameters:
26
- init_properties_declaration.append("*,")
27
- for param in init_line_parameters:
28
- init_properties_declaration.append(self.initialize_standard_property(param))
29
-
30
- return init_properties_declaration
31
-
32
- def properties_to_pass_to_super(self, model: ModelType) -> str:
33
- properties_to_pass_to_super = []
34
- for parent in model.parents:
35
- for prop in model.properties:
36
- if (
37
- prop in parent.properties
38
- and not prop.is_discriminator
39
- and not prop.constant
40
- and not prop.readonly
41
- ):
42
- properties_to_pass_to_super.append(
43
- f"{prop.client_name}={prop.client_name}"
44
- )
45
- properties_to_pass_to_super.append("**kwargs")
46
- return ", ".join(properties_to_pass_to_super)
47
-
48
- def required_property_no_default_init(self, prop: Property) -> str:
49
- return f"{prop.client_name}: {prop.type_annotation()},{prop.pylint_disable}"
50
-
51
- def optional_property_init(self, prop: Property) -> str:
52
- return (
53
- f"{prop.client_name}: {prop.type_annotation()} = "
54
- f"{prop.client_default_value_declaration},{prop.pylint_disable}"
55
- )
56
-
57
- def initialize_standard_arg(self, prop: Property) -> str:
58
- return f"self.{prop.client_name} = {prop.client_name}"
59
-
60
- def super_call_template(self, model: ModelType) -> str:
61
- return "super().__init__({})"
62
-
63
- def imports(self) -> FileImport:
64
- file_import = super(ModelPython3Serializer, self).imports()
65
- for model in self.code_model.model_types:
66
- init_line_parameters = [
67
- p for p in model.properties if not p.readonly and not p.is_discriminator
68
- ]
69
- for param in init_line_parameters:
70
- file_import.merge(param.imports())
71
-
72
- return file_import