summaryrefslogtreecommitdiff
path: root/reconfigure/includers/auto.py
blob: c220d884c2050f183fb3b11a67fcabd2508716ee (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
from reconfigure.includers.base import BaseIncluder
from reconfigure.nodes import *
import glob
import os


class AutoIncluder (BaseIncluder):
    """
    This base includer automatically walks the node tree and loads the include files from ``IncludeNode.files`` properties. ``files`` is supposed to contain absolute path, relative path or a shell wildcard.
    """

    def compose(self, origin, tree):
        self.compose_rec(origin, origin, tree)
        return tree

    def compose_rec(self, root, origin, node):
        if not node.origin:
            node.origin = origin
        for child in node.children:
            self.compose_rec(root, origin, child)
        for child in node.children:
            spec = self.is_include(child)
            if spec:
                files = spec
                if node.origin and not files.startswith('/'):
                    files = os.path.join(os.path.split(root)[0], files)
                if '*' in files or '.' in files:
                    files = glob.glob(files)
                else:
                    files = [files]
                for file in files:
                    if file in self.content_map:
                        content = self.content_map[file]
                    else:
                        content = open(file, 'r').read()
                    subtree = self.parser.parse(content)
                    node.children.extend(subtree.children)
                    self.compose_rec(root, file, subtree)
                node.children[node.children.index(child)] = IncludeNode(spec)

    def decompose(self, tree):
        result = {}
        result[tree.origin] = self.decompose_rec(tree, result)
        return result

    def decompose_rec(self, node, result):
        for child in node.children:
            if child.__class__ == IncludeNode:
                replacement = self.remove_include(child)
                if replacement:
                    node.children[node.children.index(child)] = replacement
            else:
                if child.origin is None:
                    child.origin = node.origin
                elif child.origin != node.origin:
                    node.children.remove(child)
                    result.setdefault(child.origin, RootNode()).children.append(self.decompose_rec(child, result))
                else:
                    self.decompose_rec(child, result)
        return node

    def is_include(self, node):
        """
        Should return whether the node is an include node and return file pattern glob if it is
        """

    def remove_include(self, node):
        """
        Shoud transform :class:`reconfigure.nodes.IncludeNode` into a normal Node to be stringified into the file
        """