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) 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 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 \