fix(ci): hoist imports to satisfy E402 + declare runtime/test deps in pyproject
All checks were successful
All checks were successful
CI failures на feature/ET-011 были вызваны двумя проблемами:
1. ruff `E402 Module level import not at top of file` × 10 в src/api/main.py:
- 9 ошибок от ET-008 (GPS_TRACKS_DB_PATH между импортами) +
1 новая от ET-011 (`from src.api.gps_tracks.endpoint import ...` после
определения `app`). Перенёс все импорты наверх; константы
GPS_TRACKS_DB_PATH и GPS_SOURCES_CONFIG_PATH теперь сразу после import-блока,
а создание router-а остаётся в нижней части файла (зависит от `app`).
2. pyproject.toml не объявлял runtime-deps, которые реально импортируются
в src/ (defusedxml, pyyaml) и в тестах (lxml). Dockerfile брал их из
src/api/requirements.txt, но CI jobs `lint`/`test` ставят `.[dev]` —
поэтому `pytest tests/` падал на ModuleNotFoundError при коллекции
тестов из ET-008/ET-009/ET-011. Добавил недостающие пины в pyproject
(defusedxml/pyyaml в основные deps, lxml — только в dev, нужен для
XSD-валидации в test_gps_tracks_download/_gpx_builder).
Проверено локально в чистом venv после `pip install .[dev]`:
- `ruff check src/` → All checks passed
- `pytest tests/` → 200 passed, 2 deselected
Refs: ET-011
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -10,6 +10,8 @@ dependencies = [
|
||||
"shapely==2.0.4",
|
||||
"mapbox-vector-tile==2.2.0",
|
||||
"httpx==0.27.0",
|
||||
"defusedxml==0.7.1",
|
||||
"pyyaml==6.0.1",
|
||||
]
|
||||
|
||||
[project.optional-dependencies]
|
||||
@@ -18,6 +20,7 @@ dev = [
|
||||
"pytest>=8.0",
|
||||
"httpx>=0.27",
|
||||
"pytest-asyncio>=0.23",
|
||||
"lxml==5.2.2",
|
||||
]
|
||||
|
||||
[build-system]
|
||||
|
||||
@@ -11,25 +11,31 @@ import os
|
||||
import math
|
||||
import struct
|
||||
import sqlite3
|
||||
|
||||
import itertools
|
||||
from typing import List
|
||||
|
||||
import httpx
|
||||
import uvicorn
|
||||
from fastapi import FastAPI, HTTPException, Response
|
||||
from fastapi.responses import FileResponse
|
||||
from fastapi.staticfiles import StaticFiles
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
from pydantic import BaseModel
|
||||
from shapely.geometry import LineString
|
||||
|
||||
from src.api.gps_tracks.endpoint import create_gps_router
|
||||
|
||||
GPS_TRACKS_DB_PATH = os.environ.get(
|
||||
"GPS_TRACKS_DB_PATH",
|
||||
os.path.join(os.path.dirname(__file__), "../../data/gps_tracks.sqlite"),
|
||||
)
|
||||
|
||||
from shapely.geometry import LineString
|
||||
from typing import List
|
||||
|
||||
|
||||
from fastapi import FastAPI, HTTPException, Response
|
||||
from fastapi.responses import FileResponse
|
||||
from fastapi.staticfiles import StaticFiles
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
from pydantic import BaseModel
|
||||
import httpx
|
||||
import uvicorn
|
||||
# ET-011 / ADR-015: путь к config/gps_sources.yaml — содержит per-source
|
||||
# флаг `download_allowed`, который router читает один раз при старте.
|
||||
GPS_SOURCES_CONFIG_PATH = os.environ.get(
|
||||
"GPS_SOURCES_CONFIG_PATH",
|
||||
os.path.join(os.path.dirname(__file__), "../../config/gps_sources.yaml"),
|
||||
)
|
||||
|
||||
# ─── Tile cache ──────────────────────────────────────────────────────────────
|
||||
|
||||
@@ -1251,14 +1257,8 @@ async def terrain_tile(layer: str, z: int, x: int, y: int):
|
||||
|
||||
# ─── Static files ─────────────────────────────────────────────────────────────
|
||||
|
||||
from src.api.gps_tracks.endpoint import create_gps_router
|
||||
|
||||
# ET-011 / ADR-015: путь к config/gps_sources.yaml — содержит per-source
|
||||
# флаг `download_allowed`, который router читает один раз при старте.
|
||||
GPS_SOURCES_CONFIG_PATH = os.environ.get(
|
||||
"GPS_SOURCES_CONFIG_PATH",
|
||||
os.path.join(os.path.dirname(__file__), "../../config/gps_sources.yaml"),
|
||||
)
|
||||
# ET-011 / ADR-015: GPS_SOURCES_CONFIG_PATH объявлен в начале файла рядом с
|
||||
# GPS_TRACKS_DB_PATH; здесь только создаём router после того, как `app` определён.
|
||||
gps_router = create_gps_router(GPS_TRACKS_DB_PATH, GPS_SOURCES_CONFIG_PATH)
|
||||
app.include_router(gps_router)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user