taskai-cli 1.1.5__tar.gz → 1.2.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {taskai_cli-1.1.5 → taskai_cli-1.2.1}/PKG-INFO +1 -1
- {taskai_cli-1.1.5 → taskai_cli-1.2.1}/pyproject.toml +1 -1
- {taskai_cli-1.1.5 → taskai_cli-1.2.1}/taskai/cli.py +5 -1
- {taskai_cli-1.1.5 → taskai_cli-1.2.1}/taskai/models.py +12 -1
- {taskai_cli-1.1.5 → taskai_cli-1.2.1}/taskai/views.py +54 -4
- taskai_cli-1.1.5/migrations/_001_removing_lists.py +0 -50
- taskai_cli-1.1.5/migrations/convert_title_to_name.py +0 -30
- {taskai_cli-1.1.5 → taskai_cli-1.2.1}/.github/workflows/publish-to-pypi.yml +0 -0
- {taskai_cli-1.1.5 → taskai_cli-1.2.1}/.gitignore +0 -0
- {taskai_cli-1.1.5 → taskai_cli-1.2.1}/DEVLOG.md +0 -0
- {taskai_cli-1.1.5 → taskai_cli-1.2.1}/README.md +0 -0
- {taskai_cli-1.1.5 → taskai_cli-1.2.1}/docs/index.md +0 -0
- {taskai_cli-1.1.5 → taskai_cli-1.2.1}/mkdocs.yml +0 -0
- {taskai_cli-1.1.5 → taskai_cli-1.2.1}/scripts/bump_version.py +0 -0
- {taskai_cli-1.1.5 → taskai_cli-1.2.1}/taskai/config.py +0 -0
- {taskai_cli-1.1.5 → taskai_cli-1.2.1}/taskai/help_menu.py +0 -0
- {taskai_cli-1.1.5 → taskai_cli-1.2.1}/taskai/json_dir_database.py +0 -0
- {taskai_cli-1.1.5 → taskai_cli-1.2.1}/taskai/services/ai.py +0 -0
- {taskai_cli-1.1.5 → taskai_cli-1.2.1}/taskai/services/pomodoro.py +0 -0
- {taskai_cli-1.1.5 → taskai_cli-1.2.1}/taskai/services/repair_database.py +0 -0
- {taskai_cli-1.1.5 → taskai_cli-1.2.1}/taskai/services/user_setup.py +0 -0
- {taskai_cli-1.1.5 → taskai_cli-1.2.1}/test/test_cli.py +0 -0
- {taskai_cli-1.1.5 → taskai_cli-1.2.1}/test/test_execution.py +0 -0
- {taskai_cli-1.1.5 → taskai_cli-1.2.1}/test/test_json_dir_database.py +0 -0
- {taskai_cli-1.1.5 → taskai_cli-1.2.1}/test/test_view.py +0 -0
|
@@ -406,7 +406,11 @@ def execute_commands(*args, **kwargs) -> int:
|
|
|
406
406
|
# developer use
|
|
407
407
|
case "db":
|
|
408
408
|
import orjson as json
|
|
409
|
-
print_json(json.dumps(db.
|
|
409
|
+
print_json(json.dumps(db.get_item(int(args[1])).model_dump()).decode())
|
|
410
|
+
|
|
411
|
+
case "status":
|
|
412
|
+
item_id, status_val = args[1:3]
|
|
413
|
+
Controller.update_item(item_id, status=status_val)
|
|
410
414
|
|
|
411
415
|
case "exit" | "exit()" | "quit":
|
|
412
416
|
return 0
|
|
@@ -4,7 +4,7 @@ from typing import Optional
|
|
|
4
4
|
from datetime import datetime, timedelta
|
|
5
5
|
|
|
6
6
|
# external
|
|
7
|
-
from pydantic import Field, BaseModel
|
|
7
|
+
from pydantic import Field, BaseModel, field_validator
|
|
8
8
|
|
|
9
9
|
class Base(BaseModel):
|
|
10
10
|
pass
|
|
@@ -46,6 +46,12 @@ class TodoItem(Base):
|
|
|
46
46
|
recur_keep_incomplete: bool = False
|
|
47
47
|
status: str = ""
|
|
48
48
|
|
|
49
|
+
@field_validator("status", mode="before")
|
|
50
|
+
def coerce_status(cls, value):
|
|
51
|
+
if not isinstance(value, str):
|
|
52
|
+
return ""
|
|
53
|
+
return value
|
|
54
|
+
|
|
49
55
|
|
|
50
56
|
class Comment(Base):
|
|
51
57
|
content: str
|
|
@@ -61,5 +67,10 @@ class CLIConfig(Base):
|
|
|
61
67
|
GEMINI_MODEL: str = None
|
|
62
68
|
GEMINI_API_KEY: str = None
|
|
63
69
|
|
|
70
|
+
# VIEW
|
|
71
|
+
DISPLAY_STRING: str = "id name status due_by"
|
|
72
|
+
DISPLAY_COLORS: str = "_ white dark_orange _"
|
|
73
|
+
|
|
74
|
+
|
|
64
75
|
class LLMConfig(Base):
|
|
65
76
|
pass
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# local
|
|
2
2
|
from taskai.json_dir_database import JsonDirectoryDatabase
|
|
3
3
|
from taskai.models import TodoItem, Comment
|
|
4
|
+
from taskai.config import config
|
|
4
5
|
|
|
5
6
|
# external
|
|
6
7
|
from rich import print
|
|
@@ -8,19 +9,68 @@ from rich.console import Console
|
|
|
8
9
|
import rich
|
|
9
10
|
|
|
10
11
|
|
|
12
|
+
"""
|
|
13
|
+
Lets give the lists a display string
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
set of valid attributes
|
|
17
|
+
- id
|
|
18
|
+
- name
|
|
19
|
+
- status
|
|
20
|
+
-
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
VALID_ATTRS = {
|
|
27
|
+
"id",
|
|
28
|
+
"name",
|
|
29
|
+
"created_on",
|
|
30
|
+
"due_by",
|
|
31
|
+
"priority",
|
|
32
|
+
"status"
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
@config("DISPLAY_STRING", "display_str")
|
|
37
|
+
@config("DISPLAY_COLORS", "display_colors")
|
|
11
38
|
def view_lists(
|
|
12
39
|
db: JsonDirectoryDatabase,
|
|
13
40
|
roots: list[int],
|
|
14
|
-
show_done=True,
|
|
41
|
+
show_done=True,
|
|
42
|
+
display_str: str = "id name status",
|
|
43
|
+
display_colors: str = None
|
|
15
44
|
):
|
|
16
45
|
"""Shows all the lists"""
|
|
17
46
|
|
|
47
|
+
attrs = display_str.lower().split(" ")
|
|
48
|
+
|
|
49
|
+
if display_colors:
|
|
50
|
+
colors = display_colors.lower().split(" ")
|
|
51
|
+
assert len(colors) == len(attrs), "must have a color for every attr"
|
|
52
|
+
|
|
53
|
+
for attr in attrs:
|
|
54
|
+
assert attr in VALID_ATTRS, "invalid attribute in display string {}".format(attr)
|
|
55
|
+
|
|
56
|
+
def _render_display_string(item: TodoItem):
|
|
57
|
+
display_string = ""
|
|
58
|
+
for i, attr in enumerate(attrs):
|
|
59
|
+
part = getattr(item, attr)
|
|
60
|
+
if not part:
|
|
61
|
+
continue
|
|
62
|
+
part = str(part)
|
|
63
|
+
if display_colors and colors[i] != "_":
|
|
64
|
+
part = _wrap_string(part, f"[{colors[i]}]", f"[/{colors[i]}]")
|
|
65
|
+
display_string += f" {part}"
|
|
66
|
+
display_string = _wrap_string(display_string, "[strike]", "[/strike]", condition=item.completed)
|
|
67
|
+
return display_string
|
|
18
68
|
|
|
19
69
|
def _print_item(item: TodoItem, level: int):
|
|
20
70
|
if not show_done and item.completed:
|
|
21
71
|
return
|
|
22
|
-
|
|
23
|
-
display_string =
|
|
72
|
+
|
|
73
|
+
display_string = _render_display_string(item)
|
|
24
74
|
indent = "\t" * level
|
|
25
75
|
print(indent + display_string)
|
|
26
76
|
|
|
@@ -101,4 +151,4 @@ def _wrap_string(string_, before, after=None, condition=True):
|
|
|
101
151
|
if condition:
|
|
102
152
|
return f"{before}{string_}{after}"
|
|
103
153
|
else:
|
|
104
|
-
return string_
|
|
154
|
+
return string_
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
import argparse
|
|
2
|
-
import orjson as json
|
|
3
|
-
from taskai.models import TodoItem
|
|
4
|
-
|
|
5
|
-
def migrate(data):
|
|
6
|
-
if "TodoList" in data:
|
|
7
|
-
for k, record in data["TodoList"].items():
|
|
8
|
-
|
|
9
|
-
record["child_ids"] = record.pop("item_ids")
|
|
10
|
-
TodoItem(**record)
|
|
11
|
-
print(f"Converting {k} to Item")
|
|
12
|
-
data["TodoItem"][k] = record
|
|
13
|
-
data.pop("TodoList")
|
|
14
|
-
|
|
15
|
-
for k, record in data["TodoItem"].items():
|
|
16
|
-
|
|
17
|
-
if "title" in record:
|
|
18
|
-
print(f"converting title->name for {k}")
|
|
19
|
-
record["title"] = record["name"]
|
|
20
|
-
record.pop("title")
|
|
21
|
-
|
|
22
|
-
if "parent" in record:
|
|
23
|
-
print(f"converting parent->parent_id for {k}")
|
|
24
|
-
record["parent_id"] = record["parent"]
|
|
25
|
-
record.pop("parent")
|
|
26
|
-
|
|
27
|
-
if "child_ids" not in record:
|
|
28
|
-
print(f"Adding Child IDs {k}")
|
|
29
|
-
record["child_ids"] = []
|
|
30
|
-
|
|
31
|
-
try:
|
|
32
|
-
data["TodoItem"][k] = TodoItem(**record).model_dump()
|
|
33
|
-
except:
|
|
34
|
-
print("validation for {} failed".format(k))
|
|
35
|
-
import sys
|
|
36
|
-
sys.exit()
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
arg_parser = argparse.ArgumentParser()
|
|
40
|
-
arg_parser.add_argument("path", help="path to taskai root")
|
|
41
|
-
args = arg_parser.parse_args()
|
|
42
|
-
|
|
43
|
-
with open(args.path, "rb") as f:
|
|
44
|
-
data = json.loads(f.read())
|
|
45
|
-
|
|
46
|
-
migrate(data)
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
with open(args.path, "wb") as f:
|
|
50
|
-
f.write(json.dumps(data))
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import argparse
|
|
2
|
-
import orjson as json
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
def convert_name_to_name(path):
|
|
6
|
-
with open(path, "rb") as f:
|
|
7
|
-
data = json.loads(f.read())
|
|
8
|
-
|
|
9
|
-
for k, record in data["TodoItem"].items():
|
|
10
|
-
|
|
11
|
-
if "name" in record:
|
|
12
|
-
print(f"migrating {k}")
|
|
13
|
-
record["name"] = record["name"]
|
|
14
|
-
record.pop("name")
|
|
15
|
-
elif "name" in record:
|
|
16
|
-
print(f"validated {k}")
|
|
17
|
-
else:
|
|
18
|
-
print(f"{k} is corrupted")
|
|
19
|
-
|
|
20
|
-
with open(path, "wb") as f:
|
|
21
|
-
f.write(json.dumps(data))
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
arg_parser = argparse.ArgumentParser()
|
|
25
|
-
arg_parser.add_argument("path", help="path to taskai root")
|
|
26
|
-
args = arg_parser.parse_args()
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
convert_name_to_name(args.path)
|
|
30
|
-
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|