From 8394f532e7bb19c9db6d3f25de3e9c2449afea50 Mon Sep 17 00:00:00 2001 From: DrGalio Date: Thu, 26 Mar 2026 14:03:44 +0000 Subject: [PATCH] fix: handle missing config file gracefully When ~/.config/task-cli/config.yaml doesn't exist, load_config() now creates a default config file instead of crashing with FileNotFoundError. Changes: - load_config() creates default config if missing - Wired load_config() into main() so config is loaded on startup - Added tests for missing config and existing config scenarios Fixes #2 --- .gitignore | 2 ++ task.py | 28 +++++++++++++++++++++++++--- test_task.py | 38 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 65 insertions(+), 3 deletions(-) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7a60b85 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +__pycache__/ +*.pyc diff --git a/task.py b/task.py index 53cc8ed..8abf70e 100644 --- a/task.py +++ b/task.py @@ -3,17 +3,36 @@ import argparse import sys +import shutil from pathlib import Path from commands.add import add_task from commands.list import list_tasks from commands.done import mark_done +DEFAULT_CONFIG = """# Task CLI configuration +storage: + format: json + max_tasks: 1000 +display: + color: true + unicode: true +""" + def load_config(): - """Load configuration from file.""" - config_path = Path.home() / ".config" / "task-cli" / "config.yaml" - # NOTE: This will crash if config doesn't exist - known bug for bounty testing + """Load configuration from file. + + If the config file doesn't exist, creates a default config and returns it. + """ + config_dir = Path.home() / ".config" / "task-cli" + config_path = config_dir / "config.yaml" + + if not config_path.exists(): + config_dir.mkdir(parents=True, exist_ok=True) + config_path.write_text(DEFAULT_CONFIG) + print(f"Created default config at {config_path}", file=sys.stderr) + with open(config_path) as f: return f.read() @@ -35,6 +54,9 @@ def main(): args = parser.parse_args() + # Load config (creates default if missing) + load_config() + if args.command == "add": add_task(args.description) elif args.command == "list": diff --git a/test_task.py b/test_task.py index ba98e43..29c9a5b 100644 --- a/test_task.py +++ b/test_task.py @@ -1,10 +1,13 @@ """Basic tests for task CLI.""" import json +import os import pytest from pathlib import Path +from unittest.mock import patch from commands.add import add_task, validate_description from commands.done import validate_task_id +from task import load_config, DEFAULT_CONFIG def test_validate_description(): @@ -28,3 +31,38 @@ def test_validate_task_id(): with pytest.raises(ValueError): validate_task_id(tasks, 99) + + +def test_load_config_creates_default_when_missing(tmp_path, monkeypatch): + """Test that load_config creates a default config when file is missing.""" + fake_home = tmp_path + monkeypatch.setattr(Path, "home", lambda: fake_home) + + config_dir = fake_home / ".config" / "task-cli" + config_path = config_dir / "config.yaml" + + # Ensure it doesn't exist + assert not config_path.exists() + + result = load_config() + + # Should have created the file + assert config_path.exists() + assert "storage:" in result + assert "format: json" in result + + +def test_load_config_reads_existing_file(tmp_path, monkeypatch): + """Test that load_config reads existing config without overwriting.""" + fake_home = tmp_path + monkeypatch.setattr(Path, "home", lambda: fake_home) + + config_dir = fake_home / ".config" / "task-cli" + config_dir.mkdir(parents=True) + config_path = config_dir / "config.yaml" + custom_config = "storage:\n format: yaml\n" + config_path.write_text(custom_config) + + result = load_config() + + assert result == custom_config