blob: 4711165180f625abbb3b74b975dfa037494aa01b [file] [log] [blame]
Brad Bishopbf066a62016-10-19 08:09:44 -04001#!/usr/bin/env python
2
Brad Bishop22cfbe62016-11-30 13:25:10 -05003'''Phosphor Inventory Manager YAML parser and code generator.
4
5The parser workflow is broken down as follows:
6 1 - Import YAML files as native python type(s) instance(s).
7 2 - Create an instance of the Everything class from the
8 native python type instance(s) with the Everything.load
9 method.
10 3 - The Everything class constructor orchestrates conversion of the
11 native python type(s) instances(s) to render helper types.
12 Each render helper type constructor imports its attributes
13 from the native python type(s) instances(s).
14 4 - Present the converted YAML to the command processing method
15 requested by the script user.
16'''
17
Brad Bishopbf066a62016-10-19 08:09:44 -040018import sys
19import os
Brad Bishopbf066a62016-10-19 08:09:44 -040020import argparse
Brad Bishopcfb3c892016-11-12 11:43:37 -050021import subprocess
Brad Bishop22cfbe62016-11-30 13:25:10 -050022import yaml
23import mako.lookup
24import sdbusplus.property
25from sdbusplus.namedelement import NamedElement
26from sdbusplus.renderer import Renderer
Brad Bishopbf066a62016-10-19 08:09:44 -040027
28
Brad Bishop9b5a12f2017-01-21 14:42:11 -050029def cppTypeName(yaml_type):
30 ''' Convert yaml types to cpp types.'''
31 return sdbusplus.property.Property(type=yaml_type).cppTypeName
32
33
Brad Bishop22cfbe62016-11-30 13:25:10 -050034class Interface(list):
35 '''Provide various interface transformations.'''
36
37 def __init__(self, iface):
38 super(Interface, self).__init__(iface.split('.'))
39
40 def namespace(self):
41 '''Represent as an sdbusplus namespace.'''
42 return '::'.join(['sdbusplus'] + self[:-1] + ['server', self[-1]])
43
44 def header(self):
45 '''Represent as an sdbusplus server binding header.'''
46 return os.sep.join(self + ['server.hpp'])
47
48 def __str__(self):
49 return '.'.join(self)
Brad Bishopbf066a62016-10-19 08:09:44 -040050
Brad Bishopcfb3c892016-11-12 11:43:37 -050051
Brad Bishop9b5a12f2017-01-21 14:42:11 -050052class Indent(object):
53 '''Help templates be depth agnostic.'''
54
55 def __init__(self, depth=0):
56 self.depth = depth
57
58 def __add__(self, depth):
59 return Indent(self.depth + depth)
60
61 def __call__(self, depth):
62 '''Render an indent at the current depth plus depth.'''
63 return 4*' '*(depth + self.depth)
64
65
66class Template(NamedElement):
67 '''Associate a template name with its namespace.'''
68
69 def __init__(self, **kw):
Brad Bishopc1f47982017-02-09 01:27:38 -050070 self.namespace = kw.pop('namespace', [])
Brad Bishop9b5a12f2017-01-21 14:42:11 -050071 super(Template, self).__init__(**kw)
72
73 def qualified(self):
74 return '::'.join(self.namespace + [self.name])
75
76
Brad Bishopdb9b3252017-01-30 08:58:40 -050077class FixBool(object):
78 '''Un-capitalize booleans.'''
79
80 def __call__(self, arg):
81 return '{0}'.format(arg.lower())
82
83
Brad Bishop9b5a12f2017-01-21 14:42:11 -050084class Quote(object):
85 '''Decorate an argument by quoting it.'''
86
87 def __call__(self, arg):
88 return '"{0}"'.format(arg)
89
90
91class Cast(object):
92 '''Decorate an argument by casting it.'''
93
94 def __init__(self, cast, target):
95 '''cast is the cast type (static, const, etc...).
96 target is the cast target type.'''
97 self.cast = cast
98 self.target = target
99
100 def __call__(self, arg):
101 return '{0}_cast<{1}>({2})'.format(self.cast, self.target, arg)
102
103
104class Literal(object):
105 '''Decorate an argument with a literal operator.'''
106
Brad Bishop134d2cb2017-02-23 12:37:56 -0500107 integer_types = [
108 'int8',
109 'int16',
110 'int32',
111 'int64',
112 'uint8',
113 'uint16',
114 'uint32',
115 'uint64'
116 ]
Brad Bishop9b5a12f2017-01-21 14:42:11 -0500117
118 def __init__(self, type):
119 self.type = type
120
121 def __call__(self, arg):
Brad Bishop134d2cb2017-02-23 12:37:56 -0500122 if 'uint' in self.type:
123 arg = '{0}ull'.format(arg)
124 elif 'int' in self.type:
125 arg = '{0}ll'.format(arg)
Brad Bishop9b5a12f2017-01-21 14:42:11 -0500126
Brad Bishop134d2cb2017-02-23 12:37:56 -0500127 if self.type in self.integer_types:
128 return Cast('static', '{0}_t'.format(self.type))(arg)
129
130 if self.type == 'string':
131 return '{0}s'.format(arg)
Brad Bishop9b5a12f2017-01-21 14:42:11 -0500132
133 return arg
134
135
Brad Bishop75800cf2017-01-21 15:24:18 -0500136class Argument(NamedElement, Renderer):
137 '''Define argument type inteface.'''
138
139 def __init__(self, **kw):
140 self.type = kw.pop('type', None)
141 super(Argument, self).__init__(**kw)
142
143 def argument(self, loader, indent):
144 raise NotImplementedError
145
146
147class TrivialArgument(Argument):
148 '''Non-array type arguments.'''
Brad Bishop14a9fe52016-11-12 12:51:26 -0500149
Brad Bishop22cfbe62016-11-30 13:25:10 -0500150 def __init__(self, **kw):
151 self.value = kw.pop('value')
Brad Bishop75800cf2017-01-21 15:24:18 -0500152 self.decorators = kw.pop('decorators', [])
153 if kw.get('type', None) == 'string':
154 self.decorators.insert(0, Quote())
Brad Bishopdb9b3252017-01-30 08:58:40 -0500155 if kw.get('type', None) == 'boolean':
156 self.decorators.insert(0, FixBool())
Brad Bishop75800cf2017-01-21 15:24:18 -0500157
Brad Bishop75800cf2017-01-21 15:24:18 -0500158 super(TrivialArgument, self).__init__(**kw)
159
160 def argument(self, loader, indent):
161 a = str(self.value)
162 for d in self.decorators:
163 a = d(a)
164
165 return a
Brad Bishop14a9fe52016-11-12 12:51:26 -0500166
Brad Bishop14a9fe52016-11-12 12:51:26 -0500167
Brad Bishop9b5a12f2017-01-21 14:42:11 -0500168class InitializerList(Argument):
169 '''Initializer list arguments.'''
170
171 def __init__(self, **kw):
172 self.values = kw.pop('values')
173 super(InitializerList, self).__init__(**kw)
174
175 def argument(self, loader, indent):
176 return self.render(
177 loader,
178 'argument.mako.cpp',
179 arg=self,
180 indent=indent)
181
182
Brad Bishop75800cf2017-01-21 15:24:18 -0500183class DbusSignature(Argument):
184 '''DBus signature arguments.'''
185
186 def __init__(self, **kw):
187 self.sig = {x: y for x, y in kw.iteritems()}
188 kw.clear()
189 super(DbusSignature, self).__init__(**kw)
190
191 def argument(self, loader, indent):
192 return self.render(
193 loader,
194 'signature.mako.cpp',
195 signature=self,
196 indent=indent)
197
198
Brad Bishopc93bcc92017-01-21 16:23:39 -0500199class MethodCall(Argument):
Brad Bishop22cfbe62016-11-30 13:25:10 -0500200 '''Render syntatically correct c++ method calls.'''
201
202 def __init__(self, **kw):
203 self.namespace = kw.pop('namespace', [])
Brad Bishopc93bcc92017-01-21 16:23:39 -0500204 self.templates = kw.pop('templates', [])
205 self.args = kw.pop('args', [])
Brad Bishop22cfbe62016-11-30 13:25:10 -0500206 super(MethodCall, self).__init__(**kw)
207
Brad Bishopcab2bdd2017-01-21 15:00:54 -0500208 def call(self, loader, indent):
209 return self.render(
210 loader,
211 'method.mako.cpp',
212 method=self,
213 indent=indent)
214
215 def argument(self, loader, indent):
216 return self.call(loader, indent)
217
Brad Bishop14a9fe52016-11-12 12:51:26 -0500218
Brad Bishop9b5a12f2017-01-21 14:42:11 -0500219class Vector(MethodCall):
220 '''Convenience type for vectors.'''
221
222 def __init__(self, **kw):
223 kw['name'] = 'vector'
224 kw['namespace'] = ['std']
225 kw['args'] = [InitializerList(values=kw.pop('args'))]
226 super(Vector, self).__init__(**kw)
227
228
Brad Bishopc1f47982017-02-09 01:27:38 -0500229class Filter(MethodCall):
Brad Bishopc93bcc92017-01-21 16:23:39 -0500230 '''Convenience type for filters'''
Brad Bishopbf066a62016-10-19 08:09:44 -0400231
Brad Bishop22cfbe62016-11-30 13:25:10 -0500232 def __init__(self, **kw):
Brad Bishopc1f47982017-02-09 01:27:38 -0500233 kw['name'] = 'make_filter'
Brad Bishop22cfbe62016-11-30 13:25:10 -0500234 super(Filter, self).__init__(**kw)
Brad Bishopbf066a62016-10-19 08:09:44 -0400235
Brad Bishop0a6a4792016-11-12 12:10:07 -0500236
Brad Bishopc1f47982017-02-09 01:27:38 -0500237class Action(MethodCall):
Brad Bishopc93bcc92017-01-21 16:23:39 -0500238 '''Convenience type for actions'''
Brad Bishop561a5652016-10-26 21:13:32 -0500239
Brad Bishop22cfbe62016-11-30 13:25:10 -0500240 def __init__(self, **kw):
Brad Bishopc1f47982017-02-09 01:27:38 -0500241 kw['name'] = 'make_action'
Brad Bishop22cfbe62016-11-30 13:25:10 -0500242 super(Action, self).__init__(**kw)
Brad Bishop92665b22016-10-26 20:51:16 -0500243
Brad Bishopcfb3c892016-11-12 11:43:37 -0500244
Brad Bishopd0f48ad2017-01-30 08:52:26 -0500245class PathCondition(MethodCall):
246 '''Convenience type for path conditions'''
247
248 def __init__(self, **kw):
249 kw['name'] = 'make_path_condition'
250 super(PathCondition, self).__init__(**kw)
251
252
Brad Bishopc1f47982017-02-09 01:27:38 -0500253class CreateObjects(MethodCall):
254 '''Assemble a createObjects functor.'''
Brad Bishopdb92c282017-01-21 23:44:28 -0500255
256 def __init__(self, **kw):
257 objs = []
258
259 for path, interfaces in kw.pop('objs').iteritems():
260 key_o = TrivialArgument(
261 value=path,
262 type='string',
263 decorators=[Literal('string')])
264 value_i = []
265
266 for interface, properties, in interfaces.iteritems():
267 key_i = TrivialArgument(value=interface, type='string')
268 value_p = []
269
270 for prop, value in properties.iteritems():
271 key_p = TrivialArgument(value=prop, type='string')
272 value_v = TrivialArgument(
273 decorators=[Literal(value.get('type', None))],
274 **value)
275 value_p.append(InitializerList(values=[key_p, value_v]))
276
277 value_p = InitializerList(values=value_p)
278 value_i.append(InitializerList(values=[key_i, value_p]))
279
280 value_i = InitializerList(values=value_i)
281 objs.append(InitializerList(values=[key_o, value_i]))
282
283 kw['args'] = [InitializerList(values=objs)]
Brad Bishopc1f47982017-02-09 01:27:38 -0500284 kw['namespace'] = ['functor']
Brad Bishopdb92c282017-01-21 23:44:28 -0500285 super(CreateObjects, self).__init__(**kw)
286
287
Brad Bishopc1f47982017-02-09 01:27:38 -0500288class DestroyObjects(MethodCall):
289 '''Assemble a destroyObject functor.'''
Brad Bishop22cfbe62016-11-30 13:25:10 -0500290
291 def __init__(self, **kw):
Brad Bishop7b7e7122017-01-21 21:21:46 -0500292 values = [{'value': x, 'type': 'string'} for x in kw.pop('paths')]
Brad Bishopd0f48ad2017-01-30 08:52:26 -0500293 conditions = [
294 Event.functor_map[
295 x['name']](**x) for x in kw.pop('conditions', [])]
296 conditions = [PathCondition(args=[x]) for x in conditions]
Brad Bishop7b7e7122017-01-21 21:21:46 -0500297 args = [InitializerList(
298 values=[TrivialArgument(**x) for x in values])]
Brad Bishopd0f48ad2017-01-30 08:52:26 -0500299 args.append(InitializerList(values=conditions))
Brad Bishopc93bcc92017-01-21 16:23:39 -0500300 kw['args'] = args
Brad Bishopc1f47982017-02-09 01:27:38 -0500301 kw['namespace'] = ['functor']
Brad Bishop7b7e7122017-01-21 21:21:46 -0500302 super(DestroyObjects, self).__init__(**kw)
Brad Bishop22cfbe62016-11-30 13:25:10 -0500303
304
Brad Bishopc1f47982017-02-09 01:27:38 -0500305class SetProperty(MethodCall):
306 '''Assemble a setProperty functor.'''
Brad Bishope2e402f2016-11-30 18:00:17 -0500307
308 def __init__(self, **kw):
Brad Bishopc93bcc92017-01-21 16:23:39 -0500309 args = []
310
311 value = kw.pop('value')
312 prop = kw.pop('property')
313 iface = kw.pop('interface')
314 iface = Interface(iface)
315 namespace = iface.namespace().split('::')[:-1]
316 name = iface[-1]
317 t = Template(namespace=namespace, name=iface[-1])
318
Brad Bishope2e402f2016-11-30 18:00:17 -0500319 member = '&%s' % '::'.join(
Brad Bishopc93bcc92017-01-21 16:23:39 -0500320 namespace + [name, NamedElement(name=prop).camelCase])
321 member_type = cppTypeName(value['type'])
322 member_cast = '{0} ({1}::*)({0})'.format(member_type, t.qualified())
Brad Bishope2e402f2016-11-30 18:00:17 -0500323
Brad Bishop02ca0212017-01-28 23:25:58 -0500324 paths = [{'value': x, 'type': 'string'} for x in kw.pop('paths')]
325 args.append(InitializerList(
326 values=[TrivialArgument(**x) for x in paths]))
327
Brad Bishopd0f48ad2017-01-30 08:52:26 -0500328 conditions = [
329 Event.functor_map[
330 x['name']](**x) for x in kw.pop('conditions', [])]
331 conditions = [PathCondition(args=[x]) for x in conditions]
332
333 args.append(InitializerList(values=conditions))
Brad Bishopc93bcc92017-01-21 16:23:39 -0500334 args.append(TrivialArgument(value=str(iface), type='string'))
335 args.append(TrivialArgument(
336 value=member, decorators=[Cast('static', member_cast)]))
337 args.append(TrivialArgument(**value))
Brad Bishope2e402f2016-11-30 18:00:17 -0500338
Brad Bishopc93bcc92017-01-21 16:23:39 -0500339 kw['templates'] = [Template(name=name, namespace=namespace)]
340 kw['args'] = args
Brad Bishopc1f47982017-02-09 01:27:38 -0500341 kw['namespace'] = ['functor']
Brad Bishope2e402f2016-11-30 18:00:17 -0500342 super(SetProperty, self).__init__(**kw)
343
344
Brad Bishopc1f47982017-02-09 01:27:38 -0500345class PropertyChanged(MethodCall):
346 '''Assemble a propertyChanged functor.'''
Brad Bishop22cfbe62016-11-30 13:25:10 -0500347
348 def __init__(self, **kw):
Brad Bishopc93bcc92017-01-21 16:23:39 -0500349 args = []
350 args.append(TrivialArgument(value=kw.pop('interface'), type='string'))
351 args.append(TrivialArgument(value=kw.pop('property'), type='string'))
352 args.append(TrivialArgument(
353 decorators=[
354 Literal(kw['value'].get('type', None))], **kw.pop('value')))
355 kw['args'] = args
Brad Bishopc1f47982017-02-09 01:27:38 -0500356 kw['namespace'] = ['functor']
Brad Bishop22cfbe62016-11-30 13:25:10 -0500357 super(PropertyChanged, self).__init__(**kw)
358
359
Brad Bishopc1f47982017-02-09 01:27:38 -0500360class PropertyIs(MethodCall):
361 '''Assemble a propertyIs functor.'''
Brad Bishop040e18b2017-01-21 22:04:00 -0500362
363 def __init__(self, **kw):
364 args = []
Brad Bishopd0f48ad2017-01-30 08:52:26 -0500365 path = kw.pop('path', None)
366 if not path:
367 path = TrivialArgument(value='nullptr')
368 else:
369 path = TrivialArgument(value=path, type='string')
370
371 args.append(path)
Brad Bishop040e18b2017-01-21 22:04:00 -0500372 args.append(TrivialArgument(value=kw.pop('interface'), type='string'))
373 args.append(TrivialArgument(value=kw.pop('property'), type='string'))
374 args.append(TrivialArgument(
375 decorators=[
376 Literal(kw['value'].get('type', None))], **kw.pop('value')))
377
378 service = kw.pop('service', None)
379 if service:
380 args.append(TrivialArgument(value=service, type='string'))
381
382 kw['args'] = args
Brad Bishopc1f47982017-02-09 01:27:38 -0500383 kw['namespace'] = ['functor']
Brad Bishop040e18b2017-01-21 22:04:00 -0500384 super(PropertyIs, self).__init__(**kw)
385
386
Brad Bishopc93bcc92017-01-21 16:23:39 -0500387class Event(MethodCall):
388 '''Assemble an inventory manager event.'''
Brad Bishop22cfbe62016-11-30 13:25:10 -0500389
Brad Bishopd0f48ad2017-01-30 08:52:26 -0500390 functor_map = {
Brad Bishop7b7e7122017-01-21 21:21:46 -0500391 'destroyObjects': DestroyObjects,
Brad Bishopdb92c282017-01-21 23:44:28 -0500392 'createObjects': CreateObjects,
Brad Bishopc93bcc92017-01-21 16:23:39 -0500393 'propertyChangedTo': PropertyChanged,
Brad Bishop040e18b2017-01-21 22:04:00 -0500394 'propertyIs': PropertyIs,
Brad Bishopd0f48ad2017-01-30 08:52:26 -0500395 'setProperty': SetProperty,
Brad Bishopc93bcc92017-01-21 16:23:39 -0500396 }
397
Brad Bishop22cfbe62016-11-30 13:25:10 -0500398 def __init__(self, **kw):
Brad Bishopc93bcc92017-01-21 16:23:39 -0500399 self.summary = kw.pop('name')
400
401 filters = [
Brad Bishopd0f48ad2017-01-30 08:52:26 -0500402 self.functor_map[x['name']](**x) for x in kw.pop('filters', [])]
Brad Bishopc1f47982017-02-09 01:27:38 -0500403 filters = [Filter(args=[x]) for x in filters]
Brad Bishop064c94a2017-01-21 21:33:30 -0500404 filters = Vector(
Brad Bishop12f8a3c2017-02-09 00:02:00 -0500405 templates=[Template(name='Filter', namespace=[])],
Brad Bishop064c94a2017-01-21 21:33:30 -0500406 args=filters)
Brad Bishopc93bcc92017-01-21 16:23:39 -0500407
408 event = MethodCall(
409 name='make_shared',
410 namespace=['std'],
411 templates=[Template(
412 name=kw.pop('event'),
413 namespace=kw.pop('event_namespace', []))],
Brad Bishop064c94a2017-01-21 21:33:30 -0500414 args=kw.pop('event_args', []) + [filters])
Brad Bishopc93bcc92017-01-21 16:23:39 -0500415
416 events = Vector(
Brad Bishop12f8a3c2017-02-09 00:02:00 -0500417 templates=[Template(name='EventBasePtr', namespace=[])],
Brad Bishopc93bcc92017-01-21 16:23:39 -0500418 args=[event])
419
Brad Bishop12f8a3c2017-02-09 00:02:00 -0500420 action_type = Template(name='Action', namespace=[])
Brad Bishopc93bcc92017-01-21 16:23:39 -0500421 action_args = [
Brad Bishopd0f48ad2017-01-30 08:52:26 -0500422 self.functor_map[x['name']](**x) for x in kw.pop('actions', [])]
Brad Bishopc1f47982017-02-09 01:27:38 -0500423 action_args = [Action(args=[x]) for x in action_args]
Brad Bishopc93bcc92017-01-21 16:23:39 -0500424 actions = Vector(
425 templates=[action_type],
426 args=action_args)
427
428 kw['name'] = 'make_tuple'
429 kw['namespace'] = ['std']
430 kw['args'] = [events, actions]
Brad Bishop22cfbe62016-11-30 13:25:10 -0500431 super(Event, self).__init__(**kw)
Brad Bishopcfb3c892016-11-12 11:43:37 -0500432
Brad Bishopcfb3c892016-11-12 11:43:37 -0500433
Brad Bishop22cfbe62016-11-30 13:25:10 -0500434class MatchEvent(Event):
435 '''Associate one or more dbus signal match signatures with
436 a filter.'''
437
Brad Bishop22cfbe62016-11-30 13:25:10 -0500438 def __init__(self, **kw):
Brad Bishopc93bcc92017-01-21 16:23:39 -0500439 kw['event'] = 'DbusSignal'
Brad Bishop12f8a3c2017-02-09 00:02:00 -0500440 kw['event_namespace'] = []
Brad Bishopc93bcc92017-01-21 16:23:39 -0500441 kw['event_args'] = [
442 DbusSignature(**x) for x in kw.pop('signatures', [])]
443
Brad Bishop22cfbe62016-11-30 13:25:10 -0500444 super(MatchEvent, self).__init__(**kw)
445
446
Brad Bishop828df832017-01-21 22:20:43 -0500447class StartupEvent(Event):
448 '''Assemble a startup event.'''
449
450 def __init__(self, **kw):
451 kw['event'] = 'StartupEvent'
Brad Bishop12f8a3c2017-02-09 00:02:00 -0500452 kw['event_namespace'] = []
Brad Bishop828df832017-01-21 22:20:43 -0500453 super(StartupEvent, self).__init__(**kw)
454
455
Brad Bishop22cfbe62016-11-30 13:25:10 -0500456class Everything(Renderer):
457 '''Parse/render entry point.'''
458
459 class_map = {
460 'match': MatchEvent,
Brad Bishop828df832017-01-21 22:20:43 -0500461 'startup': StartupEvent,
Brad Bishop22cfbe62016-11-30 13:25:10 -0500462 }
463
464 @staticmethod
465 def load(args):
Brad Bishop22cfbe62016-11-30 13:25:10 -0500466 # Aggregate all the event YAML in the events.d directory
467 # into a single list of events.
468
Brad Bishop22cfbe62016-11-30 13:25:10 -0500469 events = []
Brad Bishopa6fcd562017-02-03 11:00:27 -0500470 events_dir = os.path.join(args.inputdir, 'events.d')
471
472 if os.path.exists(events_dir):
473 yaml_files = filter(
474 lambda x: x.endswith('.yaml'),
475 os.listdir(events_dir))
476
477 for x in yaml_files:
478 with open(os.path.join(events_dir, x), 'r') as fd:
479 for e in yaml.safe_load(fd.read()).get('events', {}):
480 events.append(e)
Brad Bishop22cfbe62016-11-30 13:25:10 -0500481
Brad Bishop834989f2017-02-06 12:08:20 -0500482 interfaces = Everything.get_interfaces(args.ifacesdir)
483 extra_interfaces = Everything.get_interfaces(
484 os.path.join(args.inputdir, 'extra_interfaces.d'))
485
Brad Bishop22cfbe62016-11-30 13:25:10 -0500486 return Everything(
487 *events,
Brad Bishop834989f2017-02-06 12:08:20 -0500488 interfaces=interfaces + extra_interfaces)
Brad Bishop22cfbe62016-11-30 13:25:10 -0500489
490 @staticmethod
Brad Bishop834989f2017-02-06 12:08:20 -0500491 def get_interfaces(targetdir):
492 '''Scan the interfaces directory for interfaces that PIM can create.'''
Brad Bishop22cfbe62016-11-30 13:25:10 -0500493
Brad Bishop834989f2017-02-06 12:08:20 -0500494 yaml_files = []
Brad Bishop22cfbe62016-11-30 13:25:10 -0500495 interfaces = []
Brad Bishopa6fcd562017-02-03 11:00:27 -0500496
Brad Bishop834989f2017-02-06 12:08:20 -0500497 if targetdir and os.path.exists(targetdir):
498 for directory, _, files in os.walk(targetdir):
499 if not files:
500 continue
501
502 yaml_files += map(
503 lambda f: os.path.relpath(
504 os.path.join(directory, f),
505 targetdir),
506 filter(lambda f: f.endswith('.interface.yaml'), files))
507
508 for y in yaml_files:
Marri Devender Rao06e3d502017-06-09 11:33:38 -0500509 # parse only phosphor dbus related interface files
510 if not y.startswith('xyz'):
511 continue
Brad Bishop834989f2017-02-06 12:08:20 -0500512 with open(os.path.join(targetdir, y)) as fd:
513 i = y.replace('.interface.yaml', '').replace(os.sep, '.')
514
515 # PIM can't create interfaces with methods.
516 # PIM can't create interfaces without properties.
517 parsed = yaml.safe_load(fd.read())
518 if parsed.get('methods', None):
519 continue
520 if not parsed.get('properties', None):
521 continue
522
523 interfaces.append(i)
Brad Bishop22cfbe62016-11-30 13:25:10 -0500524
525 return interfaces
526
527 def __init__(self, *a, **kw):
528 self.interfaces = \
529 [Interface(x) for x in kw.pop('interfaces', [])]
530 self.events = [
531 self.class_map[x['type']](**x) for x in a]
532 super(Everything, self).__init__(**kw)
533
Brad Bishop22cfbe62016-11-30 13:25:10 -0500534 def generate_cpp(self, loader):
535 '''Render the template with the provided events and interfaces.'''
536 with open(os.path.join(
537 args.outputdir,
538 'generated.cpp'), 'w') as fd:
539 fd.write(
540 self.render(
541 loader,
542 'generated.mako.cpp',
543 events=self.events,
Brad Bishop9b5a12f2017-01-21 14:42:11 -0500544 interfaces=self.interfaces,
545 indent=Indent()))
Brad Bishopbf066a62016-10-19 08:09:44 -0400546
Brad Bishop95dd98f2016-11-12 12:39:15 -0500547
548if __name__ == '__main__':
549 script_dir = os.path.dirname(os.path.realpath(__file__))
Brad Bishop14a9fe52016-11-12 12:51:26 -0500550 valid_commands = {
551 'generate-cpp': 'generate_cpp',
Brad Bishop22cfbe62016-11-30 13:25:10 -0500552 }
Brad Bishop95dd98f2016-11-12 12:39:15 -0500553
554 parser = argparse.ArgumentParser(
555 description='Phosphor Inventory Manager (PIM) YAML '
556 'scanner and code generator.')
557 parser.add_argument(
558 '-o', '--output-dir', dest='outputdir',
559 default='.', help='Output directory.')
560 parser.add_argument(
Brad Bishop834989f2017-02-06 12:08:20 -0500561 '-i', '--interfaces-dir', dest='ifacesdir',
562 help='Location of interfaces to be supported.')
563 parser.add_argument(
Brad Bishop95dd98f2016-11-12 12:39:15 -0500564 '-d', '--dir', dest='inputdir',
565 default=os.path.join(script_dir, 'example'),
566 help='Location of files to process.')
Brad Bishopf4666f52016-11-12 12:44:42 -0500567 parser.add_argument(
568 'command', metavar='COMMAND', type=str,
569 choices=valid_commands.keys(),
Brad Bishopc029f6a2017-01-18 19:43:26 -0500570 help='%s.' % " | ".join(valid_commands.keys()))
Brad Bishop95dd98f2016-11-12 12:39:15 -0500571
572 args = parser.parse_args()
Brad Bishop22cfbe62016-11-30 13:25:10 -0500573
574 if sys.version_info < (3, 0):
575 lookup = mako.lookup.TemplateLookup(
576 directories=[script_dir],
577 disable_unicode=True)
578 else:
579 lookup = mako.lookup.TemplateLookup(
580 directories=[script_dir])
581
582 function = getattr(
583 Everything.load(args),
584 valid_commands[args.command])
585 function(lookup)
Brad Bishop95dd98f2016-11-12 12:39:15 -0500586
587
Brad Bishopbf066a62016-10-19 08:09:44 -0400588# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4