Changeset 481

Show
Ignore:
Timestamp:
09/30/09 20:25:04 (4 years ago)
Author:
ged
Message:

- added test for migration after M2M column format change through local_colname
- tablename, remote_colname, local_colname, schema and table_kwargs can now be

defined on either side of a ManyToMany relationship and will propagate to
the other side if that other side doesn't specify anything for that argument.
Also added an assertion to catch the case where the same/mirror
argument is specified on both sides but with different values.

- refactored slightly the code for the table rename migration_aid so that it is

more readable.

Location:
elixir/trunk
Files:
2 modified

Legend:

Unmodified
Added
Removed
  • elixir/trunk/elixir/relationships.py

    r478 r481  
    906906               'secondaryjoin' not in self.kwargs: 
    907907                self._build_join_clauses() 
     908            assert self.inverse is None or self.inverse.table is None or \ 
     909                   self.inverse.table is self.table 
    908910            return 
    909911 
    910912        if self.inverse: 
    911             if self.inverse.table is not None: 
    912                 self.table = self.inverse.table 
    913                 self.primaryjoin_clauses = self.inverse.secondaryjoin_clauses 
    914                 self.secondaryjoin_clauses = self.inverse.primaryjoin_clauses 
     913            inverse = self.inverse 
     914            if inverse.table is not None: 
     915                self.table = inverse.table 
     916                self.primaryjoin_clauses = inverse.secondaryjoin_clauses 
     917                self.secondaryjoin_clauses = inverse.primaryjoin_clauses 
    915918                return 
     919 
     920            assert not inverse.user_tablename or not self.user_tablename or \ 
     921                   inverse.user_tablename == self.user_tablename 
     922            assert not inverse.remote_colname or not self.local_colname or \ 
     923                   inverse.remote_colname == self.local_colname 
     924            assert not inverse.local_colname or not self.remote_colname or \ 
     925                   inverse.local_colname == self.remote_colname 
     926            assert not inverse.schema or not self.schema or \ 
     927                   inverse.schema == self.schema 
     928            assert not inverse.table_kwargs or not self.table_kwargs or \ 
     929                   inverse.table_kwargs == self.table_kwargs 
     930 
     931            self.user_tablename = inverse.user_tablename or self.user_tablename 
     932            self.local_colname = inverse.remote_colname or self.local_colname 
     933            self.remote_colname = inverse.local_colname or self.remote_colname 
     934            self.schema = inverse.schema or self.schema 
     935            self.local_colname = inverse.remote_colname or self.local_colname 
    916936 
    917937        # compute table_kwargs 
     
    961981                #     table name twice)? 
    962982                tablename = "%s__%s" % (target_part, source_part) 
    963                 if options.MIGRATION_TO_07_AID and \ 
    964                    e1_desc.tablename >= e2_desc.tablename: 
    965                     oldname = "%s__%s" % (source_part, target_part) 
     983            else: 
     984                tablename = "%s__%s" % (source_part, target_part) 
     985 
     986            if options.MIGRATION_TO_07_AID: 
     987                oldname = (self.inverse and 
     988                           e1_desc.tablename < e2_desc.tablename) and \ 
     989                          "%s__%s" % (target_part, source_part) or \ 
     990                          "%s__%s" % (source_part, target_part) 
     991                if oldname != tablename: 
    966992                    warnings.warn( 
    967993                        "The generated table name for the '%s' relationship " 
     
    973999                        % (self.name, self.entity.__name__, oldname, 
    9741000                           tablename, oldname)) 
    975             else: 
    976                 tablename = "%s__%s" % (source_part, target_part) 
    9771001 
    9781002        if e1_desc.autoload: 
     
    10141038                fk_colnames = [] 
    10151039                fk_refcols = [] 
    1016  
    10171040                if colnames: 
    10181041                    assert len(colnames) == len(desc.primary_keys) 
     
    10971120        # In the case we have a self-reference, we need to build join clauses 
    10981121        if self.entity is self.target: 
    1099             #TODO: we should check if that information was defined on the 
    1100             #inverse relationship. We have two options: either we force the 
    1101             #definition on both sides, or we accept defining on one side only. 
    1102             #In the later case, we still need to make the check as to not 
    1103             #peusdo-randomly fail depending on initialization order. 
    11041122            if not self.local_colname and not self.remote_colname: 
    11051123                raise Exception( 
  • elixir/trunk/tests/test_m2m.py

    r478 r481  
    139139        assert 'inverse_id' in m2m_cols 
    140140 
    141     def test_upgrade(self): 
     141    def test_upgrade_rename_col(self): 
    142142        elixir.options.M2MCOL_NAMEFORMAT = elixir.options.OLD_M2MCOL_NAMEFORMAT 
    143143 
     
    212212        assert a2.is_linked_from == [a1] 
    213213 
     214    def test_upgrade_local_colname(self): 
     215        elixir.options.M2MCOL_NAMEFORMAT = elixir.options.OLD_M2MCOL_NAMEFORMAT 
     216 
     217        class A(Entity): 
     218            using_options(shortnames=True) 
     219            name = Field(String(20)) 
     220            links_to = ManyToMany('A') 
     221            is_linked_from = ManyToMany('A') 
     222            bs_ = ManyToMany('B') 
     223 
     224        class B(Entity): 
     225            using_options(shortnames=True) 
     226            name = Field(String(20)) 
     227            as_ = ManyToMany('A') 
     228 
     229        setup_all(True) 
     230 
     231        a = A(name='a1', links_to=[A(name='a2')]) 
     232 
     233        session.commit() 
     234        session.clear() 
     235 
     236        del A 
     237        del B 
     238 
     239        # do not drop the tables, that's the whole point! 
     240        cleanup_all() 
     241 
     242        # ... 
     243        elixir.options.M2MCOL_NAMEFORMAT = elixir.options.NEW_M2MCOL_NAMEFORMAT 
     244#        elixir.options.MIGRATION_TO_07_AID = True 
     245 
     246        class A(Entity): 
     247            using_options(shortnames=True) 
     248            name = Field(String(20)) 
     249            links_to = ManyToMany('A', local_colname='a_id1') 
     250            is_linked_from = ManyToMany('A', local_colname='a_id2') 
     251            bs_ = ManyToMany('B') 
     252 
     253        class B(Entity): 
     254            using_options(shortnames=True) 
     255            name = Field(String(20)) 
     256            as_ = ManyToMany('A') 
     257 
     258        setup_all() 
     259 
     260        a1 = A.get_by(name='a1') 
     261        assert len(a1.links_to) == 1 
     262        assert not a1.is_linked_from 
     263 
     264        a2 = a1.links_to[0] 
     265        assert a2.name == 'a2' 
     266        assert not a2.links_to 
     267        assert a2.is_linked_from == [a1] 
     268 
    214269    def test_manual_column_format(self): 
    215270        class A(Entity):