--- a/docsrc/doxytag.py
+++ b/docsrc/doxytag.py
@@ -62,7 +62,7 @@
 
     def dump(self):
         for k in self.index:
-            print "%40s -> %40s" % (k, self.index[k])
+            print("%40s -> %40s" % (k, self.index[k]))
 
 if __name__ == '__main__':
     d = Doxytag("doc/doxygen.tag")
--- a/docsrc/formatter.py
+++ b/docsrc/formatter.py
@@ -139,7 +139,7 @@
         for line in lines:
             self.tokens.append(lex(line))
 
-    def next(self):
+    def __next__(self):
         self.pos = self.pos + 1
         if self.pos >= len(self.tokens):
             return E()
@@ -195,7 +195,7 @@
         #print self.tokens
 
     def toTextNode(self,s):
-        return self.xmldoc.createTextNode(unicode(s, 'iso-8859-1'))
+        return self.xmldoc.createTextNode(s)
 
     def addAttr(self, tag, attr, val):
         x = self.xmldoc.createAttribute(attr)
@@ -232,7 +232,7 @@
             func_name = i.group("function")
             page_name = i.group("page")
 
-            if func_name and self.funcs.has_key(func_name.upper()):
+            if func_name and func_name.upper() in self.funcs:
                 # retrieve function HTML location
                 func_href = self.funcs[func_name.upper()]
 
@@ -241,9 +241,9 @@
 
                 if self.linktype == 'a':
                     # add link to function
-                    atag = self.xmldoc.createElement(u"a")
+                    atag = self.xmldoc.createElement("a")
                     self.addText(atag, i.group('function'))
-                    atag.setAttribute(u"href", u"%s" % (func_href))
+                    atag.setAttribute("href", "%s" % (func_href))
                     xs.append(atag)
                 elif self.linktype == 'wiki':
                     linktxt = "[[%s|%s]]" % (func_href, i.group('function'))
@@ -261,9 +261,9 @@
 
                 if self.linktype == 'a':
                     # add link to function
-                    atag = self.xmldoc.createElement(u"a")
+                    atag = self.xmldoc.createElement("a")
                     self.addText(atag, i.group('text'))
-                    atag.setAttribute(u"href", u"%s" % (page_href))
+                    atag.setAttribute("href", "%s" % (page_href))
                     xs.append(atag)
                 elif self.linktype == 'wiki':
                     linktxt = "[[%s|%s]]" % (func_href, i.group('function'))
@@ -282,7 +282,7 @@
         "If the next terminal on the stream is of type T, the terminal"
         "is extracted and returned. Otherwise the function returns None"
         pos = self.tokens.getpos()
-        t = self.tokens.next()
+        t = next(self.tokens)
         if t.isa(T):
             return t
         self.tokens.seek(pos)
@@ -434,8 +434,8 @@
                 else:
                     self.tokens.back()
             break
-        litag = self.xmldoc.createElement(u"li")
-        ptag  = self.xmldoc.createElement(u"p")
+        litag = self.xmldoc.createElement("li")
+        ptag  = self.xmldoc.createElement("p")
         self.addFancyText(ptag, content)
         litag.appendChild(ptag)
 
@@ -459,7 +459,7 @@
                 continue
             break
         if len(xs) == 0: return None
-        dltag = self.xmldoc.createElement(u"dl")
+        dltag = self.xmldoc.createElement("dl")
         for x in xs:
             dltag.appendChild(x)
         return dltag
@@ -485,7 +485,7 @@
 
         if False:
             # adds text after :: as part of the description dd
-            dttag = self.xmldoc.createElement(u"dt")
+            dttag = self.xmldoc.createElement("dt")
             dttxt = self.toTextNode(content)
             dttag.appendChild(dttxt)
             xs.append(dttag)
@@ -495,7 +495,7 @@
             if len(c) > 0:
                 tk = PL()
                 tk.content = x.inner_content
-                t = self.tokens.next()
+                t = next(self.tokens)
                 self.tokens.back()
                 if t.isa(L) and t.indent > indent:
                     tk.indent = t.indent
@@ -505,24 +505,24 @@
                     self.tokens.back()
         else:
             # adds text after :: as part of the description term dt
-            dttag = self.xmldoc.createElement(u"dt")
+            dttag = self.xmldoc.createElement("dt")
             dttxt = self.toTextNode(content)
             dttag.appendChild(dttxt)
             c = x.inner_content.strip()
             if len(c) > 0:
-                deftag = self.xmldoc.createElement(u"span")
+                deftag = self.xmldoc.createElement("span")
                 self.addAttr(deftag, "class", "defaults")
                 self.addText(deftag, c)
                 dttag.appendChild(deftag)
             xs.append(dttag)
 
         # Continued by DIV
-        t = self.tokens.next()
+        t = next(self.tokens)
         self.tokens.back()
         if t.isa(L) and t.indent > indent:
             xs_ = self.parse_DIV(t.indent)
             if len(xs_) > 0:
-                ddtag = self.xmldoc.createElement(u"dd")
+                ddtag = self.xmldoc.createElement("dd")
                 for x in xs_:
                     ddtag.appendChild(x)
                 xs.append(ddtag)
@@ -533,7 +533,7 @@
     def toDOM(self):
         # write <mfile></mfile>
         xmf = self.xmldoc.createElement("div")
-        xmf.setAttribute(u"class", u"documentation")
+        xmf.setAttribute("class", "documentation")
 
         self.xmldoc.appendChild(xmf)
 
@@ -626,4 +626,4 @@
 """
     lines = text.splitlines()
     formatter = Formatter(lines, {'BL':'http://www.google.com'}, 'a')
-    print formatter.toDOM().toxml("UTF-8")
+    print(formatter.toDOM().toxml("UTF-8"))
--- a/docsrc/mdoc.py
+++ b/docsrc/mdoc.py
@@ -297,7 +297,7 @@
             mo = rx.match(fileRelPath)
             if mo and (mo.end() - mo.start() == len(fileRelPath)):
                 if verb:
-                    print "mdoc: excluding ''%s''." % fileRelPath
+                    print("mdoc: excluding ''%s''." % fileRelPath)
                     exclude = True
         if exclude: continue
 
@@ -318,7 +318,10 @@
     else:
         breadcrumb += "<li><a href='index.html'>Index</a></li>"
     if m.prev: breadcrumb += "<li><a href='%s'>Prev</a></li>" % m.prev.getRef(format)
-    if m.next: breadcrumb += "<li><a href='%s'>Next</a></li>" % m.next.getRef(format)
+    try:
+        breadcrumb += "<li><a href='%s'>Next</a></li>" % m.next.getRef(format)
+    except:
+        pass
     breadcrumb += "</ul>"
     #breadcrumb += "<span class='path'>%s</span>" % m.node.dirname.upper()
 
@@ -338,7 +341,7 @@
     format = options.format
     helptoc = options.helptoc
 
-    print options.excludeList
+    print(options.excludeList)
     for ex in options.excludeList:
         rx = re.compile(ex)
         excludeRegexList.append(rx)
@@ -354,9 +357,9 @@
     if not basedir.endswith('/'): docdir  = docdir + "/"
 
     if verb:
-        print "mdoc: search path: %s" % basedir
-        print "mdoc: output path: %s" % docdir
-        print "mdoc: output format: %s" % format
+        print("mdoc: search path: %s" % basedir)
+        print("mdoc: output path: %s" % docdir)
+        print("mdoc: output format: %s" % format)
 
     #
     # Search for mfiles
@@ -382,7 +385,7 @@
             mfiles[func] = m
             linkdict[func] = m.getRef(format)
     if verb:
-        print "mdoc: num mfiles: %d" % (len(mfiles))
+        print("mdoc: num mfiles: %d" % (len(mfiles)))
 
     # Create output directory
     if not os.access(docdir, os.F_OK):
@@ -391,7 +394,7 @@
     # ----------------------------------------------------------------
     #                          Extract comment block and run formatter
     # ----------------------------------------------------------------
-    for (func, m) in mfiles.items():
+    for (func, m) in list(mfiles.items()):
 
         if format == 'wiki':
             outname = m.wikiname
@@ -401,7 +404,7 @@
             outname = m.htmlname
 
         if verb:
-            print "mdoc: generating %s from %s" % (outname, m.path)
+            print("mdoc: generating %s from %s" % (outname, m.path))
 
         # extract comment block from file
         (lines, func, brief) = extract(m.path)
@@ -416,7 +419,7 @@
             else:
                 formatter = Formatter(lines, linkdict, 'a')
 
-            content = formatter.toDOM().toxml("UTF-8")
+            content = formatter.toDOM().toxml(None)
             content = content[content.find('?>')+2:]
 
         # add decorations
@@ -486,7 +489,7 @@
         pagenamewiki = pagename + '.wiki'
         runcmd("cd %s ; mvs update %s" % (docdir, pagenamewiki))
         if verb:
-            print "mdoc: converting", pagename, "to", pagenamewiki
+            print("mdoc: converting", pagename, "to", pagenamewiki)
         wikidoc(os.path.join(docdir, pagenamewiki),
                 os.path.join(docdir, pagename))
         runcmd("cd %s ; mvs commit -M -m 'Documentation update' %s" % (docdir, pagenamewiki))
@@ -497,7 +500,7 @@
         except (KeyboardInterrupt, SystemExit):
             sys.exit(1)
 
-        for (func, m) in mfiles.items():
+        for (func, m) in list(mfiles.items()):
             try:
                 towiki(docdir, m.wikiname)
             except (KeyboardInterrupt, SystemExit):
--- a/docsrc/webdoc.py
+++ b/docsrc/webdoc.py
@@ -18,12 +18,12 @@
 import sys
 import random
 import copy
-import htmlentitydefs
+import html.entities
 
 from xml.sax.handler import ContentHandler
 from xml.sax         import parse
-from urlparse        import urlparse
-from urlparse        import urlunparse
+from urllib.parse        import urlparse
+from urllib.parse        import urlunparse
 from optparse        import OptionParser
 from doxytag         import Doxytag
 
@@ -43,9 +43,9 @@
 
 # Create a dictonary that maps unicode characters to HTML entities
 mapUnicodeToHtmlEntity = { }
-for k, v in htmlentitydefs.name2codepoint.items():
-    c = unichr(v)
-    if c == u'&' or c == u'<' or c == u'>': continue
+for k, v in list(html.entities.name2codepoint.items()):
+    c = chr(v)
+    if c == '&' or c == '<' or c == '>': continue
     mapUnicodeToHtmlEntity [c] = "&%s;"  % k
 
 # This indexes the document nodes by ID
@@ -79,8 +79,8 @@
     """
     Dump the node index, for debugging purposes.
     """
-    for x in nodeIndex.itervalues():
-      print x
+    for x in nodeIndex.values():
+      print(x)
 
 def ensureDir(dirName):
     """
@@ -110,8 +110,8 @@
 
     fromPath = fromURL.path.split("/")
     toPath   = toURL.path.split("/")
-    for j in xrange(len(fromPath) - 1): fromPath[j] += u"/"
-    for j in xrange(len(toPath)   - 1): toPath[j] += u"/"
+    for j in range(len(fromPath) - 1): fromPath[j] += "/"
+    for j in range(len(toPath)   - 1): toPath[j] += "/"
 
     # abs path: ['/', 'dir1/', ..., 'dirN/', 'file']
     # rel path: ['dir1/', ..., 'dirN/', 'file']
@@ -127,13 +127,13 @@
 
     # a/b/c/d.html  --> ../../../d.html
     # a/b//c/d.html --> ../../../d.html
-    for j in xrange(len(fromPath) - 1):
-        if len(fromPath[j]) > 1: fromPath[j] = u"../"
-        else:                    fromPath[j] = u""
+    for j in range(len(fromPath) - 1):
+        if len(fromPath[j]) > 1: fromPath[j] = "../"
+        else:                    fromPath[j] = ""
 
     fromPath = fromPath[i:-1]
     toPath = toPath[i:]
-    relPath = u"".join(fromPath) + "".join(toPath)
+    relPath = "".join(fromPath) + "".join(toPath)
 
     return urlunparse(("", "", relPath, "", "", toURL.fragment))
 
@@ -183,7 +183,7 @@
     def __str__(self):
         str = ""
         if len(self.locations) > 0:
-            for i in xrange(len(self.locations)-1,0,-1):
+            for i in range(len(self.locations)-1,0,-1):
                 str += "included from %s:\n" % self.locations[i]
             return str + "%s: error: %s" % (self.locations[0], BaseException.__str__(self))
         else:
@@ -208,7 +208,7 @@
     def __call__(self, obj, *args, **keys):
         try:
             self.func(obj, *args, **keys)
-        except DocError, e:
+        except DocError as e:
             if len(e.locations) == 0:
                 e.appendLocation(obj.getLocation())
             raise e
@@ -216,7 +216,7 @@
             raise
 
     def __get__(self, obj, type=None):
-        return types.MethodType(self, obj, type)
+        return types.MethodType(self, obj)
 
 # --------------------------------------------------------------------
 class DocBareNode:
@@ -263,7 +263,7 @@
         self.sourceURL = None
         self.sourceRow = None
         self.sourceColumn = None
-        if attrs.has_key('id'):
+        if 'id' in attrs:
             self.id = attrs['id']
         else:
             self.id = getUniqueNodeID()
@@ -281,7 +281,7 @@
         Recusively dump the tree of nodes, for debugging purposes.
         """
         depth = self.getDepth()
-        print " " * depth, self
+        print(" " * depth, self)
         for x in self.children: x.dump()
 
     def getID(self):
@@ -407,7 +407,7 @@
             c.publish(generator, pageNode)
         return None
 
-    publish = makeGuard(publish)
+    #publish = makeGuard(publish)
 
     def publishIndex(self, gen, inPage, activePageNodes, full=False):
         """
@@ -460,10 +460,10 @@
             if mo:
                 toNodeID = mo.group(1)
                 toNodeURL = None
-                if nodeIndex.has_key(toNodeID):
+                if toNodeID in nodeIndex:
                     toNodeURL = nodeIndex[toNodeID].getPublishURL()
                 if toNodeURL is None:
-                    print "%s: warning: could not cross-reference '%s'" % (self.getLocation(), toNodeID)
+                    print("%s: warning: could not cross-reference '%s'" % (self.getLocation(), toNodeID))
                     toNodeURL = toNodeID
                 fromPageURL = pageNode.getPublishURL()
                 xvalue += calcRelURL(toNodeURL, fromPageURL)
@@ -474,16 +474,16 @@
                 if envName in os.environ:
                     xvalue += os.environ[envName]
                 else:
-                    print "%s: warning: the environment variable '%s' not defined" % (self.getLocation(), envName)
+                    print("%s: warning: the environment variable '%s' not defined" % (self.getLocation(), envName))
                 continue
             mo = re.match('dox:(.*)', directive)
             if mo:
                 if doxygenIndex is None:
                     if opts.verb > 1:
-						print "%s: warning: no Doxygen tag file loaded, skipping this directive." % self.getLocation()
+                         print("%s: warning: no Doxygen tag file loaded, skipping this directive." % self.getLocation())
                     continue
                 if not mo.group(1) in doxygenIndex.index:
-                    print "%s: warning: the ID %s was not found in the Doxygen tag file." % (self.getLocation(), mo.group(2))
+                    print("%s: warning: the ID %s was not found in the Doxygen tag file." % (self.getLocation(), mo.group(2)))
                     continue
                 toNodeURL = getDoxygenURL(mo.group(1))
                 fromPageURL = pageNode.getPublishURL()
@@ -499,7 +499,7 @@
 # --------------------------------------------------------------------
     def __init__(self, attrs, URL, locator):
         DocNode.__init__(self, attrs, URL, locator)
-        if not attrs.has_key("src"):
+        if "src" not in attrs:
             raise DocError("include missing 'src' attribute")
         self.filePath = attrs["src"]
 
@@ -512,7 +512,7 @@
 # --------------------------------------------------------------------
     def __init__(self, attrs, URL, locator):
         DocNode.__init__(self, attrs, URL, locator)
-        if not attrs.has_key("name"):
+        if "name" not in attrs:
             raise DocError("dir tag missing 'name' attribute")
         self.dirName = attrs["name"]
 
@@ -564,7 +564,7 @@
         DocNode.publish(self, gen, pageNode)
         gen.putString("]]>")
 
-    publish = makeGuard(publish)
+    #publish = makeGuard(publish)
 
 # --------------------------------------------------------------------
 class DocHtmlText(DocBareNode):
@@ -615,7 +615,7 @@
                     if option=="plain":
                         plain=True
                     else:
-                        print "warning: ignoring unknown option '%s' while expanding 'path'" % option
+                        print("warning: ignoring unknown option '%s' while expanding 'path'" % option)
                 if ancPages is not None:
                     for i,p in enumerate(reversed(ancPages)):
                         if plain:
@@ -633,7 +633,7 @@
                 # get the branch of DocPage nodes from the site root to this page
                 activePageNodes = [x for x in walkAncestors(pageNode, DocPage)]
                 # find the root site node and publish the contents
-                siteNode = walkAncestors(pageNode, DocSite).next()
+                siteNode = next(walkAncestors(pageNode, DocSite))
                 siteNode.publishIndex(gen, pageNode, activePageNodes, True)
                 gen.putString("</ul>\n")
 
@@ -645,9 +645,9 @@
                 if envName in os.environ:
                     gen.putString(os.environ[envName])
                 else:
-                    print "warning: environment variable '%s' not defined" % envName
+                    print("warning: environment variable '%s' not defined" % envName)
             else:
-                print "warning: ignoring unknown directive '%s'" % label
+                print("warning: ignoring unknown directive '%s'" % label)
         if next < len(self.text):
             gen.putXMLString(self.text[next:])
 
@@ -669,11 +669,11 @@
     def __init__(self, attrs, URL = None, locator = None):
         DocNode.__init__(self, attrs, URL, locator)
         self.type = "plain"
-        if attrs.has_key("type"): self.type = attrs["type"]
+        if "type" in attrs: self.type = attrs["type"]
 
     def __str__(self):
         str = "<web:precode"
-        for k, v in self.attrs.items():
+        for k, v in list(self.attrs.items()):
             str = str + " " + k + "='" + xml.sax.saxutils.escape(v) + "'"
             str = str + "> type = " + self.type
         return DocNode.__str__(self) + ":" + str
@@ -690,13 +690,13 @@
                                                  lexer,
                                                  pygments.formatters.HtmlFormatter()))
             except pygments.util.ClassNotFound:
-                print "warning: could not find a syntax highlighter for '%s'" % self.type
+                print("warning: could not find a syntax highlighter for '%s'" % self.type)
                 gen.putString("<pre>" + code + "</pre>")
         else:
             gen.putString("<pre>" + code + "</pre>")
         DocNode.publish(self, gen, pageNode)
 
-    publish = makeGuard(publish)
+    #publish = makeGuard(publish)
 
 # --------------------------------------------------------------------
 class DocHtmlElement(DocNode):
@@ -707,7 +707,7 @@
 
     def __str__(self):
         str = "<html:" + self.tag
-        for k, v in self.attrs.items():
+        for k, v in list(self.attrs.items()):
             str = str + " " + k + "='" + xml.sax.saxutils.escape(v) + "'"
         str = str + ">"
         return DocNode.__str__(self) + ":" + str
@@ -724,7 +724,7 @@
         if self.tag in ['h1', 'h2', 'h3', 'h4', 'h5'] and \
            not "id" in self.attrs:
             self.attrs["id"] = self.id ;
-        for name, value in self.attrs.items():
+        for name, value in list(self.attrs.items()):
             gen.putString(" ")
             gen.putString(name)
             gen.putString("=")
@@ -736,7 +736,7 @@
             # expand tags such as <code>vl_function</code> as links
             gen.putString("/>")
             text = "".join([y.text for y in walkNodes(self, DocHtmlText)])
-            ok = nodeIndex.has_key(text)
+            ok = text in nodeIndex
             if ok: gen.putString("<a href=" + self.expandAttr("%%pathto:%s;" % text, pageNode) + ">")
             DocNode.publish(self, gen, pageNode)
             if ok: gen.putString("</a>")
@@ -750,7 +750,7 @@
             gen.putString(self.tag)
             gen.putString(">")
 
-    publish = makeGuard(publish)
+    #publish = makeGuard(publish)
 
 # --------------------------------------------------------------------
 class DocTemplate(DocNode):
@@ -769,9 +769,9 @@
 
     def expand(self, gen, pageNode = None):
         sa = self.getAttributes()
-        if sa.has_key("href"):
+        if "href" in sa:
             gen.putString("<link rel=\"stylesheet\" type=")
-            if sa.has_key("type"):
+            if "type" in sa:
                 gen.putXMLAttr(self.expandAttr(sa["type"], pageNode))
             else:
                 gen.putString("\"text/css\" ")
@@ -780,11 +780,11 @@
             gen.putString("></link>\n")
         else:
             gen.putString("<style rel=\"stylesheet\" type=")
-            if sa.has_key("type"):
+            if "type" in sa:
                 gen.putXMLAttr(self.expandAttr(sa["type"], pageNode))
             else:
                 gen.putString("\"text/css\" ")
-	        gen.putString(">")
+                gen.putString(">")
             DocNode.publish(self, gen, pageNode)
             gen.putString("</style>\n")
 
@@ -802,12 +802,12 @@
     def expand(self, gen, pageNode = None):
         sa = self.getAttributes()
         gen.putString("<script type=")
-        if sa.has_key("type"):
+        if "type" in sa:
             gen.putXMLAttr(self.expandAttr(sa["type"], pageNode))
             gen.putString(" ")
         else:
             gen.putString("\"text/javascript\" ")
-        if sa.has_key("src"):
+        if "src" in sa:
             gen.putString("src=")
             gen.putXMLAttr(self.expandAttr(sa["src"], pageNode))
         gen.putString(">")
@@ -829,7 +829,7 @@
         self.title = "untitled"
         self.hide = False
 
-        for k, v in self.attrs.items():
+        for k, v in list(self.attrs.items()):
             if k == 'src':
                 self.title = v
             elif k == 'name':
@@ -868,7 +868,7 @@
     def publish(self, generator, pageNode = None):
         if pageNode is self:
             # this is the page being published, so go on
-            if opts.verb: print 'Publishing \'%s\''  % self.getPublishURL()
+            if opts.verb: print('Publishing \'%s\''  % self.getPublishURL())
             DocNode.publish(self, generator, pageNode)
         # otherwise this page has been encountered recursively
         # during publishing
@@ -936,7 +936,7 @@
         generator = Generator(self.outDir)
         self.visit(generator)
 
-    publish = makeGuard(publish)
+    #publish = makeGuard(publish)
 
 # --------------------------------------------------------------------
 class Generator:
@@ -959,9 +959,9 @@
         fid = self.fileStack[-1]
         try:
             encoded = str.encode('utf-8')
-            fid.write(encoded)
-        except (UnicodeEncodeError, IOError), e:
-            print str
+            fid.write(str)
+        except (UnicodeEncodeError, IOError) as e:
+            print(str)
             raise DocError("writing text:"  + e.__str__())
         except:
             raise
@@ -970,8 +970,8 @@
         fid = self.fileStack[-1]
         xstr = xml.sax.saxutils.escape(str, mapUnicodeToHtmlEntity)
         try:
-            fid.write(xstr.encode('utf-8'))
-        except (UnicodeEncodeError, IOError), e:
+            fid.write(xstr)
+        except (UnicodeEncodeError, IOError) as e:
             raise DocError("writing XML-escaped string:"  + e.__str__())
         except:
             raise
@@ -980,8 +980,8 @@
         fid = self.fileStack[-1]
         xstr = xml.sax.saxutils.quoteattr(str)
         try:
-            fid.write(xstr.encode('utf-8'))
-        except (UnicodeEncodeError, IOError), e:
+            fid.write(xstr)
+        except (UnicodeEncodeError, IOError) as e:
             raise DocError("writing XML-escaped attribute:"  + e.__str__())
         except:
             raise
@@ -1045,7 +1045,7 @@
 
     def makeError(self, message):
         e = DocError(message)
-        for i in xrange(len(self.filePathStack)-1,-1,-1):
+        for i in range(len(self.filePathStack)-1,-1,-1):
             URL = self.filePathStack[i]
             locator = self.locatorStack[i]
             e.appendLocation(DocLocation(URL,
@@ -1062,7 +1062,7 @@
         """
         # convert attrs to a dictionary (implicitly copies as required by the doc)
         attrs_ = {}
-        for k, v in attrs.items():
+        for k, v in list(attrs.items()):
             attrs_[k] = v
         attrs = attrs_
 
@@ -1072,14 +1072,14 @@
         # The <web:include> element is not parsed recusrively; instead
         # it simply switches to parsing the specified file.
         if name == "include":
-            if not attrs.has_key("src"):
+            if "src" not in attrs:
                 raise self.makeError("<web:include> lacks the 'src' attribute")
             filePath = attrs["src"]
             qualFilePath = self.lookupFile(filePath)
             if qualFilePath is None:
                 raise self.makeError("the file '%s' could not be found while expanding <web:include>" % filePath)
-            if opts.verb: print "Parsing '%s'" % qualFilePath
-            if attrs.has_key("type"):
+            if opts.verb: print("Parsing '%s'" % qualFilePath)
+            if "type" in attrs:
                 includeType = attrs["type"]
             else:
                 includeType = "webdoc"
@@ -1137,7 +1137,7 @@
         parser.setProperty(xml.sax.handler.property_lexical_handler, self)
         try:
             parser.parse(qualFilePath)
-        except xml.sax.SAXParseException, e:
+        except xml.sax.SAXParseException as e:
             raise self.makeError("XML parsing error: %s" % e.getMessage())
 
     def setDocumentLocator(self, locator):
@@ -1204,13 +1204,13 @@
     global doxygenDir
 
     if not has_pygments and opts.verb:
-        print "Warning: Pygments module not found: syntax coloring disabled."
+        print("Warning: Pygments module not found: syntax coloring disabled.")
 
     handler = DocHandler()
     try:
         handler.load(filePath)
-    except DocError, e:
-        print e
+    except DocError as e:
+        print(e)
         sys.exit(-1)
 
     # configure site
@@ -1219,46 +1219,46 @@
 
     # load doxygen tag file
     if opts.doxytag:
-        if opts.verb: print "Loading the Doxygen tag file", opts.doxytag
+        if opts.verb: print("Loading the Doxygen tag file", opts.doxytag)
         try:
             doxygenIndex = Doxytag(opts.doxytag)
             doxygenDir = opts.doxydir
-        except Exception, e:
-            print "Error parsing the Doxygen tag file", opts.doxytag
-            print e
+        except Exception as e:
+            print("Error parsing the Doxygen tag file", opts.doxytag)
+            print(e)
             sys.exit(-1)
 
     if opts.verb > 2:
-        print "== All pages =="
+        print("== All pages ==")
         for x in walkNodes(handler.rootNode, DocPage):
-            print x
+            print(x)
 
-    if opts.verb: print "Publishing website..."
+    if opts.verb: print("Publishing website...")
     try:
         handler.rootNode.publish()
-    except DocError, e:
-        print e
+    except DocError as e:
+        print(e)
         sys.exit(-1)
 
     if opts.indexfile:
-        if opts.verb: print "Storing the website index to", opts.indexfile
+        if opts.verb: print("Storing the website index to", opts.indexfile)
         try:
             f = open(opts.indexfile, 'w+')
             siteurl = nodeIndex['root'].getPublishURL()
             for (id,x) in sorted(nodeIndex.items()):
-                if (x.isA(DocHtmlElement) or x.isA(DocPage)) and x.attrs.has_key('id'):
+                if (x.isA(DocHtmlElement) or x.isA(DocPage)) and 'id' in x.attrs:
                     url = x.getPublishURL()
                     if not url: continue
-                    print >>f, '%s|%s' % (x.attrs['id'],
-                                          calcRelURL(url,siteurl))
+                    print('%s|%s' % (x.attrs['id'],
+                                          calcRelURL(url,siteurl)), file=f)
             if doxygenIndex:
                 for tag in sorted(doxygenIndex.index):
                     url = getDoxygenURL(tag)
-                    print >>f, '%s|%s' % (tag,
-                                          calcRelURL(url,siteurl))
-        except Exception, e:
-            print "Error writing the website index file"
-            print e
+                    print('%s|%s' % (tag,
+                                          calcRelURL(url,siteurl)), file=f)
+        except Exception as e:
+            print("Error writing the website index file")
+            print(e)
             sys.exit(-1)
 
     sys.exit(0)
--- a/docsrc/wikidoc.py
+++ b/docsrc/wikidoc.py
@@ -3,9 +3,9 @@
 import sys,os
 
 def usage():
-    print "Usage:", sys.argv[0], "<wikiname> <htmlname>"
-    print ""
-    print "Replaces wiki documentation with documentation from html files"
+    print("Usage:", sys.argv[0], "<wikiname> <htmlname>")
+    print("")
+    print("Replaces wiki documentation with documentation from html files")
 
 def wikidoc(pagename, htmlfile):
     f = open(htmlfile)
@@ -30,7 +30,7 @@
         if wikilines[i].strip() == endtag   and endline == -1:   endline = i
 
     if startline == -1 or endline == -1 or startline >= endline:
-        print "Wikidoc warning: Didn't find tags for", pagename
+        print("Wikidoc warning: Didn't find tags for", pagename)
         startline = 0
         endline = 0
 
@@ -44,5 +44,5 @@
         usage()
         sys.exit(2)
 
-    print "wikidoc: using", sys.argv[1], "for page", sys.argv[2]
+    print("wikidoc: using", sys.argv[1], "for page", sys.argv[2])
     wikidoc(sys.argv[1], sys.argv[2])
