user308827
user308827

Reputation: 21961

Unexpected keyword argument in python click

@click.group(context_settings=dict(help_option_names=['-h', '--help']))
def plot_glm():
    pass

@plot_glm.command()
@click.argument('path_nc')
@click.argument('out_path')
@click.argument('var_name')
@click.option('--xaxis_min', default=0.0, help='')
@click.option('--xaxis_max', default=1.1, help='')
@click.option('--xaxis_step', default=0.1, help='')
@click.option('--annotate_date', help='')
@click.option('--yr', default=0, help='')
@click.option('--date', default=-1, help='')
@click.option('--xlabel', default='', help='')
@click.option('--title', default='', help='')
@click.option('--tme_name', default='time', help='')
@click.option('--show_plot', help='')
@click.option('--any_time_data', help='')
@click.option('--format', default='%.2f', help='')
@click.option('--land_bg', help='')
@click.option('--cmap', default=plt.cm.RdBu, help='')
@click.option('--grid', help='')
@click.option('--fill_mask', help='')
def plot_map_from_nc(path_nc, out_path, var_name, xaxis_min=0.0, xaxis_max=1.1, xaxis_step=0.1,
                     annotate_date=False, yr=0, date=-1, xlabel='', title='', tme_name='time', show_plot=False,
                     any_time_data=True, format='%.2f', land_bg=True, cmap=plt.cm.RdBu, grid=False, fill_mask=False)

if __name__ == '__main__':
    plot_glm()

I get this error when using python click library (python version 2.7.11, windows 10, click version 6.6):

    ctx = Context(self, info_name=info_name, parent=parent, **extra)
TypeError: __init__() got an unexpected keyword argument 'any_time_data'

What can I do to fix this error?

Upvotes: 9

Views: 11454

Answers (3)

Jonathan Schulz
Jonathan Schulz

Reputation: 31

I wanted to add to @gdlmx's answer because I tried running the code from their answer and ran into errors that took a little bit to parse through. I'd add this as a comment but unfortunately I don't have enough karma.

The code from this block will raise an error: "SyntaxError: invalid syntax" on the last line.

def __plot_map_from_nc__(... , any_time_data=True, ...):
    do_your_job_here
# create an alias
plot_map_from_nc = __plot_map_from_nc__ 
# pass this alias to click
@plot_glm.command()
@click.argument('path_nc') # ...
@click.option('--xaxis_min', default=0.0, help='') # ...
plot_map_from_nc

The thing that seems to work for this is:

#define your original function
def __plot_map_from_nc__(... , any_time_data=True, ...):
    do_your_job_here
#put @ decorator on a regular decorator expression
@plot_glm.command()
@click.argument('path_nc') # ...
@click.option('--xaxis_min', default=0.0, help='') # ...
def plot_map_from_nc(... , any_time_data=True, ...):
    __plot_map_from_nc__(... , any_time_data=True, ...)

Basically, this traditional decorator definition gives you a define block to put your @ decorator syntax on. Honestly, this probably isn't the best way to handle this, but because click uses so many decorators for setting up your CLI, it'd be unreasonable to add all of your commands with the traditional syntax.

Upvotes: 3

gdlmx
gdlmx

Reputation: 6789

It seems that you try to call plot_map_from_nc or plot_glm with actual arguments somewhere in your code like this:

plot_map_from_nc(any_time_data=False)
plot_glm(any_time_data=False)

which will generate the same error message that you got.

  File "testClick.py", line 39, in <module>
    plot_glm(any_time_data=False)
  File "c:\winPython\python-2.7.10.amd64\lib\site-packages\click\core.py", line 716, in __call__
    return self.main(*args, **kwargs)
  File "c:\winPython\python-2.7.10.amd64\lib\site-packages\click\core.py", line 695, in main
    with self.make_context(prog_name, args, **extra) as ctx:
  File "c:\winPython\python-2.7.10.amd64\lib\site-packages\click\core.py", line 618, in make_context
    ctx = Context(self, info_name=info_name, parent=parent, **extra)
TypeError: __init__() got an unexpected keyword argument 'any_time_data'

Reason for the error

That is because plot_map_from_nc and plot_glm are not normal functions after those click decorators. They are callable objects, whose signature becomes

plot_map_from_nc(args=None, prog_name=None, complete_var=None, standalone_mode=True, **extra)

The type of plot_map_from_nc is click.core.Command and every arguments passed to it will be redirected to click.core.Command.main()

Solution

The correct way to invoke these callable objects is

plot_map_from_nc(sys.argv[1:]) # or
plot_map_from_nc()

If you want to use plot_map_from_nc normally in your code, define it with a different name:

def __plot_map_from_nc__(... , any_time_data=True, ...):
    do_your_job_here
# create an alias
plot_map_from_nc = __plot_map_from_nc__ 
# pass this alias to click
@plot_glm.command()
@click.argument('path_nc') # ...
@click.option('--xaxis_min', default=0.0, help='') # ...
plot_map_from_nc

# Now  plot_map_from_nc becomes a   'click.core.Command'   object  while
# __plot_map_from_nc__ is still a normal function which can be invoke as
__plot_map_from_nc__(... , any_time_data=True, ...)

Upvotes: 11

Tom Myddeltyn
Tom Myddeltyn

Reputation: 1375

I did a little digging. Sometimes the best place to look is in the code that gave you the error: https://github.com/pallets/click/blob/0d48b2fbd256c1c692e3f3ba4c22b102f21f82f7/click/core.py#L879

if args and not ctx.allow_extra_args and not ctx.resilient_parsing:
    ctx.fail('Got unexpected extra argument%s (%s)'
             % (len(args) != 1 and 's' or '',
                ' '.join(map(make_str, args))))

So What I think is that you need to set the allow_extra_args=True or resilient_parsing=True

By default they are:

resilient_parsing=False, allow_extra_args=None,

https://github.com/pallets/click/blob/0d48b2fbd256c1c692e3f3ba4c22b102f21f82f7/click/core.py#L196

If you want, test it out by commenting out that one, I bet that the error you get will be from annotate_date (next alphabetically)

Upvotes: 3

Related Questions