1#!/usr/bin/env python 2 3import sys 4import os 5import re 6import argparse 7import yaml 8import subprocess 9from mako.template import Template 10 11valid_c_name_pattern = re.compile('[\W_]+') 12 13 14def parse_event(e): 15 e['name'] = valid_c_name_pattern.sub('_', e['name']).lower() 16 if e.get('filter') is None: 17 e.setdefault('filter', {}).setdefault('type', 'none') 18 if e.get('action') is None: 19 e.setdefault('action', {}).setdefault('type', 'noop') 20 return e 21 22 23if __name__ == '__main__': 24 script_dir = os.path.dirname(os.path.realpath(__file__)) 25 26 parser = argparse.ArgumentParser( 27 description='Phosphor Inventory Manager (PIM) YAML ' 28 'scanner and code generator.') 29 parser.add_argument( 30 '-o', '--output-dir', dest='outputdir', 31 default='.', help='Output directory.') 32 parser.add_argument( 33 '-d', '--dir', dest='inputdir', 34 default=os.path.join(script_dir, 'example'), 35 help='Location of files to process.') 36 37 args = parser.parse_args() 38 39 # Aggregate all the event YAML in the events.d directory 40 # into a single list of events. 41 events_dir = os.path.join(args.inputdir, 'events.d') 42 yaml_files = filter( 43 lambda x: x.endswith('.yaml'), 44 os.listdir(events_dir)) 45 46 events = [] 47 for x in yaml_files: 48 with open(os.path.join(events_dir, x), 'r') as fd: 49 for e in yaml.load(fd.read()).get('events', {}): 50 events.append(parse_event(e)) 51 52 # Aggregate all the interface YAML in the interfaces.d 53 # directory into a single list of interfaces. 54 template = os.path.join(script_dir, 'generated.mako.cpp') 55 t = Template(filename=template) 56 57 interfaces_dir = os.path.join(args.inputdir, 'interfaces.d') 58 yaml_files = filter( 59 lambda x: x.endswith('.yaml'), 60 os.listdir(interfaces_dir)) 61 62 interfaces = [] 63 for x in yaml_files: 64 with open(os.path.join(interfaces_dir, x), 'r') as fd: 65 for i in yaml.load(fd.read()): 66 interfaces.append(i) 67 68 # Render the template with the provided events and interfaces. 69 template = os.path.join(script_dir, 'generated.mako.cpp') 70 t = Template(filename=template) 71 with open(os.path.join(args.outputdir, 'generated.cpp'), 'w') as fd: 72 fd.write( 73 t.render( 74 interfaces=interfaces, 75 events=events)) 76 77 # Invoke sdbus++ to generate any extra interface bindings for 78 # extra interfaces that aren't defined externally. 79 yaml_files = [] 80 extra_ifaces_dir = os.path.join(args.inputdir, 'extra_interfaces.d') 81 if os.path.exists(extra_ifaces_dir): 82 for directory, _, files in os.walk(extra_ifaces_dir): 83 if not files: 84 continue 85 86 yaml_files += map( 87 lambda f: os.path.relpath( 88 os.path.join(directory, f), 89 extra_ifaces_dir), 90 filter(lambda f: f.endswith('.interface.yaml'), files)) 91 92 genfiles = { 93 'server-cpp': lambda x: '%s.cpp' % ( 94 x.replace(os.sep, '.')), 95 'server-header': lambda x: os.path.join( 96 os.path.join( 97 *x.split('.')), 'server.hpp') 98 } 99 100 for i in yaml_files: 101 iface = i.replace('.interface.yaml', '').replace(os.sep, '.') 102 for process, f in genfiles.iteritems(): 103 104 dest = os.path.join(args.outputdir, f(iface)) 105 parent = os.path.dirname(dest) 106 if parent and not os.path.exists(parent): 107 os.makedirs(parent) 108 109 with open(dest, 'w') as fd: 110 subprocess.call([ 111 'sdbus++', 112 '-r', 113 extra_ifaces_dir, 114 'interface', 115 process, 116 iface], 117 stdout=fd) 118 119# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 120