root/masterdriverz/snakeoil-formatters/snakeoil/dependant_methods.py @ masterdriverz%2540gentoo.org-20070423160306-qau2ymexqbb9cwja

Revision masterdriverz%2540gentoo.org-20070423160306-qau2ymexqbb9cwja, 2.3 kB (checked in by Charlie Shepherd <masterdriverz@…>, 21 months ago)

Misc doc fixups

Line 
1# Copyright: 2005-2006 Brian Harring <ferringb@gmail.com>
2# License: GPL2
3
4"""Metaclass to inject dependencies into method calls.
5
6Essentially, method a must be run prior to method b, invoking method a
7if b is called first.
8"""
9
10from snakeoil.lists import iflatten_instance
11from snakeoil.currying import partial
12
13__all__ = ["ForcedDepends"]
14
15def ensure_deps(self, name, *a, **kw):
16    ignore_deps = "ignore_deps" in kw
17    if ignore_deps:
18        del kw["ignore_deps"]
19        s = [name]
20    else:
21        s = yield_deps(self, self.stage_depends, name)
22
23    r = True
24    for dep in s:
25        if dep not in self._stage_state:
26            r = getattr(self, dep).raw_func(*a, **kw)
27            if r:
28                self._stage_state.add(dep)
29            else:
30                return r
31    return r
32
33def yield_deps(inst, d, k):
34    # While at first glance this looks like should use expandable_chain,
35    # it shouldn't. --charlie
36    if k not in d:
37        yield k
38        return
39    s = [k, iflatten_instance(d.get(k, ()))]
40    while s:
41        if isinstance(s[-1], basestring):
42            yield s.pop(-1)
43            continue
44        exhausted = True
45        for x in s[-1]:
46            v = d.get(x)
47            if v:
48                s.append(x)
49                s.append(iflatten_instance(v))
50                exhausted = False
51                break
52            yield x
53        if exhausted:
54            s.pop(-1)
55
56
57class ForcedDepends(type):
58    """
59    Metaclass forcing methods to run in a certain order.
60
61    Dependencies are controlled by the existance of a stage_depends
62    dict in the class namespace. Its keys are method names, values are
63    either a string (name of preceeding method), or list/tuple
64    (proceeding methods).
65
66    U{pkgcore projects pkgcore.intefaces.format.build_base is an example consumer<http://pkgcore.org>}
67    to look at for usage.
68    """
69    def __call__(cls, *a, **kw):
70        o = super(ForcedDepends, cls).__call__(*a, **kw)
71        if not getattr(cls, "stage_depends"):
72            return o
73
74        if not hasattr(o, "_stage_state"):
75            o._stage_state = set()
76
77        # wrap the funcs
78
79        for x in set(x for x in iflatten_instance(o.stage_depends.iteritems())
80                     if x):
81            f = getattr(o, x)
82            f2 = partial(ensure_deps, o, x)
83            f2.raw_func = f
84            setattr(o, x, f2)
85
86        return o
Note: See TracBrowser for help on using the browser.