1
1
"""Transformer implementation."""
2
2
import logging
3
- from typing import Dict , List , Set , Union
3
+ from typing import Dict , List , Optional , Set , Union
4
4
5
5
from ruamel .yaml .comments import CommentedMap , CommentedSeq
6
6
7
7
from ansiblelint .errors import MatchError
8
8
from ansiblelint .file_utils import Lintable
9
+ from ansiblelint .rules import TransformMixin
9
10
from ansiblelint .runner import LintResult
10
11
from ansiblelint .yaml_utils import FormattedYAML
11
12
@@ -50,7 +51,7 @@ def __init__(self, result: LintResult):
50
51
51
52
def run (self ) -> None :
52
53
"""For each file, read it, execute transforms on it, then write it."""
53
- for file , _ in self .matches_per_file .items ():
54
+ for file , matches in self .matches_per_file .items ():
54
55
# str() convinces mypy that "text/yaml" is a valid Literal.
55
56
# Otherwise, it thinks base_kind is one of playbook, meta, tasks, ...
56
57
file_is_yaml = str (file .base_kind ) == "text/yaml"
@@ -62,17 +63,37 @@ def run(self) -> None:
62
63
data = ""
63
64
file_is_yaml = False
64
65
66
+ ruamel_data : Optional [Union [CommentedMap , CommentedSeq ]] = None
65
67
if file_is_yaml :
66
68
# We need a fresh YAML() instance for each load because ruamel.yaml
67
69
# stores intermediate state during load which could affect loading
68
70
# any other files. (Based on suggestion from ruamel.yaml author)
69
71
yaml = FormattedYAML ()
70
72
71
- ruamel_data : Union [ CommentedMap , CommentedSeq ] = yaml .loads (data )
73
+ ruamel_data = yaml .loads (data )
72
74
if not isinstance (ruamel_data , (CommentedMap , CommentedSeq )):
73
75
# This is an empty vars file or similar which loads as None.
74
76
# It is not safe to write this file or data-loss is likely.
75
77
# Only maps and sequences can preserve comments. Skip it.
76
78
continue
79
+
80
+ self ._do_transforms (file , ruamel_data or data , matches )
81
+
82
+ if file_is_yaml :
83
+ # noinspection PyUnboundLocalVariable
77
84
file .content = yaml .dumps (ruamel_data )
85
+
86
+ if file .updated :
78
87
file .write ()
88
+
89
+ @staticmethod
90
+ def _do_transforms (
91
+ file : Lintable ,
92
+ data : Union [CommentedMap , CommentedSeq , str ],
93
+ matches : List [MatchError ],
94
+ ) -> None :
95
+ """Do Rule-Transforms handling any last-minute MatchError inspections."""
96
+ for match in sorted (matches ):
97
+ if not isinstance (match .rule , TransformMixin ):
98
+ continue
99
+ match .rule .transform (match , file , data )
0 commit comments