def _relation_repr(cls, rel): target = rel.argument if target and inspect.isfunction(target): target = target() if isinstance(target, Mapper): target = target.class_ target = target.__name__ primaryjoin = '' lookup = mtl() foo = rel.key if rel.primaryjoin is not None and hasattr( rel.primaryjoin, 'right'): right_lookup = lookup.get( rel.primaryjoin.right.table.name, '%s.c' % rel.primaryjoin.right.table.name) left_lookup = lookup.get( rel.primaryjoin.left.table.name, '%s.c' % rel.primaryjoin.left.table.name) primaryjoin = ", primaryjoin='%s.%s==%s.%s'" % ( left_lookup, rel.primaryjoin.left.name, right_lookup, rel.primaryjoin.right.name) elif hasattr(rel, '_as_string'): primaryjoin = ', primaryjoin="%s"' % rel._as_string secondary = '' secondaryjoin = '' if rel.secondary is not None: """ **HACK**: If there is a secondary relationship like between Venue, Event, and Event_Type, then I'm only going show a primary relationship. "Events = relationship('Event', primaryjoin='Venue.id==Event.venue_id')" and not "Event_Types = relation('EventType', primaryjoin='Venue.id==Event.venue_id', secondary=Event, secondaryjoin='Event.event_type_id==EventType.id')" """ if rel.secondary.name in self.table_model_dict: target = self.table_model_dict[rel.secondary.name] else: target = self.find_new_name( singular(name2label(rel.secondary.name)), []) # **HACK** secondary = '' secondaryjoin = '' foo = plural(rel.secondary.name) backref = '' # if rel.backref: # backref=", backref='%s'"%rel.backref.key return "%s = relationship('%s'%s%s%s%s)" % ( foo, target, primaryjoin, secondary, secondaryjoin, backref)
def _relation_repr(cls, rel): target = rel.argument if target and inspect.isfunction(target): target = target() if isinstance(target, Mapper): target = target.class_ target = target.__name__ primaryjoin = '' lookup = mtl() foo = rel.key if rel.primaryjoin is not None and hasattr(rel.primaryjoin, 'right'): right_lookup = lookup.get(rel.primaryjoin.right.table.name, '%s.c' % rel.primaryjoin.right.table.name) left_lookup = lookup.get(rel.primaryjoin.left.table.name, '%s.c' % rel.primaryjoin.left.table.name) primaryjoin = ", primaryjoin='%s.%s==%s.%s'" % (left_lookup, rel.primaryjoin.left.name, right_lookup, rel.primaryjoin.right.name) elif hasattr(rel, '_as_string'): primaryjoin = ', primaryjoin="%s"' % rel._as_string secondary = '' secondaryjoin = '' if rel.secondary is not None: """ **HACK**: If there is a secondary relationship like between Venue, Event, and Event_Type, then I'm only going show a primary relationship. "Events = relationship('Event', primaryjoin='Venue.id==Event.venue_id')" and not "Event_Types = relation('EventType', primaryjoin='Venue.id==Event.venue_id', secondary=Event, secondaryjoin='Event.event_type_id==EventType.id')" """ if rel.secondary.name in self.table_model_dict: target = self.table_model_dict[rel.secondary.name] else: target = self.find_new_name(singular(name2label(rel.secondary.name)), []) # **HACK** secondary = '' secondaryjoin = '' foo = plural(rel.secondary.name) backref = '' # if rel.backref: # backref=", backref='%s'"%rel.backref.key return "%s = relationship('%s'%s%s%s%s)" % (foo, target, primaryjoin, secondary, secondaryjoin, backref)
def create_model(self, table): #partially borrowed from Jorge Vargas' code #http://dpaste.org/V6YS/ log.debug('Creating Model from table: %s' % table.name) model_name = self.find_new_name(singular(name2label(table.name)), self.used_model_names) self.used_model_names.append(model_name) is_many_to_many_table = self.is_many_to_many_table(table) table_name = self.find_new_name(table.name, self.used_table_names) self.used_table_names.append(table_name) mtl = self.model_table_lookup class Temporal(self.DeclarativeBase): __table__ = table @classmethod def _relation_repr(cls, rel): target = rel.argument if target and inspect.isfunction(target): target = target() if isinstance(target, Mapper): target = target.class_ target = target.__name__ primaryjoin = '' lookup = mtl() if rel.primaryjoin is not None and hasattr( rel.primaryjoin, 'right'): right_lookup = lookup.get( rel.primaryjoin.right.table.name, '%s.c' % rel.primaryjoin.right.table.name) left_lookup = lookup.get( rel.primaryjoin.left.table.name, '%s.c' % rel.primaryjoin.left.table.name) primaryjoin = ", primaryjoin='%s.%s==%s.%s'" % ( left_lookup, rel.primaryjoin.left.name, right_lookup, rel.primaryjoin.right.name) elif hasattr(rel, '_as_string'): primaryjoin = ', primaryjoin="%s"' % rel._as_string secondary = '' secondaryjoin = '' if rel.secondary is not None: secondary = ", secondary=%s" % rel.secondary.name right_lookup = lookup.get( rel.secondaryjoin.right.table.name, '%s.c' % rel.secondaryjoin.right.table.name) left_lookup = lookup.get( rel.secondaryjoin.left.table.name, '%s.c' % rel.secondaryjoin.left.table.name) secondaryjoin = ", secondaryjoin='%s.%s==%s.%s'" % ( left_lookup, rel.secondaryjoin.left.name, right_lookup, rel.secondaryjoin.right.name) backref = '' # if rel.backref: # backref=", backref='%s'"%rel.backref.key return "%s = relation('%s'%s%s%s%s)" % (rel.key, target, primaryjoin, secondary, secondaryjoin, backref) @classmethod def __repr__(cls): log.debug('repring class with name %s' % cls.__name__) try: mapper = None try: mapper = class_mapper(cls) except exc.InvalidRequestError: log.warn( "A proper mapper could not be generated for the class %s, no relations will be created" % model_name) s = "" s += "class " + model_name + '(DeclarativeBase):\n' if is_many_to_many_table: s += " __table__ = %s\n\n" % table_name else: s += " __tablename__ = '%s'\n\n" % table_name if hasattr(cls, '__table_args__'): #if cls.__table_args__[0]: #for fkc in cls.__table_args__[0]: # fkc.__class__.__repr__ = foreignkeyconstraint_repr # break s += " __table_args__ = %s\n\n" % cls.__table_args__ s += " #column definitions\n" for column in sorted(cls.__table__.c, by_name): s += " %s = %s\n" % (column.name, column_repr(column)) s += "\n #relation definitions\n" ess = s # this is only required in SA 0.5 if mapper and RelationProperty: for prop in mapper.iterate_properties: if isinstance(prop, RelationshipProperty): s += ' %s\n' % cls._relation_repr(prop) return s except Exception, e: log.error("Could not generate class for: %s" % cls.__name__) from traceback import format_exc log.error(format_exc()) return ''
class ModelFactory(object): def __init__(self, config): self.config = config self.used_model_names = [] self.used_table_names = [] schema = getattr(self.config, 'schema', None) self._metadata = MetaData(bind=config.engine) self._foreign_keys = {} kw = {} self.schemas = None if schema: if isinstance(schema, (list, tuple)): self.schemas = schema else: self.schemas = (schema, ) for schema in self.schemas: log.info('Reflecting database... schema:%s' % schema) self._metadata.reflect(schema=schema) else: log.info('Reflecting database...') self._metadata.reflect() self.DeclarativeBase = declarative_base(metadata=self._metadata) def _table_repr(self, table): s = "Table(u'%s', metadata,\n" % (table.name) for column in table.c: s += " %s,\n" % column_repr(column) if table.schema: s += " schema='%s'\n" % table.schema s += ")" return s def __repr__(self): tables = self.get_many_to_many_tables() tables.extend(self.get_tables_with_no_pks()) models = self.models s = StringIO() engine = self.config.engine if not isinstance(engine, basestring): engine = str(engine.url) s.write(constants.HEADER_DECL % engine) if 'postgres' in engine: s.write(constants.PG_IMPORT) self.used_table_names = [] self.used_model_names = [] for table in tables: if table not in self.tables: continue table_name = self.find_new_name(table.name, self.used_table_names) self.used_table_names.append(table_name) s.write('%s = %s\n\n' % (table_name, self._table_repr(table))) for model in models: s.write(model.__repr__()) s.write("\n\n") if self.config.example or self.config.interactive: s.write(constants.EXAMPLE_DECL % (models[0].__name__, models[0].__name__)) if self.config.interactive: s.write(constants.INTERACTIVE % ([model.__name__ for model in models], models[0].__name__)) return s.getvalue() @property def tables(self): if self.config.options.tables: tables = set(self.config.options.tables) return [ self._metadata.tables[t] for t in set(self._metadata.tables.keys()).intersection(tables) ] return self._metadata.tables.values() @property def table_names(self): return [t.name for t in self.tables] @property def models(self): if hasattr(self, '_models'): return self._models self.used_model_names = [] self.used_table_names = [] self._models = [] for table in self.get_non_many_to_many_tables(): try: self._models.append(self.create_model(table)) except exc.ArgumentError: log.warning( "Table with name %s ha no primary key. No ORM class created" % table.name) self._models.sort(by__name__) return self._models def get_tables_with_no_pks(self): r = [] for table in self.get_non_many_to_many_tables(): if not [c for c in table.columns if c.primary_key]: r.append(table) return r def model_table_lookup(self): if hasattr(self, '_model_table_lookup'): return self._model_table_lookup self._model_table_lookup = dict( ((m.__table__.name, m.__name__) for m in self.models)) return self._model_table_lookup def find_new_name(self, prefix, used, i=0): if i != 0: prefix = "%s%d" % (prefix, i) if prefix in used: prefix = prefix return self.find_new_name(prefix, used, i + 1) return prefix def create_model(self, table): #partially borrowed from Jorge Vargas' code #http://dpaste.org/V6YS/ log.debug('Creating Model from table: %s' % table.name) model_name = self.find_new_name(singular(name2label(table.name)), self.used_model_names) self.used_model_names.append(model_name) is_many_to_many_table = self.is_many_to_many_table(table) table_name = self.find_new_name(table.name, self.used_table_names) self.used_table_names.append(table_name) mtl = self.model_table_lookup class Temporal(self.DeclarativeBase): __table__ = table @classmethod def _relation_repr(cls, rel): target = rel.argument if target and inspect.isfunction(target): target = target() if isinstance(target, Mapper): target = target.class_ target = target.__name__ primaryjoin = '' lookup = mtl() if rel.primaryjoin is not None and hasattr( rel.primaryjoin, 'right'): right_lookup = lookup.get( rel.primaryjoin.right.table.name, '%s.c' % rel.primaryjoin.right.table.name) left_lookup = lookup.get( rel.primaryjoin.left.table.name, '%s.c' % rel.primaryjoin.left.table.name) primaryjoin = ", primaryjoin='%s.%s==%s.%s'" % ( left_lookup, rel.primaryjoin.left.name, right_lookup, rel.primaryjoin.right.name) elif hasattr(rel, '_as_string'): primaryjoin = ', primaryjoin="%s"' % rel._as_string secondary = '' secondaryjoin = '' if rel.secondary is not None: secondary = ", secondary=%s" % rel.secondary.name right_lookup = lookup.get( rel.secondaryjoin.right.table.name, '%s.c' % rel.secondaryjoin.right.table.name) left_lookup = lookup.get( rel.secondaryjoin.left.table.name, '%s.c' % rel.secondaryjoin.left.table.name) secondaryjoin = ", secondaryjoin='%s.%s==%s.%s'" % ( left_lookup, rel.secondaryjoin.left.name, right_lookup, rel.secondaryjoin.right.name) backref = '' # if rel.backref: # backref=", backref='%s'"%rel.backref.key return "%s = relation('%s'%s%s%s%s)" % (rel.key, target, primaryjoin, secondary, secondaryjoin, backref) @classmethod def __repr__(cls): log.debug('repring class with name %s' % cls.__name__) try: mapper = None try: mapper = class_mapper(cls) except exc.InvalidRequestError: log.warn( "A proper mapper could not be generated for the class %s, no relations will be created" % model_name) s = "" s += "class " + model_name + '(DeclarativeBase):\n' if is_many_to_many_table: s += " __table__ = %s\n\n" % table_name else: s += " __tablename__ = '%s'\n\n" % table_name if hasattr(cls, '__table_args__'): #if cls.__table_args__[0]: #for fkc in cls.__table_args__[0]: # fkc.__class__.__repr__ = foreignkeyconstraint_repr # break s += " __table_args__ = %s\n\n" % cls.__table_args__ s += " #column definitions\n" for column in sorted(cls.__table__.c, by_name): s += " %s = %s\n" % (column.name, column_repr(column)) s += "\n #relation definitions\n" ess = s # this is only required in SA 0.5 if mapper and RelationProperty: for prop in mapper.iterate_properties: if isinstance(prop, RelationshipProperty): s += ' %s\n' % cls._relation_repr(prop) return s except Exception, e: log.error("Could not generate class for: %s" % cls.__name__) from traceback import format_exc log.error(format_exc()) return '' #hack the class to have the right classname Temporal.__name__ = model_name #set up some blank table args Temporal.__table_args__ = {} #add in the schema if self.config.schema: Temporal.__table_args__[1]['schema'] = table.schema #trick sa's model registry to think the model is the correct name if model_name != 'Temporal': Temporal._decl_class_registry[ model_name] = Temporal._decl_class_registry['Temporal'] del Temporal._decl_class_registry['Temporal'] #add in single relations fks = self.get_single_foreign_keys_by_column(table) for column, fk in fks.iteritems(): related_table = fk.column.table if related_table not in self.tables: continue log.info(' Adding <primary> foreign key for:%s' % related_table.name) backref_name = plural(table_name) rel = relation( singular(name2label(related_table.name, related_table.schema)), primaryjoin=column == fk.column) #, backref=backref_name) setattr(Temporal, related_table.name, _deferred_relationship(Temporal, rel)) #add in the relations for the composites for constraint in table.constraints: if isinstance(constraint, ForeignKeyConstraint): if len(constraint.elements) > 1: related_table = constraint.elements[0].column.table related_classname = singular( name2label(related_table.name, related_table.schema)) primary_join = "and_(%s)" % ', '.join([ "%s.%s==%s.%s" % (model_name, k.parent.name, related_classname, k.column.name) for k in constraint.elements ]) rel = relation( related_classname, primaryjoin=primary_join # foreign_keys=[k.parent for k in constraint.elements] ) rel._as_string = primary_join setattr(Temporal, related_table.name, rel) # _deferred_relationship(Temporal, rel)) #add in many-to-many relations for join_table in self.get_related_many_to_many_tables(table.name): if join_table not in self.tables: continue primary_column = [ c for c in join_table.columns if c.foreign_keys and list(c.foreign_keys)[0].column.table == table ][0] for column in join_table.columns: if column.foreign_keys: key = list(column.foreign_keys)[0] if key.column.table is not table: related_column = related_table = list( column.foreign_keys)[0].column related_table = related_column.table if related_table not in self.tables: continue log.info( ' Adding <secondary> foreign key(%s) for:%s' % (key, related_table.name)) setattr( Temporal, plural(related_table.name), _deferred_relationship( Temporal, relation( singular( name2label(related_table.name, related_table.schema)), secondary=join_table, primaryjoin=list( primary_column.foreign_keys)[0].column == primary_column, secondaryjoin=column == related_column))) break return Temporal
def create_model(self, table): # partially borrowed from Jorge Vargas' code # http://dpaste.org/V6YS/ log.debug("Creating Model from table: %s" % table.name) model_name = self.find_new_name(singular(name2label(table.name)), self.used_model_names) self.used_model_names.append(model_name) is_many_to_many_table = self.is_many_to_many_table(table) table_name = self.find_new_name(table.name, self.used_table_names) self.used_table_names.append(table_name) mtl = self.model_table_lookup class Temporal(self.DeclarativeBase): __table__ = table @classmethod def _relation_repr(cls, rel): target = rel.argument if target and inspect.isfunction(target): target = target() if isinstance(target, Mapper): target = target.class_ target = target.__name__ primaryjoin = "" lookup = mtl() if rel.primaryjoin is not None: right_lookup = lookup.get( rel.primaryjoin.right.table.name, "%s.c." % rel.primaryjoin.right.table.name ) left_lookup = lookup.get(rel.primaryjoin.left.table.name, "%s.c." % rel.primaryjoin.left.table.name) primaryjoin = ", primaryjoin='%s.%s==%s.%s'" % ( left_lookup, rel.primaryjoin.left.name, right_lookup, rel.primaryjoin.right.name, ) secondary = "" secondaryjoin = "" if rel.secondary is not None: secondary = ", secondary=%s" % rel.secondary.name right_lookup = lookup.get( rel.secondaryjoin.right.table.name, "%s.c." % rel.secondaryjoin.right.table.name ) left_lookup = lookup.get( rel.secondaryjoin.left.table.name, "%s.c." % rel.secondaryjoin.left.table.name ) # import ipdb; ipdb.set_trace() secondaryjoin = ", secondaryjoin='%s.%s==%s.%s'" % ( left_lookup, rel.secondaryjoin.left.name, right_lookup, rel.secondaryjoin.right.name, ) backref = "" # if rel.backref: # backref=", backref='%s'"%rel.backref.key return "%s = relation('%s'%s%s%s%s)" % (rel.key, target, primaryjoin, secondary, secondaryjoin, backref) @classmethod def __repr__(cls): log.debug("repring class with name %s" % cls.__name__) try: mapper = class_mapper(cls) s = "" s += "class " + model_name + "(DeclarativeBase):\n" if is_many_to_many_table: s += " __table__ = %s\n\n" % table_name else: s += " __tablename__ = '%s'\n\n" % table_name if hasattr(cls, "__table_args__"): s += " __table_args__ = %s\n\n" % cls.__table_args__ s += " #column definitions\n" for column in sorted(cls.__table__.c, by_name): s += " %s = %s\n" % (column.name, column_repr(column)) s += "\n #relation definitions\n" ess = s # this is only required in SA 0.5 if RelationProperty: for prop in mapper.iterate_properties: if isinstance(prop, RelationshipProperty): s += " %s\n" % cls._relation_repr(prop) return s except Exception, e: log.error("Could not generate class for: %s" % cls.__name__) from traceback import format_exc log.error(format_exc()) return ""
if model_name != "Temporal": Temporal._decl_class_registry[model_name] = Temporal._decl_class_registry["Temporal"] del Temporal._decl_class_registry["Temporal"] # add in single relations fks = self.get_foreign_keys(table) for related_table in sorted(fks.keys(), by_name): columns = fks[related_table] if len(columns) > 1: continue column = columns[0] log.info(" Adding <primary> foreign key for:%s" % related_table.name) backref_name = plural(table_name) # import ipdb; ipdb.set_trace() rel = relation( singular(name2label(related_table.name, related_table.schema)), primaryjoin=column == list(column.foreign_keys)[0].column, ) # , backref=backref_name) setattr(Temporal, related_table.name, _deferred_relationship(Temporal, rel)) # add in many-to-many relations for join_table in self.get_related_many_to_many_tables(table.name): primary_column = [ c for c in join_table.columns if c.foreign_keys and list(c.foreign_keys)[0].column.table == table ][0] # import ipdb; ipdb.set_trace(); for column in join_table.columns: if column.foreign_keys: key = list(column.foreign_keys)[0]
def create_model(self, table): #partially borrowed from Jorge Vargas' code #http://dpaste.org/V6YS/ log.debug('Creating Model from table: %s'%table.name) model_name = self.find_new_name(singular(name2label(table.name)), self.used_model_names) self.used_model_names.append(model_name) is_many_to_many_table = self.is_many_to_many_table(table) table_name = self.find_new_name(table.name, self.used_table_names) self.used_table_names.append(table_name) mtl = self.model_table_lookup class Temporal(self.DeclarativeBase): __table__ = table @classmethod def _relation_repr(cls, rel): target = rel.argument if target and inspect.isfunction(target): target = target() if isinstance(target, Mapper): target = target.class_ target = target.__name__ primaryjoin='' lookup = mtl() if rel.primaryjoin is not None and hasattr(rel.primaryjoin, 'right'): right_lookup = lookup.get(rel.primaryjoin.right.table.name, '%s.c'%rel.primaryjoin.right.table.name) left_lookup = lookup.get(rel.primaryjoin.left.table.name, '%s.c'%rel.primaryjoin.left.table.name) primaryjoin = ", primaryjoin='%s.%s==%s.%s'"%(left_lookup, rel.primaryjoin.left.name, right_lookup, rel.primaryjoin.right.name) elif hasattr(rel, '_as_string'): primaryjoin=', primaryjoin="%s"'%rel._as_string secondary = '' secondaryjoin = '' if rel.secondary is not None: secondary = ", secondary=%s"%rel.secondary.name right_lookup = lookup.get(rel.secondaryjoin.right.table.name, '%s.c'%rel.secondaryjoin.right.table.name) left_lookup = lookup.get(rel.secondaryjoin.left.table.name, '%s.c'%rel.secondaryjoin.left.table.name) secondaryjoin = ", secondaryjoin='%s.%s==%s.%s'"%(left_lookup, rel.secondaryjoin.left.name, right_lookup, rel.secondaryjoin.right.name) backref='' # if rel.backref: # backref=", backref='%s'"%rel.backref.key return "%s = relation('%s'%s%s%s%s)"%(rel.key, target, primaryjoin, secondary, secondaryjoin, backref) @classmethod def __repr__(cls): log.debug('repring class with name %s'%cls.__name__) try: mapper = None try: mapper = class_mapper(cls) except exc.InvalidRequestError: log.warn("A proper mapper could not be generated for the class %s, no relations will be created"%model_name) s = "" s += "class "+model_name+'(DeclarativeBase):\n' if is_many_to_many_table: s += " __table__ = %s\n\n"%table_name else: s += " __tablename__ = '%s'\n\n"%table_name if hasattr(cls, '__table_args__'): #if cls.__table_args__[0]: #for fkc in cls.__table_args__[0]: # fkc.__class__.__repr__ = foreignkeyconstraint_repr # break s+=" __table_args__ = %s\n\n"%cls.__table_args__ s += " #column definitions\n" for column in sorted(cls.__table__.c, by_name): s += " %s = %s\n"%(column.name, column_repr(column)) s += "\n #relation definitions\n" ess = s # this is only required in SA 0.5 if mapper and RelationProperty: for prop in mapper.iterate_properties: if isinstance(prop, RelationshipProperty): s+=' %s\n'%cls._relation_repr(prop) return s except Exception as e: log.error("Could not generate class for: %s"%cls.__name__) from traceback import format_exc log.error(format_exc()) return '' #hack the class to have the right classname Temporal.__name__ = model_name #set up some blank table args Temporal.__table_args__ = {} #add in the schema #if self.config.schema: #Temporal.__table_args__[1]['schema'] = table.schema #trick sa's model registry to think the model is the correct name if model_name != 'Temporal': Temporal._decl_class_registry[model_name] = Temporal._decl_class_registry['Temporal'] del Temporal._decl_class_registry['Temporal'] #add in single relations fks = self.get_single_foreign_keys_by_column(table) for column, fk in fks.iteritems(): related_table = fk.column.table if related_table not in self.tables: continue log.info(' Adding <primary> foreign key for:%s'%related_table.name) backref_name = plural(table_name) rel = relation(singular(name2label(related_table.name, related_table.schema)), primaryjoin=column==fk.column)#, backref=backref_name) setattr(Temporal, related_table.name, _deferred_relationship(Temporal, rel)) #add in the relations for the composites for constraint in table.constraints: if isinstance(constraint, ForeignKeyConstraint): if len(constraint.elements) >1: related_table = constraint.elements[0].column.table related_classname = singular(name2label(related_table.name, related_table.schema)) primary_join = "and_(%s)"%', '.join(["%s.%s==%s.%s"%(model_name, k.parent.name, related_classname, k.column.name) for k in constraint.elements]) rel = relation(related_classname, primaryjoin=primary_join # foreign_keys=[k.parent for k in constraint.elements] ) rel._as_string = primary_join setattr(Temporal, related_table.name, rel) # _deferred_relationship(Temporal, rel)) #add in many-to-many relations for join_table in self.get_related_many_to_many_tables(table.name): if join_table not in self.tables: continue primary_column = [c for c in join_table.columns if c.foreign_keys and list(c.foreign_keys)[0].column.table==table][0] for column in join_table.columns: if column.foreign_keys: key = list(column.foreign_keys)[0] if key.column.table is not table: related_column = related_table = list(column.foreign_keys)[0].column related_table = related_column.table if related_table not in self.tables: continue log.info(' Adding <secondary> foreign key(%s) for:%s'%(key, related_table.name)) setattr(Temporal, plural(related_table.name), _deferred_relationship(Temporal, relation(singular(name2label(related_table.name, related_table.schema)), secondary=join_table, primaryjoin=list(primary_column.foreign_keys)[0].column==primary_column, secondaryjoin=column==related_column ))) break; return Temporal
def create_model(self, table): #partially borrowed from Jorge Vargas' code #http://dpaste.org/V6YS/ log.debug('Creating Model from table: %s'%table.name) model_name = self.find_new_name(singular(name2label(table.name)), self.used_model_names) self.used_model_names.append(model_name) is_many_to_many_table = self.is_many_to_many_table(table) table_name = self.find_new_name(table.name, self.used_table_names) self.used_table_names.append(table_name) mtl = self.model_table_lookup class Temporal(self.DeclarativeBase): __table__ = table @classmethod def _relation_repr(cls, rel): target = rel.argument if target and inspect.isfunction(target): target = target() if isinstance(target, Mapper): target = target.class_ target = target.__name__ primaryjoin='' lookup = mtl() if rel.primaryjoin is not None and hasattr(rel.primaryjoin, 'right'): right_lookup = lookup.get(rel.primaryjoin.right.table.name, '%s.c'%rel.primaryjoin.right.table.name) left_lookup = lookup.get(rel.primaryjoin.left.table.name, '%s.c'%rel.primaryjoin.left.table.name) primaryjoin = ", primaryjoin='%s.%s==%s.%s'"%(left_lookup, rel.primaryjoin.left.name, right_lookup, rel.primaryjoin.right.name) elif hasattr(rel, '_as_string'): primaryjoin=', primaryjoin="%s"'%rel._as_string secondary = '' secondaryjoin = '' if rel.secondary is not None: secondary = ", secondary=%s"%rel.secondary.name right_lookup = lookup.get(rel.secondaryjoin.right.table.name, '%s.c'%rel.secondaryjoin.right.table.name) left_lookup = lookup.get(rel.secondaryjoin.left.table.name, '%s.c'%rel.secondaryjoin.left.table.name) secondaryjoin = ", secondaryjoin='%s.%s==%s.%s'"%(left_lookup, rel.secondaryjoin.left.name, right_lookup, rel.secondaryjoin.right.name) backref='' # if rel.backref: # backref=", backref='%s'"%rel.backref.key return "%s = relation('%s'%s%s%s%s)"%(rel.key, target, primaryjoin, secondary, secondaryjoin, backref) @classmethod def __repr__(cls): log.debug('repring class with name %s'%cls.__name__) try: mapper = None try: mapper = class_mapper(cls) except exc.InvalidRequestError: log.warn("A proper mapper could not be generated for the class %s, no relations will be created"%model_name) s = "" s += "class "+model_name+'(DeclarativeBase):\n' if is_many_to_many_table: s += " __table__ = %s\n\n"%table_name else: s += " __tablename__ = '%s'\n\n"%table_name if hasattr(cls, '__table_args__'): #if cls.__table_args__[0]: #for fkc in cls.__table_args__[0]: # fkc.__class__.__repr__ = foreignkeyconstraint_repr # break s+=" __table_args__ = %s\n\n"%cls.__table_args__ s += " #column definitions\n" for column in sorted(cls.__table__.c, by_name): s += " %s = %s\n"%(column.name, column_repr(column)) s += "\n #relation definitions\n" ess = s # this is only required in SA 0.5 if mapper and RelationProperty: for prop in mapper.iterate_properties: if isinstance(prop, RelationshipProperty): s+=' %s\n'%cls._relation_repr(prop) return s except Exception, e: log.error("Could not generate class for: %s"%cls.__name__) from traceback import format_exc log.error(format_exc()) return ''
def create_model(self, table): # partially borrowed from Jorge Vargas' code # http://dpaste.org/V6YS/ log.debug('Creating Model from table: %s' % table.name) model_name = self.find_new_name(singular(name2label(table.name)), self.used_model_names) self.used_model_names.append(model_name) is_many_to_many_table = self.is_many_to_many_table(table) table_name = self.find_new_name(table.name, self.used_table_names) self.used_table_names.append(table_name) self.table_model_dict[table_name] = model_name # Kamil Edit mtl = self.model_table_lookup class Temporal(self.DeclarativeBase): __table__ = table @classmethod def _relation_repr(cls, rel): target = rel.argument if target and inspect.isfunction(target): target = target() if isinstance(target, Mapper): target = target.class_ target = target.__name__ primaryjoin = '' lookup = mtl() foo = rel.key if rel.primaryjoin is not None and hasattr( rel.primaryjoin, 'right'): right_lookup = lookup.get( rel.primaryjoin.right.table.name, '%s.c' % rel.primaryjoin.right.table.name) left_lookup = lookup.get( rel.primaryjoin.left.table.name, '%s.c' % rel.primaryjoin.left.table.name) primaryjoin = ", primaryjoin='%s.%s==%s.%s'" % ( left_lookup, rel.primaryjoin.left.name, right_lookup, rel.primaryjoin.right.name) elif hasattr(rel, '_as_string'): primaryjoin = ', primaryjoin="%s"' % rel._as_string secondary = '' secondaryjoin = '' if rel.secondary is not None: """ **HACK**: If there is a secondary relationship like between Venue, Event, and Event_Type, then I'm only going show a primary relationship. "Events = relationship('Event', primaryjoin='Venue.id==Event.venue_id')" and not "Event_Types = relation('EventType', primaryjoin='Venue.id==Event.venue_id', secondary=Event, secondaryjoin='Event.event_type_id==EventType.id')" """ if rel.secondary.name in self.table_model_dict: target = self.table_model_dict[rel.secondary.name] else: target = self.find_new_name( singular(name2label(rel.secondary.name)), []) # **HACK** secondary = '' secondaryjoin = '' foo = plural(rel.secondary.name) backref = '' # if rel.backref: # backref=", backref='%s'"%rel.backref.key return "%s = relationship('%s'%s%s%s%s)" % ( foo, target, primaryjoin, secondary, secondaryjoin, backref) @classmethod def __repr__(cls): log.debug('repring class with name %s' % cls.__name__) try: mapper = None try: mapper = class_mapper(cls) except exc.InvalidRequestError: log.warn( "A proper mapper could not be generated for the class %s, no relations will be created" % model_name) s = "" s += "class " + model_name + '(DeclarativeBase):\n' if is_many_to_many_table: s += " __table__ = %s\n\n" % table_name else: s += " __tablename__ = '%s'\n\n" % table_name if hasattr(cls, '__table_args__'): # if cls.__table_args__[0]: # for fkc in cls.__table_args__[0]: # fkc.__class__.__repr__ = foreignkeyconstraint_repr # break s += " __table_args__ = %s\n\n" % cls.__table_args__ s += " #column definitions\n" for column in sorted(cls.__table__.c, by_name): s += " %s = %s\n" % (column.name, column_repr(column)) s += "\n #relation definitions\n" # this is only required in SA 0.5 if mapper and RelationProperty: for prop in mapper.iterate_properties: if isinstance(prop, RelationshipProperty): s += ' %s\n' % cls._relation_repr(prop) return s except Exception: log.error("Could not generate class for: %s" % cls.__name__) from traceback import format_exc log.error(format_exc()) return '' # hack the class to have the right classname Temporal.__name__ = model_name # set up some blank table args Temporal.__table_args__ = {} # add in the schema if self.config.schema: Temporal.__table_args__[1]['schema'] = table.schema # trick sa's model registry to think the model is the correct name if model_name != 'Temporal': Temporal._decl_class_registry[ model_name] = Temporal._decl_class_registry['Temporal'] del Temporal._decl_class_registry['Temporal'] # add in single relations fks = self.get_single_foreign_keys_by_column(table) for column, fk in fks.iteritems(): related_table = fk.column.table if related_table not in self.tables: continue log.info(' Adding <primary> foreign key for:%s' % related_table.name) rel = relation( singular(name2label(related_table.name, related_table.schema)), primaryjoin=column == fk.column) # , backref=backref_name) setattr(Temporal, related_table.name, _deferred_relationship(Temporal, rel)) # add in the relations for the composites for constraint in table.constraints: if isinstance(constraint, ForeignKeyConstraint): if len(constraint.elements) > 1: related_table = constraint.elements[0].column.table related_classname = singular( name2label(related_table.name, related_table.schema)) primary_join = "and_(%s)" % ', '.join([ "%s.%s==%s.%s" % (model_name, k.parent.name, related_classname, k.column.name) for k in constraint.elements ]) rel = relation( related_classname, primaryjoin=primary_join # foreign_keys=[k.parent for k in constraint.elements] ) rel._as_string = primary_join setattr(Temporal, related_table.name, rel) # _deferred_relationship(Temporal, rel)) # add in many-to-many relations for join_table in self.get_related_many_to_many_tables(table.name): if join_table not in self.tables: continue primary_column = [ c for c in join_table.columns if c.foreign_keys and list(c.foreign_keys)[0].column.table == table ][0] for column in join_table.columns: if column.foreign_keys: key = list(column.foreign_keys)[0] if key.column.table is not table: related_column = related_table = list( column.foreign_keys)[0].column related_table = related_column.table if related_table not in self.tables: continue log.info( ' Adding <secondary> foreign key(%s) for:%s' % (key, related_table.name)) setattr( Temporal, plural(related_table.name), _deferred_relationship( Temporal, relation( singular( name2label(related_table.name, related_table.schema)), secondary=join_table, primaryjoin=list( primary_column.foreign_keys)[0].column == primary_column, secondaryjoin=column == related_column))) break return Temporal
class ModelFactory(object): def __init__(self, config): self.config = config self.used_model_names = [] self.used_table_names = [] schema = getattr(self.config, 'schema', None) self._metadata = MetaData(bind=config.engine) kw = {} self.schemas = None if schema: if isinstance(schema, (list, tuple)): self.schemas = schema else: self.schemas = (schema, ) for schema in self.schemas: log.info('Reflecting database... schema:%s' % schema) self._metadata.reflect(schema=schema) else: log.info('Reflecting database...') self._metadata.reflect() self.DeclarativeBase = declarative_base(metadata=self._metadata) def _table_repr(self, table): s = "Table(u'%s', metadata,\n" % (table.name) for column in table.c: s += " %s,\n" % column_repr(column) if table.schema: s += " schema='%s'\n" % table.schema s += ")" return s def __repr__(self): tables = self.get_many_to_many_tables() models = self.models s = StringIO() engine = self.config.engine if not isinstance(engine, basestring): engine = str(engine.url) s.write(constants.HEADER_DECL % engine) if 'postgres' in engine: s.write(constants.PG_IMPORT) self.used_table_names = [] self.used_model_names = [] for table in tables: table_name = self.find_new_name(table.name, self.used_table_names) self.used_table_names.append(table_name) s.write('%s = %s\n\n' % (table_name, self._table_repr(table))) for model in models: s.write(model.__repr__()) s.write("\n\n") if self.config.example or self.config.interactive: s.write(constants.EXAMPLE_DECL % (models[0].__name__, models[0].__name__)) if self.config.interactive: s.write(constants.INTERACTIVE % ([model.__name__ for model in models], models[0].__name__)) return s.getvalue() @property def tables(self): return self._metadata.tables.keys() @property def models(self): if hasattr(self, '_models'): return self._models self.used_model_names = [] self.used_table_names = [] self._models = sorted( (self.create_model(table) for table in self.get_non_many_to_many_tables()), by__name__) return self._models def model_table_lookup(self): if hasattr(self, '_model_table_lookup'): return self._model_table_lookup self._model_table_lookup = dict( ((m.__table__.name, m.__name__) for m in self.models)) return self._model_table_lookup def find_new_name(self, prefix, used, i=0): if i != 0: prefix = "%s%d" % (prefix, i) if prefix in used: prefix = prefix return self.find_new_name(prefix, used, i + 1) return prefix def create_model(self, table): #partially borrowed from Jorge Vargas' code #http://dpaste.org/V6YS/ log.debug('Creating Model from table: %s' % table.name) model_name = self.find_new_name(singular(name2label(table.name)), self.used_model_names) self.used_model_names.append(model_name) is_many_to_many_table = self.is_many_to_many_table(table) table_name = self.find_new_name(table.name, self.used_table_names) self.used_table_names.append(table_name) mtl = self.model_table_lookup class Temporal(self.DeclarativeBase): __table__ = table @classmethod def _relation_repr(cls, rel): target = rel.argument if target and inspect.isfunction(target): target = target() if isinstance(target, Mapper): target = target.class_ target = target.__name__ primaryjoin = '' lookup = mtl() if rel.primaryjoin is not None: right_lookup = lookup.get( rel.primaryjoin.right.table.name, '%s.c.' % rel.primaryjoin.right.table.name) left_lookup = lookup.get( rel.primaryjoin.left.table.name, '%s.c.' % rel.primaryjoin.left.table.name) primaryjoin = ", primaryjoin='%s.%s==%s.%s'" % ( left_lookup, rel.primaryjoin.left.name, right_lookup, rel.primaryjoin.right.name) secondary = '' secondaryjoin = '' if rel.secondary is not None: secondary = ", secondary=%s" % rel.secondary.name right_lookup = lookup.get( rel.secondaryjoin.right.table.name, '%s.c.' % rel.secondaryjoin.right.table.name) left_lookup = lookup.get( rel.secondaryjoin.left.table.name, '%s.c.' % rel.secondaryjoin.left.table.name) # import ipdb; ipdb.set_trace() secondaryjoin = ", secondaryjoin='%s.%s==%s.%s'" % ( left_lookup, rel.secondaryjoin.left.name, right_lookup, rel.secondaryjoin.right.name) backref = '' # if rel.backref: # backref=", backref='%s'"%rel.backref.key return "%s = relation('%s'%s%s%s%s)" % (rel.key, target, primaryjoin, secondary, secondaryjoin, backref) @classmethod def __repr__(cls): log.debug('repring class with name %s' % cls.__name__) try: mapper = class_mapper(cls) s = "" s += "class " + model_name + '(DeclarativeBase):\n' if is_many_to_many_table: s += " __table__ = %s\n\n" % table_name else: s += " __tablename__ = '%s'\n\n" % table_name if hasattr(cls, '__table_args__'): s += " __table_args__ = %s\n\n" % cls.__table_args__ s += " #column definitions\n" for column in sorted(cls.__table__.c, by_name): s += " %s = %s\n" % (column.name, column_repr(column)) s += "\n #relation definitions\n" ess = s # this is only required in SA 0.5 if RelationProperty: for prop in mapper.iterate_properties: if isinstance(prop, RelationshipProperty): s += ' %s\n' % cls._relation_repr(prop) return s except Exception, e: log.error("Could not generate class for: %s" % cls.__name__) from traceback import format_exc log.error(format_exc()) return '' #hack the class to have the right classname Temporal.__name__ = model_name #add in the schema if self.config.schema: Temporal.__table_args__ = {'schema': table.schema} #trick sa's model registry to think the model is the correct name if model_name != 'Temporal': Temporal._decl_class_registry[ model_name] = Temporal._decl_class_registry['Temporal'] del Temporal._decl_class_registry['Temporal'] #add in single relations fks = self.get_foreign_keys(table) for related_table in sorted(fks.keys(), by_name): columns = fks[related_table] if len(columns) > 1: continue column = columns[0] log.info(' Adding <primary> foreign key for:%s' % related_table.name) backref_name = plural(table_name) # import ipdb; ipdb.set_trace() rel = relation( singular(name2label(related_table.name, related_table.schema)), primaryjoin=column == column.foreign_keys[0].column) #, backref=backref_name) setattr(Temporal, related_table.name, _deferred_relationship(Temporal, rel)) #add in many-to-many relations for join_table in self.get_related_many_to_many_tables(table.name): primary_column = [ c for c in join_table.columns if c.foreign_keys and c.foreign_keys[0].column.table == table ][0] # import ipdb; ipdb.set_trace(); for column in join_table.columns: if column.foreign_keys: key = column.foreign_keys[0] if key.column.table is not table: related_column = related_table = column.foreign_keys[ 0].column related_table = related_column.table log.info( ' Adding <secondary> foreign key(%s) for:%s' % (key, related_table.name)) # import ipdb; ipdb.set_trace() setattr( Temporal, plural(related_table.name), _deferred_relationship( Temporal, relation( singular( name2label(related_table.name, related_table.schema)), secondary=join_table, primaryjoin=primary_column.foreign_keys[0]. column == primary_column, secondaryjoin=column == related_column))) break return Temporal