未验证 提交 989ca0b2 编写于 作者: C Caio Carrara

Merge remote-tracking branch 'clebergnu/yaml_to_mux_unwind_v2'

Signed-off-by: NCaio Carrara <ccarrara@redhat.com>
...@@ -73,58 +73,113 @@ class ListOfNodeObjects(list): # Few methods pylint: disable=R0903 ...@@ -73,58 +73,113 @@ class ListOfNodeObjects(list): # Few methods pylint: disable=R0903
""" """
def _normalize_path(path):
"""
End the path with single '/'
:param path: original path
:type path: str
:returns: path with trailing '/', or None when empty path
:rtype: str or None
"""
if not path:
return
if path[-1] != '/':
path += '/'
return path
def _handle_control_tag(path, cls_node, node, value):
"""
Handling of most YAML control tags (all but "!using")
:param path: path on the YAML
:type path: str
:param cls_node: the class of the node
:type cls_node: :class:`avocado.core.tree.TreeNode` or similar
:param node: the node in which to handle control tags
:type node: instance of :class:`avocado.core.tree.TreeNode` or similar
:param value: the value of the node
"""
if value[0].code == YAML_INCLUDE:
# Include file
ypath = value[1]
if not os.path.isabs(ypath):
ypath = os.path.join(os.path.dirname(path), ypath)
if not os.path.exists(ypath):
raise ValueError("File '%s' included from '%s' does not "
"exist." % (ypath, path))
node.merge(_create_from_yaml('/:' + ypath, cls_node))
elif value[0].code in (YAML_REMOVE_NODE, YAML_REMOVE_VALUE):
value[0].value = value[1] # set the name
node.ctrl.append(value[0]) # add "blue pill" of death
elif value[0].code == YAML_MUX:
node.multiplex = True
elif value[0].code == YAML_FILTER_ONLY:
new_value = _normalize_path(value[1])
if new_value:
node.filters[0].append(new_value)
elif value[0].code == YAML_FILTER_OUT:
new_value = _normalize_path(value[1])
if new_value:
node.filters[1].append(new_value)
def _handle_control_tag_using(path, name, using, value):
"""
Handling of the "!using" YAML control tag
:param path: path on the YAML
:type path: str
:param name: name to be applied in the "!using" tag
:type name: str
:param using: wether using is already being used
:type using: bool
:param value: the value of the node
"""
if using:
raise ValueError("!using can be used only once per "
"node! (%s:%s)" % (path, name))
using = value
if using[0] == '/':
using = using[1:]
if using[-1] == '/':
using = using[:-1]
return using
def _apply_using(name, cls_node, using, node):
"""
Create the structure defined by "!using" and return the new root
:param name: the tag name to have the "!using" applied to
:type name: str
:param cls_node: the class of the node
:type cls_node: :class:`avocado.core.tree.TreeNode` or similar
:param using: the new location to put the tag into
:type using: bool
:param node: the node in which to handle control tags
:type node: instance of :class:`avocado.core.tree.TreeNode` or similar
"""
if name is not '':
for name in using.split('/')[::-1]:
node = cls_node(name, children=[node])
else:
using = using.split('/')[::-1]
node.name = using.pop()
while True:
if not using:
break
name = using.pop() # 'using' is list pylint: disable=E1101
node = cls_node(name, children=[node])
node = cls_node('', children=[node])
return node
def _create_from_yaml(path, cls_node=mux.MuxTreeNode): def _create_from_yaml(path, cls_node=mux.MuxTreeNode):
"""Create tree structure from yaml stream""" """Create tree structure from yaml stream"""
def tree_node_from_values(name, values): def tree_node_from_values(name, values):
"""Create `name` node and add values""" """Create `name` node and add values"""
def handle_control_tag(node, value):
"""Handling of YAML tags (except of !using)"""
def normalize_path(path):
"""End the path with single '/', None when empty path"""
if not path:
return
if path[-1] != '/':
path += '/'
return path
if value[0].code == YAML_INCLUDE:
# Include file
ypath = value[1]
if not os.path.isabs(ypath):
ypath = os.path.join(os.path.dirname(path), ypath)
if not os.path.exists(ypath):
raise ValueError("File '%s' included from '%s' does not "
"exist." % (ypath, path))
node.merge(_create_from_yaml('/:' + ypath, cls_node))
elif value[0].code == YAML_REMOVE_NODE:
value[0].value = value[1] # set the name
node.ctrl.append(value[0]) # add "blue pill" of death
elif value[0].code == YAML_REMOVE_VALUE:
value[0].value = value[1] # set the name
node.ctrl.append(value[0])
elif value[0].code == YAML_MUX:
node.multiplex = True
elif value[0].code == YAML_FILTER_ONLY:
new_value = normalize_path(value[1])
if new_value:
node.filters[0].append(new_value)
elif value[0].code == YAML_FILTER_OUT:
new_value = normalize_path(value[1])
if new_value:
node.filters[1].append(new_value)
def handle_control_tag_using(name, using, value):
"""Handling of the !using tag"""
if using:
raise ValueError("!using can be used only once per "
"node! (%s:%s)" % (path, name))
using = value
if using[0] == '/':
using = using[1:]
if using[-1] == '/':
using = using[:-1]
return using
def node_content_from_node(node, values, using): def node_content_from_node(node, values, using):
"""Processes node values into the current node content""" """Processes node values into the current node content"""
for value in values: for value in values:
...@@ -132,9 +187,9 @@ def _create_from_yaml(path, cls_node=mux.MuxTreeNode): ...@@ -132,9 +187,9 @@ def _create_from_yaml(path, cls_node=mux.MuxTreeNode):
node.add_child(value) node.add_child(value)
elif isinstance(value[0], mux.Control): elif isinstance(value[0], mux.Control):
if value[0].code == YAML_USING: if value[0].code == YAML_USING:
using = handle_control_tag_using(name, using, value[1]) using = _handle_control_tag_using(path, name, using, value[1])
else: else:
handle_control_tag(node, value) _handle_control_tag(path, cls_node, node, value)
elif isinstance(value[1], collections.OrderedDict): elif isinstance(value[1], collections.OrderedDict):
node.add_child(tree_node_from_values(str(value[0]), node.add_child(tree_node_from_values(str(value[0]),
value[1])) value[1]))
...@@ -147,9 +202,9 @@ def _create_from_yaml(path, cls_node=mux.MuxTreeNode): ...@@ -147,9 +202,9 @@ def _create_from_yaml(path, cls_node=mux.MuxTreeNode):
for key, value in iteritems(values): for key, value in iteritems(values):
if isinstance(key, mux.Control): if isinstance(key, mux.Control):
if key.code == YAML_USING: if key.code == YAML_USING:
using = handle_control_tag_using(name, using, value) using = _handle_control_tag_using(path, name, using, value)
else: else:
handle_control_tag(node, [key, value]) _handle_control_tag(path, cls_node, node, [key, value])
elif (isinstance(value, collections.OrderedDict) or elif (isinstance(value, collections.OrderedDict) or
value is None): value is None):
node.add_child(tree_node_from_values(key, value)) node.add_child(tree_node_from_values(key, value))
...@@ -157,22 +212,6 @@ def _create_from_yaml(path, cls_node=mux.MuxTreeNode): ...@@ -157,22 +212,6 @@ def _create_from_yaml(path, cls_node=mux.MuxTreeNode):
node.value[key] = value node.value[key] = value
return using return using
def apply_using(name, using, node):
'''Create the structure defined by using and return the new root'''
if name is not '':
for name in using.split('/')[::-1]:
node = cls_node(name, children=[node])
else:
using = using.split('/')[::-1]
node.name = using.pop()
while True:
if not using:
break
name = using.pop() # 'using' is list pylint: disable=E1101
node = cls_node(name, children=[node])
node = cls_node('', children=[node])
return node
# Initialize the node # Initialize the node
node = cls_node(str(name)) node = cls_node(str(name))
if not values: if not values:
...@@ -187,7 +226,7 @@ def _create_from_yaml(path, cls_node=mux.MuxTreeNode): ...@@ -187,7 +226,7 @@ def _create_from_yaml(path, cls_node=mux.MuxTreeNode):
# Prefix nodes if tag "!using" was used # Prefix nodes if tag "!using" was used
if using: if using:
node = apply_using(name, using, node) node = _apply_using(name, cls_node, using, node)
return node return node
def mapping_to_tree_loader(loader, node, looks_like_node=False): def mapping_to_tree_loader(loader, node, looks_like_node=False):
......
...@@ -55,6 +55,13 @@ class MultiplexTests(unittest.TestCase): ...@@ -55,6 +55,13 @@ class MultiplexTests(unittest.TestCase):
result = self.run_and_check(cmd_line, expected_rc) result = self.run_and_check(cmd_line, expected_rc)
self.assertIn('No such file or directory', result.stderr_text) self.assertIn('No such file or directory', result.stderr_text)
def test_mplex_plugin_using(self):
cmd_line = ('%s variants -m /:optional_plugins/varianter_yaml_to_mux/'
'tests/.data/mux-selftest-using.yaml' % AVOCADO)
expected_rc = exit_codes.AVOCADO_ALL_OK
result = self.run_and_check(cmd_line, expected_rc)
self.assertIn(b' /foo/baz/bar', result.stdout)
@unittest.skipIf(sys.version_info[0] == 3, @unittest.skipIf(sys.version_info[0] == 3,
"Test currently broken on Python 3") "Test currently broken on Python 3")
def test_mplex_debug(self): def test_mplex_debug(self):
......
...@@ -535,6 +535,49 @@ class TestPathParent(unittest.TestCase): ...@@ -535,6 +535,49 @@ class TestPathParent(unittest.TestCase):
self.assertNotEqual(mux.path_parent('/os/linux'), '/') self.assertNotEqual(mux.path_parent('/os/linux'), '/')
class TestCreateFromYaml(unittest.TestCase):
def test_normalize_path(self):
self.assertEqual(yaml_to_mux._normalize_path(''), None)
self.assertEqual(yaml_to_mux._normalize_path('path'), 'path/')
def test_handle_control_path_include_file_does_not_exist(self):
with self.assertRaises(ValueError):
yaml_to_mux._handle_control_tag(
'original_fake_file.yaml',
mux.MuxTreeNode, mux.MuxTreeNode(),
(mux.Control(yaml_to_mux.YAML_INCLUDE),
'unexisting_include.yaml'))
def test_handle_control_path_remove(self):
klass = mux.MuxTreeNode
node = klass()
control = mux.Control(yaml_to_mux.YAML_REMOVE_NODE)
to_be_removed = 'node_to_be_removed'
yaml_to_mux._handle_control_tag('fake_path',
klass, node,
(control, to_be_removed))
self.assertEqual(control.value, to_be_removed)
self.assertIn(control, node.ctrl)
def test_handle_control_tag_using_multiple(self):
with self.assertRaises(ValueError):
yaml_to_mux._handle_control_tag_using('original_fake_file.yaml',
'name', True, 'using')
def test_handle_control_tag_using(self):
using = yaml_to_mux._handle_control_tag_using('fake_path',
'name',
False,
'/using/path/')
self.assertEqual(using, 'using/path')
def test_apply_using(self):
node = yaml_to_mux._apply_using('bar', mux.MuxTreeNode,
'foo', mux.MuxTreeNode())
self.assertEqual(node.path, '/foo')
class TestFingerprint(unittest.TestCase): class TestFingerprint(unittest.TestCase):
def test_fingerprint(self): def test_fingerprint(self):
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册