diff options
author | noelallen@google.com <noelallen@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-07-14 15:59:04 +0000 |
---|---|---|
committer | noelallen@google.com <noelallen@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-07-14 15:59:04 +0000 |
commit | faff5fc7665abfcbcf5ab497ca533d7d3d4e53ac (patch) | |
tree | b6fd31f661c042ea2c7ed935d34c3d05f8d6164e /ppapi/generators/idl_propertynode.py | |
parent | 5dcc294d4a360c49923b6b079a4a3cfec6dca781 (diff) | |
download | chromium_src-faff5fc7665abfcbcf5ab497ca533d7d3d4e53ac.zip chromium_src-faff5fc7665abfcbcf5ab497ca533d7d3d4e53ac.tar.gz chromium_src-faff5fc7665abfcbcf5ab497ca533d7d3d4e53ac.tar.bz2 |
Split property system into it's own file.
Split the property system into it's own file to
make testing and updating easier.
TEST= python idl_propertynode.py
BUG= http://code.google.com/p/chromium/issues/detail?id=74634
R= sehr@google.com
Review URL: http://codereview.chromium.org/7356008
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@92546 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ppapi/generators/idl_propertynode.py')
-rw-r--r-- | ppapi/generators/idl_propertynode.py | 196 |
1 files changed, 196 insertions, 0 deletions
diff --git a/ppapi/generators/idl_propertynode.py b/ppapi/generators/idl_propertynode.py new file mode 100644 index 0000000..caf0974 --- /dev/null +++ b/ppapi/generators/idl_propertynode.py @@ -0,0 +1,196 @@ +#!/usr/bin/python +# +# Copyright (c) 2011 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +""" Hierarchical property system for IDL AST """ +import re +import sys + +from idl_log import ErrOut, InfoOut, WarnOut +from idl_option import GetOption, Option, ParseOptions + +# +# IDLPropertyNode +# +# A property node is a hierarchically aware system for mapping +# keys to values, such that a local dictionary is search first, +# followed by parent dictionaries in order. +# +class IDLPropertyNode(object): + def __init__(self): + self.parents = [] + self.property_map = {} + + def Error(self, msg): + name = self.GetProperty('NAME', 'Unknown') + parents = [parent.GetProperty('NAME', '???') for parent in self.parents] + ErrOut.Log('%s [%s] : %s' % (name, ' '.join(parents), msg)) + + def AddParent(self, parent): + assert parent + self.parents.append(parent) + + def SetProperty(self, name, val): + self.property_map[name] = val + + def _GetProperty_(self, name): + # Check locally for the property, and return it if found. + prop = self.property_map.get(name, None) + if prop is not None: return prop + # If not, seach parents in order + for parent in self.parents: + prop = parent.GetProperty(name) + if prop is not None: return prop + # Otherwise, it can not be found. + return None + + def GetProperty(self, name, default=None): + prop = self._GetProperty_(name) + if prop is None: + return default + else: + return prop + + def GetPropertyLocal(self, name, default=None): + # Search for the property, but only locally, returning the + # default if not found. + prop = self.property_map.get(name, default) + return prop + + # Regular expression to parse property keys in a string such that a string + # "My string $NAME$" will find the key "NAME". + regex_var = re.compile('(?P<src>[^\\$]+)|(?P<key>\\$\\w+\\$)') + + def GetPropertyList(self): + return self.property_map.keys() + + # Recursively expands text keys in the form of $KEY$ with the value + # of the property of the same name. Since this is done recursively + # one property can be defined in terms of another. + def Replace(self, text): + itr = IDLPropertyNode.regex_var.finditer(text) + out = '' + for m in itr: + (start, stop) = m.span() + if m.lastgroup == 'src': + out += text[start:stop] + if m.lastgroup == 'key': + key = text[start+1:stop-1] + val = self.GetProperty(key, None) + if not val: + self.Error('No property "%s"' % key) + out += self.Replace(str(val)) + return out + + +# +# Testing functions +# + +# Build a property node, setting the properties including a name, and +# associate the children with this new node. +# +def BuildNode(name, props, children=[], parents=[]): + node = IDLPropertyNode() + node.SetProperty('NAME', name) + for prop in props: + toks = prop.split('=') + node.SetProperty(toks[0], toks[1]) + for child in children: + child.AddParent(node) + for parent in parents: + node.AddParent(parent) + return node + +def ExpectProp(node, name, val): + found = node.GetProperty(name) + if found != val: + ErrOut.Log('Got property %s expecting %s' % (found, val)) + return 1 + return 0 + +# +# Verify property inheritance +# +def PropertyTest(): + errors = 0 + left = BuildNode('Left', ['Left=Left']) + right = BuildNode('Right', ['Right=Right']) + top = BuildNode('Top', ['Left=Top', 'Right=Top'], [left, right]) + + errors += ExpectProp(top, 'Left', 'Top') + errors += ExpectProp(top, 'Right', 'Top') + + errors += ExpectProp(left, 'Left', 'Left') + errors += ExpectProp(left, 'Right', 'Top') + + errors += ExpectProp(right, 'Left', 'Top') + errors += ExpectProp(right, 'Right', 'Right') + + if not errors: InfoOut.Log('Passed PropertyTest') + return errors + + +def ExpectText(node, text, val): + found = node.Replace(text) + if found != val: + ErrOut.Log('Got replacement %s expecting %s' % (found, val)) + return 1 + return 0 + +# +# Verify text replacement +# +def ReplaceTest(): + errors = 0 + left = BuildNode('Left', ['Left=Left']) + right = BuildNode('Right', ['Right=Right']) + top = BuildNode('Top', ['Left=Top', 'Right=Top'], [left, right]) + + errors += ExpectText(top, '$Left$', 'Top') + errors += ExpectText(top, '$Right$', 'Top') + + errors += ExpectText(left, '$Left$', 'Left') + errors += ExpectText(left, '$Right$', 'Top') + + errors += ExpectText(right, '$Left$', 'Top') + errors += ExpectText(right, '$Right$', 'Right') + + if not errors: InfoOut.Log('Passed ReplaceTest') + return errors + + +def MultiParentTest(): + errors = 0 + + parent1 = BuildNode('parent1', ['PARENT1=parent1', 'TOPMOST=$TOP$']) + parent2 = BuildNode('parent2', ['PARENT1=parent2', 'PARENT2=parent2']) + child = BuildNode('child', ['CHILD=child'], parents=[parent1, parent2]) + BuildNode('top', ['TOP=top'], children=[parent1]) + + errors += ExpectText(child, '$CHILD$', 'child') + errors += ExpectText(child, '$PARENT1$', 'parent1') + errors += ExpectText(child, '$PARENT2$', 'parent2') + + # Verify recursive resolution + errors += ExpectText(child, '$TOPMOST$', 'top') + + if not errors: InfoOut.Log('Passed MultiParentTest') + return errors + +def Main(): + errors = 0 + errors += PropertyTest() + errors += ReplaceTest() + errors += MultiParentTest() + + if errors: + ErrOut.Log('IDLNode failed with %d errors.' % errors) + return -1 + return 0 + +if __name__ == '__main__': + sys.exit(Main()) + |