From 2e11b3784979d5d6c20e7b2384b169474d291e65 Mon Sep 17 00:00:00 2001 From: David Rose Date: Wed, 14 Dec 2005 20:14:50 +0000 Subject: [PATCH] integrate gendocs --- direct/src/directscripts/gendocs.py | 62 ++++++++++------- direct/src/ffi/DoGenPyCode.py | 104 ++++++++++++++++++++-------- direct/src/ffi/genPyCode.pp | 10 ++- 3 files changed, 123 insertions(+), 53 deletions(-) diff --git a/direct/src/directscripts/gendocs.py b/direct/src/directscripts/gendocs.py index 84f43a13ac..8b12b19847 100644 --- a/direct/src/directscripts/gendocs.py +++ b/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 + "\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 = "

" + type + "

\n" comment = code.getClassComment(type) body = body + "\n\n" diff --git a/direct/src/ffi/DoGenPyCode.py b/direct/src/ffi/DoGenPyCode.py index 5afa7c7ec5..53fd9dfbf2 100644 --- a/direct/src/ffi/DoGenPyCode.py +++ b/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 = """ + + +Panda3D documentation generated %s + + +""" + +HTMLFooter = """ + + +""" + # 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') diff --git a/direct/src/ffi/genPyCode.pp b/direct/src/ffi/genPyCode.pp index d104f31408..3d8a5cd79f 100644 --- a/direct/src/ffi/genPyCode.pp +++ b/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)