Changeset 321
- Timestamp:
- 04/22/08 13:33:34 (5 years ago)
- Location:
- elixir/trunk
- Files:
-
- 4 modified
-
elixir/entity.py (modified) (10 diffs)
-
elixir/options.py (modified) (1 diff)
-
elixir/relationships.py (modified) (3 diffs)
-
tests/test_inherit.py (modified) (7 diffs)
Legend:
- Unmodified
- Added
- Removed
-
elixir/trunk/elixir/entity.py
r318 r321 11 11 import sqlalchemy 12 12 from sqlalchemy import Table, Column, Integer, \ 13 desc, ForeignKey, and_ 13 desc, ForeignKey, and_, \ 14 ForeignKeyConstraint 14 15 from sqlalchemy.orm import Query, MapperExtension,\ 15 16 mapper, object_session, EXT_PASS … … 194 195 if self.parent: 195 196 if self.inheritance == 'multi': 196 # add columns with foreign keys to the parent's primary197 # Add columns with foreign keys to the parent's primary 197 198 # key columns 198 199 parent_desc = self.parent._descriptor … … 206 207 'key': pk_col.key} 207 208 208 # it seems like SA ForeignKey is not happy being given209 # It seems like SA ForeignKey is not happy being given 209 210 # a real column object when said column is not yet 210 211 # attached to a table … … 214 215 primary_key=True) 215 216 self.add_column(col) 217 elif self.inheritance == 'concrete': 218 # Copy primary key columns from the parent. 219 for col in self.parent._descriptor.columns: 220 if col.primary_key: 221 self.add_column(col.copy()) 216 222 elif not self.has_pk and self.auto_primarykey: 217 223 if isinstance(self.auto_primarykey, basestring): … … 219 225 else: 220 226 colname = options.DEFAULT_AUTO_PRIMARYKEY_NAME 221 227 222 228 self.add_column( 223 229 Column(colname, options.DEFAULT_AUTO_PRIMARYKEY_TYPE, … … 259 265 # parent is a base entity (whatever the inheritance type -> elif 260 266 # will need to be changed) 261 # copy all columns from parent table 267 268 # Copy all non-primary key columns from parent table (primary 269 # key columns have already been copied earlier). 262 270 for col in self.parent._descriptor.columns: 263 self.add_column(col.copy()) 264 #FIXME: copy constraints. But those are not as simple to copy 265 #since the source column must be changed 271 if not col.primary_key: 272 self.add_column(col.copy()) 273 274 #FIXME: use the public equivalent of _get_colspec when available 275 for con in self.parent._descriptor.constraints: 276 self.add_constraint( 277 ForeignKeyConstraint( 278 [c.key for c in con.columns], 279 [e._get_colspec() for e in con.elements], 280 name=con.name, #TODO: modify it 281 onupdate=con.onupdate, ondelete=con.ondelete, 282 use_alter=con.use_alter)) 266 283 267 284 if self.polymorphic and self.inheritance in ('single', 'multi') and \ … … 455 472 # Autosetup triggers shouldn't be active anymore at this point, so we 456 473 # can theoretically access the entity's table safely. But the problem 457 # is that if, for some reason, the "trigger"removal phase didn't474 # is that if, for some reason, the trigger removal phase didn't 458 475 # happen, we'll get an infinite loop. So we just make sure we don't 459 476 # get one in any case. … … 477 494 (name, self.entity.__name__)) 478 495 self.properties[name] = property 496 479 497 mapper = self.entity.mapper 480 498 if mapper: … … 548 566 549 567 def primary_keys(self): 568 """ 569 Returns the list of primary key columns of the entity. 570 571 This property isn't valid before the "create_pk_cols" phase. 572 """ 550 573 if self.autoload: 551 574 return [col for col in self.entity.table.primary_key.columns] … … 559 582 560 583 class TriggerProxy(object): 561 """A class that serves as a "trigger" ; accessing its attributes runs 584 """ 585 A class that serves as a "trigger" ; accessing its attributes runs 562 586 the setup_all function. 563 587 -
elixir/trunk/elixir/options.py
r299 r321 28 28 +=====================+=======================================================+ 29 29 | ``inheritance`` | Specify the type of inheritance this entity must use. | 30 | | It can be one of ``single`` or ``multi``. Defaults to | 31 | | ``single``. Concrete inheritance is currently not in | 32 | | a usable state. | 30 | | It can be one of ``single``, ``concrete`` or | 31 | | ``multi``. Defaults to ``single``. | 32 | | Note that polymorphic concrete inheritance is | 33 | | currently not implemented. | 33 34 +---------------------+-------------------------------------------------------+ 34 35 | ``polymorphic`` | Whether the inheritance should be polymorphic or not. | -
elixir/trunk/elixir/relationships.py
r319 r321 554 554 self.target.__name__)) 555 555 556 for key_num, pk_col in enumerate(target_desc.primary_keys): 556 pks = target_desc.primary_keys 557 if not pks: 558 raise Exception("No primary key found in target table ('%s') " 559 "for the '%s' relationship of the '%s' entity." 560 % (self.target.tablename, self.name, 561 self.entity.__name__)) 562 563 for key_num, pk_col in enumerate(pks): 557 564 if self.colname: 558 565 colname = self.colname[key_num] … … 562 569 'key': pk_col.key} 563 570 564 # we can't add the column to the table directly as the table571 # We can't add the column to the table directly as the table 565 572 # might not be created yet. 566 573 col = Column(colname, pk_col.type, **self.column_kwargs) 567 574 source_desc.add_column(col) 568 575 569 # build the list of local columns which will be part of576 # Build the list of local columns which will be part of 570 577 # the foreign key 571 578 self.foreign_key.append(col) 572 579 573 # store the names of those columns580 # Store the names of those columns 574 581 fk_colnames.append(col.key) 575 582 576 # build the list of column "paths" the foreign key will583 # Build the list of column "paths" the foreign key will 577 584 # point to 578 585 target_path = "%s.%s" % (target_desc.tablename, pk_col.key) … … 582 589 fk_refcols.append(target_path) 583 590 584 # build up the primary join. This is needed when you have591 # Build up the primary join. This is needed when you have 585 592 # several belongs_to relationships between two objects 586 593 self.primaryjoin_clauses.append(col == pk_col) -
elixir/trunk/tests/test_inherit.py
r318 r321 16 16 elixir.options_defaults['shortnames'] = False 17 17 18 def do_tst(inheritance, polymorphic, with_rel,expected_res):18 def do_tst(inheritance, polymorphic, expected_res): 19 19 class A(Entity): 20 using_options(inheritance=inheritance, polymorphic=polymorphic) 20 21 data1 = Field(String(20)) 21 using_options(inheritance=inheritance, polymorphic=polymorphic)22 22 23 23 class B(A): 24 using_options(inheritance=inheritance, polymorphic=polymorphic) 24 25 data2 = Field(String(20)) 25 if with_rel: 26 many_c = OneToMany('C', inverse='some_b') 27 using_options(inheritance=inheritance, polymorphic=polymorphic) 26 some_e = ManyToOne('E') 28 27 29 28 class C(B): 29 using_options(inheritance=inheritance, polymorphic=polymorphic) 30 30 data3 = Field(String(20)) 31 if with_rel:32 some_b = ManyToOne('B', inverse='many_c')33 using_options(inheritance=inheritance, polymorphic=polymorphic)34 31 35 32 class D(A): 33 using_options(inheritance=inheritance, polymorphic=polymorphic) 36 34 data4 = Field(String(20)) 37 using_options(inheritance=inheritance, polymorphic=polymorphic)38 35 39 36 class E(A): 40 37 using_options(inheritance=inheritance, polymorphic=polymorphic) 38 many_b = OneToMany('B') 41 39 42 40 setup_all(True) … … 148 146 149 147 def test_singletable_inheritance(self): 150 do_tst('single', False, True,{148 do_tst('single', False, { 151 149 'A': ('A', 'A', 'A', 'A', 'A'), 152 150 'B': ('B', 'B', 'B', 'B', 'B'), … … 157 155 158 156 def test_polymorphic_singletable_inheritance(self): 159 do_tst('single', True, True,{157 do_tst('single', True, { 160 158 'A': ('A', 'B', 'C', 'D', 'E'), 161 159 'B': ('B', 'C'), … … 166 164 167 165 def test_concrete_inheritance(self): 168 # concrete fails when there are relationships involved ! 169 do_tst('concrete', False, False, { 166 do_tst('concrete', False, { 170 167 'A': ('A',), 171 168 'B': ('B',), … … 176 173 177 174 def test_multitable_inheritance(self): 178 do_tst('multi', False, True,{175 do_tst('multi', False, { 179 176 'A': ('A', 'A', 'A', 'A', 'A'), 180 177 'B': ('B', 'B'), … … 185 182 186 183 def test_polymorphic_multitable_inheritance(self): 187 do_tst('multi', True, True,{184 do_tst('multi', True, { 188 185 'A': ('A', 'B', 'C', 'D', 'E'), 189 186 'B': ('B', 'C'), … … 193 190 }) 194 191 195
