def test_clean(self): Migration.create_table(if_not_exists=True).run_sync() real_migration_ids = [ "2020-12-17T18:44:30", "2020-12-17T18:44:39", "2020-12-17T18:44:44", ] orphaned_migration_id = "2010-01-101T00:00:00" migration_ids = real_migration_ids + [orphaned_migration_id] Migration.insert( *[Migration(name=i, app_name="example_app") for i in migration_ids] ).run_sync() run_sync(clean(app_name="example_app", auto_agree=True)) remaining_rows = ( Migration.select(Migration.name) .where(Migration.app_name == "example_app") .output(as_list=True) .order_by(Migration.name) .run_sync() ) self.assertEqual(remaining_rows, real_migration_ids) Migration.alter().drop_table(if_exists=True).run_sync()
def test_check_migrations(self, get_app_registry: MagicMock): get_app_registry.return_value = AppRegistry( apps=["piccolo.apps.user.piccolo_app"] ) # Make sure it runs without raising an exception: run_sync(check())
def test_clean_sessions(self): SessionsBase.create_session_sync( user_id=1, expiry_date=datetime.datetime.now(), ) run_sync(clean()) session = SessionsBase.select().run_sync() self.assertEqual(session, [])
def test_reflect_all_tables(self): run_sync(self.table_storage.reflect()) reflected_tables = self.table_storage.tables self.assertEqual(len(reflected_tables), 2) for table_class in (Manager, Band): self._compare_table_columns( reflected_tables[table_class._meta.tablename], table_class )
def test_sync_nested(self): """ Test calling a coroutine, which contains a call to `run_sync`. """ async def test(): run_sync(asyncio.sleep(0.1)) run_sync(test())
def test_new_command(self): """ Call the command, when no migration changes are needed. """ with self.assertRaises(SystemExit) as manager: run_sync(new(app_name="example_app", auto=True)) self.assertEqual(manager.exception.__str__(), "No changes detected - exiting.")
def test_forwards_no_migrations(self, print_: MagicMock): """ Test running the migrations if they've already run. """ run_sync(forwards(app_name="music", migration_id="all")) run_sync(forwards(app_name="music", migration_id="all")) self.assertTrue( print_.mock_calls[-1] == call("🏁 No migrations need to be run"))
def test_forwards_no_migrations(self, print_: MagicMock): """ Test running the migrations if they've already run. """ run_sync(forwards(app_name="example_app", migration_id="all")) run_sync(forwards(app_name="example_app", migration_id="all")) self.assertTrue( print_.mock_calls[-1] == call("No migrations left to run!"))
def test_generate_command(self, print_: MagicMock): """ Test the main generate command runs without errors. """ run_sync(generate()) file_contents = print_.call_args[0][0] # Make sure the output is valid Python code (will raise a SyntaxError # exception otherwise). ast.parse(file_contents)
def test_get_unavailable_table(self): run_sync(self.table_storage.reflect(exclude=["band"])) # make sure only one table is present self.assertEqual(len(self.table_storage.tables), 1) table = run_sync(self.table_storage.get_table(tablename="band")) # make sure the returned table is correct self._compare_table_columns(table, Band) # make sure the requested table has been added to the TableStorage self.assertEqual(len(self.table_storage.tables), 2) self.assertIsNotNone(self.table_storage.tables.get("band"))
def test_forwards_unknown_migration(self, print_: MagicMock): """ Test running an unknown migrations forwards. """ with self.assertRaises(SystemExit): run_sync(forwards(app_name="music", migration_id="migration-12345")) self.assertTrue( call("migration-12345 is unrecognised", file=sys.stderr) in print_.mock_calls)
def test_sync_stopped_event_loop(self): """ Test calling a coroutine, when the current thread has an event loop, but it isn't running. """ loop = asyncio.new_event_loop() asyncio.set_event_loop(loop) run_sync(asyncio.sleep(0.1)) asyncio.set_event_loop(None)
def test_backwards_no_migrations(self, print_: MagicMock): """ Test running migrations backwards if none have been run previously. """ run_sync( backwards( app_name="example_app", migration_id="2020-12-17T18:44:30", auto_agree=True, )) self.assertTrue(call("No migrations to reverse!") in print_.mock_calls)
def run_sync(self, timed=False, *args, **kwargs): """ A convenience method for running the coroutine synchronously. """ coroutine = self.run(*args, **kwargs, in_pool=False) if timed: with Timer(): return run_sync(coroutine) else: return run_sync(coroutine)
def test_new_command(self, print_: MagicMock): """ Call the command, when no migration changes are needed. """ with self.assertRaises(SystemExit) as manager: run_sync(new(app_name="example_app", auto=True)) self.assertEqual(manager.exception.code, 0) self.assertTrue( print_.mock_calls[-1] == call("No changes detected - exiting."))
def test_forwards_unknown_migration(self): """ Test running an unknown migrations forwards. """ with self.assertRaises(SystemExit) as manager: run_sync( forwards(app_name="example_app", migration_id="migration-12345")) self.assertEqual(manager.exception.__str__(), "migration-12345 is unrecognised")
def test_forwards_no_migrations(self, print_: MagicMock): """ Test running the migrations if they've already run. """ run_sync(forwards(app_name="example_app", migration_id="all")) with self.assertRaises(SystemExit) as manager: run_sync(forwards(app_name="example_app", migration_id="all")) self.assertEqual(manager.exception.code, 0) self.assertTrue( print_.mock_calls[-1] == call("No migrations left to run!"))
def test_backwards_no_migrations(self, print_): """ Test running migrations backwards if none have been run previously. """ with self.assertRaises(SystemExit) as manager: run_sync( backwards( app_name="example_app", migration_id="2020-12-17T18:44:30", auto_agree=True, )) self.assertEqual(manager.exception.code, 0) self.assertTrue( print_.mock_calls[-1] == call("No migrations to reverse!"))
def run_sync(self, timed=False, *args, **kwargs): """ A convenience method for running the coroutine synchronously. """ coroutine = self.run(*args, **kwargs, in_pool=False) self.run_pre_functions_sync() if timed: with Timer(): response = run_sync(coroutine) self.run_post_functions_sync() return response else: response = run_sync(coroutine) self.run_post_functions_sync() return response
def build_sync( cls, table_class: t.Type[Table], defaults: t.Dict[t.Union[Column, str], t.Any] = None, persist: bool = True, minimal: bool = False, ) -> Table: """ Build Table instance with random data and save sync. This can build relationships, supported data types and parameters. :param table_class: Table class to randomize. Examples: manager = ModelBuilder.build_sync(Manager) manager = ModelBuilder.build_sync(Manager, name='Guido') manager = ModelBuilder(persist=False).build_sync(Manager) manager = ModelBuilder(minimal=True).build_sync(Manager) band = ModelBuilder.build_sync(Band, manager=manager) """ return run_sync( cls.build( table_class=table_class, defaults=defaults, persist=persist, minimal=minimal, ) )
def test_backwards_unknown_migration(self): """ Test running an unknown migrations backwards. """ run_sync(forwards(app_name="example_app", migration_id="all")) with self.assertRaises(SystemExit) as manager: run_sync( backwards( app_name="example_app", migration_id="migration-12345", auto_agree=True, )) self.assertTrue(manager.exception.__str__().startswith( "Unrecognized migration name - must be one of "))
def test_unknown_column_type(self): """ Make sure unknown column types are handled gracefully. """ class Box(Column): """ A column type which isn't supported by Piccolo officially yet. """ pass MegaTable.alter().add_column("my_column", Box()).run_sync() output_schema: OutputSchema = run_sync(get_output_schema()) # Make sure there's a warning. self.assertEqual(output_schema.warnings, ["mega_table.my_column ['box']"]) # Make sure the column type of the generated table is just ``Column``. for table in output_schema.tables: if table.__name__ == "MegaTable": self.assertEqual( output_schema.tables[1].my_column.__class__.__name__, "Column", )
def create_session_sync( cls, user_id: int, expiry_date: t.Optional[datetime] = None) -> SessionsBase: """ A sync equivalent of :meth:`create_session`. """ return run_sync(cls.create_session(user_id, expiry_date))
def test_backwards_unknown_migration(self, print_: MagicMock): """ Test running an unknown migrations backwards. """ run_sync(forwards(app_name="music", migration_id="all")) with self.assertRaises(SystemExit): run_sync( backwards( app_name="music", migration_id="migration-12345", auto_agree=True, )) self.assertTrue( tuple(print_.mock_calls[0])[1][0].startswith( "Unrecognized migration name - must be one of "))
def _test_migrations( self, table_snapshots: t.List[t.List[t.Type[Table]]], test_function: t.Optional[t.Callable[[RowMeta], None]] = None, ): """ Writes a migration file to disk and runs it. :param table_snapshots: A list of lists. Each sub list represents a snapshot of the table state. Migrations will be created and run based each snapshot. :param test_function: After the migrations are run, this function is called. It is passed a ``RowMeta`` instance which can be used to check the column was created correctly in the database. It should return ``True`` if the test passes, otherwise ``False``. """ temp_directory_path = tempfile.gettempdir() migrations_folder_path = os.path.join(temp_directory_path, "piccolo_migrations") if os.path.exists(migrations_folder_path): shutil.rmtree(migrations_folder_path) _create_migrations_folder(migrations_folder_path) app_config = AppConfig( app_name="test_app", migrations_folder_path=migrations_folder_path, table_classes=[], ) for table_snapshot in table_snapshots: app_config.table_classes = table_snapshot meta = run_sync( _create_new_migration(app_config=app_config, auto=True, auto_input="y")) self.assertTrue(os.path.exists(meta.migration_path)) self.run_migrations(app_config=app_config) # It's kind of absurd sleeping for 1 microsecond, but it guarantees # the migration IDs will be unique, and just in case computers # and / or Python get insanely fast in the future :) time.sleep(1e-6) if test_function: column_name = (table_snapshots[-1][-1]._meta. non_default_columns[0]._meta.db_column_name) row_meta = self.get_postgres_column_definition( tablename="my_table", column_name=column_name, ) self.assertTrue( test_function(row_meta), msg=f"Meta is incorrect: {row_meta}", )
def test_exclude_table(self): """ Make sure exclude works. """ output_schema: OutputSchema = run_sync( get_output_schema(exclude=[MegaTable._meta.tablename])) self.assertEqual(len(output_schema.tables), 1) SmallTable_ = output_schema.get_table_with_name("SmallTable") self._compare_table_columns(SmallTable, SmallTable_)
def test_generate_required_tables(self): """ Make sure only tables passed to `tablenames` are created. """ output_schema: OutputSchema = run_sync( get_output_schema(include=[SmallTable._meta.tablename])) self.assertEqual(len(output_schema.tables), 1) SmallTable_ = output_schema.get_table_with_name("SmallTable") self._compare_table_columns(SmallTable, SmallTable_)
def test_validator(self): """ Test calling the hCaptcha API with correct and incorrect tokens. """ captcha = hcaptcha( site_key=HCAPTCHA_TEST_CREDENTIALS.site_key, secret_key=HCAPTCHA_TEST_CREDENTIALS.secret_key, ) # Test correct token response = run_sync( captcha.validate(token=HCAPTCHA_TEST_CREDENTIALS.token) ) self.assertTrue(response is None) # Test incorrect token incorrect_token = "10000000-aaaa-bbbb-cccc-100000000001" response = run_sync(captcha.validate(token=incorrect_token)) self.assertTrue(response == "CAPTCHA failed.")
def test_forwards_backwards_all_migrations(self): """ Test running all of the migrations forwards, then backwards. """ for app_name in ("music", "all"): run_sync(forwards(app_name=app_name, migration_id="all")) # Check the tables exist for table_class in TABLE_CLASSES: self.assertTrue(table_class.table_exists().run_sync()) run_sync( backwards(app_name=app_name, migration_id="all", auto_agree=True)) # Check the tables don't exist for table_class in TABLE_CLASSES: self.assertTrue(not table_class.table_exists().run_sync())
def create_user_sync( cls, username: str, password: str, **extra_params ) -> BaseUser: """ A sync equivalent of :meth:`create_user`. """ return run_sync( cls.create_user( username=username, password=password, **extra_params ) )