Skip to content

Commit

Permalink
_parse_semantic_location_history: handle missing placeId in otherCand…
Browse files Browse the repository at this point in the history
…idateLocations (#71)

should resolve #57
  • Loading branch information
karlicoss authored Sep 12, 2024
1 parent 60e230e commit 5d4304d
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 5 deletions.
21 changes: 19 additions & 2 deletions google_takeout_parser/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -194,16 +194,33 @@ class CandidateLocation:
lng: float
address: Optional[str]
name: Optional[str]
placeId: str

placeId: Optional[str]
"""
Sometimes missing, in this case semanticType is set
"""

semanticType: Optional[str]
"""
Something like TYPE_HOME or TYPE_WORK or TYPE_ALIAS
"""

locationConfidence: Optional[float] # missing in older (around 2014/15) history
sourceInfoDeviceTag: Optional[int]

@classmethod
def from_dict(cls, data: Dict[str, Any]) -> CandidateLocation:
placeId = data.get("placeId")
semanticType = data.get("semanticType")
if placeId is None:
# at least one of them should be present
assert semanticType is not None, data

return cls(
address=data.get("address"),
name=data.get("name"),
placeId=data["placeId"],
placeId=placeId,
semanticType=semanticType,
locationConfidence=data.get("locationConfidence"),
lat=data["latitudeE7"] / 1e7,
lng=data["longitudeE7"] / 1e7,
Expand Down
4 changes: 3 additions & 1 deletion google_takeout_parser/parse_json.py
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,8 @@ def _parse_semantic_location_history(p: Path) -> Iterator[Res[PlaceVisit]]:
)
continue
location = CandidateLocation.from_dict(location_json)
placeId = location.placeId
assert placeId is not None, location_json # this is always present for the actual location
duration = placeVisit["duration"]
yield PlaceVisit(
name=location.name,
Expand All @@ -213,7 +215,7 @@ def _parse_semantic_location_history(p: Path) -> Iterator[Res[PlaceVisit]]:
placeVisitType=placeVisit.get("placeVisitType"),
visitConfidence=placeVisit.get("visitConfidence"),
editConfirmationStatus=placeVisit.get("editConfirmationStatus"),
placeId=location.placeId,
placeId=placeId,
lng=location.lng,
lat=location.lat,
centerLat=(
Expand Down
21 changes: 19 additions & 2 deletions tests/test_json.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ def test_chrome_history(tmp_path_f: Path) -> None:
]


# FIXME add test here
def test_semantic_location_history(tmp_path_f: Path) -> None:
data = {
"timelineObjects": [
Expand Down Expand Up @@ -177,7 +178,12 @@ def test_semantic_location_history(tmp_path_f: Path) -> None:
"address": "address2",
"name": "name2",
"locationConfidence": 24.475897,
}
},
{
"latitudeE7": 910000000,
"longitudeE7": -1000,
"semanticType": "TYPE_WORK",
},
],
"editConfirmationStatus": "NOT_CONFIRMED",
"locationConfidence": 55,
Expand Down Expand Up @@ -222,7 +228,18 @@ def test_semantic_location_history(tmp_path_f: Path) -> None:
address="address2",
locationConfidence=24.475897,
placeId="XPRK4E4P",
semanticType=None,
sourceInfoDeviceTag=None,
)
),
models.CandidateLocation(
lat=91.0,
lng=-0.0001,
name=None,
address=None,
locationConfidence=None,
placeId=None,
semanticType='TYPE_WORK',
sourceInfoDeviceTag=None,
),
],
)

0 comments on commit 5d4304d

Please sign in to comment.