feat: filter Wishlist from --my-tasks; document the mode (#71)
Tasks in the "Wishlist" bucket version are now excluded from the list and summary entirely (no due date, noise backlog); exact case match, tasks without a version are unaffected. Document --my-tasks in README and the user guide (sorting, summary metrics, OSC 8 links, stream separation); all examples use synthetic data. Declare ruff known-first-party in pyproject so the lint result is CWD-independent.
This commit is contained in:
@@ -16,7 +16,12 @@ from .formatters.factory import get_console_formatter, get_formatter_by_extensio
|
||||
from .formatters.task_table import TaskTableFormatter
|
||||
from .mailer import send_report
|
||||
from .report_builder import build_grouped_report, calculate_summary
|
||||
from .task_list import build_task_rows, calculate_task_summary, format_summary_line
|
||||
from .task_list import (
|
||||
build_task_rows,
|
||||
calculate_task_summary,
|
||||
filter_excluded_versions,
|
||||
format_summary_line,
|
||||
)
|
||||
from .yaml_config import ensure_config_dir, resolve_output_path, save_period_to_config
|
||||
|
||||
# Маскируем API-ключ Redmine в тексте ошибок (#55):
|
||||
@@ -287,6 +292,10 @@ def _run_my_tasks(args: argparse.Namespace) -> int:
|
||||
logging.exception("Unexpected error") # noqa: LOG015
|
||||
return 1
|
||||
|
||||
# Бакет-версии (Wishlist) исключаются до проверки на пустоту: если все
|
||||
# открытые задачи в них, пользователь видит "Открытых задач нет".
|
||||
items = filter_excluded_versions(items)
|
||||
|
||||
if not items:
|
||||
print("ℹ️ Открытых задач нет.", file=sys.stderr)
|
||||
return 0
|
||||
|
||||
@@ -22,6 +22,31 @@ def _issue_version_name(issue: Issue) -> str:
|
||||
return get_version(issue, default="")
|
||||
|
||||
|
||||
# "Wishlist" -- постоянная бакет-версия без срока (личный бакет Wendy, факт
|
||||
# из трекера): задачи в ней -- отложенные идеи, создающие мусорный фон в
|
||||
# персональной выборке, поэтому режим --my-tasks исключает их целиком --
|
||||
# из таблицы и из саммари. Сравнение имени точное, без нормализации регистра.
|
||||
EXCLUDED_VERSION_NAMES: frozenset[str] = frozenset({"Wishlist"})
|
||||
|
||||
|
||||
def filter_excluded_versions(
|
||||
items: list[tuple[Issue, date | None]],
|
||||
) -> list[tuple[Issue, date | None]]:
|
||||
"""Убирает задачи версий-исключений из выборки --my-tasks.
|
||||
|
||||
Доступ к fixed_version.name getattr-безопасный: задача без версии или
|
||||
с версией без имени остаётся в выборке. Даты в парах сохраняются как есть.
|
||||
"""
|
||||
kept: list[tuple[Issue, date | None]] = []
|
||||
for item in items:
|
||||
version = getattr(item[0], "fixed_version", None)
|
||||
name = getattr(version, "name", None) if version is not None else None
|
||||
if name and str(name) in EXCLUDED_VERSION_NAMES:
|
||||
continue
|
||||
kept.append(item)
|
||||
return kept
|
||||
|
||||
|
||||
def _sort_key(item: tuple[Issue, date | None]) -> tuple[int, bool, date, int]:
|
||||
"""Ключ сортировки: приоритет, затем срок по возрастанию, затем id.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user