feat(models): Task dataclass replaces TypedDict cast zoo (Issue #ARCH-24)#1007
Merged
feat(models): Task dataclass replaces TypedDict cast zoo (Issue #ARCH-24)#1007
Conversation
…o (Issue #ARCH-24) Introduce a proper Document domain object (@DataClass) that replaces the scattered TypedDict projections (DocumentRow, DocumentListItem, RecentDocumentItem, DeletedDocumentItem, ChildDocumentItem, SupersedeCandidate) with a single type constructed via factory methods. Phase 1 — Document dataclass (emdx/models/document.py): - @DataClass(slots=True) with all 15 document fields - from_row() / from_partial_row() factories with datetime parsing - __getitem__ / .get() / keys() / items() dict-compat layer so all 158 existing bracket-access sites keep working - to_dict() with datetime→ISO serialization for JSON output - 31 unit tests covering construction, parsing, compat, serialization Phase 1b — SearchHit dataclass (emdx/models/search.py): - Wraps Document + snippet + rank for search results - Same dict-compat interface with field fallthrough Phase 2 — Wire into database layer: - database/documents.py: all functions return Document instead of TypedDict casts. Removed _parse_doc_datetimes() (absorbed into Document.from_row()) - database/search.py: returns list[SearchHit] instead of list[SearchResult] - database/__init__.py: SQLiteDatabase methods updated to return Document / SearchHit - commands/context.py: switched from DocumentRow to Document 25 cast() calls eliminated. 2068 tests passing, zero breakage. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…CH-24) Phase 3 of the data model refactor — migrate bracket access to attribute access across 10 consumer files and 9 test files. Converted files: - commands/core.py (43 sites — display_save_result, view, edit, delete, _find_all, _find_recent, _view_review, _print_view_header_*) - commands/context.py, history.py, tags.py, tasks.py, wiki.py, gist.py, briefing.py, trash.py - ui/activity/activity_data.py Updated test mocks to return Document objects instead of raw dicts: - test_commands_core.py, test_commands_tags.py, test_commands_trash.py, test_gist.py, test_v028_regressions.py, test_activity_doc_type.py, test_activity_view.py, test_task_commands.py, test_view_review.py Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…y (Issue #ARCH-24) Phase 4 — remove DocumentRow, DocumentListItem, RecentDocumentItem, DeletedDocumentItem, ChildDocumentItem, SupersedeCandidate, and SearchResult from database/types.py. All replaced by the Document dataclass and SearchHit in emdx/models/. Remaining types in database/types.py are non-document structures: MostViewedDoc, DatabaseStats, DocumentLinkDetail, WikiArticleTimingDict, StandingQueryRow, StandingQueryMatch. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…(Issue #ARCH-24) - Create emdx/models/task.py with Task and TaskLogEntry dataclasses - Factory methods from_row()/from_partial_row() with datetime parsing - Dict-compat layer (__getitem__, .get()) for incremental migration - Wire into models/tasks.py: all functions return Task/TaskLogEntry - Migrate consumers: commands/tasks.py, ui/task_view.py type annotations - Fix mypy errors: switch 3 bracket accesses to attribute access - Remove TaskDict, EpicTaskDict, EpicViewDict, TaskLogEntryDict from types.py - Update test factories to use Task.from_row() Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…at needed) Tests mock get_task() with raw dicts, so attribute access like task.epic_key breaks. Restore bracket access via dict-compat layer until test mocks are migrated to Task objects. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Phase 5 of the data model refactor (ARCH-24). Introduces a
Taskdataclass that replaces the scatteredTaskDict/EpicTaskDict/EpicViewDict/TaskLogEntryDictTypedDicts with proper domain model objects.emdx/models/task.py:TaskandTaskLogEntrydataclasses withfrom_row()factory methods, datetime parsing at DB boundary, and dict-compat layer for incremental migrationmodels/tasks.py: All functions returnTask/TaskLogEntryinstead ofcast(TypedDict, dict(row))commands/tasks.py,ui/task_view.pytype annotations updated fromTaskDict→TaskTaskDict,EpicTaskDict,EpicViewDict,TaskLogEntryDictfrommodels/types.pyTask.from_row(), fixed item assignment patternsSame pattern as the Document dataclass (PR #1006):
@dataclass(slots=True),__getitem__/.get()backward compat,to_dict()serialization.Test plan
🤖 Generated with Claude Code