0

Here is a working version of DocOpt (partially taken from naval fate):

"""
Instance Manager

Usage:
  instance_manager cluster create <name> <manager> <worker>... [--google|--virtualbox]
  instance_manager cluster delete <name>
  instance_manager cluster <name> add <worker> [--size=<size>]
  instance_manager cluster <name> remove <worker>
  instance_manager cluster <name> service add <service> [--replication=<replication>]
  instance_manager cluster <name> service remove <service>
  instance_manager cluster <name> service remove <service>
  instance_manager instance (add|remove) <x> <y> [--moored|--drifting]
  instance_manager -h | --help
  instance_manager --version

Options:
  -h --help     Show this screen.
  --version     Show version.
  --size=<size> Size of the container.
  --moored      Moored (anchored) instance.
  --drifting    Drifting instance.
  --google  Google Cloud.
  --virtualbox  VirtualBox.
  --replication Service Replication.
"""
from docopt import docopt


if __name__ == '__main__':
    arguments = docopt(__doc__, version='0.1.1rc')
    print(arguments)

Here is a non-working version of DocOpt.

"""
Instance Manager

Usage:
  instance_manager cluster create <name> <manager> <worker>... [--google|--virtualbox]
  instance_manager cluster delete <name>
  instance_manager cluster <name> add <worker> [--size=<size>]
  instance_manager cluster <name> remove <worker>
  instance_manager cluster <name> service add <service> [--replicas=<replicas>]
  instance_manager cluster <name> service remove <service>
  instance_manager cluster <name> service remove <service>
  instance_manager instance (add|remove) <x> <y> [--moored|--drifting]
  instance_manager -h | --help
  instance_manager --version

Options:
  -h --help     Show this screen.
  --version     Show version.
  --size=<size> Size of the container.
  --moored      Moored (anchored) instance.
  --drifting    Drifting instance.
  --google  Google Cloud.
  --virtualbox  VirtualBox.
  --replicas    Service Replication.
"""
from docopt import docopt


if __name__ == '__main__':
    arguments = docopt(__doc__, version='0.1.1rc')
    print(arguments)

Error:

docopt.DocoptLanguageError: --replicas must not have an argument

The only difference is that one uses the word replicas instead of replication.

diff first.py second.py 
9c9
<   instance_manager cluster <name> service add <service> [--replication=<replication>]
---
>   instance_manager cluster <name> service add <service> [--replicas=<replicas>]
24c24
<   --replication Service Replication.
---
>   --replicas    Service Replication.

This is unacceptable.

Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
Alexander Kleinhans
  • 5,950
  • 10
  • 55
  • 111

2 Answers2

2

You need two spaces after --replication, you have only one. Same after --size=<size>.

Also, in the second example there is both --replicas (no argument) in the [Options] and --replicas=<replicas> in the pattern (top section). These contradict each other, it is not clear whether an argument should be allowed or not.

Lastly, no need to have two identical patterns, remove one:

instance_manager cluster <name> service remove <service>

The docs: https://github.com/docopt/docopt#option-descriptions-format

Use two spaces to separate options with their informal description:

--verbose More text.   # BAD, will be treated as if verbose option had
                       # an argument "More", so use 2 spaces instead
-q        Quit.        # GOOD
-o FILE   Output file. # GOOD
--stdout  Use stdout.  # GOOD, 2 spaces

Here is a working pattern with --replication:

Instance Manager

Usage:
  instance_manager cluster create <name> <manager> <worker>... [--google|--virtualbox]
  instance_manager cluster delete <name>
  instance_manager cluster <name> add <worker> [--size=<size>]
  instance_manager cluster <name> remove <worker>
  instance_manager cluster <name> service add <service> [--replication=<replicas>]
  instance_manager cluster <name> service remove <service>
  instance_manager instance (add|remove) <x> <y> [--moored|--drifting]
  instance_manager -h | --help
  instance_manager --version

Options:
  -h --help      Show this screen.
  --version      Show version.
  --size=<size>  Size of the container.
  --moored       Moored (anchored) instance.
  --drifting     Drifting instance.
  --google       Google Cloud.
  --virtualbox   VirtualBox.
  --replication=<replicas>  Service Replication.

Live (prefilled) test on http://try.docopt.org

frnhr
  • 12,354
  • 9
  • 63
  • 90
  • Thanks for reply. I tried adding two spaces (at least) after Options. Still receiving the error. `--replication` was the version that was working, `--replicas` wasn't. I'm gonna stick with https://github.com/google/python-fire for now. – Alexander Kleinhans Aug 12 '19 at 22:35
0

Change --replicas to --replicas=<replicas> in the Options: section in your broken version. Then it works.

Basically, if an option takes an argument, then that argument has to appear in the option entry in the "Options:" section too. You made the same mistake in both of your versions.

Your second version only "works" in that it's failing to catch that mistake for you, because you're confusing it by not following the "two spaces between options and their description" rule. If you add the required space after --replication in your "working" version, you get the same error.

You could also "fix" your broken version by putting only one space between --replicas and the description in the "options" section. Then is also works, although since this way is "against the rules" of docopt, I wouldn't count on it working - if it were me, my attempts to "fix" this would be to either

  1. try to accept one space between options and their descriptions, in which case this version (and thus also your "working" version posted in the question) would raise the same error, or

  2. try to make sure that this version (and thus also your "working" version posted in the question) always threw an exception about not having enough spaces between options and their descriptions.

mtraceur
  • 3,254
  • 24
  • 33