cli: add option to output locations to gpx files (#286)

* cli: add option to output locations to gpx files
This commit is contained in:
seanbreckenridge 2023-04-14 16:31:11 -07:00 committed by GitHub
parent 02c738594f
commit 40de162fab
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 56 additions and 2 deletions

View file

@ -542,6 +542,14 @@ def query_hpi_functions(
pprint(item)
else:
pprint(list(res))
elif output == 'gpx':
from my.location.common import locations_to_gpx
# can ignore the mypy warning here, locations_to_gpx yields any errors
# if you didnt pass it something that matches the LocationProtocol
for exc in locations_to_gpx(res, sys.stdout): # type: ignore[arg-type]
click.echo(str(exc), err=True)
sys.stdout.flush()
else:
res = list(res) # type: ignore[assignment]
# output == 'repl'
@ -681,7 +689,7 @@ def module_install_cmd(user: bool, parallel: bool, modules: Sequence[str]) -> No
@click.option('-o',
'--output',
default='json',
type=click.Choice(['json', 'pprint', 'repl']),
type=click.Choice(['json', 'pprint', 'repl', 'gpx']),
help='what to do with the result [default: json]')
@click.option('-s',
'--stream',

View file

@ -1,5 +1,5 @@
from datetime import date, datetime
from typing import Union, Tuple, Optional
from typing import Union, Tuple, Optional, Iterable, TextIO, Iterator
from dataclasses import dataclass
from my.core import __NOT_HPI_MODULE__
@ -32,3 +32,48 @@ class Location(LocationProtocol):
accuracy: Optional[float]
elevation: Optional[float]
datasource: Optional[str] = None # which module provided this, useful for debugging
def locations_to_gpx(locations: Iterable[LocationProtocol], buffer: TextIO) -> Iterator[Exception]:
"""
Convert locations to a GPX file, printing to a buffer (an open file, io.StringIO, sys.stdout, etc)
"""
try:
import gpxpy.gpx
except ImportError as ie:
from my.core.warnings import warn
warn("gpxpy not installed, cannot write to gpx. 'pip install gpxpy'")
raise ie
gpx = gpxpy.gpx.GPX()
# hmm -- would it be useful to allow the user to split this into tracks?, perhaps by date?
# Create first track in our GPX:
gpx_track = gpxpy.gpx.GPXTrack()
gpx.tracks.append(gpx_track)
# Create first segment in our GPX track:
gpx_segment = gpxpy.gpx.GPXTrackSegment()
gpx_track.segments.append(gpx_segment)
for location in locations:
try:
point = gpxpy.gpx.GPXTrackPoint(
latitude=location.lat,
longitude=location.lon,
elevation=location.elevation,
time=location.dt,
comment=location.datasource,
)
except AttributeError:
yield TypeError(
f"Expected a Location or Location-like object, got {type(location)} {repr(location)}"
)
continue
gpx_segment.points.append(point)
buffer.write(gpx.to_xml())

View file

@ -85,6 +85,7 @@ allowlist_externals = cat
commands =
pip install -e .[testing,optional]
pip install orgparse # used it core.orgmode?
pip install gpxpy # for hpi query --output gpx
{envpython} -m mypy --install-types --non-interactive \
-p my.core \