Python Fire

repository·master·Indexed 12 days ago

https://github.com/google/python-fire

A library for automatically generating command line interfaces (CLIs) from any Python object, including functions, classes, modules, and dictionaries. Version 0.7.1 allows developers to expose Python code to the command line using `fire.Fire()`, supporting nested command structures, Python literal parsing, and an interactive REPL mode via the `--interactive` flag.

Tokens
14.6K
Snippets
57
Records
83
Agent score
98%

What's inside Python Fire

  1. Access members of objects, dicts, and lists

    master

    You can navigate Python structures through the CLI by appending names or indices as arguments:

    • Objects: Append the member name (method or property). Note that property names like high_score can be accessed using kebab-case: high-score.
    • Dicts: Append the key name to access the corresponding value.
    • Lists/Tuples: Append the integer index to access the element at that position.

    Example patterns:

    • command member_name (Method/Property)
    • command key_name (Dict key)
    • command 2 (List index 2)
  2. Change the argument separator

    master

    The separator (default is -) allows you to call a function and then perform an operation on its return value. Arguments to the left of the separator are passed to the function; arguments to the right are applied to the result.

    If you need to use the default separator character as a literal argument, use the --separator flag to change it.

    def display(arg1, arg2='!'):
      return arg1 + arg2
    
    # Using default hyphen separator
    display hello                         # hello!
    display hello - upper                 # HELLO! (if upper is a function applied to result)
    
    # Changing separator to 'SEP' to allow '-' as an argument
    display - SEP upper -- --separator SEP    # -!
  3. Call functions and instantiate classes

    master

    Fire allows you to execute Python logic directly from the terminal:

    • Functions: Pass arguments positionally (command 5) or by name using flag syntax (command --value 5).
    • Classes: To instantiate a class, provide the arguments for its __init__ method using flag syntax.
    • Callables: For objects with a __call__ method, pass arguments using flag syntax.

    Handling Variable Arguments (*args, **kwargs): If a function accepts variable arguments or has default values, use a separator (default is -) to stop Fire from consuming arguments for the function call. Arguments to the right of the separator are applied to the result of the function call.

    def double(value=0):
      return 2 * value
    
    # Positional argument
    # command 5 -> returns 10
    
    # Named argument
    # command --value 5 -> returns 10
  4. Parse Python literals from the command line

    master

    Fire automatically determines argument types based on their values. You can pass Python literals directly from the CLI:

    • Integers: 10 $\rightarrow$ int
    • Floats: 10.0 $\rightarrow$ float
    • Strings: hello $\rightarrow$ str (Note: use quotes if you want to ensure a string type, e.g., "10")
    • Tuples: '(1,2)' $\rightarrow$ tuple
    • Lists: [1,2] $\rightarrow$ list
    • Booleans: True or False $\rightarrow$ bool
    • Dictionaries: {name:David} $\rightarrow$ dict

    Important: Shell Quoting Bash processes arguments before Fire. To pass complex structures like dictionaries, wrap them in single quotes: $ python example.py '{"name": "David Bieber"}'

  5. Turn existing modules into CLIs for exploration

    master

    You can turn any existing Python module into a CLI by calling fire.Fire() on it. This is useful for exploring the functionality of third-party libraries without reading their source code. Fire automatically generates help strings that describe the available functionality.

    import fire
    import difflib
    import PIL
    
    # Turning existing libraries into powerful CLI tools
    fire.Fire(difflib)
    fire.Fire(PIL)
  6. Generate shell completion scripts

    master

    You can generate completion scripts to improve the CLI experience in your shell.

    1. Default/Bash: Run widget -- --completion and redirect to a file (e.g., ~/.widget-completion), then source it in your .bashrc.
    2. Fish: Run widget -- --completion fish and source it in your fish.config.

    Note: If your CLI structure changes, you must regenerate and re-source the script.

    widget -- --completion > ~/.widget-completion
  7. Expose multiple commands using a dictionary

    master

    To selectively expose specific functions to the CLI, pass a dictionary to fire.Fire() where keys are the command names and values are the functions.

    import fire
    
    def add(x, y):
      return x + y
    
    def multiply(x, y):
      return x * y
    
    if __name__ == '__main__':
      fire.Fire({
          'add': add,
          'multiply': multiply,
      })
  8. Expose a specific function or component to the CLI

    master

    You can limit the CLI surface by passing a specific function, object, or class to fire.Fire(component).

    Exposing a single function:

    import fire
    
    def hello(name):
      return f'Hello {name}!'
    
    if __name__ == '__main__':
      fire.Fire(hello)

    Run as: $ python example.py World (no need to specify hello).

    Exposing a class (allows constructor arguments):

    import fire
    
    class BrokenCalculator:
      def __init__(self, offset=1):
          self._offset = offset
      def add(self, x, y):
        return x + y + self._offset
    
    if __name__ == '__main__':
      fire.Fire(BrokenCalculator)

    Run with constructor flags: $ python example.py add 10 20 --offset=0.

  9. Create a Fire CLI

    master

    You can turn Python objects, functions, or modules into a Command Line Interface (CLI) using fire.Fire().

    • import fire: Import the library.
    • fire.Fire(): Turns the current module into a Fire CLI.
    • fire.Fire(component): Turns the specified component (such as a class, function, or dictionary) into a Fire CLI.
    import fire
    
    def hello(name='World'):
        return f'Hello {name}!'
    
    if __name__ == '__main__':
        fire.Fire()
  10. Create CLIs in Python with Fire

    master

    To create a Command Line Interface (CLI), write your functionality as a function, module, or class, and then pass that object to fire.Fire(). A single-line call to Fire is sufficient to expose the object's interface to the command line.

    import fire
    
    def my_function(name="World"):
        return f"Hello {name}!"
    
    if __name__ == '__main__':
      fire.Fire(my_function)
  11. Handle *varargs and **kwargs in Fire

    master

    Fire supports functions using *args and **kwargs. To distinguish between arguments intended for the function and arguments intended for the result (to be processed by a subsequent chain), use a separator. The default separator is -.

    Using the separator: $ python example.py dog cat elephant - upper $\rightarrow$ CAT DOG ELEPHANT (where upper is called on the result of the function).

    Changing the separator: Use the --separator flag. Note that flags must be separated from the Fire command by an isolated --. $ python example.py dog cat elephant X upper -- --separator=X

    import fire
    
    def order_by_length(*items):
      """Orders items by length, breaking ties alphabetically."""
      sorted_items = sorted(items, key=lambda item: (len(str(item)), str(item)))
      return ' '.join(sorted_items)
    
    if __name__ == '__main__':
      fire.Fire(order_by_length)