Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@avalentino
Copy link
Member

@avalentino avalentino commented Jul 31, 2022

Description of proposed changes

Implementation of a single entry-point script with multiple sub-commands as proposed in #810.

Reminders

  • Pass Codacy code review (green)
  • Pass Circle CI test (green)
  • Make sure that your code follows our style. Use the other functions/files as a basis.
  • If modifying functionality, describe changes to function behavior and arguments in a comment below the function declaration.
  • If adding new functionality, add a detailed description to the documentation and/or an example.

@avalentino avalentino force-pushed the feature/single-entrypoint branch from 1050d73 to ef8f413 Compare July 31, 2022 11:15
@avalentino avalentino changed the title [WIP] Single entrypoint with sub-commands Single entrypoint with sub-commands Aug 1, 2022
@yunjunz yunjunz self-requested a review August 1, 2022 18:47
Copy link
Member

@yunjunz yunjunz left a comment

Choose a reason for hiding this comment

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

Thank you @avalentino very much for the PR!

I like the idea of grouping the scripts into different categories. I am wondering that is it possible, while running mintpy -h, to show the sub-commands in groups? We have that in view.py, which helps a lot when the sub-commands/options are long.

@avalentino
Copy link
Member Author

I like the idea of grouping the scripts into different categories. I am wondering that is it possible, while running mintpy -h, to show the sub-commands in groups? We have that in view.py, which helps a lot when the sub-commands/options are long.

Indeed that was the original idea.
Unfortunately only one "subparsers" can be create.
The only option AFAIK would be to provide a custom description argument and not providing help, as described in [1].
But I do not like to much this solution because because you ned to keep the description updated manually.

Another option would be to have 2 levels of sub-commands:

  • the first one for categories (processing pre-processing, ...)
  • the second level for actual commands

E.g.

python3 -m mintpy -h

usage: mintpy [-h] [--version]
              {proessing,pre-processing,display,...}
              ...

Command line interface for MintPy. The Miami INsar Time-series software in PYthon
(MintPy as /mint pai/) is an open-source package for Interferometric Synthetic
Aperture Radar (InSAR) time series analysis. It reads the stack of interferograms
(coregistered and unwrapped) in ISCE, ARIA, FRInGE, HyP3, GMTSAR, SNAP, GAMMA or
ROI_PAC format, and produces three dimensional (2D in space and 1D in time) ground
surface displacement in line-of-sight direction. It includes a routine time series
analysis (`smallbaselineApp.py`) and some independent toolbox. This is research
code provided to you "as is" with NO WARRANTIES OF CORRECTNESS. Use at your own
risk.

options:
  -h, --help            show this help message and exit
  --version             show program's version number and exit

sub-commands:
  {proessing,pre-processing,display,...}
    processing        description
    pre-processing    description
    display           description
    ...

this solution could be more problematic for users if one does not already know in which category is the subcommand he is interested in, because one do not have a full list of sib-commands in the first level help.

[1] https://stackoverflow.com/questions/32017020/grouping-argparse-subparser-arguments

@yunjunz
Copy link
Member

yunjunz commented Aug 2, 2022

Thank you for the exploration and explanation @avalentino. I agree with you: none of the existing approaches are desired. It's perfectly fine with me to go ahead with the current single group sub-parser design.

@avalentino
Copy link
Member Author

avalentino commented Aug 3, 2022

Please note that the single-entripoint script (mintpy) currently has a startup time that is a little bit high (specially if you try to use tab completion).
This depends on the fact that to load the argument parsers it is currently necessary to import many modules that, depending on the sub-command used, could be not necessary.

A solution for this issue could be to move the definition of the argument parser and the main function of all sub-commands in a separate file (one for each sub-command), maybe in a dedicated mintpy/cli sub-package, and use lazy import of processing modules form the main function.

@yunjunz If you think that the change is not too invasive I could implement it in a separate PR.

@yunjunz
Copy link
Member

yunjunz commented Aug 3, 2022

Please not that the single-entripoint script (mintpy) currently has a startup time that is a little bit high (specially if you try to use tab completion). This depends on the fact that to load the argument parsers it is currently necessary to import many modules that, depending on the sub-command used, could be not necessary.

A solution for this issue could be to move the definition of the argument parser and the main function of all sub-commands in a separate file (one for each sub-command), maybe in a dedicated mintpy/cli sub-package, and use lazy import of processing modules form the main function.

@yunjunz If you think that the change is not too invasive I could implement it in a separate PR.

I noticed this slow startup time as well. The mintpy/cli and lazy import solution looks good to me. Since this is a big change affecting existing functionalities, I would prefer we do it in a separate PR.

FYI, I plan to cut for a new release (v1.4.0) after this PR is merged (for the upcoming UNAVCO training short course), will try this PR ASAP and merge it.

@yunjunz
Copy link
Member

yunjunz commented Aug 4, 2022

There was a strange error as below while testing the mintpy timeseries2velocity: the inps.step should be initiated with [] (L147), similar to inps.exp, but was initiated with a float value of 0.00011111111111111112 and was somehow missing in the output while typing inps in the debug mode. This error is not there while running timeseries2velocity.py. This smells like a "conflict with a system/reserved variable" behavior, but I am not sure about the exact reason. This is fixed by replacing inps.step with inps.stepDate in the commit above. Posted here for bookkeeping.

(insar) yunjunz:~/data/test/FernandinaSenDT128/mintpy>$ mintpy timeseries2velocity timeseries_SET_ERA5_ramp_demErr.h5 
open timeseries file: timeseries_SET_ERA5_ramp_demErr.h5
--------------------------------------------------
dates from input file: 36
['20141213', '20141225', '20150307', '20150319', '20150331', '20150412', '20150424', '20150506', '20150518', '20150530', '20150611', '20150623', '20150717', '20150729', '20150822', '20150903', '20150915', '20150927', '20151009', '20151021', '20151102', '20151114', '20151126', '20151208', '20151220', '20160101', '20160113', '20160125', '20160206', '20160218', '20160301', '20160406', '20160418', '20160430', '20160512', '20160524']
--------------------------------------------------
using all dates to calculate the time function
--------------------------------------------------
2022-08-03 21:47:42,715 CRITICAL -- unexpected exception caught: 'TypeError' 'float' object is not iterable


(insar) yunjunz:~/data/test/FernandinaSenDT128/mintpy>$ mintpy timeseries2velocity timeseries_SET_ERA5_ramp_demErr.h5 
> /Users/yunjunz/tools/MintPy/mintpy/timeseries2velocity.py(150)cmd_line_parse()
-> if inps.template_file:
(Pdb) inps
Namespace(bootstrapCount=400, endDate=None, excludeDate=[], exp=[], file_type='timeseries', log=[], maxMemory=4.0, outfile=None, periodic=[], polynomial=1, ref_date=None, ref_lalo=None, ref_yx=None, res_file='timeseriesResidual.h5', save_res=False, startDate=None, template_file=None, timeSeriesCovFile=None, timeseries_file='timeseries_SET_ERA5_ramp_demErr.h5', uncertaintyQuantification='residue', update_mode=False)
(Pdb) inps.step
0.00011111111111111112

@yunjunz
Copy link
Member

yunjunz commented Aug 4, 2022

@avalentino one last comment: each sub-command is currently accessed in cmd without .py, e.g. mintpy geocode. Is this the standard practice for python software installed via apt? I would think the mintpy geocode.py style is more consistent with other existing styles. Let me know what do you think please.

@jhkennedy
Copy link
Collaborator

For subcommands, I would personally expect to not have the .py extension and find it rather weird to have to type it.

@avalentino
Copy link
Member Author

@avalentino one last comment: each sub-command is currently accessed in cmd without .py, e.g. mintpy geocode. Is this the standard practice for python software installed via apt? I would think the mintpy geocode.py style is more consistent with other existing styles. Let me know what do you think please.

IMHO the fact that a sub command is implemented in a specific python module is an implementation detail and it should be decoupled from the CLI design.

In general I would say that programs using sub-command based CLIs, like e.g. git or docker, use sub-commands names without any file extensions. I don't thin that he .py extension adds anything to the user experience. It is just more typing.

Personally I would stay with the current single-entrypoint implementation, but I'm open to change if you prefer.

Copy link
Member

@yunjunz yunjunz left a comment

Choose a reason for hiding this comment

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

Thank you @avalentino and @jhkennedy for your inputs. Sub-command without .py is clearly your preference with good reasons. Going forward with the current design sounds great to me.

All looks great to me now. Thank you very much @avalentino for the useful PR!

@yunjunz yunjunz merged commit 537c4ef into insarlab:main Aug 4, 2022
@avalentino
Copy link
Member Author

Thanks @yunjunz

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.

3 participants