/usr/bin/forgetsql-generate is in python-forgetsql 0.5.1-12build1.
This file is owned by root:root, with mode 0o755.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 | #!/usr/bin/python
# $Id: forgetsql-generate,v 1.5 2004/03/08 11:04:28 stain Exp $
## Distributed under LGPL
## (c) Stian Søiland 2002-2004
## stian@soiland.no
## http://forgetsql.sourceforge.net/
# __version__ should really come from setup.py.. hmm
__version__ = "0.5.1"
import exceptions, time, re, types, pprint, sys
import forgetSQL
# backwards compatibility
try:
True,False
except NameError:
(True, False) = (1==1, 1==0)
# Taken from http://www.python.org/doc/current/lib/built-in-funcs.html
def my_import(name):
mod = __import__(name)
components = name.split('.')
# Takes care of things like pyPgSQL.PgSQL
for comp in components[1:]:
mod = getattr(mod, comp)
return mod
def generateFromTables(tables, cursor, getLinks=1, code=0):
"""Generates python code (or class objects if code is false)
based on SQL queries on the table names given in the list
tables.
code - if given - should be an dictionary containing these
keys to be inserted into generated code:
'database': database name
'module': database module name
'connect': string to be inserted into module.connect()
"""
curs = cursor()
forgetters = {}
class _Wrapper(forgetSQL.Forgetter):
pass
_Wrapper.cursor = cursor
for table in tables:
# capitalize the table name to make it look like a class
name = table.capitalize()
# Define the class by instanciating the meta class to
# the given name (requires Forgetter to be new style)
forgetter = _Wrapper.__class__(name, (_Wrapper,), {})
# Register it
forgetters[name] = forgetter
forgetter._sqlTable = table
forgetter._sqlLinks = {}
forgetter._sqlFields = {}
forgetter._shortView = ()
forgetter._descriptions = {}
forgetter._userClasses = {}
# Get columns
curs.execute("SELECT * FROM %s LIMIT 1" % table)
columns = [column[0] for column in curs.description]
# convert to dictionary and register in forgetter
for column in columns:
forgetter._sqlFields[column] = column
if getLinks:
# Try to find links between tables (!)
# Note the big O factor with this ...
for (tableName, forgetter) in forgetters.items():
for (key, column) in forgetter._sqlFields.items():
# A column refering to another table would most likely
# be called otherColumnID or just otherColumn. We'll
# lowercase below when performing the test.
possTable = re.sub(r'_?id$', '', column)
# all tables (ie. one of the forgetters) are candidates
foundLink = False
for candidate in forgetters.keys():
if candidate.lower() == possTable.lower():
if possTable.lower() == tableName.lower():
# It's our own primary key!
forgetter._sqlPrimary = (column,)
break
# Woooh! First - let's replace 'blapp_id' with 'blapp'
# as the attribute name to indicate that it would
# contain the Blapp instance, not just
# some ID.
del forgetter._sqlFields[key]
forgetter._sqlFields[possTable] = column
# And.. we'll need to know which class we refer to
forgetter._userClasses[possTable] = candidate
break # we've found our candidate
if code:
if code['module'] == "MySQLdb":
code['class'] = 'forgetSQL.MysqlForgetter'
else:
code['class'] = 'forgetSQL.Forgetter'
code['date'] = time.strftime('%Y-%m-%d')
print '''
"""Database wrappers %(database)s
Autogenerated by forgetsql-generate %(date)s.
"""
import forgetSQL
#import %(module)s
class _Wrapper(%(class)s):
"""Just a simple wrapper class so that you may
easily change stuff for all forgetters. Typically
this involves subclassing MysqlForgetter instead."""
# Example database connection (might miss password)
#_dbModule = %(module)s
#_dbConnection = %(module)s.connect(%(connect)s)
#def cursor(self):
# return self._dbConnection.cursor()
''' % code
items = forgetters.items()
items.sort()
for (name, forgetter) in items:
print "class %s(_Wrapper):" % name
for (key, value) in forgetter.__dict__.items():
if key.find('__') == 0:
continue
nice = pprint.pformat(value)
# Get some indention
nice = nice.replace('\n', '\n ' + ' '*len(key))
print ' %s = ' % key, nice
print ""
print '''
# Prepare them all. We need to send in our local
# namespace.
forgetSQL.prepareClasses(locals())
'''
else:
forgetSQL.prepareClasses(forgetters)
return forgetters
def main():
try:
# Should
from optparse import OptionParser
except ImportError:
print >>sys.stderr, "optik 1.4.1 or Python 2.3 or later needed for command line usage"
print >>sys.stderr, "Download optik from http://optik.sourceforge.net/"
print >>sys.stderr, "or upgrade Python."
sys.exit(1)
usage = """usage: %prog [options]
Generates Python code for using forgetSQL to access database tables.
You need to include a line-seperated list of table names to either
stdin or as a file using option --tables."""
parser = OptionParser(version="%prog " + __version__, usage=usage)
parser.add_option("-t", "--tables", dest="tables",
help="read list of tables from FILE instead of stdin",
metavar="FILE")
parser.add_option("-o", "--output", dest="output",
help="write generated code to OUTPUT instead of stdout")
parser.add_option("-m", "--dbmodule", dest="dbmodule",
help="database module to use")
parser.add_option("-H", "--host", dest="host",
help="hostname of database server")
parser.add_option("-d", "--database", dest="database",
help="database to connect to")
parser.add_option("-u", "--username", dest="username",
help="database username")
parser.add_option("-p", "--password", dest="password",
help="database password")
parser.add_option("-c", "--connect", dest="connect",
help="database connect string (instead of host/database/user/password")
(options, args) = parser.parse_args()
if options.tables:
try:
file = open(options.tables)
except IOError, e:
print >>sys.stderr, "%s: %s" % (e.strerror, e.filename)
sys.exit(2)
else:
file = sys.stdin
if options.output:
try:
# Override print.. dirty.
sys.stdout = open(options.output, "w")
except IOError, e:
print >>sys.stderr, "%s: %s" % (e.strerror, e.filename)
sys.exit(3)
if not options.dbmodule:
print >>sys.stderr, "Missing required option --dbmodule"
parser.print_help(file=sys.stderr)
sys.exit(4)
try:
dbmodule = my_import(options.dbmodule)
except ImportError:
print >>sys.stderr, "Unknown database module", options.dbmodule
sys.exit(5)
if options.connect:
connectstring = options.connect
try:
connection = dbmodule.connect(options.connect)
except Exception, e:
print >>sys.stderr, "Could not connect to database using", \
options.connect
sys.exit(6)
else:
params = {}
if options.database:
if options.dbmodule == "MySQLdb":
params['db'] = options.database
else:
params['database'] = options.database
else:
print >>sys.stderr, "Missing required option --database or --connect"
sys.exit(7)
if options.host:
params['host'] = options.host
if options.username:
params['user'] = options.username
if options.password:
if options.dbmodule == "MySQLdb":
params['passwd'] = options.password
else:
params['password'] = options.password
connectstring = ", ".join(["%s=%r" % (key, value)
for (key,value) in params.items()
# filter out password for 'security reasons'
if key != "password"])
try:
connection = dbmodule.connect(**params)
except Exception, e:
print >>sys.stderr, "Could not connect to database using", \
connectstring
print >>sys.stderr, e
sys.exit(8)
cursor = connection.cursor
tables = file.read().split()
if not tables:
print >>sys.stderr, "No table names supplied"
sys.exit(9)
# collect useful strings for generated code
code = {}
code['connect'] = connectstring
code['module'] = options.dbmodule
code['database'] = options.database or '(unknown)'
generateFromTables(tables, cursor, code=code)
if __name__=='__main__':
main()
|