#!/usr/bin/env python
"""Generate.py
> python Generate.py -h
"""
import os, sys
from getopt import getopt
import FixPath
import MiddleKit
from MiscUtils import StringTypes
if sys.platform == 'win32':
# without this, I can't see output from uncaught exceptions!
# perhaps this is caused by the recent incorporation of win32all (via DataTable)?
sys.stderr = sys.stdout
class Generate:
def databases(self):
return ['MSSQL', 'MySQL', 'PostgreSQL'] # @@ 2000-10-19 ce: should build this dynamically
def main(self, args=sys.argv):
opt = self.options(args)
# Make or check the output directory
outdir = opt['outdir']
if not os.path.exists(outdir):
os.mkdir(outdir)
elif not os.path.isdir(outdir):
print 'Error: Output target, %s, is not a directory.' % outdir
# Generate
if opt.has_key('sql'):
print 'Generating SQL...'
self.generate(
pyClass = opt['db'] + 'SQLGenerator',
model = opt['model'],
configFilename = opt.get('config'),
outdir = os.path.join(outdir, 'GeneratedSQL'))
if opt.has_key('py'):
print 'Generating Python...'
self.generate(
pyClass = opt['db'] + 'PythonGenerator',
model = opt['model'],
configFilename = opt.get('config'),
outdir=outdir)
model = MiddleKit.Core.Model.Model(opt['model'],
configFilename=opt.get('config'), havePythonClasses=0)
model.printWarnings()
def usage(self, errorMsg=None):
progName = os.path.basename(sys.argv[0])
if errorMsg:
print '%s: error: %s' % (progName, errorMsg)
print 'Usage: %s --db DBNAME --model FILENAME [--sql] [--py] [--config FILENAME] [--outdir DIRNAME]' % progName
print ' %s -h | --help' % progName
print
print ' * Known databases include: %s' % ', '.join(self.databases())
print ' * If neither --sql nor --py are specified, both are generated.'
print ' * If --outdir is not specified, then the base filename (sans extension) is used.'
print ' * --config lets you specify a different config filename inside the model.'
print ' This is mostly useful for the regression test suite.'
print
sys.exit(1)
def options(self, args):
# Command line dissection
if type(args) == type(''):
args = args.split()
optPairs, files = getopt(args[1:], 'h',
['help', 'db=', 'model=', 'sql', 'py', 'config=', 'outdir='])
if len(optPairs) < 1:
self.usage('Missing options.')
if len(files) > 0:
self.usage('Extra files or options passed.')
# Turn the cmd line optPairs into a dictionary
opt = {}
for key, value in optPairs:
if len(key) >= 2 and key[:2] == '--':
key = key[2:]
elif key[0] == '-':
key = key[1:]
opt[key] = value
# Check for required opt, set defaults, etc.
if opt.has_key('h') or opt.has_key('help'):
self.usage()
if not opt.has_key('db'):
self.usage('No database specified.')
if not opt.has_key('model'):
self.usage('No model specified.')
if not opt.has_key('sql') and not opt.has_key('py'):
opt['sql'] = ''
opt['py'] = ''
if not opt.has_key('outdir'):
opt['outdir'] = os.curdir
return opt
def generate(self, pyClass, model, configFilename, outdir):
"""Generate code using the given class, model and output directory.
The pyClass may be a string, in which case a module of the same name is
imported and the class extracted from that. The model may be a string,
in which case it is considered a filename of a model.
"""
if type(pyClass) in StringTypes:
module = __import__(pyClass, globals())
pyClass = getattr(module, pyClass)
generator = pyClass()
if type(model) in StringTypes:
generator.readModelFileNamed(model, configFilename=configFilename,
havePythonClasses=0)
else:
generator.setModel(model)
generator.generate(outdir)
if __name__ == '__main__':
Generate().main(sys.argv)
|