| Marri Devender Rao | 44fd7e8 | 2020-03-08 09:51:34 -0500 | [diff] [blame] | 1 | #!/usr/bin/env python3 | 
| Matthew Barth | db440d4 | 2017-04-17 15:49:37 -0500 | [diff] [blame] | 2 |  | 
| Brad Bishop | 34a7acd | 2017-04-27 23:47:23 -0400 | [diff] [blame] | 3 | '''Phosphor DBus Monitor YAML parser and code generator. | 
|  | 4 |  | 
|  | 5 | The 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 |  | 
| Matthew Barth | db440d4 | 2017-04-17 15:49:37 -0500 | [diff] [blame] | 18 | import os | 
|  | 19 | import sys | 
|  | 20 | import yaml | 
| Brad Bishop | 34a7acd | 2017-04-27 23:47:23 -0400 | [diff] [blame] | 21 | import mako.lookup | 
| Matthew Barth | db440d4 | 2017-04-17 15:49:37 -0500 | [diff] [blame] | 22 | from argparse import ArgumentParser | 
| Brad Bishop | 34a7acd | 2017-04-27 23:47:23 -0400 | [diff] [blame] | 23 | from sdbusplus.renderer import Renderer | 
| Brad Bishop | 05b0c1e | 2017-05-23 00:24:01 -0400 | [diff] [blame] | 24 | from sdbusplus.namedelement import NamedElement | 
| Brad Bishop | e73b2c3 | 2017-05-23 18:01:54 -0400 | [diff] [blame] | 25 | import sdbusplus.property | 
| Brad Bishop | 05b0c1e | 2017-05-23 00:24:01 -0400 | [diff] [blame] | 26 |  | 
|  | 27 |  | 
|  | 28 | class InvalidConfigError(BaseException): | 
|  | 29 | '''General purpose config file parsing error.''' | 
|  | 30 |  | 
|  | 31 | def __init__(self, path, msg): | 
|  | 32 | '''Display configuration file with the syntax | 
|  | 33 | error and the error message.''' | 
|  | 34 |  | 
|  | 35 | self.config = path | 
|  | 36 | self.msg = msg | 
|  | 37 |  | 
|  | 38 |  | 
|  | 39 | class NotUniqueError(InvalidConfigError): | 
|  | 40 | '''Within a config file names must be unique. | 
|  | 41 | Display the config file with the duplicate and | 
|  | 42 | the duplicate itself.''' | 
|  | 43 |  | 
|  | 44 | def __init__(self, path, cls, *names): | 
|  | 45 | fmt = 'Duplicate {0}: "{1}"' | 
|  | 46 | super(NotUniqueError, self).__init__( | 
|  | 47 | path, fmt.format(cls, ' '.join(names))) | 
|  | 48 |  | 
|  | 49 |  | 
|  | 50 | def get_index(objs, cls, name, config=None): | 
|  | 51 | '''Items are usually rendered as C++ arrays and as | 
|  | 52 | such are stored in python lists.  Given an item name | 
|  | 53 | its class, and an optional config file filter, find | 
|  | 54 | the item index.''' | 
|  | 55 |  | 
|  | 56 | for i, x in enumerate(objs.get(cls, [])): | 
|  | 57 | if config and x.configfile != config: | 
|  | 58 | continue | 
|  | 59 | if x.name != name: | 
|  | 60 | continue | 
|  | 61 |  | 
|  | 62 | return i | 
|  | 63 | raise InvalidConfigError(config, 'Could not find name: "{0}"'.format(name)) | 
|  | 64 |  | 
|  | 65 |  | 
|  | 66 | def exists(objs, cls, name, config=None): | 
|  | 67 | '''Check to see if an item already exists in a list given | 
|  | 68 | the item name.''' | 
|  | 69 |  | 
|  | 70 | try: | 
|  | 71 | get_index(objs, cls, name, config) | 
|  | 72 | except: | 
|  | 73 | return False | 
|  | 74 |  | 
|  | 75 | return True | 
|  | 76 |  | 
|  | 77 |  | 
|  | 78 | def add_unique(obj, *a, **kw): | 
|  | 79 | '''Add an item to one or more lists unless already present, | 
|  | 80 | with an option to constrain the search to a specific config file.''' | 
|  | 81 |  | 
|  | 82 | for container in a: | 
|  | 83 | if not exists(container, obj.cls, obj.name, config=kw.get('config')): | 
|  | 84 | container.setdefault(obj.cls, []).append(obj) | 
| Matthew Barth | db440d4 | 2017-04-17 15:49:37 -0500 | [diff] [blame] | 85 |  | 
|  | 86 |  | 
| Brad Bishop | 0107989 | 2017-05-26 10:56:45 -0400 | [diff] [blame] | 87 | class Cast(object): | 
|  | 88 | '''Decorate an argument by casting it.''' | 
|  | 89 |  | 
|  | 90 | def __init__(self, cast, target): | 
|  | 91 | '''cast is the cast type (static, const, etc...). | 
|  | 92 | target is the cast target type.''' | 
|  | 93 | self.cast = cast | 
|  | 94 | self.target = target | 
|  | 95 |  | 
|  | 96 | def __call__(self, arg): | 
|  | 97 | return '{0}_cast<{1}>({2})'.format(self.cast, self.target, arg) | 
|  | 98 |  | 
|  | 99 |  | 
|  | 100 | class Literal(object): | 
|  | 101 | '''Decorate an argument with a literal operator.''' | 
|  | 102 |  | 
|  | 103 | integer_types = [ | 
| Brad Bishop | 0107989 | 2017-05-26 10:56:45 -0400 | [diff] [blame] | 104 | 'int16', | 
|  | 105 | 'int32', | 
|  | 106 | 'int64', | 
| Brad Bishop | 0107989 | 2017-05-26 10:56:45 -0400 | [diff] [blame] | 107 | 'uint16', | 
|  | 108 | 'uint32', | 
|  | 109 | 'uint64' | 
|  | 110 | ] | 
|  | 111 |  | 
|  | 112 | def __init__(self, type): | 
|  | 113 | self.type = type | 
|  | 114 |  | 
|  | 115 | def __call__(self, arg): | 
|  | 116 | if 'uint' in self.type: | 
|  | 117 | arg = '{0}ull'.format(arg) | 
|  | 118 | elif 'int' in self.type: | 
|  | 119 | arg = '{0}ll'.format(arg) | 
|  | 120 |  | 
|  | 121 | if self.type in self.integer_types: | 
|  | 122 | return Cast('static', '{0}_t'.format(self.type))(arg) | 
| Brad Bishop | ec2ed2f | 2017-05-31 21:10:43 -0400 | [diff] [blame] | 123 | elif self.type == 'byte': | 
|  | 124 | return Cast('static', 'uint8_t'.format(self.type))(arg) | 
| Harvey.Wu | afa54c6 | 2022-03-30 18:56:36 +0800 | [diff] [blame^] | 125 | elif self.type == 'double': | 
|  | 126 | return Cast('static', 'double'.format(self.type))(arg) | 
| Brad Bishop | 0107989 | 2017-05-26 10:56:45 -0400 | [diff] [blame] | 127 |  | 
|  | 128 | if self.type == 'string': | 
|  | 129 | return '{0}s'.format(arg) | 
|  | 130 |  | 
|  | 131 | return arg | 
|  | 132 |  | 
|  | 133 |  | 
|  | 134 | class FixBool(object): | 
|  | 135 | '''Un-capitalize booleans.''' | 
|  | 136 |  | 
|  | 137 | def __call__(self, arg): | 
|  | 138 | return '{0}'.format(arg.lower()) | 
|  | 139 |  | 
|  | 140 |  | 
|  | 141 | class Quote(object): | 
|  | 142 | '''Decorate an argument by quoting it.''' | 
|  | 143 |  | 
|  | 144 | def __call__(self, arg): | 
|  | 145 | return '"{0}"'.format(arg) | 
|  | 146 |  | 
|  | 147 |  | 
|  | 148 | class Argument(NamedElement, Renderer): | 
| Gunnar Mills | 06fdaff | 2018-04-08 16:28:18 -0500 | [diff] [blame] | 149 | '''Define argument type interface.''' | 
| Brad Bishop | 0107989 | 2017-05-26 10:56:45 -0400 | [diff] [blame] | 150 |  | 
|  | 151 | def __init__(self, **kw): | 
|  | 152 | self.type = kw.pop('type', None) | 
|  | 153 | super(Argument, self).__init__(**kw) | 
|  | 154 |  | 
|  | 155 | def argument(self, loader, indent): | 
|  | 156 | raise NotImplementedError | 
|  | 157 |  | 
|  | 158 |  | 
|  | 159 | class TrivialArgument(Argument): | 
|  | 160 | '''Non-array type arguments.''' | 
|  | 161 |  | 
|  | 162 | def __init__(self, **kw): | 
|  | 163 | self.value = kw.pop('value') | 
|  | 164 | self.decorators = kw.pop('decorators', []) | 
|  | 165 | if kw.get('type', None): | 
|  | 166 | self.decorators.insert(0, Literal(kw['type'])) | 
|  | 167 | if kw.get('type', None) == 'string': | 
|  | 168 | self.decorators.insert(0, Quote()) | 
|  | 169 | if kw.get('type', None) == 'boolean': | 
|  | 170 | self.decorators.insert(0, FixBool()) | 
|  | 171 |  | 
|  | 172 | super(TrivialArgument, self).__init__(**kw) | 
|  | 173 |  | 
|  | 174 | def argument(self, loader, indent): | 
|  | 175 | a = str(self.value) | 
|  | 176 | for d in self.decorators: | 
|  | 177 | a = d(a) | 
|  | 178 |  | 
|  | 179 | return a | 
|  | 180 |  | 
| Matt Spinler | 80e9b65 | 2017-11-02 14:21:04 -0500 | [diff] [blame] | 181 |  | 
| Gunnar Mills | 30474cf | 2017-08-11 09:38:54 -0500 | [diff] [blame] | 182 | class Metadata(Argument): | 
|  | 183 | '''Metadata type arguments.''' | 
|  | 184 |  | 
|  | 185 | def __init__(self, **kw): | 
|  | 186 | self.value = kw.pop('value') | 
|  | 187 | self.decorators = kw.pop('decorators', []) | 
|  | 188 | if kw.get('type', None) == 'string': | 
|  | 189 | self.decorators.insert(0, Quote()) | 
|  | 190 |  | 
|  | 191 | super(Metadata, self).__init__(**kw) | 
|  | 192 |  | 
|  | 193 | def argument(self, loader, indent): | 
|  | 194 | a = str(self.value) | 
|  | 195 | for d in self.decorators: | 
|  | 196 | a = d(a) | 
|  | 197 |  | 
|  | 198 | return a | 
| Brad Bishop | 0107989 | 2017-05-26 10:56:45 -0400 | [diff] [blame] | 199 |  | 
| Matt Spinler | 80e9b65 | 2017-11-02 14:21:04 -0500 | [diff] [blame] | 200 |  | 
| Matthew Barth | ae786ef | 2019-09-04 15:46:13 -0500 | [diff] [blame] | 201 | class OpArgument(Argument): | 
|  | 202 | '''Operation type arguments.''' | 
|  | 203 |  | 
|  | 204 | def __init__(self, **kw): | 
|  | 205 | self.op = kw.pop('op') | 
|  | 206 | self.bound = kw.pop('bound') | 
|  | 207 | self.decorators = kw.pop('decorators', []) | 
|  | 208 | if kw.get('type', None): | 
|  | 209 | self.decorators.insert(0, Literal(kw['type'])) | 
|  | 210 | if kw.get('type', None) == 'string': | 
|  | 211 | self.decorators.insert(0, Quote()) | 
|  | 212 | if kw.get('type', None) == 'boolean': | 
|  | 213 | self.decorators.insert(0, FixBool()) | 
|  | 214 |  | 
|  | 215 | super(OpArgument, self).__init__(**kw) | 
|  | 216 |  | 
|  | 217 | def argument(self, loader, indent): | 
|  | 218 | a = str(self.bound) | 
|  | 219 | for d in self.decorators: | 
|  | 220 | a = d(a) | 
|  | 221 |  | 
|  | 222 | return a | 
|  | 223 |  | 
|  | 224 |  | 
| Brad Bishop | 34a7acd | 2017-04-27 23:47:23 -0400 | [diff] [blame] | 225 | class Indent(object): | 
|  | 226 | '''Help templates be depth agnostic.''' | 
| Matthew Barth | db440d4 | 2017-04-17 15:49:37 -0500 | [diff] [blame] | 227 |  | 
| Brad Bishop | 34a7acd | 2017-04-27 23:47:23 -0400 | [diff] [blame] | 228 | def __init__(self, depth=0): | 
|  | 229 | self.depth = depth | 
| Matthew Barth | db440d4 | 2017-04-17 15:49:37 -0500 | [diff] [blame] | 230 |  | 
| Brad Bishop | 34a7acd | 2017-04-27 23:47:23 -0400 | [diff] [blame] | 231 | def __add__(self, depth): | 
|  | 232 | return Indent(self.depth + depth) | 
|  | 233 |  | 
|  | 234 | def __call__(self, depth): | 
|  | 235 | '''Render an indent at the current depth plus depth.''' | 
|  | 236 | return 4*' '*(depth + self.depth) | 
|  | 237 |  | 
|  | 238 |  | 
| Brad Bishop | 05b0c1e | 2017-05-23 00:24:01 -0400 | [diff] [blame] | 239 | class ConfigEntry(NamedElement): | 
|  | 240 | '''Base interface for rendered items.''' | 
|  | 241 |  | 
|  | 242 | def __init__(self, *a, **kw): | 
|  | 243 | '''Pop the configfile/class/subclass keywords.''' | 
|  | 244 |  | 
|  | 245 | self.configfile = kw.pop('configfile') | 
|  | 246 | self.cls = kw.pop('class') | 
|  | 247 | self.subclass = kw.pop(self.cls) | 
| Patrick Williams | cfdfa0d | 2021-09-20 18:32:17 -0500 | [diff] [blame] | 248 |  | 
|  | 249 | # TODO: NamedElement requires 'name' to be a string, but in many cases | 
|  | 250 | #       this script treats 'name' as a dict.  Save the property off and | 
|  | 251 | #       insert it after ConfigEntry does its own thing to avoid | 
|  | 252 | #       exceptions.  This should be refactored throughout the whole | 
|  | 253 | #       script to not overload 'name' as a dict. | 
|  | 254 | name_save = kw.pop('name') | 
| Brad Bishop | 05b0c1e | 2017-05-23 00:24:01 -0400 | [diff] [blame] | 255 | super(ConfigEntry, self).__init__(**kw) | 
| Patrick Williams | cfdfa0d | 2021-09-20 18:32:17 -0500 | [diff] [blame] | 256 | self.name = name_save | 
| Brad Bishop | 05b0c1e | 2017-05-23 00:24:01 -0400 | [diff] [blame] | 257 |  | 
|  | 258 | def factory(self, objs): | 
|  | 259 | ''' Optional factory interface for subclasses to add | 
|  | 260 | additional items to be rendered.''' | 
|  | 261 |  | 
|  | 262 | pass | 
|  | 263 |  | 
|  | 264 | def setup(self, objs): | 
|  | 265 | ''' Optional setup interface for subclasses, invoked | 
|  | 266 | after all factory methods have been run.''' | 
|  | 267 |  | 
|  | 268 | pass | 
|  | 269 |  | 
|  | 270 |  | 
| Brad Bishop | 0e7df13 | 2017-05-23 17:58:12 -0400 | [diff] [blame] | 271 | class Path(ConfigEntry): | 
|  | 272 | '''Path/metadata association.''' | 
|  | 273 |  | 
|  | 274 | def __init__(self, *a, **kw): | 
|  | 275 | super(Path, self).__init__(**kw) | 
|  | 276 |  | 
| Brad Bishop | babf3b7 | 2017-05-31 19:44:53 -0400 | [diff] [blame] | 277 | if self.name['meta'].upper() != self.name['meta']: | 
|  | 278 | raise InvalidConfigError( | 
|  | 279 | self.configfile, | 
|  | 280 | 'Metadata tag "{0}" must be upper case.'.format( | 
|  | 281 | self.name['meta'])) | 
|  | 282 |  | 
| Brad Bishop | 0e7df13 | 2017-05-23 17:58:12 -0400 | [diff] [blame] | 283 | def factory(self, objs): | 
|  | 284 | '''Create path and metadata elements.''' | 
|  | 285 |  | 
|  | 286 | args = { | 
|  | 287 | 'class': 'pathname', | 
|  | 288 | 'pathname': 'element', | 
|  | 289 | 'name': self.name['path'] | 
|  | 290 | } | 
|  | 291 | add_unique(ConfigEntry( | 
|  | 292 | configfile=self.configfile, **args), objs) | 
|  | 293 |  | 
|  | 294 | args = { | 
|  | 295 | 'class': 'meta', | 
|  | 296 | 'meta': 'element', | 
|  | 297 | 'name': self.name['meta'] | 
|  | 298 | } | 
|  | 299 | add_unique(ConfigEntry( | 
|  | 300 | configfile=self.configfile, **args), objs) | 
|  | 301 |  | 
|  | 302 | super(Path, self).factory(objs) | 
|  | 303 |  | 
|  | 304 | def setup(self, objs): | 
| Gunnar Mills | 78199b4 | 2017-10-25 16:30:18 -0500 | [diff] [blame] | 305 | '''Resolve path and metadata names to indices.''' | 
| Brad Bishop | 0e7df13 | 2017-05-23 17:58:12 -0400 | [diff] [blame] | 306 |  | 
|  | 307 | self.path = get_index( | 
|  | 308 | objs, 'pathname', self.name['path']) | 
|  | 309 | self.meta = get_index( | 
|  | 310 | objs, 'meta', self.name['meta']) | 
|  | 311 |  | 
|  | 312 | super(Path, self).setup(objs) | 
|  | 313 |  | 
|  | 314 |  | 
| Brad Bishop | e73b2c3 | 2017-05-23 18:01:54 -0400 | [diff] [blame] | 315 | class Property(ConfigEntry): | 
|  | 316 | '''Property/interface/metadata association.''' | 
|  | 317 |  | 
|  | 318 | def __init__(self, *a, **kw): | 
|  | 319 | super(Property, self).__init__(**kw) | 
|  | 320 |  | 
| Brad Bishop | babf3b7 | 2017-05-31 19:44:53 -0400 | [diff] [blame] | 321 | if self.name['meta'].upper() != self.name['meta']: | 
|  | 322 | raise InvalidConfigError( | 
|  | 323 | self.configfile, | 
|  | 324 | 'Metadata tag "{0}" must be upper case.'.format( | 
|  | 325 | self.name['meta'])) | 
|  | 326 |  | 
| Brad Bishop | e73b2c3 | 2017-05-23 18:01:54 -0400 | [diff] [blame] | 327 | def factory(self, objs): | 
|  | 328 | '''Create interface, property name and metadata elements.''' | 
|  | 329 |  | 
|  | 330 | args = { | 
|  | 331 | 'class': 'interface', | 
|  | 332 | 'interface': 'element', | 
|  | 333 | 'name': self.name['interface'] | 
|  | 334 | } | 
|  | 335 | add_unique(ConfigEntry( | 
|  | 336 | configfile=self.configfile, **args), objs) | 
|  | 337 |  | 
|  | 338 | args = { | 
|  | 339 | 'class': 'propertyname', | 
|  | 340 | 'propertyname': 'element', | 
|  | 341 | 'name': self.name['property'] | 
|  | 342 | } | 
|  | 343 | add_unique(ConfigEntry( | 
|  | 344 | configfile=self.configfile, **args), objs) | 
|  | 345 |  | 
|  | 346 | args = { | 
|  | 347 | 'class': 'meta', | 
|  | 348 | 'meta': 'element', | 
|  | 349 | 'name': self.name['meta'] | 
|  | 350 | } | 
|  | 351 | add_unique(ConfigEntry( | 
|  | 352 | configfile=self.configfile, **args), objs) | 
|  | 353 |  | 
|  | 354 | super(Property, self).factory(objs) | 
|  | 355 |  | 
|  | 356 | def setup(self, objs): | 
| Gunnar Mills | 78199b4 | 2017-10-25 16:30:18 -0500 | [diff] [blame] | 357 | '''Resolve interface, property and metadata to indices.''' | 
| Brad Bishop | e73b2c3 | 2017-05-23 18:01:54 -0400 | [diff] [blame] | 358 |  | 
|  | 359 | self.interface = get_index( | 
|  | 360 | objs, 'interface', self.name['interface']) | 
|  | 361 | self.prop = get_index( | 
|  | 362 | objs, 'propertyname', self.name['property']) | 
|  | 363 | self.meta = get_index( | 
|  | 364 | objs, 'meta', self.name['meta']) | 
|  | 365 |  | 
|  | 366 | super(Property, self).setup(objs) | 
|  | 367 |  | 
|  | 368 |  | 
| Brad Bishop | 4b916f1 | 2017-05-23 18:06:38 -0400 | [diff] [blame] | 369 | class Instance(ConfigEntry): | 
|  | 370 | '''Property/Path association.''' | 
|  | 371 |  | 
|  | 372 | def __init__(self, *a, **kw): | 
|  | 373 | super(Instance, self).__init__(**kw) | 
|  | 374 |  | 
|  | 375 | def setup(self, objs): | 
| Gunnar Mills | 78199b4 | 2017-10-25 16:30:18 -0500 | [diff] [blame] | 376 | '''Resolve elements to indices.''' | 
| Brad Bishop | 4b916f1 | 2017-05-23 18:06:38 -0400 | [diff] [blame] | 377 |  | 
|  | 378 | self.interface = get_index( | 
|  | 379 | objs, 'interface', self.name['property']['interface']) | 
|  | 380 | self.prop = get_index( | 
|  | 381 | objs, 'propertyname', self.name['property']['property']) | 
|  | 382 | self.propmeta = get_index( | 
|  | 383 | objs, 'meta', self.name['property']['meta']) | 
|  | 384 | self.path = get_index( | 
|  | 385 | objs, 'pathname', self.name['path']['path']) | 
|  | 386 | self.pathmeta = get_index( | 
|  | 387 | objs, 'meta', self.name['path']['meta']) | 
|  | 388 |  | 
|  | 389 | super(Instance, self).setup(objs) | 
|  | 390 |  | 
| Marri Devender Rao | 80c7061 | 2018-04-12 09:22:55 -0500 | [diff] [blame] | 391 | class PathInstance(ConfigEntry): | 
|  | 392 | '''Path association.''' | 
|  | 393 |  | 
|  | 394 | def __init__(self, *a, **kw): | 
|  | 395 | super(PathInstance, self).__init__(**kw) | 
|  | 396 |  | 
|  | 397 | def setup(self, objs): | 
|  | 398 | '''Resolve elements to indices.''' | 
|  | 399 | self.path = self.name['path']['path'] | 
|  | 400 | self.pathmeta = self.name['path']['meta'] | 
|  | 401 | super(PathInstance, self).setup(objs) | 
| Brad Bishop | 4b916f1 | 2017-05-23 18:06:38 -0400 | [diff] [blame] | 402 |  | 
| Brad Bishop | 05b0c1e | 2017-05-23 00:24:01 -0400 | [diff] [blame] | 403 | class Group(ConfigEntry): | 
|  | 404 | '''Pop the members keyword for groups.''' | 
|  | 405 |  | 
|  | 406 | def __init__(self, *a, **kw): | 
|  | 407 | self.members = kw.pop('members') | 
|  | 408 | super(Group, self).__init__(**kw) | 
|  | 409 |  | 
|  | 410 |  | 
|  | 411 | class ImplicitGroup(Group): | 
|  | 412 | '''Provide a factory method for groups whose members are | 
|  | 413 | not explicitly declared in the config files.''' | 
|  | 414 |  | 
|  | 415 | def __init__(self, *a, **kw): | 
|  | 416 | super(ImplicitGroup, self).__init__(**kw) | 
|  | 417 |  | 
|  | 418 | def factory(self, objs): | 
|  | 419 | '''Create group members.''' | 
|  | 420 |  | 
|  | 421 | factory = Everything.classmap(self.subclass, 'element') | 
|  | 422 | for m in self.members: | 
|  | 423 | args = { | 
|  | 424 | 'class': self.subclass, | 
|  | 425 | self.subclass: 'element', | 
|  | 426 | 'name': m | 
|  | 427 | } | 
|  | 428 |  | 
|  | 429 | obj = factory(configfile=self.configfile, **args) | 
|  | 430 | add_unique(obj, objs) | 
|  | 431 | obj.factory(objs) | 
|  | 432 |  | 
|  | 433 | super(ImplicitGroup, self).factory(objs) | 
|  | 434 |  | 
|  | 435 |  | 
| Brad Bishop | 0e7df13 | 2017-05-23 17:58:12 -0400 | [diff] [blame] | 436 | class GroupOfPaths(ImplicitGroup): | 
|  | 437 | '''Path group config file directive.''' | 
|  | 438 |  | 
|  | 439 | def __init__(self, *a, **kw): | 
|  | 440 | super(GroupOfPaths, self).__init__(**kw) | 
|  | 441 |  | 
|  | 442 | def setup(self, objs): | 
|  | 443 | '''Resolve group members.''' | 
|  | 444 |  | 
|  | 445 | def map_member(x): | 
|  | 446 | path = get_index( | 
|  | 447 | objs, 'pathname', x['path']) | 
|  | 448 | meta = get_index( | 
|  | 449 | objs, 'meta', x['meta']) | 
|  | 450 | return (path, meta) | 
|  | 451 |  | 
|  | 452 | self.members = map( | 
|  | 453 | map_member, | 
|  | 454 | self.members) | 
|  | 455 |  | 
|  | 456 | super(GroupOfPaths, self).setup(objs) | 
|  | 457 |  | 
|  | 458 |  | 
| Brad Bishop | e73b2c3 | 2017-05-23 18:01:54 -0400 | [diff] [blame] | 459 | class GroupOfProperties(ImplicitGroup): | 
|  | 460 | '''Property group config file directive.''' | 
|  | 461 |  | 
|  | 462 | def __init__(self, *a, **kw): | 
| Brad Bishop | ec2ed2f | 2017-05-31 21:10:43 -0400 | [diff] [blame] | 463 | self.type = kw.pop('type') | 
| Brad Bishop | e73b2c3 | 2017-05-23 18:01:54 -0400 | [diff] [blame] | 464 | self.datatype = sdbusplus.property.Property( | 
|  | 465 | name=kw.get('name'), | 
| Brad Bishop | ec2ed2f | 2017-05-31 21:10:43 -0400 | [diff] [blame] | 466 | type=self.type).cppTypeName | 
| Brad Bishop | e73b2c3 | 2017-05-23 18:01:54 -0400 | [diff] [blame] | 467 |  | 
|  | 468 | super(GroupOfProperties, self).__init__(**kw) | 
|  | 469 |  | 
|  | 470 | def setup(self, objs): | 
|  | 471 | '''Resolve group members.''' | 
|  | 472 |  | 
|  | 473 | def map_member(x): | 
|  | 474 | iface = get_index( | 
|  | 475 | objs, 'interface', x['interface']) | 
|  | 476 | prop = get_index( | 
|  | 477 | objs, 'propertyname', x['property']) | 
|  | 478 | meta = get_index( | 
|  | 479 | objs, 'meta', x['meta']) | 
|  | 480 |  | 
|  | 481 | return (iface, prop, meta) | 
|  | 482 |  | 
|  | 483 | self.members = map( | 
|  | 484 | map_member, | 
|  | 485 | self.members) | 
|  | 486 |  | 
|  | 487 | super(GroupOfProperties, self).setup(objs) | 
|  | 488 |  | 
|  | 489 |  | 
| Brad Bishop | 4b916f1 | 2017-05-23 18:06:38 -0400 | [diff] [blame] | 490 | class GroupOfInstances(ImplicitGroup): | 
|  | 491 | '''A group of property instances.''' | 
|  | 492 |  | 
|  | 493 | def __init__(self, *a, **kw): | 
|  | 494 | super(GroupOfInstances, self).__init__(**kw) | 
|  | 495 |  | 
|  | 496 | def setup(self, objs): | 
|  | 497 | '''Resolve group members.''' | 
|  | 498 |  | 
|  | 499 | def map_member(x): | 
|  | 500 | path = get_index(objs, 'pathname', x['path']['path']) | 
|  | 501 | pathmeta = get_index(objs, 'meta', x['path']['meta']) | 
|  | 502 | interface = get_index( | 
|  | 503 | objs, 'interface', x['property']['interface']) | 
|  | 504 | prop = get_index(objs, 'propertyname', x['property']['property']) | 
|  | 505 | propmeta = get_index(objs, 'meta', x['property']['meta']) | 
|  | 506 | instance = get_index(objs, 'instance', x) | 
|  | 507 |  | 
|  | 508 | return (path, pathmeta, interface, prop, propmeta, instance) | 
|  | 509 |  | 
|  | 510 | self.members = map( | 
|  | 511 | map_member, | 
|  | 512 | self.members) | 
|  | 513 |  | 
|  | 514 | super(GroupOfInstances, self).setup(objs) | 
|  | 515 |  | 
| Marri Devender Rao | 80c7061 | 2018-04-12 09:22:55 -0500 | [diff] [blame] | 516 | class GroupOfPathInstances(ImplicitGroup): | 
|  | 517 | '''A group of path instances.''' | 
|  | 518 |  | 
|  | 519 | def __init__(self, *a, **kw): | 
|  | 520 | super(GroupOfPathInstances, self).__init__(**kw) | 
|  | 521 |  | 
|  | 522 | def setup(self, objs): | 
|  | 523 | '''Resolve group members.''' | 
|  | 524 |  | 
|  | 525 | def map_member(x): | 
|  | 526 | path = get_index(objs, 'pathname', x['path']['path']) | 
|  | 527 | pathmeta = get_index(objs, 'meta', x['path']['meta']) | 
|  | 528 | pathinstance = get_index(objs, 'pathinstance', x) | 
|  | 529 | return (path, pathmeta, pathinstance) | 
|  | 530 |  | 
|  | 531 | self.members = map( | 
|  | 532 | map_member, | 
|  | 533 | self.members) | 
|  | 534 |  | 
|  | 535 | super(GroupOfPathInstances, self).setup(objs) | 
|  | 536 |  | 
| Brad Bishop | 4b916f1 | 2017-05-23 18:06:38 -0400 | [diff] [blame] | 537 |  | 
|  | 538 | class HasPropertyIndex(ConfigEntry): | 
|  | 539 | '''Handle config file directives that require an index to be | 
|  | 540 | constructed.''' | 
|  | 541 |  | 
|  | 542 | def __init__(self, *a, **kw): | 
|  | 543 | self.paths = kw.pop('paths') | 
|  | 544 | self.properties = kw.pop('properties') | 
|  | 545 | super(HasPropertyIndex, self).__init__(**kw) | 
|  | 546 |  | 
|  | 547 | def factory(self, objs): | 
|  | 548 | '''Create a group of instances for this index.''' | 
|  | 549 |  | 
|  | 550 | members = [] | 
|  | 551 | path_group = get_index( | 
|  | 552 | objs, 'pathgroup', self.paths, config=self.configfile) | 
|  | 553 | property_group = get_index( | 
|  | 554 | objs, 'propertygroup', self.properties, config=self.configfile) | 
|  | 555 |  | 
|  | 556 | for path in objs['pathgroup'][path_group].members: | 
|  | 557 | for prop in objs['propertygroup'][property_group].members: | 
|  | 558 | member = { | 
|  | 559 | 'path': path, | 
|  | 560 | 'property': prop, | 
|  | 561 | } | 
|  | 562 | members.append(member) | 
|  | 563 |  | 
|  | 564 | args = { | 
|  | 565 | 'members': members, | 
|  | 566 | 'class': 'instancegroup', | 
|  | 567 | 'instancegroup': 'instance', | 
|  | 568 | 'name': '{0} {1}'.format(self.paths, self.properties) | 
|  | 569 | } | 
|  | 570 |  | 
|  | 571 | group = GroupOfInstances(configfile=self.configfile, **args) | 
|  | 572 | add_unique(group, objs, config=self.configfile) | 
|  | 573 | group.factory(objs) | 
|  | 574 |  | 
|  | 575 | super(HasPropertyIndex, self).factory(objs) | 
|  | 576 |  | 
|  | 577 | def setup(self, objs): | 
|  | 578 | '''Resolve path, property, and instance groups.''' | 
|  | 579 |  | 
|  | 580 | self.instances = get_index( | 
|  | 581 | objs, | 
|  | 582 | 'instancegroup', | 
|  | 583 | '{0} {1}'.format(self.paths, self.properties), | 
|  | 584 | config=self.configfile) | 
|  | 585 | self.paths = get_index( | 
|  | 586 | objs, | 
|  | 587 | 'pathgroup', | 
|  | 588 | self.paths, | 
|  | 589 | config=self.configfile) | 
|  | 590 | self.properties = get_index( | 
|  | 591 | objs, | 
|  | 592 | 'propertygroup', | 
|  | 593 | self.properties, | 
|  | 594 | config=self.configfile) | 
|  | 595 | self.datatype = objs['propertygroup'][self.properties].datatype | 
| Brad Bishop | ec2ed2f | 2017-05-31 21:10:43 -0400 | [diff] [blame] | 596 | self.type = objs['propertygroup'][self.properties].type | 
| Brad Bishop | 4b916f1 | 2017-05-23 18:06:38 -0400 | [diff] [blame] | 597 |  | 
|  | 598 | super(HasPropertyIndex, self).setup(objs) | 
|  | 599 |  | 
| Marri Devender Rao | 80c7061 | 2018-04-12 09:22:55 -0500 | [diff] [blame] | 600 | class HasPathIndex(ConfigEntry): | 
|  | 601 | '''Handle config file directives that require an index to be | 
|  | 602 | constructed.''' | 
|  | 603 |  | 
|  | 604 | def __init__(self, *a, **kw): | 
|  | 605 | self.paths = kw.pop('paths') | 
|  | 606 | super(HasPathIndex, self).__init__(**kw) | 
|  | 607 |  | 
|  | 608 | def factory(self, objs): | 
|  | 609 | '''Create a group of instances for this index.''' | 
|  | 610 |  | 
|  | 611 | members = [] | 
|  | 612 | path_group = get_index( | 
|  | 613 | objs, 'pathgroup', self.paths, config=self.configfile) | 
|  | 614 |  | 
|  | 615 | for path in objs['pathgroup'][path_group].members: | 
|  | 616 | member = { | 
|  | 617 | 'path': path, | 
|  | 618 | } | 
|  | 619 | members.append(member) | 
|  | 620 |  | 
|  | 621 | args = { | 
|  | 622 | 'members': members, | 
|  | 623 | 'class': 'pathinstancegroup', | 
|  | 624 | 'pathinstancegroup': 'pathinstance', | 
|  | 625 | 'name': '{0}'.format(self.paths) | 
|  | 626 | } | 
|  | 627 |  | 
|  | 628 | group = GroupOfPathInstances(configfile=self.configfile, **args) | 
|  | 629 | add_unique(group, objs, config=self.configfile) | 
|  | 630 | group.factory(objs) | 
|  | 631 |  | 
|  | 632 | super(HasPathIndex, self).factory(objs) | 
|  | 633 |  | 
|  | 634 | def setup(self, objs): | 
|  | 635 | '''Resolve path and instance groups.''' | 
|  | 636 |  | 
|  | 637 | self.pathinstances = get_index( | 
|  | 638 | objs, | 
|  | 639 | 'pathinstancegroup', | 
|  | 640 | '{0}'.format(self.paths), | 
|  | 641 | config=self.configfile) | 
|  | 642 | self.paths = get_index( | 
|  | 643 | objs, | 
|  | 644 | 'pathgroup', | 
|  | 645 | self.paths, | 
|  | 646 | config=self.configfile) | 
|  | 647 | super(HasPathIndex, self).setup(objs) | 
| Brad Bishop | 4b916f1 | 2017-05-23 18:06:38 -0400 | [diff] [blame] | 648 |  | 
| Matthew Barth | efe0158 | 2019-09-09 15:22:37 -0500 | [diff] [blame] | 649 | class GroupOfFilters(ConfigEntry): | 
|  | 650 | '''Handle config file directives that require an index for filters.''' | 
|  | 651 |  | 
|  | 652 | def __init__(self, *a, **kw): | 
|  | 653 | # Pop filters data for adding to the available filters array | 
|  | 654 | self.type = kw.pop('type') | 
|  | 655 | self.datatype = kw.pop('datatype', None) | 
|  | 656 | self.filters = kw.pop('filters', None) | 
|  | 657 |  | 
|  | 658 | super(GroupOfFilters, self).__init__(**kw) | 
|  | 659 |  | 
|  | 660 | def factory(self, objs): | 
|  | 661 | '''Modify filters to add the property value type and | 
|  | 662 | make them of operation argument type.''' | 
|  | 663 | if self.filters: | 
|  | 664 | # 'type' used within OpArgument to generate filter | 
|  | 665 | # argument values so add to each filter | 
|  | 666 | for f in self.filters: | 
|  | 667 | f['type'] = self.type | 
|  | 668 | self.filters = [OpArgument(**x) for x in self.filters] | 
|  | 669 |  | 
|  | 670 | super(GroupOfFilters, self).factory(objs) | 
|  | 671 |  | 
| Brad Bishop | 4b916f1 | 2017-05-23 18:06:38 -0400 | [diff] [blame] | 672 | class PropertyWatch(HasPropertyIndex): | 
|  | 673 | '''Handle the property watch config file directive.''' | 
|  | 674 |  | 
|  | 675 | def __init__(self, *a, **kw): | 
| Matthew Barth | efe0158 | 2019-09-09 15:22:37 -0500 | [diff] [blame] | 676 | # Pop optional filters for the properties being watched | 
|  | 677 | self.filters = kw.pop('filters', None) | 
| Brad Bishop | fccdc39 | 2017-05-22 21:11:09 -0400 | [diff] [blame] | 678 | self.callback = kw.pop('callback', None) | 
| Brad Bishop | 4b916f1 | 2017-05-23 18:06:38 -0400 | [diff] [blame] | 679 | super(PropertyWatch, self).__init__(**kw) | 
|  | 680 |  | 
| Matthew Barth | efe0158 | 2019-09-09 15:22:37 -0500 | [diff] [blame] | 681 | def factory(self, objs): | 
|  | 682 | '''Create any filters for this property watch.''' | 
|  | 683 |  | 
|  | 684 | if self.filters: | 
|  | 685 | # Get the datatype(i.e. "int64_t") of the properties in this watch | 
|  | 686 | # (Made available after all `super` classes init'd) | 
|  | 687 | datatype = objs['propertygroup'][get_index( | 
|  | 688 | objs, | 
|  | 689 | 'propertygroup', | 
|  | 690 | self.properties, | 
|  | 691 | config=self.configfile)].datatype | 
|  | 692 | # Get the type(i.e. "int64") of the properties in this watch | 
|  | 693 | # (Made available after all `super` classes init'd) | 
|  | 694 | type = objs['propertygroup'][get_index( | 
|  | 695 | objs, | 
|  | 696 | 'propertygroup', | 
|  | 697 | self.properties, | 
|  | 698 | config=self.configfile)].type | 
|  | 699 | # Construct the data needed to make the filters for | 
|  | 700 | # this watch available. | 
|  | 701 | # *Note: 'class', 'subclass', 'name' are required for | 
|  | 702 | # storing the filter data(i.e. 'type', 'datatype', & 'filters') | 
|  | 703 | args = { | 
|  | 704 | 'type': type, | 
|  | 705 | 'datatype': datatype, | 
|  | 706 | 'filters': self.filters, | 
|  | 707 | 'class': 'filtersgroup', | 
|  | 708 | 'filtersgroup': 'filters', | 
|  | 709 | 'name': self.name, | 
|  | 710 | } | 
|  | 711 | # Init GroupOfFilters class with this watch's filters' arguments | 
|  | 712 | group = GroupOfFilters(configfile=self.configfile, **args) | 
|  | 713 | # Store this group of filters so it can be indexed later | 
|  | 714 | add_unique(group, objs, config=self.configfile) | 
|  | 715 | group.factory(objs) | 
|  | 716 |  | 
|  | 717 | super(PropertyWatch, self).factory(objs) | 
|  | 718 |  | 
| Brad Bishop | fccdc39 | 2017-05-22 21:11:09 -0400 | [diff] [blame] | 719 | def setup(self, objs): | 
| Matthew Barth | efe0158 | 2019-09-09 15:22:37 -0500 | [diff] [blame] | 720 | '''Resolve optional filters and callback.''' | 
|  | 721 |  | 
|  | 722 | if self.filters: | 
|  | 723 | # Watch has filters, provide array index to access them | 
|  | 724 | self.filters = get_index( | 
|  | 725 | objs, | 
|  | 726 | 'filtersgroup', | 
|  | 727 | self.name, | 
|  | 728 | config=self.configfile) | 
| Brad Bishop | fccdc39 | 2017-05-22 21:11:09 -0400 | [diff] [blame] | 729 |  | 
|  | 730 | if self.callback: | 
|  | 731 | self.callback = get_index( | 
|  | 732 | objs, | 
|  | 733 | 'callback', | 
|  | 734 | self.callback, | 
|  | 735 | config=self.configfile) | 
|  | 736 |  | 
|  | 737 | super(PropertyWatch, self).setup(objs) | 
|  | 738 |  | 
| Marri Devender Rao | 80c7061 | 2018-04-12 09:22:55 -0500 | [diff] [blame] | 739 | class PathWatch(HasPathIndex): | 
|  | 740 | '''Handle the path watch config file directive.''' | 
|  | 741 |  | 
|  | 742 | def __init__(self, *a, **kw): | 
|  | 743 | self.pathcallback = kw.pop('pathcallback', None) | 
|  | 744 | super(PathWatch, self).__init__(**kw) | 
|  | 745 |  | 
|  | 746 | def setup(self, objs): | 
|  | 747 | '''Resolve optional callback.''' | 
|  | 748 | if self.pathcallback: | 
|  | 749 | self.pathcallback = get_index( | 
|  | 750 | objs, | 
|  | 751 | 'pathcallback', | 
|  | 752 | self.pathcallback, | 
|  | 753 | config=self.configfile) | 
|  | 754 | super(PathWatch, self).setup(objs) | 
|  | 755 |  | 
| Brad Bishop | c1283ae | 2017-05-20 21:42:38 -0400 | [diff] [blame] | 756 | class Callback(HasPropertyIndex): | 
|  | 757 | '''Interface and common logic for callbacks.''' | 
|  | 758 |  | 
|  | 759 | def __init__(self, *a, **kw): | 
|  | 760 | super(Callback, self).__init__(**kw) | 
|  | 761 |  | 
| Marri Devender Rao | 80c7061 | 2018-04-12 09:22:55 -0500 | [diff] [blame] | 762 | class PathCallback(HasPathIndex): | 
|  | 763 | '''Interface and common logic for callbacks.''' | 
|  | 764 |  | 
|  | 765 | def __init__(self, *a, **kw): | 
|  | 766 | super(PathCallback, self).__init__(**kw) | 
| Brad Bishop | c1283ae | 2017-05-20 21:42:38 -0400 | [diff] [blame] | 767 |  | 
| Brad Bishop | 4041d72 | 2017-05-21 10:06:07 -0400 | [diff] [blame] | 768 | class ConditionCallback(ConfigEntry, Renderer): | 
|  | 769 | '''Handle the journal callback config file directive.''' | 
|  | 770 |  | 
|  | 771 | def __init__(self, *a, **kw): | 
|  | 772 | self.condition = kw.pop('condition') | 
|  | 773 | self.instance = kw.pop('instance') | 
| Brad Bishop | 3539db6 | 2017-05-30 14:21:12 -0400 | [diff] [blame] | 774 | self.defer = kw.pop('defer', None) | 
| Brad Bishop | 4041d72 | 2017-05-21 10:06:07 -0400 | [diff] [blame] | 775 | super(ConditionCallback, self).__init__(**kw) | 
|  | 776 |  | 
|  | 777 | def factory(self, objs): | 
|  | 778 | '''Create a graph instance for this callback.''' | 
|  | 779 |  | 
|  | 780 | args = { | 
|  | 781 | 'configfile': self.configfile, | 
|  | 782 | 'members': [self.instance], | 
|  | 783 | 'class': 'callbackgroup', | 
|  | 784 | 'callbackgroup': 'callback', | 
|  | 785 | 'name': [self.instance] | 
|  | 786 | } | 
|  | 787 |  | 
|  | 788 | entry = CallbackGraphEntry(**args) | 
|  | 789 | add_unique(entry, objs, config=self.configfile) | 
|  | 790 |  | 
|  | 791 | super(ConditionCallback, self).factory(objs) | 
|  | 792 |  | 
|  | 793 | def setup(self, objs): | 
|  | 794 | '''Resolve condition and graph entry.''' | 
|  | 795 |  | 
|  | 796 | self.graph = get_index( | 
|  | 797 | objs, | 
|  | 798 | 'callbackgroup', | 
|  | 799 | [self.instance], | 
|  | 800 | config=self.configfile) | 
|  | 801 |  | 
|  | 802 | self.condition = get_index( | 
|  | 803 | objs, | 
|  | 804 | 'condition', | 
|  | 805 | self.name, | 
|  | 806 | config=self.configfile) | 
|  | 807 |  | 
|  | 808 | super(ConditionCallback, self).setup(objs) | 
|  | 809 |  | 
|  | 810 | def construct(self, loader, indent): | 
|  | 811 | return self.render( | 
|  | 812 | loader, | 
|  | 813 | 'conditional.mako.cpp', | 
|  | 814 | c=self, | 
|  | 815 | indent=indent) | 
|  | 816 |  | 
|  | 817 |  | 
|  | 818 | class Condition(HasPropertyIndex): | 
|  | 819 | '''Interface and common logic for conditions.''' | 
|  | 820 |  | 
|  | 821 | def __init__(self, *a, **kw): | 
|  | 822 | self.callback = kw.pop('callback') | 
| Brad Bishop | 3539db6 | 2017-05-30 14:21:12 -0400 | [diff] [blame] | 823 | self.defer = kw.pop('defer', None) | 
| Brad Bishop | 4041d72 | 2017-05-21 10:06:07 -0400 | [diff] [blame] | 824 | super(Condition, self).__init__(**kw) | 
|  | 825 |  | 
|  | 826 | def factory(self, objs): | 
|  | 827 | '''Create a callback instance for this conditional.''' | 
|  | 828 |  | 
|  | 829 | args = { | 
|  | 830 | 'configfile': self.configfile, | 
|  | 831 | 'condition': self.name, | 
|  | 832 | 'class': 'callback', | 
|  | 833 | 'callback': 'conditional', | 
|  | 834 | 'instance': self.callback, | 
|  | 835 | 'name': self.name, | 
| Brad Bishop | 3539db6 | 2017-05-30 14:21:12 -0400 | [diff] [blame] | 836 | 'defer': self.defer | 
| Brad Bishop | 4041d72 | 2017-05-21 10:06:07 -0400 | [diff] [blame] | 837 | } | 
|  | 838 |  | 
|  | 839 | callback = ConditionCallback(**args) | 
|  | 840 | add_unique(callback, objs, config=self.configfile) | 
|  | 841 | callback.factory(objs) | 
|  | 842 |  | 
|  | 843 | super(Condition, self).factory(objs) | 
|  | 844 |  | 
|  | 845 |  | 
|  | 846 | class CountCondition(Condition, Renderer): | 
|  | 847 | '''Handle the count condition config file directive.''' | 
|  | 848 |  | 
|  | 849 | def __init__(self, *a, **kw): | 
|  | 850 | self.countop = kw.pop('countop') | 
|  | 851 | self.countbound = kw.pop('countbound') | 
|  | 852 | self.op = kw.pop('op') | 
|  | 853 | self.bound = kw.pop('bound') | 
| Matt Spinler | c458dee | 2018-02-19 13:09:10 -0600 | [diff] [blame] | 854 | self.oneshot = TrivialArgument( | 
|  | 855 | type='boolean', | 
|  | 856 | value=kw.pop('oneshot', False)) | 
| Brad Bishop | 4041d72 | 2017-05-21 10:06:07 -0400 | [diff] [blame] | 857 | super(CountCondition, self).__init__(**kw) | 
|  | 858 |  | 
| Brad Bishop | ec2ed2f | 2017-05-31 21:10:43 -0400 | [diff] [blame] | 859 | def setup(self, objs): | 
|  | 860 | '''Resolve type.''' | 
|  | 861 |  | 
|  | 862 | super(CountCondition, self).setup(objs) | 
|  | 863 | self.bound = TrivialArgument( | 
|  | 864 | type=self.type, | 
|  | 865 | value=self.bound) | 
|  | 866 |  | 
| Brad Bishop | 4041d72 | 2017-05-21 10:06:07 -0400 | [diff] [blame] | 867 | def construct(self, loader, indent): | 
|  | 868 | return self.render( | 
|  | 869 | loader, | 
|  | 870 | 'count.mako.cpp', | 
|  | 871 | c=self, | 
|  | 872 | indent=indent) | 
|  | 873 |  | 
|  | 874 |  | 
| Matthew Barth | efdd03c | 2019-09-04 15:44:35 -0500 | [diff] [blame] | 875 | class MedianCondition(Condition, Renderer): | 
|  | 876 | '''Handle the median condition config file directive.''' | 
|  | 877 |  | 
|  | 878 | def __init__(self, *a, **kw): | 
|  | 879 | self.op = kw.pop('op') | 
|  | 880 | self.bound = kw.pop('bound') | 
|  | 881 | self.oneshot = TrivialArgument( | 
|  | 882 | type='boolean', | 
|  | 883 | value=kw.pop('oneshot', False)) | 
|  | 884 | super(MedianCondition, self).__init__(**kw) | 
|  | 885 |  | 
|  | 886 | def setup(self, objs): | 
|  | 887 | '''Resolve type.''' | 
|  | 888 |  | 
|  | 889 | super(MedianCondition, self).setup(objs) | 
|  | 890 | self.bound = TrivialArgument( | 
|  | 891 | type=self.type, | 
|  | 892 | value=self.bound) | 
|  | 893 |  | 
|  | 894 | def construct(self, loader, indent): | 
|  | 895 | return self.render( | 
|  | 896 | loader, | 
|  | 897 | 'median.mako.cpp', | 
|  | 898 | c=self, | 
|  | 899 | indent=indent) | 
|  | 900 |  | 
|  | 901 |  | 
| Brad Bishop | c1283ae | 2017-05-20 21:42:38 -0400 | [diff] [blame] | 902 | class Journal(Callback, Renderer): | 
|  | 903 | '''Handle the journal callback config file directive.''' | 
|  | 904 |  | 
|  | 905 | def __init__(self, *a, **kw): | 
|  | 906 | self.severity = kw.pop('severity') | 
|  | 907 | self.message = kw.pop('message') | 
|  | 908 | super(Journal, self).__init__(**kw) | 
|  | 909 |  | 
|  | 910 | def construct(self, loader, indent): | 
|  | 911 | return self.render( | 
|  | 912 | loader, | 
|  | 913 | 'journal.mako.cpp', | 
|  | 914 | c=self, | 
|  | 915 | indent=indent) | 
|  | 916 |  | 
|  | 917 |  | 
| Gunnar Mills | d5faea3 | 2017-08-08 14:19:36 -0500 | [diff] [blame] | 918 | class Elog(Callback, Renderer): | 
|  | 919 | '''Handle the elog callback config file directive.''' | 
|  | 920 |  | 
|  | 921 | def __init__(self, *a, **kw): | 
|  | 922 | self.error = kw.pop('error') | 
| Gunnar Mills | 30474cf | 2017-08-11 09:38:54 -0500 | [diff] [blame] | 923 | self.metadata = [Metadata(**x) for x in kw.pop('metadata', {})] | 
| Gunnar Mills | d5faea3 | 2017-08-08 14:19:36 -0500 | [diff] [blame] | 924 | super(Elog, self).__init__(**kw) | 
|  | 925 |  | 
|  | 926 | def construct(self, loader, indent): | 
| Gunnar Mills | d5faea3 | 2017-08-08 14:19:36 -0500 | [diff] [blame] | 927 | with open('errors.hpp', 'a') as fd: | 
|  | 928 | fd.write( | 
|  | 929 | self.render( | 
|  | 930 | loader, | 
|  | 931 | 'errors.mako.hpp', | 
|  | 932 | c=self)) | 
|  | 933 | return self.render( | 
|  | 934 | loader, | 
|  | 935 | 'elog.mako.cpp', | 
|  | 936 | c=self, | 
|  | 937 | indent=indent) | 
|  | 938 |  | 
| Ratan Gupta | 90bfaea | 2017-10-06 20:56:31 +0530 | [diff] [blame] | 939 | class Event(Callback, Renderer): | 
|  | 940 | '''Handle the event callback config file directive.''' | 
|  | 941 |  | 
|  | 942 | def __init__(self, *a, **kw): | 
|  | 943 | self.eventName = kw.pop('eventName') | 
|  | 944 | self.eventMessage = kw.pop('eventMessage') | 
|  | 945 | super(Event, self).__init__(**kw) | 
|  | 946 |  | 
|  | 947 | def construct(self, loader, indent): | 
|  | 948 | return self.render( | 
|  | 949 | loader, | 
|  | 950 | 'event.mako.cpp', | 
|  | 951 | c=self, | 
|  | 952 | indent=indent) | 
| Gunnar Mills | d5faea3 | 2017-08-08 14:19:36 -0500 | [diff] [blame] | 953 |  | 
| Marri Devender Rao | 80c7061 | 2018-04-12 09:22:55 -0500 | [diff] [blame] | 954 | class EventPath(PathCallback, Renderer): | 
|  | 955 | '''Handle the event path callback config file directive.''' | 
|  | 956 |  | 
|  | 957 | def __init__(self, *a, **kw): | 
|  | 958 | self.eventType = kw.pop('eventType') | 
|  | 959 | super(EventPath, self).__init__(**kw) | 
|  | 960 |  | 
|  | 961 | def construct(self, loader, indent): | 
|  | 962 | return self.render( | 
|  | 963 | loader, | 
|  | 964 | 'eventpath.mako.cpp', | 
|  | 965 | c=self, | 
|  | 966 | indent=indent) | 
| Matt Spinler | 3c5318d | 2018-02-19 14:03:05 -0600 | [diff] [blame] | 967 |  | 
|  | 968 | class ElogWithMetadata(Callback, Renderer): | 
|  | 969 | '''Handle the elog_with_metadata callback config file directive.''' | 
|  | 970 |  | 
|  | 971 | def __init__(self, *a, **kw): | 
|  | 972 | self.error = kw.pop('error') | 
|  | 973 | self.metadata = kw.pop('metadata') | 
|  | 974 | super(ElogWithMetadata, self).__init__(**kw) | 
|  | 975 |  | 
|  | 976 | def construct(self, loader, indent): | 
|  | 977 | with open('errors.hpp', 'a') as fd: | 
|  | 978 | fd.write( | 
|  | 979 | self.render( | 
|  | 980 | loader, | 
|  | 981 | 'errors.mako.hpp', | 
|  | 982 | c=self)) | 
|  | 983 | return self.render( | 
|  | 984 | loader, | 
|  | 985 | 'elog_with_metadata.mako.cpp', | 
|  | 986 | c=self, | 
|  | 987 | indent=indent) | 
|  | 988 |  | 
|  | 989 |  | 
| Matt Spinler | 1d6ca48 | 2017-11-01 10:48:02 -0500 | [diff] [blame] | 990 | class ResolveCallout(Callback, Renderer): | 
|  | 991 | '''Handle the 'resolve callout' callback config file directive.''' | 
|  | 992 |  | 
|  | 993 | def __init__(self, *a, **kw): | 
|  | 994 | self.callout = kw.pop('callout') | 
|  | 995 | super(ResolveCallout, self).__init__(**kw) | 
|  | 996 |  | 
|  | 997 | def construct(self, loader, indent): | 
|  | 998 | return self.render( | 
|  | 999 | loader, | 
|  | 1000 | 'resolve_errors.mako.cpp', | 
|  | 1001 | c=self, | 
|  | 1002 | indent=indent) | 
|  | 1003 |  | 
|  | 1004 |  | 
| Brad Bishop | 0df00be | 2017-05-25 23:38:37 -0400 | [diff] [blame] | 1005 | class Method(ConfigEntry, Renderer): | 
|  | 1006 | '''Handle the method callback config file directive.''' | 
|  | 1007 |  | 
|  | 1008 | def __init__(self, *a, **kw): | 
|  | 1009 | self.service = kw.pop('service') | 
|  | 1010 | self.path = kw.pop('path') | 
|  | 1011 | self.interface = kw.pop('interface') | 
|  | 1012 | self.method = kw.pop('method') | 
|  | 1013 | self.args = [TrivialArgument(**x) for x in kw.pop('args', {})] | 
|  | 1014 | super(Method, self).__init__(**kw) | 
|  | 1015 |  | 
|  | 1016 | def factory(self, objs): | 
|  | 1017 | args = { | 
|  | 1018 | 'class': 'interface', | 
|  | 1019 | 'interface': 'element', | 
|  | 1020 | 'name': self.service | 
|  | 1021 | } | 
|  | 1022 | add_unique(ConfigEntry( | 
|  | 1023 | configfile=self.configfile, **args), objs) | 
|  | 1024 |  | 
|  | 1025 | args = { | 
|  | 1026 | 'class': 'pathname', | 
|  | 1027 | 'pathname': 'element', | 
|  | 1028 | 'name': self.path | 
|  | 1029 | } | 
|  | 1030 | add_unique(ConfigEntry( | 
|  | 1031 | configfile=self.configfile, **args), objs) | 
|  | 1032 |  | 
|  | 1033 | args = { | 
|  | 1034 | 'class': 'interface', | 
|  | 1035 | 'interface': 'element', | 
|  | 1036 | 'name': self.interface | 
|  | 1037 | } | 
|  | 1038 | add_unique(ConfigEntry( | 
|  | 1039 | configfile=self.configfile, **args), objs) | 
|  | 1040 |  | 
|  | 1041 | args = { | 
|  | 1042 | 'class': 'propertyname', | 
|  | 1043 | 'propertyname': 'element', | 
|  | 1044 | 'name': self.method | 
|  | 1045 | } | 
|  | 1046 | add_unique(ConfigEntry( | 
|  | 1047 | configfile=self.configfile, **args), objs) | 
|  | 1048 |  | 
|  | 1049 | super(Method, self).factory(objs) | 
|  | 1050 |  | 
|  | 1051 | def setup(self, objs): | 
|  | 1052 | '''Resolve elements.''' | 
|  | 1053 |  | 
|  | 1054 | self.service = get_index( | 
|  | 1055 | objs, | 
|  | 1056 | 'interface', | 
|  | 1057 | self.service) | 
|  | 1058 |  | 
|  | 1059 | self.path = get_index( | 
|  | 1060 | objs, | 
|  | 1061 | 'pathname', | 
|  | 1062 | self.path) | 
|  | 1063 |  | 
|  | 1064 | self.interface = get_index( | 
|  | 1065 | objs, | 
|  | 1066 | 'interface', | 
|  | 1067 | self.interface) | 
|  | 1068 |  | 
|  | 1069 | self.method = get_index( | 
|  | 1070 | objs, | 
|  | 1071 | 'propertyname', | 
|  | 1072 | self.method) | 
|  | 1073 |  | 
|  | 1074 | super(Method, self).setup(objs) | 
|  | 1075 |  | 
|  | 1076 | def construct(self, loader, indent): | 
|  | 1077 | return self.render( | 
|  | 1078 | loader, | 
|  | 1079 | 'method.mako.cpp', | 
|  | 1080 | c=self, | 
|  | 1081 | indent=indent) | 
|  | 1082 |  | 
|  | 1083 |  | 
| Brad Bishop | 49e6617 | 2017-05-23 19:16:21 -0400 | [diff] [blame] | 1084 | class CallbackGraphEntry(Group): | 
|  | 1085 | '''An entry in a traversal list for groups of callbacks.''' | 
|  | 1086 |  | 
|  | 1087 | def __init__(self, *a, **kw): | 
|  | 1088 | super(CallbackGraphEntry, self).__init__(**kw) | 
|  | 1089 |  | 
|  | 1090 | def setup(self, objs): | 
|  | 1091 | '''Resolve group members.''' | 
|  | 1092 |  | 
|  | 1093 | def map_member(x): | 
|  | 1094 | return get_index( | 
|  | 1095 | objs, 'callback', x, config=self.configfile) | 
|  | 1096 |  | 
|  | 1097 | self.members = map( | 
|  | 1098 | map_member, | 
|  | 1099 | self.members) | 
|  | 1100 |  | 
|  | 1101 | super(CallbackGraphEntry, self).setup(objs) | 
|  | 1102 |  | 
| Marri Devender Rao | 80c7061 | 2018-04-12 09:22:55 -0500 | [diff] [blame] | 1103 | class PathCallbackGraphEntry(Group): | 
|  | 1104 | '''An entry in a traversal list for groups of callbacks.''' | 
|  | 1105 |  | 
|  | 1106 | def __init__(self, *a, **kw): | 
|  | 1107 | super(PathCallbackGraphEntry, self).__init__(**kw) | 
|  | 1108 |  | 
|  | 1109 | def setup(self, objs): | 
|  | 1110 | '''Resolve group members.''' | 
|  | 1111 |  | 
|  | 1112 | def map_member(x): | 
|  | 1113 | return get_index( | 
|  | 1114 | objs, 'pathcallback', x, config=self.configfile) | 
|  | 1115 |  | 
|  | 1116 | self.members = map( | 
|  | 1117 | map_member, | 
|  | 1118 | self.members) | 
|  | 1119 |  | 
|  | 1120 | super(PathCallbackGraphEntry, self).setup(objs) | 
| Brad Bishop | 49e6617 | 2017-05-23 19:16:21 -0400 | [diff] [blame] | 1121 |  | 
|  | 1122 | class GroupOfCallbacks(ConfigEntry, Renderer): | 
|  | 1123 | '''Handle the callback group config file directive.''' | 
|  | 1124 |  | 
|  | 1125 | def __init__(self, *a, **kw): | 
|  | 1126 | self.members = kw.pop('members') | 
|  | 1127 | super(GroupOfCallbacks, self).__init__(**kw) | 
|  | 1128 |  | 
|  | 1129 | def factory(self, objs): | 
|  | 1130 | '''Create a graph instance for this group of callbacks.''' | 
|  | 1131 |  | 
|  | 1132 | args = { | 
|  | 1133 | 'configfile': self.configfile, | 
|  | 1134 | 'members': self.members, | 
|  | 1135 | 'class': 'callbackgroup', | 
|  | 1136 | 'callbackgroup': 'callback', | 
|  | 1137 | 'name': self.members | 
|  | 1138 | } | 
|  | 1139 |  | 
|  | 1140 | entry = CallbackGraphEntry(**args) | 
|  | 1141 | add_unique(entry, objs, config=self.configfile) | 
|  | 1142 |  | 
|  | 1143 | super(GroupOfCallbacks, self).factory(objs) | 
|  | 1144 |  | 
|  | 1145 | def setup(self, objs): | 
|  | 1146 | '''Resolve graph entry.''' | 
|  | 1147 |  | 
|  | 1148 | self.graph = get_index( | 
|  | 1149 | objs, 'callbackgroup', self.members, config=self.configfile) | 
|  | 1150 |  | 
|  | 1151 | super(GroupOfCallbacks, self).setup(objs) | 
|  | 1152 |  | 
|  | 1153 | def construct(self, loader, indent): | 
|  | 1154 | return self.render( | 
|  | 1155 | loader, | 
|  | 1156 | 'callbackgroup.mako.cpp', | 
|  | 1157 | c=self, | 
|  | 1158 | indent=indent) | 
|  | 1159 |  | 
| Marri Devender Rao | 80c7061 | 2018-04-12 09:22:55 -0500 | [diff] [blame] | 1160 | class GroupOfPathCallbacks(ConfigEntry, Renderer): | 
|  | 1161 | '''Handle the callback group config file directive.''' | 
|  | 1162 |  | 
|  | 1163 | def __init__(self, *a, **kw): | 
|  | 1164 | self.members = kw.pop('members') | 
|  | 1165 | super(GroupOfPathCallbacks, self).__init__(**kw) | 
|  | 1166 |  | 
|  | 1167 | def factory(self, objs): | 
|  | 1168 | '''Create a graph instance for this group of callbacks.''' | 
|  | 1169 |  | 
|  | 1170 | args = { | 
|  | 1171 | 'configfile': self.configfile, | 
|  | 1172 | 'members': self.members, | 
|  | 1173 | 'class': 'pathcallbackgroup', | 
|  | 1174 | 'pathcallbackgroup': 'pathcallback', | 
|  | 1175 | 'name': self.members | 
|  | 1176 | } | 
|  | 1177 |  | 
|  | 1178 | entry = PathCallbackGraphEntry(**args) | 
|  | 1179 | add_unique(entry, objs, config=self.configfile) | 
|  | 1180 | super(GroupOfPathCallbacks, self).factory(objs) | 
|  | 1181 |  | 
|  | 1182 | def setup(self, objs): | 
|  | 1183 | '''Resolve graph entry.''' | 
|  | 1184 |  | 
|  | 1185 | self.graph = get_index( | 
|  | 1186 | objs, 'callbackpathgroup', self.members, config=self.configfile) | 
|  | 1187 |  | 
|  | 1188 | super(GroupOfPathCallbacks, self).setup(objs) | 
|  | 1189 |  | 
|  | 1190 | def construct(self, loader, indent): | 
|  | 1191 | return self.render( | 
|  | 1192 | loader, | 
|  | 1193 | 'callbackpathgroup.mako.cpp', | 
|  | 1194 | c=self, | 
|  | 1195 | indent=indent) | 
| Brad Bishop | 49e6617 | 2017-05-23 19:16:21 -0400 | [diff] [blame] | 1196 |  | 
| Brad Bishop | 34a7acd | 2017-04-27 23:47:23 -0400 | [diff] [blame] | 1197 | class Everything(Renderer): | 
|  | 1198 | '''Parse/render entry point.''' | 
|  | 1199 |  | 
|  | 1200 | @staticmethod | 
| Brad Bishop | 05b0c1e | 2017-05-23 00:24:01 -0400 | [diff] [blame] | 1201 | def classmap(cls, sub=None): | 
|  | 1202 | '''Map render item class and subclass entries to the appropriate | 
|  | 1203 | handler methods.''' | 
| Brad Bishop | 05b0c1e | 2017-05-23 00:24:01 -0400 | [diff] [blame] | 1204 | class_map = { | 
| Brad Bishop | 0e7df13 | 2017-05-23 17:58:12 -0400 | [diff] [blame] | 1205 | 'path': { | 
|  | 1206 | 'element': Path, | 
|  | 1207 | }, | 
|  | 1208 | 'pathgroup': { | 
|  | 1209 | 'path': GroupOfPaths, | 
|  | 1210 | }, | 
| Brad Bishop | e73b2c3 | 2017-05-23 18:01:54 -0400 | [diff] [blame] | 1211 | 'propertygroup': { | 
|  | 1212 | 'property': GroupOfProperties, | 
|  | 1213 | }, | 
|  | 1214 | 'property': { | 
|  | 1215 | 'element': Property, | 
|  | 1216 | }, | 
| Brad Bishop | 4b916f1 | 2017-05-23 18:06:38 -0400 | [diff] [blame] | 1217 | 'watch': { | 
|  | 1218 | 'property': PropertyWatch, | 
|  | 1219 | }, | 
| Marri Devender Rao | 80c7061 | 2018-04-12 09:22:55 -0500 | [diff] [blame] | 1220 | 'pathwatch': { | 
|  | 1221 | 'path': PathWatch, | 
|  | 1222 | }, | 
| Brad Bishop | 4b916f1 | 2017-05-23 18:06:38 -0400 | [diff] [blame] | 1223 | 'instance': { | 
|  | 1224 | 'element': Instance, | 
|  | 1225 | }, | 
| Marri Devender Rao | 80c7061 | 2018-04-12 09:22:55 -0500 | [diff] [blame] | 1226 | 'pathinstance': { | 
|  | 1227 | 'element': PathInstance, | 
|  | 1228 | }, | 
| Brad Bishop | c1283ae | 2017-05-20 21:42:38 -0400 | [diff] [blame] | 1229 | 'callback': { | 
|  | 1230 | 'journal': Journal, | 
| Gunnar Mills | d5faea3 | 2017-08-08 14:19:36 -0500 | [diff] [blame] | 1231 | 'elog': Elog, | 
| Matt Spinler | 3c5318d | 2018-02-19 14:03:05 -0600 | [diff] [blame] | 1232 | 'elog_with_metadata': ElogWithMetadata, | 
| Ratan Gupta | 90bfaea | 2017-10-06 20:56:31 +0530 | [diff] [blame] | 1233 | 'event': Event, | 
| Brad Bishop | 49e6617 | 2017-05-23 19:16:21 -0400 | [diff] [blame] | 1234 | 'group': GroupOfCallbacks, | 
| Brad Bishop | 0df00be | 2017-05-25 23:38:37 -0400 | [diff] [blame] | 1235 | 'method': Method, | 
| Matt Spinler | 1d6ca48 | 2017-11-01 10:48:02 -0500 | [diff] [blame] | 1236 | 'resolve callout': ResolveCallout, | 
| Brad Bishop | c1283ae | 2017-05-20 21:42:38 -0400 | [diff] [blame] | 1237 | }, | 
| Marri Devender Rao | 80c7061 | 2018-04-12 09:22:55 -0500 | [diff] [blame] | 1238 | 'pathcallback': { | 
|  | 1239 | 'eventpath': EventPath, | 
|  | 1240 | 'grouppath': GroupOfPathCallbacks, | 
|  | 1241 | }, | 
| Brad Bishop | 4041d72 | 2017-05-21 10:06:07 -0400 | [diff] [blame] | 1242 | 'condition': { | 
|  | 1243 | 'count': CountCondition, | 
| Matthew Barth | efdd03c | 2019-09-04 15:44:35 -0500 | [diff] [blame] | 1244 | 'median': MedianCondition, | 
| Brad Bishop | 4041d72 | 2017-05-21 10:06:07 -0400 | [diff] [blame] | 1245 | }, | 
| Brad Bishop | 05b0c1e | 2017-05-23 00:24:01 -0400 | [diff] [blame] | 1246 | } | 
|  | 1247 |  | 
|  | 1248 | if cls not in class_map: | 
|  | 1249 | raise NotImplementedError('Unknown class: "{0}"'.format(cls)) | 
|  | 1250 | if sub not in class_map[cls]: | 
|  | 1251 | raise NotImplementedError('Unknown {0} type: "{1}"'.format( | 
|  | 1252 | cls, sub)) | 
|  | 1253 |  | 
|  | 1254 | return class_map[cls][sub] | 
|  | 1255 |  | 
|  | 1256 | @staticmethod | 
|  | 1257 | def load_one_yaml(path, fd, objs): | 
|  | 1258 | '''Parse a single YAML file.  Parsing occurs in three phases. | 
|  | 1259 | In the first phase a factory method associated with each | 
|  | 1260 | configuration file directive is invoked.  These factory | 
|  | 1261 | methods generate more factory methods.  In the second | 
|  | 1262 | phase the factory methods created in the first phase | 
|  | 1263 | are invoked.  In the last phase a callback is invoked on | 
|  | 1264 | each object created in phase two.  Typically the callback | 
|  | 1265 | resolves references to other configuration file directives.''' | 
|  | 1266 |  | 
|  | 1267 | factory_objs = {} | 
|  | 1268 | for x in yaml.safe_load(fd.read()) or {}: | 
|  | 1269 |  | 
|  | 1270 | # Create factory object for this config file directive. | 
|  | 1271 | cls = x['class'] | 
|  | 1272 | sub = x.get(cls) | 
|  | 1273 | if cls == 'group': | 
|  | 1274 | cls = '{0}group'.format(sub) | 
|  | 1275 |  | 
|  | 1276 | factory = Everything.classmap(cls, sub) | 
|  | 1277 | obj = factory(configfile=path, **x) | 
|  | 1278 |  | 
|  | 1279 | # For a given class of directive, validate the file | 
|  | 1280 | # doesn't have any duplicate names (duplicates are | 
|  | 1281 | # ok across config files). | 
|  | 1282 | if exists(factory_objs, obj.cls, obj.name, config=path): | 
|  | 1283 | raise NotUniqueError(path, cls, obj.name) | 
|  | 1284 |  | 
|  | 1285 | factory_objs.setdefault(cls, []).append(obj) | 
|  | 1286 | objs.setdefault(cls, []).append(obj) | 
|  | 1287 |  | 
|  | 1288 | for cls, items in factory_objs.items(): | 
|  | 1289 | for obj in items: | 
|  | 1290 | # Add objects for template consumption. | 
|  | 1291 | obj.factory(objs) | 
|  | 1292 |  | 
|  | 1293 | @staticmethod | 
| Brad Bishop | 34a7acd | 2017-04-27 23:47:23 -0400 | [diff] [blame] | 1294 | def load(args): | 
|  | 1295 | '''Aggregate all the YAML in the input directory | 
|  | 1296 | into a single aggregate.''' | 
|  | 1297 |  | 
| Brad Bishop | 05b0c1e | 2017-05-23 00:24:01 -0400 | [diff] [blame] | 1298 | objs = {} | 
|  | 1299 | yaml_files = filter( | 
|  | 1300 | lambda x: x.endswith('.yaml'), | 
|  | 1301 | os.listdir(args.inputdir)) | 
| Brad Bishop | 34a7acd | 2017-04-27 23:47:23 -0400 | [diff] [blame] | 1302 |  | 
| Marri Devender Rao | 44fd7e8 | 2020-03-08 09:51:34 -0500 | [diff] [blame] | 1303 | for x in sorted(yaml_files): | 
| Brad Bishop | 05b0c1e | 2017-05-23 00:24:01 -0400 | [diff] [blame] | 1304 | path = os.path.join(args.inputdir, x) | 
|  | 1305 | with open(path, 'r') as fd: | 
|  | 1306 | Everything.load_one_yaml(path, fd, objs) | 
|  | 1307 |  | 
|  | 1308 | # Configuration file directives reference each other via | 
|  | 1309 | # the name attribute; however, when rendered the reference | 
|  | 1310 | # is just an array index. | 
|  | 1311 | # | 
|  | 1312 | # At this point all objects have been created but references | 
| Gunnar Mills | 78199b4 | 2017-10-25 16:30:18 -0500 | [diff] [blame] | 1313 | # have not been resolved to array indices.  Instruct objects | 
| Brad Bishop | 05b0c1e | 2017-05-23 00:24:01 -0400 | [diff] [blame] | 1314 | # to do that now. | 
|  | 1315 | for cls, items in objs.items(): | 
|  | 1316 | for obj in items: | 
|  | 1317 | obj.setup(objs) | 
|  | 1318 |  | 
|  | 1319 | return Everything(**objs) | 
| Brad Bishop | 34a7acd | 2017-04-27 23:47:23 -0400 | [diff] [blame] | 1320 |  | 
|  | 1321 | def __init__(self, *a, **kw): | 
| Brad Bishop | 0e7df13 | 2017-05-23 17:58:12 -0400 | [diff] [blame] | 1322 | self.pathmeta = kw.pop('path', []) | 
|  | 1323 | self.paths = kw.pop('pathname', []) | 
|  | 1324 | self.meta = kw.pop('meta', []) | 
|  | 1325 | self.pathgroups = kw.pop('pathgroup', []) | 
| Brad Bishop | e73b2c3 | 2017-05-23 18:01:54 -0400 | [diff] [blame] | 1326 | self.interfaces = kw.pop('interface', []) | 
|  | 1327 | self.properties = kw.pop('property', []) | 
|  | 1328 | self.propertynames = kw.pop('propertyname', []) | 
|  | 1329 | self.propertygroups = kw.pop('propertygroup', []) | 
| Brad Bishop | 4b916f1 | 2017-05-23 18:06:38 -0400 | [diff] [blame] | 1330 | self.instances = kw.pop('instance', []) | 
| Marri Devender Rao | 80c7061 | 2018-04-12 09:22:55 -0500 | [diff] [blame] | 1331 | self.pathinstances = kw.pop('pathinstance', []) | 
| Brad Bishop | 4b916f1 | 2017-05-23 18:06:38 -0400 | [diff] [blame] | 1332 | self.instancegroups = kw.pop('instancegroup', []) | 
| Marri Devender Rao | 80c7061 | 2018-04-12 09:22:55 -0500 | [diff] [blame] | 1333 | self.pathinstancegroups = kw.pop('pathinstancegroup', []) | 
| Brad Bishop | 4b916f1 | 2017-05-23 18:06:38 -0400 | [diff] [blame] | 1334 | self.watches = kw.pop('watch', []) | 
| Marri Devender Rao | 80c7061 | 2018-04-12 09:22:55 -0500 | [diff] [blame] | 1335 | self.pathwatches = kw.pop('pathwatch', []) | 
| Brad Bishop | c1283ae | 2017-05-20 21:42:38 -0400 | [diff] [blame] | 1336 | self.callbacks = kw.pop('callback', []) | 
| Marri Devender Rao | 80c7061 | 2018-04-12 09:22:55 -0500 | [diff] [blame] | 1337 | self.pathcallbacks = kw.pop('pathcallback', []) | 
| Brad Bishop | 49e6617 | 2017-05-23 19:16:21 -0400 | [diff] [blame] | 1338 | self.callbackgroups = kw.pop('callbackgroup', []) | 
| Marri Devender Rao | 80c7061 | 2018-04-12 09:22:55 -0500 | [diff] [blame] | 1339 | self.pathcallbackgroups = kw.pop('pathcallbackgroup', []) | 
| Brad Bishop | 4041d72 | 2017-05-21 10:06:07 -0400 | [diff] [blame] | 1340 | self.conditions = kw.pop('condition', []) | 
| Matthew Barth | efe0158 | 2019-09-09 15:22:37 -0500 | [diff] [blame] | 1341 | self.filters = kw.pop('filtersgroup', []) | 
| Brad Bishop | 0e7df13 | 2017-05-23 17:58:12 -0400 | [diff] [blame] | 1342 |  | 
| Brad Bishop | 34a7acd | 2017-04-27 23:47:23 -0400 | [diff] [blame] | 1343 | super(Everything, self).__init__(**kw) | 
|  | 1344 |  | 
|  | 1345 | def generate_cpp(self, loader): | 
|  | 1346 | '''Render the template with the provided data.''' | 
| Gunnar Mills | d5faea3 | 2017-08-08 14:19:36 -0500 | [diff] [blame] | 1347 | # errors.hpp is used by generated.hpp to included any error.hpp files | 
|  | 1348 | open('errors.hpp', 'w+') | 
|  | 1349 |  | 
| Brad Bishop | e3a01af | 2017-05-15 17:09:04 -0400 | [diff] [blame] | 1350 | with open(args.output, 'w') as fd: | 
| Brad Bishop | 34a7acd | 2017-04-27 23:47:23 -0400 | [diff] [blame] | 1351 | fd.write( | 
|  | 1352 | self.render( | 
|  | 1353 | loader, | 
| Brad Bishop | e3a01af | 2017-05-15 17:09:04 -0400 | [diff] [blame] | 1354 | args.template, | 
| Brad Bishop | 0e7df13 | 2017-05-23 17:58:12 -0400 | [diff] [blame] | 1355 | meta=self.meta, | 
| Brad Bishop | e73b2c3 | 2017-05-23 18:01:54 -0400 | [diff] [blame] | 1356 | properties=self.properties, | 
|  | 1357 | propertynames=self.propertynames, | 
|  | 1358 | interfaces=self.interfaces, | 
| Brad Bishop | 0e7df13 | 2017-05-23 17:58:12 -0400 | [diff] [blame] | 1359 | paths=self.paths, | 
|  | 1360 | pathmeta=self.pathmeta, | 
|  | 1361 | pathgroups=self.pathgroups, | 
| Brad Bishop | e73b2c3 | 2017-05-23 18:01:54 -0400 | [diff] [blame] | 1362 | propertygroups=self.propertygroups, | 
| Brad Bishop | 4b916f1 | 2017-05-23 18:06:38 -0400 | [diff] [blame] | 1363 | instances=self.instances, | 
| Marri Devender Rao | 80c7061 | 2018-04-12 09:22:55 -0500 | [diff] [blame] | 1364 | pathinstances=self.pathinstances, | 
| Brad Bishop | 4b916f1 | 2017-05-23 18:06:38 -0400 | [diff] [blame] | 1365 | watches=self.watches, | 
| Marri Devender Rao | 80c7061 | 2018-04-12 09:22:55 -0500 | [diff] [blame] | 1366 | pathwatches=self.pathwatches, | 
| Brad Bishop | 4b916f1 | 2017-05-23 18:06:38 -0400 | [diff] [blame] | 1367 | instancegroups=self.instancegroups, | 
| Marri Devender Rao | 80c7061 | 2018-04-12 09:22:55 -0500 | [diff] [blame] | 1368 | pathinstancegroups=self.pathinstancegroups, | 
| Brad Bishop | c1283ae | 2017-05-20 21:42:38 -0400 | [diff] [blame] | 1369 | callbacks=self.callbacks, | 
| Marri Devender Rao | 80c7061 | 2018-04-12 09:22:55 -0500 | [diff] [blame] | 1370 | pathcallbacks=self.pathcallbacks, | 
| Brad Bishop | 49e6617 | 2017-05-23 19:16:21 -0400 | [diff] [blame] | 1371 | callbackgroups=self.callbackgroups, | 
| Marri Devender Rao | 80c7061 | 2018-04-12 09:22:55 -0500 | [diff] [blame] | 1372 | pathcallbackgroups=self.pathcallbackgroups, | 
| Brad Bishop | 4041d72 | 2017-05-21 10:06:07 -0400 | [diff] [blame] | 1373 | conditions=self.conditions, | 
| Matthew Barth | efe0158 | 2019-09-09 15:22:37 -0500 | [diff] [blame] | 1374 | filters=self.filters, | 
| Brad Bishop | 34a7acd | 2017-04-27 23:47:23 -0400 | [diff] [blame] | 1375 | indent=Indent())) | 
| Matthew Barth | db440d4 | 2017-04-17 15:49:37 -0500 | [diff] [blame] | 1376 |  | 
|  | 1377 | if __name__ == '__main__': | 
| Brad Bishop | 34a7acd | 2017-04-27 23:47:23 -0400 | [diff] [blame] | 1378 | script_dir = os.path.dirname(os.path.realpath(__file__)) | 
|  | 1379 | valid_commands = { | 
|  | 1380 | 'generate-cpp': 'generate_cpp', | 
|  | 1381 | } | 
|  | 1382 |  | 
|  | 1383 | parser = ArgumentParser( | 
|  | 1384 | description='Phosphor DBus Monitor (PDM) YAML ' | 
|  | 1385 | 'scanner and code generator.') | 
|  | 1386 |  | 
| Matthew Barth | db440d4 | 2017-04-17 15:49:37 -0500 | [diff] [blame] | 1387 | parser.add_argument( | 
| Brad Bishop | e3a01af | 2017-05-15 17:09:04 -0400 | [diff] [blame] | 1388 | "-o", "--out", dest="output", | 
|  | 1389 | default='generated.cpp', | 
|  | 1390 | help="Generated output file name and path.") | 
|  | 1391 | parser.add_argument( | 
|  | 1392 | '-t', '--template', dest='template', | 
| Brad Bishop | 870c3fc | 2017-05-22 23:23:13 -0400 | [diff] [blame] | 1393 | default='generated.mako.hpp', | 
| Brad Bishop | e3a01af | 2017-05-15 17:09:04 -0400 | [diff] [blame] | 1394 | help='The top level template to render.') | 
|  | 1395 | parser.add_argument( | 
|  | 1396 | '-p', '--template-path', dest='template_search', | 
|  | 1397 | default=script_dir, | 
|  | 1398 | help='The space delimited mako template search path.') | 
| Brad Bishop | 34a7acd | 2017-04-27 23:47:23 -0400 | [diff] [blame] | 1399 | parser.add_argument( | 
|  | 1400 | '-d', '--dir', dest='inputdir', | 
|  | 1401 | default=os.path.join(script_dir, 'example'), | 
|  | 1402 | help='Location of files to process.') | 
|  | 1403 | parser.add_argument( | 
|  | 1404 | 'command', metavar='COMMAND', type=str, | 
|  | 1405 | choices=valid_commands.keys(), | 
|  | 1406 | help='%s.' % " | ".join(valid_commands.keys())) | 
| Matthew Barth | db440d4 | 2017-04-17 15:49:37 -0500 | [diff] [blame] | 1407 |  | 
| Brad Bishop | 34a7acd | 2017-04-27 23:47:23 -0400 | [diff] [blame] | 1408 | args = parser.parse_args() | 
|  | 1409 |  | 
|  | 1410 | if sys.version_info < (3, 0): | 
|  | 1411 | lookup = mako.lookup.TemplateLookup( | 
| Brad Bishop | e3a01af | 2017-05-15 17:09:04 -0400 | [diff] [blame] | 1412 | directories=args.template_search.split(), | 
| Brad Bishop | 34a7acd | 2017-04-27 23:47:23 -0400 | [diff] [blame] | 1413 | disable_unicode=True) | 
|  | 1414 | else: | 
|  | 1415 | lookup = mako.lookup.TemplateLookup( | 
| Brad Bishop | e3a01af | 2017-05-15 17:09:04 -0400 | [diff] [blame] | 1416 | directories=args.template_search.split()) | 
| Brad Bishop | 05b0c1e | 2017-05-23 00:24:01 -0400 | [diff] [blame] | 1417 | try: | 
|  | 1418 | function = getattr( | 
|  | 1419 | Everything.load(args), | 
|  | 1420 | valid_commands[args.command]) | 
|  | 1421 | function(lookup) | 
|  | 1422 | except InvalidConfigError as e: | 
|  | 1423 | sys.stdout.write('{0}: {1}\n\n'.format(e.config, e.msg)) | 
|  | 1424 | raise |