def test_with_bad_app(self): """Testing DeleteField with application not in signature""" mutation = DeleteField('TestModel', 'char_field1') message = ( 'Cannot delete the field "char_field1" on 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 DeleteField with model not in signature""" mutation = DeleteField('TestModel', 'char_field1') project_sig = ProjectSignature() project_sig.add_app_sig(AppSignature(app_id='tests')) message = ( 'Cannot delete the field "char_field1" on 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_add_delete_add_rename_field(self): """Testing pre-processing AddField + DeleteField + AddField + RenameField """ class DestModel(models.Model): my_id = models.AutoField(primary_key=True) char_field = models.CharField(max_length=20) renamed_field = models.IntegerField() self.perform_evolution_tests(DestModel, [ AddField('TestModel', 'added_field', models.CharField, initial='', max_length=20), DeleteField('TestModel', 'added_field'), AddField( 'TestModel', 'added_field', models.IntegerField, initial=42), RenameField('TestModel', 'added_field', 'renamed_field'), ], ("In model tests.TestModel:\n" " Field 'renamed_field' has been added"), [ "AddField('TestModel', 'renamed_field', models.IntegerField," " initial=<<USER VALUE REQUIRED>>)", ], 'add_delete_add_rename_field')
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: try: changed_attrs[prop] = \ current_field_sig.get(prop, ATTRIBUTE_DEFAULTS[prop]) except: pass 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, **changed_attrs)) for model_name in app_changes.get('deleted',{}): mutations.setdefault(app_label,[]).append( DeleteModel(model_name)) return mutations
from __future__ import unicode_literals from django_evolution.mutations import AddField, DeleteField from djblets.db.fields import JSONField MUTATIONS = [ AddField('FileDiffData', 'extra_data', JSONField, null=True), DeleteField('FileDiffData', 'insert_count'), DeleteField('FileDiffData', 'delete_count'), ]
from django_evolution.mutations import DeleteField MUTATIONS = [ DeleteField('DiffSet', 'file_count'), DeleteField('DiffCommit', 'file_count'), ]
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 django_evolution.mutations import DeleteField MUTATIONS = [DeleteField('Proyecto', 'telefono')]
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