init
This commit is contained in:
121 files changed
+17641
No files matched your search
@@ -0,0 +1,70 @@
|
||||
"""The contract every todo source implements."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass, field
|
||||
from datetime import date
|
||||
from typing import Any, Protocol
|
||||
|
||||
|
||||
class SourceError(RuntimeError):
|
||||
"""A source could not be read. Carries a message meant for the user."""
|
||||
|
||||
|
||||
@dataclass(slots=True)
|
||||
class TodoItem:
|
||||
"""One todo, normalised across Jira / Google Tasks / Todoist / local."""
|
||||
|
||||
source: str
|
||||
external_id: str
|
||||
title: str
|
||||
|
||||
description: str | None = None
|
||||
url: str | None = None
|
||||
project: str | None = None
|
||||
status: str | None = None
|
||||
priority: str | None = None
|
||||
due_date: date | None = None
|
||||
start_date: date | None = None
|
||||
labels: list[str] = field(default_factory=list)
|
||||
is_done: bool = False
|
||||
raw: dict[str, Any] = field(default_factory=dict)
|
||||
|
||||
def days_overdue(self, today: date) -> int:
|
||||
"""Days past the due date, or 0 when due today / not dated."""
|
||||
if self.due_date is None:
|
||||
return 0
|
||||
return max((today - self.due_date).days, 0)
|
||||
|
||||
|
||||
@dataclass(slots=True)
|
||||
class SourceResult:
|
||||
"""What one source returned, including the failure if it had one.
|
||||
|
||||
A source that is down costs you that source, never the whole page — the same
|
||||
rule jira-helper applies to its message sections.
|
||||
"""
|
||||
|
||||
source: str
|
||||
items: list[TodoItem] = field(default_factory=list)
|
||||
ok: bool = True
|
||||
error: str | None = None
|
||||
|
||||
@classmethod
|
||||
def failed(cls, source: str, error: str) -> "SourceResult":
|
||||
return cls(source=source, items=[], ok=False, error=error)
|
||||
|
||||
|
||||
class TodoSource(Protocol):
|
||||
"""A configured, ready-to-call source."""
|
||||
|
||||
name: str
|
||||
|
||||
def fetch(self) -> list[TodoItem]:
|
||||
"""Every open todo this source knows about."""
|
||||
|
||||
def complete(self, item: TodoItem) -> bool:
|
||||
"""Close the task in the external system. False = not supported."""
|
||||
|
||||
def check(self) -> str:
|
||||
"""Verify credentials; return a short human description of the account."""
|
||||
Reference in new issue
Block a user