Skip to content

Commit 4903efe

Browse files
committed
Fix table indent.
Fix in column_repr, boolean expressions issue. Info: http://www.sqlalchemy.org/trac/wiki/06Migration#AnImportantExpressionLanguageGotcha Fix CheckConstraints representation (merging issue 40) Fix selecting proper dialect that is used in main.py (more info at issue 30) Fix indent for z3c generator. Fix maximum number of arguments that could be passed into the table. Info: http://stackoverflow.com/questions/714475/what-is-a-maximum-number-of-arguments-in-a-python-function Refactoring main.py for better overview.
1 parent 155e8a1 commit 4903efe

File tree

8 files changed

+91
-64
lines changed

8 files changed

+91
-64
lines changed

ChangeLog

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,15 @@
1+
0.7b5
2+
Fix table indent.
3+
Fix in column_repr, boolean expressions issue.
4+
Info: http://www.sqlalchemy.org/trac/wiki/06Migration#AnImportantExpressionLanguageGotcha
5+
Fix CheckConstraints representation (merging issue 40)
6+
Fix selecting proper dialect that is used in main.py (more info at issue 30)
7+
Fix indent for z3c generator.
8+
Fix maximum number of arguments that could be passed into the table.
9+
Info: http://stackoverflow.com/questions/714475/what-is-a-maximum-number-of-arguments-in-a-python-function
10+
Refactoring main.py for better overview.
11+
[ghetman]
12+
113
0.6 (unreleased)
214
Some more fixes for Issues 16 to 24
315
[spamsch]
File renamed without changes.

setup.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
Setup script for building sqlautocode
66
"""
77

8-
version = '0.6b1'
8+
version = '0.7b5'
99

1010
from setuptools import setup, find_packages
1111

@@ -19,7 +19,7 @@
1919
zip_safe=True,
2020
license = 'MIT',
2121
classifiers = [
22-
"Development Status :: 4 - Beta",
22+
"Development Status :: 5 - Beta",
2323
"Intended Audience :: Developers",
2424
"Programming Language :: Python",
2525
],

sqlautocode/constants.py

Lines changed: 5 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,8 @@
11
# Nice print stuff
2-
TAB = 12*' '
2+
TAB = 4*' '
33

44
NLTAB = ',\n'+TAB
55

6-
USAGE = """usage: autoload.py [options]
7-
8-
Generates python code for a given database schema.
9-
10-
options:
11-
-h, --help Show this help
12-
-u URL, --url URL Database url (e.g.: postgresql+psycopg2://postgres:user@password/Database)
13-
-o FILE, --output FILE Where to put the output (default is stdout)
14-
-s NAME, --schema NAME Name of the schema to output (default is 'default')
15-
-t T1,T2,.. , --tables T1,T2 Name of tables to inspect (default is 'all').
16-
Support globbing character to select more tables.
17-
ex.: -t Download* will generate a model for all tables starting with Download
18-
19-
-i --noindex Do not generate index information
20-
-g --generic-types Generate generic column types rather than database-specific type
21-
-e --example Generate code with examples how to access data
22-
-3 --z3c Generate code for use with z3c.sqlalchemy
23-
"""
24-
256
HEADER = """\
267
# -*- coding: %(encoding)s -*-
278
## File autogenerated by SQLAutoCode
@@ -71,12 +52,9 @@ def getModel(metadata):
7152
print row
7253
"""
7354

74-
TABLE = """ Table('%(name)s', metadata,
75-
%(columns)s,
76-
%(constraints)s
77-
%(schema)s
78-
)
79-
"""
55+
#I suppose you wondering why here we use list for columns and constraints
56+
#python have a maximum number of arguments set to 255 ;(
57+
TABLE = """Table('%(name)s', metadata,*[%(columns)s,%(constraints)s]%(schema)s)"""
8058

8159
COLUMN = """Column(%(name)r, %(type)s%(constraints)s%(args)s)"""
8260

@@ -117,3 +95,4 @@ def getModel(metadata):
11795
'Failed. please easy_install ipython'
11896
"""
11997

98+
CHECK_CONSTRAINT = """CheckConstraint('%(sqltext)s')"""

sqlautocode/declarative.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -317,8 +317,8 @@ def __repr__(cls):
317317
Temporal.__table_args__ = {}
318318

319319
#add in the schema
320-
if self.config.schema:
321-
Temporal.__table_args__[1]['schema'] = table.schema
320+
#if self.config.schema:
321+
#Temporal.__table_args__[1]['schema'] = table.schema
322322

323323
#trick sa's model registry to think the model is the correct name
324324
if model_name != 'Temporal':

sqlautocode/formatter.py

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,14 @@ def table_repr(self):
1212
[repr(cn) for cn in self.constraints
1313
if not isinstance(cn, sqlalchemy.PrimaryKeyConstraint)]),
1414
'index': '',
15-
'schema': self.schema != None and "schema='%s'" % self.schema or '',
15+
'schema': self.schema != None and ",\n%sschema='%s'" % (constants.TAB, self.schema) or '',
1616
}
1717

1818
if data['constraints']:
19-
data['constraints'] = data['constraints'] + ','
19+
data['constraints'] = '\n%s%s,' % (constants.TAB, data['constraints'])
20+
21+
if data['columns']:
22+
data['columns'] = '\n%s%s' % (constants.TAB, data['columns'])
2023

2124
return util.as_out_str(constants.TABLE % data)
2225

@@ -39,7 +42,9 @@ def column_repr(self):
3942
kwarg.append( 'nullable')
4043
if self.onupdate:
4144
kwarg.append( 'onupdate')
42-
if self.default:
45+
#issue:
46+
#http://www.sqlalchemy.org/trac/wiki/06Migration#AnImportantExpressionLanguageGotcha
47+
if self.default is not None:
4348
kwarg.append( 'default')
4449
elif self.server_default:
4550
self.default = self.server_default.arg
@@ -77,9 +82,9 @@ def column_repr(self):
7782
}
7883

7984
if data['constraints']:
80-
if data['constraints']: data['constraints'] = ', ' + data['constraints']
85+
data['constraints'] = ', ' + data['constraints']
8186
if data['args']:
82-
if data['args']: data['args'] = ', ' + data['args']
87+
data['args'] = ', ' + data['args']
8388

8489
return util.as_out_str(constants.COLUMN % data)
8590

@@ -105,9 +110,14 @@ def index_repr(index):
105110
}
106111
return util.as_out_str(constants.INDEX % data)
107112

113+
def check_constraint_repr(cc):
114+
data = {'sqltext': cc.sqltext}
115+
return util.as_out_str(constants.CHECK_CONSTRAINT % data)
116+
108117
def monkey_patch_sa():
109118
sqlalchemy.sql.expression._TextClause.__repr__ = textclause_repr
110119
sqlalchemy.schema.Table.__repr__ = table_repr
111120
sqlalchemy.schema.Column.__repr__ = column_repr
112121
sqlalchemy.schema.ForeignKeyConstraint.__repr__ = foreignkeyconstraint_repr
113122
sqlalchemy.schema.Index.__repr__ = index_repr
123+
sqlalchemy.schema.CheckConstraint.__repr__ = check_constraint_repr

sqlautocode/main.py

Lines changed: 40 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,30 @@
33
from util import emit
44
from declarative import ModelFactory
55

6+
def emit_table(indent, db, options, table):
7+
"""Emit table representation."""
8+
emit('%s%s%s%s = %r' % (indent, options.table_prefix, table.name, options.table_suffix, table))
9+
emit_index(indent, db, options, table)
10+
11+
def emit_z3c_objects(indent, db, options, table):
12+
emit_table(indent, db, options, table)
13+
emit(indent + ('class %(tn)sObject(MappedClassBase): pass\n'
14+
'%(tab)smapper(%(tn)sObject, %(tn)s)') % {'tn':table.name, 'tab':indent})
15+
16+
def emit_index(indent, db, options, table):
17+
"""docstring for emit_index"""
18+
if not options.noindex:
19+
indexes = []
20+
if not table.indexes:
21+
# for certain dialects we need to include index support
22+
if hasattr(db.dialect, 'indexloader'):
23+
indexes = db.dialect.indexloader(db).indexes(table)
24+
else:
25+
print >>config.err, 'It seems that this dialect does not support indexes!'
26+
else:
27+
indexes = list(table.indexes)
28+
emit(*[indent + repr(index) for index in indexes])
29+
630
def main():
731
config.configure()
832

@@ -28,21 +52,23 @@ def main():
2852
formatter.monkey_patch_sa()
2953

3054
import sqlalchemy
55+
from sqlalchemy.engine.reflection import Inspector
3156
db, options = config.engine, config.options
3257
metadata = sqlalchemy.MetaData(db)
3358

3459
print >>config.err, 'Starting...'
3560
conn = db.connect()
61+
inspector = Inspector.from_engine(conn)
3662

3763
if options.schema != None:
3864
reflection_schema=options.schema
3965
else:
4066
try:
41-
reflection_schema = db.dialect._get_default_schema_name(conn)
67+
reflection_schema = inspector.default_schema_name
4268
except NotImplementedError:
4369
reflection_schema = None
4470

45-
tablenames = db.dialect.get_table_names(conn, reflection_schema)
71+
tablenames = inspector.get_table_names(reflection_schema)
4672

4773
# fixme: don't set up output until we're sure there's work to do!
4874
if options.tables:
@@ -62,8 +88,10 @@ def main():
6288
if options.generictypes:
6389
dialect = ''
6490
else:
65-
dialect = 'from sqlalchemy.databases.%s import *\n' % db.name
66-
91+
d1 = 'from sqlalchemy.databases.%s import *\n' % db.name
92+
d2 = 'from sqlalchemy.dialects.%s import *\n' % db.name
93+
#Determine with one is correct...
94+
dialect = util.select_imports([d1, d2])
6795

6896
header = options.z3c and constants.HEADER_Z3C or constants.HEADER
6997
emit(header % {'dialect': dialect, 'encoding': options.encoding})
@@ -72,43 +100,27 @@ def main():
72100
print >>config.err, "Generating python model for table %s" % (
73101
util.as_sys_str(tname))
74102

75-
table = sqlalchemy.Table(tname, metadata, schema=reflection_schema,
76-
autoload=True)
103+
table = sqlalchemy.Table(tname, metadata, schema=reflection_schema, autoload=True)
77104
if options.schema is None:
78105
# we're going to remove the schema from the table so that it
79106
# isn't rendered in the output. If we don't put back the
80107
# correct value, it may cause errors when other tables reference
81108
# this one.
82109
original_schema = table.schema
83110
table.schema = None
111+
else:
112+
original_schema = options.schema
84113

85-
else: original_schema = options.schema
114+
indent = ''
86115

87116
INC = '\n\n'
117+
emit(INC)
88118
if options.z3c:
89-
INC = INC + 4*' '
90-
91-
emit('%s%s%s%s = %r' % (INC, options.table_prefix, tname, options.table_suffix, table))
92-
93-
if options.z3c:
94-
emit(INC + ('class %(tn)sObject(MappedClassBase): pass\n'
95-
'mapper(%(tn)sObject, %(tn)s)') % {'tn':tname})
119+
emit_z3c_objects(constants.TAB, db, options, table)
120+
else:
121+
emit_table('', db, options, table)
96122

97123
table.schema = original_schema
98-
99-
# directly print indices after table def
100-
if not options.noindex:
101-
indexes = []
102-
if not table.indexes:
103-
# for certain dialects we need to include index support
104-
if hasattr(db.dialect, 'indexloader'):
105-
indexes = db.dialect.indexloader(db).indexes(table)
106-
else:
107-
print >>config.err, 'It seems that this dialect does not support indexes!'
108-
else:
109-
indexes = list(table.indexes)
110-
111-
util.emit(*[repr(index) for index in indexes])
112124

113125
if options.z3c:
114126
emit(constants.FOOTER_Z3C)

sqlautocode/util.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,4 +171,18 @@ def name2label(name, schema=None):
171171
name = '.'.join(name.split('.')[1:])
172172
label = str(''.join([s.capitalize() for s in
173173
re.findall(r'([A-Z][a-z0-9]+|[a-z0-9]+|[A-Z0-9]+)', name)]))
174-
return label
174+
return label
175+
176+
def select_imports(x):
177+
"""
178+
Try import modules used in output file eg: dialect.
179+
Return first valid string or ''.
180+
"""
181+
for i in x:
182+
try:
183+
exec(i)
184+
return i
185+
except:
186+
pass
187+
return ''
188+

0 commit comments

Comments
 (0)