[locations] Handle log data cleaner
All checks were successful
build / test (push) Successful in 1m54s
All checks were successful
build / test (push) Successful in 1m54s
This commit is contained in:
13
PROJECT.org
13
PROJECT.org
@ -88,7 +88,7 @@ fetching and simple saving.
|
|||||||
*** Metadata sources
|
*** Metadata sources
|
||||||
**** Scraper
|
**** 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:
|
** TODO [#C] Create small utility to clean up tracks scrobbled with wonky playback times :bug:music:scrobbles:
|
||||||
:PROPERTIES:
|
:PROPERTIES:
|
||||||
:ID: 702462cf-d54b-48c6-8a7c-78b8de751deb
|
:ID: 702462cf-d54b-48c6-8a7c-78b8de751deb
|
||||||
@ -594,6 +594,17 @@ named constants for maintainability.
|
|||||||
- ~vrobbler/apps/webpages/models.py~ (line 290) -- ="url"=
|
- ~vrobbler/apps/webpages/models.py~ (line 290) -- ="url"=
|
||||||
- ~vrobbler/apps/scrobbles/importers/tsv.py~ (line 55) -- ="S"= completion status
|
- ~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:
|
** DONE [#B] Webpage scrobbles should diff existing webpages content :webpages:metadata:
|
||||||
:PROPERTIES:
|
:PROPERTIES:
|
||||||
:ID: 25576197-258f-48d6-bfe9-e4172a0a1898
|
:ID: 25576197-258f-48d6-bfe9-e4172a0a1898
|
||||||
|
|||||||
@ -28,6 +28,14 @@ class GeoLocationLogData(BaseLogData, WithPeopleLogData):
|
|||||||
activity: str = ""
|
activity: str = ""
|
||||||
detected_at: 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):
|
class GeoLocation(ScrobblableMixin):
|
||||||
COMPLETION_PERCENT = getattr(settings, "LOCATION_COMPLETION_PERCENT", 100)
|
COMPLETION_PERCENT = getattr(settings, "LOCATION_COMPLETION_PERCENT", 100)
|
||||||
|
|||||||
@ -50,6 +50,18 @@ class BaseLogData(JSONDataclass):
|
|||||||
def override_fields(cls) -> dict:
|
def override_fields(cls) -> dict:
|
||||||
return {}
|
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:
|
def notes_as_str(self, separator: str = " | ") -> str:
|
||||||
import html
|
import html
|
||||||
import re
|
import re
|
||||||
|
|||||||
@ -973,24 +973,8 @@ class Scrobble(TimeStampedModel):
|
|||||||
if not log_dict:
|
if not log_dict:
|
||||||
log_dict = {}
|
log_dict = {}
|
||||||
|
|
||||||
# Special handling for GeoLocationLogData - data is nested under 'movement_detection'
|
# Use LogData's from_log_dict to handle any custom nesting/structure
|
||||||
# TODO there's a better way to fix this this at the LogData level
|
logdata_kwargs = logdata_cls.from_log_dict(log_dict)
|
||||||
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__
|
|
||||||
}
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
return logdata_cls(**logdata_kwargs)
|
return logdata_cls(**logdata_kwargs)
|
||||||
|
|||||||
Reference in New Issue
Block a user