def test_has_table(self): """Testing DatabaseState.has_table""" database_state = DatabaseState(db_name='default', scan=False) self.assertFalse(database_state.has_table('my_test_table')) database_state.add_table('my_test_table') self.assertTrue(database_state.has_table('my_test_table'))
def test_clone(self): """Testing DatabaseState.clone""" database_state = DatabaseState(db_name='default') cloned_state = database_state.clone() self.assertEqual(cloned_state.db_name, database_state.db_name) self.assertEqual(cloned_state._tables, database_state._tables)
def __init__(self, db_name, database_state=None): """Initialize the instance. Args: db_name (unicode): The name of the database. database_state (django_evolution.db.state.DatabaseState): The database state to track information through. """ if database_state is None: from django_evolution.db.state import DatabaseState database_state = DatabaseState(db_name, scan=False) try: from django.db import connections engine = settings.DATABASES[db_name]['ENGINE'].split('.')[-1] connection = connections[db_name] module_name = ['django_evolution.db', engine] module = __import__('.'.join(module_name), {}, {}, ['']) self.evolver = module.EvolutionOperations(database_state, connection) except ImportError: if hasattr(settings, 'DATABASE_ENGINE'): module_name = ['django_evolution.db', settings.DATABASE_ENGINE] module = __import__('.'.join(module_name), {}, {}, ['']) self.evolver = module.EvolutionOperations(database_state) else: raise
def test_has_model(self): """Testing DatabaseState.has_model""" database_state = DatabaseState(db_name='default', scan=False) self.assertFalse(database_state.has_model(Evolution)) database_state.rescan_tables() self.assertTrue(database_state.has_model(Evolution))
def test_add_table(self): """Testing DatabaseState.add_table""" database_state = DatabaseState(db_name='default', scan=False) database_state.add_table('my_test_table') self.assertEqual(database_state._tables['my_test_table'], { 'indexes': {}, })
def test_get_index_with_invalid_name(self): """Testing DatabaseState.get_index with invalid name""" database_state = DatabaseState(db_name='default', scan=False) database_state.add_table('my_test_table') self.assertIsNone( database_state.get_index(table_name='my_test_table', index_name='my_index'), )
def test_find_index_with_not_found(self): """Testing DatabaseState.find_index with index no found""" database_state = DatabaseState(db_name='default', scan=False) database_state.add_table('my_test_table') index = database_state.find_index(table_name='my_test_table', columns=['col1', 'col2'], unique=True) self.assertIsNone(index)
def setUp(self): super(BaseRelationFieldsTestCase, self).setUp() register_models(database_state=DatabaseState(DEFAULT_DB_ALIAS), models=[ ('CompatModelsTestModel', CompatModelsTestModel), ('CompatModelsAnchor', CompatModelsAnchor), ], new_app_label='tests')
def test_has_model_with_auto_created(self): """Testing DatabaseState.has_model with auto-created model""" model = get_remote_field(User._meta.get_field('groups')).through self.assertTrue(model._meta.auto_created) database_state = DatabaseState(db_name='default', scan=False) self.assertFalse(database_state.has_model(model)) database_state.rescan_tables() self.assertTrue(database_state.has_model(model))
def test_remove_index_with_untracked_table(self): """Testing DatabaseState.remove_index with untracked table""" database_state = DatabaseState(db_name='default', scan=False) expected_message = ( 'Unable to remove index "my_index" from table "my_test_table". ' 'The table is not being tracked in the database state.') with self.assertRaisesMessage(DatabaseStateError, expected_message): database_state.remove_index(table_name='my_test_table', index_name='my_index')
def clear_indexes(self): """Testing DatabaseState.clear_indexes""" database_state = DatabaseState(db_name='default', scan=False) database_state.add_table('my_test_table') database_state.add_index(table_name='my_test_table', index_name='my_index', columns=['col1', 'col2'], unique=True) self.assertEqual(database_state._tables['my_test_table']['indexes'], {})
def test_find_index(self): """Testing DatabaseState.find_index""" database_state = DatabaseState(db_name='default', scan=False) database_state.add_table('my_test_table') database_state.add_index(table_name='my_test_table', index_name='my_index', columns=['col1', 'col2']) index = database_state.find_index(table_name='my_test_table', columns=['col1', 'col2']) self.assertEqual(index, IndexState(name='my_index', columns=['col1', 'col2']))
def set_base_model(self, base_model, name=None, extra_models=[], pre_extra_models=[], db_name=None): """Set the base model(s) that will be mutated in a test. These models will be registered in Django's model registry and queued up to be written to the database. Starting signatures based on these models will be provided, which the test is expected to mutate. Args: base_model (type): The base :py:class:`~django.db.models.Model` to register and write to the database that the test will then mutate. name (unicode, optional): The name to register for the model. This defaults to :py:attr:`default_model_name`. extra_models (list of type, optional): The list of extra models to register and write to the database after writing ``base_model``. These may form relations to ``base_model``. pre_extra_models (list of type, optional): The list of extra models to write to the database before writing ``base_model``. ``base_model`` may form relations to these models. db_name (unicode, optional): The name of the database to write the models to. This defaults to :py:attr:`default_database_name`. """ name = name or self.default_model_name db_name = db_name or self.default_database_name if self.base_model: unregister_app('tests') self.base_model = base_model self.pre_extra_models = pre_extra_models self.extra_models = extra_models self.database_state = DatabaseState(db_name) self.start = self.register_model(model=base_model, name=name, register_indexes=True, db_name=db_name) self.start_sig = self.create_test_proj_sig(model=base_model, name=name)
def test_get_index(self): """Testing DatabaseState.get_index""" database_state = DatabaseState(db_name='default', scan=False) database_state.add_table('my_test_table') database_state.add_index(table_name='my_test_table', index_name='my_index', columns=['col1', 'col2'], unique=True) self.assertEqual( database_state.get_index(table_name='my_test_table', index_name='my_index'), IndexState(name='my_index', columns=['col1', 'col2'], unique=True))
def test_remove_index_with_invalid_index_name(self): """Testing DatabaseState.remove_index with invalid index name""" database_state = DatabaseState(db_name='default', scan=False) database_state.add_table('my_test_table') expected_message = ( 'Unable to remove index "my_index" from table "my_test_table". ' 'The index could not be found.') with self.assertRaisesMessage(DatabaseStateError, expected_message): database_state.remove_index(table_name='my_test_table', index_name='my_index', unique=True)
def test_add_index_with_untracked_table(self): """Testing DatabaseState.add_index with untracked table""" database_state = DatabaseState(db_name='default', scan=False) expected_message = ( 'Unable to add index "my_index" to table "my_test_table". The ' 'table is not being tracked in the database state.') with self.assertRaisesMessage(DatabaseStateError, expected_message): database_state.add_index(table_name='my_test_table', index_name='my_index', columns=['col1', 'col2'], unique=True)
def test_find_index_with_unique_true(self): """Testing DatabaseState.find_index with unique=True""" database_state = DatabaseState(db_name='default', scan=False) database_state.add_table('my_test_table') database_state.add_index(table_name='my_test_table', index_name='my_index', columns=['col1', 'col2'], unique=True) index = database_state.find_index(table_name='my_test_table', columns=['col1', 'col2'], unique=True) self.assertEqual( index, IndexState(name='my_index', columns=['col1', 'col2'], unique=True))
def test_remove_index(self): """Testing DatabaseState.remove_index""" database_state = DatabaseState(db_name='default', scan=False) database_state.add_table('my_test_table') database_state.add_index(table_name='my_test_table', index_name='my_index', columns=['col1', 'col2']) database_state.remove_index(table_name='my_test_table', index_name='my_index') self.assertEqual(database_state._tables['my_test_table'], { 'indexes': {}, 'unique_indexes': {}, })
def test_rescan_indexes(self): """Testing DatabaseState.rescan_indexes""" database_state = DatabaseState(db_name='default') # Check that a few known tables are in the list, to make sure # the scan worked. for table_name in ('django_content_type', 'django_evolution', 'django_project_version'): self.assertTrue(database_state.has_table(table_name)) # Check the Evolution model. indexes = [ (index_state.columns, index_state.unique) for index_state in database_state.iter_indexes('django_evolution') ] self.assertIn((['version_id'], False), indexes)
def test_remove_index_with_invalid_index_type(self): """Testing DatabaseState.remove_index with invalid index type""" database_state = DatabaseState(db_name='default', scan=False) database_state.add_table('my_test_table') database_state.add_index(table_name='my_test_table', index_name='my_index', columns=['col1', 'col2'], unique=True) expected_message = ( 'Unable to remove index "my_index" from table "my_test_table". ' 'The specified index type (unique=False) does not match the ' 'existing type (unique=True).') with self.assertRaisesMessage(DatabaseStateError, expected_message): database_state.remove_index(table_name='my_test_table', index_name='my_index', unique=False)
def test_add_index_with_unique_true(self): """Testing DatabaseState.add_index with unique=True""" database_state = DatabaseState(db_name='default', scan=False) database_state.add_table('my_test_table') database_state.add_index(table_name='my_test_table', index_name='my_index', columns=['col1', 'col2'], unique=True) self.assertEqual( database_state._tables['my_test_table'], { 'indexes': {}, 'unique_indexes': { 'my_index': IndexState(name='my_index', columns=['col1', 'col2'], unique=True), }, })
def test_iter_indexes(self): """Testing DatabaseState.iter_indexes""" database_state = DatabaseState(db_name='default', scan=False) database_state.add_table('my_test_table') database_state.add_index(table_name='my_test_table', index_name='my_index1', columns=['col1', 'col2'], unique=True) database_state.add_index(table_name='my_test_table', index_name='my_index2', columns=['col3']) indexes = list(database_state.iter_indexes('my_test_table')) self.assertEqual(indexes, [ IndexState(name='my_index1', columns=['col1', 'col2'], unique=True), IndexState(name='my_index2', columns=['col3'], unique=False), ])
def test_apply_migrations(self): """Testing apply_migrations""" database_state = DatabaseState(db_name=DEFAULT_DB_ALIAS) register_models(database_state=database_state, models=[('MigrationTestModel', MigrationTestModel)]) app_migrations = [ InitialMigration('0001_initial', 'tests'), AddFieldMigration('0002_add_field', 'tests'), ] targets = [ ('tests', '0001_initial'), ('tests', '0002_add_field'), ] custom_migrations = MigrationList() custom_migrations.add_migration(app_migrations[0]) custom_migrations.add_migration(app_migrations[1]) connection = connections[DEFAULT_DB_ALIAS] executor = MigrationExecutor(connection, custom_migrations=custom_migrations) migrate_state = apply_migrations( executor=executor, targets=targets, plan=[ (app_migrations[0], False), (app_migrations[1], False), ], pre_migrate_state=create_pre_migrate_state(executor)) finalize_migrations(migrate_state) # Make sure this is in the database now. MigrationTestModel.objects.create(field1=123, field2='abc', field3=True)
def test_add_index_with_existing_index(self): """Testing DatabaseState.add_index with existing index""" database_state = DatabaseState(db_name='default', scan=False) database_state.add_table('my_test_table') database_state.add_index(table_name='my_test_table', index_name='existing_index', columns=['col1', 'col2'], unique=True) expected_message = ( 'Unable to add index "existing_index" to table "my_test_table". ' 'This index already exists.') with self.assertRaisesMessage(DatabaseStateError, expected_message): database_state.add_index(table_name='my_test_table', index_name='existing_index', columns=['col1', 'col2'], unique=True) # It's fine if it has a new name. database_state.add_index(table_name='my_test_table', index_name='new_index', columns=['col1', 'col2'], unique=True)
def __init__(self, hinted=False, verbosity=0, interactive=False, database_name=DEFAULT_DB_ALIAS): """Initialize the evolver. Args: hinted (bool, optional): Whether to operate against hinted evolutions. This may result in changes to the database without there being any accompanying evolution files backing those changes. verbosity (int, optional): The verbosity level for any output. This is passed along to signal emissions. interactive (bool, optional): Whether the evolution operations are being performed in a way that allows interactivity on the command line. This is passed along to signal emissions. database_name (unicode, optional): The name of the database to evolve. Raises: django_evolution.errors.EvolutionBaselineMissingError: An initial baseline for the project was not yet installed. This is due to ``syncdb``/``migrate`` not having been run. """ self.database_name = database_name self.hinted = hinted self.verbosity = verbosity self.interactive = interactive self.evolved = False self.initial_diff = None self.project_sig = None self.version = None self.installed_new_database = False self.connection = connections[database_name] if hasattr(self.connection, 'prepare_database'): # Django >= 1.8 self.connection.prepare_database() self.database_state = DatabaseState(self.database_name) self.target_project_sig = \ ProjectSignature.from_database(database_name) self._tasks_by_class = OrderedDict() self._tasks_by_id = OrderedDict() self._tasks_prepared = False latest_version = None if self.database_state.has_model(Version): try: latest_version = \ Version.objects.current_version(using=database_name) except Version.DoesNotExist: # We'll populate this next. pass if latest_version is None: # Either the models aren't yet synced to the database, or we # don't have a saved project signature, so let's set these up. self.installed_new_database = True self.project_sig = ProjectSignature() app = get_app('django_evolution') task = EvolveAppTask(evolver=self, app=app) task.prepare(hinted=False) with self.sql_executor() as sql_executor: task.execute(sql_executor=sql_executor, create_models_now=True) self.database_state.rescan_tables() app_sig = AppSignature.from_app(app=app, database=database_name) self.project_sig.add_app_sig(app_sig) # Let's make completely sure that we've only found the models # we expect. This is mostly for the benefit of unit tests. model_names = set(model_sig.model_name for model_sig in app_sig.model_sigs) expected_model_names = set(['Evolution', 'Version']) assert model_names == expected_model_names, ( 'Unexpected models found for django_evolution app: %s' % ', '.join(model_names - expected_model_names)) self._save_project_sig(new_evolutions=task.new_evolutions) latest_version = self.version self.project_sig = latest_version.signature self.initial_diff = Diff(self.project_sig, self.target_project_sig)