tests: Unit test autopath action parsing.
[openvswitch] / ovsdb / ovsdb-doc.in
index 4950e47e4ce90a1f3b199f0d46677dc377df2f3f..b325b263283bd924bbe7ce497078ca34999991e6 100755 (executable)
@@ -7,10 +7,9 @@ import re
 import sys
 import xml.dom.minidom
 
 import sys
 import xml.dom.minidom
 
-sys.path.insert(0, "@abs_top_srcdir@/ovsdb")
-import simplejson as json
-
-from OVSDB import *
+import ovs.json
+from ovs.db import error
+import ovs.db.schema
 
 argv0 = sys.argv[0]
 
 
 argv0 = sys.argv[0]
 
@@ -29,7 +28,7 @@ def textToNroff(s, font=r'\fR'):
         elif c == "'":
             return r'\(cq'
         else:
         elif c == "'":
             return r'\(cq'
         else:
-            raise Error("bad escape")
+            raise error.Error("bad escape")
 
     # Escape - \ " ' as needed by nroff.
     s = re.sub('([-"\'\\\\])', escape, s)
 
     # Escape - \ " ' as needed by nroff.
     s = re.sub('([-"\'\\\\])', escape, s)
@@ -44,7 +43,7 @@ def inlineXmlToNroff(node, font):
     if node.nodeType == node.TEXT_NODE:
         return textToNroff(node.data, font)
     elif node.nodeType == node.ELEMENT_NODE:
     if node.nodeType == node.TEXT_NODE:
         return textToNroff(node.data, font)
     elif node.nodeType == node.ELEMENT_NODE:
-        if node.tagName == 'code' or node.tagName == 'em':
+        if node.tagName in ['code', 'em', 'option']:
             s = r'\fB'
             for child in node.childNodes:
                 s += inlineXmlToNroff(child, r'\fB')
             s = r'\fB'
             for child in node.childNodes:
                 s += inlineXmlToNroff(child, r'\fB')
@@ -58,7 +57,7 @@ def inlineXmlToNroff(node, font):
             elif node.hasAttribute('group'):
                 s += node.attributes['group'].nodeValue
             else:
             elif node.hasAttribute('group'):
                 s += node.attributes['group'].nodeValue
             else:
-                raise Error("'ref' lacks column and table attributes")
+                raise error.Error("'ref' lacks column and table attributes")
             return s + font
         elif node.tagName == 'var':
             s = r'\fI'
             return s + font
         elif node.tagName == 'var':
             s = r'\fI'
@@ -66,9 +65,9 @@ def inlineXmlToNroff(node, font):
                 s += inlineXmlToNroff(child, r'\fI')
             return s + font
         else:
                 s += inlineXmlToNroff(child, r'\fI')
             return s + font
         else:
-            raise Error("element <%s> unknown or invalid here" % node.tagName)
+            raise error.Error("element <%s> unknown or invalid here" % node.tagName)
     else:
     else:
-        raise Error("unknown node %s in inline xml" % node)
+        raise error.Error("unknown node %s in inline xml" % node)
 
 def blockXmlToNroff(nodes, para='.PP'):
     s = ''
 
 def blockXmlToNroff(nodes, para='.PP'):
     s = ''
@@ -77,17 +76,23 @@ def blockXmlToNroff(nodes, para='.PP'):
             s += textToNroff(node.data)
             s = s.lstrip()
         elif node.nodeType == node.ELEMENT_NODE:
             s += textToNroff(node.data)
             s = s.lstrip()
         elif node.nodeType == node.ELEMENT_NODE:
-            if node.tagName == 'ul':
+            if node.tagName in ['ul', 'ol']:
                 if s != "":
                     s += "\n"
                 s += ".RS\n"
                 if s != "":
                     s += "\n"
                 s += ".RS\n"
+                i = 0
                 for liNode in node.childNodes:
                     if (liNode.nodeType == node.ELEMENT_NODE
                         and liNode.tagName == 'li'):
                 for liNode in node.childNodes:
                     if (liNode.nodeType == node.ELEMENT_NODE
                         and liNode.tagName == 'li'):
-                        s += ".IP \\(bu\n" + blockXmlToNroff(liNode.childNodes, ".IP")
+                        i += 1
+                        if node.tagName == 'ul':
+                            s += ".IP \\bu\n"
+                        else:
+                            s += ".IP %d. .25in\n" % i
+                        s += blockXmlToNroff(liNode.childNodes, ".IP")
                     elif (liNode.nodeType != node.TEXT_NODE
                           or not liNode.data.isspace()):
                     elif (liNode.nodeType != node.TEXT_NODE
                           or not liNode.data.isspace()):
-                        raise Error("<ul> element may only have <li> children")
+                        raise error.Error("<%s> element may only have <li> children" % node.tagName)
                 s += ".RE\n"
             elif node.tagName == 'dl':
                 if s != "":
                 s += ".RE\n"
             elif node.tagName == 'dl':
                 if s != "":
@@ -109,7 +114,7 @@ def blockXmlToNroff(nodes, para='.PP'):
                         prev = 'dd'
                     elif (liNode.nodeType != node.TEXT_NODE
                           or not liNode.data.isspace()):
                         prev = 'dd'
                     elif (liNode.nodeType != node.TEXT_NODE
                           or not liNode.data.isspace()):
-                        raise Error("<dl> element may only have <dt> and <dd> children")
+                        raise error.Error("<dl> element may only have <dt> and <dd> children")
                     s += blockXmlToNroff(liNode.childNodes, ".IP")
                 s += ".RE\n"
             elif node.tagName == 'p':
                     s += blockXmlToNroff(liNode.childNodes, ".IP")
                 s += ".RE\n"
             elif node.tagName == 'p':
@@ -121,7 +126,7 @@ def blockXmlToNroff(nodes, para='.PP'):
             else:
                 s += inlineXmlToNroff(node, r'\fR')
         else:
             else:
                 s += inlineXmlToNroff(node, r'\fR')
         else:
-            raise Error("unknown node %s in block xml" % node)
+            raise error.Error("unknown node %s in block xml" % node)
     if s != "" and not s.endswith('\n'):
         s += '\n'
     return s
     if s != "" and not s.endswith('\n'):
         s += '\n'
     return s
@@ -131,6 +136,8 @@ def typeAndConstraintsToNroff(column):
     constraints = column.type.constraintsToEnglish(escapeNroffLiteral)
     if constraints:
         type += ", " + constraints
     constraints = column.type.constraintsToEnglish(escapeNroffLiteral)
     if constraints:
         type += ", " + constraints
+    if column.unique:
+        type += " (must be unique within table)"
     return type
 
 def columnToNroff(columnName, column, node):
     return type
 
 def columnToNroff(columnName, column, node):
@@ -165,14 +172,14 @@ def columnGroupToNroff(table, groupXml):
             body += '.ST "%s:"\n' % textToNroff(title)
             body += subIntro + subBody
         else:
             body += '.ST "%s:"\n' % textToNroff(title)
             body += subIntro + subBody
         else:
-            raise Error("unknown element %s in <table>" % node.tagName)
+            raise error.Error("unknown element %s in <table>" % node.tagName)
     return summary, intro, body
 
 def tableSummaryToNroff(summary, level=0):
     s = ""
     for type, name, arg in summary:
         if type == 'column':
     return summary, intro, body
 
 def tableSummaryToNroff(summary, level=0):
     s = ""
     for type, name, arg in summary:
         if type == 'column':
-            
+
             s += "%s\\fB%s\\fR\tT{\n%s\nT}\n" % (
                 r'\ \ ' * level, name, typeAndConstraintsToNroff(arg))
         else:
             s += "%s\\fB%s\\fR\tT{\n%s\nT}\n" % (
                 r'\ \ ' * level, name, typeAndConstraintsToNroff(arg))
         else:
@@ -214,13 +221,13 @@ Column    Type
     return s
 
 def docsToNroff(schemaFile, xmlFile, erFile, title=None):
     return s
 
 def docsToNroff(schemaFile, xmlFile, erFile, title=None):
-    schema = DbSchema.fromJson(json.load(open(schemaFile, "r")))
+    schema = ovs.db.schema.DbSchema.from_json(ovs.json.from_file(schemaFile))
     doc = xml.dom.minidom.parse(xmlFile).documentElement
     doc = xml.dom.minidom.parse(xmlFile).documentElement
-    
+
     schemaDate = os.stat(schemaFile).st_mtime
     xmlDate = os.stat(xmlFile).st_mtime
     d = date.fromtimestamp(max(schemaDate, xmlDate))
     schemaDate = os.stat(schemaFile).st_mtime
     xmlDate = os.stat(xmlFile).st_mtime
     d = date.fromtimestamp(max(schemaDate, xmlDate))
-    
+
     if title == None:
         title = schema.name
 
     if title == None:
         title = schema.name
 
@@ -281,20 +288,25 @@ Table     Purpose
 
     if erFile:
         s += """
 
     if erFile:
         s += """
+.if !'\*[.T]'ascii' \{
 .sp 1
 .SH "TABLE RELATIONSHIPS"
 .PP
 The following diagram shows the relationship among tables in the
 .sp 1
 .SH "TABLE RELATIONSHIPS"
 .PP
 The following diagram shows the relationship among tables in the
-database.  Each node represents a table.  Each edge leads from the
+database.  Each node represents a table.  Tables that are part of the
+``root set'' are shown with double borders.  Each edge leads from the
 table that contains it and points to the table that its value
 table that contains it and points to the table that its value
-represents.  Edges are labeled with their column names.
+represents.  Edges are labeled with their column names, followed by a
+constraint on the number of allowed values: \\fB?\\fR for zero or one,
+\\fB*\\fR for zero or more, \\fB+\\fR for one or more.  Thick lines
+represent strong references; thin lines represent weak references.
 .RS -1in
 """
         erStream = open(erFile, "r")
         for line in erStream:
             s += line + '\n'
         erStream.close()
 .RS -1in
 """
         erStream = open(erFile, "r")
         for line in erStream:
             s += line + '\n'
         erStream.close()
-        s += ".RE\n"
+        s += ".RE\\}\n"
 
     for node in tableNodes:
         s += tableToNroff(schema, node) + "\n"
 
     for node in tableNodes:
         s += tableToNroff(schema, node) + "\n"
@@ -339,20 +351,20 @@ if __name__ == "__main__":
                 print "ovsdb-doc (Open vSwitch) @VERSION@"
             else:
                 sys.exit(0)
                 print "ovsdb-doc (Open vSwitch) @VERSION@"
             else:
                 sys.exit(0)
-            
+
         if len(args) != 2:
             sys.stderr.write("%s: exactly 2 non-option arguments required "
                              "(use --help for help)\n" % argv0)
             sys.exit(1)
         if len(args) != 2:
             sys.stderr.write("%s: exactly 2 non-option arguments required "
                              "(use --help for help)\n" % argv0)
             sys.exit(1)
-        
+
         # XXX we should warn about undocumented tables or columns
         s = docsToNroff(args[0], args[1], er_diagram)
         for line in s.split("\n"):
             line = line.strip()
             if len(line):
                 print line
         # XXX we should warn about undocumented tables or columns
         s = docsToNroff(args[0], args[1], er_diagram)
         for line in s.split("\n"):
             line = line.strip()
             if len(line):
                 print line
-            
-    except Error, e:
+
+    except error.Error, e:
         sys.stderr.write("%s: %s\n" % (argv0, e.msg))
         sys.exit(1)
 
         sys.stderr.write("%s: %s\n" % (argv0, e.msg))
         sys.exit(1)