Switch all imports to relative paths
Some checks failed
Deploy Tracker / deploy (push) Failing after 3s

This commit is contained in:
markov 2026-02-26 10:46:09 +01:00
parent 659454c2e6
commit c7b073b36c
20 changed files with 89 additions and 89 deletions

View File

@ -9,9 +9,9 @@ from fastapi.responses import FileResponse
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession
from tracker.database import get_db
from tracker.models import Attachment, Message, Member
from tracker.api.schemas import UploadOut
from ..database import get_db
from ..models import Attachment, Message, Member
from .schemas import UploadOut
router = APIRouter(tags=["attachments"])

View File

@ -10,9 +10,9 @@ from pydantic import BaseModel
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession
from tracker.config import settings
from tracker.database import get_db
from tracker.models import Member
from ..config import settings
from ..database import get_db
from ..models import Member
router = APIRouter(tags=["auth"])

View File

@ -1,8 +1,8 @@
"""ORM → Pydantic converters. Single place for all model-to-schema transformations."""
from tracker.models import Attachment, Member, Message, ProjectFile, Step, Task
from tracker.enums import MemberType
from tracker.api.schemas import (
from ..models import Attachment, Member, Message, ProjectFile, Step, Task
from ..enums import MemberType
from .schemas import (
AgentConfigOut,
AttachmentOut,
MemberBrief,

View File

@ -9,11 +9,11 @@ from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.orm import selectinload
from tracker.database import get_db
from tracker.enums import AuthMethod, ListenMode, MemberRole, MemberStatus, MemberType
from tracker.models import Member, AgentConfig
from tracker.api.schemas import MemberOut, AgentConfigOut, OkResponse
from tracker.api.converters import member_out
from ..database import get_db
from ..enums import AuthMethod, ListenMode, MemberRole, MemberStatus, MemberType
from ..models import Member, AgentConfig
from .schemas import MemberOut, AgentConfigOut, OkResponse
from .converters import member_out
router = APIRouter(tags=["members"])

View File

@ -10,11 +10,11 @@ from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.orm import selectinload
from tracker.database import get_db
from tracker.enums import AuthorType, ChatKind
from tracker.models import Message, Chat, Attachment
from tracker.api.schemas import MessageOut
from tracker.api.converters import message_out
from ..database import get_db
from ..enums import AuthorType, ChatKind
from ..models import Message, Chat, Attachment
from .schemas import MessageOut
from .converters import message_out
router = APIRouter(tags=["messages"])
@ -127,7 +127,7 @@ async def create_message(req: MessageCreate, request: Request, db: AsyncSession
msg_data = message_out(msg).model_dump()
# Broadcast via WebSocket
from tracker.ws.manager import manager
from ..ws.manager import manager
project_id = None
if req.chat_id:

View File

@ -12,9 +12,9 @@ from sqlalchemy import select, or_
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.orm import selectinload
from tracker.database import get_db
from tracker.models import ProjectFile, Project, Member
from tracker.api.schemas import ProjectFileOut, MemberBrief
from ..database import get_db
from ..models import ProjectFile, Project, Member
from .schemas import ProjectFileOut, MemberBrief
router = APIRouter(tags=["project-files"])

View File

@ -6,10 +6,10 @@ from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.orm import selectinload
from tracker.database import get_db
from tracker.enums import ChatKind, MemberRole, ProjectStatus
from tracker.models import Project, Chat, Member, ProjectMember
from tracker.api.schemas import ProjectOut
from ..database import get_db
from ..enums import ChatKind, MemberRole, ProjectStatus
from ..models import Project, Chat, Member, ProjectMember
from .schemas import ProjectOut
router = APIRouter(tags=["projects"])

View File

@ -7,11 +7,11 @@ from pydantic import BaseModel
from sqlalchemy import select, func
from sqlalchemy.ext.asyncio import AsyncSession
from tracker.database import get_db
from tracker.models import Step, Task
from tracker.api.schemas import StepOut
from tracker.api.schemas import StepOut
from tracker.api.converters import step_out
from ..database import get_db
from ..models import Step, Task
from .schemas import StepOut
from .schemas import StepOut
from .converters import step_out
router = APIRouter(tags=["steps"])

View File

@ -10,14 +10,14 @@ from sqlalchemy import select, update
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.orm import selectinload, joinedload
from tracker.database import get_db
from tracker.enums import (
from ..database import get_db
from ..enums import (
AuthorType, ChatKind, TaskActionType, TaskPriority, TaskStatus, TaskType, WSEventType,
)
from tracker.models import Task, Step, Project, Member, Message, Chat, TaskAction
from tracker.api.auth import get_current_member
from tracker.api.schemas import TaskOut, MessageOut
from tracker.api.converters import task_out, message_out, member_brief
from ..models import Task, Step, Project, Member, Message, Chat, TaskAction
from .auth import get_current_member
from .schemas import TaskOut, MessageOut
from .converters import task_out, message_out, member_brief
router = APIRouter(tags=["tasks"])
@ -97,7 +97,7 @@ async def _system_message(
):
"""Create system messages: one in project chat + one in task comments.
Uses MessageOut schema for WS broadcasts."""
from tracker.ws.manager import manager
from ..ws.manager import manager
prefix = project_slug[:2].upper() if project_slug else "XX"
key = f"{prefix}-{task.number}"
@ -262,7 +262,7 @@ async def create_task(
task_full = await _get_task(str(task.id), db)
# Broadcast using TaskOut schema
from tracker.ws.manager import manager
from ..ws.manager import manager
task_schema = task_out(task_full, project.slug)
key = f"{project.slug[:2].upper()}-{task.number}"
await manager.broadcast_task_event(str(project.id), WSEventType.TASK_CREATED, task_schema.model_dump())
@ -372,7 +372,7 @@ async def update_task(
await db.refresh(task)
# Broadcast simplified update
from tracker.ws.manager import manager
from ..ws.manager import manager
task_full = await _get_task(task_id, db)
task_schema = task_out(task_full, slug)
await manager.broadcast_task_event(str(task.project_id), WSEventType.TASK_UPDATED, task_schema.model_dump())
@ -392,7 +392,7 @@ async def delete_task(
await db.commit()
await db.delete(task)
await db.commit()
from tracker.ws.manager import manager
from ..ws.manager import manager
await manager.broadcast_task_event(project_id, WSEventType.TASK_DELETED, {
"id": task_id, "project_id": project_id,
})
@ -433,7 +433,7 @@ async def take_task(
)
await db.commit()
from tracker.ws.manager import manager
from ..ws.manager import manager
task_full = await _get_task(task_id, db)
task_schema = task_out(task_full, proj_slug)
await manager.broadcast_task_event(str(task.project_id), WSEventType.TASK_ASSIGNED, task_schema.model_dump())
@ -469,7 +469,7 @@ async def reject_task(
db.add(comment)
await db.commit()
from tracker.ws.manager import manager
from ..ws.manager import manager
task_full = await _get_task(task_id, db)
proj_slug = task.project.slug if task.project else ""
task_schema = task_out(task_full, proj_slug)
@ -507,7 +507,7 @@ async def assign_task(
)
await db.commit()
from tracker.ws.manager import manager
from ..ws.manager import manager
task_full = await _get_task(str(task.id), db)
task_schema = task_out(task_full, proj_slug)
await manager.broadcast_task_event(str(task.project_id), WSEventType.TASK_ASSIGNED, task_schema.model_dump())

View File

@ -11,9 +11,9 @@ from fastapi import FastAPI, Request
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import JSONResponse
from tracker.config import settings
from tracker.database import engine, async_session
from tracker.models import Base, Member
from .config import settings
from .database import engine, async_session
from .models import Base, Member
from sqlalchemy import select, update
@ -26,7 +26,7 @@ logger = logging.getLogger("tracker")
async def heartbeat_monitor():
"""Monitor heartbeat timeout — set status=offline after 90 seconds."""
from tracker.ws.manager import manager
from .ws.manager import manager
from datetime import datetime, timezone, timedelta
while True:
@ -69,7 +69,7 @@ async def lifespan(app: FastAPI):
result = await session.execute(select(Member).limit(1))
if not result.scalar_one_or_none():
logger.info("Empty DB detected in dev mode — running seed...")
from tracker.init_db import seed_dev_data
from .init_db import seed_dev_data
await seed_dev_data(session)
logger.info("Dev seed complete.")
@ -120,7 +120,7 @@ async def auth_middleware(request: Request, call_next):
member = result.scalar_one_or_none()
if not member:
# Try JWT
from tracker.api.auth import decode_jwt
from .api.auth import decode_jwt
try:
payload = decode_jwt(token)
result = await db.execute(select(Member).where(Member.id == payload["sub"]))
@ -167,8 +167,8 @@ app.add_middleware(
)
# Routers
from tracker.api import auth, members, projects, tasks, messages, steps, attachments, project_files # noqa: E402
from tracker.ws.handler import router as ws_router # noqa: E402
from .api import auth, members, projects, tasks, messages, steps, attachments, project_files # noqa: E402
from .ws.handler import router as ws_router # noqa: E402
app.include_router(auth.router, prefix="/api/v1")
app.include_router(members.router, prefix="/api/v1")

View File

@ -2,7 +2,7 @@
from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker, create_async_engine
from tracker.config import settings
from .config import settings
engine = create_async_engine(settings.database_url, echo=(settings.env == "dev"))
async_session = async_sessionmaker(engine, class_=AsyncSession, expire_on_commit=False)

View File

@ -6,8 +6,8 @@ import logging
from sqlalchemy.ext.asyncio import AsyncSession
from tracker.enums import AuthMethod, ChatKind, MemberRole, MemberStatus, MemberType, ProjectStatus
from tracker.models import Base, Member, Chat, Project, ProjectMember, AgentConfig
from .enums import AuthMethod, ChatKind, MemberRole, MemberStatus, MemberType, ProjectStatus
from .models import Base, Member, Chat, Project, ProjectMember, AgentConfig
logger = logging.getLogger("tracker.init_db")
@ -71,7 +71,7 @@ async def seed_dev_data(session: AsyncSession):
async def reset_db():
"""Drop all tables, recreate, and seed. For dev use only."""
from tracker.database import engine, async_session
from .database import engine, async_session
async with engine.begin() as conn:
await conn.run_sync(Base.metadata.drop_all)

View File

@ -1,11 +1,11 @@
"""Models package — import all models for metadata discovery."""
from tracker.models.base import Base
from tracker.models.member import AgentConfig, Member
from tracker.models.project import Project, ProjectMember
from tracker.models.task import Step, Task, TaskAction
from tracker.models.chat import Attachment, Chat, Message
from tracker.models.project_file import ProjectFile
from .base import Base
from .member import AgentConfig, Member
from .project import Project, ProjectMember
from .task import Step, Task, TaskAction
from .chat import Attachment, Chat, Message
from .project_file import ProjectFile
__all__ = [
"Base",

View File

@ -7,12 +7,12 @@ from sqlalchemy import ForeignKey, Integer, String, Text
from sqlalchemy.dialects.postgresql import ARRAY, UUID
from sqlalchemy.orm import Mapped, mapped_column, relationship
from tracker.enums import ChatKind
from tracker.models.base import Base
from ..enums import ChatKind
from .base import Base
if TYPE_CHECKING:
from tracker.models.member import Member
from tracker.models.project import Project
from .member import Member
from .project import Project
class Chat(Base):

View File

@ -7,11 +7,11 @@ from sqlalchemy import ForeignKey, String, Text
from sqlalchemy.dialects.postgresql import ARRAY, UUID
from sqlalchemy.orm import Mapped, mapped_column, relationship
from tracker.enums import AuthMethod, ListenMode, MemberRole, MemberStatus, MemberType
from tracker.models.base import Base
from ..enums import AuthMethod, ListenMode, MemberRole, MemberStatus, MemberType
from .base import Base
if TYPE_CHECKING:
from tracker.models.project import ProjectMember
from .project import ProjectMember
class Member(Base):

View File

@ -7,13 +7,13 @@ from sqlalchemy import ForeignKey, Integer, String, Text, UniqueConstraint
from sqlalchemy.dialects.postgresql import ARRAY, UUID
from sqlalchemy.orm import Mapped, mapped_column, relationship
from tracker.enums import MemberRole, ProjectStatus
from tracker.models.base import Base
from ..enums import MemberRole, ProjectStatus
from .base import Base
if TYPE_CHECKING:
from tracker.models.task import Task
from tracker.models.chat import Chat
from tracker.models.member import Member
from .task import Task
from .chat import Chat
from .member import Member
class Project(Base):

View File

@ -7,11 +7,11 @@ from sqlalchemy import ForeignKey, Integer, String, Text
from sqlalchemy.dialects.postgresql import UUID
from sqlalchemy.orm import Mapped, mapped_column, relationship
from tracker.models.base import Base
from .base import Base
if TYPE_CHECKING:
from tracker.models.project import Project
from tracker.models.member import Member
from .project import Project
from .member import Member
class ProjectFile(Base):

View File

@ -7,12 +7,12 @@ from sqlalchemy import Boolean, ForeignKey, Integer, String, Text
from sqlalchemy.dialects.postgresql import ARRAY, UUID
from sqlalchemy.orm import Mapped, mapped_column, relationship
from tracker.enums import TaskPriority, TaskStatus, TaskType
from tracker.models.base import Base
from ..enums import TaskPriority, TaskStatus, TaskType
from .base import Base
if TYPE_CHECKING:
from tracker.models.member import Member
from tracker.models.project import Project
from .member import Member
from .project import Project
class Task(Base):

View File

@ -7,14 +7,14 @@ from fastapi import APIRouter, WebSocket, WebSocketDisconnect
from sqlalchemy import select
from sqlalchemy.orm import selectinload
from tracker.database import async_session
from tracker.enums import (
from ..database import async_session
from ..enums import (
AuthMethod, ChatKind, ListenMode, MemberRole, MemberStatus, MemberType,
ProjectStatus, WSEventType,
)
from tracker.models import Member, AgentConfig, Chat, Message, Project, ProjectMember
from tracker.api.schemas import MessageOut, MemberBrief
from tracker.ws.manager import ConnectedClient, manager
from ..models import Member, AgentConfig, Chat, Message, Project, ProjectMember
from ..api.schemas import MessageOut, MemberBrief
from .manager import ConnectedClient, manager
logger = logging.getLogger("tracker.ws")
router = APIRouter()
@ -134,7 +134,7 @@ async def _authenticate(ws: WebSocket, token: str, on_behalf_of: str | None = No
member = result.scalar_one_or_none()
else:
# Try JWT decode
from tracker.api.auth import decode_jwt
from ..api.auth import decode_jwt
try:
payload = decode_jwt(token)
member_id = payload["sub"]

View File

@ -7,7 +7,7 @@ from datetime import datetime, timezone
from fastapi import WebSocket
from tracker.enums import AuthorType, ListenMode, MemberType, WSEventType
from ..enums import AuthorType, ListenMode, MemberType, WSEventType
logger = logging.getLogger("tracker.ws")