4444
4545_logger = logging .getLogger (__name__ )
4646
47+
4748YAMLLINT_CONFIG = """
4849extends: default
4950rules:
@@ -750,13 +751,14 @@ def write_version_directive(self, version_text: Any) -> None:
750751class FormattedYAML (YAML ):
751752 """A YAML loader/dumper that handles ansible content better by default."""
752753
753- def __init__ (
754+ def __init__ ( # pylint: disable=too-many-arguments
754755 self ,
755756 * ,
756757 typ : str | None = None ,
757758 pure : bool = False ,
758759 output : Any = None ,
759760 plug_ins : list [str ] | None = None ,
761+ version : VersionType | None = None ,
760762 ):
761763 """Return a configured ``ruamel.yaml.YAML`` instance.
762764
@@ -817,8 +819,11 @@ def __init__(
817819 - name: Task
818820 """
819821 # Default to reading/dumping YAML 1.1 (ruamel.yaml defaults to 1.2)
820- self ._yaml_version_default : tuple [int , int ] = (1 , 1 )
821- self ._yaml_version : str | tuple [int , int ] = self ._yaml_version_default
822+ if version :
823+ if isinstance (version , str ):
824+ version = tuple (version .split ("." ))
825+ self ._yaml_version_default : VersionType = version
826+ self ._yaml_version : VersionType = self ._yaml_version_default
822827
823828 super ().__init__ (typ = typ , pure = pure , output = output , plug_ins = plug_ins )
824829
@@ -874,6 +879,9 @@ def __init__(
874879 # (see https://stackoverflow.com/a/44314840/1134951)
875880 # self.Representer.add_representer(
876881
882+ if version :
883+ self .version = version
884+
877885 @staticmethod
878886 def _defaults_from_yamllint_config () -> dict [str , bool | int | str ]:
879887 """Extract FormattedYAML-relevant settings from yamllint config if possible."""
@@ -920,16 +928,18 @@ def _defaults_from_yamllint_config() -> dict[str, bool | int | str]:
920928
921929 return cast (dict [str , Union [bool , int , str ]], config )
922930
923- @property # type: ignore[override]
924- def version (self ) -> str | tuple [ int , int ] :
931+ @property
932+ def version (self ) -> VersionType | None :
925933 """Return the YAML version used to parse or dump.
926934
927935 Ansible uses PyYAML which only supports YAML 1.1. ruamel.yaml defaults to 1.2.
928936 So, we have to make sure we dump yaml files using YAML 1.1.
929937 We can relax the version requirement once ansible uses a version of PyYAML
930938 that includes this PR: https://github.com/yaml/pyyaml/pull/555
931939 """
932- return self ._yaml_version
940+ if hasattr (self , "_yaml_version" ):
941+ return self ._yaml_version
942+ return None
933943
934944 @version .setter
935945 def version (self , value : str | tuple [int , int ] | None ) -> None :
@@ -939,7 +949,11 @@ def version(self, value: str | tuple[int, int] | None) -> None:
939949 So, if a file does not include the directive, it sets this to None.
940950 But, None effectively resets the parsing version to YAML 1.2 (ruamel's default).
941951 """
942- self ._yaml_version = value if value is not None else self ._yaml_version_default
952+ if value is not None :
953+ self ._yaml_version = value
954+ elif hasattr (self , "_yaml_version_default" ):
955+ self ._yaml_version = self ._yaml_version_default
956+ # We do nothing if the object did not had a previous default version defined
943957
944958 def load (self , stream : Path | StreamTextType ) -> Any :
945959 """Load YAML content from a string while avoiding known ruamel.yaml issues."""
@@ -958,6 +972,9 @@ def load(self, stream: Path | StreamTextType) -> Any:
958972 except ParserError :
959973 data = None
960974 _logger .error ("Invalid yaml, verify the file contents and try again." )
975+ except Exception as exc :
976+ breakpoint ()
977+ raise exc
961978 if preamble_comment is not None and isinstance (
962979 data ,
963980 (CommentedMap , CommentedSeq ),
@@ -977,7 +994,11 @@ def dumps(self, data: Any) -> str:
977994 stream .write (preamble_comment )
978995 self .dump (data , stream )
979996 text = stream .getvalue ()
980- return self ._post_process_yaml (text )
997+ strip_version_directive = hasattr (self , "_yaml_version_default" )
998+ return self ._post_process_yaml (
999+ text ,
1000+ strip_version_directive = strip_version_directive ,
1001+ )
9811002
9821003 def _prevent_wrapping_flow_style (self , data : Any ) -> None :
9831004 if not isinstance (data , (CommentedMap , CommentedSeq )):
@@ -1065,7 +1086,7 @@ def _pre_process_yaml(self, text: str) -> tuple[str, str | None]:
10651086 return text , "" .join (preamble_comments ) or None
10661087
10671088 @staticmethod
1068- def _post_process_yaml (text : str ) -> str :
1089+ def _post_process_yaml (text : str , * , strip_version_directive : bool = False ) -> str :
10691090 """Handle known issues with ruamel.yaml dumping.
10701091
10711092 Make sure there's only one newline at the end of the file.
@@ -1077,6 +1098,10 @@ def _post_process_yaml(text: str) -> str:
10771098
10781099 Make sure null list items don't end in a space.
10791100 """
1101+ # remove YAML directive
1102+ if strip_version_directive and text .startswith ("%YAML" ):
1103+ text = text .split ("\n " , 1 )[1 ]
1104+
10801105 text = text .rstrip ("\n " ) + "\n "
10811106
10821107 lines = text .splitlines (keepends = True )
0 commit comments