feat: add daily report - #7
Conversation
Code Review:
|
| File | Added | Changed | Purpose |
|---|---|---|---|
timetracker_utils/report.py |
✨ New | — | Daily/range text reports and matplotlib bar charts |
timetracker_utils/csv_formatters.py |
✨ New | — | TimeCop and SimpleTimeTracker CSV export |
timetracker_utils/datetime_utils.py |
— | ✅ Extended | Added aggregate_by_date() and _parse_list_field() |
timetracker_utils/cli.py |
— | ✅ Refactored | report command, export improvements, cleanup |
tests/test_cli.py |
— | ✅ Extended | 482 lines added for report/export/bar tests |
tests/test_datetime_utils.py |
— | ✅ Extended | aggregate_by_date() tests |
pyproject.toml |
— | ✅ Tweaked | Python 3.13 classifier added |
uv.lock |
— | ✅ Updated | Dependency lockfile |
Strengths
1. 🧪 Excellent Test Coverage (96.7%)
All modules except report.py (77%) achieve 100% coverage. Tests are well-structured, cover edge cases, and mock external dependencies (matplotlib) appropriately.
2. 🏗️ Clean Architecture
- Base class pattern (
BaseTimeEntry/BaseTimeTracker) provides clean inheritance for format-specific implementations (TimeCop,SimpleTimeTracker). - Separation of concerns: Parsing, persistence, export, reporting, and CLI are well-separated.
- No circular dependencies detected.
3. 🔤 Comprehensive Type Hints
Nearly all functions and class members have full type annotations. The project enforces disallow_untyped_defs = true in mypy config.
4. 📚 Documentation
Google-style docstrings on all public APIs. README is thorough with installation, usage examples, and CLI commands.
5. 🛠️ Developer Experience
Well-configured pyproject.toml with ruff, mypy, and pytest. GitHub Actions CI runs all quality gates.
6. 🎯 Edge Case Handling
Strong handling of BOM characters, None DictReader values, timezone-naive vs aware datetimes, merge conflict detection, and empty DataFrames.
Issues & Recommendations
🔴 High Severity — None found.
All 281 tests pass. The code is functionally correct.
🟡 Medium Severity
1. report.py below 95% coverage threshold (77%)
- File:
/sandbox/GitHub/timetracker-utils/timetracker_utils/report.py - Suggestion: Add tests for untested matplotlib code paths (
_show_bar_single,_show_bar_range,_import_matplotlib).
2. mypy type error in test file
- File:
/sandbox/GitHub/timetracker-utils/tests/test_cli.py:1262 - Error:
Function is missing a return type annotation [no-untyped-def] - Suggestion: Add
-> tuple[mock.MagicMock, mock.MagicMock]to_make_mock_plt().
🟢 Low Severity / Suggestions
3. Code duplication in datetime formatting
- File:
/sandbox/GitHub/timetracker-utils/timetracker_utils/csv_formatters.py _format_datetime_iso(lines 19–48) and_format_simple_datetime(lines 189–218) share ~90% identical logic.- Suggestion: Extract a shared
_format_datetime(dt, target_tz)helper.
4. _parse_date_arg module boundary
- Defined in:
report.py(line 22), imported/re-exported bycli.py. - Suggestion: Either define in
cli.pyor havetest_cli.pyimport fromreportdirectly.
5. warnings.filterwarnings at module level
- File:
/sandbox/GitHub/timetracker-utils/timetracker_utils/base_tracker.py, lines 25–29 - Suggestion: Use
warnings.catch_warnings()context manager instead of global suppression.
6. _merge_dataframes complexity
- File:
/sandbox/GitHub/timetracker-utils/timetracker_utils/database.py, lines 314–381 (~68 lines) - Suggestion: Extract inner loop into a helper like
_process_incoming_row.
7. model_config as plain dict vs. ConfigDict
- Suggestion: Use
from pydantic import ConfigDictandmodel_config = ConfigDict(...)for better IDE support.
8. CLI add command format branching
- File:
/sandbox/GitHub/timetracker-utils/timetracker_utils/cli.py, lines 79–107 - Suggestion: Use a format-to-class mapping dict instead of duplicated branches.
9. _seconds_to_hhmm cross-module import
- Defined in
csv_formatters.py, used byreport.pyandcli.py. - Suggestion: Move to
datetime_utils.pyas a general utility.
10. _compute_hours / _compute_simple_duration overlap
- File:
csv_formatters.pylines 51–75 and 221–247 share datetime parsing.
📝 Nitpicks
cli.pylines 60–61:_ = TimeCop/_ = SimpleTimeTracker— use# noqa: F401on imports instead.pyproject.tomlline 15: Remove trailing# Addeddevelopment artifact.
Test Results Summary
| Suite | Tests | Status |
|---|---|---|
test_base_tracker.py |
39 | ✅ Passed |
test_cli.py |
76 | ✅ Passed |
test_config.py |
11 | ✅ Passed |
test_database.py |
49 | ✅ Passed |
test_datetime_utils.py |
35 | ✅ Passed |
test_simple_time_tracker.py |
46 | ✅ Passed |
test_time_cop.py |
25 | ✅ Passed |
| Total | 281 | ✅ All passed |
Quality Gate Checks
| Check | Result |
|---|---|
uv run pytest (281 tests) |
✅ Passed, 96.7% coverage |
uv run ruff check . |
✅ All checks passed |
uv run mypy . |
test_cli.py:1262 |
Conclusion
This is a well-engineered feature branch. The report generation system is cleanly designed, CSV export formatters are comprehensive, and test coverage is excellent. The code maintains the high quality bar set by the existing codebase.
Recommended actions before merging:
- (Low effort) Fix the mypy error in
test_cli.py:1262 - (Low effort) Remove the
# Addedcomment frompyproject.tomlline 15 - (Medium effort) Consider adding coverage for
report.pyto meet the 95% threshold
None of these are blocking — the branch is in good shape for merge.
Adds a new
reportCLI command that generates daily summaries of time tracking data, along with supporting datetime utilities and comprehensive test coverage.What's New
reportcommand — Generate a daily report for any date, showing:hh:mm)Usage:
Key Changes
timetracker_utils/cli.py: Addedreportcommand and_seconds_to_hhmmhelper; fixed timezone offset formatting to handleNoneoffsets gracefullytimetracker_utils/datetime_utils.py: Addedaggregate_by_date()for timezone-aware date filtering and breakdown aggregation; added_parse_list_field()for robust tag/category parsing from DBtests/test_cli.py: Added integration tests for thereportcommandtests/test_datetime_utils.py: Added unit tests foraggregate_by_date,_parse_list_field, and edge cases (empty data, midnight-crossing entries, timezone handling)Notes