diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..d40ca43 --- /dev/null +++ b/Makefile @@ -0,0 +1,49 @@ +# Команды разработки scan-gateway. Запуск из корня репозитория; рецепты сами переходят в api/ (как и в arm-core), +# поэтому backend-команды работают с каталогом api/ и окружением api/.venv. +VENV := api/.venv +BIN := $(CURDIR)/$(VENV)/bin +# docs/dev — соседний репозиторий и в основном workspace, и в worktree .wt/<срез>/ +COMPOSE_FILE ?= ../docs/dev/docker-compose.yml +COMPOSE_PROJECT ?= arm-ka + +.PHONY: help venv lint test test-integration check check-full up emulator + +help: + @echo "venv - окружение api/.venv (Python 3.11) с зависимостями без raisa_*" + @echo "lint - ruff check, ruff format --check, mypy src" + @echo "test - pytest без интеграционных тестов" + @echo "test-integration - интеграционные тесты (нужны NATS и MinIO: make up)" + @echo "check - lint + test" + @echo "check-full - check + test-integration" + @echo "up - поднять NATS/MinIO/PostgreSQL общим compose-проектом arm-ka" + @echo "emulator - запустить эмулятор ИС Сканирование (python -m src.scan_emulator)" + +# Python 3.11 (версия платформы); внутренние пакеты raisa_* вне банка недоступны — пропускаем их +venv: + cd api && uv venv --python 3.11 --allow-existing .venv + cd api && grep -v '^raisa_' requirements-dev.txt | uv pip install --python .venv/bin/python -r - + +lint: + cd api && $(BIN)/ruff check . + cd api && $(BIN)/ruff format --check . + cd api && $(BIN)/mypy src + +test: + cd api && $(BIN)/pytest -m "not integration" + +test-integration: + cd api && $(BIN)/pytest -m integration + +check: lint test + +# Полная проверка перед PR. Сборку docker-образа добавит задача 15 +check-full: check test-integration + +# Общий compose-проект workspace (arm-ka): его используют и другие сервисы, поэтому целей down/stop/restart нет. +# --wait — только со списком долгоживущих сервисов: одноразовый minio-init завершается кодом 0, и compose считает это сбоем +up: + docker compose -f $(COMPOSE_FILE) --project-name $(COMPOSE_PROJECT) up -d --wait postgres nats minio + +# Эмулятор ИС Сканирование: модуль появится в задаче 9 +emulator: + cd api && $(BIN)/python -m src.scan_emulator diff --git a/api/pyproject.toml b/api/pyproject.toml new file mode 100644 index 0000000..985539a --- /dev/null +++ b/api/pyproject.toml @@ -0,0 +1,50 @@ +# Настройки инструментов качества. Зависимости — в requirements*.txt, pytest (и его маркеры) — в pytest.ini. + +[tool.ruff] +line-length = 120 +target-version = "py311" + +[tool.ruff.lint] +select = ["E", "F", "I", "UP", "B", "PL"] + +# В тестах сравнение с конкретными числами (порты, тайм-ауты, размеры кэша) — и есть проверка; константы только ухудшили бы чтение +[tool.ruff.lint.per-file-ignores] +"tests/**" = ["PLR2004"] + +[tool.ruff.lint.isort] +known-first-party = ["src"] + +[tool.mypy] +python_version = "3.11" +strict = false +check_untyped_defs = true +plugins = ["pydantic.mypy"] +mypy_path = "." +explicit_package_bases = true + +# Строгий режим для собственного кода сервиса (`src`). `strict = true` в overrides mypy (2.x) применяется глобально, +# а не к модулю, поэтому флаги семейства strict перечислены явно. +[[tool.mypy.overrides]] +module = ["src.contract.*", "src.gateway.*", "src.scan_emulator.*"] +disallow_any_generics = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_defs = true +disallow_incomplete_defs = true +disallow_untyped_decorators = true +warn_return_any = true +warn_unused_ignores = true +no_implicit_reexport = true +strict_equality = true +extra_checks = true + +# Сторонние пакеты без типов (smbprotocol/nkeys не поставляют py.typed; raisa_* недоступны вне банка) +[[tool.mypy.overrides]] +module = ["smbclient.*", "smbprotocol.*", "nkeys.*", "raisa_fastapi_protected_api", "raisa_fastapi_protected_api.*"] +ignore_missing_imports = true + +# miniopy_async: пакет типизирован с ошибкой (Minio не виден mypy при реэкспорте) — типы не подтягиваем, Minio = Any +[[tool.mypy.overrides]] +module = ["miniopy_async", "miniopy_async.*"] +follow_imports = "skip" +ignore_missing_imports = true diff --git a/api/pytest.ini b/api/pytest.ini index 2dc434a..59d52bd 100644 --- a/api/pytest.ini +++ b/api/pytest.ini @@ -18,4 +18,7 @@ addopts = env = APP_ENV=test ENV_FILE=.env.test +markers = + integration: требует запущенной инфраструктуры (NATS, MinIO из docs/dev); исключается из `make test` + fixtures: использует реальные данные из ../fixtures (репозиторий arm-ka-fixtures, внутренний доступ) norecursedirs = .git __pycache__ .venv env build dist diff --git a/api/requirements-dev.txt b/api/requirements-dev.txt index e4d6841..0214af3 100644 --- a/api/requirements-dev.txt +++ b/api/requirements-dev.txt @@ -1,50 +1,11 @@ -aiosqlite -alembic -annotated-types==0.7.0 -anyio==4.8.0 -argon2-cffi -asyncpg -certifi==2024.12.14 -click==8.1.8 -colorama==0.4.6 -dnspython==2.7.0 -email_validator==2.2.0 -et_xmlfile==2.0.0 -fastapi==0.115.7 -fastapi-cli==0.0.7 -h11==0.14.0 -httpcore==1.0.7 -httptools==0.6.4 -httpx==0.27.2 -idna==3.10 -itsdangerous==2.2.0 -Jinja2==3.1.5 -markdown-it-py==3.0.0 -MarkupSafe==3.0.2 -mdurl==0.1.2 -openpyxl==3.1.5 -orjson==3.10.15 -pydantic==2.10.6 -pydantic-extra-types==2.10.2 -pydantic-settings==2.7.1 -pydantic_core==2.27.2 -Pygments==2.19.1 -python-dotenv==1.0.1 -python-jose -python-multipart==0.0.20 -PyYAML==6.0.2 -rich==13.9.4 -rich-toolkit==0.13.2 -shellingham==1.5.4 -sniffio==1.3.1 -sqlalchemy -starlette==0.45.3 -typer==0.15.1 -typing_extensions==4.12.2 -ujson==5.10.0 -uvicorn==0.34.0 -watchfiles==1.0.4 -websockets==14.2 -pytest-asyncio -pytest-env -cosmic-ray \ No newline at end of file +# Инструменты разработки и проверок. Платформенные зависимости — в requirements.txt (не меняем). +# httpx (клиент для TestClient) уже закреплён в requirements.txt — здесь не дублируется. +-r requirements.txt +ruff==0.16.10 +mypy==2.4.0 +pytest==9.1.1 +pytest-asyncio==1.4.0 +pytest-env==1.7.1 +jsonschema==4.26.0 +# заглушки типов для mypy (yaml используется эмулятором и загрузкой схем) +types-PyYAML==6.0.12.20260906