cli: add option to output locations to gpx files

This commit is contained in:
Sean Breckenridge 2023-04-14 15:52:36 -07:00
parent 02c738594f
commit 87c13defd1
3 changed files with 56 additions and 2 deletions

View file

@ -542,6 +542,14 @@ def query_hpi_functions(
pprint(item) pprint(item)
else: else:
pprint(list(res)) 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 list(locations_to_gpx(res, sys.stdout)): # type: ignore[arg-type]
click.echo(str(exc), err=True)
sys.stdout.flush()
else: else:
res = list(res) # type: ignore[assignment] res = list(res) # type: ignore[assignment]
# output == 'repl' # output == 'repl'
@ -681,7 +689,7 @@ def module_install_cmd(user: bool, parallel: bool, modules: Sequence[str]) -> No
@click.option('-o', @click.option('-o',
'--output', '--output',
default='json', default='json',
type=click.Choice(['json', 'pprint', 'repl']), type=click.Choice(['json', 'pprint', 'repl', 'gpx']),
help='what to do with the result [default: json]') help='what to do with the result [default: json]')
@click.option('-s', @click.option('-s',
'--stream', '--stream',

View file

@ -1,5 +1,5 @@
from datetime import date, datetime 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 dataclasses import dataclass
from my.core import __NOT_HPI_MODULE__ from my.core import __NOT_HPI_MODULE__
@ -32,3 +32,48 @@ class Location(LocationProtocol):
accuracy: Optional[float] accuracy: Optional[float]
elevation: Optional[float] elevation: Optional[float]
datasource: Optional[str] = None # which module provided this, useful for debugging 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 = commands =
pip install -e .[testing,optional] pip install -e .[testing,optional]
pip install orgparse # used it core.orgmode? pip install orgparse # used it core.orgmode?
pip install gpxpy # for hpi query --output gpx
{envpython} -m mypy --install-types --non-interactive \ {envpython} -m mypy --install-types --non-interactive \
-p my.core \ -p my.core \