summaryrefslogtreecommitdiffstats
path: root/ppapi/generators
diff options
context:
space:
mode:
Diffstat (limited to 'ppapi/generators')
-rw-r--r--ppapi/generators/idl_ast.py132
-rw-r--r--ppapi/generators/idl_node.py445
-rw-r--r--ppapi/generators/idl_version.py147
3 files changed, 553 insertions, 171 deletions
diff --git a/ppapi/generators/idl_ast.py b/ppapi/generators/idl_ast.py
new file mode 100644
index 0000000..71aaf93
--- /dev/null
+++ b/ppapi/generators/idl_ast.py
@@ -0,0 +1,132 @@
+#!/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.
+
+"""Nodes for PPAPI IDL AST."""
+
+from idl_namespace import IDLNamespace, IDLVersionMap
+from idl_node import IDLAttribute, IDLFile, IDLNode
+from idl_option import GetOption
+from idl_visitor import IDLVisitor
+
+#
+# IDL Predefined types
+#
+BuiltIn = set(['int8_t', 'int16_t', 'int32_t', 'int64_t', 'uint8_t',
+ 'uint16_t', 'uint32_t', 'uint64_t', 'double_t', 'float_t',
+ 'handle_t', 'interface_t', 'char', 'mem_t', 'str_t', 'void'])
+
+
+#
+# IDLNamespaceLabelResolver
+#
+# Once the AST is build, we need to resolve the namespace and version
+# information.
+#
+class IDLNamespaceLabelResolver(IDLVisitor):
+ NamespaceSet = set(['AST', 'Callspec', 'Interface', 'Member', 'Struct'])
+ #
+ # When we arrive at a node we must assign it a namespace and if the
+ # node is named, then place it in the appropriate namespace.
+ #
+ def Arrive(self, node, parent_namespace):
+ # Set version min and max based on properties
+ vmin = node.GetProperty('version')
+ vmax = node.GetProperty('deprecate')
+ node.SetVersionRange(vmin, vmax)
+
+ # If this object is not a namespace aware object, use the parent's one
+ if node.cls not in self.NamespaceSet:
+ node.namespace = parent_namespace
+ else:
+ # otherwise create one.
+ node.namespace = IDLNamespace(parent_namespace)
+ node.namespace.name = node.GetName()
+
+ # If this node is named, place it in its parent's namespace
+ if parent_namespace and node.cls in IDLNode.NamedSet:
+ parent_namespace.AddNode(node)
+
+ # Pass this namespace to each child in case they inherit it
+ return node.namespace
+
+ #
+ # As we return from a node, if the node is a LabelItem we pass back
+ # the key=value pair representing the mapping of release to version.
+ # If the node is a Label take the lists of mapping and generate a
+ # version map which is assigned to the Labels parent as a property.
+ #
+ def Depart(self, node, data, childdata):
+ if node.IsA('LabelItem'):
+ return (node.GetName(), node.GetProperty('VALUE'))
+ if node.IsA('Label') and node.GetName() == GetOption('label'):
+ vmap = IDLVersionMap()
+ for release, version in childdata:
+ vmap.AddReleaseVersionMapping(release, float(version))
+ node.parent.SetProperty("LABEL", vmap)
+ return None
+
+
+class IDLFileTypeResolver(IDLVisitor):
+ def VisitFilter(self, node, data):
+ return not node.IsA('Comment', 'Copyright')
+
+ def Arrive(self, node, filenode):
+ # Track the file node to update errors
+ if node.IsA('File'):
+ node.SetProperty('FILE', node)
+
+
+ # If this node has a TYPEREF, resolve it to a version list
+ typeref = node.property_node.GetPropertyLocal('TYPEREF')
+ if typeref:
+ node.typelist = node.parent.namespace.FindList(typeref)
+ if not node.typelist:
+ node.Error('Could not resolve %s.' % typeref)
+ else:
+ node.typelist = None
+ return filenode
+
+
+
+class IDLVersionMapDefault(IDLVersionMap):
+ def GetRelease(self, version):
+ return 'M13'
+
+ def GetVersion(self, release):
+ return float(0.0)
+
+#
+# IDLAst
+#
+# A specialized version of the IDLNode for containing the whole of the
+# AST. The specialized BuildTree function pulls the per file namespaces
+# into the global AST namespace and checks for collisions.
+#
+class IDLAst(IDLNode):
+ def __init__(self, children):
+ objs = []
+
+ for name in BuiltIn:
+ nameattr = IDLAttribute('NAME', name)
+ objs.append(IDLNode('Type', 'BuiltIn', 1, 0, [nameattr]))
+
+ builtin = IDLFile('pp_stdint.idl', objs)
+ IDLNode.__init__(self, 'AST', 'BuiltIn', 1, 0, [builtin] + children)
+ self.SetProperty('LABEL', IDLVersionMapDefault())
+ self.Resolve()
+
+ def Resolve(self):
+ self.namespace = IDLNamespace(None)
+ self.namespace.name = 'AST'
+ IDLNamespaceLabelResolver().Visit(self, self.namespace)
+ IDLFileTypeResolver().Visit(self, None)
+
+ def SetTypeInfo(self, name, properties):
+ node = self.namespace[name]
+ for prop in properties:
+ node.properties[prop] = properties[prop]
+
+
diff --git a/ppapi/generators/idl_node.py b/ppapi/generators/idl_node.py
index 93b6b4a..285307a 100644
--- a/ppapi/generators/idl_node.py
+++ b/ppapi/generators/idl_node.py
@@ -4,7 +4,7 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-""" Nodes for PPAPI IDL AST """
+"""Nodes for PPAPI IDL AST"""
#
# IDL Node
@@ -17,13 +17,15 @@
# as the source data by the various generators.
#
-import re
-import sys
import hashlib
+import sys
from idl_log import ErrOut, InfoOut, WarnOut
+from idl_propertynode import IDLPropertyNode
+from idl_namespace import IDLNamespace
+from idl_version import IDLVersion
+
-#
# IDLAttribute
#
# A temporary object used by the parsing process to hold an Extended Attribute
@@ -35,94 +37,93 @@ class IDLAttribute(object):
self.name = name
self.value = value
-# Set of object IDLNode types which have a name and belong in the namespace.
-NamedSet = set(['Enum', 'EnumItem', 'Function', 'Interface', 'Member', 'Param',
- 'Struct', 'Type', 'Typedef'])
+ def __str__(self):
+ return '%s=%s' % (self.name, self.value)
+
#
# IDLNode
#
-# A node in the AST. The Node is composed of children, implemented as a
-# dictionary of lists of child types and a dictionary of local properties,
-# a.k.a. ExtendedAttributes.
+# This class implements the AST tree, providing the associations between
+# parents and children. It also contains a namepsace and propertynode to
+# allow for look-ups. IDLNode is derived from IDLVersion, so it is
+# version aware.
#
-class IDLNode(object):
- # 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+\\$)")
+class IDLNode(IDLVersion):
+
+ # Set of object IDLNode types which have a name and belong in the namespace.
+ NamedSet = set(['Enum', 'EnumItem', 'File', 'Function', 'Interface',
+ 'Member', 'Param', 'Struct', 'Type', 'Typedef'])
+
+ show_versions = False
+ def __init__(self, cls, filename, lineno, pos, children=None):
+ # Initialize with no starting or ending Version
+ IDLVersion.__init__(self, None, None)
- def __init__(self, cls, name, filename, lineno, pos, children):
self.cls = cls
- self.name = name
self.lineno = lineno
self.pos = pos
self.filename = filename
-
- # Dictionary of type to in order child list
- self.children = {}
-
- # Dictionary of child name to child object
- self.namespace = {}
-
- # Dictionary of properties (ExtAttributes)
- self.properties = { 'NAME' : name }
-
- self.hash = None
- self.typeref = None
+ self.hashes = {}
+ self.deps = {}
+ self.errors = 0
+ self.namespace = None
+ self.typelist = None
self.parent = None
- self.childlist = children
-
- if children:
- for child in children:
- #
- # Copy children into local dictionary such that children of the
- # same class are added in order to the per key list. All
- # ExtAttributes are filtered and applied to a property dictionary
- # instead of becoming children of IDLNode
- #
- if child.cls == 'ExtAttribute':
- self.properties[child.name] = child.value
- else:
- if child.cls in self.children:
- self.children[child.cls].append(child)
- else:
- self.children[child.cls] = [child]
+ self.property_node = IDLPropertyNode()
+ # self.children is a list of children ordered as defined
+ self.children = []
+ # Process the passed in list of children, placing ExtAttributes into the
+ # property dictionary, and nodes into the local child list in order. In
+ # addition, add nodes to the namespace if the class is in the NamedSet.
+ if not children: children = []
+ for child in children:
+ if child.cls == 'ExtAttribute':
+ self.SetProperty(child.name, child.value)
+ else:
+ child.SetParent(self)
+ self.children.append(child)
+
+#
+# String related functions
+#
+#
# Return a string representation of this node
def __str__(self):
- return "%s(%s)" % (self.cls, self.name)
+ name = self.GetName()
+ ver = IDLVersion.__str__(self)
+ if name is None: name = ''
+ if not IDLNode.show_versions: ver = ''
+ return '%s(%s%s)' % (self.cls, name, ver)
+
+ # Return file and line number for where node was defined
+ def Location(self):
+ return '%s(%d)' % (self.filename, self.lineno)
# Log an error for this object
def Error(self, msg):
- ErrOut.LogLine(self.filename, self.lineno, 0, " %s %s" %
+ self.errors += 1
+ ErrOut.LogLine(self.filename, self.lineno, 0, ' %s %s' %
(str(self), msg))
+ if self.lineno == 46: raise Exception("huh?")
# Log a warning for this object
def Warning(self, msg):
- WarnOut.LogLine(self.filename, self.lineno, 0, " %s %s" %
+ WarnOut.LogLine(self.filename, self.lineno, 0, ' %s %s' %
(str(self), msg))
- # Get a list of objects for this key
- def GetListOf(self, key):
- return self.children.get(key, [])
-
- def GetOneOf(self, key):
- children = self.children.get(key, None)
- if children:
- assert(len(children) == 1)
- return children[0]
- return None
+ def GetName(self):
+ return self.GetProperty('NAME')
- # Get a list of all objects
- def Children(self):
- out = []
- for key in sorted(self.children.keys()):
- out.extend(self.children[key])
- return out
+ def GetNameVersion(self):
+ name = self.GetProperty('NAME', default='')
+ ver = IDLVersion.__str__(self)
+ return '%s%s' % (name, ver)
# Dump this object and its children
def Dump(self, depth=0, comments=False, out=sys.stdout):
- if self.cls == 'Comment' or self.cls == 'Copyright':
+ if self.cls in ['Comment', 'Copyright']:
is_comment = True
else:
is_comment = False
@@ -130,128 +131,230 @@ class IDLNode(object):
# Skip this node if it's a comment, and we are not printing comments
if not comments and is_comment: return
- tab = ""
- for t in range(depth):
- tab += ' '
+ tab = ''.rjust(depth * 2)
if is_comment:
- for line in self.name.split('\n'):
- out.write("%s%s\n" % (tab, line))
+ for line in self.GetName().split('\n'):
+ out.write('%s%s\n' % (tab, line))
else:
- out.write("%s%s\n" % (tab, self))
+ out.write('%s%s\n' % (tab, self))
+ properties = self.property_node.GetProperyList()
+ if properties:
+ out.write('%s Properties\n' % tab)
+ for p in properties:
+ out.write('%s %s : %s\n' % (tab, p, self.GetProperty(p)))
+ for child in self.children:
+ child.Dump(depth+1, comments=comments, out=out)
- if self.properties:
- out.write("%s Properties\n" % tab)
- for p in self.properties:
- out.write("%s %s : %s\n" % (tab, p, self.properties[p]))
+#
+# Search related functions
+#
- for cls in sorted(self.children.keys()):
- # Skip comments
- if (cls == 'Comment' or cls == 'Copyright') and not comments: continue
+ # Check if node is of a given type
+ def IsA(self, *typelist):
+ if self.cls in typelist: return True
+ return False
+
+ # Get a list of objects for this key
+ def GetListOf(self, *keys):
+ out = []
+ for child in self.children:
+ if child.cls in keys: out.append(child)
+ return out
- out.write("%s %ss\n" % (tab, cls))
- for c in self.children[cls]:
- c.Dump(depth + 1, comments=comments, out=out)
+ def GetOneOf(self, *keys):
+ out = self.GetListOf(*keys)
+ if out: return out[0]
+ return None
- # Link the parents and add the object to the parent's namespace
- def BuildTree(self, parent):
+ def SetParent(self, parent):
+ self.property_node.AddParent(parent)
self.parent = parent
- for child in self.Children():
- child.BuildTree(self)
- name = child.name
-
- # Add this child to the local namespace if it's a 'named' type
- if child.cls in NamedSet:
- if name in self.namespace:
- other = self.namespace[name]
- child.Error('Attempting to add %s to namespace of %s when already '
- 'declared in %s' % (name, str(self), str(other)))
- self.namespace[name] = child
-
- def Resolve(self):
- errs = 0
- typename = self.properties.get('TYPEREF', None)
-
- if typename:
- if typename in self.namespace:
- self.Error('Type collision in local namespace')
- errs += 1
-
- typeinfo = self.parent.Find(typename)
- if not typeinfo:
- self.Error('Unable to resolve typename %s.' % typename)
- errs += 1
- sys.exit(-1)
- self.typeinfo = typeinfo
- else:
- self.typeinfo = None
- for child in self.Children():
- errs += child.Resolve()
+ # Get a list of all children
+ def GetChildren(self):
+ return self.children
- return errs
+ # Get a list of all children of a given version
+ def GetChildrenVersion(self, version):
+ out = []
+ for child in self.children:
+ if child.IsVersion(version): out.append(child)
+ return out
- def Find(self, name):
- if name in self.namespace: return self.namespace[name]
- if self.parent: return self.parent.Find(name)
- return None
+ # Get a list of all children in a given range
+ def GetChildrenRange(self, vmin, vmax):
+ out = []
+ for child in self.children:
+ if child.IsRange(vmin, vmax): out.append(child)
+ return out
- def Hash(self):
- hash = hashlib.sha1()
- for key, val in self.properties.iteritems():
- hash.update('%s=%s' % (key, str(val)))
- for child in self.Children():
- hash.update(child.Hash())
- if self.typeref: hash.update(self.typeref.hash)
- self.hash = hash.hexdigest()
- return self.hash
-
- def GetProperty(self, name):
- return self.properties.get(name, None)
-
- # 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 tems of another.
- def Replace(self, text):
- itr = IDLNode.regex_var.finditer(text)
- out = ""
- for m in itr:
- (min,max) = m.span()
- if m.lastgroup == "src":
- out += text[min:max]
- if m.lastgroup == "key":
- key = text[min+1:max-1]
- val = self.properties.get(key, None)
- if not val:
- self.Error("No property '%s'" % key)
- out += self.Replace(str(val))
+ def FindVersion(self, name, version):
+ node = self.namespace.FindNode(name, version)
+ if not node and self.parent:
+ node = self.parent.FindVersion(name, version)
+ return node
+
+ def FindRange(self, name, vmin, vmax):
+ nodes = self.namespace.FindNodes(name, vmin, vmax)
+ if not nodes and self.parent:
+ nodes = self.parent.FindVersion(name, vmin, vmax)
+ return nodes
+
+ def IsRelease(self, release):
+ label = self.GetLabel()
+ # Assume object is always available if there is no Label
+ if not label:
+ return True
+
+ version = label.GetVersion(release)
+ out = self.IsVersion(version)
return out
+
+ def GetLabel(self):
+ label = self.GetProperty('LABEL')
+ if not label:
+ self.Error('No label availible.')
+ return None
+ return label
+
+ def GetType(self, release):
+ label = self.GetLabel()
+ if not label: return None
+ if not self.typelist: return None
+ version = label.GetVersion(release)
+ return self.typelist.FindVersion(version)
+
+ def GetHash(self, release):
+ hashval = self.hashes.get(release, None)
+ if hashval is None:
+ hashval = hashlib.sha1()
+ hashval.update(self.cls)
+ for key in self.property_node.GetPropertyList():
+ val = self.GetProperty(key)
+ hashval.update('%s=%s' % (key, str(val)))
+ typeref = self.GetType(release)
+ if typeref:
+ hashval.update(typeref.GetHash(release))
+ for child in self.GetChildren():
+ if child.IsA('Copyright', 'Comment', 'Label'): continue
+ if not child.IsRelease(release):
+ continue
+ hashval.update( child.GetHash(release) )
+ self.hashes[release] = hashval
+ return hashval.hexdigest()
+
+ def GetDeps(self, release):
+ deps = self.deps.get(release, None)
+ if deps is None:
+ deps = set([self])
+ for child in self.GetChildren():
+ deps |= child.GetDeps(release)
+ typeref = self.GetType(release)
+ if typeref: deps |= typeref.GetDeps(release)
+ self.deps[release] = deps
+ return deps
+
+ def GetRelease(self, version):
+ label = self.GetLabel()
+ if not label: return None
+ return label.GetRelease(version)
+
+ def GetVersion(self, release):
+ label = self.GetLabel()
+ if not label: return None
+ return label.GetVersion(release)
+
+ def SetProperty(self, name, val):
+ self.property_node.SetProperty(name, val)
+
+ def GetProperty(self, name, default=None):
+ return self.property_node.GetProperty(name, default)
+
+ def Traverse(self, data, func):
+ func(self, data)
+ for child in self.children:
+ child.Traverse(data, func)
+
+
#
-# IDL Predefined types
+# IDLFile
#
-BuiltIn = set(['int8_t', 'int16_t', 'int32_t', 'int64_t', 'uint8_t', 'uint16_t',
- 'uint32_t', 'uint64_t', 'double_t', 'float_t', 'handle_t',
- 'mem_t', 'str_t', 'void', 'enum', 'struct', 'bool'])
-
+# A specialized version of IDLNode which tracks errors and warnings.
#
-# IDLAst
+class IDLFile(IDLNode):
+ def __init__(self, name, children, errors=0):
+ attrs = [IDLAttribute('NAME', name),
+ IDLAttribute('ERRORS', errors)]
+ if not children: children = []
+ IDLNode.__init__(self, 'File', name, 1, 0, attrs + children)
+
+
#
-# A specialized version of the IDLNode for containing the whole of the
-# AST. The specialized BuildTree function pulls the per file namespaces
-# into the global AST namespace and checks for collisions.
+# Tests
#
-class IDLAst(IDLNode):
- def __init__(self, children):
- objs = [IDLNode('Type', name, 'BuiltIn', 1, 0, None) for name in BuiltIn]
- IDLNode.__init__(self, 'AST', 'PPAPI', 'BuiltIn', 1, 0, objs + children)
-
- def BuildTree(self, parent):
- IDLNode.BuildTree(self, parent)
- for fileobj in self.GetListOf('File'):
- for name, val in fileobj.namespace.iteritems():
- if name in self.namespace:
- other = self.namespace[name]
- val.Error('Attempting to add %s to namespace of %s when already '
- 'declared in %s' % (name, str(self), str(other)))
- self.namespace[name] = val
+def StringTest():
+ errors = 0
+ name_str = 'MyName'
+ text_str = 'MyNode(%s)' % name_str
+ name_node = IDLAttribute('NAME', name_str)
+ node = IDLNode('MyNode', 'no file', 1, 0, [name_node])
+ if node.GetName() != name_str:
+ ErrOut.Log('GetName returned >%s< not >%s<' % (node.GetName(), name_str))
+ errors += 1
+ if node.GetProperty('NAME') != name_str:
+ ErrOut.Log('Failed to get name property.')
+ errors += 1
+ if str(node) != text_str:
+ ErrOut.Log('str() returned >%s< not >%s<' % (str(node), text_str))
+ errors += 1
+ if not errors: InfoOut.Log('Passed StringTest')
+ return errors
+
+
+def ChildTest():
+ errors = 0
+ child = IDLNode('child', 'no file', 1, 0)
+ parent = IDLNode('parent', 'no file', 1, 0, [child])
+
+ if child.parent != parent:
+ ErrOut.Log('Failed to connect parent.')
+ errors += 1
+
+ if [child] != parent.GetChildren():
+ ErrOut.Log('Failed GetChildren.')
+ errors += 1
+
+ if child != parent.GetOneOf('child'):
+ ErrOut.Log('Failed GetOneOf(child)')
+ errors += 1
+
+ if parent.GetOneOf('bogus'):
+ ErrOut.Log('Failed GetOneOf(bogus)')
+ errors += 1
+
+ if not parent.IsA('parent'):
+ ErrOut.Log('Expecting parent type')
+ errors += 1
+
+ parent = IDLNode('parent', 'no file', 1, 0, [child, child])
+ if [child, child] != parent.GetChildren():
+ ErrOut.Log('Failed GetChildren2.')
+ errors += 1
+
+ if not errors: InfoOut.Log('Passed ChildTest')
+ return errors
+
+
+def Main():
+ errors = StringTest()
+ errors += ChildTest()
+
+ if errors:
+ ErrOut.Log('IDLNode failed with %d errors.' % errors)
+ return -1
+ return 0
+
+if __name__ == '__main__':
+ sys.exit(Main())
diff --git a/ppapi/generators/idl_version.py b/ppapi/generators/idl_version.py
new file mode 100644
index 0000000..a67abd5c
--- /dev/null
+++ b/ppapi/generators/idl_version.py
@@ -0,0 +1,147 @@
+#!/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.
+
+"""
+IDLVersion for PPAPI
+
+This file defines the behavior of the AST namespace which allows for resolving
+a symbol as one or more AST nodes given a version or range of versions.
+"""
+
+import sys
+
+from idl_log import ErrOut, InfoOut, WarnOut
+from idl_option import GetOption, Option, ParseOptions
+
+Option('version_debug', 'Debug version data')
+Option('wgap', 'Ignore version gap warning')
+
+
+#
+# Module level functions and data used for testing.
+#
+error = None
+warning = None
+def ReportVersionError(msg):
+ global error
+ error = msg
+
+def ReportVersionWarning(msg):
+ global warning
+ warning = msg
+
+def ReportClear():
+ global error, warning
+ error = None
+ warning = None
+
+#
+# IDLVersion
+#
+# IDLVersion is an object which stores the association of a given symbol
+# name, with an AST node for a range of versions for that object.
+#
+# A vmin value of None indicates that the object begins at the earliest
+# available version number. The value of vmin is always inclusive.
+
+# A vmax value of None indicates that the object is never deprecated, so
+# it exists until it is overloaded or until the latest available version.
+# The value of vmax is always exclusive, representing the first version
+# on which the object is no longer valid.
+class IDLVersion(object):
+ def __init__(self, vmin, vmax):
+ self.vmin = vmin
+ self.vmax = vmax
+
+ def __str__(self):
+ if not self.vmin:
+ vmin = '0'
+ else:
+ vmin = str(self.vmin)
+ if not self.vmax:
+ vmax = '+oo'
+ else:
+ vmax = str(self.vmax)
+ return '[%s,%s)' % (vmin, vmax)
+
+ def SetVersionRange(self, vmin, vmax):
+ if vmin is not None: vmin = float(vmin)
+ if vmax is not None: vmax = float(vmax)
+ self.vmin = vmin
+ self.vmax = vmax
+
+ # True, if version falls within the interval [self.vmin, self.vmax)
+ def IsVersion(self, version):
+ assert type(version) == float
+
+ if self.vmax and self.vmax <= version:
+ return False
+ if self.vmin and self.vmin > version:
+ return False
+ if GetOption('version_debug'):
+ InfoOut.Log('%f is in %s' % (version, self))
+ return True
+
+ # True, if interval [vmin, vmax) overlaps interval [self.vmin, self.vmax)
+ def InRange(self, vmin, vmax):
+ assert type(vmin) == float
+ assert type(vmax) == float
+ assert vmin != vmax
+
+ if self.vmax and self.vmax <= vmin:
+ return False
+ if self.vmin and self.vmin >= vmax:
+ return False
+
+ if GetOption('version_debug'):
+ InfoOut.Log('%f to %f is in %s' % (vmin, vmax, self))
+ return True
+
+ def Error(self, msg):
+ ReportVersionError(msg)
+
+ def Warning(self, msg):
+ ReportVersionWarning(msg)
+
+
+#
+# Test Code
+#
+def Main(args):
+ global errors
+
+ FooXX = IDLVersion(None, None)
+ Foo1X = IDLVersion(1.0, None)
+ Foo23 = IDLVersion(2.0, 3.0)
+
+ assert FooXX.IsVersion(0.0)
+ assert FooXX.IsVersion(1.0)
+ assert FooXX.InRange(0.0, 0.1)
+ assert FooXX.InRange(1.0,2.0)
+
+ assert not Foo1X.IsVersion(0.0)
+ assert Foo1X.IsVersion(1.0)
+ assert Foo1X.IsVersion(2.0)
+
+ assert not Foo1X.InRange(0.0, 1.0)
+ assert not Foo1X.InRange(0.5, 1.0)
+ assert Foo1X.InRange(1.0, 2.0)
+ assert Foo1X.InRange(2.0, 3.0)
+
+ assert not Foo23.InRange(0.0, 1.0)
+ assert not Foo23.InRange(0.5, 1.0)
+ assert not Foo23.InRange(1.0, 2.0)
+ assert Foo23.InRange(2.0, 3.0)
+ assert Foo23.InRange(1.0, 2.1)
+ assert Foo23.InRange(2.9, 4.0)
+ assert not Foo23.InRange(3.0, 4.0)
+
+ print "Passed"
+ return 0
+
+if __name__ == '__main__':
+ sys.exit(Main(sys.argv[1:]))
+