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

Issues around underscores, dashes and metavars #7

Open
ekimekim opened this issue Mar 29, 2020 · 0 comments
Open

Issues around underscores, dashes and metavars #7

ekimekim opened this issue Mar 29, 2020 · 0 comments

Comments

@ekimekim
Copy link
Owner

Currently, argh has some somewhat inconsistent behaviour with respect to how arguments are presented based on their name:

Arg Type Name Metavar Usage
foo_bar Positional foo_bar foo_bar example.py foo_bar
_foo_bar Positional _foo_bar _foo_bar example.py _foo_bar
foo_bar=default Option --foo-bar FOO_BAR example.py [--foo-bar FOO_BAR]
_foo_bar=default Option ---foo-bar N/A Crashes during assembly
*foo_bar Multiple Positional foo_bar foo_bar example.py [foo_bar [foo_bar ...]]
*_foo_bar Multiple Positional _foo_bar _foo_bar example.py [_foo_bar [_foo_bar ...]]

Note that positional args are lowercased with underscores, whereas options are replaced with dashes (for name) or uppercased (for metavar).

Note also that leading underscores are treated naively, which leads to a bug for options.

We cannot safely change the behaviour of names, as this will break compatability in a serious way (people's @arg decorators will no longer match the right args), but this is fine since it's not name that matters to the usage string for positional args.

See also discussion from upstream: neithere#79, neithere#106

I pretty strongly believe that lowercased metavars for positional args is a mistake. In most usage conventions, lowercase strings are intended to be taken as literals and uppercase as variables, eg. from ip link help: Usage: ip link add [link DEV] [ name ] NAME. This also clears up the consistency of dashes vs underscores, since positional arg metavars will now act the same as option metavars, ie. FOO_BAR.

The other option to resolve the inconsistency would be to set the metavar as foo-bar, and this is the solution suggested in neithere#106. But I would rather have positional metavars match option metavars rather than option names.

Then there is the question of underscore-prefixed args.
By python conventions this would denote an "internal use only" argument.
This seems like a reasonable convention for us to adopt, where underscore-prefixed arguments with defaults are simply ignored when assembling, as we assume they're for use internally within the application.
This also works for *_args - we can assume the extra args are to be passed only in internal calls, though this would be a backwards-incompatible change.
However, this doesn't map cleanly to single arguments without defaults - we need to give some value for these args.

I see three options:

  • Keep the current behaviour of treating these args no differently to ones without underscores
  • Pass None for these args
  • Raise an error for this case during assembly

I am leaning towards option 2, but I could see any of these options as being fairly sane behaviour here (especially since the user could trivially add a =None if option 2 is what they actually want).
If we go with option 1, it is a strong argument for also keeping the current behaviour for *_args for consistency.

So then, assuming option 1 above, this would be our new behaviour:

Arg Type Name Metavar Usage
foo_bar Positional foo_bar FOO_BAR example.py FOO_BAR
_foo_bar Positional _foo_bar _FOO_BAR example.py _FOO_BAR
foo_bar=default Option --foo-bar FOO_BAR example.py [--foo-bar FOO_BAR]
_foo_bar=default Internal N/A N/A Ignored, always called with default
*foo_bar Multiple Positional foo_bar FOO_BAR example.py [FOO_BAR [FOO_BAR ...]]
*_foo_bar Multiple Positional _foo_bar _FOO_BAR example.py [_FOO_BAR [_FOO_BAR ...]]

One very nice thing about these choices is that the only backwards-incompatible changes are to the exact syntax of the usage (which no-one should be programatically relying on), plus behaviour that used to be an error.

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

No branches or pull requests

1 participant