1__author__ = 'roland'
2
3
4def find_paths(cls, arg, path=None, seen=None, res=None, lev=0):
5    if lev == 0 and res is None:
6        res = []
7
8    if path is None:
9        path = []
10
11    if seen is None:
12        seen = [cls]
13    else:
14        if cls in seen:
15            return None
16
17        seen.append(cls)
18
19    for cn, c in cls.c_children.values():
20        _path = path + [cn]
21        if cn == arg:
22            if res is not None:
23                res.append(_path)
24        else:
25            if isinstance(c, list):
26                _c = c[0]
27            else:
28                _c = c
29
30            find_paths(_c, arg, _path, seen, res)
31
32    for an, typ, mult in cls.c_attributes.values():
33        if an == arg:
34            if res is not None:
35                res.append(path + [an])
36
37    if lev == 0:
38        return res
39
40
41def set_arg(cls, arg, value):
42    res = []
43    for path in find_paths(cls, arg):
44        x = y = {}
45        for arc in path[:-1]:
46            y[arc] = {}
47            y = y[arc]
48        y[path[-1]] = value
49        res.append(x)
50
51    return res
52
53
54def add_path(tdict, path):
55    """
56    Create or extend an argument tree `tdict` from `path`.
57
58    :param tdict: a dictionary representing a argument tree
59    :param path: a path list
60    :return: a dictionary
61
62    Convert a list of items in a 'path' into a nested dict, where the
63    second to last item becomes the key for the final item. The remaining
64    items in the path become keys in the nested dict around that final pair
65    of items.
66
67    For example, for input values of:
68        tdict={}
69        path = ['assertion', 'subject', 'subject_confirmation',
70                'method', 'urn:oasis:names:tc:SAML:2.0:cm:bearer']
71
72        Returns an output value of:
73           {'assertion': {'subject': {'subject_confirmation':
74                         {'method': 'urn:oasis:names:tc:SAML:2.0:cm:bearer'}}}}
75
76    Another example, this time with a non-empty tdict input:
77
78        tdict={'method': 'urn:oasis:names:tc:SAML:2.0:cm:bearer'},
79        path=['subject_confirmation_data', 'in_response_to', '_012345']
80
81        Returns an output value of:
82            {'subject_confirmation_data': {'in_response_to': '_012345'},
83             'method': 'urn:oasis:names:tc:SAML:2.0:cm:bearer'}
84    """
85    t = tdict
86    for step in path[:-2]:
87        try:
88            t = t[step]
89        except KeyError:
90            t[step] = {}
91            t = t[step]
92    t[path[-2]] = path[-1]
93
94    return tdict
95
96
97def is_set(tdict, path):
98    """
99
100    :param tdict: a dictionary representing a argument tree
101    :param path: a path list
102    :return: True/False if the value is set
103    """
104    t = tdict
105    for step in path:
106        try:
107            t = t[step]
108        except KeyError:
109            return False
110
111    if t is not None:
112        return True
113
114    return False
115
116
117def get_attr(tdict, path):
118    t = tdict
119    for step in path:
120        t = t[step]
121
122    return t
123