Changeset 327

Show
Ignore:
Timestamp:
05/08/08 16:05:42 (5 years ago)
Author:
ged
Message:

- Fixed inheritance with autoloaded entities: when using autoload, we

shouldn't try to add columns to the table (closes tickets #41 and #43).

- Fixed ColumnProperty to work with latest version of SQLAlchemy (O.4.5 and

later)

- Added AUTHORS list. If you are missing from this list, don't hesitate to

contact me.

- Merged test_autoload_nopk into test_autoload

Location:
elixir/trunk
Files:
1 added
1 removed
5 modified

Legend:

Unmodified
Added
Removed
  • elixir/trunk/CHANGES

    r325 r327  
    1717- Fixed ManyToOne relationships using 'key' kwarg in their column_kwargs 
    1818  (patch by Jason R. Coombs)  
     19- Fixed inheritance with autoloaded entities: when using autoload, we  
     20  shouldn't try to add columns to the table (closes tickets #41 and #43). 
     21- Fixed ColumnProperty to work with latest version of SQLAlchemy (O.4.5 and 
     22  later) 
     23 
     24Misc: 
     25- Added AUTHORS list. If you are missing from this list, don't hesitate to 
     26  contact me. 
    1927 
    20280.5.2 - 2008-03-28 
  • elixir/trunk/elixir/entity.py

    r324 r327  
    261261        if self.autoload != only_autoloaded: 
    262262            return 
    263          
    264         if self.parent: 
    265             if self.inheritance == 'single': 
    266                 # we know the parent is setup before the child 
    267                 self.entity.table = self.parent.table  
    268  
    269                 # re-add the entity columns to the parent entity so that they 
    270                 # are added to the parent's table (whether the parent's table 
    271                 # is already setup or not). 
    272                 for col in self.columns: 
    273                     self.parent._descriptor.add_column(col) 
    274                 for constraint in self.constraints: 
    275                     self.parent._descriptor.add_constraint(constraint) 
    276                 return 
    277             elif self.inheritance == 'concrete':  
    278                 #TODO: we should also copy columns from the parent table if the 
    279                 # parent is a base entity (whatever the inheritance type -> elif 
    280                 # will need to be changed) 
    281  
    282                 # Copy all non-primary key columns from parent table (primary  
    283                 # key columns have already been copied earlier). 
    284                 for col in self.parent._descriptor.columns: 
    285                     if not col.primary_key: 
    286                         self.add_column(col.copy()) 
    287  
    288                 #FIXME: use the public equivalent of _get_colspec when available  
    289                 for con in self.parent._descriptor.constraints: 
    290                     self.add_constraint( 
    291                         ForeignKeyConstraint( 
    292                             [c.key for c in con.columns], 
    293                             [e._get_colspec() for e in con.elements], 
    294                             name=con.name, #TODO: modify it 
    295                             onupdate=con.onupdate, ondelete=con.ondelete, 
    296                             use_alter=con.use_alter)) 
    297  
    298         if self.polymorphic and \ 
    299            self.inheritance in ('single', 'multi') and \ 
    300            self.children and not self.parent: 
    301             self.add_column(Column(self.polymorphic,  
    302                                    options.POLYMORPHIC_COL_TYPE)) 
    303  
    304         if self.version_id_col: 
    305             if not isinstance(self.version_id_col, basestring): 
    306                 self.version_id_col = options.DEFAULT_VERSION_ID_COL_NAME 
    307             self.add_column(Column(self.version_id_col, Integer)) 
    308  
    309         # create list of columns and constraints 
     263 
     264        kwargs = self.table_options 
    310265        if self.autoload: 
    311266            args = self.table_args 
     267            kwargs['autoload'] = True 
    312268        else: 
     269            if self.parent: 
     270                if self.inheritance == 'single': 
     271                    # we know the parent is setup before the child 
     272                    self.entity.table = self.parent.table  
     273 
     274                    # re-add the entity columns to the parent entity so that they 
     275                    # are added to the parent's table (whether the parent's table 
     276                    # is already setup or not). 
     277                    for col in self.columns: 
     278                        self.parent._descriptor.add_column(col) 
     279                    for constraint in self.constraints: 
     280                        self.parent._descriptor.add_constraint(constraint) 
     281                    return 
     282                elif self.inheritance == 'concrete':  
     283                    #TODO: we should also copy columns from the parent table  
     284                    # if the parent is a base (abstract?) entity (whatever the 
     285                    # inheritance type -> elif will need to be changed) 
     286 
     287                    # Copy all non-primary key columns from parent table  
     288                    # (primary key columns have already been copied earlier). 
     289                    for col in self.parent._descriptor.columns: 
     290                        if not col.primary_key: 
     291                            self.add_column(col.copy()) 
     292 
     293                    #FIXME: use the public equivalent of _get_colspec when  
     294                    #available  
     295                    for con in self.parent._descriptor.constraints: 
     296                        self.add_constraint( 
     297                            ForeignKeyConstraint( 
     298                                [c.key for c in con.columns], 
     299                                [e._get_colspec() for e in con.elements], 
     300                                name=con.name, #TODO: modify it 
     301                                onupdate=con.onupdate, ondelete=con.ondelete, 
     302                                use_alter=con.use_alter)) 
     303 
     304            if self.polymorphic and \ 
     305               self.inheritance in ('single', 'multi') and \ 
     306               self.children and not self.parent: 
     307                self.add_column(Column(self.polymorphic,  
     308                                       options.POLYMORPHIC_COL_TYPE)) 
     309 
     310            if self.version_id_col: 
     311                if not isinstance(self.version_id_col, basestring): 
     312                    self.version_id_col = options.DEFAULT_VERSION_ID_COL_NAME 
     313                self.add_column(Column(self.version_id_col, Integer)) 
     314 
    313315            args = self.columns + self.constraints + self.table_args 
    314316         
    315         # specify options 
    316         kwargs = self.table_options 
    317  
    318         if self.autoload: 
    319             kwargs['autoload'] = True 
    320  
    321317        self.entity.table = Table(self.tablename, self.metadata,  
    322318                                  *args, **kwargs) 
  • elixir/trunk/elixir/properties.py

    r303 r327  
    178178 
    179179    def evaluate_property(self, prop): 
    180         return column_property(prop.label(self.name)) 
     180        return column_property(prop.label(None)) 
    181181 
    182182 
  • elixir/trunk/tests/test_autoload.py

    r313 r327  
    55from sqlalchemy import Table, Column, ForeignKey, MetaData 
    66from elixir import * 
     7from elixir import options 
    78import elixir 
    89 
     10def setup_entity_raise(cls): 
     11    try: 
     12        setup_entities([cls]) 
     13    except Exception, e: 
     14        pass 
     15    else: 
     16        assert False, "Exception did not occur setting up %s" % cls.__name__ 
     17 
     18# ------ 
     19 
    920def setup(): 
    10     # First create the tables (it would be better to use an external db) 
     21    # First create the tables 
    1122    meta = MetaData('sqlite:///') 
    1223 
     
    3950    global Person, Animal, Category 
    4051 
    41     #TODO: split these into individual classes for each test. It's best to wait 
    42     # till we can define several classes in a method with reference between them 
    43     # without having to make them global. 
     52    #TODO: split these into individual classes for each test. 
    4453    class Person(Entity): 
    4554        father = ManyToOne('Person') 
     
    7382    elixir.options_defaults.update(dict(autoload=False, shortnames=False)) 
    7483 
    75 #----------- 
     84# ----------- 
    7685 
    7786class TestAutoload(object): 
     
    8392        session.clear() 
    8493     
    85     def test_autoload(self): 
     94    def test_simple(self): 
    8695        snowball = Animal(name="Snowball II") 
    8796        slh = Animal(name="Santa's Little Helper") 
     
    100109        assert homer == slh.owner 
    101110 
    102     def test_autoload_selfref(self): 
     111    def test_selfref(self): 
    103112        grampa = Person(name="Abe") 
    104113        homer = Person(name="Homer") 
     
    120129        assert p is Person.get_by(name="Lisa").father 
    121130 
    122     def test_autoload_m2m(self): 
     131    def test_m2m(self): 
    123132        stupid = Category(name="Stupid") 
    124133        simpson = Category(name="Simpson") 
     
    145154        assert c in grampa.categories 
    146155 
    147     def test_autoload_m2m_selfref(self): 
     156    def test_m2m_selfref(self): 
    148157        barney = Person(name="Barney") 
    149158        homer = Person(name="Homer", appreciate=[barney]) 
     
    158167        assert homer in barney.isappreciatedby 
    159168 
    160  
    161 def setup_entity_raise(cls): 
    162     try: 
    163         setup_entities([cls]) 
    164     except Exception, e: 
    165         pass 
    166     else: 
    167         assert False, "Exception did not occur setting up %s" % cls.__name__ 
    168  
    169 class TestAutoloadOverrideColumn(object): 
    170     def setup(self): 
    171         create_all() 
    172  
    173     def teardown(self): 
    174         drop_all() 
     169    # overrides tests 
    175170 
    176171    def test_override_pk_fails(self): 
     
    203198        assert isinstance(Animal.table.columns['name'].type, String) 
    204199 
    205  
     200    # ---------------- 
     201 
     202    def test_nopk(self): 
     203        metadata.bind = 'sqlite:///' 
     204 
     205        local_meta = MetaData(metadata.bind) 
     206 
     207        table = Table('a', local_meta, 
     208            Column('id', Integer), 
     209            Column('name', String(32))) 
     210         
     211        local_meta.create_all() 
     212 
     213        class A(Entity): 
     214            using_options(tablename='a', autoload=True) 
     215            using_mapper_options(primary_key=['id']) 
     216 
     217        setup_all() 
     218 
     219        a1 = A(id=1, name="a1") 
     220 
     221        session.flush() 
     222        session.clear() 
     223 
     224        res = A.query.all() 
     225 
     226        assert len(res) == 1 
     227        assert res[0].name == "a1" 
     228 
     229    def test_inheritance(self): 
     230        metadata.bind = 'sqlite:///' 
     231 
     232        local_meta = MetaData(metadata.bind) 
     233 
     234        table = Table('father', local_meta, 
     235            Column('id', Integer, primary_key=True), 
     236            Column('row_type', options.POLYMORPHIC_COL_TYPE)) 
     237 
     238        local_meta.create_all() 
     239 
     240        options_defaults["autoload"] = True 
     241 
     242        class Father(Entity): 
     243            using_options(tablename='father') 
     244 
     245        class Son(Father):  
     246            pass 
     247 
     248        setup_all() 
  • elixir/trunk/tests/test_properties.py

    r313 r327  
    7474  
    7575            score = ColumnProperty(lambda c:  
    76                                    select([func.sum(User.score)], 
     76                                   select([func.avg(User.score)], 
    7777                                          User.category_id == c.id 
    7878                                         ).as_scalar()) 
     
    9292 
    9393        category = Category.query.one() 
    94 #        assert category.score == 85 # doesn't work for now 
     94        assert category.score == 85 
    9595        for user in category.users: 
    9696            assert user.score == sum([tag.score for tag in user.tags])