keleshev / docopt-dispatch

Dispatch from command-line arguments to functions
MIT License
20 stars 2 forks source link

docopt-dispatch not passing parameter value correctly #4

Open pmgpmg opened 6 years ago

pmgpmg commented 6 years ago

I want to use the docopt dispatcher, but the parsing is not behaving in the same way as docopt. Here is an example. I have two commands defined in docopt - one that uses key as a positional parameter and the other that uses it as an optional parameter.

When used as: python3 /home/peterg/xx.py create_key xxx I would expect the key with xxx to appear in kwargs, but it doesn't. Is there any chance of a fix?

"""
MyProgram

Usage:
   myProg.py  create_key <key>
   myProg.py --key <key> add_key_to_user <user>

"""
from docopt_dispatch import dispatch

@dispatch.on('create_key')
def create_key(**kwargs):
    for k in kwargs:
        print(k,end=" "),
        print(kwargs[k])

if __name__ == '__main__':
    dispatch(__doc__)

python3 /home/peterg/xx.py create_key xxx
create_key True
key False
add_key_to_user False
user None
bittner commented 1 year ago

I have just analysed the problem:

There is a conflict in your (docstring-based) specification between <key> and --key. You can see this when you run the docstring with (the original) docopt. The output will be:

$ python myProg.py --key bar add_key_to_user foo
create_key False
<key> bar
--key True
add_key_to_user True
<user> foo

docopt-dispatch consolidates <key> and --key into a single kwargs key-value pair, overwriting the value of <key> by the value of --key, which hence becomes key -> True (False in your case).

The problem of your specification

I believe, the problem in your case is really your specification:

Design issue

The current design introduces the bug explained above, the consolidation conflict in docopt-dispatch.

docopt-dispatch could avoid this problem by populating kwargs only with the data that is relevant to the dispatched command (i.e. create_key in your case). All the other data is irrelevant in the context of the dispatched command and should not even be visible.

I'll open a feature request for that.

EDIT: :arrow_down:

The consolidation bug

My above suggestion only avoids conflicts between two specified calls. However, the consolidation conflict can happen in a single call too, e.g.

myProg.py <key> --key

The value of <key> will always be overwritten by the True/False flag value of --key. The consolidation as such (i.e. the stripping of --, < and >) is the root cause of the problem.