From ad3fb34dba6459e3e85107569ef7babf8cc34782 Mon Sep 17 00:00:00 2001 From: Andrey Epifancev Date: Sun, 4 Oct 2026 05:01:16 +0400 Subject: [PATCH] =?UTF-8?q?=D0=A1=D1=80=D0=B5=D0=B7=200=20[fix=20C-1]:=20?= =?UTF-8?q?=D0=BF=D0=B0=D0=BA=D0=B5=D1=82=20src=20=D0=BD=D0=B5=20=D1=81?= =?UTF-8?q?=D0=BE=D0=B7=D0=B4=D0=B0=D1=91=D1=82=20=D0=BF=D1=80=D0=B8=D0=BB?= =?UTF-8?q?=D0=BE=D0=B6=D0=B5=D0=BD=D0=B8=D0=B5=20=E2=80=94=20=D1=8D=D0=BC?= =?UTF-8?q?=D1=83=D0=BB=D1=8F=D1=82=D0=BE=D1=80=20=D1=81=D1=82=D0=B0=D1=80?= =?UTF-8?q?=D1=82=D1=83=D0=B5=D1=82=20=D0=B1=D0=B5=D0=B7=20=D0=BD=D0=B0?= =?UTF-8?q?=D1=81=D1=82=D1=80=D0=BE=D0=B5=D0=BA=20=D1=88=D0=BB=D1=8E=D0=B7?= =?UTF-8?q?=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `api/src/__init__.py` оставлен только с docstring: `python -m src.scan_emulator` больше не импортирует `src.app` и не требует `OPENBAO__*`. `run_server.py` импортирует `app` из `src.app`, `get_settings` — из `src.core.config`. Регрессионный тест: subprocess эмулятора с окружением только PATH/ENV_FILE/SCAN_HOTFOLDER_PATH -> код 2, сообщение про корень горячей папки, без ValidationError. Co-Authored-By: Claude Fable 5.1 --- api/run_server.py | 3 ++- api/src/__init__.py | 10 ++++------ api/tests/conftest.py | 4 ++-- api/tests/unit/test_emulator.py | 28 ++++++++++++++++++++++++++++ 4 files changed, 36 insertions(+), 9 deletions(-) diff --git a/api/run_server.py b/api/run_server.py index 37a9775..7715863 100644 --- a/api/run_server.py +++ b/api/run_server.py @@ -1,6 +1,7 @@ import uvicorn -from src import app, get_settings +from src.app import app +from src.core.config import get_settings if __name__ == "__main__": settings = get_settings() diff --git a/api/src/__init__.py b/api/src/__init__.py index 97b1796..9cc1d91 100644 --- a/api/src/__init__.py +++ b/api/src/__init__.py @@ -1,7 +1,5 @@ -from .app import app -from .core.config import get_settings +"""Пакет сервиса scan-gateway. -__all__ = [ - "app", - "get_settings", -] +Импорт пакета не создаёт приложение и не читает настройки шлюза: эмулятор (`python -m src.scan_emulator`) запускается +без переменных `OPENBAO__*`. Приложение — `src.app:app` (точка входа — `run_server.py`). +""" diff --git a/api/tests/conftest.py b/api/tests/conftest.py index a5c3825..94f60e8 100644 --- a/api/tests/conftest.py +++ b/api/tests/conftest.py @@ -1,5 +1,5 @@ """Общие фикстуры. Окружение тестов — `api/.env.test`: его подключает pytest.ini (`ENV_FILE=.env.test`, путь от -каталога api/), поэтому `import src` (он создаёт приложение) работает без своей настройки окружения +каталога api/), поэтому `import src.app` (он создаёт приложение) работает без своей настройки окружения и без инфраструктуры.""" import sys @@ -12,7 +12,7 @@ from loguru import logger @pytest.fixture(autouse=True) def _fresh_settings(): """get_settings кэшируется (lru_cache): сбрасываем кэш до и после каждого теста.""" - # Импорт отложен намеренно: `import src` создаёт приложение и читает окружение + # Импорт отложен намеренно: модули тестов импортируют `src.app`, а он создаёт приложение и читает окружение from src.core.config import get_settings # noqa: PLC0415 get_settings.cache_clear() diff --git a/api/tests/unit/test_emulator.py b/api/tests/unit/test_emulator.py index 26e454a..098775a 100644 --- a/api/tests/unit/test_emulator.py +++ b/api/tests/unit/test_emulator.py @@ -5,7 +5,10 @@ """ import json +import os import shutil +import subprocess +import sys import threading import uuid from collections.abc import Iterator @@ -392,3 +395,28 @@ class TestMain: threading.Timer(0.3, stop.set).start() assert main(stop) == 0 assert hf.answer_path(job_id).is_file() + + def test_module_starts_without_gateway_settings(self, tmp_path: Path) -> None: + """C-1: `python -m src.scan_emulator` не читает настройки шлюза — импорт пакета `src` не создаёт приложение. + + Окружение — только PATH, пустой ENV_FILE и несуществующий корень: ожидается штатный отказ эмулятора (код 2, + сообщение про корень горячей папки), а не `ValidationError` настроек шлюза (`OPENBAO`). + """ + env = { + "PATH": os.environ.get("PATH", ""), + "ENV_FILE": str(tmp_path / "none.env"), + "SCAN_HOTFOLDER_PATH": str(tmp_path / "missing"), + } + proc = subprocess.run( + [sys.executable, "-m", "src.scan_emulator"], + cwd=API_DIR, + env=env, + capture_output=True, + text=True, + timeout=60, + check=False, + ) + assert proc.returncode == 2, proc.stderr + assert "корень горячей папки" in proc.stderr + assert "ValidationError" not in proc.stderr + assert "OPENBAO" not in proc.stderr