from __future__ import annotations from pathlib import Path import runpy from types import SimpleNamespace import unittest from unittest.mock import MagicMock, patch from alembic import context from alembic.config import Config class MigrationUrlConfigurationTests(unittest.TestCase): def test_database_urls_round_trip_exactly_in_online_and_offline_modes(self) -> None: urls = ( "postgresql+psycopg://localhost/example?host=%2Ftmp%2Fexample", "postgresql+psycopg://synthetic%40user:synthetic%25%40pass@localhost/example", "sqlite:////tmp/synthetic%25-database.db", "sqlite:////tmp/synthetic%%-database.db", "sqlite:////tmp/%(here)s-literal.db", "sqlite:////tmp/synthetic-database.db", ) environment = Path(__file__).resolve().parents[1] / "alembic" / "env.py" for url in urls: for offline in (False, True): for from_settings in (False, True): with self.subTest(url=url, offline=offline, from_settings=from_settings): config = Config() config.attributes.update(enabled_modules=(), manifest_factories=()) if not from_settings: config.attributes["database_url"] = url engine = MagicMock() connection = engine.connect.return_value.__enter__.return_value with ( patch.object(context, "config", config, create=True), patch.object(context, "is_offline_mode", return_value=offline), patch.object(context, "configure") as configure, patch.object(context, "begin_transaction"), patch.object(context, "run_migrations") as run_migrations, patch("sqlalchemy.engine_from_config", return_value=engine) as engine_from_config, patch( "govoplan_core.server.default_config.get_server_config", return_value=SimpleNamespace(enabled_modules=(), manifest_factories=()), ), patch("govoplan_core.server.registry.build_platform_registry"), patch( "govoplan_core.core.migrations.migration_metadata_plan", return_value=SimpleNamespace(metadata=()), ), patch("govoplan_core.settings.settings.database_url", url), ): runpy.run_path(str(environment)) self.assertEqual(config.get_main_option("sqlalchemy.url"), url) self.assertEqual(config.get_section(config.config_ini_section)["sqlalchemy.url"], url) run_migrations.assert_called_once_with() if offline: engine_from_config.assert_not_called() self.assertEqual(configure.call_args.kwargs["url"], url) else: engine_from_config.assert_called_once() self.assertEqual(engine_from_config.call_args.args[0]["sqlalchemy.url"], url) self.assertIs(configure.call_args.kwargs["connection"], connection) if __name__ == "__main__": unittest.main()