tkrajina / gpx-cmd-tools

Commandline tools for GPX
Apache License 2.0
49 stars 13 forks source link

Make gpxmerge default output (print, I guess?) to stdout vs. file? #1

Open bdklahn opened 3 years ago

bdklahn commented 3 years ago

Thanks for making such a handy library!

Using your package, I was able to create a monthly summary of my daughter's Strava bulk download for her Physical Education (PE) class monthly logs, with your code and a bash script. I do this by running gpxinfo on a gpxmerge file of all the monthly files.

This is fine, but it nagged me a little thinking about that intermediate file on disk. So I decided to put it in memory, by making it a named pipe (mkfifo and mktemp -u).

It got me thinking that it seems like the following might be more conventional.

It looks like it might not be too hard, utilizing the argparser info with some addition/modification near . . . https://github.com/tkrajina/gpx-cmd-tools/blob/e042c4d65cc153ddf3589b4d8723bed5f71a9d0d/gpxtools/gpxmerge.py#L72-L73

Then, I ought to be able to run something like gpxinfo <(gpxmerge . . .). I suppose another step might then be to have gpxinfo accept stdin.

I suppose I could put together come code, and a pull request. :-)

I remember now . . . it's a little tricky with argparse to make an optional argument act both like a flag and like a container to store a value. But it can be done with 'default=argparse.SUPPRESS' (don't even add that attribute to the namespace if the flag is missing from the CL) and nargs = '?'. Then branch to stdout (print) if hasattr(args, 'output') returns False. If args.output == None ('if args.output:' should be enough), then set filename = 'merged.gpx'. Otherwise take the filename string entered after the '--output' (args.output).

bdklahn commented 3 years ago

Here is one way which seems to work.

diff --git a/gpxtools/gpxmerge.py b/gpxtools/gpxmerge.py
index 5cc9136..d5fa1f6 100644
--- a/gpxtools/gpxmerge.py
+++ b/gpxtools/gpxmerge.py
@@ -18,14 +18,21 @@ def get_time(g: gpx.GPX) -> Optional[datetime.datetime]:
     return None

 def main() -> None:
+    default_outfile_name = 'merged.gpx'
     parser = argparse.ArgumentParser(description='Merge GPX files')
     parser.add_argument('gpx_files', metavar='gpx', type=str, default='', nargs='*', help='GPX file')
-    parser.add_argument('-o', '--output', metavar='F', type=str, default='merged.gpx', help='Output GPX file')
+    parser.add_argument('-o', '--output', metavar='F', type=str, default=argparse.SUPPRESS, nargs='?', help=f'Output GPX file (default: {default_outfile_name}; omit option, for stdout).')
     parser.add_argument('-t', '--time', action='store_true', help='Sort by time')
     args = parser.parse_args()

     gpx_files = args.gpx_files
-    out_file = args.output
+
+    out_place = 'stdout'
+    if hasattr(args, 'output'):
+        out_place = default_outfile_name
+        if args.output:
+            out_place = args.output
+
     sort_by_time = args.time

     keep_extensions = True
@@ -68,6 +75,9 @@ def main() -> None:
         if not keep_extensions:
             print("Removing extensions")
             common.clean_extensions(base_gpx)
-    
-        with open(out_file, "w") as f:
-            f.write(base_gpx.to_xml())
\ No newline at end of file
+
+        if out_place == 'stdout':
+            print(base_gpx.to_xml())
+        else:
+            with open(out_place, "w") as f:
+               f.write(base_gpx.to_xml())