提交 e1fe14f2 编写于 作者: L Lukáš Doktor

avocado.core.tree: Support for including files from yaml

This patch defines "!include" tag for inserting other files from within
the yaml file.

Keep in mind that it's necessarily to separate the ':' from the tag,
otherwise yaml thinks it's a different tag.
Signed-off-by: NLukáš Doktor <ldoktor@redhat.com>
上级 66823a25
......@@ -34,6 +34,7 @@ original base tree code and re-license under GPLv2+, given that GPLv3 and GPLv2
"""
import collections
import os
import yaml
......@@ -44,6 +45,10 @@ except ImportError:
from yaml import Loader
# Mapping for yaml flags
YAML_INCLUDE = 0
class TreeNode(object):
"""
......@@ -294,18 +299,43 @@ class Value(tuple): # Few methods pylint: disable=R0903
pass
class Control(object): # Few methods pylint: disable=R0903
""" Container used to identify node vs. control sequence """
def __init__(self, ctr_type):
self.ctr_type = ctr_type
def __eq__(self, other):
if isinstance(other, Control):
return self.ctr_type == other.ctr_type
else:
return self.ctr_type == other
def __req__(self, other):
return self == other
def __str__(self):
return self.ctr_type
def _create_from_yaml(path, cls_node=TreeNode):
""" Create tree structure from yaml stream """
def tree_node_from_values(name, values):
""" Create `name` node and add values """
node_children = []
node_values = []
node = cls_node(str(name))
for value in values:
if isinstance(value, TreeNode):
node_children.append(value)
node.add_child(value)
elif isinstance(value[0], Control):
# Include file
ypath = value[1]
if not os.path.isabs(ypath):
ypath = os.path.join(os.path.dirname(path), ypath)
node.merge(_create_from_yaml(ypath, cls_node))
else:
node_values.append(value)
return cls_node(name, dict(node_values), children=node_children)
node.value[value[0]] = value[1]
return node
def mapping_to_tree_loader(loader, node):
""" Maps yaml mapping tag to TreeNode structure """
......@@ -323,10 +353,13 @@ def _create_from_yaml(path, cls_node=TreeNode):
if is_node(values): # New node
objects.append(tree_node_from_values(name, values))
elif values is None: # Empty node
objects.append(cls_node(name))
objects.append(cls_node(str(name)))
else: # Values
objects.append(Value((name, values)))
return objects
Loader.add_constructor(u'!include',
lambda loader, node: Control(YAML_INCLUDE))
Loader.add_constructor(yaml.resolver.BaseResolver.DEFAULT_MAPPING_TAG,
mapping_to_tree_loader)
......
......@@ -155,6 +155,21 @@ results in::
fast:
CFLAGS: '-Ofast' # appended
It's also possilbe to include existing file into other file's node. This
is done by `!include : $path` directive::
os:
fedora:
!include : fedora.yaml
gentoo:
!include : gentoo.yaml
Due to yaml nature, it's __mandatory__ to put space between `!include` and `:`!
The file location can be either absolute path or relative path to the yaml
file where the `!include` is called (even when it's nested).
Whole file is __merged__ into the node where it's defined.
.. _variants:
......
# Following line makes it look exactly as mux-selftest.yaml
!include : mux-selftest.yaml
distro:
# This line extends the distro branch using include
!include : mux-selftest-distro.yaml
# This creates new branch the usual way
new_node:
new_value: "something"
RHEL:
enterprise: true
6:
init: 'systemv'
7:
init: 'systemd'
......@@ -152,6 +152,18 @@ class TestTree(unittest.TestCase):
self.assertEqual({'nic': 'virtio'},
tree2.children[0].children[2].children[1].value)
def test_advanced_yaml(self):
tree2 = tree.create_from_yaml(['examples/mux-selftest-advanced.yaml'])
exp = ['intel', 'amd', 'arm', 'scsi', 'virtio', 'fedora', 'mint', '6',
'7', 'prod', 'new_node']
act = tree2.get_leaves()
self.assertEqual(exp, act)
self.assertEqual({'enterprise': True},
tree2.children[1].children[2].value)
self.assertEqual({'init': 'systemd'},
tree2.children[1].children[0].value)
self.assertEqual({'new_value': 'something'}, tree2.children[3].value)
class TestPathParent(unittest.TestCase):
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册