Skip to content

Commit 90d118c

Browse files
committed
refactor: explicit attribute initialization for last_changed_field
Initialize _last_changed_field and _last_changed_paths explicitly in __init__ with proper type annotations. Direct attribute access only - no getattr. Changes: - Add explicit initialization in __init__ section - Property returns self._last_changed_field directly - Remove last_dirty_field property (unused) - Set _last_changed_field = None when no changes Attributes are structure, not data. No dynamic attribute access.
1 parent 285ec5f commit 90d118c

1 file changed

Lines changed: 10 additions & 12 deletions

File tree

src/objectstate/object_state.py

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1578,6 +1578,12 @@ def __init__(
15781578
self._dirty_fields: Set[str] = set()
15791579
self._signature_diff_fields: Set[str] = set()
15801580

1581+
# === Change tracking for navigation (2 attributes) ===
1582+
# Track which field most recently changed VALUE (not just dirty status)
1583+
# Used for time-travel navigation to scroll to what changed in a transition
1584+
self._last_changed_field: Optional[str] = None
1585+
self._last_changed_paths: Set[str] = set()
1586+
15811587
# === Flags (kept for batch operations) ===
15821588
self._in_reset = False
15831589
self._block_cross_window_updates = False
@@ -2425,16 +2431,18 @@ def _recompute_invalid_fields(self) -> Set[str]:
24252431
changed_paths,
24262432
key=lambda field: (field == "func", -field.count("."), field),
24272433
)[0]
2434+
else:
2435+
self._last_changed_field = None
24282436
return changed_paths
24292437

24302438
@property
24312439
def last_changed_field(self) -> Optional[str]:
24322440
"""Field that most recently changed value (not just dirty status).
2433-
2441+
24342442
This tracks any value change regardless of saved/unsaved state,
24352443
useful for time-travel navigation to show what changed in a transition.
24362444
"""
2437-
return getattr(self, "_last_changed_field", None)
2445+
return self._last_changed_field
24382446

24392447
def reset_parameter(self, param_name: str) -> None:
24402448
"""Reset parameter to signature default (None for lazy dataclasses).
@@ -2472,10 +2480,6 @@ def dirty_fields(self) -> Set[str]:
24722480
"""Fields where resolved_live != resolved_saved."""
24732481
return self._dirty_fields
24742482

2475-
@property
2476-
def last_dirty_field(self) -> Optional[str]:
2477-
return getattr(self, "_last_dirty_field", None)
2478-
24792483
@property
24802484
def signature_diff_fields(self) -> Set[str]:
24812485
"""Fields where raw != signature_default."""
@@ -2551,12 +2555,6 @@ def _update_dirty_fields(self) -> Set[str]:
25512555
# Symmetric difference: fields that changed dirty status in either direction
25522556
changed_fields = new_dirty ^ self._dirty_fields
25532557
self._dirty_fields = new_dirty
2554-
# Track latest changed field for navigation (prefer deterministic choice)
2555-
if changed_fields:
2556-
self._last_dirty_field = sorted(
2557-
changed_fields,
2558-
key=lambda field: (field == "func", -field.count("."), field),
2559-
)[0]
25602558
return changed_fields
25612559
return set()
25622560

0 commit comments

Comments
 (0)