<s> """<STR_LIT>""" <EOL> from . models import Person <EOL> from django . db import models <EOL> from django . test import TestCase <EOL> from . models import Part , Car , SportsCar , Person <EOL> class ManyToManySignalsTest ( TestCase ) : <EOL> def m2m_changed_signal_receiver ( self , signal , sender , ** kwargs ) : <EOL> message = { <EOL> '<STR_LIT>' : kwargs [ '<STR_LIT>' ] , <EOL> '<STR_LIT:action>' : kwargs [ '<STR_LIT:action>' ] , <EOL> '<STR_LIT>' : kwargs [ '<STR_LIT>' ] , <EOL> '<STR_LIT>' : kwargs [ '<STR_LIT>' ] , <EOL> } <EOL> if kwargs [ '<STR_LIT>' ] : <EOL> message [ '<STR_LIT>' ] = list ( <EOL> kwargs [ '<STR_LIT>' ] . objects . filter ( pk__in = kwargs [ '<STR_LIT>' ] ) <EOL> ) <EOL> self . m2m_changed_messages . append ( message ) <EOL> def setUp ( self ) : <EOL> self . m2m_changed_messages = [ ] <EOL> self . vw = Car . objects . create ( name = '<STR_LIT>' ) <EOL> self . bmw = Car . objects . create ( name = '<STR_LIT>' ) <EOL> self . toyota = Car . objects . create ( name = '<STR_LIT>' ) <EOL> self . wheelset = Part . objects . create ( name = '<STR_LIT>' ) <EOL> self . doors = Part . objects . create ( name = '<STR_LIT>' ) <EOL> self . engine = Part . objects . create ( name = '<STR_LIT>' ) <EOL> self . airbag = Part . objects . create ( name = '<STR_LIT>' ) <EOL> self . sunroof = Part . objects . create ( name = '<STR_LIT>' ) <EOL> self . alice = Person . objects . create ( name = '<STR_LIT>' ) <EOL> self . bob = Person . objects . create ( name = '<STR_LIT>' ) <EOL> self . chuck = Person . objects . create ( name = '<STR_LIT>' ) <EOL> self . daisy = Person . objects . create ( name = '<STR_LIT>' ) <EOL> def tearDown ( self ) : <EOL> models . signals . m2m_changed . disconnect ( <EOL> self . m2m_changed_signal_receiver , Car . default_parts . through <EOL> ) <EOL> models . signals . m2m_changed . disconnect ( <EOL> self . m2m_changed_signal_receiver , Car . optional_parts . through <EOL> ) <EOL> models . signals . m2m_changed . disconnect ( <EOL> self . m2m_changed_signal_receiver , Person . fans . through <EOL> ) <EOL> models . signals . m2m_changed . disconnect ( <EOL> self . m2m_changed_signal_receiver , Person . friends . through <EOL> ) <EOL> def test_m2m_relations_add_remove_clear ( self ) : <EOL> expected_messages = [ ] <EOL> models . signals . m2m_changed . connect ( <EOL> self . m2m_changed_signal_receiver , Car . optional_parts . through <EOL> ) <EOL> self . vw . default_parts . add ( self . sunroof ) <EOL> models . signals . m2m_changed . connect ( <EOL> self . m2m_changed_signal_receiver , Car . default_parts . through <EOL> ) <EOL> self . vw . default_parts . add ( self . wheelset , self . doors , self . engine ) <EOL> expected_messages . append ( { <EOL> '<STR_LIT>' : self . vw , <EOL> '<STR_LIT:action>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : False , <EOL> '<STR_LIT>' : Part , <EOL> '<STR_LIT>' : [ self . doors , self . engine , self . wheelset ] , <EOL> } ) <EOL> expected_messages . append ( { <EOL> '<STR_LIT>' : self . vw , <EOL> '<STR_LIT:action>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : False , <EOL> '<STR_LIT>' : Part , <EOL> '<STR_LIT>' : [ self . doors , self . engine , self . wheelset ] , <EOL> } ) <EOL> self . assertEqual ( self . m2m_changed_messages , expected_messages ) <EOL> self . doors . car_set . add ( self . bmw , self . toyota ) <EOL> expected_messages . append ( { <EOL> '<STR_LIT>' : self . doors , <EOL> '<STR_LIT:action>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : True , <EOL> '<STR_LIT>' : Car , <EOL> '<STR_LIT>' : [ self . bmw , self . toyota ] , <EOL> } ) <EOL> expected_messages . append ( { <EOL> '<STR_LIT>' : self . doors , <EOL> '<STR_LIT:action>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : True , <EOL> '<STR_LIT>' : Car , <EOL> '<STR_LIT>' : [ self . bmw , self . toyota ] , <EOL> } ) <EOL> self . assertEqual ( self . m2m_changed_messages , expected_messages ) <EOL> self . vw . default_parts . remove ( self . engine , self . airbag ) <EOL> expected_messages . append ( { <EOL> '<STR_LIT>' : self . vw , <EOL> '<STR_LIT:action>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : False , <EOL> '<STR_LIT>' : Part , <EOL> '<STR_LIT>' : [ self . airbag , self . engine ] , <EOL> } ) <EOL> expected_messages . append ( { <EOL> '<STR_LIT>' : self . vw , <EOL> '<STR_LIT:action>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : False , <EOL> '<STR_LIT>' : Part , <EOL> '<STR_LIT>' : [ self . airbag , self . engine ] , <EOL> } ) <EOL> self . assertEqual ( self . m2m_changed_messages , expected_messages ) <EOL> self . vw . optional_parts . add ( self . airbag , self . sunroof ) <EOL> expected_messages . append ( { <EOL> '<STR_LIT>' : self . vw , <EOL> '<STR_LIT:action>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : False , <EOL> '<STR_LIT>' : Part , <EOL> '<STR_LIT>' : [ self . airbag , self . sunroof ] , <EOL> } ) <EOL> expected_messages . append ( { <EOL> '<STR_LIT>' : self . vw , <EOL> '<STR_LIT:action>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : False , <EOL> '<STR_LIT>' : Part , <EOL> '<STR_LIT>' : [ self . airbag , self . sunroof ] , <EOL> } ) <EOL> self . assertEqual ( self . m2m_changed_messages , expected_messages ) <EOL> self . airbag . cars_optional . add ( self . vw , self . bmw , self . toyota ) <EOL> expected_messages . append ( { <EOL> '<STR_LIT>' : self . airbag , <EOL> '<STR_LIT:action>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : True , <EOL> '<STR_LIT>' : Car , <EOL> '<STR_LIT>' : [ self . bmw , self . toyota ] , <EOL> } ) <EOL> expected_messages . append ( { <EOL> '<STR_LIT>' : self . airbag , <EOL> '<STR_LIT:action>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : True , <EOL> '<STR_LIT>' : Car , <EOL> '<STR_LIT>' : [ self . bmw , self . toyota ] , <EOL> } ) <EOL> self . assertEqual ( self . m2m_changed_messages , expected_messages ) <EOL> self . airbag . cars_optional . remove ( self . vw ) <EOL> expected_messages . append ( { <EOL> '<STR_LIT>' : self . airbag , <EOL> '<STR_LIT:action>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : True , <EOL> '<STR_LIT>' : Car , <EOL> '<STR_LIT>' : [ self . vw ] , <EOL> } ) <EOL> expected_messages . append ( { <EOL> '<STR_LIT>' : self . airbag , <EOL> '<STR_LIT:action>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : True , <EOL> '<STR_LIT>' : Car , <EOL> '<STR_LIT>' : [ self . vw ] , <EOL> } ) <EOL> self . assertEqual ( self . m2m_changed_messages , expected_messages ) <EOL> self . vw . default_parts . clear ( ) <EOL> expected_messages . append ( { <EOL> '<STR_LIT>' : self . vw , <EOL> '<STR_LIT:action>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : False , <EOL> '<STR_LIT>' : Part , <EOL> } ) <EOL> expected_messages . append ( { <EOL> '<STR_LIT>' : self . vw , <EOL> '<STR_LIT:action>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : False , <EOL> '<STR_LIT>' : Part , <EOL> } ) <EOL> self . assertEqual ( self . m2m_changed_messages , expected_messages ) <EOL> self . doors . car_set . clear ( ) <EOL> expected_messages . append ( { <EOL> '<STR_LIT>' : self . doors , <EOL> '<STR_LIT:action>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : True , <EOL> '<STR_LIT>' : Car , <EOL> } ) <EOL> expected_messages . append ( { <EOL> '<STR_LIT>' : self . doors , <EOL> '<STR_LIT:action>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : True , <EOL> '<STR_LIT>' : Car , <EOL> } ) <EOL> self . assertEqual ( self . m2m_changed_messages , expected_messages ) <EOL> self . airbag . cars_optional . clear ( ) <EOL> expected_messages . append ( { <EOL> '<STR_LIT>' : self . airbag , <EOL> '<STR_LIT:action>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : True , <EOL> '<STR_LIT>' : Car , <EOL> } ) <EOL> expected_messages . append ( { <EOL> '<STR_LIT>' : self . airbag , <EOL> '<STR_LIT:action>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : True , <EOL> '<STR_LIT>' : Car , <EOL> } ) <EOL> self . assertEqual ( self . m2m_changed_messages , expected_messages ) <EOL> self . vw . default_parts . create ( name = '<STR_LIT>' ) <EOL> p6 = Part . objects . get ( name = '<STR_LIT>' ) <EOL> expected_messages . append ( { <EOL> '<STR_LIT>' : self . vw , <EOL> '<STR_LIT:action>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : False , <EOL> '<STR_LIT>' : Part , <EOL> '<STR_LIT>' : [ p6 ] , <EOL> } ) <EOL> expected_messages . append ( { <EOL> '<STR_LIT>' : self . vw , <EOL> '<STR_LIT:action>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : False , <EOL> '<STR_LIT>' : Part , <EOL> '<STR_LIT>' : [ p6 ] , <EOL> } ) <EOL> self . assertEqual ( self . m2m_changed_messages , expected_messages ) <EOL> self . vw . default_parts = [ self . wheelset , self . doors , self . engine ] <EOL> expected_messages . append ( { <EOL> '<STR_LIT>' : self . vw , <EOL> '<STR_LIT:action>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : False , <EOL> '<STR_LIT>' : Part , <EOL> } ) <EOL> expected_messages . append ( { <EOL> '<STR_LIT>' : self . vw , <EOL> '<STR_LIT:action>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : False , <EOL> '<STR_LIT>' : Part , <EOL> } ) <EOL> expected_messages . append ( { <EOL> '<STR_LIT>' : self . vw , <EOL> '<STR_LIT:action>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : False , <EOL> '<STR_LIT>' : Part , <EOL> '<STR_LIT>' : [ self . doors , self . engine , self . wheelset ] , <EOL> } ) <EOL> expected_messages . append ( { <EOL> '<STR_LIT>' : self . vw , <EOL> '<STR_LIT:action>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : False , <EOL> '<STR_LIT>' : Part , <EOL> '<STR_LIT>' : [ self . doors , self . engine , self . wheelset ] , <EOL> } ) <EOL> self . assertEqual ( self . m2m_changed_messages , expected_messages ) <EOL> c4 = SportsCar . objects . create ( name = '<STR_LIT>' , price = '<STR_LIT>' ) <EOL> c4b = Car . objects . get ( name = '<STR_LIT>' ) <EOL> c4 . default_parts = [ self . doors ] <EOL> expected_messages . append ( { <EOL> '<STR_LIT>' : c4 , <EOL> '<STR_LIT:action>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : False , <EOL> '<STR_LIT>' : Part , <EOL> } ) <EOL> expected_messages . append ( { <EOL> '<STR_LIT>' : c4 , <EOL> '<STR_LIT:action>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : False , <EOL> '<STR_LIT>' : Part , <EOL> } ) <EOL> expected_messages . append ( { <EOL> '<STR_LIT>' : c4 , <EOL> '<STR_LIT:action>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : False , <EOL> '<STR_LIT>' : Part , <EOL> '<STR_LIT>' : [ self . doors ] , <EOL> } ) <EOL> expected_messages . append ( { <EOL> '<STR_LIT>' : c4 , <EOL> '<STR_LIT:action>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : False , <EOL> '<STR_LIT>' : Part , <EOL> '<STR_LIT>' : [ self . doors ] , <EOL> } ) <EOL> self . assertEqual ( self . m2m_changed_messages , expected_messages ) <EOL> self . engine . car_set . add ( c4 ) <EOL> expected_messages . append ( { <EOL> '<STR_LIT>' : self . engine , <EOL> '<STR_LIT:action>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : True , <EOL> '<STR_LIT>' : Car , <EOL> '<STR_LIT>' : [ c4b ] , <EOL> } ) <EOL> expected_messages . append ( { <EOL> '<STR_LIT>' : self . engine , <EOL> '<STR_LIT:action>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : True , <EOL> '<STR_LIT>' : Car , <EOL> '<STR_LIT>' : [ c4b ] , <EOL> } ) <EOL> self . assertEqual ( self . m2m_changed_messages , expected_messages ) <EOL> def test_m2m_relations_with_self ( self ) : <EOL> expected_messages = [ ] <EOL> models . signals . m2m_changed . connect ( <EOL> self . m2m_changed_signal_receiver , Person . fans . through <EOL> ) <EOL> models . signals . m2m_changed . connect ( <EOL> self . m2m_changed_signal_receiver , Person . friends . through <EOL> ) <EOL> self . alice . friends = [ self . bob , self . chuck ] <EOL> expected_messages . append ( { <EOL> '<STR_LIT>' : self . alice , <EOL> '<STR_LIT:action>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : False , <EOL> '<STR_LIT>' : Person , <EOL> } ) <EOL> expected_messages . append ( { <EOL> '<STR_LIT>' : self . alice , <EOL> '<STR_LIT:action>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : False , <EOL> '<STR_LIT>' : Person , <EOL> } ) <EOL> expected_messages . append ( { <EOL> '<STR_LIT>' : self . alice , <EOL> '<STR_LIT:action>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : False , <EOL> '<STR_LIT>' : Person , <EOL> '<STR_LIT>' : [ self . bob , self . chuck ] , <EOL> } ) <EOL> expected_messages . append ( { <EOL> '<STR_LIT>' : self . alice , <EOL> '<STR_LIT:action>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : False , <EOL> '<STR_LIT>' : Person , <EOL> '<STR_LIT>' : [ self . bob , self . chuck ] , <EOL> } ) <EOL> self . assertEqual ( self . m2m_changed_messages , expected_messages ) <EOL> self . alice . fans = [ self . daisy ] <EOL> expected_messages . append ( { <EOL> '<STR_LIT>' : self . alice , <EOL> '<STR_LIT:action>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : False , <EOL> '<STR_LIT>' : Person , <EOL> } ) <EOL> expected_messages . append ( { <EOL> '<STR_LIT>' : self . alice , <EOL> '<STR_LIT:action>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : False , <EOL> '<STR_LIT>' : Person , <EOL> } ) <EOL> expected_messages . append ( { <EOL> '<STR_LIT>' : self . alice , <EOL> '<STR_LIT:action>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : False , <EOL> '<STR_LIT>' : Person , <EOL> '<STR_LIT>' : [ self . daisy ] , <EOL> } ) <EOL> expected_messages . append ( { <EOL> '<STR_LIT>' : self . alice , <EOL> '<STR_LIT:action>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : False , <EOL> '<STR_LIT>' : Person , <EOL> '<STR_LIT>' : [ self . daisy ] , <EOL> } ) <EOL> self . assertEqual ( self . m2m_changed_messages , expected_messages ) <EOL> self . chuck . idols = [ self . alice , self . bob ] <EOL> expected_messages . append ( { <EOL> '<STR_LIT>' : self . chuck , <EOL> '<STR_LIT:action>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : True , <EOL> '<STR_LIT>' : Person , <EOL> } ) <EOL> expected_messages . append ( { <EOL> '<STR_LIT>' : self . chuck , <EOL> '<STR_LIT:action>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : True , <EOL> '<STR_LIT>' : Person , <EOL> } ) <EOL> expected_messages . append ( { <EOL> '<STR_LIT>' : self . chuck , <EOL> '<STR_LIT:action>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : True , <EOL> '<STR_LIT>' : Person , <EOL> '<STR_LIT>' : [ self . alice , self . bob ] , <EOL> } ) <EOL> expected_messages . append ( { <EOL> '<STR_LIT>' : self . chuck , <EOL> '<STR_LIT:action>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : True , <EOL> '<STR_LIT>' : Person , <EOL> '<STR_LIT>' : [ self . alice , self . bob ] , <EOL> } ) <EOL> self . assertEqual ( self . m2m_changed_messages , expected_messages ) </s>
