Package turbogears :: Package command :: Module sacommand

Source Code for Module turbogears.command.sacommand

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