summaryrefslogtreecommitdiffstats
path: root/pimgen.py
blob: 072f7d687ba74d7b8eb313e27a32ce01b9e10988 (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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
#!/usr/bin/env python

import sys
import os
import re
import argparse
import yaml
import subprocess
from mako.template import Template

valid_c_name_pattern = re.compile('[\W_]+')


def parse_event(e):
    e['name'] = valid_c_name_pattern.sub('_', e['name']).lower()
    if e.get('filter') is None:
        e.setdefault('filter', {}).setdefault('type', 'none')
    if e.get('action') is None:
        e.setdefault('action', {}).setdefault('type', 'noop')
    return e


def get_interfaces(args):
    interfaces_dir = os.path.join(args.inputdir, 'interfaces.d')
    yaml_files = filter(
        lambda x: x.endswith('.yaml'),
        os.listdir(interfaces_dir))

    interfaces = []
    for x in yaml_files:
        with open(os.path.join(interfaces_dir, x), 'r') as fd:
            for i in yaml.load(fd.read()):
                interfaces.append(i)

    return interfaces


def list_interfaces(args):
    print ' '.join(get_interfaces(args))


def generate_cpp(args):
    # Aggregate all the event YAML in the events.d directory
    # into a single list of events.
    events_dir = os.path.join(args.inputdir, 'events.d')
    yaml_files = filter(
        lambda x: x.endswith('.yaml'),
        os.listdir(events_dir))

    events = []
    for x in yaml_files:
        with open(os.path.join(events_dir, x), 'r') as fd:
            for e in yaml.load(fd.read()).get('events', {}):
                events.append(parse_event(e))

    # Aggregate all the interface YAML in the interfaces.d
    # directory into a single list of interfaces.
    template = os.path.join(script_dir, 'generated.mako.cpp')
    t = Template(filename=template)

    interfaces = get_interfaces(args)

    # Render the template with the provided events and interfaces.
    template = os.path.join(script_dir, 'generated.mako.cpp')
    t = Template(filename=template)
    with open(os.path.join(args.outputdir, 'generated.cpp'), 'w') as fd:
        fd.write(
            t.render(
                interfaces=interfaces,
                events=events))

    # Invoke sdbus++ to generate any extra interface bindings for
    # extra interfaces that aren't defined externally.
    yaml_files = []
    extra_ifaces_dir = os.path.join(args.inputdir, 'extra_interfaces.d')
    if os.path.exists(extra_ifaces_dir):
        for directory, _, files in os.walk(extra_ifaces_dir):
            if not files:
                continue

            yaml_files += map(
                lambda f: os.path.relpath(
                    os.path.join(directory, f),
                    extra_ifaces_dir),
                filter(lambda f: f.endswith('.interface.yaml'), files))

    genfiles = {
        'server-cpp': lambda x: '%s.cpp' % (
            x.replace(os.sep, '.')),
        'server-header': lambda x: os.path.join(
            os.path.join(
                *x.split('.')), 'server.hpp')
    }

    for i in yaml_files:
        iface = i.replace('.interface.yaml', '').replace(os.sep, '.')
        for process, f in genfiles.iteritems():

            dest = os.path.join(args.outputdir, f(iface))
            parent = os.path.dirname(dest)
            if parent and not os.path.exists(parent):
                os.makedirs(parent)

            with open(dest, 'w') as fd:
                subprocess.call([
                    'sdbus++',
                    '-r',
                    extra_ifaces_dir,
                    'interface',
                    process,
                    iface],
                    stdout=fd)


if __name__ == '__main__':
    script_dir = os.path.dirname(os.path.realpath(__file__))
    valid_commands = {
        'generate-cpp': 'generate_cpp',
        'list-interfaces': 'list_interfaces'}

    parser = argparse.ArgumentParser(
        description='Phosphor Inventory Manager (PIM) YAML '
        'scanner and code generator.')
    parser.add_argument(
        '-o', '--output-dir', dest='outputdir',
        default='.', help='Output directory.')
    parser.add_argument(
        '-d', '--dir', dest='inputdir',
        default=os.path.join(script_dir, 'example'),
        help='Location of files to process.')
    parser.add_argument(
        'command', metavar='COMMAND', type=str,
        choices=valid_commands.keys(),
        help='Command to run.')

    args = parser.parse_args()
    function = getattr(sys.modules[__name__], valid_commands[args.command])
    function(args)


# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
OpenPOWER on IntegriCloud