refactor: enhance docstrings for clarity and consistency across multiple files

This commit is contained in:
Abhimanyu Saharan
2026-02-09 16:23:41 +05:30
parent 7ca1899d9f
commit 7706943209
28 changed files with 1829 additions and 932 deletions

View File

@@ -1,3 +1,5 @@
"""Task-dependency helpers for validation, querying, and replacement."""
from __future__ import annotations
from collections import defaultdict
@@ -14,6 +16,7 @@ from app.models.task_dependencies import TaskDependency
from app.models.tasks import Task
DONE_STATUS: Final[str] = "done"
_RUNTIME_TYPE_REFERENCES = (UUID, AsyncSession, Mapping, Sequence)
def _dedupe_uuid_list(values: Sequence[UUID]) -> list[UUID]:
@@ -34,6 +37,7 @@ async def dependency_ids_by_task_id(
board_id: UUID,
task_ids: Sequence[UUID],
) -> dict[UUID, list[UUID]]:
"""Return dependency ids keyed by task id for tasks on a board."""
if not task_ids:
return {}
rows = list(
@@ -41,8 +45,8 @@ async def dependency_ids_by_task_id(
select(col(TaskDependency.task_id), col(TaskDependency.depends_on_task_id))
.where(col(TaskDependency.board_id) == board_id)
.where(col(TaskDependency.task_id).in_(task_ids))
.order_by(col(TaskDependency.created_at).asc())
)
.order_by(col(TaskDependency.created_at).asc()),
),
)
mapping: dict[UUID, list[UUID]] = defaultdict(list)
for task_id, depends_on_task_id in rows:
@@ -56,16 +60,17 @@ async def dependency_status_by_id(
board_id: UUID,
dependency_ids: Sequence[UUID],
) -> dict[UUID, str]:
"""Return dependency status values keyed by dependency task id."""
if not dependency_ids:
return {}
rows = list(
await session.exec(
select(col(Task.id), col(Task.status))
.where(col(Task.board_id) == board_id)
.where(col(Task.id).in_(dependency_ids))
)
.where(col(Task.id).in_(dependency_ids)),
),
)
return {task_id: status_value for task_id, status_value in rows}
return dict(rows)
def blocked_by_dependency_ids(
@@ -73,11 +78,12 @@ def blocked_by_dependency_ids(
dependency_ids: Sequence[UUID],
status_by_id: Mapping[UUID, str],
) -> list[UUID]:
blocked: list[UUID] = []
for dep_id in dependency_ids:
if status_by_id.get(dep_id) != DONE_STATUS:
blocked.append(dep_id)
return blocked
"""Return dependency ids that are not yet in the done status."""
return [
dep_id
for dep_id in dependency_ids
if status_by_id.get(dep_id) != DONE_STATUS
]
async def blocked_by_for_task(
@@ -87,6 +93,7 @@ async def blocked_by_for_task(
task_id: UUID,
dependency_ids: Sequence[UUID] | None = None,
) -> list[UUID]:
"""Return unresolved dependency ids for the provided task."""
dep_ids = list(dependency_ids or [])
if dependency_ids is None:
deps_map = await dependency_ids_by_task_id(
@@ -97,11 +104,16 @@ async def blocked_by_for_task(
dep_ids = deps_map.get(task_id, [])
if not dep_ids:
return []
status_by_id = await dependency_status_by_id(session, board_id=board_id, dependency_ids=dep_ids)
status_by_id = await dependency_status_by_id(
session,
board_id=board_id,
dependency_ids=dep_ids,
)
return blocked_by_dependency_ids(dependency_ids=dep_ids, status_by_id=status_by_id)
def _has_cycle(nodes: Sequence[UUID], edges: Mapping[UUID, set[UUID]]) -> bool:
"""Detect cycles in a directed dependency graph."""
visited: set[UUID] = set()
in_stack: set[UUID] = set()
@@ -118,10 +130,7 @@ def _has_cycle(nodes: Sequence[UUID], edges: Mapping[UUID, set[UUID]]) -> bool:
in_stack.remove(node)
return False
for node in nodes:
if dfs(node):
return True
return False
return any(dfs(node) for node in nodes)
async def validate_dependency_update(
@@ -131,6 +140,7 @@ async def validate_dependency_update(
task_id: UUID,
depends_on_task_ids: Sequence[UUID],
) -> list[UUID]:
"""Validate a dependency update and return normalized dependency ids."""
normalized = _dedupe_uuid_list(depends_on_task_ids)
if task_id in normalized:
raise HTTPException(
@@ -145,8 +155,8 @@ async def validate_dependency_update(
await session.exec(
select(col(Task.id))
.where(col(Task.board_id) == board_id)
.where(col(Task.id).in_(normalized))
)
.where(col(Task.id).in_(normalized)),
),
)
missing = [dep_id for dep_id in normalized if dep_id not in existing_ids]
if missing:
@@ -159,13 +169,18 @@ async def validate_dependency_update(
)
# Ensure the dependency graph is acyclic after applying the update.
task_ids = list(await session.exec(select(col(Task.id)).where(col(Task.board_id) == board_id)))
task_ids = list(
await session.exec(
select(col(Task.id)).where(col(Task.board_id) == board_id),
),
)
rows = list(
await session.exec(
select(col(TaskDependency.task_id), col(TaskDependency.depends_on_task_id)).where(
col(TaskDependency.board_id) == board_id
)
)
select(
col(TaskDependency.task_id),
col(TaskDependency.depends_on_task_id),
).where(col(TaskDependency.board_id) == board_id),
),
)
edges: dict[UUID, set[UUID]] = defaultdict(set)
for src, dst in rows:
@@ -188,6 +203,7 @@ async def replace_task_dependencies(
task_id: UUID,
depends_on_task_ids: Sequence[UUID],
) -> list[UUID]:
"""Replace dependencies for a task and return the normalized dependency ids."""
normalized = await validate_dependency_update(
session,
board_id=board_id,
@@ -207,7 +223,7 @@ async def replace_task_dependencies(
board_id=board_id,
task_id=task_id,
depends_on_task_id=dep_id,
)
),
)
return normalized
@@ -218,9 +234,10 @@ async def dependent_task_ids(
board_id: UUID,
dependency_task_id: UUID,
) -> list[UUID]:
"""Return task ids that depend on the provided dependency task id."""
rows = await session.exec(
select(col(TaskDependency.task_id))
.where(col(TaskDependency.board_id) == board_id)
.where(col(TaskDependency.depends_on_task_id) == dependency_task_id)
.where(col(TaskDependency.depends_on_task_id) == dependency_task_id),
)
return list(rows)