feat: add --my-tasks mode for open assigned issues (#71)
List open Redmine issues assigned to the current (or overridden) user, sorted by priority rank (P1..P5) then version due date with a stable id tie-break. Renders an OSC 8 hyperlinked console table on stdout and a counts/hours summary line on stderr; version due dates are fetched once per unique version, unavailable versions degrade to an empty due date. Also migrates the codebase to ruff 0.17.3 defaults (PEP 585/604 annotations, targeted noqa for intentional blind excepts and CLI root logging). Behavior-neutral: 408 tests pass with -W error.
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
from typing import Dict, List, Optional, Tuple, cast
|
||||
from typing import cast
|
||||
|
||||
from redminelib.resources import Issue
|
||||
|
||||
@@ -22,7 +22,7 @@ STATUS_TRANSLATION = {
|
||||
}
|
||||
|
||||
|
||||
def _format_activities(activities: Dict[str, float]) -> str:
|
||||
def _format_activities(activities: dict[str, float]) -> str:
|
||||
"""Форматирует разбивку по активностям в многострочный текст."""
|
||||
if not activities:
|
||||
return ""
|
||||
@@ -32,11 +32,11 @@ def _format_activities(activities: Dict[str, float]) -> str:
|
||||
|
||||
|
||||
def build_grouped_report(
|
||||
issue_hours: List[Tuple[Issue, float, Optional[Dict[str, float]]]],
|
||||
issue_hours: list[tuple[Issue, float, dict[str, float] | None]],
|
||||
fill_time: bool = True,
|
||||
by_activity: bool = False,
|
||||
status_translation: Optional[Dict[str, str]] = None,
|
||||
) -> List[ReportRow]:
|
||||
status_translation: dict[str, str] | None = None,
|
||||
) -> list[ReportRow]:
|
||||
"""
|
||||
Преобразует список задач с затраченным временем в плоский список строк отчёта,
|
||||
с учётом группировки по проекту и версии (пустые ячейки для повторяющихся значений).
|
||||
@@ -59,12 +59,12 @@ def build_grouped_report(
|
||||
status_translation if status_translation is not None else STATUS_TRANSLATION
|
||||
)
|
||||
|
||||
rows: List[ReportRow] = []
|
||||
rows: list[ReportRow] = []
|
||||
prev_project: str = ""
|
||||
prev_version: str = ""
|
||||
|
||||
for issue, hours, *rest in issue_hours:
|
||||
activities: Optional[Dict[str, float]] = rest[0] if rest else None
|
||||
activities: dict[str, float] | None = rest[0] if rest else None
|
||||
project = str(issue.project)
|
||||
version = get_version(issue)
|
||||
status_en = str(issue.status)
|
||||
@@ -108,14 +108,14 @@ def build_grouped_report(
|
||||
|
||||
|
||||
def calculate_summary(
|
||||
rows: List[ReportRow],
|
||||
rows: list[ReportRow],
|
||||
by_activity: bool = False,
|
||||
) -> Dict[str, float]:
|
||||
) -> dict[str, float]:
|
||||
"""Возвращает сводку: общее время, время по проектам, версиям и активностям."""
|
||||
total = 0.0
|
||||
by_project: Dict[str, float] = {}
|
||||
by_project_version: Dict[str, float] = {}
|
||||
by_activity_name: Dict[str, float] = {}
|
||||
by_project: dict[str, float] = {}
|
||||
by_project_version: dict[str, float] = {}
|
||||
by_activity_name: dict[str, float] = {}
|
||||
|
||||
for r in rows:
|
||||
hours = r.get("hours", 0.0)
|
||||
@@ -130,7 +130,7 @@ def calculate_summary(
|
||||
for name, act_hours in activities.items():
|
||||
by_activity_name[name] = by_activity_name.get(name, 0.0) + act_hours
|
||||
|
||||
result: Dict[str, float] = {
|
||||
result: dict[str, float] = {
|
||||
"total": round(total, 2),
|
||||
**{f"project:{k}": round(v, 2) for k, v in by_project.items()},
|
||||
**{f"version:{k}": round(v, 2) for k, v in by_project_version.items()},
|
||||
@@ -144,8 +144,8 @@ def calculate_summary(
|
||||
|
||||
|
||||
def group_rows_by_project_and_version(
|
||||
rows: List[ReportRow],
|
||||
) -> Dict[str, Dict[str, List[ReportRow]]]:
|
||||
rows: list[ReportRow],
|
||||
) -> dict[str, dict[str, list[ReportRow]]]:
|
||||
"""
|
||||
Группирует плоский список строк отчёта в иерархию project → version → [rows].
|
||||
|
||||
@@ -153,7 +153,7 @@ def group_rows_by_project_and_version(
|
||||
Возвращает обычный dict, сохраняющий порядок вставки (Python 3.7+).
|
||||
Используется форматтерами HTML и ODT для объединения ячеек.
|
||||
"""
|
||||
projects: Dict[str, Dict[str, List[ReportRow]]] = {}
|
||||
projects: dict[str, dict[str, list[ReportRow]]] = {}
|
||||
for r in rows:
|
||||
project = r["project"]
|
||||
version = r["version"]
|
||||
|
||||
Reference in New Issue
Block a user