/sqlautocode/config.py
Python | 189 lines | 179 code | 4 blank | 6 comment | 9 complexity | a012232eaa45ab8b0024c8d35504cd04 MD5 | raw file
1#!python 2#-*- coding: UTF-8 -*- 3 4import optparse 5import os 6import sys 7import re 8 9options = None 10out = sys.stdout 11err = sys.stderr 12dburl = None 13engine = None 14 15# TODO: encoding (default utf-8) 16 17def create_parser(): 18 parser = optparse.OptionParser( 19 """autocode.py <database_url> [options, ] 20Generates Python source code for a given database schema. 21 22Example: ./autocode.py postgres://user:password@myhost/database -o out.py""") 23 24 parser.add_option( 25 "-o", "--output", 26 help="Write to file (default is stdout)", 27 action="store", dest="output") 28 29 parser.add_option( 30 "--force", 31 help="Overwrite Write to file (default is stdout)", 32 action="store_true", dest="force") 33 34 parser.add_option( 35 "-s", "--schema", 36 help="Optional, reflect a non-default schema", 37 action="callback", callback=_prep_schema, type="string", dest="schema") 38 39 parser.add_option( 40 "-t", "--tables", 41 help=("Optional, only reflect this comma-separated list of tables. " 42 "Wildcarding with '*' is supported, e.g: --tables account_*," 43 "orders,order_items,*_audit"), 44 action="callback", callback=_prep_tables, type="string", dest="tables") 45 46 parser.add_option( 47 "-b", "--table-prefix", 48 help="Prefix for generated SQLAlchemy Table object names", 49 action="store", dest="table_prefix") 50 51 parser.add_option( 52 "-a", "--table-suffix", 53 help="Suffix for generated SQLAlchemy Table object names", 54 action="store", dest="table_suffix") 55 56 parser.add_option( 57 "-i", "--noindexes", "--noindex", 58 help="Do not emit index information", 59 action="store_true", dest="noindex") 60 61 parser.add_option( 62 "-g", "--generic-types", 63 help="Emit generic ANSI column types instead of database-specific.", 64 action="store_true", dest="generictypes") 65 66 parser.add_option( 67 "--encoding", 68 help="Encoding for output, default utf8", 69 action="store", dest="encoding") 70 71 parser.add_option( 72 "-e", "--example", 73 help="Generate code with examples how to access data", 74 action="store_true", dest="example") 75 76 parser.add_option( 77 "-3", "--z3c", 78 help="Generate code for use with z3c.sqlalchemy", 79 action="store_true", dest="z3c") 80 81 parser.add_option( 82 "-d", "--declarative", 83 help="Generate declarative SA code", 84 action="store_true", dest="declarative") 85 86 parser.add_option( 87 "-n", "--interactive", 88 help="Generate Interactive example in your code.", 89 action="store_true", dest="interactive") 90 91 92 parser.set_defaults(tables=[], 93 encoding='utf-8', 94 table_prefix='', 95 table_suffix='') 96 97 return parser 98 99def _prep_tables(option, opt_str, value, parser): 100 if not value: 101 parser.values.tables = [] 102 else: 103 parser.values.tables = [x.strip() 104 for x in value.split(',') 105 if x.strip() != ''] 106 107def _prep_schema(option, opt_str, value, parser): 108 #handle multiple schemas on the command line 109 value = [x.strip() 110 for x in value.split(',') 111 if x.strip() != ''] 112 if len(value) == 1: 113 parser.values.schema = value[0] 114 return 115 parser.values.schema = value 116 117def _version_check(parser): 118 try: 119 import sqlalchemy 120 except ImportError, ex: 121 parser.error("SQLAlchemy version 0.4.0 or higher is required. (%s)" % 122 (ex)) 123 124 version = getattr(sqlalchemy, '__version__', None) 125 if version is None: 126 parser.error("SQLAlchemy version 0.4.0 or higher is required.") 127 elif version == 'svn': 128 pass 129 else: 130 non_numeric = re.compile('[^0-9]*') 131 version_info = tuple([int(i) for i in non_numeric.split(version)]) 132 if version_info < (0, 4): 133 parser.error("SQLAlchemy version 0.4.0 or higher is required.") 134 135def _setup_engine(parser, url): 136 global engine 137 138 import sqlalchemy 139 try: 140 engine = sqlalchemy.create_engine(url) 141 test = engine.connect() 142 test.close() 143 except sqlalchemy.exceptions.SQLAlchemyError, ex: 144 parser.error('Could not connect to "%s": %s' % (url, ex)) 145 146 147def _instrument(): 148 # monkeypatch SQLAlchemy __repr__ methods 149 import formatter 150 import loader 151 152def _set_output(path, overwrite=False): 153 if os.path.exists(path) and not overwrite: 154 print >>err, 'File "%s" exists and will be overwritten.' % path 155 resp = raw_input('Overwrite (y/[n]): ') 156 if not resp.strip().lower().startswith('y'): 157 print >>err, "Aborted." 158 sys.exit(-1) 159 160 global out 161 try: 162 out = open(path, 'w') 163 except IOError, e: 164 print >>err, 'Could not open "%s" for writing: %s' % (path, e) 165 sys.exit(-1) 166 167 168def configure(argv=sys.argv): 169 global options, dburl 170 171 parser = create_parser() 172 options, args = parser.parse_args(argv) 173 174 if len(args) < 2: 175 parser.error("A database URL is required.") 176 elif len(args) > 2: 177 parser.error("Unknown arguments: %s" % (' '.join(args[2:]))) 178 else: 179 dburl = args[1] 180 181 _version_check(parser) 182 183 _setup_engine(parser, dburl) 184 185 _instrument() 186 187 if options.output is not None: 188 _set_output(options.output, options.force) 189