argparse zero-length switch

C

Carl Banks

Is it possible to specify a zero-length switch? Here's what I mean.

I have a use case where some users would have to enter a section name on the command line almost every time, whereas other users (the ones using only one section) will never have to enter the section name. I don't want to burden users with only one "section" to always enter the section name as a required argument, but I also want to make it as convenient as possible to enter the section name for those who need to.

My thought, on the thinking that practicality beats purity, was to create azero-length switch using a different prefix character (say, @) to indicatethe section name. So instead of typing this:

sp subcommand -s abc foo bar

they could type this:

sp subcommand @abc foo bar

Admittedly a small benefit. I tried the following but argparse doesn't seem to do what I'd hoped:

p = argparse.ArgumentParser(prefix_chars='-@')
p.add_argument('@',type=str,dest='section')
ar = p.parse_args(['@abc'])

This throws an exception claiming unrecognized arguments.

Is there a way (that's not a hack) to do this? Since the current behavior of the above code seems to do nothing useful, it could be added to argparsewith very low risk of backwards incompatibility.

Carl Banks
 
P

Peter Otten

Carl said:
Is it possible to specify a zero-length switch? Here's what I mean.

I have a use case where some users would have to enter a section name on
the command line almost every time, whereas other users (the ones using
only one section) will never have to enter the section name. I don't want
to burden users with only one "section" to always enter the section name
as a required argument, but I also want to make it as convenient as
possible to enter the section name for those who need to.

My thought, on the thinking that practicality beats purity, was to create
a zero-length switch using a different prefix character (say, @) to
indicate the section name. So instead of typing this:

sp subcommand -s abc foo bar

they could type this:

sp subcommand @abc foo bar

Admittedly a small benefit. I tried the following but argparse doesn't
seem to do what I'd hoped:

p = argparse.ArgumentParser(prefix_chars='-@')
p.add_argument('@',type=str,dest='section')
ar = p.parse_args(['@abc'])

This throws an exception claiming unrecognized arguments.

Is there a way (that's not a hack) to do this? Since the current behavior
of the above code seems to do nothing useful, it could be added to
argparse with very low risk of backwards incompatibility.

If the number of positional arguments is otherwise fixed you could make
section a positional argument with nargs="?"
import argparse
parser = argparse.ArgumentParser()
_ = parser.add_argument("section", nargs="?")
_ = parser.add_argument("foo")
_ = parser.add_argument("bar")
parser.parse_args(["alpha", "beta"]) Namespace(bar='beta', foo='alpha', section=None)
parser.parse_args(["alpha", "beta", "gamma"])
Namespace(bar='gamma', foo='beta', section='alpha')
 
S

Steven D'Aprano

Carl said:
So instead of typing this:

sp subcommand -s abc foo bar

they could type this:

sp subcommand @abc foo bar

Admittedly a small benefit.


I would call it a *cost* and not a benefit at all. Instead of using a
standard, familiar user interface for entering command options, you
introduce a second special purpose mechanism *just* for entering a section
name. -s is at least a mnemonic for "section", @ is not.

And it isn't like you gain any extra clarity or expressiveness, or even a
major saving of typing! "-s" vs "@". You don't even save a key stroke: "@"
requires two keystrokes, just as "-s" does. (Okay, perhaps you save a key
stroke if you type a space after the -s.)

-s section_name is pretty simple already. Spelling it @section_name is not
sufficiently more simple to make up for the burden of introducing
unfamiliar syntax.
 
C

Carl Banks

Carl said:
Is it possible to specify a zero-length switch? Here's what I mean.

I have a use case where some users would have to enter a section name on
the command line almost every time, whereas other users (the ones using
only one section) will never have to enter the section name. I don't want
to burden users with only one "section" to always enter the section name
as a required argument, but I also want to make it as convenient as
possible to enter the section name for those who need to.

My thought, on the thinking that practicality beats purity, was to create
a zero-length switch using a different prefix character (say, @) to
indicate the section name. So instead of typing this:

sp subcommand -s abc foo bar

they could type this:

sp subcommand @abc foo bar

Admittedly a small benefit. I tried the following but argparse doesn't
seem to do what I'd hoped:

p = argparse.ArgumentParser(prefix_chars='-@')
p.add_argument('@',type=str,dest='section')
ar = p.parse_args(['@abc'])

This throws an exception claiming unrecognized arguments.

Is there a way (that's not a hack) to do this? Since the current behavior
of the above code seems to do nothing useful, it could be added to
argparse with very low risk of backwards incompatibility.

If the number of positional arguments is otherwise fixed you could make
section a positional argument with nargs="?"

The positional arguments aren't fixed, otherwise I would have done it that way. I ended up deciding to prescan the command line for arguments starting with @, and that actually has some benefits over doing it with argparse. (One little surprise is if you pass it something like "-x @abc foo", wherefoo is the argument of -x.)

I don't really care for or agree with Steven and Ben Finney's foolish consistency. I already weighed it against the benefits of consistency, and decided that this parameter was easily important enough to warrant special treatment. It's actually a good thing for this parameter to look different from other switches; it marks it as specially important.


Carl Banks
 
C

Chris Angelico

I don't really care for or agree with Steven and Ben Finney's foolish consistency.  I already weighed it against the benefits of consistency, and decided that this parameter was easily important enough to warrant special treatment.  It's actually a good thing for this parameter to look different from other switches; it marks it as specially important.

I'll weigh in then - in favour of the "foolish" consistency. It's a
far more valuable feature than you might imagine. Think how much time
your users (even yourself) are going to spend using your program; now
think how much time those same people will spend using other programs.
You can't fight something that's orders of magnitude bigger than you,
so what you'll be doing is creating a special-case that has to be kept
in the user's mind. You'll also run into trouble if anyone has a file
name that begins @; this situation already exists, but I think most
people know not to create a file called "-rf" (and even then, most
Unix programs accept "--" to mean "end of options, the next thing is a
filename").

Do what everyone else does. You'll thank yourself for it in a year or so.

ChrisA
 
S

Steven D'Aprano

I don't really care for or agree with Steven and Ben Finney's foolish
consistency. I already weighed it against the benefits of consistency,
and decided that this parameter was easily important enough to warrant
special treatment. It's actually a good thing for this parameter to
look different from other switches; it marks it as specially important.

It seems to me that a parameter hardly deserves to be called "specially
important" if it is optional and the user can leave it out. "Specially
unimportant" is probably a better description.

At the end of the day, your claimed motivation for inventing this anti-
mnemonic was, and I quote, "to make it as convenient as possible to enter
the section name". If you honestly think that typing shift-2 is more
convenient than typing -s then go right ahead and do what you like. No
skin off my nose.
 
G

Gregory Ewing

Steven said:
And it isn't like you gain any extra clarity or expressiveness, or even a
major saving of typing! "-s" vs "@". You don't even save a key stroke: "@"
requires two keystrokes, just as "-s" does.

Also keep in mind that not all keystrokes are equal. Someone
who uses all their fingers probably finds "-s" faster and
easier to type than "@". I certainly do.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,065
Latest member
OrderGreenAcreCBD

Latest Threads

Top