integrate gendocs

This commit is contained in:
David Rose 2005-12-14 20:14:50 +00:00
parent f0da9ce2ba
commit 2e11b37849
3 changed files with 123 additions and 53 deletions

View File

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

View File

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

View File

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