Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add callback to limit which nodes are adjusted #282

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 33 additions & 5 deletions fmf/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,22 @@ def __call__(
pass


class ApplyRulesCallback(Protocol):
"""
A callback to decide if rules should be processed in Tree.adjust()

Function to be called for every node before ``additional_rules``
are processed. It is called with fmf tree as the parameter.
It should return ``True`` when additional_rules should be processed
or ``False`` when they should be ignored.
"""

def __call__(
self,
node: 'Tree') -> bool:
return True


class Tree:
""" Metadata Tree """

Expand Down Expand Up @@ -438,7 +454,8 @@ def update(self, data):

def adjust(self, context, key='adjust', undecided='skip',
case_sensitive=True, decision_callback=None,
additional_rules=None):
additional_rules=None,
additional_rules_callback: Optional[ApplyRulesCallback] = None):
"""
Adjust tree data based on provided context and rules

Expand All @@ -465,6 +482,11 @@ class describing the environment context. By default, the key
that should be applied after those from the node itself.
These additional rules are processed even when an applied
rule defined in the node has ``continue: false`` set.

Optional 'additional_rules_callback' callback could be set to
limit nodes for which 'additional_rules' are processed.
This callback is called current fmf node as an argument and should
return 'True' to process 'additional_rules' or 'False' to skip them.
"""

# Check context sanity
Expand Down Expand Up @@ -495,9 +517,8 @@ class describing the environment context. By default, the key

context.case_sensitive = case_sensitive

# 'continue' has to affect only its rule_set
for rule_set in rules, additional_rules:
# Check and apply each rule
def apply_rules(rule_set):
# 'continue' has to affect only its rule_set
for rule in rule_set:
# Rule must be a dictionary
if not isinstance(rule, dict):
Expand Down Expand Up @@ -550,12 +571,19 @@ class describing the environment context. By default, the key
"Invalid value for the 'undecided' parameter. Should "
"be 'skip' or 'raise', got '{}'.".format(undecided))

# Always process rules from 'key' (adjust)
apply_rules(rules)
# Additional rules might be skipped depending on the callback
if additional_rules_callback is None or additional_rules_callback(self):
apply_rules(additional_rules)

# Adjust all child nodes as well
for child in self.children.values():
child.adjust(context, key, undecided,
case_sensitive=case_sensitive,
decision_callback=decision_callback,
additional_rules=additional_rules)
additional_rules=additional_rules,
additional_rules_callback=additional_rules_callback)

def get(self, name=None, default=None):
"""
Expand Down
26 changes: 26 additions & 0 deletions tests/unit/test_adjust.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,32 @@ def test_adjusted_additional(self, mini, centos):
mini.adjust(centos, additional_rules={'enabled': True})
assert mini.get('enabled') is True

def test_additional_rules_callback(self, fedora):
""" Additional rules might be ignored """
data = """
/is_test:
test: echo
/is_plan:
execute:
how: tmt
"""
yaml = YAML(typ="safe")
tree = fmf.Tree(yaml.load(data))

def additional_rules_callback(tree_node):
return 'test' in tree_node.data
tree.adjust(
context=fedora,
additional_rules=[
{'test': 'magic'}
],
additional_rules_callback=additional_rules_callback
)
# 'is_test' node was adjusted
assert tree.find('/is_test').data == {'test': 'magic'}
# 'is_plan' node was not adjusted
assert tree.find('/is_plan').data == {'execute': {'how': 'tmt'}}

def test_adjusted_additional_after_continue(self, full, centos):
""" Additional rule is evaluated even if 'node' rule has continue:false """
full.adjust(centos,
Expand Down