Срез 0 [2.1]: ruff format и правки линтера в коде шаблона, отметка задачи
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
parent
5a818b4356
commit
55fa7ce25c
@ -1,4 +1,5 @@
|
|||||||
import uvicorn
|
import uvicorn
|
||||||
|
|
||||||
from src import app, get_settings
|
from src import app, get_settings
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
@ -9,4 +10,3 @@ if __name__ == "__main__":
|
|||||||
port=settings.server.PORT,
|
port=settings.server.PORT,
|
||||||
lifespan="on",
|
lifespan="on",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@ -2,6 +2,6 @@ from .app import app
|
|||||||
from .core.config import get_settings
|
from .core.config import get_settings
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
'app',
|
"app",
|
||||||
'get_settings',
|
"get_settings",
|
||||||
]
|
]
|
||||||
|
|||||||
@ -5,8 +5,9 @@ headers), обработчики ошибок, `GET /healthcheck` (`uptime`, `ve
|
|||||||
Чего здесь пока нет: NATS-воркера и S3-клиента (подключаются в lifespan задачами 5.2/5.3 change slice-0-skeleton),
|
Чего здесь пока нет: NATS-воркера и S3-клиента (подключаются в lifespan задачами 5.2/5.3 change slice-0-skeleton),
|
||||||
полей `nats`/`hotfolder` в healthcheck.
|
полей `nats`/`hotfolder` в healthcheck.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from contextlib import asynccontextmanager
|
from contextlib import asynccontextmanager
|
||||||
from datetime import datetime, timezone
|
from datetime import UTC, datetime
|
||||||
|
|
||||||
import smbclient
|
import smbclient
|
||||||
from fastapi import FastAPI
|
from fastapi import FastAPI
|
||||||
@ -31,7 +32,7 @@ def _normalize_root_path(value: str) -> str:
|
|||||||
def create_app(settings: Settings | None = None) -> FastAPI:
|
def create_app(settings: Settings | None = None) -> FastAPI:
|
||||||
settings = settings or get_settings()
|
settings = settings or get_settings()
|
||||||
version = settings.VERSION
|
version = settings.VERSION
|
||||||
up_time = datetime.now(timezone.utc)
|
up_time = datetime.now(UTC)
|
||||||
|
|
||||||
@asynccontextmanager
|
@asynccontextmanager
|
||||||
async def lifespan(app: FastAPI):
|
async def lifespan(app: FastAPI):
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
class NotFoundError(Exception):
|
class NotFoundError(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class CouldntCreateError(Exception):
|
class CouldntCreateError(Exception):
|
||||||
pass
|
pass
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
"""Клиенты инфраструктуры. Каркас: оставлен S3Storage; outbox-паблишер (PollWorker) реализуется в Срезе 0
|
"""Клиенты инфраструктуры. Каркас: оставлен S3Storage; outbox-паблишер (PollWorker) реализуется в Срезе 0
|
||||||
по docs/context/03-architecture.md (референс — reference-old-arm/api/src/core/clients.py).
|
по docs/context/03-architecture.md (референс — reference-old-arm/api/src/core/clients.py).
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
|
|
||||||
from miniopy_async import Minio
|
from miniopy_async import Minio
|
||||||
@ -10,11 +11,11 @@ class S3Storage:
|
|||||||
def __init__(self, client: Minio, bucket_name: str):
|
def __init__(self, client: Minio, bucket_name: str):
|
||||||
self.client = client
|
self.client = client
|
||||||
self.bucket = bucket_name
|
self.bucket = bucket_name
|
||||||
|
|
||||||
async def put_object(self, obj_name, file_data):
|
async def put_object(self, obj_name, file_data):
|
||||||
try:
|
try:
|
||||||
stream = BytesIO(file_data)
|
stream = BytesIO(file_data)
|
||||||
await self.client.put_object(self.bucket, obj_name, stream, length=len(file_data))
|
await self.client.put_object(self.bucket, obj_name, stream, length=len(file_data))
|
||||||
except:
|
except:
|
||||||
raise
|
raise
|
||||||
|
|
||||||
@ -23,5 +24,5 @@ class S3Storage:
|
|||||||
response = await self.client.get_object(self.bucket, obj_name)
|
response = await self.client.get_object(self.bucket, obj_name)
|
||||||
# file_bytes = await response.content.read()
|
# file_bytes = await response.content.read()
|
||||||
return response
|
return response
|
||||||
except:
|
except:
|
||||||
raise
|
raise
|
||||||
|
|||||||
@ -6,6 +6,7 @@
|
|||||||
Файл окружения выбирается переменной `ENV_FILE` (по умолчанию `.env`, путь считается от текущего каталога — `api/`);
|
Файл окружения выбирается переменной `ENV_FILE` (по умолчанию `.env`, путь считается от текущего каталога — `api/`);
|
||||||
переменные окружения приоритетнее файла. Настройки читаются при первом вызове `get_settings()`, не при импорте.
|
переменные окружения приоритетнее файла. Настройки читаются при первом вызове `get_settings()`, не при импорте.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import os
|
import os
|
||||||
from functools import lru_cache
|
from functools import lru_cache
|
||||||
from typing import Literal
|
from typing import Literal
|
||||||
|
|||||||
@ -5,7 +5,6 @@ import sys
|
|||||||
|
|
||||||
from loguru import logger
|
from loguru import logger
|
||||||
|
|
||||||
|
|
||||||
# Периодические пробы мониторинга/оркестратора и служебные doc-эндпоинты.
|
# Периодические пробы мониторинга/оркестратора и служебные doc-эндпоинты.
|
||||||
NOISE_PATHS: tuple[str, ...] = (
|
NOISE_PATHS: tuple[str, ...] = (
|
||||||
"/healthcheck",
|
"/healthcheck",
|
||||||
@ -22,8 +21,20 @@ _NOISE_MARKERS: tuple[str, ...] = ("/static/", "/static-swagger/")
|
|||||||
|
|
||||||
# Расширения статических ассетов (картинки, стили, скрипты, шрифты).
|
# Расширения статических ассетов (картинки, стили, скрипты, шрифты).
|
||||||
_STATIC_SUFFIXES: tuple[str, ...] = (
|
_STATIC_SUFFIXES: tuple[str, ...] = (
|
||||||
".png", ".jpg", ".jpeg", ".gif", ".svg", ".ico", ".webp",
|
".png",
|
||||||
".css", ".js", ".map", ".woff", ".woff2", ".ttf", ".eot",
|
".jpg",
|
||||||
|
".jpeg",
|
||||||
|
".gif",
|
||||||
|
".svg",
|
||||||
|
".ico",
|
||||||
|
".webp",
|
||||||
|
".css",
|
||||||
|
".js",
|
||||||
|
".map",
|
||||||
|
".woff",
|
||||||
|
".woff2",
|
||||||
|
".ttf",
|
||||||
|
".eot",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -73,6 +84,7 @@ def setup_logger(
|
|||||||
|
|
||||||
class InterceptHandler(logging.Handler):
|
class InterceptHandler(logging.Handler):
|
||||||
def emit(self, record: logging.LogRecord) -> None:
|
def emit(self, record: logging.LogRecord) -> None:
|
||||||
|
lvl: str | int
|
||||||
try:
|
try:
|
||||||
lvl = logger.level(record.levelname).name
|
lvl = logger.level(record.levelname).name
|
||||||
except ValueError:
|
except ValueError:
|
||||||
|
|||||||
@ -4,6 +4,7 @@
|
|||||||
маппинг JSON из S3 в document/osv_entry/financial_statement_*) реализуется в Срезе 0–2 по
|
маппинг JSON из S3 в document/osv_entry/financial_statement_*) реализуется в Срезе 0–2 по
|
||||||
docs/context/03-architecture.md. Для референса — reference-old-arm/api/src/core/nats_callback.py.
|
docs/context/03-architecture.md. Для референса — reference-old-arm/api/src/core/nats_callback.py.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from loguru import logger
|
from loguru import logger
|
||||||
from nats.aio.client import Client as NATS
|
from nats.aio.client import Client as NATS
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
"""Общие фикстуры. Минимальное окружение local-режима задаётся здесь, чтобы `import src` (он создаёт приложение)
|
"""Общие фикстуры. Минимальное окружение local-режима задаётся здесь, чтобы `import src` (он создаёт приложение)
|
||||||
работал без `.env.test` и без инфраструктуры; значения можно переопределить переменными окружения."""
|
работал без `.env.test` и без инфраструктуры; значения можно переопределить переменными окружения."""
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
@ -20,7 +21,8 @@ for _key, _value in _MINIMAL_ENV.items():
|
|||||||
@pytest.fixture(autouse=True)
|
@pytest.fixture(autouse=True)
|
||||||
def _fresh_settings():
|
def _fresh_settings():
|
||||||
"""get_settings кэшируется (lru_cache): сбрасываем кэш до и после каждого теста."""
|
"""get_settings кэшируется (lru_cache): сбрасываем кэш до и после каждого теста."""
|
||||||
from src.core.config import get_settings
|
# Импорт отложен намеренно: `import src` создаёт приложение и требует окружения, заданного выше
|
||||||
|
from src.core.config import get_settings # noqa: PLC0415
|
||||||
|
|
||||||
get_settings.cache_clear()
|
get_settings.cache_clear()
|
||||||
yield
|
yield
|
||||||
|
|||||||
@ -32,7 +32,7 @@
|
|||||||
|
|
||||||
### Task 4: [2.1] `api/pyproject.toml` (ruff, mypy), `requirements-dev.txt` = `-r requirements.txt
|
### Task 4: [2.1] `api/pyproject.toml` (ruff, mypy), `requirements-dev.txt` = `-r requirements.txt
|
||||||
|
|
||||||
- [ ] `api/pyproject.toml` (ruff, mypy), `requirements-dev.txt` = `-r requirements.txt` + ruff, mypy, pytest, pytest-asyncio, pytest-env, httpx, jsonschema; `Makefile`: `venv` (python3.11, без `raisa_*`), `lint`, `test`, `test-integration`, `check`, `check-full`, `up`, `emulator`; проверка: `make venv && make lint` зелёные
|
- [x] `api/pyproject.toml` (ruff, mypy), `requirements-dev.txt` = `-r requirements.txt` + ruff, mypy, pytest, pytest-asyncio, pytest-env, httpx, jsonschema; `Makefile`: `venv` (python3.11, без `raisa_*`), `lint`, `test`, `test-integration`, `check`, `check-full`, `up`, `emulator`; проверка: `make venv && make lint` зелёные
|
||||||
|
|
||||||
### Task 5: [2.2] `Dockerfile` (`python
|
### Task 5: [2.2] `Dockerfile` (`python
|
||||||
|
|
||||||
|
|||||||
@ -19,7 +19,7 @@
|
|||||||
|
|
||||||
## 2. Инструменты
|
## 2. Инструменты
|
||||||
|
|
||||||
- [ ] 2.1 `api/pyproject.toml` (ruff, mypy), `requirements-dev.txt` = `-r requirements.txt` + ruff, mypy, pytest,
|
- [x] 2.1 `api/pyproject.toml` (ruff, mypy), `requirements-dev.txt` = `-r requirements.txt` + ruff, mypy, pytest,
|
||||||
pytest-asyncio, pytest-env, httpx, jsonschema; `Makefile`: `venv` (python3.11, без `raisa_*`), `lint`, `test`,
|
pytest-asyncio, pytest-env, httpx, jsonschema; `Makefile`: `venv` (python3.11, без `raisa_*`), `lint`, `test`,
|
||||||
`test-integration`, `check`, `check-full`, `up`, `emulator`; проверка: `make venv && make lint` зелёные
|
`test-integration`, `check`, `check-full`, `up`, `emulator`; проверка: `make venv && make lint` зелёные
|
||||||
- [ ] 2.2 `Dockerfile` (`python:3.11-slim`; `CMD python run_server.py`, эмулятор — через `command` в compose),
|
- [ ] 2.2 `Dockerfile` (`python:3.11-slim`; `CMD python run_server.py`, эмулятор — через `command` в compose),
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user