blob: deaeb5928dff821150f492390719c77a96079b17 [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
77class Quote(object):
78 '''Decorate an argument by quoting it.'''
79
80 def __call__(self, arg):
81 return '"{0}"'.format(arg)
82
83
84class Cast(object):
85 '''Decorate an argument by casting it.'''
86
87 def __init__(self, cast, target):
88 '''cast is the cast type (static, const, etc...).
89 target is the cast target type.'''
90 self.cast = cast
91 self.target = target
92
93 def __call__(self, arg):
94 return '{0}_cast<{1}>({2})'.format(self.cast, self.target, arg)
95
96
97class Literal(object):
98 '''Decorate an argument with a literal operator.'''
99
100 literals = {
101 'string': 's',
102 'int64': 'll',
103 'uint64': 'ull'
104 }
105
106 def __init__(self, type):
107 self.type = type
108
109 def __call__(self, arg):
110 literal = self.literals.get(self.type)
111
112 if literal:
113 return '{0}{1}'.format(arg, literal)
114
115 return arg
116
117
Brad Bishop75800cf2017-01-21 15:24:18 -0500118class Argument(NamedElement, Renderer):
119 '''Define argument type inteface.'''
120
121 def __init__(self, **kw):
122 self.type = kw.pop('type', None)
123 super(Argument, self).__init__(**kw)
124
125 def argument(self, loader, indent):
126 raise NotImplementedError
127
128
129class TrivialArgument(Argument):
130 '''Non-array type arguments.'''
Brad Bishop14a9fe52016-11-12 12:51:26 -0500131
Brad Bishop22cfbe62016-11-30 13:25:10 -0500132 def __init__(self, **kw):
133 self.value = kw.pop('value')
Brad Bishop75800cf2017-01-21 15:24:18 -0500134 self.decorators = kw.pop('decorators', [])
135 if kw.get('type', None) == 'string':
136 self.decorators.insert(0, Quote())
137
Brad Bishop75800cf2017-01-21 15:24:18 -0500138 super(TrivialArgument, self).__init__(**kw)
139
140 def argument(self, loader, indent):
141 a = str(self.value)
142 for d in self.decorators:
143 a = d(a)
144
145 return a
Brad Bishop14a9fe52016-11-12 12:51:26 -0500146
Brad Bishop14a9fe52016-11-12 12:51:26 -0500147
Brad Bishop9b5a12f2017-01-21 14:42:11 -0500148class InitializerList(Argument):
149 '''Initializer list arguments.'''
150
151 def __init__(self, **kw):
152 self.values = kw.pop('values')
153 super(InitializerList, self).__init__(**kw)
154
155 def argument(self, loader, indent):
156 return self.render(
157 loader,
158 'argument.mako.cpp',
159 arg=self,
160 indent=indent)
161
162
Brad Bishop75800cf2017-01-21 15:24:18 -0500163class DbusSignature(Argument):
164 '''DBus signature arguments.'''
165
166 def __init__(self, **kw):
167 self.sig = {x: y for x, y in kw.iteritems()}
168 kw.clear()
169 super(DbusSignature, self).__init__(**kw)
170
171 def argument(self, loader, indent):
172 return self.render(
173 loader,
174 'signature.mako.cpp',
175 signature=self,
176 indent=indent)
177
178
Brad Bishopc93bcc92017-01-21 16:23:39 -0500179class MethodCall(Argument):
Brad Bishop22cfbe62016-11-30 13:25:10 -0500180 '''Render syntatically correct c++ method calls.'''
181
182 def __init__(self, **kw):
183 self.namespace = kw.pop('namespace', [])
Brad Bishopc93bcc92017-01-21 16:23:39 -0500184 self.templates = kw.pop('templates', [])
185 self.args = kw.pop('args', [])
Brad Bishop22cfbe62016-11-30 13:25:10 -0500186 super(MethodCall, self).__init__(**kw)
187
Brad Bishopcab2bdd2017-01-21 15:00:54 -0500188 def call(self, loader, indent):
189 return self.render(
190 loader,
191 'method.mako.cpp',
192 method=self,
193 indent=indent)
194
195 def argument(self, loader, indent):
196 return self.call(loader, indent)
197
Brad Bishop14a9fe52016-11-12 12:51:26 -0500198
Brad Bishop9b5a12f2017-01-21 14:42:11 -0500199class Vector(MethodCall):
200 '''Convenience type for vectors.'''
201
202 def __init__(self, **kw):
203 kw['name'] = 'vector'
204 kw['namespace'] = ['std']
205 kw['args'] = [InitializerList(values=kw.pop('args'))]
206 super(Vector, self).__init__(**kw)
207
208
Brad Bishopc1f47982017-02-09 01:27:38 -0500209class Filter(MethodCall):
Brad Bishopc93bcc92017-01-21 16:23:39 -0500210 '''Convenience type for filters'''
Brad Bishopbf066a62016-10-19 08:09:44 -0400211
Brad Bishop22cfbe62016-11-30 13:25:10 -0500212 def __init__(self, **kw):
Brad Bishopc1f47982017-02-09 01:27:38 -0500213 kw['name'] = 'make_filter'
Brad Bishop22cfbe62016-11-30 13:25:10 -0500214 super(Filter, self).__init__(**kw)
Brad Bishopbf066a62016-10-19 08:09:44 -0400215
Brad Bishop0a6a4792016-11-12 12:10:07 -0500216
Brad Bishopc1f47982017-02-09 01:27:38 -0500217class Action(MethodCall):
Brad Bishopc93bcc92017-01-21 16:23:39 -0500218 '''Convenience type for actions'''
Brad Bishop561a5652016-10-26 21:13:32 -0500219
Brad Bishop22cfbe62016-11-30 13:25:10 -0500220 def __init__(self, **kw):
Brad Bishopc1f47982017-02-09 01:27:38 -0500221 kw['name'] = 'make_action'
Brad Bishop22cfbe62016-11-30 13:25:10 -0500222 super(Action, self).__init__(**kw)
Brad Bishop92665b22016-10-26 20:51:16 -0500223
Brad Bishopcfb3c892016-11-12 11:43:37 -0500224
Brad Bishopd0f48ad2017-01-30 08:52:26 -0500225class PathCondition(MethodCall):
226 '''Convenience type for path conditions'''
227
228 def __init__(self, **kw):
229 kw['name'] = 'make_path_condition'
230 super(PathCondition, self).__init__(**kw)
231
232
Brad Bishopc1f47982017-02-09 01:27:38 -0500233class CreateObjects(MethodCall):
234 '''Assemble a createObjects functor.'''
Brad Bishopdb92c282017-01-21 23:44:28 -0500235
236 def __init__(self, **kw):
237 objs = []
238
239 for path, interfaces in kw.pop('objs').iteritems():
240 key_o = TrivialArgument(
241 value=path,
242 type='string',
243 decorators=[Literal('string')])
244 value_i = []
245
246 for interface, properties, in interfaces.iteritems():
247 key_i = TrivialArgument(value=interface, type='string')
248 value_p = []
249
250 for prop, value in properties.iteritems():
251 key_p = TrivialArgument(value=prop, type='string')
252 value_v = TrivialArgument(
253 decorators=[Literal(value.get('type', None))],
254 **value)
255 value_p.append(InitializerList(values=[key_p, value_v]))
256
257 value_p = InitializerList(values=value_p)
258 value_i.append(InitializerList(values=[key_i, value_p]))
259
260 value_i = InitializerList(values=value_i)
261 objs.append(InitializerList(values=[key_o, value_i]))
262
263 kw['args'] = [InitializerList(values=objs)]
Brad Bishopc1f47982017-02-09 01:27:38 -0500264 kw['namespace'] = ['functor']
Brad Bishopdb92c282017-01-21 23:44:28 -0500265 super(CreateObjects, self).__init__(**kw)
266
267
Brad Bishopc1f47982017-02-09 01:27:38 -0500268class DestroyObjects(MethodCall):
269 '''Assemble a destroyObject functor.'''
Brad Bishop22cfbe62016-11-30 13:25:10 -0500270
271 def __init__(self, **kw):
Brad Bishop7b7e7122017-01-21 21:21:46 -0500272 values = [{'value': x, 'type': 'string'} for x in kw.pop('paths')]
Brad Bishopd0f48ad2017-01-30 08:52:26 -0500273 conditions = [
274 Event.functor_map[
275 x['name']](**x) for x in kw.pop('conditions', [])]
276 conditions = [PathCondition(args=[x]) for x in conditions]
Brad Bishop7b7e7122017-01-21 21:21:46 -0500277 args = [InitializerList(
278 values=[TrivialArgument(**x) for x in values])]
Brad Bishopd0f48ad2017-01-30 08:52:26 -0500279 args.append(InitializerList(values=conditions))
Brad Bishopc93bcc92017-01-21 16:23:39 -0500280 kw['args'] = args
Brad Bishopc1f47982017-02-09 01:27:38 -0500281 kw['namespace'] = ['functor']
Brad Bishop7b7e7122017-01-21 21:21:46 -0500282 super(DestroyObjects, self).__init__(**kw)
Brad Bishop22cfbe62016-11-30 13:25:10 -0500283
284
Brad Bishopc1f47982017-02-09 01:27:38 -0500285class SetProperty(MethodCall):
286 '''Assemble a setProperty functor.'''
Brad Bishope2e402f2016-11-30 18:00:17 -0500287
288 def __init__(self, **kw):
Brad Bishopc93bcc92017-01-21 16:23:39 -0500289 args = []
290
291 value = kw.pop('value')
292 prop = kw.pop('property')
293 iface = kw.pop('interface')
294 iface = Interface(iface)
295 namespace = iface.namespace().split('::')[:-1]
296 name = iface[-1]
297 t = Template(namespace=namespace, name=iface[-1])
298
Brad Bishope2e402f2016-11-30 18:00:17 -0500299 member = '&%s' % '::'.join(
Brad Bishopc93bcc92017-01-21 16:23:39 -0500300 namespace + [name, NamedElement(name=prop).camelCase])
301 member_type = cppTypeName(value['type'])
302 member_cast = '{0} ({1}::*)({0})'.format(member_type, t.qualified())
Brad Bishope2e402f2016-11-30 18:00:17 -0500303
Brad Bishop02ca0212017-01-28 23:25:58 -0500304 paths = [{'value': x, 'type': 'string'} for x in kw.pop('paths')]
305 args.append(InitializerList(
306 values=[TrivialArgument(**x) for x in paths]))
307
Brad Bishopd0f48ad2017-01-30 08:52:26 -0500308 conditions = [
309 Event.functor_map[
310 x['name']](**x) for x in kw.pop('conditions', [])]
311 conditions = [PathCondition(args=[x]) for x in conditions]
312
313 args.append(InitializerList(values=conditions))
Brad Bishopc93bcc92017-01-21 16:23:39 -0500314 args.append(TrivialArgument(value=str(iface), type='string'))
315 args.append(TrivialArgument(
316 value=member, decorators=[Cast('static', member_cast)]))
317 args.append(TrivialArgument(**value))
Brad Bishope2e402f2016-11-30 18:00:17 -0500318
Brad Bishopc93bcc92017-01-21 16:23:39 -0500319 kw['templates'] = [Template(name=name, namespace=namespace)]
320 kw['args'] = args
Brad Bishopc1f47982017-02-09 01:27:38 -0500321 kw['namespace'] = ['functor']
Brad Bishope2e402f2016-11-30 18:00:17 -0500322 super(SetProperty, self).__init__(**kw)
323
324
Brad Bishopc1f47982017-02-09 01:27:38 -0500325class PropertyChanged(MethodCall):
326 '''Assemble a propertyChanged functor.'''
Brad Bishop22cfbe62016-11-30 13:25:10 -0500327
328 def __init__(self, **kw):
Brad Bishopc93bcc92017-01-21 16:23:39 -0500329 args = []
330 args.append(TrivialArgument(value=kw.pop('interface'), type='string'))
331 args.append(TrivialArgument(value=kw.pop('property'), type='string'))
332 args.append(TrivialArgument(
333 decorators=[
334 Literal(kw['value'].get('type', None))], **kw.pop('value')))
335 kw['args'] = args
Brad Bishopc1f47982017-02-09 01:27:38 -0500336 kw['namespace'] = ['functor']
Brad Bishop22cfbe62016-11-30 13:25:10 -0500337 super(PropertyChanged, self).__init__(**kw)
338
339
Brad Bishopc1f47982017-02-09 01:27:38 -0500340class PropertyIs(MethodCall):
341 '''Assemble a propertyIs functor.'''
Brad Bishop040e18b2017-01-21 22:04:00 -0500342
343 def __init__(self, **kw):
344 args = []
Brad Bishopd0f48ad2017-01-30 08:52:26 -0500345 path = kw.pop('path', None)
346 if not path:
347 path = TrivialArgument(value='nullptr')
348 else:
349 path = TrivialArgument(value=path, type='string')
350
351 args.append(path)
Brad Bishop040e18b2017-01-21 22:04:00 -0500352 args.append(TrivialArgument(value=kw.pop('interface'), type='string'))
353 args.append(TrivialArgument(value=kw.pop('property'), type='string'))
354 args.append(TrivialArgument(
355 decorators=[
356 Literal(kw['value'].get('type', None))], **kw.pop('value')))
357
358 service = kw.pop('service', None)
359 if service:
360 args.append(TrivialArgument(value=service, type='string'))
361
362 kw['args'] = args
Brad Bishopc1f47982017-02-09 01:27:38 -0500363 kw['namespace'] = ['functor']
Brad Bishop040e18b2017-01-21 22:04:00 -0500364 super(PropertyIs, self).__init__(**kw)
365
366
Brad Bishopc93bcc92017-01-21 16:23:39 -0500367class Event(MethodCall):
368 '''Assemble an inventory manager event.'''
Brad Bishop22cfbe62016-11-30 13:25:10 -0500369
Brad Bishopd0f48ad2017-01-30 08:52:26 -0500370 functor_map = {
Brad Bishop7b7e7122017-01-21 21:21:46 -0500371 'destroyObjects': DestroyObjects,
Brad Bishopdb92c282017-01-21 23:44:28 -0500372 'createObjects': CreateObjects,
Brad Bishopc93bcc92017-01-21 16:23:39 -0500373 'propertyChangedTo': PropertyChanged,
Brad Bishop040e18b2017-01-21 22:04:00 -0500374 'propertyIs': PropertyIs,
Brad Bishopd0f48ad2017-01-30 08:52:26 -0500375 'setProperty': SetProperty,
Brad Bishopc93bcc92017-01-21 16:23:39 -0500376 }
377
Brad Bishop22cfbe62016-11-30 13:25:10 -0500378 def __init__(self, **kw):
Brad Bishopc93bcc92017-01-21 16:23:39 -0500379 self.summary = kw.pop('name')
380
381 filters = [
Brad Bishopd0f48ad2017-01-30 08:52:26 -0500382 self.functor_map[x['name']](**x) for x in kw.pop('filters', [])]
Brad Bishopc1f47982017-02-09 01:27:38 -0500383 filters = [Filter(args=[x]) for x in filters]
Brad Bishop064c94a2017-01-21 21:33:30 -0500384 filters = Vector(
Brad Bishop12f8a3c2017-02-09 00:02:00 -0500385 templates=[Template(name='Filter', namespace=[])],
Brad Bishop064c94a2017-01-21 21:33:30 -0500386 args=filters)
Brad Bishopc93bcc92017-01-21 16:23:39 -0500387
388 event = MethodCall(
389 name='make_shared',
390 namespace=['std'],
391 templates=[Template(
392 name=kw.pop('event'),
393 namespace=kw.pop('event_namespace', []))],
Brad Bishop064c94a2017-01-21 21:33:30 -0500394 args=kw.pop('event_args', []) + [filters])
Brad Bishopc93bcc92017-01-21 16:23:39 -0500395
396 events = Vector(
Brad Bishop12f8a3c2017-02-09 00:02:00 -0500397 templates=[Template(name='EventBasePtr', namespace=[])],
Brad Bishopc93bcc92017-01-21 16:23:39 -0500398 args=[event])
399
Brad Bishop12f8a3c2017-02-09 00:02:00 -0500400 action_type = Template(name='Action', namespace=[])
Brad Bishopc93bcc92017-01-21 16:23:39 -0500401 action_args = [
Brad Bishopd0f48ad2017-01-30 08:52:26 -0500402 self.functor_map[x['name']](**x) for x in kw.pop('actions', [])]
Brad Bishopc1f47982017-02-09 01:27:38 -0500403 action_args = [Action(args=[x]) for x in action_args]
Brad Bishopc93bcc92017-01-21 16:23:39 -0500404 actions = Vector(
405 templates=[action_type],
406 args=action_args)
407
408 kw['name'] = 'make_tuple'
409 kw['namespace'] = ['std']
410 kw['args'] = [events, actions]
Brad Bishop22cfbe62016-11-30 13:25:10 -0500411 super(Event, self).__init__(**kw)
Brad Bishopcfb3c892016-11-12 11:43:37 -0500412
Brad Bishopcfb3c892016-11-12 11:43:37 -0500413
Brad Bishop22cfbe62016-11-30 13:25:10 -0500414class MatchEvent(Event):
415 '''Associate one or more dbus signal match signatures with
416 a filter.'''
417
Brad Bishop22cfbe62016-11-30 13:25:10 -0500418 def __init__(self, **kw):
Brad Bishopc93bcc92017-01-21 16:23:39 -0500419 kw['event'] = 'DbusSignal'
Brad Bishop12f8a3c2017-02-09 00:02:00 -0500420 kw['event_namespace'] = []
Brad Bishopc93bcc92017-01-21 16:23:39 -0500421 kw['event_args'] = [
422 DbusSignature(**x) for x in kw.pop('signatures', [])]
423
Brad Bishop22cfbe62016-11-30 13:25:10 -0500424 super(MatchEvent, self).__init__(**kw)
425
426
Brad Bishop828df832017-01-21 22:20:43 -0500427class StartupEvent(Event):
428 '''Assemble a startup event.'''
429
430 def __init__(self, **kw):
431 kw['event'] = 'StartupEvent'
Brad Bishop12f8a3c2017-02-09 00:02:00 -0500432 kw['event_namespace'] = []
Brad Bishop828df832017-01-21 22:20:43 -0500433 super(StartupEvent, self).__init__(**kw)
434
435
Brad Bishop22cfbe62016-11-30 13:25:10 -0500436class Everything(Renderer):
437 '''Parse/render entry point.'''
438
439 class_map = {
440 'match': MatchEvent,
Brad Bishop828df832017-01-21 22:20:43 -0500441 'startup': StartupEvent,
Brad Bishop22cfbe62016-11-30 13:25:10 -0500442 }
443
444 @staticmethod
445 def load(args):
Brad Bishop22cfbe62016-11-30 13:25:10 -0500446 # Aggregate all the event YAML in the events.d directory
447 # into a single list of events.
448
Brad Bishop22cfbe62016-11-30 13:25:10 -0500449 events = []
Brad Bishopa6fcd562017-02-03 11:00:27 -0500450 events_dir = os.path.join(args.inputdir, 'events.d')
451
452 if os.path.exists(events_dir):
453 yaml_files = filter(
454 lambda x: x.endswith('.yaml'),
455 os.listdir(events_dir))
456
457 for x in yaml_files:
458 with open(os.path.join(events_dir, x), 'r') as fd:
459 for e in yaml.safe_load(fd.read()).get('events', {}):
460 events.append(e)
Brad Bishop22cfbe62016-11-30 13:25:10 -0500461
462 return Everything(
463 *events,
464 interfaces=Everything.get_interfaces(args))
465
466 @staticmethod
467 def get_interfaces(args):
468 '''Aggregate all the interface YAML in the interfaces.d
469 directory into a single list of interfaces.'''
470
Brad Bishop22cfbe62016-11-30 13:25:10 -0500471 interfaces = []
Brad Bishopa6fcd562017-02-03 11:00:27 -0500472 interfaces_dir = os.path.join(args.inputdir, 'interfaces.d')
473 if os.path.exists(interfaces_dir):
474 yaml_files = filter(
475 lambda x: x.endswith('.yaml'),
476 os.listdir(interfaces_dir))
477
478 for x in yaml_files:
479 with open(os.path.join(interfaces_dir, x), 'r') as fd:
480 for i in yaml.safe_load(fd.read()):
481 interfaces.append(i)
Brad Bishop22cfbe62016-11-30 13:25:10 -0500482
483 return interfaces
484
485 def __init__(self, *a, **kw):
486 self.interfaces = \
487 [Interface(x) for x in kw.pop('interfaces', [])]
488 self.events = [
489 self.class_map[x['type']](**x) for x in a]
490 super(Everything, self).__init__(**kw)
491
Brad Bishop22cfbe62016-11-30 13:25:10 -0500492 def generate_cpp(self, loader):
493 '''Render the template with the provided events and interfaces.'''
494 with open(os.path.join(
495 args.outputdir,
496 'generated.cpp'), 'w') as fd:
497 fd.write(
498 self.render(
499 loader,
500 'generated.mako.cpp',
501 events=self.events,
Brad Bishop9b5a12f2017-01-21 14:42:11 -0500502 interfaces=self.interfaces,
503 indent=Indent()))
Brad Bishopbf066a62016-10-19 08:09:44 -0400504
Brad Bishop95dd98f2016-11-12 12:39:15 -0500505
506if __name__ == '__main__':
507 script_dir = os.path.dirname(os.path.realpath(__file__))
Brad Bishop14a9fe52016-11-12 12:51:26 -0500508 valid_commands = {
509 'generate-cpp': 'generate_cpp',
Brad Bishop22cfbe62016-11-30 13:25:10 -0500510 }
Brad Bishop95dd98f2016-11-12 12:39:15 -0500511
512 parser = argparse.ArgumentParser(
513 description='Phosphor Inventory Manager (PIM) YAML '
514 'scanner and code generator.')
515 parser.add_argument(
516 '-o', '--output-dir', dest='outputdir',
517 default='.', help='Output directory.')
518 parser.add_argument(
519 '-d', '--dir', dest='inputdir',
520 default=os.path.join(script_dir, 'example'),
521 help='Location of files to process.')
Brad Bishopf4666f52016-11-12 12:44:42 -0500522 parser.add_argument(
523 'command', metavar='COMMAND', type=str,
524 choices=valid_commands.keys(),
Brad Bishopc029f6a2017-01-18 19:43:26 -0500525 help='%s.' % " | ".join(valid_commands.keys()))
Brad Bishop95dd98f2016-11-12 12:39:15 -0500526
527 args = parser.parse_args()
Brad Bishop22cfbe62016-11-30 13:25:10 -0500528
529 if sys.version_info < (3, 0):
530 lookup = mako.lookup.TemplateLookup(
531 directories=[script_dir],
532 disable_unicode=True)
533 else:
534 lookup = mako.lookup.TemplateLookup(
535 directories=[script_dir])
536
537 function = getattr(
538 Everything.load(args),
539 valid_commands[args.command])
540 function(lookup)
Brad Bishop95dd98f2016-11-12 12:39:15 -0500541
542
Brad Bishopbf066a62016-10-19 08:09:44 -0400543# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4