Changeset 267
- Timestamp:
- 11/14/07 10:57:14 (6 years ago)
- Location:
- elixir/trunk
- Files:
-
- 12 modified
-
elixir/__init__.py (modified) (3 diffs)
-
elixir/entity.py (modified) (7 diffs)
-
elixir/events.py (modified) (1 diff)
-
elixir/ext/associable.py (modified) (6 diffs)
-
elixir/ext/encrypted.py (modified) (2 diffs)
-
elixir/ext/versioned.py (modified) (2 diffs)
-
elixir/fields.py (modified) (1 diff)
-
elixir/options.py (modified) (1 diff)
-
elixir/properties.py (modified) (1 diff)
-
elixir/relationships.py (modified) (1 diff)
-
elixir/statements.py (modified) (3 diffs)
-
tests/test_inherit.py (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
elixir/trunk/elixir/__init__.py
r263 r267 3 3 4 4 A declarative layer on top of the `SQLAlchemy library 5 <http://www.sqlalchemy.org/>`_. It is a fairly thin wrapper, which provides 6 the ability to create simple Python classes that map directly to relational 5 <http://www.sqlalchemy.org/>`_. It is a fairly thin wrapper, which provides 6 the ability to create simple Python classes that map directly to relational 7 7 database tables (this pattern is often referred to as the Active Record design 8 pattern), providing many of the benefits of traditional databases 8 pattern), providing many of the benefits of traditional databases 9 9 without losing the convenience of Python objects. 10 10 11 Elixir is intended to replace the ActiveMapper SQLAlchemy extension, and the 11 Elixir is intended to replace the ActiveMapper SQLAlchemy extension, and the 12 12 TurboEntity project but does not intend to replace SQLAlchemy's core features, 13 and instead focuses on providing a simpler syntax for defining model objects 14 when you do not need the full expressiveness of SQLAlchemy's manual mapper 13 and instead focuses on providing a simpler syntax for defining model objects 14 when you do not need the full expressiveness of SQLAlchemy's manual mapper 15 15 definitions. 16 16 ''' … … 92 92 entities = list() 93 93 94 94 95 def create_all(*args, **kwargs): 95 96 '''Create the necessary tables for all declared entities''' 96 97 for md in metadatas: 97 98 md.create_all(*args, **kwargs) 99 98 100 99 101 def drop_all(*args, **kwargs): … … 118 120 create_all(*args, **kwargs) 119 121 122 120 123 def cleanup_all(drop_tables=False, *args, **kwargs): 121 124 '''Clear all mappers, clear the session, and clear all metadatas. -
elixir/trunk/elixir/entity.py
r265 r267 33 33 # Not on sqlalchemy version 0.4 34 34 ScopedSession = type(None) 35 35 36 36 37 def _do_mapping(session, cls, *args, **kwargs): 37 38 if session is None: … … 51 52 def __getattr__(s, key): 52 53 return getattr(session.registry().query(cls), key) 54 53 55 def __call__(s): 54 56 return session.registry().query(cls) … … 252 254 return 253 255 elif self.inheritance == 'concrete': 254 # copy all columns from parent table255 for col in self.parent._descriptor.columns:256 # copy all columns from parent table 257 for col in self.parent._descriptor.columns: 256 258 self.add_column(col.copy()) 257 #FIXME: copy constraints. But those are not as simple to copy258 #since the source column must be changed259 #FIXME: copy constraints. But those are not as simple to copy 260 #since the source column must be changed 259 261 260 262 if self.polymorphic and self.inheritance in ('single', 'multi') and \ … … 524 526 525 527 def columns(self): 526 #FIXME: this would be more correct but it breaks inheritance, so I'll use the527 # old test for now.528 #FIXME: this would be more correct but it breaks inheritance, so I'll 529 # use the old test for now. 528 530 # if self.entity.table: 529 531 if self.autoload: … … 567 569 return "<TriggerProxy (%s)>" % (self.class_.__name__) 568 570 571 569 572 class TriggerAttribute(object): 573 570 574 def __init__(self, attrname): 571 575 self.attrname = attrname … … 581 585 def _is_entity(class_): 582 586 return isinstance(class_, EntityMeta) 587 583 588 584 589 class EntityMeta(type): … … 733 738 method() 734 739 740 735 741 def cleanup_entities(entities): 736 742 """ -
elixir/trunk/elixir/events.py
r177 r267 7 7 'after_delete' 8 8 ] 9 9 10 10 11 def create_decorator(event_name): -
elixir/trunk/elixir/ext/associable.py
r263 r267 14 14 15 15 Polymorphic associations lower the amount of many-to-many tables by setting up 16 a table that allows relations to any other table in the database, and relates it17 to the associable table. In some implementations, this layout does not enforce 18 referential integrity with database foreign key constraints, this implementation 19 uses an additional many-to-many table with foreign key constraints to avoid 20 this problem.16 a table that allows relations to any other table in the database, and relates 17 it to the associable table. In some implementations, this layout does not 18 enforce referential integrity with database foreign key constraints, this 19 implementation uses an additional many-to-many table with foreign key 20 constraints to avoid this problem. 21 21 22 22 .. note: … … 116 116 __doc_all__ = ['associable'] 117 117 118 118 119 def associable(assoc_entity, plural_name=None, lazy=True): 119 120 ''' … … 130 131 131 132 class GenericAssoc(object): 133 132 134 def __init__(self, tablename): 133 135 self.type = tablename … … 136 138 class Associable(object): 137 139 """An associable Elixir Statement object""" 140 138 141 def __init__(self, entity, name=None, uselist=True, lazy=True): 139 142 self.entity = entity … … 152 155 153 156 if not hasattr(assoc_entity, '_assoc_table'): 154 association_table = sa.Table("%s" % able_name, assoc_entity._descriptor.metadata, 157 metadata = assoc_entity._descriptor.metadata 158 association_table = sa.Table("%s" % able_name, metadata, 155 159 sa.Column('id', sa.Integer, primary_key=True), 156 160 sa.Column('type', sa.String(40), nullable=False), 157 161 ) 158 159 association_to_table = sa.Table("%s_to_%s" % (able_name, interface_name), assoc_entity._descriptor.metadata, 160 sa.Column('assoc_id', sa.Integer, sa.ForeignKey(association_table.c.id, ondelete="CASCADE"), primary_key=True), 162 tablename = "%s_to_%s" % (able_name, interface_name) 163 association_to_table = sa.Table(tablename, metadata, 164 sa.Column('assoc_id', sa.Integer, 165 sa.ForeignKey(association_table.c.id, 166 ondelete="CASCADE"), 167 primary_key=True), 161 168 #FIXME: this assumes a single id col 162 sa.Column('%s_id' % interface_name, sa.Integer, sa.ForeignKey(assoc_entity.table.c.id, ondelete="RESTRICT"), primary_key=True), 169 sa.Column('%s_id' % interface_name, sa.Integer, 170 sa.ForeignKey(assoc_entity.table.c.id, 171 ondelete="RESTRICT"), 172 primary_key=True), 163 173 ) 164 174 … … 212 222 # add helper methods 213 223 def select_by(cls, **kwargs): 214 return cls.query.join([attr_name, 'targets']).filter_by(**kwargs).all() 224 return cls.query.join([attr_name, 'targets']) \ 225 .filter_by(**kwargs).all() 215 226 setattr(entity, 'select_by_%s' % self.name, classmethod(select_by)) 216 227 217 228 def select(cls, *args, **kwargs): 218 return cls.query.join([attr_name, 'targets']).filter(*args, **kwargs).all() 229 return cls.query.join([attr_name, 'targets']) \ 230 .filter(*args, **kwargs).all() 219 231 setattr(entity, 'select_%s' % self.name, classmethod(select)) 220 232 -
elixir/trunk/elixir/ext/encrypted.py
r264 r267 34 34 __doc_all__ = [] 35 35 36 36 37 # 37 38 # encryption and decryption functions … … 52 53 53 54 class ActsAsEncrypted(object): 55 54 56 def __init__(self, entity, for_fields=[], with_secret='abcdef'): 55 57 -
elixir/trunk/elixir/ext/versioned.py
r263 r267 90 90 91 91 def after_insert(self, mapper, connection, instance): 92 colvalues = dict([(key, getattr(instance, key)) for key in instance.c.keys()]) 92 colvalues = dict([(key, getattr(instance, key)) 93 for key in instance.c.keys()]) 93 94 instance.__class__.__history_table__.insert().execute(colvalues) 94 95 return EXT_PASS 95 96 96 97 def before_update(self, mapper, connection, instance): 97 colvalues = dict([(key, getattr(instance, key)) for key in instance.c.keys()]) 98 colvalues = dict([(key, getattr(instance, key)) 99 for key in instance.c.keys()]) 98 100 history = instance.__class__.__history_table__ 99 101 … … 237 239 return differences 238 240 239 entity.versions = property(get_versions)240 entity.get_as_of = get_as_of241 entity.revert_to = revert_to242 entity.revert = revert243 entity.compare_with = compare_with241 entity.versions = property(get_versions) 242 entity.get_as_of = get_as_of 243 entity.revert_to = revert_to 244 entity.revert = revert 245 entity.compare_with = compare_with 244 246 Version.compare_with = compare_with 245 247 -
elixir/trunk/elixir/fields.py
r243 r267 200 200 201 201 if self.synonym: 202 self.entity._descriptor.add_property(self.synonym, synonym(self.name)) 202 self.entity._descriptor.add_property(self.synonym, 203 synonym(self.name)) 203 204 204 205 -
elixir/trunk/elixir/options.py
r265 r267 181 181 ] 182 182 183 183 184 def using_options_handler(entity, *args, **kwargs): 184 185 for kwarg in kwargs: -
elixir/trunk/elixir/properties.py
r248 r267 114 114 entity._descriptor.builders.append(self) 115 115 116 # delete the original attribute so that it doesn't interfere with 117 # SQLAlchemy. 118 if hasattr(entity, name): 119 delattr(entity, name) 120 116 121 def __repr__(self): 117 122 return "Property(%s, %s)" % (self.name, self.entity) -
elixir/trunk/elixir/relationships.py
r265 r267 778 778 constraints.append( 779 779 ForeignKeyConstraint(fk_colnames, fk_refcols, 780 name=fk_name, onupdate=onupdate, ondelete=ondelete)) 780 name=fk_name, onupdate=onupdate, 781 ondelete=ondelete)) 781 782 782 783 args = columns + constraints -
elixir/trunk/elixir/statements.py
r224 r267 35 35 self.handler(entity, *args, **kwargs) 36 36 37 37 38 #TODO: move this to the super class (to be created here) of EntityMeta 38 39 def process_mutators(entity): … … 46 47 47 48 class Statement(ClassMutator): 49 48 50 def process(self, entity, *args, **kwargs): 49 51 builder = self.handler(entity, *args, **kwargs) … … 51 53 52 54 class PropertyStatement(ClassMutator): 55 53 56 def process(self, entity, name, *args, **kwargs): 54 57 prop = self.handler(*args, **kwargs) -
elixir/trunk/tests/test_inherit.py
r234 r267 65 65 }) 66 66 67 # this is related to SA ticket 866 68 # http://www.sqlalchemy.org/trac/ticket/866 69 # the problam was caused by the fact that the attribute-based syntax left 70 # the class-attributes in place after initialization (in Elixir 0.4). 71 def test_missing_value(self): 72 class A(Entity): 73 pass 74 75 class B(A): 76 name = Field(Unicode(30)) 77 other = Field(Unicode) 78 79 setup_all() 80 create_all() 81 82 b1 = B(name="b1") # no value for other 83 84 session.flush() 85 67 86 def test_polymorphic_singletable_inheritance(self): 68 87 do_tst('single', True, True, { … … 98 117 }) 99 118 119
