def test_with_bad_app(self): """Testing DeleteModel with application not in signature""" mutation = DeleteModel('TestModel') message = ( 'Cannot delete the model "badapp.TestModel". The application ' 'could not be found in the signature.') with self.assertRaisesMessage(SimulationFailure, message): mutation.run_simulation(app_label='badapp', project_sig=ProjectSignature(), database_state=None)
def test_with_bad_app(self): """Testing DeleteModel with application not in signature""" mutation = DeleteModel('TestModel') message = ( 'Cannot delete the model "badapp.TestModel". The application ' 'could not be found in the signature.' ) with self.assertRaisesMessage(SimulationFailure, message): mutation.run_simulation(app_label='badapp', project_sig=ProjectSignature(), database_state=None)
def test_with_bad_model(self): """Testing DeleteModel with model not in signature""" mutation = DeleteModel('TestModel') project_sig = ProjectSignature() project_sig.add_app_sig(AppSignature(app_id='tests')) message = ( 'Cannot delete the model "tests.TestModel". The model could ' 'not be found in the signature.') with self.assertRaisesMessage(SimulationFailure, message): mutation.run_simulation(app_label='tests', project_sig=project_sig, database_state=None)
def test_delete_model_with_m2m_field(self): """Testing DeleteModel with a model containing a ManyToManyField""" class BasicWithM2MModel(BaseTestModel): value = models.IntegerField() m2m = models.ManyToManyField(DeleteModelAnchor) self.set_base_model( BasicWithM2MModel, name='BasicWithM2MModel', extra_models=[('DeleteModelAnchor', DeleteModelAnchor)]) end_sig = self.start_sig.clone() end = self.copy_models(self.start) end_sig.get_app_sig('tests').remove_model_sig('BasicWithM2MModel') end.pop('basicwithm2mmodel') self.perform_evolution_tests( None, [ DeleteModel('BasicWithM2MModel'), ], 'The model tests.BasicWithM2MModel has been deleted', [ "DeleteModel('BasicWithM2MModel')", ], 'BasicWithM2MModel', end_sig=end_sig, end=end)
def test_delete_model(self): """Testing DeleteModel""" class BasicModel(BaseTestModel): value = models.IntegerField() self.set_base_model(BasicModel, 'BasicModel') end_sig = self.start_sig.clone() end = self.copy_models(self.start) end_sig.get_app_sig('tests').remove_model_sig('BasicModel') end.pop('basicmodel') self.perform_evolution_tests( None, [ DeleteModel('BasicModel'), ], 'The model tests.BasicModel has been deleted', [ "DeleteModel('BasicModel')", ], 'BasicModel', end_sig=end_sig, end=end)
def test_delete_model_with_custom_table_and_m2m_field(self): """Testing DeleteModel with a model and custom table name and ManyToManyField """ class CustomTableWithM2MModel(BaseTestModel): value = models.IntegerField() m2m = models.ManyToManyField(DeleteModelAnchor) class Meta(BaseTestModel.Meta): db_table = 'another_custom_table_name' self.set_base_model( CustomTableWithM2MModel, name='CustomTableWithM2MModel', extra_models=[('DeleteModelAnchor', DeleteModelAnchor)]) end_sig = self.start_sig.clone() end = self.copy_models(self.start) end_sig.get_app_sig('tests').remove_model_sig( 'CustomTableWithM2MModel') end.pop('customtablewithm2mmodel') self.perform_evolution_tests( None, [ DeleteModel('CustomTableWithM2MModel'), ], 'The model tests.CustomTableWithM2MModel has been deleted', [ "DeleteModel('CustomTableWithM2MModel')", ], 'CustomTableWithM2MModel', end_sig=end_sig, end=end)
def test_delete_model_with_custom_table(self): """Testing DeleteModel with a model and custom table name""" class CustomTableModel(BaseTestModel): value = models.IntegerField() class Meta(BaseTestModel.Meta): db_table = 'custom_table_name' self.set_base_model(CustomTableModel, 'CustomTableModel') end_sig = self.start_sig.clone() end = self.copy_models(self.start) end_sig.get_app_sig('tests').remove_model_sig('CustomTableModel') end.pop('customtablemodel') self.perform_evolution_tests( None, [ DeleteModel('CustomTableModel'), ], 'The model tests.CustomTableModel has been deleted', [ "DeleteModel('CustomTableModel')", ], 'CustomTableModel', end_sig=end_sig, end=end)
def test_with_bad_model(self): """Testing DeleteModel with model not in signature""" mutation = DeleteModel('TestModel') project_sig = ProjectSignature() project_sig.add_app_sig(AppSignature(app_id='tests')) message = ( 'Cannot delete the model "tests.TestModel". The model could ' 'not be found in the signature.' ) with self.assertRaisesMessage(SimulationFailure, message): mutation.run_simulation(app_label='tests', project_sig=project_sig, database_state=None)
def evolution(self): "Generate an evolution that would neutralize the diff" mutations = {} for app_label, app_changes in self.changed.items(): for model_name, change in app_changes.get('changed', {}).items(): for field_name in change.get('added',{}): field_sig = self.current_sig[app_label][model_name]['fields'][field_name] add_params = [(key,field_sig[key]) for key in field_sig.keys() if key in ATTRIBUTE_DEFAULTS.keys()] add_params.append(('field_type', field_sig['field_type'])) if (field_sig['field_type'] != models.ManyToManyField and not field_sig.get('null', ATTRIBUTE_DEFAULTS['null'])): add_params.append( ('initial', get_initial_value(app_label, model_name, field_name))) if 'related_model' in field_sig: add_params.append(('related_model', '%s' % field_sig['related_model'])) mutations.setdefault(app_label,[]).append( AddField(model_name, field_name, **dict(add_params))) for field_name in change.get('deleted',[]): mutations.setdefault(app_label,[]).append( DeleteField(model_name, field_name)) for field_name,field_change in change.get('changed',{}).items(): changed_attrs = {} current_field_sig = self.current_sig[app_label][model_name]['fields'][field_name] for prop in field_change: if prop == 'related_model': changed_attrs[prop] = current_field_sig[prop] else: changed_attrs[prop] = \ current_field_sig.get(prop, ATTRIBUTE_DEFAULTS[prop]) if (changed_attrs.has_key('null') and current_field_sig['field_type'] != models.ManyToManyField and not current_field_sig.get('null', ATTRIBUTE_DEFAULTS['null'])): changed_attrs['initial'] = \ get_initial_value(app_label, model_name, field_name) mutations.setdefault(app_label,[]).append( ChangeField(model_name, field_name,current_field_sig, **changed_attrs)) #j----------add for model_name in app_changes.get('deleted',{}): mutations.setdefault(app_label,[]).append( DeleteModel(model_name)) return mutations
def test_rename_delete_model(self): """Testing pre-processing RenameModel + DeleteModel""" class DestModel(models.Model): my_id = models.AutoField(primary_key=True) char_field = models.CharField(max_length=20) class Meta: db_table = 'tests_testmodel' self.perform_evolution_tests( DestModel, [ RenameModel( 'TestModel', 'TempModel', db_table='tests_testmodel'), DeleteModel('TempModel'), ], "The model tests.TestModel has been deleted", [ "DeleteModel('TestModel')", ], 'rename_delete_model', model_name='DestModel')
def test_delete_model_with_custom_database(self): """Testing DeleteModel with custom database""" class BasicModel(models.Model): value = models.IntegerField() self.set_base_model(BasicModel, 'BasicModel', db_name='db_multi') end_sig = self.start_sig.clone() end = self.copy_models(self.start) end_sig.get_app_sig('tests').remove_model_sig('BasicModel') end.pop('basicmodel') self.perform_evolution_tests( None, [ DeleteModel('BasicModel'), ], 'The model tests.BasicModel has been deleted', [ "DeleteModel('BasicModel')", ], 'BasicModel', end_sig=end_sig, end=end, db_name='db_multi')
from __future__ import unicode_literals from django_evolution.mutations import DeleteModel MUTATIONS = [DeleteModel('Message')]
def evolution(self): """Return the mutations needed for resolving the diff. This will attempt to return a hinted evolution, consisting of a series of mutations for each affected application. These mutations will convert the database from the original to the target signatures. Returns: collections.OrderedDict: An ordered dictionary of mutations. Each key is an application label, and each value is a list of mutations for the application. """ if self._mutations is not None: return self._mutations mutations = OrderedDict() for app_label, app_changes in six.iteritems(self.changed): app_sig = self.target_project_sig.get_app_sig(app_label) model_changes = app_changes.get('changed', {}) app_mutations = [] for model_name, model_change in six.iteritems(model_changes): model_sig = app_sig.get_model_sig(model_name) # Process the list of added fields for the model. for field_name in model_change.get('added', {}): field_sig = model_sig.get_field_sig(field_name) field_type = field_sig.field_type add_params = field_sig.field_attrs.copy() add_params['field_type'] = field_type if (not issubclass(field_type, models.ManyToManyField) and not field_sig.get_attr_value('null')): # This field requires an initial value. Inject either # a suitable initial value or a placeholder that must # be filled in by the developer. add_params['initial'] = \ self._get_initial_value(app_label=app_label, model_name=model_name, field_name=field_name) if field_sig.related_model: add_params['related_model'] = field_sig.related_model app_mutations.append(AddField( model_name=model_name, field_name=field_name, **add_params)) # Process the list of deleted fields for the model. app_mutations += [ DeleteField(model_name=model_name, field_name=field_name) for field_name in model_change.get('deleted', []) ] # Process the list of changed fields for the model. field_changes = model_change.get('changed', {}) for field_name, field_change in six.iteritems(field_changes): field_sig = model_sig.get_field_sig(field_name) changed_attrs = OrderedDict() field_type_changed = 'field_type' in field_change if field_type_changed: # If the field type changes, we're doing a hard # reset on the attributes. We won't be showing the # difference between any other attributes on here. changed_attrs['field_type'] = field_sig.field_type changed_attrs.update(field_sig.field_attrs) else: changed_attrs.update( (attr, field_sig.get_attr_value(attr)) for attr in field_change ) if ('null' in field_change and not field_sig.get_attr_value('null') and not issubclass(field_sig.field_type, models.ManyToManyField)): # The field no longer allows null values, meaning an # initial value is required. Inject either a suitable # initial value or a placeholder that must be filled # in by the developer. changed_attrs['initial'] = \ self._get_initial_value(app_label=app_label, model_name=model_name, field_name=field_name) if 'related_model' in field_change: changed_attrs['related_model'] = \ field_sig.related_model app_mutations.append(ChangeField( model_name=model_name, field_name=field_name, **changed_attrs)) # Process the Meta attribute changes for the model. meta_changed = model_change.get('meta_changed', []) # Check if the Meta.constraints property has any changes. # They'll all be assembled into a single ChangeMeta. if 'constraints' in meta_changed: app_mutations.append(ChangeMeta( model_name=model_name, prop_name='constraints', new_value=[ dict({ 'type': constraint_sig.type, 'name': constraint_sig.name, }, **constraint_sig.attrs) for constraint_sig in model_sig.constraint_sigs ])) # Check if the Meta.indexes property has any changes. # They'll all be assembled into a single ChangeMeta. if 'indexes' in meta_changed: change_meta_indexes = [] for index_sig in model_sig.index_sigs: change_meta_index = index_sig.attrs.copy() if index_sig.expressions: change_meta_index['expressions'] = \ index_sig.expressions if index_sig.fields: change_meta_index['fields'] = index_sig.fields if index_sig.name: change_meta_index['name'] = index_sig.name change_meta_indexes.append(change_meta_index) app_mutations.append(ChangeMeta( model_name=model_name, prop_name='indexes', new_value=change_meta_indexes)) # Check Meta.index_together and Meta.unique_together. app_mutations += [ ChangeMeta(model_name=model_name, prop_name=prop_name, new_value=getattr(model_sig, prop_name) or []) for prop_name in ('index_together', 'unique_together') if prop_name in meta_changed ] # Process the list of deleted models for the application. app_mutations += [ DeleteModel(model_name=model_name) for model_name in app_changes.get('deleted', {}) ] # See if any important details about the app have changed. meta_changed = app_changes.get('meta_changed', {}) app_label_changed = meta_changed.get('app_id', {}) legacy_app_label_changed = meta_changed.get('legacy_app_label', {}) if app_label_changed or legacy_app_label_changed: app_mutations.append(RenameAppLabel( app_label_changed.get('old', app_sig.app_id), app_label_changed.get('new', app_sig.app_id), legacy_app_label=legacy_app_label_changed.get( 'new', app_sig.legacy_app_label))) if app_mutations: mutations[app_label] = app_mutations self._mutations = mutations return mutations
from __future__ import unicode_literals from django_evolution.mutations import DeleteModel MUTATIONS = [ DeleteModel('ReviewBotTool'), ]
def evolution(self): """Return the mutations needed for resolving the diff. This will attempt to return a hinted evolution, consisting of a series of mutations for each affected application. These mutations will convert the database from the original to the target signatures. Returns: collections.OrderedDict: An ordered dictionary of mutations. Each key is an application label, and each value is a list of mutations for the application. """ mutations = OrderedDict() for app_label, app_changes in six.iteritems(self.changed): app_sig = self.target_project_sig.get_app_sig(app_label) model_changes = app_changes.get('changed', {}) app_mutations = [] for model_name, model_change in six.iteritems(model_changes): model_sig = app_sig.get_model_sig(model_name) # Process the list of added fields for the model. for field_name in model_change.get('added', {}): field_sig = model_sig.get_field_sig(field_name) field_type = field_sig.field_type add_params = field_sig.field_attrs.copy() add_params['field_type'] = field_type if (not issubclass(field_type, models.ManyToManyField) and not field_sig.get_attr_value('null')): # This field requires an initial value. Inject either # a suitable initial value or a placeholder that must # be filled in by the developer. add_params['initial'] = \ self._get_initial_value(app_label=app_label, model_name=model_name, field_name=field_name) if field_sig.related_model: add_params['related_model'] = field_sig.related_model app_mutations.append( AddField(model_name=model_name, field_name=field_name, **add_params)) # Process the list of deleted fields for the model. app_mutations += [ DeleteField(model_name=model_name, field_name=field_name) for field_name in model_change.get('deleted', []) ] # Process the list of changed fields for the model. field_changes = model_change.get('changed', {}) for field_name, field_change in six.iteritems(field_changes): field_sig = model_sig.get_field_sig(field_name) changed_attrs = OrderedDict( (attr, field_sig.get_attr_value(attr)) for attr in field_change) if ('null' in changed_attrs and not field_sig.get_attr_value('null') and not issubclass(field_sig.field_type, models.ManyToManyField)): # The field no longer allows null values, meaning an # initial value is required. Inject either a suitable # initial value or a placeholder that must be filled # in by the developer. changed_attrs['initial'] = \ self._get_initial_value(app_label=app_label, model_name=model_name, field_name=field_name) if 'related_model' in field_change: changed_attrs['related_model'] = \ field_sig.related_model app_mutations.append( ChangeField(model_name=model_name, field_name=field_name, **changed_attrs)) # Process the Meta attribute changes for the model. meta_changed = model_change.get('meta_changed', []) # First, check if the Meta.indexes property has any changes. # They'll all be assembled into a single ChangeMeta. if 'indexes' in meta_changed: change_meta_indexes = [] for index_sig in model_sig.index_sigs: change_meta_index = { 'fields': index_sig.fields, } if index_sig.name: change_meta_index['name'] = index_sig.name change_meta_indexes.append(change_meta_index) app_mutations.append( ChangeMeta(model_name=model_name, prop_name='indexes', new_value=change_meta_indexes)) # Then check Meta.index_together and Meta.unique_together. app_mutations += [ ChangeMeta(model_name=model_name, prop_name=prop_name, new_value=getattr(model_sig, prop_name) or []) for prop_name in ('index_together', 'unique_together') if prop_name in meta_changed ] # Process the list of deleted models for the application. app_mutations += [ DeleteModel(model_name=model_name) for model_name in app_changes.get('deleted', {}) ] if app_mutations: mutations[app_label] = app_mutations return mutations