From 45b6223e168e3aba381ab756c7740cf8237a4d0c Mon Sep 17 00:00:00 2001 From: Lucas Miller Date: Mon, 19 May 2025 00:53:53 -0400 Subject: [PATCH] Add JSON storage and CLI integration --- pyproject.toml | 1 + src/cli.py | 23 +++++++++++++---------- src/mood_logger.py | 25 ++++++++++++++++++++++++- tests/test_storage.py | 15 +++++++++++++++ 4 files changed, 53 insertions(+), 11 deletions(-) create mode 100644 tests/test_storage.py diff --git a/pyproject.toml b/pyproject.toml index 5b580fb..f380663 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -13,3 +13,4 @@ build-backend = "setuptools.build_meta" [tool.pytest.ini_options] minversion = "8.0" testpaths = ["tests"] +addopts = "-q" diff --git a/src/cli.py b/src/cli.py index 090c619..f3a1953 100644 --- a/src/cli.py +++ b/src/cli.py @@ -1,6 +1,6 @@ -import sys +from datetime import date import click -from src.mood_logger import log_mood, latest_entries +from src.mood_logger import MoodEntry, save_entry, load_entries @click.group() def cli(): @@ -12,16 +12,19 @@ def cli(): @click.argument("note", type=str, required=False) def log(rating, note): """Log your mood with RATING (1–10) and optional NOTE.""" - log_mood(rating, note) - click.echo(f"Logged mood {rating}{f' – {note}' if note else ''}") + entry = MoodEntry(date.today().isoformat(), rating, note) + save_entry(entry) + click.echo("Logged!") @cli.command() -@click.option("--n", default=5, help="How many entries to show.") -def latest(n): - """Show the last N mood entries.""" - entries = latest_entries(n) - for e in entries: - click.echo(f"{e.date}: {e.rating} – {e.note or ''}") +def latest(): + """Show the most recent mood entry.""" + entries = load_entries() + if not entries: + click.echo("No entries found.") + return + e = entries[-1] + click.echo(f"{e.date}: {e.rating}{f' – {e.note}' if e.note else ''}") if __name__ == "__main__": cli() diff --git a/src/mood_logger.py b/src/mood_logger.py index 261130a..4a079aa 100644 --- a/src/mood_logger.py +++ b/src/mood_logger.py @@ -1,6 +1,7 @@ -from dataclasses import dataclass +from dataclasses import dataclass, asdict from datetime import date import csv +import json from pathlib import Path from typing import List, Optional @@ -11,6 +12,9 @@ class MoodEntry: rating: int note: Optional[str] = None +# Default JSON data file stored at the repository root +DATA_FILE = Path(__file__).resolve().parent.parent / "moods.json" + def log_mood( rating: int, note: Optional[str] = None, @@ -50,3 +54,22 @@ def latest_entries( for row in rows ] return entries[-n:] + + +def load_entries() -> List[MoodEntry]: + """Load all mood entries from the JSON ``DATA_FILE``.""" + path = Path(DATA_FILE) + if not path.exists(): + return [] + with path.open() as f: + data = json.load(f) + return [MoodEntry(**item) for item in data] + + +def save_entry(entry: MoodEntry) -> None: + """Append ``entry`` to ``DATA_FILE``.""" + path = Path(DATA_FILE) + entries = load_entries() + entries.append(entry) + with path.open("w") as f: + json.dump([asdict(e) for e in entries], f) diff --git a/tests/test_storage.py b/tests/test_storage.py new file mode 100644 index 0000000..86a53f9 --- /dev/null +++ b/tests/test_storage.py @@ -0,0 +1,15 @@ +from datetime import date +from src import mood_logger + + +def test_save_and_load_round_trip(tmp_path, monkeypatch): + data_file = tmp_path / "moods.json" + monkeypatch.setattr(mood_logger, "DATA_FILE", data_file) + + entry = mood_logger.MoodEntry(date.today().isoformat(), 8, "feeling good") + mood_logger.save_entry(entry) + + assert data_file.exists() + + loaded = mood_logger.load_entries() + assert loaded == [entry]