#!/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