-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathreminder.py
132 lines (102 loc) · 3.23 KB
/
reminder.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
import click
import datetime as dt
import pickle
from typing import Optional, List
from difflib import SequenceMatcher as SM
from dataclasses import dataclass
@dataclass
class Task:
name: str = ""
deadline: Optional[dt.date] = None
done: bool = False
def _get_task_list() -> List[Task]:
try:
return pickle.load(open("reminder.p", "rb"))
except Exception:
return []
def _save_task_list(task_list: List[Task]) -> None:
pickle.dump(task_list, open("reminder.p", "wb"))
def _overdue(deadline: Optional[dt.date]) -> bool:
if deadline is None:
return False
if deadline < dt.date.today():
return True
else:
return False
def _to_date(deadline: str) -> dt.date:
try:
return dt.date.fromisoformat(deadline)
except ValueError:
raise ValueError(f"{deadline} is not in YYYY-MM-DD format.") from None
def _find_task(target: str, task_list: List[Task]) -> Optional[Task]:
for task in task_list:
if target.lower() == task.name.lower():
return task
def _find_match(target: str, task_list: List[Task]):
potential_match = []
for task in task_list:
score = SM(None, target, task.name).ratio()
if score >= 0.9:
potential_match.append((score, task.name))
if potential_match:
potential_match = sorted(potential_match, key=lambda x: x[0], reverse=True)
click.echo(f"Cannot find {target}, here are the close matches:")
for num, match in enumerate(potential_match):
click.echo(f"{num+1}. {match[1]}")
@click.group()
def app():
pass
@click.command()
@click.option("--deadline", default=None, help="Enter date in YYYY-MM-DD format.")
@click.argument("task")
def add(task: str, deadline: str):
"""Add a task in reminders."""
task_list = _get_task_list()
target = _find_task(task, task_list)
if target is not None:
click.echo(f"{task} already in the list.")
return
if deadline is None:
task_list.append(Task(task))
else:
task_list.append(Task(task, _to_date(deadline)))
_save_task_list(task_list)
@click.command()
def list():
"""list all the task in the reminders."""
task_list = _get_task_list()
for num, task in enumerate(task_list):
if task.done:
click.secho(f"{num+1}. {task.name}", fg="green")
elif _overdue(task.deadline):
click.secho(f"{num+1}. {task.name}", fg="red")
else:
click.echo(f"{num+1}. {task.name}")
@click.command()
@click.argument("task")
def remove(task: str):
"""Remove a task in reminder."""
task_list = _get_task_list()
target = _find_task(task, task_list)
if target is not None:
task_list.remove(target)
else:
_find_match(task, task_list)
_save_task_list(task_list)
@click.command()
@click.argument("task")
def done(task: str):
"""Mark a task as done in reminder."""
task_list = _get_task_list()
target = _find_task(task, task_list)
if target is not None:
target.done = True
else:
_find_match(task, task_list)
_save_task_list(task_list)
app.add_command(add)
app.add_command(list)
app.add_command(remove)
app.add_command(done)
if __name__ == "__main__":
app()