Package turbogears :: Package command :: Module sacommand

Source Code for Module turbogears.command.sacommand

  1  from peak.rules import abstract, when, around 
  2  from turbogears import config 
  3  from turbogears.util import get_model 
  4  from turbogears.decorator import simple_decorator 
  5  try: 
  6      from sqlalchemy import MetaData, exceptions, Table, String, Unicode 
  7      from turbogears.database import bind_metadata, metadata, get_engine 
  8  except ImportError: # if not available, complain only at run-time 
  9      from turbogears.util import missing_dependency_error 
 10      no_sqlalchemy = missing_dependency_error('SQLAlchemy') 
 11  else: 
 12      from sqlalchemy import Text, UnicodeText 
 13      no_sqlalchemy = False 
14 15 16 @abstract() 17 -def sacommand(command, args):
18 pass
19 20 @around(sacommand, "command and command != 'help' and no_sqlalchemy")
21 -def no_engine(command, args):
22 print no_sqlalchemy
23 24 @when(sacommand, "command == 'help'")
25 -def help(command, args):
26 print """TurboGears SQLAlchemy Helper 27 28 tg-admin sql command [options] 29 30 Available commands: 31 create Create tables 32 execute Execute SQL statements 33 help Show help 34 list List tables that appear in the model 35 status Show differences between model and database 36 """
37 38 @when(sacommand, "command == 'create'")
39 -def create(command, args):
40 print "Creating tables at %s" % (config.get("sqlalchemy.dburi")) 41 bind_metadata() 42 get_model() 43 metadata.create_all()
44 45 @when(sacommand, "command == 'list'")
46 -def list_(command, args):
47 get_model() 48 for tbl in metadata.tables.values(): 49 print tbl.fullname
50 51 @when(sacommand, "command == 'execute'")
52 -def execute(command, args):
53 eng = get_engine() 54 for cmd in args[2:]: 55 ret = eng.execute(cmd) 56 try: 57 print list(ret) 58 except: 59 # Proceed silently if the command produced no results 60 pass
61 62 @when(sacommand, "command == 'status'")
63 -def status(command, args):
64 bind_metadata() 65 get_model() 66 ret = compare_metadata(metadata, MetaData(metadata.bind)) 67 for l in ret: 68 print l 69 if not ret: 70 print "Database matches model"
71
72 -def indent(ls):
73 return [' ' + l for l in ls]
74
75 -def compare_metadata(pym, dbm):
76 rc = [] 77 for pyt in pym.tables.values(): 78 try: 79 dbt = Table(pyt.name, dbm, autoload=True, schema=pyt.schema) 80 except exceptions.NoSuchTableError: 81 rc.extend(("Create table " + pyt.fullname, '')) 82 else: 83 ret = compare_table(pyt, dbt) 84 if ret: 85 rc.append("Change table " + pyt.fullname) 86 rc.extend(indent(ret) + ['']) 87 return rc
88
89 -def compare_table(pyt, dbt):
90 rc = [] 91 dbcols = dict([(s.lower(), s) for s in dbt.columns.keys()]) 92 for pyc in pyt.columns: 93 name = pyc.name.lower() 94 if dbcols.has_key(name): 95 ret = compare_column(pyc, dbt.columns[dbcols[name]]) 96 if ret: 97 rc.append("Change column " + pyc.name) 98 rc.extend(indent(ret)) 99 dbcols.pop(name) 100 else: 101 rc.append("Add column " + pyc.name) 102 for dbcol in dbcols: 103 rc.append("Remove column " + dbcol) 104 return rc
105
106 -def compare_column(pyc, dbc):
107 rc = [] 108 pyt, dbt = pyc.type, dbc.type 109 110 # Table reflection cannot recognize Unicode, so check only for String 111 if isinstance(pyt, Unicode): 112 pyt = String(pyt.length) 113 elif isinstance(pyt, UnicodeText): 114 pyt = Text(pyt.length) 115 116 # Check type 117 if not isinstance(dbt, pyt.__class__): 118 rc.append('Change type to ' + pyt.__class__.__name__) 119 120 # Check length (for strings) 121 else: 122 if isinstance(pyt, String): 123 if pyt.length != dbt.length: 124 rc.append('Change length to ' + str(pyt.length)) 125 126 # Check primary key 127 if dbc.primary_key != pyc.primary_key: 128 rc.append(pyc.primary_key and 'Make primary key' or 'Remove primary key') 129 130 # TODO: Check foreign keys 131 132 # Check default 133 if (dbc.default is not None and pyc.default is not None 134 and dbc.default != pyc.default): 135 rc.append('Change default to ' + str(pyc.default.arg)) 136 137 # Check index 138 if dbc.index is not None and dbc.index != pyc.index: 139 rc.append(pyc.index and 'Add index' or 'Remove index') 140 141 return rc
142