Exemplo n.º 1
0
class _BaseLoader(Loader):
    """
    YAML loader with additional features related to mux
    """
    Loader.add_constructor(u'!include', lambda loader,
                           node: mux.Control(YAML_INCLUDE))
    Loader.add_constructor(u'!using',
                           lambda loader, node: mux.Control(YAML_USING))
    Loader.add_constructor(u'!remove_node',
                           lambda loader, node: mux.Control(YAML_REMOVE_NODE))
    Loader.add_constructor(u'!remove_value',
                           lambda loader, node: mux.Control(YAML_REMOVE_VALUE))
Exemplo n.º 2
0
 def mux_loader(loader, obj):
     """
     Special !mux loader which allows to tag node as 'multiplex = True'.
     """
     if not isinstance(obj, yaml.ScalarNode):
         objects = mapping_to_tree_loader(loader, obj)
     else:   # This means it's empty node. Don't call mapping_to_tree_loader
         objects = ListOfNodeObjects()
     objects.append((mux.Control(YAML_MUX), None))
     return objects
Exemplo n.º 3
0
 def test_tree_mux_node(self):
     """
     Check the extension of fingerprint in MuxTreeNode
     """
     node1 = tree.TreeNode("node1", {"foo": "bar"})
     node1m = mux.MuxTreeNode("node1", {"foo": "bar"})
     node1m_fingerprint = node1m.fingerprint()
     self.assertNotEqual(node1.fingerprint(), node1m_fingerprint)
     node1mduplicate = mux.MuxTreeNode("node1", {"foo": "bar"})
     self.assertEqual(node1m_fingerprint, node1mduplicate.fingerprint())
     node1mb_ctrl = mux.MuxTreeNode("node1", {"foo": "bar"})
     node1mb_ctrl.ctrl = [mux.Control(0, 0)]
     self.assertNotEqual(node1m_fingerprint, node1mb_ctrl.fingerprint())
Exemplo n.º 4
0
class _BaseLoader(Loader):
    """
    YAML loader with additional features related to mux
    """
    Loader.add_constructor(u'!include',
                           lambda *_: mux.Control(YAML_INCLUDE))
    Loader.add_constructor(u'!using',
                           lambda *_: mux.Control(YAML_USING))
    Loader.add_constructor(u'!remove_node',
                           lambda *_: mux.Control(YAML_REMOVE_NODE))
    Loader.add_constructor(u'!remove_value',
                           lambda *_: mux.Control(YAML_REMOVE_VALUE))
    Loader.add_constructor(u'!filter-only',
                           lambda *_: mux.Control(YAML_FILTER_ONLY))
    Loader.add_constructor(u'!filter-out',
                           lambda *_: mux.Control(YAML_FILTER_OUT))
Exemplo n.º 5
0
def _create_from_yaml(path, cls_node=mux.MuxTreeNode):
    """ Create tree structure from yaml stream """
    def tree_node_from_values(name, values):
        """ Create `name` node and add values  """
        node = cls_node(str(name))
        using = ''
        for value in values:
            if isinstance(value, cls_node):
                node.add_child(value)
            elif isinstance(value[0], mux.Control):
                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_USING:
                    if using:
                        raise ValueError("!using can be used only once per "
                                         "node! (%s:%s)" % (path, name))
                    using = value[1]
                    if using[0] == '/':
                        using = using[1:]
                    if using[-1] == '/':
                        using = using[:-1]
                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
            else:
                node.value[value[0]] = value[1]
        if using:
            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 mapping_to_tree_loader(loader, node):
        """ Maps yaml mapping tag to TreeNode structure """
        _value = []
        for key_node, value_node in node.value:
            if key_node.tag.startswith('!'):    # reflect tags everywhere
                key = loader.construct_object(key_node)
            else:
                key = loader.construct_python_str(key_node)
            value = loader.construct_object(value_node)
            _value.append((key, value))
        objects = ListOfNodeObjects()
        for name, values in _value:
            if isinstance(values, ListOfNodeObjects):   # New node from list
                objects.append(tree_node_from_values(name, values))
            elif values is None:            # Empty node
                objects.append(cls_node(str(name)))
            else:                           # Values
                objects.append(Value((name, values)))
        return objects

    def mux_loader(loader, obj):
        """
        Special !mux loader which allows to tag node as 'multiplex = True'.
        """
        if not isinstance(obj, yaml.ScalarNode):
            objects = mapping_to_tree_loader(loader, obj)
        else:   # This means it's empty node. Don't call mapping_to_tree_loader
            objects = ListOfNodeObjects()
        objects.append((mux.Control(YAML_MUX), None))
        return objects

    Loader.add_constructor(u'!include',
                           lambda loader, node: mux.Control(YAML_INCLUDE))
    Loader.add_constructor(u'!using',
                           lambda loader, node: mux.Control(YAML_USING))
    Loader.add_constructor(u'!remove_node',
                           lambda loader, node: mux.Control(YAML_REMOVE_NODE))
    Loader.add_constructor(u'!remove_value',
                           lambda loader, node: mux.Control(YAML_REMOVE_VALUE))
    Loader.add_constructor(u'!mux', mux_loader)
    Loader.add_constructor(yaml.resolver.BaseResolver.DEFAULT_MAPPING_TAG,
                           mapping_to_tree_loader)

    # Parse file name ([$using:]$path)
    path = __RE_FILE_SPLIT.split(path, 1)
    if len(path) == 1:
        path = __RE_FILE_SUBS.sub(':', path[0])
        using = ["run"]
    else:
        nodes = __RE_FILE_SUBS.sub(':', path[0]).strip('/').split('/')
        using = [node for node in nodes if node]
        if not path[0].startswith('/'):  # relative path, put into /run
            using.insert(0, 'run')
        path = __RE_FILE_SUBS.sub(':', path[1])

    # Load the tree
    with open(path) as stream:
        loaded_tree = yaml.load(stream, Loader)
        if loaded_tree is None:
            return
        loaded_tree = tree_node_from_values('', loaded_tree)

    # Add prefix
    if using:
        loaded_tree.name = using.pop()
        while True:
            if not using:
                break
            loaded_tree = cls_node(using.pop(), children=[loaded_tree])
        loaded_tree = cls_node('', children=[loaded_tree])
    return loaded_tree