Show
Ignore:
Timestamp:
09/29/09 14:14:37 (3 years ago)
Author:
ged
Message:

- changed the M2M column format again (only differ from the 0.6.x naming for

selfref M2M) and use the inverse relationship name to produce more sensible
column names.

- added a test simulating a migration from the old column format to the new

one.

- added lots of comments to explain what the different variables you can use in

the M2M format strings actually mean.

- changed the migration_aid_m2m_column_formatter so that the method can be

reused to migrate from any format to any format.

Files:
1 modified

Legend:

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

    r465 r475  
    870870        if options.MIGRATION_TO_07_AID: 
    871871            self.column_format = \ 
    872                 migration_aid_m2m_column_formatter(self.column_format) 
     872                migration_aid_m2m_column_formatter( 
     873                    lambda data: options.OLD_M2MCOL_NAMEFORMAT % data, 
     874                    self.column_format) 
    873875 
    874876        self.filter = filter 
     
    995997 
    996998            joins = (self.primaryjoin_clauses, self.secondaryjoin_clauses) 
    997             for num, desc, fk_name, rel, colnames in ( 
    998               (0, e1_desc, source_fk_name, self, self.local_colname), 
    999               (1, e2_desc, target_fk_name, self.inverse, self.remote_colname)): 
     999            for num, desc, fk_name, rel, inverse, colnames in ( 
     1000              (0, e1_desc, source_fk_name, self, self.inverse, self.local_colname), 
     1001              (1, e2_desc, target_fk_name, self.inverse, self, self.remote_colname)): 
    10001002 
    10011003                fk_colnames = [] 
     
    10051007                    assert len(colnames) == len(desc.primary_keys) 
    10061008                else: 
    1007                     #FIXME: desc is not the target desc. Do I need to fix to 
    1008                     # code or the doc? in fact the relname corresponds to the 
    1009                     # relationship going from the entity to the M2M, so the new 
    1010                     # naming scheme might not really make sense 
    1011                     data = {# relationship info 
     1009                    # The data generated here will be fed to the M2M column 
     1010                    # formatter to generate the name of the columns of the 
     1011                    # intermediate table for *one* side of the relationship, 
     1012                    # that is, from the intermediate table to the current 
     1013                    # entity, as stored in the "desc" variable. 
     1014                    data = {# A) relationships info 
     1015 
     1016                            # the name of the rel going *from* the entity 
     1017                            # we are currently generating a column pointing 
     1018                            # *to*. This is generally *not* what you want to 
     1019                            # use. eg in a "Post" and "Tag" example, with 
     1020                            # relationships named 'tags' and 'posts', when 
     1021                            # creating the columns from the intermediate 
     1022                            # table to the "Post" entity, 'relname' will 
     1023                            # contain 'tags'. 
    10121024                            'relname': rel and rel.name or 'inverse', 
     1025 
     1026                            # the name of the inverse relationship. In the 
     1027                            # above example, 'inversename' will contain 
     1028                            # 'posts'. 
     1029                            'inversename': inverse and inverse.name 
     1030                                                   or 'inverse', 
     1031                            # is A == B? 
    10131032                            'selfref': e1_desc is e2_desc, 
     1033                            # provided for backward compatibility, DO NOT USE! 
    10141034                            'num': num, 
     1035                            # provided for backward compatibility, DO NOT USE! 
    10151036                            'numifself': e1_desc is e2_desc and str(num + 1) 
    10161037                                                            or '', 
    1017                             # source (not target!) info 
    1018                             'source': desc.entity, 
     1038                            # B) target information (from the perspective of 
     1039                            #    the intermediate table) 
     1040                            'target': desc.entity, 
    10191041                            'entity': desc.entity.__name__.lower(), 
    1020                             'tablename': desc.tablename 
     1042                            'tablename': desc.tablename, 
     1043 
     1044                            # C) current (intermediate) table name 
     1045                            'current_table': tablename 
    10211046                           } 
    10221047                    colnames = [] 
     
    10451070                ondelete = rel and rel.ondelete 
    10461071 
     1072                #FIXME: fk_name is misleading 
    10471073                constraints.append( 
    10481074                    ForeignKeyConstraint(fk_colnames, fk_refcols, 
     
    11041130 
    11051131 
    1106 def alternate_m2m_column_formatter(data): 
    1107     if data['selfref']: 
    1108         return options.NEW_M2MCOL_NAMEFORMAT % data 
    1109     else: 
    1110         return options.OLD_M2MCOL_NAMEFORMAT % data 
    1111  
    1112  
    1113 def migration_aid_m2m_column_formatter(formatter): 
     1132def migration_aid_m2m_column_formatter(oldformatter, newformatter): 
    11141133    def debug_formatter(data): 
    1115         new_name = formatter(data) 
    1116         old_name = options.OLD_M2MCOL_NAMEFORMAT % data 
     1134        old_name = oldformatter(data) 
     1135        new_name = newformatter(data) 
    11171136        if new_name != old_name: 
    11181137            complete_data = data.copy() 
    11191138            complete_data.update(old_name=old_name, 
    11201139                                 new_name=new_name, 
    1121                                  dir=data['num'] is 0 and 'local' or 'remote') 
     1140                                 targetname=data['target'].__name__) 
    11221141            # Specifying a stacklevel is useless in this case as the name 
    11231142            # generation is triggered by setup_all(), not by the declaration 
    11241143            # of the offending relationship. 
    1125             #FIXME: entity is probably wrong here since it refers to the target 
    1126             #entity. 
    1127             warnings.warn("The generated column name for the '%(relname)s' " 
    1128                           "relationship on the '%(entity)s' entity changed " 
    1129                           "from '%(old_name)s' to '%(new_name)s'. " 
     1144            warnings.warn("The '%(old_name)s' column in the " 
     1145                          "'%(current_table)s' table, used as the " 
     1146                          "intermediate table for the '%(relname)s' " 
     1147                          "relationship on the '%(targetname)s' entity " 
     1148                          "was renamed to '%(new_name)s'." 
    11301149                          % complete_data) 
    11311150        return new_name