my.moves provides source-faithful Python access to an original
Moves data export. Moves was a
location diary acquired by Facebook and discontinued in 2018.
The provider reads the original outer ZIP directly and exposes days, segments, activities, and track points. Every object retains its complete decoded JSON mapping and a reference to its archive, nested ZIP member, and source indices.
It deliberately does not merge Moves with Google, infer visits or workouts, reverse geocode coordinates, or create a database. Those are downstream policy decisions; the export remains the immutable authority.
HPI uses a PEP 420 namespace package, so
this repository and upstream HPI install together under the same my package:
python -m pip install "git+https://github.com/AndrewSB/HPI-moves"For an editable development install:
git clone https://github.com/AndrewSB/HPI-moves
python -m pip install -e "./HPI-moves[testing]"Add the archive to your normal HPI configuration, usually
~/.config/my/my/config/__init__.py:
class moves:
export_path = "/path/to/moves_export.zip"Use a stable, access-restricted copy of the original outer ZIP. The provider opens it read-only and never rewrites it.
from my.moves import days, stats
print(stats())
for result in days():
if isinstance(result, Exception):
print(result)
continue
print(result.date, len(tuple(result.segments())))The public providers are:
inputs()
days()
segments()
activities()
trackpoints()
stats()days(), segments(), activities(), and trackpoints() yield HPI
Res values: either a source object or an exception. A malformed daily member
therefore does not hide valid members elsewhere in the archive.
Only json/daily/storyline/storyline_YYYYMMDD.json is parsed. Moves repeats the
same underlying history at weekly, monthly, yearly, and full-export
granularities and in alternate formats; reading those as independent sources
would create duplicates.
Moves archives contain precise coordinates, timestamps, movement
classifications, place IDs, and personal place names. Keep the archive private,
avoid printing raw objects in routine diagnostics, and prefer content-free
aggregate queries such as stats().
The tests generate a tiny synthetic nested ZIP at runtime. They contain no data copied or transformed from a real export.
python -m pip install -e ".[testing]"
pytest
ruff check my tests
ruff format --check my tests
mypy my/moves.py
ty check my/moves.py tests/test_moves.py