From 16328be0010f1c438bd94a4f20f7dd0aa9ebcd1d Mon Sep 17 00:00:00 2001 From: autogainz Date: Thu, 19 Feb 2026 11:18:34 -0500 Subject: [PATCH 1/7] feat: create utils package --- utils/__init__.py | 1 + 1 file changed, 1 insertion(+) create mode 100644 utils/__init__.py diff --git a/utils/__init__.py b/utils/__init__.py new file mode 100644 index 0000000..3857fda --- /dev/null +++ b/utils/__init__.py @@ -0,0 +1 @@ +"""Shared utilities for task CLI.""" From 64ca55b4cdc88c4d791e0ab207d1d754a8862bd3 Mon Sep 17 00:00:00 2001 From: autogainz Date: Thu, 19 Feb 2026 11:18:36 -0500 Subject: [PATCH 2/7] feat: extract path helpers to utils/paths.py --- utils/paths.py | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 utils/paths.py diff --git a/utils/paths.py b/utils/paths.py new file mode 100644 index 0000000..ec29514 --- /dev/null +++ b/utils/paths.py @@ -0,0 +1,8 @@ +"""Shared path helpers for task CLI.""" + +from pathlib import Path + + +def get_tasks_file(): + """Get path to tasks file.""" + return Path.home() / ".local" / "share" / "task-cli" / "tasks.json" From aed5e40d9a58d01c213b4e65e23317b751be9f1c Mon Sep 17 00:00:00 2001 From: autogainz Date: Thu, 19 Feb 2026 11:18:40 -0500 Subject: [PATCH 3/7] feat: extract validation functions to utils/validation.py --- utils/validation.py | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 utils/validation.py diff --git a/utils/validation.py b/utils/validation.py new file mode 100644 index 0000000..b226e73 --- /dev/null +++ b/utils/validation.py @@ -0,0 +1,27 @@ +"""Validation helpers for task CLI.""" + +from utils.paths import get_tasks_file + + +def validate_description(description): + """Validate task description.""" + if not description: + raise ValueError("Description cannot be empty") + if len(description) > 200: + raise ValueError("Description too long (max 200 chars)") + return description.strip() + + +def validate_task_file(): + """Validate tasks file exists.""" + tasks_file = get_tasks_file() + if not tasks_file.exists(): + return [] + return tasks_file + + +def validate_task_id(tasks, task_id): + """Validate task ID exists.""" + if task_id < 1 or task_id > len(tasks): + raise ValueError(f"Invalid task ID: {task_id}") + return task_id From 4e6d8e3e4c5e068481f483bc2af5043bc69a95b7 Mon Sep 17 00:00:00 2001 From: autogainz Date: Thu, 19 Feb 2026 11:18:43 -0500 Subject: [PATCH 4/7] refactor: update add.py to use utils --- commands/add.py | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/commands/add.py b/commands/add.py index 1b1a943..dba12e4 100644 --- a/commands/add.py +++ b/commands/add.py @@ -1,22 +1,8 @@ """Add task command.""" import json -from pathlib import Path - - -def get_tasks_file(): - """Get path to tasks file.""" - return Path.home() / ".local" / "share" / "task-cli" / "tasks.json" - - -def validate_description(description): - """Validate task description.""" - # NOTE: Validation logic scattered here - should be in utils (refactor bounty) - if not description: - raise ValueError("Description cannot be empty") - if len(description) > 200: - raise ValueError("Description too long (max 200 chars)") - return description.strip() +from utils.paths import get_tasks_file +from utils.validation import validate_description def add_task(description): From 4974e168e1c064f2c11f0bc7a6062dc730adb319 Mon Sep 17 00:00:00 2001 From: autogainz Date: Thu, 19 Feb 2026 11:18:46 -0500 Subject: [PATCH 5/7] refactor: update list.py to use utils --- commands/list.py | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/commands/list.py b/commands/list.py index 714315d..b4584c3 100644 --- a/commands/list.py +++ b/commands/list.py @@ -1,26 +1,12 @@ """List tasks command.""" import json -from pathlib import Path - - -def get_tasks_file(): - """Get path to tasks file.""" - return Path.home() / ".local" / "share" / "task-cli" / "tasks.json" - - -def validate_task_file(): - """Validate tasks file exists.""" - # NOTE: Validation logic scattered here - should be in utils (refactor bounty) - tasks_file = get_tasks_file() - if not tasks_file.exists(): - return [] - return tasks_file +from utils.paths import get_tasks_file +from utils.validation import validate_task_file def list_tasks(): """List all tasks.""" - # NOTE: No --json flag support yet (feature bounty) tasks_file = validate_task_file() if not tasks_file: print("No tasks yet!") From 1d8a7d39062c1c771d84900f54e81527a4c6fffe Mon Sep 17 00:00:00 2001 From: autogainz Date: Thu, 19 Feb 2026 11:18:48 -0500 Subject: [PATCH 6/7] refactor: update done.py to use utils --- commands/done.py | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/commands/done.py b/commands/done.py index c9dfd42..995f058 100644 --- a/commands/done.py +++ b/commands/done.py @@ -1,20 +1,8 @@ """Mark task done command.""" import json -from pathlib import Path - - -def get_tasks_file(): - """Get path to tasks file.""" - return Path.home() / ".local" / "share" / "task-cli" / "tasks.json" - - -def validate_task_id(tasks, task_id): - """Validate task ID exists.""" - # NOTE: Validation logic scattered here - should be in utils (refactor bounty) - if task_id < 1 or task_id > len(tasks): - raise ValueError(f"Invalid task ID: {task_id}") - return task_id +from utils.paths import get_tasks_file +from utils.validation import validate_task_id def mark_done(task_id): From 584b450fb85427828ea145667109b2a15d8ff780 Mon Sep 17 00:00:00 2001 From: autogainz Date: Thu, 19 Feb 2026 11:18:52 -0500 Subject: [PATCH 7/7] refactor: update test imports to use utils --- test_task.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test_task.py b/test_task.py index ba98e43..af8e67b 100644 --- a/test_task.py +++ b/test_task.py @@ -3,8 +3,7 @@ import json import pytest from pathlib import Path -from commands.add import add_task, validate_description -from commands.done import validate_task_id +from utils.validation import validate_description, validate_task_id def test_validate_description():