Browse Source

integrate gendocs

David Rose 20 years ago
parent
commit
2e11b37849
3 changed files with 123 additions and 53 deletions
  1. 38 24
      direct/src/directscripts/gendocs.py
  2. 77 27
      direct/src/ffi/DoGenPyCode.py
  3. 8 2
      direct/src/ffi/genPyCode.pp

+ 38 - 24
direct/src/directscripts/gendocs.py

@@ -5,15 +5,18 @@
 # How to use this module:
 #
 #   from direct.directscripts import gendocs
-#   gendocs.generate(version, indir, directdir, docdir, header, footer, urlprefix, urlsuffix)
+#   gendocs.generate(version, indirlist, directdirlist, docdir, header, footer, urlprefix, urlsuffix)
 #
 #   - version is the panda version number
 #
-#   - indir is the name of a directory containing the "xxx.in"
-#     files that interrogate generates.  No slash at end.
+#   - indirlist is the name of a directory, or a list of directories,
+#     containing the "xxx.in" files that interrogate generates.  No
+#     slash at end.
 #
-#   - directdir is the name of a directory containing the 
-#     source code for "direct."  No slash at end.
+#   - directdirlist is the name of a directory, or a list of
+#     directories, containing the source code for "direct," as well as
+#     for other Python-based trees that should be included in the
+#     documentation pages.  No slash at end.
 #
 #   - docdir is the name of a directory into which HTML files
 #     will be emitted.  No slash at end.
@@ -73,15 +76,18 @@ def writeFile(wfile,data):
     except:
         sys.exit("Cannot write "+wfile)
 
-def findFiles(dir, ext, ign, list):
-    for file in os.listdir(dir):
-        full = dir + "/" + file
-        if (ign.has_key(full)==0) and (ign.has_key(file)==0):
-            if (os.path.isfile(full)):
-                if (file.endswith(ext)):
-                    list.append(full)
-            elif (os.path.isdir(full)):
-                findFiles(full, ext, ign, list)
+def findFiles(dirlist, ext, ign, list):
+    if isinstance(dirlist, types.StringTypes):
+        dirlist = [dirlist]
+    for dir in dirlist:
+        for file in os.listdir(dir):
+            full = dir + "/" + file
+            if (ign.has_key(full)==0) and (ign.has_key(file)==0):
+                if (os.path.isfile(full)):
+                    if (file.endswith(ext)):
+                        list.append(full)
+                elif (os.path.isdir(full)):
+                    findFiles(full, ext, ign, list)
 
 def textToHTML(comment,sep,delsection=None):
     sections = [""]
@@ -477,8 +483,9 @@ class CodeDatabase:
         self.funcs = {}
         self.goodtypes = {}
         self.globalfn = []
+        print "Reading C++ source files"
         for cxx in cxxlist:
-            print "Reading source file "+cxx
+            #print "Reading source file "+cxx
             tokzr = InterrogateTokenizer(cxx)
             idb = InterrogateDatabase(tokzr)
             for type in idb.types.values():
@@ -494,8 +501,9 @@ class CodeDatabase:
                     self.globalfn.append("GLOBAL."+func.pyname)
                 else:
                     self.funcs[type.scopedname+"."+func.pyname] = func
+        print "Reading Python sources files"
         for py in pylist:
-            print "Reading source file "+py
+            #print "Reading source file "+py
             pyinf = ParseTreeInfo(readFile(py), py)
             for type in pyinf.class_info.keys():
                 typinf = pyinf.class_info[type]
@@ -663,23 +671,29 @@ def generateLinkTable(table, cols, urlprefix, urlsuffix):
     result = result + "</table>\n"
     return result
 
-def generate(pversion, indir, directdir, docdir, header, footer, urlprefix, urlsuffix):
+def generate(pversion, indirlist, directdirlist, docdir, header, footer, urlprefix, urlsuffix):
     ignore = {}
     ignore["__init__.py"] = 1
-    ignore[directdir + "/src/directscripts"] = 1
-    ignore[directdir + "/src/extensions"] = 1
-    ignore[directdir + "/src/extensions_native"] = 1
-    ignore[directdir + "/src/ffi"] = 1
+
+    if isinstance(directdirlist, types.StringTypes):
+        directdirlist = [directdirlist]
+    for directdir in directdirlist:
+        ignore[directdir + "/src/directscripts"] = 1
+        ignore[directdir + "/src/extensions"] = 1
+        ignore[directdir + "/src/extensions_native"] = 1
+        ignore[directdir + "/src/ffi"] = 1
+        ignore[directdir + "/built"] = 1
     cxxfiles = []
     pyfiles = []
-    findFiles(indir,     ".in", ignore, cxxfiles)
-    findFiles(directdir, ".py", ignore, pyfiles)
+    findFiles(indirlist,     ".in", ignore, cxxfiles)
+    findFiles(directdirlist, ".py", ignore, pyfiles)
     code = CodeDatabase(cxxfiles, pyfiles)
     classes = code.getClassList()[:]
     classes.sort()
     xclasses = classes[:]
+    print "Generating HTML pages"
     for type in classes:
-        print "Generating page for class "+type
+        #print "Generating page for class "+type
         body = "<h1>" + type + "</h1>\n"
         comment = code.getClassComment(type)
         body = body + "<ul>\n" + comment + "</ul>\n\n"

+ 77 - 27
direct/src/ffi/DoGenPyCode.py

@@ -7,6 +7,7 @@ import sys
 import os
 import glob
 import types
+import time
 from direct.ffi import FFIConstants
 
 # Define a help string for the user
@@ -32,10 +33,13 @@ default.
 Options:
   -h          print this message
   -v          verbose
-  -d dir      directory to write output code
+  -d          generate HTML documentation too
+  -C dir      directory to write output code
+  -H dir      directory to write output HTML
   -x dir      directory to pull extension code from
   -i lib      interrogate library
   -e dir      directory to search for *.in files (may be repeated)
+  -p dir      directory to search for Python source files (may be repeated)
   -r          remove the default library list; instrument only named libraries
   -O          no C++ comments or assertion statements
   -n          Don't use squeezeTool to squeeze the result into one .pyz file
@@ -46,25 +50,44 @@ of libraries that are to be instrumented.
 
 """
 
+HTMLHeader = """
+<html>
+<head>
+<title>Panda3D documentation generated %s</title>
+</head>
+<body>
+"""
+
+HTMLFooter = """
+</body>
+</html>
+"""
+
 # Initialize variables
-outputDir = ''
+outputCodeDir = ''
+outputHTMLDir = ''
 directDir = ''
 extensionsDir = ''
 interrogateLib = ''
 codeLibs = []
 etcPath = []
+pythonSourcePath = []
 doSqueeze = True
 deleteSourceAfterSqueeze = True
+doHTML = False
 native = False  # This is set by genPyCode.py
 
 def doGetopts():
-    global outputDir
+    global outputCodeDir
+    global outputHTMLDir
     global extensionsDir
     global interrogateLib
     global codeLibs
     global doSqueeze
     global deleteSourceAfterSqueeze
+    global doHTML
     global etcPath
+    global pythonSourcePath
 
     # These options are allowed but are flagged as warnings (they are
     # deprecated with the new genPyCode script):
@@ -79,7 +102,7 @@ def doGetopts():
 
     # Extract the args the user passed in
     try:
-        opts, pargs = getopt.getopt(sys.argv[1:], 'hvOd:x:Ni:e:rnsgtpom')
+        opts, pargs = getopt.getopt(sys.argv[1:], 'hvdOC:H:x:Ni:e:p:rns')
     except Exception, e:
         # User passed in a bad option, print the error and the help, then exit
         print e
@@ -98,13 +121,19 @@ def doGetopts():
             else:
                 FFIConstants.notify.setDebug(1)
         elif (flag == '-d'):
-            outputDir = value
+            doHTML = True
+        elif (flag == '-C'):
+            outputCodeDir = value
+        elif (flag == '-H'):
+            outputHTMLDir = value
         elif (flag == '-x'):
             extensionsDir = value
         elif (flag == '-i'):
             interrogateLib = value
         elif (flag == '-e'):
             etcPath.append(value)
+        elif (flag == '-p'):
+            pythonSourcePath.append(value)
         elif (flag == '-r'):
             codeLibs = []
         elif (flag == '-O'):
@@ -114,8 +143,6 @@ def doGetopts():
             doSqueeze = False
         elif (flag == '-s'):
             deleteSourceAfterSqueeze = False
-        elif (flag in ['-g', '-t', '-p', '-o']):
-            FFIConstants.notify.warning("option is deprecated: %s" % (flag))
             
         else:
             FFIConstants.notify.error('illegal option: ' + flag)
@@ -141,7 +168,8 @@ def doGetopts():
         
 
 def doErrorCheck():
-    global outputDir
+    global outputCodeDir
+    global outputHTMLDir
     global extensionsDir
     global interrogateLib
     global codeLibs
@@ -155,15 +183,26 @@ def doErrorCheck():
         FFIConstants.notify.debug('Setting interrogate library to: ' + interrogateLib)
         FFIConstants.InterrogateModuleName = interrogateLib
 
-    if (not outputDir):
-        FFIConstants.notify.info('Setting output directory to current directory')
-        outputDir = '.'
-    elif (not os.path.exists(outputDir)):
-        FFIConstants.notify.info('Directory does not exist, creating: ' + outputDir)
-        os.mkdir(outputDir)
-        FFIConstants.notify.info('Setting output directory to: ' + outputDir)
+    if (not outputCodeDir):
+        FFIConstants.notify.info('Setting output code directory to current directory')
+        outputCodeDir = '.'
+    elif (not os.path.exists(outputCodeDir)):
+        FFIConstants.notify.info('Directory does not exist, creating: ' + outputCodeDir)
+        os.mkdir(outputCodeDir)
+        FFIConstants.notify.info('Setting output code directory to: ' + outputCodeDir)
     else:
-        FFIConstants.notify.info('Setting output directory to: ' + outputDir)
+        FFIConstants.notify.info('Setting output code directory to: ' + outputCodeDir)
+
+    if doHTML:
+        if (not outputHTMLDir):
+            FFIConstants.notify.info('Setting output HTML directory to current directory')
+            outputHTMLDir = '.'
+        elif (not os.path.exists(outputHTMLDir)):
+            FFIConstants.notify.info('Directory does not exist, creating: ' + outputHTMLDir)
+            os.makedirs(outputHTMLDir)
+            FFIConstants.notify.info('Setting output HTML directory to: ' + outputHTMLDir)
+        else:
+            FFIConstants.notify.info('Setting output HTML directory to: ' + outputHTMLDir)
 
 
     if (not extensionsDir):
@@ -182,26 +221,26 @@ def doErrorCheck():
         FFIConstants.CodeModuleNameList = codeLibs
 
 def generateNativeWrappers():
-    # Empty out the codeDir of unnecessary crud from previous runs
-    # before we begin.
-    for file in os.listdir(outputDir):
-        pathname = os.path.join(outputDir, file)
+    # Empty out the output directories of unnecessary crud from
+    # previous runs before we begin.
+    for file in os.listdir(outputCodeDir):
+        pathname = os.path.join(outputCodeDir, file)
         if not os.path.isdir(pathname):
             os.unlink(pathname)
 
     # Generate __init__.py
-    initFilename = os.path.join(outputDir, '__init__.py')
+    initFilename = os.path.join(outputCodeDir, '__init__.py')
     init = open(initFilename, 'w')
 
     # Generate PandaModules.py
-    pandaModulesFilename = os.path.join(outputDir, 'PandaModules.py')
+    pandaModulesFilename = os.path.join(outputCodeDir, 'PandaModules.py')
     pandaModules = open(pandaModulesFilename, 'w')
 
     # Copy in any helper classes from the extensions_native directory
     extensionHelperFiles = [ 'extension_native_helpers.py' ]
     for name in extensionHelperFiles:
         inFilename = os.path.join(extensionsDir, name)
-        outFilename = os.path.join(outputDir, name)
+        outFilename = os.path.join(outputCodeDir, name)
         if os.path.exists(inFilename):
             inFile = open(inFilename, 'r')
             outFile = open(outFilename, 'w')
@@ -215,7 +254,7 @@ def generateNativeWrappers():
 
         pandaModules.write('from %sModules import *\n' % (moduleName))
 
-        moduleModulesFilename = os.path.join(outputDir, '%sModules.py' % (moduleName))
+        moduleModulesFilename = os.path.join(outputCodeDir, '%sModules.py' % (moduleName))
         moduleModules = open(moduleModulesFilename, 'w')
 
         moduleModules.write('from %s import *\n\n' % (moduleName))
@@ -232,7 +271,8 @@ def generateNativeWrappers():
         
 
 def run():
-    global outputDir
+    global outputCodeDir
+    global outputHTMLDir
     global directDir
     global extensionsDir
     global interrogateLib
@@ -240,6 +280,7 @@ def run():
     global doSqueeze
     global deleteSourceAfterSqueeze
     global etcPath
+    global pythonSourcePath
 
     doGetopts()
     doErrorCheck()
@@ -251,8 +292,17 @@ def run():
     else:
         from direct.ffi import FFIInterrogateDatabase
         db = FFIInterrogateDatabase.FFIInterrogateDatabase(etcPath = etcPath)
-        db.generateCode(outputDir, extensionsDir)
+        db.generateCode(outputCodeDir, extensionsDir)
 
         if doSqueeze:
-            db.squeezeGeneratedCode(outputDir, deleteSourceAfterSqueeze)
+            db.squeezeGeneratedCode(outputCodeDir, deleteSourceAfterSqueeze)
+
+    if doHTML:
+        from direct.directscripts import gendocs
+        from pandac.PandaModules import PandaSystem
+        versionString = '%s %s' % (
+            PandaSystem.getDistributor(), PandaSystem.getVersionString())
 
+        gendocs.generate(versionString, etcPath, pythonSourcePath,
+                         outputHTMLDir, HTMLHeader % time.asctime(),
+                         HTMLFooter, '', '.html')

+ 8 - 2
direct/src/ffi/genPyCode.pp

@@ -131,9 +131,11 @@ DoGenPyCode.native = $[if $[PYTHON_NATIVE],1,0]
 #if $[not $[CTPROJS]]
 // Since the user is not using ctattach, bake these variables in too.
 DoGenPyCode.directDir = r'$[osfilename $[TOPDIR]]'
-DoGenPyCode.outputDir = r'$[osfilename $[install_lib_dir]/pandac]'
+DoGenPyCode.outputCodeDir = r'$[osfilename $[install_lib_dir]/pandac]'
+DoGenPyCode.outputHTMLDir = r'$[osfilename $[install_data_dir]/doc]'
 DoGenPyCode.extensionsDir = r'$[osfilename $[TOPDIR]/src/$[extensions_name]]'
 DoGenPyCode.etcPath = [r'$[osfilename $[install_igatedb_dir]]']
+DoGenPyCode.pythonSourcePath = r'$[osfilename $[TOPDIR]]'
 
 #else
 # The user is expected to be using ctattach, so don't bake in the
@@ -141,9 +143,11 @@ DoGenPyCode.etcPath = [r'$[osfilename $[install_igatedb_dir]]']
 # ctattach.
 
 DoGenPyCode.directDir = directDir
-DoGenPyCode.outputDir = os.path.join(directDir, 'built', 'lib', 'pandac')
+DoGenPyCode.outputCodeDir = os.path.join(directDir, 'built', 'lib', 'pandac')
+DoGenPyCode.outputHTMLDir = os.path.join(directDir, 'built', 'shared', 'doc')
 DoGenPyCode.extensionsDir = os.path.join(directDir, 'src', '$[extensions_name]')
 DoGenPyCode.etcPath = []
+DoGenPyCode.pythonSourcePath = []
 
 # Look for additional packages (other than the basic three)
 # that the user might be dynamically attached to.
@@ -166,6 +170,8 @@ for package in packages:
             DoGenPyCode.etcPath.append(etcDir)
 
         if package not in ['WINTOOLS', 'DTOOL', 'DIRECT', 'PANDA']:
+	    DoGenPyCode.pythonSourcePath.append(packageDir)
+
             libDir = os.path.join(packageDir, 'built', 'lib')
             try:
                 files = os.listdir(libDir)