From 33e8868bdbb62997bb25c27d9b9cb19ba861ae12 Mon Sep 17 00:00:00 2001 From: tarai Date: Thu, 16 Apr 2026 23:28:46 +0000 Subject: [PATCH] refactor: #3 extract validation and path helpers to utils module - Create utils/__init__.py, utils/validation.py, utils/paths.py - Move get_tasks_file() to utils/paths.py (was duplicated in 3 files) - Move validate_description(), validate_task_id(), validate_task_file() to utils/validation.py - Update commands/add.py, commands/done.py, commands/list.py to import from utils - Update test imports to use utils.validation - Add .gitignore for __pycache__/, *.pyc, .pytest_cache/ - All tests pass, no behavior changes Fixes #3 --- .gitignore | 3 +++ commands/add.py | 18 ++---------------- commands/done.py | 16 ++-------------- commands/list.py | 16 +--------------- test_task.py | 5 +---- utils/__init__.py | 1 + utils/paths.py | 8 ++++++++ utils/validation.py | 27 +++++++++++++++++++++++++++ 8 files changed, 45 insertions(+), 49 deletions(-) create mode 100644 .gitignore create mode 100644 utils/__init__.py create mode 100644 utils/paths.py create mode 100644 utils/validation.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..75c6182 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +__pycache__/ +*.pyc +.pytest_cache/ 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): 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): diff --git a/commands/list.py b/commands/list.py index 714315d..41fd9c8 100644 --- a/commands/list.py +++ b/commands/list.py @@ -1,21 +1,7 @@ """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.validation import validate_task_file def list_tasks(): diff --git a/test_task.py b/test_task.py index ba98e43..f4a4885 100644 --- a/test_task.py +++ b/test_task.py @@ -1,10 +1,7 @@ """Basic tests for task CLI.""" -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(): 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.""" 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" diff --git a/utils/validation.py b/utils/validation.py new file mode 100644 index 0000000..8ac2c2e --- /dev/null +++ b/utils/validation.py @@ -0,0 +1,27 @@ +"""Shared validation logic 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_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 + + +def validate_task_file(): + """Validate tasks file exists.""" + tasks_file = get_tasks_file() + if not tasks_file.exists(): + return [] + return tasks_file