-1

In python I have:

parser = argparse.ArgumentParser(description='RANGES')
parser.add_argument('IP_Address', action='store', type=str)

How can I let the user provide a single IP adresses or range or separate data?

for example I want to support:

python3 main.py 1.1.1.1
python3 main.py 1.1.1.1, 2.2.2.2
python3 main.py 1.1.1.1-2.2.2.2

Where the first iterates over 1.1.1.1 only, the second iterates over 1.1.1.1 and 2.2.2.2. While the latter iterates over all ips in the specified range.

Pranav Hosangadi
  • 23,755
  • 7
  • 44
  • 70
john
  • 13
  • 3
  • You'll simply have to parse the entered string later…? – deceze Jul 07 '22 at 09:51
  • @deceze I remember there is a simplier approach, for example what if I want to support only multiple values and not ranges? – john Jul 07 '22 at 09:59
  • 1
    You can use `nargs` to accept multiple values, but that won't help you for the ranges case, which you still need to parse separately… – deceze Jul 07 '22 at 10:01

2 Answers2

0

You could try something like this:

parser.add_argument('IP_Address', nargs='+', action='store', type=str)

This would only solve your first question.

nargs='*' might also be possible although does not seem like it from your use case

For the second, you need to specify the rules of the range creation.

erasmortg
  • 3,246
  • 1
  • 17
  • 34
0

A slightly more complex solution is to define a function for the type attribute and a class extending argparse._AppendAction. The idea of this class is to 'flatten' internally the argument list. This is a job that can also be done after parsing (in this case, no need to extend the class).

import argparse
import re

class newAppendAction(argparse._AppendAction):
    def __call__(self, parser, namespace, values, option_string=None):
        items = getattr(namespace, self.dest, None)
        items = argparse._copy_items(items)
        for value in values:
            if type(value) is list:
                for item in value:
                    items.append(item)
            else:
                items.append(value)
        setattr(namespace, self.dest, items)

def type_lambda(value):
    return [v for v in re.split("\-|\,", value) if len(v) > 0]

We can then simply declare the argument of the parser:

parser = argparse.ArgumentParser(description='RANGES')
parser.add_argument('IP_Address', nargs='+', action=newAppendAction, type=type_lambda)

And test the result:

>>> s3 = "python3 main.py 1.1.1.1-2.2.2.2"
>>> print(parser.parse_args(s1.split(" ")[2:]))
Namespace(IP_Address=['1.1.1.1'])

>>> s2 = "python3 main.py 1.1.1.1, 2.2.2.2"
>>> print(parser.parse_args(s2.split(" ")[2:]))
Namespace(IP_Address=['1.1.1.1', '2.2.2.2'])

>>> s1 = "python3 main.py 1.1.1.1"
>>> print(parser.parse_args(s3.split(" ")[2:]))
Namespace(IP_Address=['1.1.1.1', '2.2.2.2'])