0

I am having an issue with python-fire when a method has arguments with default values. Consider the following code:

import fire

class SomeClass(object):
    def __init__(self):
        self.a = ''
        self.b = ''

    def methoda(self):
        self.a = 'A'
        return self

    def methodb(self, x='B123'):
        self.b = self.a + x
        return self

    def __str__(self):
        return self.b

if __name__ == '__main__':
    s = SomeClass()
    s.methodb().methoda()
    print(s.b) # this prints B123 correctly

    fire.Fire(SomeClass)

As seen in the comments, in the print(s.b), it is printingB123` correctly. But when i change the order of the methods being called in fire from the command line, I am getting the odd behavior.

Example:

> python x.py
B123 # correct

> python x.py methoda methodb
Here: B123
AB123 # both correct

> python x.py methodb --x B123 methoda
Here: B123
B123 # again both correct

> python x.py methodb methoda
Here: B123
methoda # this is not correct. It should print B123 here also

As you can see with the last example, if i call methodb (which has an argument with a default value), it prints methoda instead of B123 as expected.

My question is, How can I use a method that has a default argument value first in this type of scenario without passing in --x=something?

In short, how can i make > python x.py methodb methoda properly print B123?

securisec
  • 3,435
  • 6
  • 36
  • 63
  • Looks like you need `--` or so otherwise the second string is interpreted as a positional argument to the method. What does the manual say? – Mad Physicist Oct 29 '19 at 03:18
  • Sadly, the manual doesnt really address this question. Nor does the examples. The usage of `--` seems odd considering the code works correctly when i do `methoda methodb`, but not when i do `methodb methoda`, but as seen by the print statement, it does work.. – securisec Oct 29 '19 at 03:30
  • One method has a positional argument, the other doesn't – Mad Physicist Oct 29 '19 at 03:30
  • But the argument has a default value.. which is why `methoda methodb` works fine without passing a `--x=something`. – securisec Oct 29 '19 at 03:32
  • Yes, but the interpreter appears to be greedy – Mad Physicist Oct 29 '19 at 03:33
  • Haha. Yes, it does appear so. I am not sure if I am doing something wrong, if it is a bug, or if this is an area for improvement on handling default args better in `fire`. – securisec Oct 29 '19 at 03:35
  • Looks like a bug. I'd file an issue with the library devs. Worst case, you'll get an explanation. Best case they'll update the docs or fix it. – Mad Physicist Oct 29 '19 at 03:38

1 Answers1

0

You need to change def methodb(self, x='B123'): to def methodb(self, *, x='B123'):, which makes x a keyword only argument, so it can no longer be used as a positional argument. This way fire will use the default value.

There has also been a github issue discussing this.

M. Gruber
  • 351
  • 3
  • 10