csm10495
csm10495

Reputation: 569

Python argparse with numbered argument name

GNU grep has an argument to print a certain number of extra lines around a matching line. From the man page:

-C NUM, -NUM, --context=NUM Print NUM lines of output context. Places a line containing a group separator (--) between contiguous groups of matches. With the -o or --only-matching option, this has no effect and a warning is given.

So I can do something like

grep -5 pattern file.txt

would be the equivalent of

grep -C 5 pattern file.txt

How can I emulate the -NUMBER behavior using argparse to where a user can pass in -NUM and I can get that number easily from argparse.

A silly way of doing this is to do something like this:

parser = argparse.ArgumentParser()
for i in range(1, 10000):
    parser.add_argument(f'-{i}', action='store_true', dest=f'border_lines_{i}', help=argparse.SUPPRESS)

args = parser.parse_args()

border_line_count = 0
for i in range(1, 10000):
    if getattr(args, f'border_lines_{i}'):
        border_line_count = i
        break

Basically, I add a bunch of hidden arguments for different -NUMs. Then find the one that is set. Is there a better way?

Upvotes: 3

Views: 349

Answers (1)

0xc0de
0xc0de

Reputation: 8287

This is a way to do this, but I don't like it personally.

parser.add_argument('-', dest='border_lines')

will give you the basic behaviour you want. Note that this is a required argument and if you want this to be an optional argument, you could:

parser.add_argument('-', dest='border_lines', default=0)

A (weird) problem with this now is that it accepts only single digits. To fix that, you'll need to define and override the parse action.

 class ConcatAction(argparse.Action):
     def __call__(self, parser, namespace, values, option_string):
         value = int(''.join(values))
         setattr(namespace, 'border_lines', value)

Now you can use this as:

parser = argparse.ArgumentParser()
parser.add_argument('-', dest='border_lines', default=0, nargs='*', action=ConcatAction)
parser.parse_args('-555')  # Gives Namespace(border_lines=555)

I strongly feel that this will mess up with other arguments, I have not tested that. I repeat, I don't like this way and following python zen, we should be explicit (with arg name) and as clear as possible.

Upvotes: 1

Related Questions