xref: /openbmc/phosphor-dbus-monitor/src/pdmgen.py (revision ab375ecaa45264b8a656a392684724e9c815a504)
144fd7e89SMarri Devender Rao#!/usr/bin/env python3
20019197fSBrad Bishop
3a1709e4aSPatrick Williams"""Phosphor DBus Monitor YAML parser and code generator.
434a7acdfSBrad Bishop
534a7acdfSBrad BishopThe parser workflow is broken down as follows:
634a7acdfSBrad Bishop  1 - Import YAML files as native python type(s) instance(s).
734a7acdfSBrad Bishop  2 - Create an instance of the Everything class from the
834a7acdfSBrad Bishop        native python type instance(s) with the Everything.load
934a7acdfSBrad Bishop        method.
1034a7acdfSBrad Bishop  3 - The Everything class constructor orchestrates conversion of the
1134a7acdfSBrad Bishop        native python type(s) instances(s) to render helper types.
1234a7acdfSBrad Bishop        Each render helper type constructor imports its attributes
1334a7acdfSBrad Bishop        from the native python type(s) instances(s).
1434a7acdfSBrad Bishop  4 - Present the converted YAML to the command processing method
1534a7acdfSBrad Bishop        requested by the script user.
16a1709e4aSPatrick Williams"""
1734a7acdfSBrad Bishop
180019197fSBrad Bishopimport os
190019197fSBrad Bishopimport sys
200019197fSBrad Bishopfrom argparse import ArgumentParser
21*ab375ecaSPatrick Williams
22*ab375ecaSPatrick Williamsimport mako.lookup
23e73b2c35SBrad Bishopimport sdbusplus.property
24*ab375ecaSPatrick Williamsimport yaml
25*ab375ecaSPatrick Williamsfrom sdbusplus.namedelement import NamedElement
26*ab375ecaSPatrick Williamsfrom sdbusplus.renderer import Renderer
2705b0c1eeSBrad Bishop
2805b0c1eeSBrad Bishop
2918447acbSPatrick Williamsclass InvalidConfigError(Exception):
30a1709e4aSPatrick Williams    """General purpose config file parsing error."""
3105b0c1eeSBrad Bishop
3205b0c1eeSBrad Bishop    def __init__(self, path, msg):
33a1709e4aSPatrick Williams        """Display configuration file with the syntax
34a1709e4aSPatrick Williams        error and the error message."""
3505b0c1eeSBrad Bishop
3605b0c1eeSBrad Bishop        self.config = path
3705b0c1eeSBrad Bishop        self.msg = msg
3805b0c1eeSBrad Bishop
3905b0c1eeSBrad Bishop
4005b0c1eeSBrad Bishopclass NotUniqueError(InvalidConfigError):
41a1709e4aSPatrick Williams    """Within a config file names must be unique.
4205b0c1eeSBrad Bishop    Display the config file with the duplicate and
43a1709e4aSPatrick Williams    the duplicate itself."""
4405b0c1eeSBrad Bishop
4505b0c1eeSBrad Bishop    def __init__(self, path, cls, *names):
4605b0c1eeSBrad Bishop        fmt = 'Duplicate {0}: "{1}"'
4705b0c1eeSBrad Bishop        super(NotUniqueError, self).__init__(
48a1709e4aSPatrick Williams            path, fmt.format(cls, " ".join(names))
49a1709e4aSPatrick Williams        )
5005b0c1eeSBrad Bishop
5105b0c1eeSBrad Bishop
5205b0c1eeSBrad Bishopdef get_index(objs, cls, name, config=None):
53a1709e4aSPatrick Williams    """Items are usually rendered as C++ arrays and as
5405b0c1eeSBrad Bishop    such are stored in python lists.  Given an item name
5505b0c1eeSBrad Bishop    its class, and an optional config file filter, find
56a1709e4aSPatrick Williams    the item index."""
5705b0c1eeSBrad Bishop
5805b0c1eeSBrad Bishop    for i, x in enumerate(objs.get(cls, [])):
5905b0c1eeSBrad Bishop        if config and x.configfile != config:
6005b0c1eeSBrad Bishop            continue
6105b0c1eeSBrad Bishop        if x.name != name:
6205b0c1eeSBrad Bishop            continue
6305b0c1eeSBrad Bishop
6405b0c1eeSBrad Bishop        return i
6505b0c1eeSBrad Bishop    raise InvalidConfigError(config, 'Could not find name: "{0}"'.format(name))
6605b0c1eeSBrad Bishop
6705b0c1eeSBrad Bishop
6805b0c1eeSBrad Bishopdef exists(objs, cls, name, config=None):
69a1709e4aSPatrick Williams    """Check to see if an item already exists in a list given
70a1709e4aSPatrick Williams    the item name."""
7105b0c1eeSBrad Bishop
7205b0c1eeSBrad Bishop    try:
7305b0c1eeSBrad Bishop        get_index(objs, cls, name, config)
7418447acbSPatrick Williams    except Exception:
7505b0c1eeSBrad Bishop        return False
7605b0c1eeSBrad Bishop
7705b0c1eeSBrad Bishop    return True
7805b0c1eeSBrad Bishop
7905b0c1eeSBrad Bishop
8005b0c1eeSBrad Bishopdef add_unique(obj, *a, **kw):
81a1709e4aSPatrick Williams    """Add an item to one or more lists unless already present,
82a1709e4aSPatrick Williams    with an option to constrain the search to a specific config file."""
8305b0c1eeSBrad Bishop
8405b0c1eeSBrad Bishop    for container in a:
85a1709e4aSPatrick Williams        if not exists(container, obj.cls, obj.name, config=kw.get("config")):
8605b0c1eeSBrad Bishop            container.setdefault(obj.cls, []).append(obj)
870019197fSBrad Bishop
880019197fSBrad Bishop
8901079892SBrad Bishopclass Cast(object):
90a1709e4aSPatrick Williams    """Decorate an argument by casting it."""
9101079892SBrad Bishop
9201079892SBrad Bishop    def __init__(self, cast, target):
93a1709e4aSPatrick Williams        """cast is the cast type (static, const, etc...).
94a1709e4aSPatrick Williams        target is the cast target type."""
9501079892SBrad Bishop        self.cast = cast
9601079892SBrad Bishop        self.target = target
9701079892SBrad Bishop
9801079892SBrad Bishop    def __call__(self, arg):
99a1709e4aSPatrick Williams        return "{0}_cast<{1}>({2})".format(self.cast, self.target, arg)
10001079892SBrad Bishop
10101079892SBrad Bishop
10201079892SBrad Bishopclass Literal(object):
103a1709e4aSPatrick Williams    """Decorate an argument with a literal operator."""
10401079892SBrad Bishop
105a1709e4aSPatrick Williams    integer_types = ["int16", "int32", "int64", "uint16", "uint32", "uint64"]
10601079892SBrad Bishop
10701079892SBrad Bishop    def __init__(self, type):
10801079892SBrad Bishop        self.type = type
10901079892SBrad Bishop
11001079892SBrad Bishop    def __call__(self, arg):
111a1709e4aSPatrick Williams        if "uint" in self.type:
112a1709e4aSPatrick Williams            arg = "{0}ull".format(arg)
113a1709e4aSPatrick Williams        elif "int" in self.type:
114a1709e4aSPatrick Williams            arg = "{0}ll".format(arg)
11501079892SBrad Bishop
11601079892SBrad Bishop        if self.type in self.integer_types:
117a1709e4aSPatrick Williams            return Cast("static", "{0}_t".format(self.type))(arg)
118a1709e4aSPatrick Williams        elif self.type == "byte":
11918447acbSPatrick Williams            return Cast("static", "uint8_t")(arg)
120a1709e4aSPatrick Williams        elif self.type == "double":
12118447acbSPatrick Williams            return Cast("static", "double")(arg)
12201079892SBrad Bishop
123a1709e4aSPatrick Williams        if self.type == "string":
124a1709e4aSPatrick Williams            return "{0}s".format(arg)
12501079892SBrad Bishop
12601079892SBrad Bishop        return arg
12701079892SBrad Bishop
12801079892SBrad Bishop
12901079892SBrad Bishopclass FixBool(object):
130a1709e4aSPatrick Williams    """Un-capitalize booleans."""
13101079892SBrad Bishop
13201079892SBrad Bishop    def __call__(self, arg):
133a1709e4aSPatrick Williams        return "{0}".format(arg.lower())
13401079892SBrad Bishop
13501079892SBrad Bishop
13601079892SBrad Bishopclass Quote(object):
137a1709e4aSPatrick Williams    """Decorate an argument by quoting it."""
13801079892SBrad Bishop
13901079892SBrad Bishop    def __call__(self, arg):
14001079892SBrad Bishop        return '"{0}"'.format(arg)
14101079892SBrad Bishop
14201079892SBrad Bishop
14301079892SBrad Bishopclass Argument(NamedElement, Renderer):
144a1709e4aSPatrick Williams    """Define argument type interface."""
14501079892SBrad Bishop
14601079892SBrad Bishop    def __init__(self, **kw):
147a1709e4aSPatrick Williams        self.type = kw.pop("type", None)
14801079892SBrad Bishop        super(Argument, self).__init__(**kw)
14901079892SBrad Bishop
15001079892SBrad Bishop    def argument(self, loader, indent):
15101079892SBrad Bishop        raise NotImplementedError
15201079892SBrad Bishop
15301079892SBrad Bishop
15401079892SBrad Bishopclass TrivialArgument(Argument):
155a1709e4aSPatrick Williams    """Non-array type arguments."""
15601079892SBrad Bishop
15701079892SBrad Bishop    def __init__(self, **kw):
158a1709e4aSPatrick Williams        self.value = kw.pop("value")
159a1709e4aSPatrick Williams        self.decorators = kw.pop("decorators", [])
160a1709e4aSPatrick Williams        if kw.get("type", None):
161a1709e4aSPatrick Williams            self.decorators.insert(0, Literal(kw["type"]))
162a1709e4aSPatrick Williams        if kw.get("type", None) == "string":
16301079892SBrad Bishop            self.decorators.insert(0, Quote())
164a1709e4aSPatrick Williams        if kw.get("type", None) == "boolean":
16501079892SBrad Bishop            self.decorators.insert(0, FixBool())
16601079892SBrad Bishop
16701079892SBrad Bishop        super(TrivialArgument, self).__init__(**kw)
16801079892SBrad Bishop
16901079892SBrad Bishop    def argument(self, loader, indent):
17001079892SBrad Bishop        a = str(self.value)
17101079892SBrad Bishop        for d in self.decorators:
17201079892SBrad Bishop            a = d(a)
17301079892SBrad Bishop
17401079892SBrad Bishop        return a
17501079892SBrad Bishop
17680e9b65fSMatt Spinler
17730474cf5SGunnar Millsclass Metadata(Argument):
178a1709e4aSPatrick Williams    """Metadata type arguments."""
17930474cf5SGunnar Mills
18030474cf5SGunnar Mills    def __init__(self, **kw):
181a1709e4aSPatrick Williams        self.value = kw.pop("value")
182a1709e4aSPatrick Williams        self.decorators = kw.pop("decorators", [])
183a1709e4aSPatrick Williams        if kw.get("type", None) == "string":
18430474cf5SGunnar Mills            self.decorators.insert(0, Quote())
18530474cf5SGunnar Mills
18630474cf5SGunnar Mills        super(Metadata, self).__init__(**kw)
18730474cf5SGunnar Mills
18830474cf5SGunnar Mills    def argument(self, loader, indent):
18930474cf5SGunnar Mills        a = str(self.value)
19030474cf5SGunnar Mills        for d in self.decorators:
19130474cf5SGunnar Mills            a = d(a)
19230474cf5SGunnar Mills
19330474cf5SGunnar Mills        return a
19401079892SBrad Bishop
19580e9b65fSMatt Spinler
196ae786ef6SMatthew Barthclass OpArgument(Argument):
197a1709e4aSPatrick Williams    """Operation type arguments."""
198ae786ef6SMatthew Barth
199ae786ef6SMatthew Barth    def __init__(self, **kw):
200a1709e4aSPatrick Williams        self.op = kw.pop("op")
201a1709e4aSPatrick Williams        self.bound = kw.pop("bound")
202a1709e4aSPatrick Williams        self.decorators = kw.pop("decorators", [])
203a1709e4aSPatrick Williams        if kw.get("type", None):
204a1709e4aSPatrick Williams            self.decorators.insert(0, Literal(kw["type"]))
205a1709e4aSPatrick Williams        if kw.get("type", None) == "string":
206ae786ef6SMatthew Barth            self.decorators.insert(0, Quote())
207a1709e4aSPatrick Williams        if kw.get("type", None) == "boolean":
208ae786ef6SMatthew Barth            self.decorators.insert(0, FixBool())
209ae786ef6SMatthew Barth
210ae786ef6SMatthew Barth        super(OpArgument, self).__init__(**kw)
211ae786ef6SMatthew Barth
212ae786ef6SMatthew Barth    def argument(self, loader, indent):
213ae786ef6SMatthew Barth        a = str(self.bound)
214ae786ef6SMatthew Barth        for d in self.decorators:
215ae786ef6SMatthew Barth            a = d(a)
216ae786ef6SMatthew Barth
217ae786ef6SMatthew Barth        return a
218ae786ef6SMatthew Barth
219ae786ef6SMatthew Barth
22034a7acdfSBrad Bishopclass Indent(object):
221a1709e4aSPatrick Williams    """Help templates be depth agnostic."""
2220019197fSBrad Bishop
22334a7acdfSBrad Bishop    def __init__(self, depth=0):
22434a7acdfSBrad Bishop        self.depth = depth
2250019197fSBrad Bishop
22634a7acdfSBrad Bishop    def __add__(self, depth):
22734a7acdfSBrad Bishop        return Indent(self.depth + depth)
22834a7acdfSBrad Bishop
22934a7acdfSBrad Bishop    def __call__(self, depth):
230a1709e4aSPatrick Williams        """Render an indent at the current depth plus depth."""
231a1709e4aSPatrick Williams        return 4 * " " * (depth + self.depth)
23234a7acdfSBrad Bishop
23334a7acdfSBrad Bishop
23405b0c1eeSBrad Bishopclass ConfigEntry(NamedElement):
235a1709e4aSPatrick Williams    """Base interface for rendered items."""
23605b0c1eeSBrad Bishop
23705b0c1eeSBrad Bishop    def __init__(self, *a, **kw):
238a1709e4aSPatrick Williams        """Pop the configfile/class/subclass keywords."""
23905b0c1eeSBrad Bishop
240a1709e4aSPatrick Williams        self.configfile = kw.pop("configfile")
241a1709e4aSPatrick Williams        self.cls = kw.pop("class")
24205b0c1eeSBrad Bishop        self.subclass = kw.pop(self.cls)
243cfdfa0daSPatrick Williams
244cfdfa0daSPatrick Williams        # TODO: NamedElement requires 'name' to be a string, but in many cases
245cfdfa0daSPatrick Williams        #       this script treats 'name' as a dict.  Save the property off and
246cfdfa0daSPatrick Williams        #       insert it after ConfigEntry does its own thing to avoid
247cfdfa0daSPatrick Williams        #       exceptions.  This should be refactored throughout the whole
248cfdfa0daSPatrick Williams        #       script to not overload 'name' as a dict.
249a1709e4aSPatrick Williams        name_save = kw.pop("name")
25005b0c1eeSBrad Bishop        super(ConfigEntry, self).__init__(**kw)
251cfdfa0daSPatrick Williams        self.name = name_save
25205b0c1eeSBrad Bishop
25305b0c1eeSBrad Bishop    def factory(self, objs):
254a1709e4aSPatrick Williams        """Optional factory interface for subclasses to add
255a1709e4aSPatrick Williams        additional items to be rendered."""
25605b0c1eeSBrad Bishop
25705b0c1eeSBrad Bishop        pass
25805b0c1eeSBrad Bishop
25905b0c1eeSBrad Bishop    def setup(self, objs):
260a1709e4aSPatrick Williams        """Optional setup interface for subclasses, invoked
261a1709e4aSPatrick Williams        after all factory methods have been run."""
26205b0c1eeSBrad Bishop
26305b0c1eeSBrad Bishop        pass
26405b0c1eeSBrad Bishop
26505b0c1eeSBrad Bishop
2660e7df131SBrad Bishopclass Path(ConfigEntry):
267a1709e4aSPatrick Williams    """Path/metadata association."""
2680e7df131SBrad Bishop
2690e7df131SBrad Bishop    def __init__(self, *a, **kw):
2700e7df131SBrad Bishop        super(Path, self).__init__(**kw)
2710e7df131SBrad Bishop
272a1709e4aSPatrick Williams        if self.name["meta"].upper() != self.name["meta"]:
273babf3b78SBrad Bishop            raise InvalidConfigError(
274babf3b78SBrad Bishop                self.configfile,
275babf3b78SBrad Bishop                'Metadata tag "{0}" must be upper case.'.format(
276a1709e4aSPatrick Williams                    self.name["meta"]
277a1709e4aSPatrick Williams                ),
278a1709e4aSPatrick Williams            )
279babf3b78SBrad Bishop
2800e7df131SBrad Bishop    def factory(self, objs):
281a1709e4aSPatrick Williams        """Create path and metadata elements."""
2820e7df131SBrad Bishop
2830e7df131SBrad Bishop        args = {
284a1709e4aSPatrick Williams            "class": "pathname",
285a1709e4aSPatrick Williams            "pathname": "element",
286a1709e4aSPatrick Williams            "name": self.name["path"],
2870e7df131SBrad Bishop        }
288a1709e4aSPatrick Williams        add_unique(ConfigEntry(configfile=self.configfile, **args), objs)
2890e7df131SBrad Bishop
290a1709e4aSPatrick Williams        args = {"class": "meta", "meta": "element", "name": self.name["meta"]}
291a1709e4aSPatrick Williams        add_unique(ConfigEntry(configfile=self.configfile, **args), objs)
2920e7df131SBrad Bishop
2930e7df131SBrad Bishop        super(Path, self).factory(objs)
2940e7df131SBrad Bishop
2950e7df131SBrad Bishop    def setup(self, objs):
296a1709e4aSPatrick Williams        """Resolve path and metadata names to indices."""
2970e7df131SBrad Bishop
298a1709e4aSPatrick Williams        self.path = get_index(objs, "pathname", self.name["path"])
299a1709e4aSPatrick Williams        self.meta = get_index(objs, "meta", self.name["meta"])
3000e7df131SBrad Bishop
3010e7df131SBrad Bishop        super(Path, self).setup(objs)
3020e7df131SBrad Bishop
3030e7df131SBrad Bishop
304e73b2c35SBrad Bishopclass Property(ConfigEntry):
305a1709e4aSPatrick Williams    """Property/interface/metadata association."""
306e73b2c35SBrad Bishop
307e73b2c35SBrad Bishop    def __init__(self, *a, **kw):
308e73b2c35SBrad Bishop        super(Property, self).__init__(**kw)
309e73b2c35SBrad Bishop
310a1709e4aSPatrick Williams        if self.name["meta"].upper() != self.name["meta"]:
311babf3b78SBrad Bishop            raise InvalidConfigError(
312babf3b78SBrad Bishop                self.configfile,
313babf3b78SBrad Bishop                'Metadata tag "{0}" must be upper case.'.format(
314a1709e4aSPatrick Williams                    self.name["meta"]
315a1709e4aSPatrick Williams                ),
316a1709e4aSPatrick Williams            )
317babf3b78SBrad Bishop
318e73b2c35SBrad Bishop    def factory(self, objs):
319a1709e4aSPatrick Williams        """Create interface, property name and metadata elements."""
320e73b2c35SBrad Bishop
321e73b2c35SBrad Bishop        args = {
322a1709e4aSPatrick Williams            "class": "interface",
323a1709e4aSPatrick Williams            "interface": "element",
324a1709e4aSPatrick Williams            "name": self.name["interface"],
325e73b2c35SBrad Bishop        }
326a1709e4aSPatrick Williams        add_unique(ConfigEntry(configfile=self.configfile, **args), objs)
327e73b2c35SBrad Bishop
328e73b2c35SBrad Bishop        args = {
329a1709e4aSPatrick Williams            "class": "propertyname",
330a1709e4aSPatrick Williams            "propertyname": "element",
331a1709e4aSPatrick Williams            "name": self.name["property"],
332e73b2c35SBrad Bishop        }
333a1709e4aSPatrick Williams        add_unique(ConfigEntry(configfile=self.configfile, **args), objs)
334e73b2c35SBrad Bishop
335a1709e4aSPatrick Williams        args = {"class": "meta", "meta": "element", "name": self.name["meta"]}
336a1709e4aSPatrick Williams        add_unique(ConfigEntry(configfile=self.configfile, **args), objs)
337e73b2c35SBrad Bishop
338e73b2c35SBrad Bishop        super(Property, self).factory(objs)
339e73b2c35SBrad Bishop
340e73b2c35SBrad Bishop    def setup(self, objs):
341a1709e4aSPatrick Williams        """Resolve interface, property and metadata to indices."""
342e73b2c35SBrad Bishop
343a1709e4aSPatrick Williams        self.interface = get_index(objs, "interface", self.name["interface"])
344a1709e4aSPatrick Williams        self.prop = get_index(objs, "propertyname", self.name["property"])
345a1709e4aSPatrick Williams        self.meta = get_index(objs, "meta", self.name["meta"])
346e73b2c35SBrad Bishop
347e73b2c35SBrad Bishop        super(Property, self).setup(objs)
348e73b2c35SBrad Bishop
349e73b2c35SBrad Bishop
3504b916f13SBrad Bishopclass Instance(ConfigEntry):
351a1709e4aSPatrick Williams    """Property/Path association."""
3524b916f13SBrad Bishop
3534b916f13SBrad Bishop    def __init__(self, *a, **kw):
3544b916f13SBrad Bishop        super(Instance, self).__init__(**kw)
3554b916f13SBrad Bishop
3564b916f13SBrad Bishop    def setup(self, objs):
357a1709e4aSPatrick Williams        """Resolve elements to indices."""
3584b916f13SBrad Bishop
3594b916f13SBrad Bishop        self.interface = get_index(
360a1709e4aSPatrick Williams            objs, "interface", self.name["property"]["interface"]
361a1709e4aSPatrick Williams        )
3624b916f13SBrad Bishop        self.prop = get_index(
363a1709e4aSPatrick Williams            objs, "propertyname", self.name["property"]["property"]
364a1709e4aSPatrick Williams        )
365a1709e4aSPatrick Williams        self.propmeta = get_index(objs, "meta", self.name["property"]["meta"])
366a1709e4aSPatrick Williams        self.path = get_index(objs, "pathname", self.name["path"]["path"])
367a1709e4aSPatrick Williams        self.pathmeta = get_index(objs, "meta", self.name["path"]["meta"])
3684b916f13SBrad Bishop
3694b916f13SBrad Bishop        super(Instance, self).setup(objs)
3704b916f13SBrad Bishop
371a1709e4aSPatrick Williams
37280c70610SMarri Devender Raoclass PathInstance(ConfigEntry):
373a1709e4aSPatrick Williams    """Path association."""
37480c70610SMarri Devender Rao
37580c70610SMarri Devender Rao    def __init__(self, *a, **kw):
37680c70610SMarri Devender Rao        super(PathInstance, self).__init__(**kw)
37780c70610SMarri Devender Rao
37880c70610SMarri Devender Rao    def setup(self, objs):
379a1709e4aSPatrick Williams        """Resolve elements to indices."""
380a1709e4aSPatrick Williams        self.path = self.name["path"]["path"]
381a1709e4aSPatrick Williams        self.pathmeta = self.name["path"]["meta"]
38280c70610SMarri Devender Rao        super(PathInstance, self).setup(objs)
3834b916f13SBrad Bishop
384a1709e4aSPatrick Williams
38505b0c1eeSBrad Bishopclass Group(ConfigEntry):
386a1709e4aSPatrick Williams    """Pop the members keyword for groups."""
38705b0c1eeSBrad Bishop
38805b0c1eeSBrad Bishop    def __init__(self, *a, **kw):
389a1709e4aSPatrick Williams        self.members = kw.pop("members")
39005b0c1eeSBrad Bishop        super(Group, self).__init__(**kw)
39105b0c1eeSBrad Bishop
39205b0c1eeSBrad Bishop
39305b0c1eeSBrad Bishopclass ImplicitGroup(Group):
394a1709e4aSPatrick Williams    """Provide a factory method for groups whose members are
395a1709e4aSPatrick Williams    not explicitly declared in the config files."""
39605b0c1eeSBrad Bishop
39705b0c1eeSBrad Bishop    def __init__(self, *a, **kw):
39805b0c1eeSBrad Bishop        super(ImplicitGroup, self).__init__(**kw)
39905b0c1eeSBrad Bishop
40005b0c1eeSBrad Bishop    def factory(self, objs):
401a1709e4aSPatrick Williams        """Create group members."""
40205b0c1eeSBrad Bishop
403a1709e4aSPatrick Williams        factory = Everything.classmap(self.subclass, "element")
40405b0c1eeSBrad Bishop        for m in self.members:
40505b0c1eeSBrad Bishop            args = {
406a1709e4aSPatrick Williams                "class": self.subclass,
407a1709e4aSPatrick Williams                self.subclass: "element",
408a1709e4aSPatrick Williams                "name": m,
40905b0c1eeSBrad Bishop            }
41005b0c1eeSBrad Bishop
41105b0c1eeSBrad Bishop            obj = factory(configfile=self.configfile, **args)
41205b0c1eeSBrad Bishop            add_unique(obj, objs)
41305b0c1eeSBrad Bishop            obj.factory(objs)
41405b0c1eeSBrad Bishop
41505b0c1eeSBrad Bishop        super(ImplicitGroup, self).factory(objs)
41605b0c1eeSBrad Bishop
41705b0c1eeSBrad Bishop
4180e7df131SBrad Bishopclass GroupOfPaths(ImplicitGroup):
419a1709e4aSPatrick Williams    """Path group config file directive."""
4200e7df131SBrad Bishop
4210e7df131SBrad Bishop    def __init__(self, *a, **kw):
4220e7df131SBrad Bishop        super(GroupOfPaths, self).__init__(**kw)
4230e7df131SBrad Bishop
4240e7df131SBrad Bishop    def setup(self, objs):
425a1709e4aSPatrick Williams        """Resolve group members."""
4260e7df131SBrad Bishop
4270e7df131SBrad Bishop        def map_member(x):
428a1709e4aSPatrick Williams            path = get_index(objs, "pathname", x["path"])
429a1709e4aSPatrick Williams            meta = get_index(objs, "meta", x["meta"])
4300e7df131SBrad Bishop            return (path, meta)
4310e7df131SBrad Bishop
432a1709e4aSPatrick Williams        self.members = map(map_member, self.members)
4330e7df131SBrad Bishop
4340e7df131SBrad Bishop        super(GroupOfPaths, self).setup(objs)
4350e7df131SBrad Bishop
4360e7df131SBrad Bishop
437e73b2c35SBrad Bishopclass GroupOfProperties(ImplicitGroup):
438a1709e4aSPatrick Williams    """Property group config file directive."""
439e73b2c35SBrad Bishop
440e73b2c35SBrad Bishop    def __init__(self, *a, **kw):
441a1709e4aSPatrick Williams        self.type = kw.pop("type")
442e73b2c35SBrad Bishop        self.datatype = sdbusplus.property.Property(
443a1709e4aSPatrick Williams            name=kw.get("name"), type=self.type
444a1709e4aSPatrick Williams        ).cppTypeName
445e73b2c35SBrad Bishop
446e73b2c35SBrad Bishop        super(GroupOfProperties, self).__init__(**kw)
447e73b2c35SBrad Bishop
448e73b2c35SBrad Bishop    def setup(self, objs):
449a1709e4aSPatrick Williams        """Resolve group members."""
450e73b2c35SBrad Bishop
451e73b2c35SBrad Bishop        def map_member(x):
452a1709e4aSPatrick Williams            iface = get_index(objs, "interface", x["interface"])
453a1709e4aSPatrick Williams            prop = get_index(objs, "propertyname", x["property"])
454a1709e4aSPatrick Williams            meta = get_index(objs, "meta", x["meta"])
455e73b2c35SBrad Bishop
456e73b2c35SBrad Bishop            return (iface, prop, meta)
457e73b2c35SBrad Bishop
458a1709e4aSPatrick Williams        self.members = map(map_member, self.members)
459e73b2c35SBrad Bishop
460e73b2c35SBrad Bishop        super(GroupOfProperties, self).setup(objs)
461e73b2c35SBrad Bishop
462e73b2c35SBrad Bishop
4634b916f13SBrad Bishopclass GroupOfInstances(ImplicitGroup):
464a1709e4aSPatrick Williams    """A group of property instances."""
4654b916f13SBrad Bishop
4664b916f13SBrad Bishop    def __init__(self, *a, **kw):
4674b916f13SBrad Bishop        super(GroupOfInstances, self).__init__(**kw)
4684b916f13SBrad Bishop
4694b916f13SBrad Bishop    def setup(self, objs):
470a1709e4aSPatrick Williams        """Resolve group members."""
4714b916f13SBrad Bishop
4724b916f13SBrad Bishop        def map_member(x):
473a1709e4aSPatrick Williams            path = get_index(objs, "pathname", x["path"]["path"])
474a1709e4aSPatrick Williams            pathmeta = get_index(objs, "meta", x["path"]["meta"])
4754b916f13SBrad Bishop            interface = get_index(
476a1709e4aSPatrick Williams                objs, "interface", x["property"]["interface"]
477a1709e4aSPatrick Williams            )
478a1709e4aSPatrick Williams            prop = get_index(objs, "propertyname", x["property"]["property"])
479a1709e4aSPatrick Williams            propmeta = get_index(objs, "meta", x["property"]["meta"])
480a1709e4aSPatrick Williams            instance = get_index(objs, "instance", x)
4814b916f13SBrad Bishop
4824b916f13SBrad Bishop            return (path, pathmeta, interface, prop, propmeta, instance)
4834b916f13SBrad Bishop
484a1709e4aSPatrick Williams        self.members = map(map_member, self.members)
4854b916f13SBrad Bishop
4864b916f13SBrad Bishop        super(GroupOfInstances, self).setup(objs)
4874b916f13SBrad Bishop
488a1709e4aSPatrick Williams
48980c70610SMarri Devender Raoclass GroupOfPathInstances(ImplicitGroup):
490a1709e4aSPatrick Williams    """A group of path instances."""
49180c70610SMarri Devender Rao
49280c70610SMarri Devender Rao    def __init__(self, *a, **kw):
49380c70610SMarri Devender Rao        super(GroupOfPathInstances, self).__init__(**kw)
49480c70610SMarri Devender Rao
49580c70610SMarri Devender Rao    def setup(self, objs):
496a1709e4aSPatrick Williams        """Resolve group members."""
49780c70610SMarri Devender Rao
49880c70610SMarri Devender Rao        def map_member(x):
499a1709e4aSPatrick Williams            path = get_index(objs, "pathname", x["path"]["path"])
500a1709e4aSPatrick Williams            pathmeta = get_index(objs, "meta", x["path"]["meta"])
501a1709e4aSPatrick Williams            pathinstance = get_index(objs, "pathinstance", x)
50280c70610SMarri Devender Rao            return (path, pathmeta, pathinstance)
50380c70610SMarri Devender Rao
504a1709e4aSPatrick Williams        self.members = map(map_member, self.members)
50580c70610SMarri Devender Rao
50680c70610SMarri Devender Rao        super(GroupOfPathInstances, self).setup(objs)
50780c70610SMarri Devender Rao
5084b916f13SBrad Bishop
5094b916f13SBrad Bishopclass HasPropertyIndex(ConfigEntry):
510a1709e4aSPatrick Williams    """Handle config file directives that require an index to be
511a1709e4aSPatrick Williams    constructed."""
5124b916f13SBrad Bishop
5134b916f13SBrad Bishop    def __init__(self, *a, **kw):
514a1709e4aSPatrick Williams        self.paths = kw.pop("paths")
515a1709e4aSPatrick Williams        self.properties = kw.pop("properties")
5164b916f13SBrad Bishop        super(HasPropertyIndex, self).__init__(**kw)
5174b916f13SBrad Bishop
5184b916f13SBrad Bishop    def factory(self, objs):
519a1709e4aSPatrick Williams        """Create a group of instances for this index."""
5204b916f13SBrad Bishop
5214b916f13SBrad Bishop        members = []
5224b916f13SBrad Bishop        path_group = get_index(
523a1709e4aSPatrick Williams            objs, "pathgroup", self.paths, config=self.configfile
524a1709e4aSPatrick Williams        )
5254b916f13SBrad Bishop        property_group = get_index(
526a1709e4aSPatrick Williams            objs, "propertygroup", self.properties, config=self.configfile
527a1709e4aSPatrick Williams        )
5284b916f13SBrad Bishop
529a1709e4aSPatrick Williams        for path in objs["pathgroup"][path_group].members:
530a1709e4aSPatrick Williams            for prop in objs["propertygroup"][property_group].members:
5314b916f13SBrad Bishop                member = {
532a1709e4aSPatrick Williams                    "path": path,
533a1709e4aSPatrick Williams                    "property": prop,
5344b916f13SBrad Bishop                }
5354b916f13SBrad Bishop                members.append(member)
5364b916f13SBrad Bishop
5374b916f13SBrad Bishop        args = {
538a1709e4aSPatrick Williams            "members": members,
539a1709e4aSPatrick Williams            "class": "instancegroup",
540a1709e4aSPatrick Williams            "instancegroup": "instance",
541a1709e4aSPatrick Williams            "name": "{0} {1}".format(self.paths, self.properties),
5424b916f13SBrad Bishop        }
5434b916f13SBrad Bishop
5444b916f13SBrad Bishop        group = GroupOfInstances(configfile=self.configfile, **args)
5454b916f13SBrad Bishop        add_unique(group, objs, config=self.configfile)
5464b916f13SBrad Bishop        group.factory(objs)
5474b916f13SBrad Bishop
5484b916f13SBrad Bishop        super(HasPropertyIndex, self).factory(objs)
5494b916f13SBrad Bishop
5504b916f13SBrad Bishop    def setup(self, objs):
551a1709e4aSPatrick Williams        """Resolve path, property, and instance groups."""
5524b916f13SBrad Bishop
5534b916f13SBrad Bishop        self.instances = get_index(
5544b916f13SBrad Bishop            objs,
555a1709e4aSPatrick Williams            "instancegroup",
556a1709e4aSPatrick Williams            "{0} {1}".format(self.paths, self.properties),
557a1709e4aSPatrick Williams            config=self.configfile,
558a1709e4aSPatrick Williams        )
5594b916f13SBrad Bishop        self.paths = get_index(
560a1709e4aSPatrick Williams            objs, "pathgroup", self.paths, config=self.configfile
561a1709e4aSPatrick Williams        )
5624b916f13SBrad Bishop        self.properties = get_index(
563a1709e4aSPatrick Williams            objs, "propertygroup", self.properties, config=self.configfile
564a1709e4aSPatrick Williams        )
565a1709e4aSPatrick Williams        self.datatype = objs["propertygroup"][self.properties].datatype
566a1709e4aSPatrick Williams        self.type = objs["propertygroup"][self.properties].type
5674b916f13SBrad Bishop
5684b916f13SBrad Bishop        super(HasPropertyIndex, self).setup(objs)
5694b916f13SBrad Bishop
570a1709e4aSPatrick Williams
57180c70610SMarri Devender Raoclass HasPathIndex(ConfigEntry):
572a1709e4aSPatrick Williams    """Handle config file directives that require an index to be
573a1709e4aSPatrick Williams    constructed."""
57480c70610SMarri Devender Rao
57580c70610SMarri Devender Rao    def __init__(self, *a, **kw):
576a1709e4aSPatrick Williams        self.paths = kw.pop("paths")
57780c70610SMarri Devender Rao        super(HasPathIndex, self).__init__(**kw)
57880c70610SMarri Devender Rao
57980c70610SMarri Devender Rao    def factory(self, objs):
580a1709e4aSPatrick Williams        """Create a group of instances for this index."""
58180c70610SMarri Devender Rao
58280c70610SMarri Devender Rao        members = []
58380c70610SMarri Devender Rao        path_group = get_index(
584a1709e4aSPatrick Williams            objs, "pathgroup", self.paths, config=self.configfile
585a1709e4aSPatrick Williams        )
58680c70610SMarri Devender Rao
587a1709e4aSPatrick Williams        for path in objs["pathgroup"][path_group].members:
58880c70610SMarri Devender Rao            member = {
589a1709e4aSPatrick Williams                "path": path,
59080c70610SMarri Devender Rao            }
59180c70610SMarri Devender Rao            members.append(member)
59280c70610SMarri Devender Rao
59380c70610SMarri Devender Rao        args = {
594a1709e4aSPatrick Williams            "members": members,
595a1709e4aSPatrick Williams            "class": "pathinstancegroup",
596a1709e4aSPatrick Williams            "pathinstancegroup": "pathinstance",
597a1709e4aSPatrick Williams            "name": "{0}".format(self.paths),
59880c70610SMarri Devender Rao        }
59980c70610SMarri Devender Rao
60080c70610SMarri Devender Rao        group = GroupOfPathInstances(configfile=self.configfile, **args)
60180c70610SMarri Devender Rao        add_unique(group, objs, config=self.configfile)
60280c70610SMarri Devender Rao        group.factory(objs)
60380c70610SMarri Devender Rao
60480c70610SMarri Devender Rao        super(HasPathIndex, self).factory(objs)
60580c70610SMarri Devender Rao
60680c70610SMarri Devender Rao    def setup(self, objs):
607a1709e4aSPatrick Williams        """Resolve path and instance groups."""
60880c70610SMarri Devender Rao
60980c70610SMarri Devender Rao        self.pathinstances = get_index(
61080c70610SMarri Devender Rao            objs,
611a1709e4aSPatrick Williams            "pathinstancegroup",
612a1709e4aSPatrick Williams            "{0}".format(self.paths),
613a1709e4aSPatrick Williams            config=self.configfile,
614a1709e4aSPatrick Williams        )
61580c70610SMarri Devender Rao        self.paths = get_index(
616a1709e4aSPatrick Williams            objs, "pathgroup", self.paths, config=self.configfile
617a1709e4aSPatrick Williams        )
61880c70610SMarri Devender Rao        super(HasPathIndex, self).setup(objs)
6194b916f13SBrad Bishop
620a1709e4aSPatrick Williams
621efe0158cSMatthew Barthclass GroupOfFilters(ConfigEntry):
622a1709e4aSPatrick Williams    """Handle config file directives that require an index for filters."""
623efe0158cSMatthew Barth
624efe0158cSMatthew Barth    def __init__(self, *a, **kw):
625efe0158cSMatthew Barth        # Pop filters data for adding to the available filters array
626a1709e4aSPatrick Williams        self.type = kw.pop("type")
627a1709e4aSPatrick Williams        self.datatype = kw.pop("datatype", None)
628a1709e4aSPatrick Williams        self.filters = kw.pop("filters", None)
629efe0158cSMatthew Barth
630efe0158cSMatthew Barth        super(GroupOfFilters, self).__init__(**kw)
631efe0158cSMatthew Barth
632efe0158cSMatthew Barth    def factory(self, objs):
633a1709e4aSPatrick Williams        """Modify filters to add the property value type and
634a1709e4aSPatrick Williams        make them of operation argument type."""
635efe0158cSMatthew Barth        if self.filters:
636efe0158cSMatthew Barth            # 'type' used within OpArgument to generate filter
637efe0158cSMatthew Barth            # argument values so add to each filter
638efe0158cSMatthew Barth            for f in self.filters:
639a1709e4aSPatrick Williams                f["type"] = self.type
640efe0158cSMatthew Barth            self.filters = [OpArgument(**x) for x in self.filters]
641efe0158cSMatthew Barth
642efe0158cSMatthew Barth        super(GroupOfFilters, self).factory(objs)
643efe0158cSMatthew Barth
644a1709e4aSPatrick Williams
6454b916f13SBrad Bishopclass PropertyWatch(HasPropertyIndex):
646a1709e4aSPatrick Williams    """Handle the property watch config file directive."""
6474b916f13SBrad Bishop
6484b916f13SBrad Bishop    def __init__(self, *a, **kw):
649efe0158cSMatthew Barth        # Pop optional filters for the properties being watched
650a1709e4aSPatrick Williams        self.filters = kw.pop("filters", None)
651a1709e4aSPatrick Williams        self.callback = kw.pop("callback", None)
652a1709e4aSPatrick Williams        self.ignore_start_callback = kw.pop("ignore_start_callback", False)
653a1709e4aSPatrick Williams        self.ignore_start_callback = (
654a1709e4aSPatrick Williams            "true" if self.ignore_start_callback else "false"
655a1709e4aSPatrick Williams        )
6564b916f13SBrad Bishop        super(PropertyWatch, self).__init__(**kw)
6574b916f13SBrad Bishop
658efe0158cSMatthew Barth    def factory(self, objs):
659a1709e4aSPatrick Williams        """Create any filters for this property watch."""
660efe0158cSMatthew Barth
661efe0158cSMatthew Barth        if self.filters:
662efe0158cSMatthew Barth            # Get the datatype(i.e. "int64_t") of the properties in this watch
663efe0158cSMatthew Barth            # (Made available after all `super` classes init'd)
664a1709e4aSPatrick Williams            datatype = objs["propertygroup"][
665a1709e4aSPatrick Williams                get_index(
666efe0158cSMatthew Barth                    objs,
667a1709e4aSPatrick Williams                    "propertygroup",
668efe0158cSMatthew Barth                    self.properties,
669a1709e4aSPatrick Williams                    config=self.configfile,
670a1709e4aSPatrick Williams                )
671a1709e4aSPatrick Williams            ].datatype
672efe0158cSMatthew Barth            # Get the type(i.e. "int64") of the properties in this watch
673efe0158cSMatthew Barth            # (Made available after all `super` classes init'd)
674a1709e4aSPatrick Williams            type = objs["propertygroup"][
675a1709e4aSPatrick Williams                get_index(
676efe0158cSMatthew Barth                    objs,
677a1709e4aSPatrick Williams                    "propertygroup",
678efe0158cSMatthew Barth                    self.properties,
679a1709e4aSPatrick Williams                    config=self.configfile,
680a1709e4aSPatrick Williams                )
681a1709e4aSPatrick Williams            ].type
682efe0158cSMatthew Barth            # Construct the data needed to make the filters for
683efe0158cSMatthew Barth            # this watch available.
684efe0158cSMatthew Barth            # *Note: 'class', 'subclass', 'name' are required for
685efe0158cSMatthew Barth            # storing the filter data(i.e. 'type', 'datatype', & 'filters')
686efe0158cSMatthew Barth            args = {
687a1709e4aSPatrick Williams                "type": type,
688a1709e4aSPatrick Williams                "datatype": datatype,
689a1709e4aSPatrick Williams                "filters": self.filters,
690a1709e4aSPatrick Williams                "class": "filtersgroup",
691a1709e4aSPatrick Williams                "filtersgroup": "filters",
692a1709e4aSPatrick Williams                "name": self.name,
693efe0158cSMatthew Barth            }
694efe0158cSMatthew Barth            # Init GroupOfFilters class with this watch's filters' arguments
695efe0158cSMatthew Barth            group = GroupOfFilters(configfile=self.configfile, **args)
696efe0158cSMatthew Barth            # Store this group of filters so it can be indexed later
697efe0158cSMatthew Barth            add_unique(group, objs, config=self.configfile)
698efe0158cSMatthew Barth            group.factory(objs)
699efe0158cSMatthew Barth
700efe0158cSMatthew Barth        super(PropertyWatch, self).factory(objs)
701efe0158cSMatthew Barth
702fccdc39fSBrad Bishop    def setup(self, objs):
703a1709e4aSPatrick Williams        """Resolve optional filters and callback."""
704efe0158cSMatthew Barth
705efe0158cSMatthew Barth        if self.filters:
706efe0158cSMatthew Barth            # Watch has filters, provide array index to access them
707efe0158cSMatthew Barth            self.filters = get_index(
708a1709e4aSPatrick Williams                objs, "filtersgroup", self.name, config=self.configfile
709a1709e4aSPatrick Williams            )
710fccdc39fSBrad Bishop
711fccdc39fSBrad Bishop        if self.callback:
712fccdc39fSBrad Bishop            self.callback = get_index(
713a1709e4aSPatrick Williams                objs, "callback", self.callback, config=self.configfile
714a1709e4aSPatrick Williams            )
715fccdc39fSBrad Bishop
716fccdc39fSBrad Bishop        super(PropertyWatch, self).setup(objs)
717fccdc39fSBrad Bishop
718a1709e4aSPatrick Williams
71980c70610SMarri Devender Raoclass PathWatch(HasPathIndex):
720a1709e4aSPatrick Williams    """Handle the path watch config file directive."""
72180c70610SMarri Devender Rao
72280c70610SMarri Devender Rao    def __init__(self, *a, **kw):
723a1709e4aSPatrick Williams        self.pathcallback = kw.pop("pathcallback", None)
72480c70610SMarri Devender Rao        super(PathWatch, self).__init__(**kw)
72580c70610SMarri Devender Rao
72680c70610SMarri Devender Rao    def setup(self, objs):
727a1709e4aSPatrick Williams        """Resolve optional callback."""
72880c70610SMarri Devender Rao        if self.pathcallback:
72980c70610SMarri Devender Rao            self.pathcallback = get_index(
730a1709e4aSPatrick Williams                objs, "pathcallback", self.pathcallback, config=self.configfile
731a1709e4aSPatrick Williams            )
73280c70610SMarri Devender Rao        super(PathWatch, self).setup(objs)
73380c70610SMarri Devender Rao
734a1709e4aSPatrick Williams
735c1283ae8SBrad Bishopclass Callback(HasPropertyIndex):
736a1709e4aSPatrick Williams    """Interface and common logic for callbacks."""
737c1283ae8SBrad Bishop
738c1283ae8SBrad Bishop    def __init__(self, *a, **kw):
739c1283ae8SBrad Bishop        super(Callback, self).__init__(**kw)
740c1283ae8SBrad Bishop
741a1709e4aSPatrick Williams
74280c70610SMarri Devender Raoclass PathCallback(HasPathIndex):
743a1709e4aSPatrick Williams    """Interface and common logic for callbacks."""
74480c70610SMarri Devender Rao
74580c70610SMarri Devender Rao    def __init__(self, *a, **kw):
74680c70610SMarri Devender Rao        super(PathCallback, self).__init__(**kw)
747c1283ae8SBrad Bishop
748a1709e4aSPatrick Williams
7494041d720SBrad Bishopclass ConditionCallback(ConfigEntry, Renderer):
750a1709e4aSPatrick Williams    """Handle the journal callback config file directive."""
7514041d720SBrad Bishop
7524041d720SBrad Bishop    def __init__(self, *a, **kw):
753a1709e4aSPatrick Williams        self.condition = kw.pop("condition")
754a1709e4aSPatrick Williams        self.instance = kw.pop("instance")
755a1709e4aSPatrick Williams        self.defer = kw.pop("defer", None)
7564041d720SBrad Bishop        super(ConditionCallback, self).__init__(**kw)
7574041d720SBrad Bishop
7584041d720SBrad Bishop    def factory(self, objs):
759a1709e4aSPatrick Williams        """Create a graph instance for this callback."""
7604041d720SBrad Bishop
7614041d720SBrad Bishop        args = {
762a1709e4aSPatrick Williams            "configfile": self.configfile,
763a1709e4aSPatrick Williams            "members": [self.instance],
764a1709e4aSPatrick Williams            "class": "callbackgroup",
765a1709e4aSPatrick Williams            "callbackgroup": "callback",
766a1709e4aSPatrick Williams            "name": [self.instance],
7674041d720SBrad Bishop        }
7684041d720SBrad Bishop
7694041d720SBrad Bishop        entry = CallbackGraphEntry(**args)
7704041d720SBrad Bishop        add_unique(entry, objs, config=self.configfile)
7714041d720SBrad Bishop
7724041d720SBrad Bishop        super(ConditionCallback, self).factory(objs)
7734041d720SBrad Bishop
7744041d720SBrad Bishop    def setup(self, objs):
775a1709e4aSPatrick Williams        """Resolve condition and graph entry."""
7764041d720SBrad Bishop
7774041d720SBrad Bishop        self.graph = get_index(
778a1709e4aSPatrick Williams            objs, "callbackgroup", [self.instance], config=self.configfile
779a1709e4aSPatrick Williams        )
7804041d720SBrad Bishop
7814041d720SBrad Bishop        self.condition = get_index(
782a1709e4aSPatrick Williams            objs, "condition", self.name, config=self.configfile
783a1709e4aSPatrick Williams        )
7844041d720SBrad Bishop
7854041d720SBrad Bishop        super(ConditionCallback, self).setup(objs)
7864041d720SBrad Bishop
7874041d720SBrad Bishop    def construct(self, loader, indent):
7884041d720SBrad Bishop        return self.render(
789a1709e4aSPatrick Williams            loader, "conditional.mako.cpp", c=self, indent=indent
790a1709e4aSPatrick Williams        )
7914041d720SBrad Bishop
7924041d720SBrad Bishop
7934041d720SBrad Bishopclass Condition(HasPropertyIndex):
794a1709e4aSPatrick Williams    """Interface and common logic for conditions."""
7954041d720SBrad Bishop
7964041d720SBrad Bishop    def __init__(self, *a, **kw):
797a1709e4aSPatrick Williams        self.callback = kw.pop("callback")
798a1709e4aSPatrick Williams        self.defer = kw.pop("defer", None)
7994041d720SBrad Bishop        super(Condition, self).__init__(**kw)
8004041d720SBrad Bishop
8014041d720SBrad Bishop    def factory(self, objs):
802a1709e4aSPatrick Williams        """Create a callback instance for this conditional."""
8034041d720SBrad Bishop
8044041d720SBrad Bishop        args = {
805a1709e4aSPatrick Williams            "configfile": self.configfile,
806a1709e4aSPatrick Williams            "condition": self.name,
807a1709e4aSPatrick Williams            "class": "callback",
808a1709e4aSPatrick Williams            "callback": "conditional",
809a1709e4aSPatrick Williams            "instance": self.callback,
810a1709e4aSPatrick Williams            "name": self.name,
811a1709e4aSPatrick Williams            "defer": self.defer,
8124041d720SBrad Bishop        }
8134041d720SBrad Bishop
8144041d720SBrad Bishop        callback = ConditionCallback(**args)
8154041d720SBrad Bishop        add_unique(callback, objs, config=self.configfile)
8164041d720SBrad Bishop        callback.factory(objs)
8174041d720SBrad Bishop
8184041d720SBrad Bishop        super(Condition, self).factory(objs)
8194041d720SBrad Bishop
8204041d720SBrad Bishop
8214041d720SBrad Bishopclass CountCondition(Condition, Renderer):
822a1709e4aSPatrick Williams    """Handle the count condition config file directive."""
8234041d720SBrad Bishop
8244041d720SBrad Bishop    def __init__(self, *a, **kw):
825a1709e4aSPatrick Williams        self.countop = kw.pop("countop")
826a1709e4aSPatrick Williams        self.countbound = kw.pop("countbound")
827a1709e4aSPatrick Williams        self.op = kw.pop("op")
828a1709e4aSPatrick Williams        self.bound = kw.pop("bound")
829c458deeaSMatt Spinler        self.oneshot = TrivialArgument(
830a1709e4aSPatrick Williams            type="boolean", value=kw.pop("oneshot", False)
831a1709e4aSPatrick Williams        )
8324041d720SBrad Bishop        super(CountCondition, self).__init__(**kw)
8334041d720SBrad Bishop
834ec2ed2fbSBrad Bishop    def setup(self, objs):
835a1709e4aSPatrick Williams        """Resolve type."""
836ec2ed2fbSBrad Bishop
837ec2ed2fbSBrad Bishop        super(CountCondition, self).setup(objs)
838a1709e4aSPatrick Williams        self.bound = TrivialArgument(type=self.type, value=self.bound)
839ec2ed2fbSBrad Bishop
8404041d720SBrad Bishop    def construct(self, loader, indent):
841a1709e4aSPatrick Williams        return self.render(loader, "count.mako.cpp", c=self, indent=indent)
8424041d720SBrad Bishop
8434041d720SBrad Bishop
844efdd03c2SMatthew Barthclass MedianCondition(Condition, Renderer):
845a1709e4aSPatrick Williams    """Handle the median condition config file directive."""
846efdd03c2SMatthew Barth
847efdd03c2SMatthew Barth    def __init__(self, *a, **kw):
848a1709e4aSPatrick Williams        self.op = kw.pop("op")
849a1709e4aSPatrick Williams        self.bound = kw.pop("bound")
850efdd03c2SMatthew Barth        self.oneshot = TrivialArgument(
851a1709e4aSPatrick Williams            type="boolean", value=kw.pop("oneshot", False)
852a1709e4aSPatrick Williams        )
853efdd03c2SMatthew Barth        super(MedianCondition, self).__init__(**kw)
854efdd03c2SMatthew Barth
855efdd03c2SMatthew Barth    def setup(self, objs):
856a1709e4aSPatrick Williams        """Resolve type."""
857efdd03c2SMatthew Barth
858efdd03c2SMatthew Barth        super(MedianCondition, self).setup(objs)
859a1709e4aSPatrick Williams        self.bound = TrivialArgument(type=self.type, value=self.bound)
860efdd03c2SMatthew Barth
861efdd03c2SMatthew Barth    def construct(self, loader, indent):
862a1709e4aSPatrick Williams        return self.render(loader, "median.mako.cpp", c=self, indent=indent)
863efdd03c2SMatthew Barth
864efdd03c2SMatthew Barth
865c1283ae8SBrad Bishopclass Journal(Callback, Renderer):
866a1709e4aSPatrick Williams    """Handle the journal callback config file directive."""
867c1283ae8SBrad Bishop
868c1283ae8SBrad Bishop    def __init__(self, *a, **kw):
869a1709e4aSPatrick Williams        self.severity = kw.pop("severity")
870a1709e4aSPatrick Williams        self.message = kw.pop("message")
871c1283ae8SBrad Bishop        super(Journal, self).__init__(**kw)
872c1283ae8SBrad Bishop
873c1283ae8SBrad Bishop    def construct(self, loader, indent):
874a1709e4aSPatrick Williams        return self.render(loader, "journal.mako.cpp", c=self, indent=indent)
875c1283ae8SBrad Bishop
876c1283ae8SBrad Bishop
877d5faea31SGunnar Millsclass Elog(Callback, Renderer):
878a1709e4aSPatrick Williams    """Handle the elog callback config file directive."""
879d5faea31SGunnar Mills
880d5faea31SGunnar Mills    def __init__(self, *a, **kw):
881a1709e4aSPatrick Williams        self.error = kw.pop("error")
882a1709e4aSPatrick Williams        self.metadata = [Metadata(**x) for x in kw.pop("metadata", {})]
883d5faea31SGunnar Mills        super(Elog, self).__init__(**kw)
884d5faea31SGunnar Mills
885d5faea31SGunnar Mills    def construct(self, loader, indent):
886a1709e4aSPatrick Williams        with open(args.gen_errors, "a") as fd:
887a1709e4aSPatrick Williams            fd.write(self.render(loader, "errors.mako.hpp", c=self))
888a1709e4aSPatrick Williams        return self.render(loader, "elog.mako.cpp", c=self, indent=indent)
889a1709e4aSPatrick Williams
890d5faea31SGunnar Mills
89190bfaea4SRatan Guptaclass Event(Callback, Renderer):
892a1709e4aSPatrick Williams    """Handle the event callback config file directive."""
89390bfaea4SRatan Gupta
89490bfaea4SRatan Gupta    def __init__(self, *a, **kw):
895a1709e4aSPatrick Williams        self.eventName = kw.pop("eventName")
896a1709e4aSPatrick Williams        self.eventMessage = kw.pop("eventMessage")
89790bfaea4SRatan Gupta        super(Event, self).__init__(**kw)
89890bfaea4SRatan Gupta
89990bfaea4SRatan Gupta    def construct(self, loader, indent):
900a1709e4aSPatrick Williams        return self.render(loader, "event.mako.cpp", c=self, indent=indent)
901a1709e4aSPatrick Williams
902d5faea31SGunnar Mills
90380c70610SMarri Devender Raoclass EventPath(PathCallback, Renderer):
904a1709e4aSPatrick Williams    """Handle the event path callback config file directive."""
90580c70610SMarri Devender Rao
90680c70610SMarri Devender Rao    def __init__(self, *a, **kw):
907a1709e4aSPatrick Williams        self.eventType = kw.pop("eventType")
90880c70610SMarri Devender Rao        super(EventPath, self).__init__(**kw)
90980c70610SMarri Devender Rao
91080c70610SMarri Devender Rao    def construct(self, loader, indent):
911a1709e4aSPatrick Williams        return self.render(loader, "eventpath.mako.cpp", c=self, indent=indent)
912a1709e4aSPatrick Williams
9133c5318d8SMatt Spinler
9143c5318d8SMatt Spinlerclass ElogWithMetadata(Callback, Renderer):
915a1709e4aSPatrick Williams    """Handle the elog_with_metadata callback config file directive."""
9163c5318d8SMatt Spinler
9173c5318d8SMatt Spinler    def __init__(self, *a, **kw):
918a1709e4aSPatrick Williams        self.error = kw.pop("error")
919a1709e4aSPatrick Williams        self.metadata = kw.pop("metadata")
9203c5318d8SMatt Spinler        super(ElogWithMetadata, self).__init__(**kw)
9213c5318d8SMatt Spinler
9223c5318d8SMatt Spinler    def construct(self, loader, indent):
923a1709e4aSPatrick Williams        with open(args.gen_errors, "a") as fd:
924a1709e4aSPatrick Williams            fd.write(self.render(loader, "errors.mako.hpp", c=self))
9253c5318d8SMatt Spinler        return self.render(
926a1709e4aSPatrick Williams            loader, "elog_with_metadata.mako.cpp", c=self, indent=indent
927a1709e4aSPatrick Williams        )
9283c5318d8SMatt Spinler
9293c5318d8SMatt Spinler
9301d6ca484SMatt Spinlerclass ResolveCallout(Callback, Renderer):
931a1709e4aSPatrick Williams    """Handle the 'resolve callout' callback config file directive."""
9321d6ca484SMatt Spinler
9331d6ca484SMatt Spinler    def __init__(self, *a, **kw):
934a1709e4aSPatrick Williams        self.callout = kw.pop("callout")
9351d6ca484SMatt Spinler        super(ResolveCallout, self).__init__(**kw)
9361d6ca484SMatt Spinler
9371d6ca484SMatt Spinler    def construct(self, loader, indent):
9381d6ca484SMatt Spinler        return self.render(
939a1709e4aSPatrick Williams            loader, "resolve_errors.mako.cpp", c=self, indent=indent
940a1709e4aSPatrick Williams        )
9411d6ca484SMatt Spinler
9421d6ca484SMatt Spinler
9430df00be0SBrad Bishopclass Method(ConfigEntry, Renderer):
944a1709e4aSPatrick Williams    """Handle the method callback config file directive."""
9450df00be0SBrad Bishop
9460df00be0SBrad Bishop    def __init__(self, *a, **kw):
947a1709e4aSPatrick Williams        self.service = kw.pop("service")
948a1709e4aSPatrick Williams        self.path = kw.pop("path")
949a1709e4aSPatrick Williams        self.interface = kw.pop("interface")
950a1709e4aSPatrick Williams        self.method = kw.pop("method")
951a1709e4aSPatrick Williams        self.args = [TrivialArgument(**x) for x in kw.pop("args", {})]
9520df00be0SBrad Bishop        super(Method, self).__init__(**kw)
9530df00be0SBrad Bishop
9540df00be0SBrad Bishop    def factory(self, objs):
9550df00be0SBrad Bishop        args = {
956a1709e4aSPatrick Williams            "class": "interface",
957a1709e4aSPatrick Williams            "interface": "element",
958a1709e4aSPatrick Williams            "name": self.service,
9590df00be0SBrad Bishop        }
960a1709e4aSPatrick Williams        add_unique(ConfigEntry(configfile=self.configfile, **args), objs)
961a1709e4aSPatrick Williams
962a1709e4aSPatrick Williams        args = {"class": "pathname", "pathname": "element", "name": self.path}
963a1709e4aSPatrick Williams        add_unique(ConfigEntry(configfile=self.configfile, **args), objs)
9640df00be0SBrad Bishop
9650df00be0SBrad Bishop        args = {
966a1709e4aSPatrick Williams            "class": "interface",
967a1709e4aSPatrick Williams            "interface": "element",
968a1709e4aSPatrick Williams            "name": self.interface,
9690df00be0SBrad Bishop        }
970a1709e4aSPatrick Williams        add_unique(ConfigEntry(configfile=self.configfile, **args), objs)
9710df00be0SBrad Bishop
9720df00be0SBrad Bishop        args = {
973a1709e4aSPatrick Williams            "class": "propertyname",
974a1709e4aSPatrick Williams            "propertyname": "element",
975a1709e4aSPatrick Williams            "name": self.method,
9760df00be0SBrad Bishop        }
977a1709e4aSPatrick Williams        add_unique(ConfigEntry(configfile=self.configfile, **args), objs)
9780df00be0SBrad Bishop
9790df00be0SBrad Bishop        super(Method, self).factory(objs)
9800df00be0SBrad Bishop
9810df00be0SBrad Bishop    def setup(self, objs):
982a1709e4aSPatrick Williams        """Resolve elements."""
9830df00be0SBrad Bishop
984a1709e4aSPatrick Williams        self.service = get_index(objs, "interface", self.service)
9850df00be0SBrad Bishop
986a1709e4aSPatrick Williams        self.path = get_index(objs, "pathname", self.path)
9870df00be0SBrad Bishop
988a1709e4aSPatrick Williams        self.interface = get_index(objs, "interface", self.interface)
9890df00be0SBrad Bishop
990a1709e4aSPatrick Williams        self.method = get_index(objs, "propertyname", self.method)
9910df00be0SBrad Bishop
9920df00be0SBrad Bishop        super(Method, self).setup(objs)
9930df00be0SBrad Bishop
9940df00be0SBrad Bishop    def construct(self, loader, indent):
995a1709e4aSPatrick Williams        return self.render(loader, "method.mako.cpp", c=self, indent=indent)
9960df00be0SBrad Bishop
9970df00be0SBrad Bishop
99849e66175SBrad Bishopclass CallbackGraphEntry(Group):
999a1709e4aSPatrick Williams    """An entry in a traversal list for groups of callbacks."""
100049e66175SBrad Bishop
100149e66175SBrad Bishop    def __init__(self, *a, **kw):
100249e66175SBrad Bishop        super(CallbackGraphEntry, self).__init__(**kw)
100349e66175SBrad Bishop
100449e66175SBrad Bishop    def setup(self, objs):
1005a1709e4aSPatrick Williams        """Resolve group members."""
100649e66175SBrad Bishop
100749e66175SBrad Bishop        def map_member(x):
1008a1709e4aSPatrick Williams            return get_index(objs, "callback", x, config=self.configfile)
100949e66175SBrad Bishop
1010a1709e4aSPatrick Williams        self.members = map(map_member, self.members)
101149e66175SBrad Bishop
101249e66175SBrad Bishop        super(CallbackGraphEntry, self).setup(objs)
101349e66175SBrad Bishop
1014a1709e4aSPatrick Williams
101580c70610SMarri Devender Raoclass PathCallbackGraphEntry(Group):
1016a1709e4aSPatrick Williams    """An entry in a traversal list for groups of callbacks."""
101780c70610SMarri Devender Rao
101880c70610SMarri Devender Rao    def __init__(self, *a, **kw):
101980c70610SMarri Devender Rao        super(PathCallbackGraphEntry, self).__init__(**kw)
102080c70610SMarri Devender Rao
102180c70610SMarri Devender Rao    def setup(self, objs):
1022a1709e4aSPatrick Williams        """Resolve group members."""
102380c70610SMarri Devender Rao
102480c70610SMarri Devender Rao        def map_member(x):
1025a1709e4aSPatrick Williams            return get_index(objs, "pathcallback", x, config=self.configfile)
102680c70610SMarri Devender Rao
1027a1709e4aSPatrick Williams        self.members = map(map_member, self.members)
102880c70610SMarri Devender Rao
102980c70610SMarri Devender Rao        super(PathCallbackGraphEntry, self).setup(objs)
103049e66175SBrad Bishop
1031a1709e4aSPatrick Williams
103249e66175SBrad Bishopclass GroupOfCallbacks(ConfigEntry, Renderer):
1033a1709e4aSPatrick Williams    """Handle the callback group config file directive."""
103449e66175SBrad Bishop
103549e66175SBrad Bishop    def __init__(self, *a, **kw):
1036a1709e4aSPatrick Williams        self.members = kw.pop("members")
103749e66175SBrad Bishop        super(GroupOfCallbacks, self).__init__(**kw)
103849e66175SBrad Bishop
103949e66175SBrad Bishop    def factory(self, objs):
1040a1709e4aSPatrick Williams        """Create a graph instance for this group of callbacks."""
104149e66175SBrad Bishop
104249e66175SBrad Bishop        args = {
1043a1709e4aSPatrick Williams            "configfile": self.configfile,
1044a1709e4aSPatrick Williams            "members": self.members,
1045a1709e4aSPatrick Williams            "class": "callbackgroup",
1046a1709e4aSPatrick Williams            "callbackgroup": "callback",
1047a1709e4aSPatrick Williams            "name": self.members,
104849e66175SBrad Bishop        }
104949e66175SBrad Bishop
105049e66175SBrad Bishop        entry = CallbackGraphEntry(**args)
105149e66175SBrad Bishop        add_unique(entry, objs, config=self.configfile)
105249e66175SBrad Bishop
105349e66175SBrad Bishop        super(GroupOfCallbacks, self).factory(objs)
105449e66175SBrad Bishop
105549e66175SBrad Bishop    def setup(self, objs):
1056a1709e4aSPatrick Williams        """Resolve graph entry."""
105749e66175SBrad Bishop
105849e66175SBrad Bishop        self.graph = get_index(
1059a1709e4aSPatrick Williams            objs, "callbackgroup", self.members, config=self.configfile
1060a1709e4aSPatrick Williams        )
106149e66175SBrad Bishop
106249e66175SBrad Bishop        super(GroupOfCallbacks, self).setup(objs)
106349e66175SBrad Bishop
106449e66175SBrad Bishop    def construct(self, loader, indent):
106549e66175SBrad Bishop        return self.render(
1066a1709e4aSPatrick Williams            loader, "callbackgroup.mako.cpp", c=self, indent=indent
1067a1709e4aSPatrick Williams        )
1068a1709e4aSPatrick Williams
106949e66175SBrad Bishop
107080c70610SMarri Devender Raoclass GroupOfPathCallbacks(ConfigEntry, Renderer):
1071a1709e4aSPatrick Williams    """Handle the callback group config file directive."""
107280c70610SMarri Devender Rao
107380c70610SMarri Devender Rao    def __init__(self, *a, **kw):
1074a1709e4aSPatrick Williams        self.members = kw.pop("members")
107580c70610SMarri Devender Rao        super(GroupOfPathCallbacks, self).__init__(**kw)
107680c70610SMarri Devender Rao
107780c70610SMarri Devender Rao    def factory(self, objs):
1078a1709e4aSPatrick Williams        """Create a graph instance for this group of callbacks."""
107980c70610SMarri Devender Rao
108080c70610SMarri Devender Rao        args = {
1081a1709e4aSPatrick Williams            "configfile": self.configfile,
1082a1709e4aSPatrick Williams            "members": self.members,
1083a1709e4aSPatrick Williams            "class": "pathcallbackgroup",
1084a1709e4aSPatrick Williams            "pathcallbackgroup": "pathcallback",
1085a1709e4aSPatrick Williams            "name": self.members,
108680c70610SMarri Devender Rao        }
108780c70610SMarri Devender Rao
108880c70610SMarri Devender Rao        entry = PathCallbackGraphEntry(**args)
108980c70610SMarri Devender Rao        add_unique(entry, objs, config=self.configfile)
109080c70610SMarri Devender Rao        super(GroupOfPathCallbacks, self).factory(objs)
109180c70610SMarri Devender Rao
109280c70610SMarri Devender Rao    def setup(self, objs):
1093a1709e4aSPatrick Williams        """Resolve graph entry."""
109480c70610SMarri Devender Rao
109580c70610SMarri Devender Rao        self.graph = get_index(
1096a1709e4aSPatrick Williams            objs, "callbackpathgroup", self.members, config=self.configfile
1097a1709e4aSPatrick Williams        )
109880c70610SMarri Devender Rao
109980c70610SMarri Devender Rao        super(GroupOfPathCallbacks, self).setup(objs)
110080c70610SMarri Devender Rao
110180c70610SMarri Devender Rao    def construct(self, loader, indent):
110280c70610SMarri Devender Rao        return self.render(
1103a1709e4aSPatrick Williams            loader, "callbackpathgroup.mako.cpp", c=self, indent=indent
1104a1709e4aSPatrick Williams        )
1105a1709e4aSPatrick Williams
110649e66175SBrad Bishop
110734a7acdfSBrad Bishopclass Everything(Renderer):
1108a1709e4aSPatrick Williams    """Parse/render entry point."""
110934a7acdfSBrad Bishop
111034a7acdfSBrad Bishop    @staticmethod
111105b0c1eeSBrad Bishop    def classmap(cls, sub=None):
1112a1709e4aSPatrick Williams        """Map render item class and subclass entries to the appropriate
1113a1709e4aSPatrick Williams        handler methods."""
111405b0c1eeSBrad Bishop        class_map = {
1115a1709e4aSPatrick Williams            "path": {
1116a1709e4aSPatrick Williams                "element": Path,
11170e7df131SBrad Bishop            },
1118a1709e4aSPatrick Williams            "pathgroup": {
1119a1709e4aSPatrick Williams                "path": GroupOfPaths,
11200e7df131SBrad Bishop            },
1121a1709e4aSPatrick Williams            "propertygroup": {
1122a1709e4aSPatrick Williams                "property": GroupOfProperties,
1123e73b2c35SBrad Bishop            },
1124a1709e4aSPatrick Williams            "property": {
1125a1709e4aSPatrick Williams                "element": Property,
1126e73b2c35SBrad Bishop            },
1127a1709e4aSPatrick Williams            "watch": {
1128a1709e4aSPatrick Williams                "property": PropertyWatch,
11294b916f13SBrad Bishop            },
1130a1709e4aSPatrick Williams            "pathwatch": {
1131a1709e4aSPatrick Williams                "path": PathWatch,
113280c70610SMarri Devender Rao            },
1133a1709e4aSPatrick Williams            "instance": {
1134a1709e4aSPatrick Williams                "element": Instance,
11354b916f13SBrad Bishop            },
1136a1709e4aSPatrick Williams            "pathinstance": {
1137a1709e4aSPatrick Williams                "element": PathInstance,
113880c70610SMarri Devender Rao            },
1139a1709e4aSPatrick Williams            "callback": {
1140a1709e4aSPatrick Williams                "journal": Journal,
1141a1709e4aSPatrick Williams                "elog": Elog,
1142a1709e4aSPatrick Williams                "elog_with_metadata": ElogWithMetadata,
1143a1709e4aSPatrick Williams                "event": Event,
1144a1709e4aSPatrick Williams                "group": GroupOfCallbacks,
1145a1709e4aSPatrick Williams                "method": Method,
1146a1709e4aSPatrick Williams                "resolve callout": ResolveCallout,
1147c1283ae8SBrad Bishop            },
1148a1709e4aSPatrick Williams            "pathcallback": {
1149a1709e4aSPatrick Williams                "eventpath": EventPath,
1150a1709e4aSPatrick Williams                "grouppath": GroupOfPathCallbacks,
115180c70610SMarri Devender Rao            },
1152a1709e4aSPatrick Williams            "condition": {
1153a1709e4aSPatrick Williams                "count": CountCondition,
1154a1709e4aSPatrick Williams                "median": MedianCondition,
11554041d720SBrad Bishop            },
115605b0c1eeSBrad Bishop        }
115705b0c1eeSBrad Bishop
115805b0c1eeSBrad Bishop        if cls not in class_map:
115905b0c1eeSBrad Bishop            raise NotImplementedError('Unknown class: "{0}"'.format(cls))
116005b0c1eeSBrad Bishop        if sub not in class_map[cls]:
1161a1709e4aSPatrick Williams            raise NotImplementedError(
1162a1709e4aSPatrick Williams                'Unknown {0} type: "{1}"'.format(cls, sub)
1163a1709e4aSPatrick Williams            )
116405b0c1eeSBrad Bishop
116505b0c1eeSBrad Bishop        return class_map[cls][sub]
116605b0c1eeSBrad Bishop
116705b0c1eeSBrad Bishop    @staticmethod
116805b0c1eeSBrad Bishop    def load_one_yaml(path, fd, objs):
1169a1709e4aSPatrick Williams        """Parse a single YAML file.  Parsing occurs in three phases.
117005b0c1eeSBrad Bishop        In the first phase a factory method associated with each
117105b0c1eeSBrad Bishop        configuration file directive is invoked.  These factory
117205b0c1eeSBrad Bishop        methods generate more factory methods.  In the second
117305b0c1eeSBrad Bishop        phase the factory methods created in the first phase
117405b0c1eeSBrad Bishop        are invoked.  In the last phase a callback is invoked on
117505b0c1eeSBrad Bishop        each object created in phase two.  Typically the callback
1176a1709e4aSPatrick Williams        resolves references to other configuration file directives."""
117705b0c1eeSBrad Bishop
117805b0c1eeSBrad Bishop        factory_objs = {}
117905b0c1eeSBrad Bishop        for x in yaml.safe_load(fd.read()) or {}:
118005b0c1eeSBrad Bishop            # Create factory object for this config file directive.
1181a1709e4aSPatrick Williams            cls = x["class"]
118205b0c1eeSBrad Bishop            sub = x.get(cls)
1183a1709e4aSPatrick Williams            if cls == "group":
1184a1709e4aSPatrick Williams                cls = "{0}group".format(sub)
118505b0c1eeSBrad Bishop
118605b0c1eeSBrad Bishop            factory = Everything.classmap(cls, sub)
118705b0c1eeSBrad Bishop            obj = factory(configfile=path, **x)
118805b0c1eeSBrad Bishop
118905b0c1eeSBrad Bishop            # For a given class of directive, validate the file
119005b0c1eeSBrad Bishop            # doesn't have any duplicate names (duplicates are
119105b0c1eeSBrad Bishop            # ok across config files).
119205b0c1eeSBrad Bishop            if exists(factory_objs, obj.cls, obj.name, config=path):
119305b0c1eeSBrad Bishop                raise NotUniqueError(path, cls, obj.name)
119405b0c1eeSBrad Bishop
119505b0c1eeSBrad Bishop            factory_objs.setdefault(cls, []).append(obj)
119605b0c1eeSBrad Bishop            objs.setdefault(cls, []).append(obj)
119705b0c1eeSBrad Bishop
119805b0c1eeSBrad Bishop        for cls, items in factory_objs.items():
119905b0c1eeSBrad Bishop            for obj in items:
120005b0c1eeSBrad Bishop                # Add objects for template consumption.
120105b0c1eeSBrad Bishop                obj.factory(objs)
120205b0c1eeSBrad Bishop
120305b0c1eeSBrad Bishop    @staticmethod
120434a7acdfSBrad Bishop    def load(args):
1205a1709e4aSPatrick Williams        """Aggregate all the YAML in the input directory
1206a1709e4aSPatrick Williams        into a single aggregate."""
120734a7acdfSBrad Bishop
120805b0c1eeSBrad Bishop        objs = {}
120934a7acdfSBrad Bishop        yaml_files = filter(
1210a1709e4aSPatrick Williams            lambda x: x.endswith(".yaml"), os.listdir(args.inputdir)
1211a1709e4aSPatrick Williams        )
121234a7acdfSBrad Bishop
121344fd7e89SMarri Devender Rao        for x in sorted(yaml_files):
121405b0c1eeSBrad Bishop            path = os.path.join(args.inputdir, x)
1215a1709e4aSPatrick Williams            with open(path, "r") as fd:
121605b0c1eeSBrad Bishop                Everything.load_one_yaml(path, fd, objs)
121705b0c1eeSBrad Bishop
121805b0c1eeSBrad Bishop        # Configuration file directives reference each other via
121905b0c1eeSBrad Bishop        # the name attribute; however, when rendered the reference
122005b0c1eeSBrad Bishop        # is just an array index.
122105b0c1eeSBrad Bishop        #
122205b0c1eeSBrad Bishop        # At this point all objects have been created but references
122378199b44SGunnar Mills        # have not been resolved to array indices.  Instruct objects
122405b0c1eeSBrad Bishop        # to do that now.
122505b0c1eeSBrad Bishop        for cls, items in objs.items():
122605b0c1eeSBrad Bishop            for obj in items:
122705b0c1eeSBrad Bishop                obj.setup(objs)
122805b0c1eeSBrad Bishop
122905b0c1eeSBrad Bishop        return Everything(**objs)
123034a7acdfSBrad Bishop
123134a7acdfSBrad Bishop    def __init__(self, *a, **kw):
1232a1709e4aSPatrick Williams        self.pathmeta = kw.pop("path", [])
1233a1709e4aSPatrick Williams        self.paths = kw.pop("pathname", [])
1234a1709e4aSPatrick Williams        self.meta = kw.pop("meta", [])
1235a1709e4aSPatrick Williams        self.pathgroups = kw.pop("pathgroup", [])
1236a1709e4aSPatrick Williams        self.interfaces = kw.pop("interface", [])
1237a1709e4aSPatrick Williams        self.properties = kw.pop("property", [])
1238a1709e4aSPatrick Williams        self.propertynames = kw.pop("propertyname", [])
1239a1709e4aSPatrick Williams        self.propertygroups = kw.pop("propertygroup", [])
1240a1709e4aSPatrick Williams        self.instances = kw.pop("instance", [])
1241a1709e4aSPatrick Williams        self.pathinstances = kw.pop("pathinstance", [])
1242a1709e4aSPatrick Williams        self.instancegroups = kw.pop("instancegroup", [])
1243a1709e4aSPatrick Williams        self.pathinstancegroups = kw.pop("pathinstancegroup", [])
1244a1709e4aSPatrick Williams        self.watches = kw.pop("watch", [])
1245a1709e4aSPatrick Williams        self.pathwatches = kw.pop("pathwatch", [])
1246a1709e4aSPatrick Williams        self.callbacks = kw.pop("callback", [])
1247a1709e4aSPatrick Williams        self.pathcallbacks = kw.pop("pathcallback", [])
1248a1709e4aSPatrick Williams        self.callbackgroups = kw.pop("callbackgroup", [])
1249a1709e4aSPatrick Williams        self.pathcallbackgroups = kw.pop("pathcallbackgroup", [])
1250a1709e4aSPatrick Williams        self.conditions = kw.pop("condition", [])
1251a1709e4aSPatrick Williams        self.filters = kw.pop("filtersgroup", [])
12520e7df131SBrad Bishop
125334a7acdfSBrad Bishop        super(Everything, self).__init__(**kw)
125434a7acdfSBrad Bishop
125534a7acdfSBrad Bishop    def generate_cpp(self, loader):
1256a1709e4aSPatrick Williams        """Render the template with the provided data."""
1257d5faea31SGunnar Mills        # errors.hpp is used by generated.hpp to included any error.hpp files
1258a1709e4aSPatrick Williams        open(args.gen_errors, "w+")
1259d5faea31SGunnar Mills
1260a1709e4aSPatrick Williams        with open(args.output, "w") as fd:
126134a7acdfSBrad Bishop            fd.write(
126234a7acdfSBrad Bishop                self.render(
126334a7acdfSBrad Bishop                    loader,
1264e3a01af4SBrad Bishop                    args.template,
12650e7df131SBrad Bishop                    meta=self.meta,
1266e73b2c35SBrad Bishop                    properties=self.properties,
1267e73b2c35SBrad Bishop                    propertynames=self.propertynames,
1268e73b2c35SBrad Bishop                    interfaces=self.interfaces,
12690e7df131SBrad Bishop                    paths=self.paths,
12700e7df131SBrad Bishop                    pathmeta=self.pathmeta,
12710e7df131SBrad Bishop                    pathgroups=self.pathgroups,
1272e73b2c35SBrad Bishop                    propertygroups=self.propertygroups,
12734b916f13SBrad Bishop                    instances=self.instances,
127480c70610SMarri Devender Rao                    pathinstances=self.pathinstances,
12754b916f13SBrad Bishop                    watches=self.watches,
127680c70610SMarri Devender Rao                    pathwatches=self.pathwatches,
12774b916f13SBrad Bishop                    instancegroups=self.instancegroups,
127880c70610SMarri Devender Rao                    pathinstancegroups=self.pathinstancegroups,
1279c1283ae8SBrad Bishop                    callbacks=self.callbacks,
128080c70610SMarri Devender Rao                    pathcallbacks=self.pathcallbacks,
128149e66175SBrad Bishop                    callbackgroups=self.callbackgroups,
128280c70610SMarri Devender Rao                    pathcallbackgroups=self.pathcallbackgroups,
12834041d720SBrad Bishop                    conditions=self.conditions,
1284efe0158cSMatthew Barth                    filters=self.filters,
1285a1709e4aSPatrick Williams                    indent=Indent(),
1286a1709e4aSPatrick Williams                )
1287a1709e4aSPatrick Williams            )
12880019197fSBrad Bishop
1289a1709e4aSPatrick Williams
1290a1709e4aSPatrick Williamsif __name__ == "__main__":
129134a7acdfSBrad Bishop    script_dir = os.path.dirname(os.path.realpath(__file__))
129234a7acdfSBrad Bishop    valid_commands = {
1293a1709e4aSPatrick Williams        "generate-cpp": "generate_cpp",
129434a7acdfSBrad Bishop    }
129534a7acdfSBrad Bishop
129634a7acdfSBrad Bishop    parser = ArgumentParser(
1297a1709e4aSPatrick Williams        description=(
1298a1709e4aSPatrick Williams            "Phosphor DBus Monitor (PDM) YAML scanner and code generator."
1299a1709e4aSPatrick Williams        )
1300a1709e4aSPatrick Williams    )
130134a7acdfSBrad Bishop
13020019197fSBrad Bishop    parser.add_argument(
1303a1709e4aSPatrick Williams        "-o",
1304a1709e4aSPatrick Williams        "--out",
1305a1709e4aSPatrick Williams        dest="output",
1306a1709e4aSPatrick Williams        default="generated.cpp",
1307a1709e4aSPatrick Williams        help="Generated output file name and path.",
1308a1709e4aSPatrick Williams    )
1309e3a01af4SBrad Bishop    parser.add_argument(
1310a1709e4aSPatrick Williams        "-t",
1311a1709e4aSPatrick Williams        "--template",
1312a1709e4aSPatrick Williams        dest="template",
1313a1709e4aSPatrick Williams        default="generated.mako.hpp",
1314a1709e4aSPatrick Williams        help="The top level template to render.",
1315a1709e4aSPatrick Williams    )
1316e3a01af4SBrad Bishop    parser.add_argument(
1317a1709e4aSPatrick Williams        "-e",
1318a1709e4aSPatrick Williams        "--errors",
1319a1709e4aSPatrick Williams        dest="gen_errors",
1320a1709e4aSPatrick Williams        default="errors.hpp",
1321a1709e4aSPatrick Williams        help="Generated errors.hpp output filename.",
1322a1709e4aSPatrick Williams    )
132304267b4fSMatt Johnston    parser.add_argument(
1324a1709e4aSPatrick Williams        "-p",
1325a1709e4aSPatrick Williams        "--template-path",
1326a1709e4aSPatrick Williams        dest="template_search",
1327e3a01af4SBrad Bishop        default=script_dir,
1328a1709e4aSPatrick Williams        help="The space delimited mako template search path.",
1329a1709e4aSPatrick Williams    )
133034a7acdfSBrad Bishop    parser.add_argument(
1331a1709e4aSPatrick Williams        "-d",
1332a1709e4aSPatrick Williams        "--dir",
1333a1709e4aSPatrick Williams        dest="inputdir",
1334a1709e4aSPatrick Williams        default=os.path.join(script_dir, "example"),
1335a1709e4aSPatrick Williams        help="Location of files to process.",
1336a1709e4aSPatrick Williams    )
133734a7acdfSBrad Bishop    parser.add_argument(
1338a1709e4aSPatrick Williams        "command",
1339a1709e4aSPatrick Williams        metavar="COMMAND",
1340a1709e4aSPatrick Williams        type=str,
134134a7acdfSBrad Bishop        choices=valid_commands.keys(),
1342a1709e4aSPatrick Williams        help="%s." % " | ".join(valid_commands.keys()),
1343a1709e4aSPatrick Williams    )
13440019197fSBrad Bishop
134534a7acdfSBrad Bishop    args = parser.parse_args()
134634a7acdfSBrad Bishop
134734a7acdfSBrad Bishop    if sys.version_info < (3, 0):
134834a7acdfSBrad Bishop        lookup = mako.lookup.TemplateLookup(
1349a1709e4aSPatrick Williams            directories=args.template_search.split(), disable_unicode=True
1350a1709e4aSPatrick Williams        )
135134a7acdfSBrad Bishop    else:
135234a7acdfSBrad Bishop        lookup = mako.lookup.TemplateLookup(
1353a1709e4aSPatrick Williams            directories=args.template_search.split()
1354a1709e4aSPatrick Williams        )
135505b0c1eeSBrad Bishop    try:
1356a1709e4aSPatrick Williams        function = getattr(Everything.load(args), valid_commands[args.command])
135734a7acdfSBrad Bishop        function(lookup)
135805b0c1eeSBrad Bishop    except InvalidConfigError as e:
1359a1709e4aSPatrick Williams        sys.stdout.write("{0}: {1}\n\n".format(e.config, e.msg))
136005b0c1eeSBrad Bishop        raise
1361