From f55d1ded998afbe632c085b7cd630053f6ac1f9c Mon Sep 17 00:00:00 2001 From: V1ki Date: Fri, 27 Feb 2026 10:01:57 +0800 Subject: [PATCH] fix: gracefully handle missing config file (#2) - Create default config at ~/.config/task-cli/config.yaml if absent - Print informative message to stderr on first run - Add tests for missing config, existing config, and no-crash guarantee Fixes #2 --- task.py | 22 ++++++++++++++++++++-- test_task.py | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 2 deletions(-) diff --git a/task.py b/task.py index 53cc8ed..3d25e06 100644 --- a/task.py +++ b/task.py @@ -10,10 +10,28 @@ from commands.done import mark_done +DEFAULT_CONFIG = """\ +# Configuration for task CLI + +# Task storage settings +storage: + format: json + max_tasks: 1000 + +# Display settings +display: + color: true + unicode: true +""" + + def load_config(): - """Load configuration from file.""" + """Load configuration from file, creating a default if it doesn't exist.""" config_path = Path.home() / ".config" / "task-cli" / "config.yaml" - # NOTE: This will crash if config doesn't exist - known bug for bounty testing + if not config_path.exists(): + config_path.parent.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() diff --git a/test_task.py b/test_task.py index ba98e43..1dce5cc 100644 --- a/test_task.py +++ b/test_task.py @@ -1,10 +1,13 @@ """Basic tests for task CLI.""" import json +import sys 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,34 @@ def test_validate_task_id(): with pytest.raises(ValueError): validate_task_id(tasks, 99) + + +def test_load_config_creates_default_when_missing(tmp_path): + """load_config() should create a default config if none exists.""" + fake_config = tmp_path / ".config" / "task-cli" / "config.yaml" + with patch("task.Path.home", return_value=tmp_path): + content = load_config() + assert fake_config.exists(), "Config file should have been created" + assert "storage" in content + + +def test_load_config_reads_existing(tmp_path): + """load_config() should return existing config content without overwriting.""" + config_dir = tmp_path / ".config" / "task-cli" + config_dir.mkdir(parents=True) + config_file = config_dir / "config.yaml" + config_file.write_text("storage:\n max_tasks: 42\n") + with patch("task.Path.home", return_value=tmp_path): + content = load_config() + assert "max_tasks: 42" in content + + +def test_load_config_no_crash_when_missing(tmp_path, capsys): + """load_config() must not raise FileNotFoundError when config is absent.""" + with patch("task.Path.home", return_value=tmp_path): + try: + load_config() + except FileNotFoundError: + pytest.fail("load_config() raised FileNotFoundError when config was missing") + captured = capsys.readouterr() + assert "Created default config" in captured.err