1import os
2
3import yaml
4
5from .enum import Enum
6from .method import Method
7from .namedelement import NamedElement
8from .path import Path
9from .property import Property
10from .renderer import Renderer
11from .servicename import ServiceName
12from .signal import Signal
13
14
15class Interface(NamedElement, Renderer):
16    @staticmethod
17    def load(name, rootdir, schemadir):
18        filename = os.path.join(
19            rootdir, name.replace(".", "/") + ".interface.yaml"
20        )
21
22        with open(filename) as f:
23            data = f.read()
24            y = yaml.safe_load(data)
25            y["name"] = name
26            return Interface(**y)
27
28    def __init__(self, **kwargs):
29        self.properties = [Property(**p) for p in kwargs.pop("properties", [])]
30        self.methods = [Method(**m) for m in kwargs.pop("methods", [])]
31        self.signals = [Signal(**s) for s in kwargs.pop("signals", [])]
32        self.enums = [Enum(**e) for e in kwargs.pop("enumerations", [])]
33        self.paths = [Path(**p) for p in kwargs.pop("paths", [])]
34        self.service_names = [
35            ServiceName(**s) for s in kwargs.pop("service_names", [])
36        ]
37
38        super(Interface, self).__init__(**kwargs)
39
40    def joinedName(self, join_str, append):
41        return join_str.join(self.namespaces + [self.classname, append])
42
43    def error_includes(self, inc_list):
44        includes = []
45        for e in inc_list:
46            e = e.replace("self.", self.name + ".")
47            if ".Error." in e:
48                n = "/".join(
49                    e.split(".")[:-2],  # ignore the Error.Name at the end
50                )
51                includes.append(f"{n}/error.hpp")
52            else:
53                n = "/".join(
54                    e.split(".")[:-1],  # ignore the .Name at the end
55                )
56                includes.append(f"{n}/event.hpp")
57        return sorted(set(includes))
58
59    def errorNamespacedClass(self, error):
60        error = error.replace("self.", self.name + ".")
61        if ".Error" not in error:
62            error = "error." + error
63        return "sdbusplus::" + "::".join(error.split("."))
64
65    def enum_includes(self, inc_list):
66        includes = []
67        for e in inc_list:
68            includes.extend(e.enum_headers())
69        return sorted(set(includes))
70
71    def markdown(self, loader):
72        return self.render(loader, "interface.md.mako", interface=self)
73
74    def async_server_header(self, loader):
75        return self.render(
76            loader, "interface.aserver.hpp.mako", interface=self
77        )
78
79    def server_header(self, loader):
80        return self.render(loader, "interface.server.hpp.mako", interface=self)
81
82    def server_cpp(self, loader):
83        return self.render(loader, "interface.server.cpp.mako", interface=self)
84
85    def client_header(self, loader):
86        return self.render(loader, "interface.client.hpp.mako", interface=self)
87
88    def common_header(self, loader):
89        return self.render(loader, "interface.common.hpp.mako", interface=self)
90
91    def cpp_includes(self):
92        return sorted(
93            set.union(
94                set(),
95                *[
96                    set(m.cpp_includes(self))
97                    for m in self.methods + self.properties + self.signals
98                ],
99            )
100        )
101