Code Monkey home page Code Monkey logo

python-fire's Introduction

Python Fire PyPI

Python Fire is a library for automatically generating command line interfaces (CLIs) from absolutely any Python object.

  • Python Fire is a simple way to create a CLI in Python. [1]
  • Python Fire is a helpful tool for developing and debugging Python code. [2]
  • Python Fire helps with exploring existing code or turning other people's code into a CLI. [3]
  • Python Fire makes transitioning between Bash and Python easier. [4]
  • Python Fire makes using a Python REPL easier by setting up the REPL with the modules and variables you'll need already imported and created. [5]

Installation

To install Python Fire with pip, run: pip install fire

To install Python Fire with conda, run: conda install fire -c conda-forge

To install Python Fire from source, first clone the repository and then run: python setup.py install

Basic Usage

You can call Fire on any Python object:
functions, classes, modules, objects, dictionaries, lists, tuples, etc. They all work!

Here's an example of calling Fire on a function.

import fire

def hello(name="World"):
  return "Hello %s!" % name

if __name__ == '__main__':
  fire.Fire(hello)

Then, from the command line, you can run:

python hello.py  # Hello World!
python hello.py --name=David  # Hello David!
python hello.py --help  # Shows usage information.

Here's an example of calling Fire on a class.

import fire

class Calculator(object):
  """A simple calculator class."""

  def double(self, number):
    return 2 * number

if __name__ == '__main__':
  fire.Fire(Calculator)

Then, from the command line, you can run:

python calculator.py double 10  # 20
python calculator.py double --number=15  # 30

To learn how Fire behaves on functions, objects, dicts, lists, etc, and to learn about Fire's other features, see the Using a Fire CLI page.

For additional examples, see The Python Fire Guide.

Why is it called Fire?

When you call Fire, it fires off (executes) your command.

Where can I learn more?

Please see The Python Fire Guide.

Reference

Setup Command Notes
install pip install fire
Creating a CLI Command Notes
import import fire
Call fire.Fire() Turns the current module into a Fire CLI.
Call fire.Fire(component) Turns component into a Fire CLI.
Using a CLI Command Notes
Help command --help or command -- --help
REPL command -- --interactive Enters interactive mode.
Separator command -- --separator=X Sets the separator to X. The default separator is -.
Completion command -- --completion [shell] Generates a completion script for the CLI.
Trace command -- --trace Gets a Fire trace for the command.
Verbose command -- --verbose

Note that these flags are separated from the Fire command by an isolated --.

License

Licensed under the Apache 2.0 License.

Disclaimer

This is not an official Google product.

python-fire's People

Contributors

baseddepartment1 avatar bobotig avatar borda avatar dbieber avatar dependabot[bot] avatar elaatifi avatar gruberma avatar hugovk avatar jacobaustin123 avatar jaesbit avatar jaredtrog avatar jgarst avatar joejoevictor avatar jtratner avatar meshde avatar michaelcg8 avatar nealmcb avatar nfultz avatar pranavgupta1234 avatar r0fls avatar rchen152 avatar robweiss avatar roopeshvs avatar saurabhkpatel avatar sp1thas avatar timgates42 avatar tux-00 avatar vbarbaresi avatar wchliao avatar xavierfigueroav avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

python-fire's Issues

completion for function

The completion on function is missing

def add(self, first1, second1=123):
    print({"first1": first1, "second1": second1})
    return first1 + second1

def main():
    fire.Fire(add)

if __name__ == '__main__':
    main()

the completion file :

# DO NOT EDIT.
# This script is autogenerated by fire/completion.py.

_complete-test_firepy()
{
  local start cur opts
  COMPREPLY=()
  start="${COMP_WORDS[@]:0:COMP_CWORD}"
  cur="${COMP_WORDS[COMP_CWORD]}"

  opts=""



  COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
  return 0
}

complete -F _complete-test_firepy ./test_fire.py

Better handling of argument name typos

Using this minimal example of a Python-fire CLI:

import fire

def f(my_arg):
    print(my_arg)

fire.Fire(my_arg)

This is the result I get:

~ python example.py --my-arg=hello
hello
➜  ~ python example.py --myarg=hello
--myarg=hello

As you can see, a typo in the argument leads to unexpected behaviour, which can be really hard to debug.

I would suggest never treating an argument matching --[a-zA-Z0-9_-]+ as positional, without some sort of escaping by the user (perhaps similar to the escaping you require to avoid parsing ints, etc.).

Add python -m fire?

% python -m fire lxml.html
/home/d33tah/virtualenv/bin/python: No module named fire.__main__; 'fire' is a package and cannot be directly executed

Perhaps it's worth adding?

Accept argv list in calls to Fire

Currently Fire() uses sys.argv. It should also be able to accept an argv passed in directly to the call to Fire.

Some considerations:

  • Currently Fire() accepts an undocumented argument command which is a string. Do we still want to accept a string (if yes, do we continue using the name command or do we just use the name argv?
  • If we remove the command argument, we can use BigQuery to find all instances of people using this argument and send them a pull request fixing it. It's undocumented, so 1) I don't think we have any obligation to do this, and 2) there shouldn't be many people using this argument, so sending the pull requests shouldn't be too big a job.
  • Does the passed in argv need argv[0] to be the program name?

fire.Fire() ruins fire.Fire(fire.Fire)

Hi python-fire,

fire.Fire looked like a very interesting function so I wanted to inspect it with fire.Fire. I was surprised that the interpreter printed out a dictionary with all my locals and globals.

I'm not sure if that's what you guys intended to happen, I guess it kind of is because of fire.Fire() defined as a valid invocation which means fire.Fire(globals() + locals()). Perhaps it's worth considering introducing a different function that would do that? fire.FireThisModule()?

Establish a comms channel for contributors

This ticket is for discussing + establishing a comms channel for contributors.

Perhaps Gitter is the best way to do this.
@saurabhkpatel suggested Slack, but with Slack you need to specify a list of domains from which to allow email addresses, whereas I want anyone to be able to join the conversation. There are ways around this like slackin, but at a glance it looks like I'd have to commit to maintaining a server running slackin indefinitely for this to be a viable workaround, which I'm not prepared to do.

+@jtratner @nealmcb @saurabhkpatel @jgarst @keatinge @r0fls as an FYI.

Question regarding passing arguments using fire

HI,
I have the following question regarding passing of arguments. Please clarify me.
I have 3 classes A B and C. Class C has a method which consumes an argument say arg3. Class A takes arg1 and arg2 as arguments. When I try to pass the 3rd argument to the class C I get an error saying "can not consume argument for that method"
example code below
a.py

class A (object):
    def __init__(self, arg1, arg2):
         self.b = B(arg1, arg2)
         self.arg1 = arg1
         self.arg2 = arg2
def main():
  fire.Fire()
if __name__ == "__main__":
   main()

b.py

class B():
    def __init__(self, arg1, arg2):
          self._arg1 = arg1
          self._arg2 = arg2
          self._imp = self._get_imp()
    
     def _get_imp(self):
           
           if (arg1 == arg1):
                imp = C()
           else 
                imp = D()
           return imp

     def __getattr__(self, name):
          obj = getattr(self._imp, name)
          return obj

c.py

class C():
    def create(self, arg3):
        print("argument 3 %d" %arg3


if I give the following command I get an error saying 'Could not consume arg', 'create'. This create is the
method in class C() which expects an argument. FYI

python a.py B --arg1 arg1 --arg2 arg2 create 3

arg1 and arg2 are consumed by B and arg3 needs to be consumed by class C but for some reason I am not able to pass arg3 to create method in C.

  1. How can I pass arguments to methods in classes when I call multiple classes using fire.

  2. if there are no arguments for the class C method then its able to print the message.

annotations and kwonlyargs

inspectutils.GetArgSpec uses inspect.getargspec, which can't handle annotations and kwonly args. The program

from fire import Fire

def test_args(arg1: str = 'aarrrgh', *, arg2: str = 'arrrgh'):
    return arg2, arg2

if __name__ == '__main__':
    Fire(test_args)

leads to an error at line 75 in GetArgSpec
"ValueError: Function has keyword-only parameters or annotations, use getfullargspec() API which can support them"

The simplest fix would be to put in another except clause to catch the value error, and proceed with inspect.getfullargspec or inspect.signature instead. An alternate way might be to decide at import if the program is python 3 and inspect.signature can be called. Do you have a preference between the two solutions, or another suggestion?

-Jared

Fails if return value is a numpy array

If the return value of a wrapped function is a numpy array then Fire raises the following error:

File "/home/.../miniconda3/lib/python3.5/site-packages/fire/core.py", line 430, in _Fire
  if component == last_component and remaining_args == initial_args:
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

The problem is that any equality check with a numpy array will be carried out element-wise.

I tried to implement a quick fix by checking hasattr(component, 'tolist'), however, I couldn't obviously find a robust solution to this issue.

Outdated PyPi version

It appears installing the fire module using pip produces an outdated version of the library. I've run into an error identical to #6, and after checking the result of that, it appears the update that fixed #6 can only be installed by cloning the repository and running setup.py, as suggested.

FYI, I was using fire version 0.1.0 with Python 3.5.2 when installed using pip.

Why so slow?

Great concept and I like how it works except for one thing I noticed - it's very slow to initialize especially with Python3.

time python fireexpt.py

yeilds 0.3 seconds for python 2 and 0.74 seconds for python 3 where fireexpt does nothing but import fire and fire.Fire() if name is main. There is no code to evaluate. Actually its as slow if you just import fire and pass.

Am I missing something, is this likely to continue, or can it be significantly improved? I love the tool and have been trying to see what's happening - it seems to be generating lots of classes for no obvious reason.

Support the option to provide a user-defined output formatter

On trying out fire, one of the first things I wanted was a method to define an output formatter.

At the moment it appears there is a single static formatter defined in _PrintResult().

Consider making an option in Fire:

fire.Fire(OBJECT, formatter=myformatter)

at the moment this is a "formatter" and "outputter". format and output should probably be separated...

Can we select capabilities while publishing the service

Hi I just tried publishing a service using publishing commands and it worked.

I also wanted to select service Capabilities like WCS and WMS selected at time of publishing. tried to look in documentation and online did not find any clue how to pass Capabilities information into service definition or service definition draft.

publishing

use --help or -h to show comment info

Is there any way that can use "-h" or "--help" to show comment of a function or class.

example:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
:authors: wanglichao
:version: 1.0 of 2017-03-20

"""

import fire


def hello(name):
    """this is a hello test1
    """
    return 'Hello {name}!'.format(name=name)


def hello2(name):
    """this is a hello test2
    """
    return 'Hello {name}!'.format(name=name)


if __name__ == '__main__':
    fire.Fire()

expect result:

python hello.py -- --help

Usage: hello.py [OPTIONS] COMMAND [ARGS]...
             authors: wanglichao
             version: 1.0 of 2017-03-20

Options:
             -- --help
             -- --interactive
             -- --trace
             -- --verbose

Command:
             fire           inner command
             hello          this is a hello test1
             hello2         this is a hello test2

Remove `IPython` dependency from `fire.Fire` or improve load times some other way

import IPython takes about 0.5 seconds on my machine to import and is the longest part of running simple fire scripts at the moment. Launching a python script and printing something takes 0.15 seconds so the total with import fire becomes about 0.65 seconds.

It's only used in _EmbedIPython and inspectutils.py so maybe it can be optional for command line apps and the inspection part ported over (or placed in a different smaller package)? Would such a pull request be useful?

unexpected behavior with duplicate value for the same argument

This is the code I'm running:

import fire

def test_duplicates(apples, paddles, oranges='10'):
    print('There are {} apples'.format(apples))
    print('There are {} paddles'.format(paddles))
    print('There are {} oranges'.format(oranges))

if __name__ == '__main__':
    fire.Fire(test_duplicates)

I am running python3 test.py 110 67 --apples=99 and producing the following result:

There are 99 apples
There are 110 paddles
There are 67 oranges

I see how Fire is evaluating the input, but if I'm not mistaken a positional and keyword argument collision should throw an error of some sort. I haven't looked under the hood yet but does this need a fix or am I using the command line wrong?

Better Windows CLI name

Windows user here.
Could that be possible to add a configuration to modify the default CLI name ? Right now, depending on the user way to interact with the script, it can become noisy.

Note:
The following figures all use a script base on the calculator example.
Python 2.7.13
Windows 7 OS

e.g. When launching a script directly with a .py, it can become noisy:
fig1

e.g. A worse case senario with CLI_FIRE_A_BIG_NAME_FOR_SCRIPT.py in a directory far far away.
fig3

e.g. In the best case scenario, it can be attenuated if you have setup Python.exe in your environment variable.
fig2

Questions:

  1. Is it possible to do ?
  2. I didn't find any doc about configuring the "help when error" display (except the docstring) is this in development ?

Thanks.

Non-zero exit codes

I'd like a way to make my CLI exit with a custom, non-zero code when using Python-fire.

One option might be to have a specific value you could return from your Fire function in order to exit with a particular code. This could be accomplished with, say, a simple ExitCode class wrapping an integer.

Possibly a better idea is to have a special exception class, e.g. ExitCodeError, such that raising an instance of a that class (or a subclass thereof), modifies the exit code of the CLI.

fire.Fire(func) means that `func` cannot return an empty dict

import fire

def x():
    return {}

fire.Fire(x)

Will cause this stack trace:

Traceback (most recent call last):
  File "E:/1stuff/Dropbox/dev/python/testfire/testing.py", line 7, in <module>
    z = fire.Fire(x)
  File "C:\Users\yuv\AppData\Local\Programs\Python\Python36-32\lib\site-packages\fire\core.py", line 145, in Fire
    _PrintResult(component_trace, verbose=component_trace.verbose)
  File "C:\Users\yuv\AppData\Local\Programs\Python\Python36-32\lib\site-packages\fire\core.py", line 181, in _PrintResult
    print(_DictAsString(result, verbose))
  File "C:\Users\yuv\AppData\Local\Programs\Python\Python36-32\lib\site-packages\fire\core.py", line 201, in _DictAsString
    len(str(key)) for key in result.keys()
ValueError: max() arg is an empty sequence

Should helputils._UsageStringFromFullArgSpec show PEP 484 Type Hints if Available?

PEP 484 introduced the standard syntax for type annotations in Python. Consider this example

import fire
def greeting(name:str, age:int) -> str:
    return "{name} will be {new_age} in 1 year".format(name=name, new_age=age+1)
fire.Fire(greeting)

Python fire currently will show the following when I type python test.py -- --help

Type:        function
String form: <function greeting at 0x00235738>
File:        c:\users\admin\desktop\test.py
Line:        4

Usage:       test.py NAME AGE
             test.py --name NAME --age AGE

Would it be helpful to give type hints here? Maybe something like this?

Usage:       test.py NAME:str AGE:int
             test.py --name NAME --age AGE

The implementation is very straightforward, I've already done it as a test on my local copy. We can use spec.annotations inside helputils._UsageStringFromFullArgSpec which gives a dict like this:

{'name': <class 'str'>, 'return': <class 'str'>, 'age': <class 'int'>}

Questions:

  1. Are type hints useful here? Or are they just cluttering up the info?
  2. Where should the type hints be? In both the usage lines? Just the first?
  3. What should the syntax be? Should it be var:type or something else?
  4. In the future could we use type hints to enhance parser.py.DefaultParseValue?
  5. Show type hints for just the arguments or also for the return value of a function?
  6. Support for Python 2 type hints? http://stackoverflow.com/questions/35230635/type-hinting-in-python-2

Not working when we install as a package,when i Move cli script to /usr/local/bin.

I made one script teacount.py.
In the file, It has two functions. The script is working fine until I moved it to scripts folder with setup.py, So I can access it from anywhere.

But it's giving error as follows.

/usr/local/bin/teacount.py: line 6: syntax error near unexpected token `('
/usr/local/bin/teacount.py: line 6: `def countme(name):'

you can install to check by following link.
my project link

Receive date parameter conversion confusion[Receive Operation not String]

import fire
class Test:
def init(self):
print('初始化成功')

def stat(self, daystr='1970-01-01'):
    print('开始--%s' % daystr)

if name == 'main':
fire.Fire(Test)

命令行测试并输出结果:
$ python3 tests.py stat 2016-12-10
初始化成功
开始--1994
$ python3 tests.py stat 2016-12-09
初始化成功
开始--2016-12-09
$ python3 tests.py stat 2017-01-09
初始化成功
开始--2017-01-09
$ python3 tests.py stat 2016/12/10
初始化成功
开始--2016/12/10
$ python3 tests.py stat xxx
初始化成功
开始--xxx
$ python3 tests.py stat 中文
初始化成功
开始--中文
$ python3 tests.py stat 2017-12-10
初始化成功
开始--1995
$ python3 tests.py stat 2017-12-11
初始化成功
开始--1994
$ python3 tests.py stat 2017-12-12
初始化成功
开始--1993
$ python3 tests.py stat 2016-12-12
初始化成功
开始--1992
$ python3 tests.py stat 1995-10-10
初始化成功
开始--1975
$ python3 tests.py stat 1995-11-10
初始化成功
开始--1974

travis ci failing with advent of ipython 6.0.0rc1

ipython 6.0.0rc1 was released 7 hours ago:

Now when building fire, travis CI finds that version, which doesn't support Python 2.7, and complains, e.g. at https://travis-ci.org/nealmcb/python-fire/jobs/220816890

...
Processing dependencies for fire==0.1.0
Searching for ipython
Reading https://pypi.python.org/simple/ipython/
Downloading https://pypi.python.org/packages/76/46/c505c48d264715136edde1a1960f9158133e34c03bbfe4c955dbc5948ce4/ipython-6.0.0rc1.tar.gz#md5=e57acb5fabd9f18b739de35a1f00eac5
Best match: ipython 6.0.0rc1
Processing ipython-6.0.0rc1.tar.gz
Writing /tmp/easy_install-Aw9UOD/ipython-6.0.0rc1/setup.cfg
Running ipython-6.0.0rc1/setup.py -q bdist_egg --dist-dir /tmp/easy_install-Aw9UOD/ipython-6.0.0rc1/egg-dist-tmp-JVscrS
IPython 6.0+ does not support Python 2.6, 2.7, 3.0, 3.1, or 3.2.
...
error: Setup script exited with 1
The command "python setup.py develop" failed and exited with 1 during .

Time for a dependency change. For a lot of projects....

Don't name the module "cmd"

I created a CLI module for my weekend project and called it "cmd.py".
This leads to the following exception:

/home/marcel/.virtualenvs/ultrabak/bin/python /home/marcel/git/ultrabak/ultrabak/cmd.py
Traceback (most recent call last):
  File "/home/marcel/git/ultrabak/ultrabak/cmd.py", line 1, in <module>
    import fire
  File "/home/marcel/git/python-fire/fire/__init__.py", line 21, in <module>
    from fire.core import Fire
  File "/home/marcel/git/python-fire/fire/core.py", line 62, in <module>
    from fire import completion
  File "/home/marcel/git/python-fire/fire/completion.py", line 25, in <module>
    from fire import inspectutils
  File "/home/marcel/git/python-fire/fire/inspectutils.py", line 23, in <module>
    import IPython
  File "/home/marcel/.virtualenvs/ultrabak/lib/python3.5/site-packages/ipython-5.3.0-py3.5.egg/IPython/__init__.py", line 48, in <module>
    from .core.application import Application
  File "/home/marcel/.virtualenvs/ultrabak/lib/python3.5/site-packages/ipython-5.3.0-py3.5.egg/IPython/core/application.py", line 25, in <module>
    from IPython.core import release, crashhandler
  File "/home/marcel/.virtualenvs/ultrabak/lib/python3.5/site-packages/ipython-5.3.0-py3.5.egg/IPython/core/crashhandler.py", line 28, in <module>
    from IPython.core import ultratb
  File "/home/marcel/.virtualenvs/ultrabak/lib/python3.5/site-packages/ipython-5.3.0-py3.5.egg/IPython/core/ultratb.py", line 119, in <module>
    from IPython.core import debugger
  File "/home/marcel/.virtualenvs/ultrabak/lib/python3.5/site-packages/ipython-5.3.0-py3.5.egg/IPython/core/debugger.py", line 46, in <module>
    from pdb import Pdb as OldPdb
  File "/usr/lib/python3.5/pdb.py", line 135, in <module>
    class Pdb(bdb.Bdb, cmd.Cmd):
AttributeError: module 'cmd' has no attribute 'Cmd'

After renaming it to "cli.py" everything works as expected. The reason is that the cmd module is added to the pythonpath if it is executed like this and covers python's cmd module. It works if the cmd module is executed as a submodule (python -m ultrabak.cmd or using entry_points).

As cmd.py could be a common name for a CLI, I'd suggest to add a note somewhere in the docs.

Address pylint's no-else-return errors

A new version of pylint came out today that looks for no-else-return violations, and we have a few such violations. This ticket is to either fix those violations or turn off no-else-return checking.

completion option for zsh

I'm using zsh 5.0.8 on OSX 10.11.6.

When I tried to run the generated completion bash for the basic example in README, I got the following error.

_complete-calculatorpy:4: unrecognized modifier C'`

I finally resolved this issue by replacing the : in the bash script with : .

An extra option for completion command will be helpful for zsh user.

only print usage when running without arguments

My colleagues keep thinking there is a stacktrace or unexpected behavior when they read output like:

Type: function String form: <function foo at 0x7fe9d8e47b90> File: path/to/file Line: 149

I propose to only print the usage string. I can make a pull request if you like the idea.

Enable autoreload in interactive mode

Is there a way to enable IPython autoreload when using --interactive mode? I've been using this mode frequently in development, and it'd be nice to easily test changes on the fly.

How to successfuly parse list of string ip address?

--args [a,b] can be parsed into list of string correctly.
--args [192.168.1.1,192.168.1.2] is parsed to string.
I also tried '[192.168.1.1, 192.168.1.2]', '["192.168.1.1","192.168.1.2"]', all failed

Thank you

does not work for functions?

I tried this with a single function,

import fire

def double(number):
    """Doubles a given number."""
    return 2 * number

if __name__ == '__main__':
    fire.Fire(double)

which is just the class example but with a single function, but it returns

Type:        str
String form: doubledouble
Docstring:   str(object='') -> str
str(bytes_or_buffer[, encoding[, errors]]) -> str

Create a new string object from the given object. If encoding or
errors is specified, then the object must expose a data buffer
that will be decoded using the given encoding and error handler.
Otherwise, returns the result of object.__str__() (if defined)
or repr(object).
encoding defaults to sys.getdefaultencoding().
errors defaults to 'strict'.
Length:      12

Usage:       ./tests/data/scripts/calculator.py double 
             ./tests/data/scripts/calculator.py double capitalize
             ./tests/data/scripts/calculator.py double casefold
             ./tests/data/scripts/calculator.py double center
             ./tests/data/scripts/calculator.py double count
             ./tests/data/scripts/calculator.py double encode
             ./tests/data/scripts/calculator.py double endswith
             ./tests/data/scripts/calculator.py double expandtabs
             ./tests/data/scripts/calculator.py double find
             ./tests/data/scripts/calculator.py double format
             ./tests/data/scripts/calculator.py double format-map
             ./tests/data/scripts/calculator.py double index
             ./tests/data/scripts/calculator.py double isalnum
             ./tests/data/scripts/calculator.py double isalpha
             ./tests/data/scripts/calculator.py double isdecimal
             ./tests/data/scripts/calculator.py double isdigit
             ./tests/data/scripts/calculator.py double isidentifier
             ./tests/data/scripts/calculator.py double islower
             ./tests/data/scripts/calculator.py double isnumeric
             ./tests/data/scripts/calculator.py double isprintable
             ./tests/data/scripts/calculator.py double isspace
             ./tests/data/scripts/calculator.py double istitle
             ./tests/data/scripts/calculator.py double isupper
             ./tests/data/scripts/calculator.py double join
             ./tests/data/scripts/calculator.py double ljust
             ./tests/data/scripts/calculator.py double lower
             ./tests/data/scripts/calculator.py double lstrip
             ./tests/data/scripts/calculator.py double maketrans
             ./tests/data/scripts/calculator.py double partition
             ./tests/data/scripts/calculator.py double replace
             ./tests/data/scripts/calculator.py double rfind
             ./tests/data/scripts/calculator.py double rindex
             ./tests/data/scripts/calculator.py double rjust
             ./tests/data/scripts/calculator.py double rpartition
             ./tests/data/scripts/calculator.py double rsplit
             ./tests/data/scripts/calculator.py double rstrip
             ./tests/data/scripts/calculator.py double split
             ./tests/data/scripts/calculator.py double splitlines
             ./tests/data/scripts/calculator.py double startswith
             ./tests/data/scripts/calculator.py double strip
             ./tests/data/scripts/calculator.py double swapcase
             ./tests/data/scripts/calculator.py double title
             ./tests/data/scripts/calculator.py double translate
             ./tests/data/scripts/calculator.py double upper
             ./tests/data/scripts/calculator.py double zfill

I have a workaround in place that just setattr all functions I find in a file to a dummy class and then I call Fire on that instead, but just wanted to see if I was misinterpreting the documentation about being able to call Fire on any object?

python2.7 ipython fails to install

The ipython dependency fails to install with ipython<6.0 using python 2.7.13 as part of setup.py install_requires

I understand the reasoning for not wanting to maintain backports

I was able to use ipython==5.3 with success.

by using/installing python-fire with the dist tar.gz from python setup.py sdist of the master branch on git.

Can it support customize arguments info?

Like can I customize the argument type, description or something else?

I would like to export it as a json schema file , and build it as a gui tool with the export schema file.

Thx

Lazy import IPython [Remove IPython as a required dependency: Part 1]

IPython is only used in two places:

  • inspectutils.py: only uses a single function from IPython (IPython.core.oinspect.Inspector().info), so maybe we could just strip that one function out of IPython or write an equivalent function from scratch. I would want permission from the IPython folks before doing the former.
  • interact.py: uses IPython for the --interactive flag, but this should really be optional. You'll notice the unused _EmbedCode function in interact.py. (https://github.com/google/python-fire/blob/master/fire/interact.py#L89) The reason that's there is to eventually enable Fire to be used without IPython as a required dependency.

This task is to lazily import IPython in the two places it's used.


This is Part 1 of the plan to remove IPython as a required dependency.
The plan is outlined here.

Use fire without editing code directly

Currently you have to add something like this to the end of your file just to mess around with fire:

if __name__ == '__main__':
    fire.Fire()

and then run with

python path/to/code.py

But it'd be neat if instead you could just do

fire path/to/code.py

and that does equivalent of exec appending the ifmain statement to the end.

Not sure how to do it - I know kernprof does some magic to inject into builtins before exec'ing code. (or maybe you get a code object back from exit) - but this would make fire even better as a debugging tool as well.

Global usage in help or help for subcommand

I try a simple example with the following class :

#! /usr/bin/python3
import fire

class Calculator(object):
    """A simple calculator class."""

    def add(self, first, second=123):
        print({"first": first, "second": second})
        return first + second

    def mul(self, first=5, second=123):
        print({"first": first, "second": second})
        return first * second

if __name__ == '__main__':
    fire.Fire(Calculator)

Is it possible to have access to help for command and subcommand ?

when I use -- --help flag on base script I only got :

$ ./test_fire.py -- --help
Type:        type
String form: <class '__main__.Calculator'>
File:        ~/my_folder/test_fire.py
Line:        5
Docstring:   A simple calculator class.

Usage:       ./test_fire.py

When I put no argument a got a better help message :

$ ./test_fire.py
Type:        Calculator
String form: <__main__.Calculator object at 0x7fdf898230b8>
File:        ~/my_folder/test_fire.py
Docstring:   A simple calculator class.

Usage:       ./test_fire.py
             ./test_fire.py add
             ./test_fire.py mul

Use package name when __main__.py is used

I'm investigating how to package a single file application with fire at the moment.

It seems that in order to have pip install the requirements, a setup.py files needs to exist. And setup.py requires that a package be defined. When this is done, a file, __main__.py is created in the package directory and invoked using, python -m mypackage COMMAND.

In this case the logic is in mypackage/__main__.py, which, when used with fire shows __main__.py in the usage output, where mypackage display is desirable.

json cannot serialize circular references

Here's a minimal example of the failure:

import fire
x = {}
x['y'] = x
fire.Fire()

Running python example.py gives this traceback:

Traceback (most recent call last):
  File "example.py", line 4, in <module>
    fire.Fire()
  File "/Users/dbieber/virtualenvs/_/lib/python2.7/site-packages/fire/core.py", line 145, in Fire
    _PrintResult(component_trace, verbose=component_trace.verbose)
  File "/Users/dbieber/virtualenvs/_/lib/python2.7/site-packages/fire/core.py", line 181, in _PrintResult
    print(_DictAsString(result, verbose))
  File "/Users/dbieber/virtualenvs/_/lib/python2.7/site-packages/fire/core.py", line 210, in _DictAsString
    key=str(key) + ':', value=_OneLineResult(value))
  File "/Users/dbieber/virtualenvs/_/lib/python2.7/site-packages/fire/core.py", line 230, in _OneLineResult
    return json.dumps(result)
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/__init__.py", line 243, in dumps
    return _default_encoder.encode(obj)
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/encoder.py", line 207, in encode
    chunks = self.iterencode(o, _one_shot=True)
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/encoder.py", line 270, in iterencode
    return _iterencode(o, 0)
ValueError: Circular reference detected

The problem is that _DictAsString tries to serialize [each key of] the dict using json, but json cannot serialize dicts w/ circular references.

We'll need a different serialization technique to support this case.

Limit member exposition from an instance

Hi,

firstly I would like to thank you guys for this great library.

I would like to know if there is a way for limiting the members I can return to Fire in my functions. Let me give you an example about how I (half) resolved this:

import fire

class Obj:
    def __init__(self):
        self.safe = 'safe!'

    def dangerous(self):
        print('dangerous!')

class App:
    def show(self):
        obj = Obj()
        return {'safe': obj.safe}

if __name__ == '__main__':
    fire.Fire(App, name='app')

This makes the job as I expect, although the --help functionality is not as friendly as I would need since, without any parameter, show returns the dictionary (as one could expect):

$ python app.py show 
safe: safe!

But, instead, I would need to have a behaviour similar to the following:

$ python app.py show --help
Usage:       app show 
             app show safe

Is it possible to enforce to show the help output if no parameter is provided to show instead of evaluating all it? Maybe using a dictionary for restricting the access to some members is not the right way to do it. I have also tried to return a fire.Fire instance but then I lose the execution chain in the usage (i.e. app show ...).

Thanks in advance.

All possible usages are printed out when an object was returned

For example:-

class Stuff(object):
    def do_this(self):
        pass
    
    ... many more methods

def testx():
    return Stuff()

def main():
    fire.Fire({
        'testx': testx,
    })

And when executed, all the methods from the returned object was printed out:-

Type:        Stuff
String form: <Stuff object at 0x7f43202a1be0>
File:        ~/xxx/cli.py

Usage:       cli testx
             cli testx do-this

This mean the real output from the command no longer helpful as it way far to the top of the console (you have to scroll up to see the command real output). There must be a way to disable printing out the returned value as that the least concern from cli tools.

improvements to --verbose mode

This ticket is for improvements to --verbose mode, such as making debug information (like filepath, line no, etc) only show up in verbose mode.

Support case-insensitive usage of Python Fire CLIs

Much like how we allow users to use hyphens - in place of underscores, this Issue is to allow users to use all-lowercase versions of identifiers.

Typical case

import fire
class CaseExample(object):
  def Alpha():
    return 'path 1'
fire.Fire(CaseExample)
$ python example.py Alpha  # This is the current behavior.
path 1
$ python example.py alpha  # This is the new behavior I want to add.
path 1
$ python example.py ALPHA   # Do we want to support other capitalizations? Or just the all lower-case version?
path 1

Corner cases
Unlike with the -/_ support, there can potentially be members with multiple capitalization variants of the name.

E.g.

import fire
class CaseExample(object):
  def alpha():
    return 'path 1'
  def Alpha():
    return 'path 2'

fire.Fire(CaseExample)

If the user provides an exact match, it's clear what we should do. I'm open to discussion about how to handle the ambiguous case.

$ python example.py alpha
path 1
$ python example.py Alpha
path 2
$ python example.py ALPHA
WARNING: Ambiguous member access `ALPHA`; accessing `alpha`.
path 1

Why?
The primary motivation is that command line tools typically use lower case commands, whereas Python classes (and occasionally methods/functions) typically have capital names. By allowing these capital names to be used via their lower-case variant, the CLIs that result from normal python code will feel natural more often.

Possible extension
If we also support dropping/adding -/_s in some situations, then people could use snake-case to refer to CamelCase items... just brainstorming. Thoughts?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.