Search code examples
docopt

Specify an option one or more times in docopt


I have a program (in python but that shouldn't matter) that takes some options one or more times, such as:

# Valid cases:
python test.py --o 1 --p a <file>
python test.py --o 1 --o 2 --p a --p b <file>
# Invalid:
python test.py --o a <file>
python test.py --p a <file>
python test.py <file>

This script works:

#!/usr/bin/env python2.7

"""Test

Usage:
  test.py --o=<arg> [--o=<arg>...] --p=<arg> [--p=<arg>...] <file>

"""
from docopt import docopt


if __name__ == '__main__':
    arguments = docopt(__doc__, version='Test 1.0')
    print(arguments)

However the option is repeated and it feels pretty ugly. I tried the following:

test.py --o=<arg>[...] --p=<arg>[...] <file>
test.py (--o=<arg>)[...] (--p=<arg>)[...] <file>
test.py (--o=<arg>[...]) (--p=<arg>[...]) <file>

But none of them worked. The alternative would be to make the option fully optionnal and check its value in the program:

  test.py [--o=<arg>...] [--p=<arg>...] <file>
  ...
  if len(arguments["--o"]) < 1:
    raise ValueError("One or more --o required")
  if len(arguments["--p"]) < 1:
    raise ValueError("One or more --p required")

But I feel there should be an easy solution to do that with docopt directly. Is there a beautiful way to do it?


Solution

  • A bit late, but

    Usage:
      test.py (--o=<arg>)... (--p=<arg>)... <file>
    

    does what you want.

    Usage:
      test.py (--o=<arg>...) (--p=<arg>...) <file>
    

    Work too.