Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 2 commits into from
Apr 14, 2023

Conversation

purarue
Copy link
Contributor

@purarue purarue commented Apr 10, 2023

This adds an --output gpx option to hpi query that will output anything that
looks like a LocationProtocol to GPX on stdout

Found a nice GUI tool to quickly preview GPX files: https://github.com/tumic0/GPXSee

hpi query my.location.gpslogger --recent 1w -o gpx >out.gpx; gpxsee out.gpx

@purarue
Copy link
Contributor Author

purarue commented Apr 10, 2023

Ah, looks like lxml type info was updated, so this now fails since .get is optional?:

Should I change the NamedTuple definitions to reflect that?

my/smscalls.py:45: error: Argument 1 to "_parse_dt_ms" has incompatible type
"Optional[str]"; expected "str"  [arg-type]
                dt=_parse_dt_ms(cxml.get('date')),
                                ^~~~~~~~~~~~~~~~
my/smscalls.py:46: error: Argument "dt_readable" to "Call" has incompatible
type "Optional[str]"; expected "str"  [arg-type]
                dt_readable=cxml.get('readable_date'),
                            ^~~~~~~~~~~~~~~~~~~~~~~~~
my/smscalls.py:47: error: Argument 1 to "int" has incompatible type
"Optional[str]"; expected
"Union[str, bytes, bytearray, memoryview, array[Any], mmap, _CData, PickleBuffer, SupportsInt, SupportsIndex, SupportsTrunc]"
 [arg-type]
                duration_s=int(cxml.get('duration')),
                               ^~~~~~~~~~~~~~~~~~~~

Edit: see #287. Once thats merged I'll rebase this on top of master

@purarue
Copy link
Contributor Author

purarue commented Apr 14, 2023

ah, tried to rebase on top of the mypy fix from smscalls to see if CI works for this (since adding the gpxpy dependency optionally), but not sure if it did that

will try to just merge into this branch later today

edit: huh, seemed to work, lmn if you want any changes here

@purarue
Copy link
Contributor Author

purarue commented Apr 14, 2023

Oh, and also on the

# hmm -- would it be useful to allow the user to split this into tracks?, perhaps by date?

I found something like https://github.com/tkrajina/gpx-cmd-tools/blob/master/gpxtools/gpxsplitter.py if thats something we want to pursue, perhaps with localized datetimes, or by clustering locations together for a particular trip etc.

comment=location.datasource,
)
except AttributeError:
yield TypeError(
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there is also @runtime_checkable but never tried it myself, and it needs typing_extensions. So just in case you haven't seen it :) https://mypy.readthedocs.io/en/stable/protocols.html#using-isinstance-with-protocols

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah yeah, I saw that but disregarded because of the version requirement. I guess this would work even if the user duck-typed some other location class 👍


# 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]
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess one downside is that it doesn't respect the same exception policies as select_range, and just dumps everything to terminal. But not a big deal, and perhaps can think about it later if necessary

Copy link
Contributor Author

@purarue purarue Apr 14, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah yeah, this was more just a safeguard to prevent crashing, can add the two if statements to handle errors

we dont have a 'warn exceptions' flag on the cli though... guess it could use the logger instead?

edit: probably fine to leave it as is for now, one way to solve this is I'll write up some docs for hpi query as those are currently just on the main page and I'll add an example there

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

one (somewhat hacky?) way to make it fit into the existing mechanism might be hacking a wrapper iterable before calling select_range, e.g.

if output == 'gpx':
    input_src = map(check_conforms_to_location_procotol, input_src)

# select_range call etc

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah I see what you mean -- that way exceptions will end up in stdout and mess with gpx output. Anyway I think it's fine as it is :) But yeah later might worth adding an option to select_range/cli support to log exceptions to stderr?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah sounds good, will do that when I PR some docs for hpi query

@karlicoss karlicoss merged commit 40de162 into karlicoss:master Apr 14, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants