from collections.abc import Generator import pytest # Attempt import of testcontainers postgres_container_cls = None try: try: from testcontainers.community.postgres import PostgresContainer as _PostgresContainer postgres_container_cls = _PostgresContainer except ImportError: from testcontainers.postgres import PostgresContainer as _PostgresContainer postgres_container_cls = _PostgresContainer except ImportError: postgres_container_cls = None @pytest.fixture(scope="session") def postgres_container_url() -> Generator[str]: """Provides a disposable PostgreSQL 16 container URL strictly via Docker testcontainers. Scoped to session to avoid duplicating container startup across tests. No ambient admin or SQLite fallbacks. """ if postgres_container_cls is None: raise RuntimeError( "testcontainers package is required for PostgreSQL integration tests. " "SQLite/localhost fallbacks are strictly prohibited." ) try: container = postgres_container_cls("postgres:16-alpine") container.start() host = container.get_container_host_ip() port = container.get_exposed_port(5432) user = container.username password = container.password dbname = container.dbname url = f"postgresql+asyncpg://{user}:{password}@{host}:{port}/{dbname}" try: yield url finally: container.stop() except Exception as exc: raise RuntimeError( f"Failed to start PostgreSQL testcontainer: {exc}. " "Docker daemon must be running and accessible for integration tests. " "SQLite/localhost fallbacks are prohibited." ) from exc @pytest.fixture def temp_postgres_db(postgres_container_url: str) -> str: """Yields disposable PostgreSQL container database URL.""" return postgres_container_url