"""Test configuration shared by unit and end-to-end tests. Sets up sys.path and pre-mocks modules that would cause circular import issues when unit-testing lightweight config/registry code in isolation. """ import importlib.util import sys import warnings from pathlib import Path from unittest.mock import MagicMock import pytest # Make 'app' and 'deerflow' importable from any working directory sys.path.insert(0, str(Path(__file__).parent.parent)) sys.path.insert(0, str(Path(__file__).resolve().parents[2] / "scripts")) # Break the circular import chain that exists in production code: # deerflow.subagents.__init__ # -> .executor (SubagentExecutor, SubagentResult) # -> deerflow.agents.thread_state # -> deerflow.agents.__init__ # -> lead_agent.agent # -> subagent_limit_middleware # -> deerflow.subagents.executor <-- circular! # # By injecting a mock for deerflow.subagents.executor *before* any test module # triggers the import, __init__.py's "from .executor import ..." succeeds # immediately without running the real executor module. _executor_mock = MagicMock() _executor_mock.SubagentExecutor = MagicMock _executor_mock.SubagentResult = MagicMock _executor_mock.SubagentStatus = MagicMock _executor_mock.MAX_CONCURRENT_SUBAGENTS = 3 _executor_mock.get_background_task_result = MagicMock() sys.modules["deerflow.subagents.executor"] = _executor_mock def pytest_configure(config): config.addinivalue_line( "markers", "no_auto_user: disable the conftest autouse contextvar fixture for this test", ) warnings.filterwarnings( "ignore", message=r"Pydantic serializer warnings:.*field_name='context'.*", category=UserWarning, ) warnings.filterwarnings( "ignore", message=r"pkg_resources is deprecated as an API.*", category=UserWarning, ) warnings.filterwarnings( "ignore", message=r"Deprecated call to `pkg_resources\.declare_namespace\(.*", category=DeprecationWarning, ) warnings.filterwarnings( "ignore", message=r"datetime\.datetime\.utcfromtimestamp\(\) is deprecated.*", category=DeprecationWarning, ) warnings.filterwarnings( "ignore", message=r"websockets\.InvalidStatusCode is deprecated", category=DeprecationWarning, ) warnings.filterwarnings( "ignore", message=r"websockets\.legacy is deprecated.*", category=DeprecationWarning, ) warnings.filterwarnings( "ignore", message=r"websockets\.client\.WebSocketClientProtocol is deprecated", category=DeprecationWarning, ) @pytest.fixture() def provisioner_module(): """Load docker/provisioner/app.py as an importable test module.""" repo_root = Path(__file__).resolve().parents[2] module_path = repo_root / "docker" / "provisioner" / "app.py" spec = importlib.util.spec_from_file_location("provisioner_app_test", module_path) assert spec is not None assert spec.loader is not None module = importlib.util.module_from_spec(spec) spec.loader.exec_module(module) return module @pytest.fixture(autouse=True) def _auto_user_context(request): """Inject a default ``test-user-autouse`` into the contextvar.""" if request.node.get_closest_marker("no_auto_user"): yield return try: from deerflow.runtime.actor_context import ( ActorContext, bind_actor_context, reset_actor_context, ) except ImportError: yield return token = bind_actor_context(ActorContext(user_id="test-user-autouse")) try: yield finally: reset_actor_context(token)