Skip to content

Commit

Permalink
Merge pull request #11 from con-av/master
Browse files Browse the repository at this point in the history
merged in latest version (1.1.6) of parent repo
  • Loading branch information
ksindi authored Jul 30, 2016
2 parents d778b92 + b22208a commit 309133d
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 13 deletions.
2 changes: 1 addition & 1 deletion sqlacodegen/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
version = '1.1.5.pre2'
version = __version__ = '1.1.6'
27 changes: 18 additions & 9 deletions sqlacodegen/codegen.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,13 @@ def plural_noun(self, noun): # needed for backrefs
return inflect_engine.plural_noun(noun)


# In SQLAlchemy 0.x, constraint.columns is sometimes a list, on 1.x onwards, always a ColumnCollection
def _get_column_names(constraint):
if isinstance(constraint.columns, list):
return constraint.columns
return list(constraint.columns.keys())


def _convert_to_valid_identifier(name):
assert name, 'Identifier cannot be empty'
if name[0].isdigit() or iskeyword(name):
Expand Down Expand Up @@ -71,7 +78,7 @@ def visit_bindparam(self, bindparam, within_columns_clause=False, literal_binds=
def _get_constraint_sort_key(constraint):
if isinstance(constraint, CheckConstraint):
return 'C{0}'.format(constraint.sqltext)
return constraint.__class__.__name__[0] + repr(constraint.columns)
return constraint.__class__.__name__[0] + repr(_get_column_names(constraint))


def _get_common_fk_constraints(table1, table2):
Expand Down Expand Up @@ -177,7 +184,7 @@ def render_fk_options(*opts):
remote_column = '{0}.{1}'.format(constraint.column.table.fullname, constraint.column.name)
return _flask_prepend + 'ForeignKey({0})'.format(render_fk_options(remote_column))
elif isinstance(constraint, ForeignKeyConstraint):
local_columns = constraint.columns
local_columns = _get_column_names(constraint)
remote_columns = ['{0}.{1}'.format(fk.column.table.fullname, fk.column.name)
for fk in constraint.elements]
return _flask_prepend + 'ForeignKeyConstraint({0})'.format(render_fk_options(local_columns, remote_columns))
Expand Down Expand Up @@ -313,7 +320,8 @@ def __init__(self, table, association_tables, inflect_engine, detect_joined):
for constraint in sorted(table.constraints, key=_get_constraint_sort_key):
if isinstance(constraint, ForeignKeyConstraint):
target_cls = self._tablename_to_classname(constraint.elements[0].column.table.name, inflect_engine)
if detect_joined and self.parent_name == 'Base' and set(constraint.columns) == pk_column_names:
if (detect_joined and self.parent_name == 'Base' and
set(_get_column_names(constraint)) == pk_column_names):
self.parent_name = target_cls
else:
relationship_ = ManyToOneRelationship(self.name, target_cls, constraint, inflect_engine)
Expand Down Expand Up @@ -452,7 +460,8 @@ class ManyToOneRelationship(Relationship):
def __init__(self, source_cls, target_cls, constraint, inflect_engine):
super(ManyToOneRelationship, self).__init__(source_cls, target_cls)

colname = constraint.columns[0]
column_names = _get_column_names(constraint)
colname = column_names[0]
tablename = constraint.elements[0].column.table.name
if not colname.endswith('_id'):
self.preferred_name = inflect_engine.singular_noun(tablename) or tablename
Expand All @@ -462,7 +471,7 @@ def __init__(self, source_cls, target_cls, constraint, inflect_engine):

# Add uselist=False to One-to-One relationships
if any(isinstance(c, (PrimaryKeyConstraint, UniqueConstraint)) and
set(col.name for col in c.columns) == set(constraint.columns)
set(col.name for col in c.columns) == set(column_names)
for c in constraint.table.constraints):
self.kwargs['uselist'] = 'False'

Expand All @@ -481,7 +490,7 @@ def __init__(self, source_cls, target_cls, constraint, inflect_engine):
self.kwargs['primaryjoin'] = "'and_({0})'".format(', '.join(['{0}.{1} == {2}.{3}'.format(source_cls, k.parent.name, target_cls, k.column.name)
for k in constraint.elements]))
else:
self.kwargs['primaryjoin'] = "'{0}.{1} == {2}.{3}'".format(source_cls, constraint.columns[0], target_cls,
self.kwargs['primaryjoin'] = "'{0}.{1} == {2}.{3}'".format(source_cls, column_names[0], target_cls,
constraint.elements[0].column.name)


Expand All @@ -492,16 +501,16 @@ def __init__(self, source_cls, target_cls, assocation_table, inflect_engine):
self.kwargs['secondary'] = repr(assocation_table.schema + '.' + assocation_table.name)
constraints = [c for c in assocation_table.constraints if isinstance(c, ForeignKeyConstraint)]
constraints.sort(key=_get_constraint_sort_key)
colname = constraints[1].columns[0]
colname = _get_column_names(constraints[1])[0]
tablename = constraints[1].elements[0].column.table.name
self.preferred_name = tablename if not colname.endswith('_id') else colname[:-3] + 's'
self.backref_name = inflect_engine.plural_noun(self.backref_name)

# Handle self referential relationships
if source_cls == target_cls:
self.preferred_name = 'parents' if not colname.endswith('_id') else colname[:-3] + 's'
pri_pairs = zip(constraints[0].columns, constraints[0].elements)
sec_pairs = zip(constraints[1].columns, constraints[1].elements)
pri_pairs = zip(_get_column_names(constraints[0]), constraints[0].elements)
sec_pairs = zip(_get_column_names(constraints[1]), constraints[1].elements)
pri_joins = ['{0}.{1} == {2}.c.{3}'.format(source_cls, elem.column.name, assocation_table.name, col)
for col, elem in pri_pairs]
sec_joins = ['{0}.{1} == {2}.c.{3}'.format(target_cls, elem.column.name, assocation_table.name, col)
Expand Down
10 changes: 7 additions & 3 deletions sqlacodegen/main.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
""" """
from __future__ import unicode_literals, division, print_function, absolute_import
import argparse
import codecs
import importlib
import sys

Expand Down Expand Up @@ -31,11 +32,13 @@ def main():
parser.add_argument('--noconstraints', action='store_true', help='ignore constraints')
parser.add_argument('--nojoined', action='store_true', help="don't autodetect joined table inheritance")
parser.add_argument('--noinflect', action='store_true', help="don't try to convert tables names to singular form")
parser.add_argument('--noclasses', action='store_true', help="don't generate classes, only tables")
parser.add_argument('--outfile', help='file to write output to (default: stdout)')
parser.add_argument('--nobackrefs', action='store_true', help="don't include backrefs")
parser.add_argument('--flask', action='store_true', help="use Flask-SQLAlchemy columns")
parser.add_argument('--ignorefk', help="Don't check fk constraints on specified columns (comma-separated)")
parser.add_argument('--outfile', type=argparse.FileType('w'), default=sys.stdout,
help='file to write output to (default: stdout)')
# parser.add_argument('--outfile', type=argparse.FileType('w'), default=sys.stdout,
# help='file to write output to (default: stdout)')
args = parser.parse_args()

if args.version:
Expand All @@ -52,7 +55,8 @@ def main():
tables = args.tables.split(',') if args.tables else None
fkcols = args.ignorefk.split(',') if args.ignorefk else None
metadata.reflect(engine, args.schema, not args.noviews, tables)
outfile = codecs.open(args.outfile, 'w', encoding='utf-8') if args.outfile else sys.stdout
generator = CodeGenerator(metadata, args.noindexes, args.noconstraints,
args.nojoined, args.noinflect, args.nobackrefs,
args.flask, fkcols)
generator.render(args.outfile)
generator.render(outfile)

0 comments on commit 309133d

Please sign in to comment.