This commit has no recorded session.
diff
commit 6a8432c08f6bd2083e3da48101d841e61166b9c3Author: Colin Powell <colin@unbl.ink>Date: Tue Jun 16 10:12:58 2026 -0400 [locations] Handle log data cleaner@@ -88,7 +88,7 @@ fetching and simple saving. *** Metadata sources **** Scraper -* Backlog [2/22] :vrobbler:project:personal:+* Backlog [3/23] :vrobbler:project:personal: ** TODO [#C] Create small utility to clean up tracks scrobbled with wonky playback times :bug:music:scrobbles: :PROPERTIES: :ID: 702462cf-d54b-48c6-8a7c-78b8de751deb@@ -594,6 +594,17 @@ named constants for maintainability. - ~vrobbler/apps/webpages/models.py~ (line 290) -- ="url"= - ~vrobbler/apps/scrobbles/importers/tsv.py~ (line 55) -- ="S"= completion status + +** DONE [#C] Cleaner =GeoLocationLogData= deserialization :models:refactoring:+:PROPERTIES:+:ID: 85465dbf-69b3-48cb-9df0-cd076c4470ab+:END:++*** Description +Currently special-cases =GeoLocationLogData= by reaching into a nested ="movement_detection"= key. Should be handled at the LogData dataclass level.+ +File: ~vrobbler/apps/scrobbles/models.py~ (line 977)+ ** DONE [#B] Webpage scrobbles should diff existing webpages content :webpages:metadata: :PROPERTIES: :ID: 25576197-258f-48d6-bfe9-e4172a0a1898@@ -28,6 +28,14 @@ class GeoLocationLogData(BaseLogData, WithPeopleLogData): activity: str = "" detected_at: str = "" + @classmethod+ def from_log_dict(cls, log_dict: dict) -> dict:+ instance_data = log_dict.get("movement_detection", {}).copy()+ for field_name in ["description", "notes", "with_people_ids"]:+ if field_name in log_dict:+ instance_data[field_name] = log_dict[field_name]+ return instance_data+ class GeoLocation(ScrobblableMixin): COMPLETION_PERCENT = getattr(settings, "LOCATION_COMPLETION_PERCENT", 100)@@ -50,6 +50,18 @@ class BaseLogData(JSONDataclass): def override_fields(cls) -> dict: return {} + @classmethod+ def from_log_dict(cls, log_dict: dict) -> dict:+ """Extract LogData keyword arguments from a stored log dict.++ Override in subclasses to handle custom nesting/structure.+ """+ return {+ k: v+ for k, v in log_dict.items()+ if k in cls.__dataclass_fields__+ }+ def notes_as_str(self, separator: str = " | ") -> str: import html import re@@ -973,24 +973,8 @@ class Scrobble(TimeStampedModel): if not log_dict: log_dict = {} - # Special handling for GeoLocationLogData - data is nested under 'movement_detection'- # TODO there's a better way to fix this this at the LogData level- if logdata_cls.__name__ == "GeoLocationLogData":- instance_data = log_dict.get("movement_detection", {}).copy()- # Add top-level fields that GeoLocationLogData expects from BaseLogData/WithPeopleLogData- for field_name in ["description", "notes", "with_people_ids"]:- if field_name in log_dict:- instance_data[field_name] = log_dict[field_name]- try:- return logdata_cls(**instance_data)- except Exception as e:- logger.warning("Log data could not be loaded", e)- return logdata_cls()-- # Strip log-only keys (stored in JSONField but not part of LogData dataclass)- logdata_kwargs = {- k: v for k, v in log_dict.items() if k in logdata_cls().__dataclass_fields__- }+ # Use LogData's from_log_dict to handle any custom nesting/structure+ logdata_kwargs = logdata_cls.from_log_dict(log_dict) try: return logdata_cls(**logdata_kwargs)