Building a dynamic and self documenting fuzzy Python cli

Securisec
Securisec
Nov 7 · 4 min read

In this short article, I will go over how to build a completely dynamic Python cli; which will also be self documenting right from a class. For this, I will combine and usepython-fire, prompt_toolkit ,argparse and docstring_parser. Here is the asciinema for this. Once we write the skeleton for our cli, we never have to go back to it again! Every new method we add to our core class will automatically be picked up by the cli along with documentation.

So why these three libraries? Well, they each provide unique functionalities that can be combined together to build really awesome cli’s!

  • python-fire : Allows one to build a cli from any python object type including functions, classes etc, but lacks autocompletion support without sourcing a bash or fish shell script.
  • prompt_toolkit : Allows one to build really beautiful cli’s which supports input validation, colors, autocomplete etc.
  • argparse : Python built in. It is not really necessary for this blog, but I wanted to demonstrate how to combine them.

What are some of the benefits of combining these four libraries?

  • Very scalable. In the future, if I wanted to add another method to an existing class, I do not have to do anything for the cli.
  • Documentation provided as the user interacts with the app!
  • Fully dynamic! Any changes to the core class is picked up by the cli without any further code necessary from me.

A few things to know before we get started:

  • I am not a developer.
  • We need to make sure to document our core code as best as we can. Without proper documentation, docstring_parser will fail to provide the data needed for dynamic help. I am using Google style docstring in my code.
  • I am using return self at the end of my class methods for the core code for method chaining

The core SearchFiles class

  • SearchFiles class
  • Two methods in this class called ls and grep

Directory structure for the code is

├── cli.py
├── search
│ ├── __init__.py
│ └── lsgrep.py

Lets build an awesome cli!

Our imports

import inspect
import argparse
import fire
from docstring_parser import parse
from prompt_toolkit.completion import Completer, Completion, FuzzyCompleter
from prompt_toolkit import PromptSession
from search.lsgrep import SearchFiles

We will then define two global variables that we will use in other functions and class

possbile_options = dir(SearchFiles)
options = []

The possible_options will hold all the methods that are available (we will filter out _ and __ methods later on)

Define a function to get docstrings from a method

Create a custom completer for prompt_toolkit

Patch fire.Fire

Lets put it all together!

Now we have a fully functional dynamic python cli with fuzzy completion!

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade