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 directive select to force selecting node #223

Open
wants to merge 1 commit 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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
14 changes: 14 additions & 0 deletions docs/features.rst
Expand Up @@ -194,6 +194,20 @@ The key content attributes are not supposed to be hard-coded in
the Flexible Metadata Format but freely configurable. Multiple key
content attributes (e.g. script & backend) could be used as well.

Select
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Sometimes it is necessary to select node from the metadata tree
even though it is not a leaf. For example, when virtual tests are
created from a parent test but one wants to keep the parent available
as a test as well. On the other hand, one might want to hide leaf node,
instead of deleting it completely. To do so, one can set fhe directive::

/:
select: boolean

By default all leaves have it set to ``true`` (such node is selected)
and branches have set it to ``false`` (such node is not selected).

.. _virtual:

Expand Down
20 changes: 15 additions & 5 deletions fmf/base.py
Expand Up @@ -249,10 +249,12 @@ def check(value, type_, name=None):
for key, value in directives.items():
if key == "inherit":
check(value, bool, name="inherit")
continue
# No other directive supported
raise fmf.utils.FormatError(
f"Unknown fmf directive '{key}' in '{self.name}'.")
elif key == "select":
check(value, bool, name="select")
else:
# No other directive supported
raise fmf.utils.FormatError(
f"Unknown fmf directive '{key}' in '{self.name}'.")

# Everything ok, store the directives
self._directives.update(directives)
Expand Down Expand Up @@ -571,12 +573,20 @@ def grow(self, path):

def climb(self, whole=False):
""" Climb through the tree (iterate leaf/all nodes) """
if whole or not self.children:
if whole or self.select:
yield self
for name, child in self.children.items():
for node in child.climb(whole):
yield node

@property
def select(self):
""" Respect directive, otherwise by being leaf/branch node"""
try:
return self._directives["select"]
except KeyError:
return not self.children

def find(self, name):
""" Find node with given name """
for node in self.climb(whole=True):
Expand Down
1 change: 1 addition & 0 deletions tests/core/select/data/.fmf/version
@@ -0,0 +1 @@
1
Empty file.
2 changes: 2 additions & 0 deletions tests/core/select/data/foo/hidden.fmf
@@ -0,0 +1,2 @@
/:
select: false
3 changes: 3 additions & 0 deletions tests/core/select/data/foo/main.fmf
@@ -0,0 +1,3 @@
/:
select: true
test: echo
10 changes: 10 additions & 0 deletions tests/core/select/main.fmf
@@ -0,0 +1,10 @@
summary: Verify functionality of the `select` directive
description:
Sometimes the node should stay reported as a object
even though it has child nodes. Using this directive
allows it. Real life example is to keep "/test" available
after virtual tests "/test/virtual_foo" and "test/virtual_bar"
are created.

The opposite behavior, not selecting the node even though
it has no child nodes is also possible and tested.
15 changes: 15 additions & 0 deletions tests/core/select/test.sh
@@ -0,0 +1,15 @@
#!/bin/bash
. /usr/share/beakerlib/beakerlib.sh || exit 1

rlJournalStart
rlPhaseStartTest
rlRun "pushd data"

rlRun -s "fmf ls"
rlAssertGrep "^/foo$" $rlRun_LOG
rlAssertGrep "^/foo/child$" $rlRun_LOG
rlAssertNotGrep "^/foo/hidden$" $rlRun_LOG

rlRun "popd"
rlPhaseEnd
rlJournalEnd