| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271 |
- """ This module implements genPyCode, which is itself a generated
- script with a few default parameters filled in. This module allows
- the user to specify alternate parameters on the command line. """
- import getopt
- import sys
- import os
- import glob
- import types
- from direct.ffi import FFIConstants
- # Define a help string for the user
- helpString ="""
- genPyCode -h
- genPyCode
- genPyCode [opts] -i libdtoolconfig libcode1 libcode2 ...
- This script generates Python wrappers to interface with the C++
- libraries that have already been run through interrogate. It is
- necessary to run this script after building the Panda tools for the
- first time, or after any major change in which some of the interface
- may have changed.
- The default options are baked into genPyCode by ppremake and need not
- be specified. However, it is possible to override these on the
- command line if you need to fine-tune the behavior of genPyCode for
- some reason. Most often, the only needed change will be to add one or
- more additional libraries to the list of libraries instrumented by
- default.
- Options:
- -h print this message
- -v verbose
- -d dir directory to write output code
- -x dir directory to pull extension code from
- -i lib interrogate library
- -e dir directory to search for *.in 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
- -s Don't delete source files after squeezing
- -m Generate the API reference manual as well
- Any additional names listed on the command line are taken to be names
- of libraries that are to be instrumented.
- """
- # Initialize variables
- outputDir = ''
- directDir = ''
- extensionsDir = ''
- interrogateLib = ''
- codeLibs = []
- etcPath = []
- doSqueeze = True
- deleteSourceAfterSqueeze = True
- generateManual = False
- native = False # This is set by genPyCode.py
- def doGetopts():
- global outputDir
- global extensionsDir
- global interrogateLib
- global codeLibs
- global doSqueeze
- global deleteSourceAfterSqueeze
- global generateManual
- global etcPath
- # These options are allowed but are flagged as warnings (they are
- # deprecated with the new genPyCode script):
- # -g adds libgateway
- # -t adds libtoontown
- # -p adds libpirates
- # -o adds libopt
- FFIConstants.notify.setDebug(0)
- FFIConstants.notify.setInfo(0)
- # Extract the args the user passed in
- try:
- opts, pargs = getopt.getopt(sys.argv[1:], 'hvOd:x:Ni:e:rnsgtpom')
- except Exception, e:
- # User passed in a bad option, print the error and the help, then exit
- print e
- print helpString
- sys.exit()
- # Store the option values into our variables
- for opt in opts:
- flag, value = opt
- if (flag == '-h'):
- print helpString
- sys.exit()
- elif (flag == '-v'):
- if not FFIConstants.notify.getInfo():
- FFIConstants.notify.setInfo(1)
- else:
- FFIConstants.notify.setDebug(1)
- elif (flag == '-d'):
- outputDir = value
- elif (flag == '-x'):
- extensionsDir = value
- elif (flag == '-i'):
- interrogateLib = value
- elif (flag == '-e'):
- etcPath.append(value)
- elif (flag == '-r'):
- codeLibs = []
- elif (flag == '-O'):
- FFIConstants.wantComments = 0
- FFIConstants.wantTypeChecking = 0
- elif (flag == '-n'):
- doSqueeze = False
- elif (flag == '-s'):
- deleteSourceAfterSqueeze = False
- elif (flag == '-m'):
- generateManual = True
- elif (flag in ['-g', '-t', '-p', '-o']):
- FFIConstants.notify.warning("option is deprecated: %s" % (flag))
-
- else:
- FFIConstants.notify.error('illegal option: ' + flag)
- # Check for old, no-longer-used parameter:
- invalidParameters = [
- 'linux', 'win-debug', 'win-release', 'win-publish',
- 'install', 'release'
- ]
- if pargs and pargs[0] in invalidParameters:
- FFIConstants.notify.warning("parameter is deprecated: %s" % (pargs[0]))
- del pargs[0]
- # Store the program arguments into the codeLibs
- codeLibs += pargs
- # Make sure each name appears on codeLibs exactly once.
- newLibs = []
- for codeLib in codeLibs:
- if codeLib not in newLibs:
- newLibs.append(codeLib)
- codeLibs = newLibs
-
- def doErrorCheck():
- global outputDir
- global extensionsDir
- global interrogateLib
- global codeLibs
- global doSqueeze
- global etcPath
- # Now do some error checking and verbose output
- if (not interrogateLib):
- FFIConstants.notify.error('You must specify an interrogate library (-i lib)')
- else:
- 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)
- else:
- FFIConstants.notify.info('Setting output directory to: ' + outputDir)
- if (not extensionsDir):
- FFIConstants.notify.debug('Setting extensions directory to current directory')
- extensionsDir = '.'
- elif (not os.path.exists(extensionsDir)):
- FFIConstants.notify.error('Directory does not exist: ' + extensionsDir)
- else:
- FFIConstants.notify.debug('Setting extensions directory to: ' + extensionsDir)
- if (not codeLibs):
- FFIConstants.notify.error('You must specify one or more libraries to generate code from')
- else:
- FFIConstants.notify.debug('Generating code for: ' + `codeLibs`)
- 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)
- if not os.path.isdir(pathname):
- os.unlink(pathname)
- # Generate __init__.py
- initFilename = os.path.join(outputDir, '__init__.py')
- init = open(initFilename, 'w')
- # Generate PandaModules.py
- pandaModulesFilename = os.path.join(outputDir, '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)
- if os.path.exists(inFilename):
- inFile = open(inFilename, 'r')
- outFile = open(outFilename, 'w')
- outFile.write(inFile.read())
- # Generate a series of "libpandaModules.py" etc. files, one for
- # each named module.
- for moduleName in FFIConstants.CodeModuleNameList:
- print 'Importing code library: ' + moduleName
- exec('import %s as module' % moduleName)
- pandaModules.write('from %sModules import *\n' % (moduleName))
- moduleModulesFilename = os.path.join(outputDir, '%sModules.py' % (moduleName))
- moduleModules = open(moduleModulesFilename, 'w')
- moduleModules.write('from %s import *\n\n' % (moduleName))
- # Now look for extensions
- for className, classDef in module.__dict__.items():
- if type(classDef) == types.TypeType:
- extensionFilename = os.path.join(extensionsDir, '%s_extensions.py' % (className))
- if os.path.exists(extensionFilename):
- print ' Found extensions for class: %s' % (className)
- extension = open(extensionFilename, 'r')
- moduleModules.write(extension.read())
- moduleModules.write('\n')
-
- def run():
- global outputDir
- global directDir
- global extensionsDir
- global interrogateLib
- global codeLibs
- global doSqueeze
- global deleteSourceAfterSqueeze
- global generateManual
- global etcPath
- doGetopts()
- doErrorCheck()
- # Ok, now we can start generating code
- if native:
- generateNativeWrappers()
- else:
- from direct.ffi import FFIInterrogateDatabase
- db = FFIInterrogateDatabase.FFIInterrogateDatabase(etcPath = etcPath)
- db.generateCode(outputDir, extensionsDir)
- if doSqueeze:
- db.squeezeGeneratedCode(outputDir, deleteSourceAfterSqueeze)
- if generateManual:
- import epydoc.cli
- import direct.directbase.DirectStart
- mandir = os.path.join(outputDir,"docs")
- cmd = ["epydoc","-n","Panda3D","-o",mandir,"--docformat","panda","--ignore-param-mismatch",outputDir,directDir]
- sys.argv = cmd
- epydoc.cli.cli()
|