Open link89 opened 2 years ago
I think part of the problem here is that -a
requires disambiguation so that Fire can tell whether it's supposed to be treated as a positional argument or an option. In POSIX, this is typically done by passing --
to indicate the end of options. However, Fire has its own custom flags that use the same syntax (e.g., -- --interactive
) which limits what you can do with --
here.
A hacky workaround I have came up with in the past was to disable Fire's custom flags altogether and force --
to behave like POSIX. Something like:
#!/usr/bin/env python3
import fire
def _patch_fire():
# Disable Fire's custom flags.
def _SeparateFlagArgs(args):
return args, []
fire.core.parser.SeparateFlagArgs = _SeparateFlagArgs
# Make -- behave like POSIX, i.e., separate positional args from options.
orig__ParseKeywordArgs = fire.core._ParseKeywordArgs
def _ParseKeywordArgs(*args, **kwargs):
kwargs, remaining_kwargs, remaining_args = orig__ParseKeywordArgs(*args, **kwargs)
if remaining_kwargs:
try:
ddash_index = remaining_kwargs.index('--')
remaining_args.extend(remaining_kwargs[ddash_index + 1:])
remaining_kwargs = remaining_kwargs[:ddash_index]
except ValueError:
pass
return kwargs, remaining_kwargs, remaining_args
fire.core._ParseKeywordArgs = _ParseKeywordArgs
_patch_fire()
class Conda:
def __init__(self, verbose=False):
...
def run(self, *argv):
print(argv)
if __name__ == '__main__':
fire.Fire(Conda)
Now you can get the output you expect:
$ python3 fake-conda.py --verbose - run -- which -a python3
('which', '-a', 'python3')
And you can pass options too as long as you remember to end the options with --
. For example, if you change the Conda
class above to:
class Conda:
def __init__(self, verbose=False):
...
def run(self, *argv, foo=None, bar=None):
print(argv, foo, bar)
You can still do things like:
$ python3 fake-conda.py --verbose - run --foo --bar=10 -- which -a pytthon3
('which', '-a', 'python3') True 10
Of course this hack is too intrusive and will likely brick the moment Fire changes anything this code touches.. but it might be enough for your needs until a proper feature for this lands in Fire.
Hi @melsabagh-kw Thank you for the sample code. I think it's a good idea to use --
to indicate the end of options, but that's not what I intended. I don't need to have fire
to parse partial arguments and pass the remaining to the target function like the one in your sample code, but just stop parsing anything and pass all of the remining args to the target function.
def run(self, *argv, foo=None, bar=None): # That would be too complicated to have fire handle partial of args
pass
@fire.decorators.SkipParse
def run(self, *argv): # that's the simple form I want to solve, by just stop paring anything
pass
I have already make a PR for it and it works well in my use case to delegate arguments to the downstream commands. And this is the reason why I want this feature to create a tool to turn this
java -jar jenkins-cli.jar -s http://localhost:9090/ -webSocket list-jobs
into this
jenkins-fire-cli run list-jobs
by wrapping the original command line to reduce some noise for the end user.
Feature Description
I am working on a tool to wrap some existed command line tools to make them easier to use (like auto install, inject argument automatically, etc). And I hope that I can have a way to tell Fire to stop parsing after encount some specific command.
Example Here are some real world examples like
poetry run python3 ./my-scripts.py
orconda run -n my-env python3 ./my-scripts.py
Without this feature I can only put everything else as string, just like what
-c
option ofbash
does, e.g.bash -c "echo 'hello world'"
, which could still work, but the user have to type extra string quote and dealing with escaping in some cases.I am not sure if it is possbile to provide some decorator to archive this, for example
And when running with
python fake-conda.py --verbose run which -a python3
, the output should be('which', '-a', 'python3')