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.
34 lines
1.0 KiB
Python
34 lines
1.0 KiB
Python
import json
|
|
|
|
from ..types import ReportRow
|
|
from .base import Formatter
|
|
|
|
|
|
class JSONFormatter(Formatter):
|
|
"""Форматтер для экспорта отчёта в JSON."""
|
|
|
|
def __init__(self, **_kwargs):
|
|
super().__init__()
|
|
|
|
def format(self, rows: list[ReportRow]) -> str:
|
|
data = []
|
|
for r in rows:
|
|
item = {
|
|
"project": r["project"],
|
|
"version": r["version"],
|
|
"issue_id": r["issue_id"],
|
|
"subject": r["subject"],
|
|
"status": r["status_ru"],
|
|
"time": r["time_text"],
|
|
}
|
|
activities = r.get("activities")
|
|
if activities:
|
|
item["activities"] = activities
|
|
data.append(item)
|
|
return json.dumps(data, ensure_ascii=False, indent=2)
|
|
|
|
def save(self, rows: list[ReportRow], output_path: str) -> None:
|
|
content = self.format(rows)
|
|
with open(output_path, "w", encoding="utf-8") as f:
|
|
f.write(content)
|