Skip to main content

Squiffy is the minimal library that helps you build your CLI application before your boss notices

Project description

squiffy - a light library for interactive CLI application

This is squiffy, a small, small - wonderfully small - library for developing and deploying locally interactive CLI applications.

It's intended for things that should be done quickly, with prime focuse on functionality and not on the infrastructure.

We aim to provide a bit of infrastructure for simple applications, that depend on user interaction which triggers custom actions.

Table of Contents

Installation

You can use pip to install squiffy into your environment.

pip install squiffy

Additionally we encourage usage of virtualenv to for development environments. we recommend to use pipenv for your development environment.

Install pipenv using pip:

pip install pipenv

If restricted or there are problems with pip, you can use:

python -m pip install pipenv

Navigate in the directory you wish to install squiffy into and develop the app and use pipenv install to install squiffy.

cd my_app
pipenv install squiffy

If you want to modify squiffy to suit your need, just clone the repo:

cd my_app
git init.
git clone https://github.com/Gygarte/squiffy.git

Create the environment and install de dependencies specified in the Pipfile using:

pipenv --python 3.12
pipenv install --dev

or:

python -m pipenv --python 3.12
python -m pipenv install --dev

Start using squiffy in your project.

Note: Refer to the pipenv documentation here: https://pypi.org/project/pipenv/

Usage

Squiffy uses four mandatory items to setup the CLI application:

  1. layout.json the blueprint of your application's layout.
  2. LayoutFactory the main class for app layout construction
  3. State the main class for configuring an internal state - which contains whatever informations is needed in the app
  4. Application the main class to be used

Creating a layout.json

An example equals to 1000 words :D (please be advise that I purposfully let some keywords that do nothing yet! Squiffy is still in alpha and I'm still a noob)

{
    "submenu": [
        {
            "title": "Main_Menu",
            "main":true,
            "logo_path": null,  // NOT IMPLEMENTED
            "header_msg": "This is the header for the main menu",
            "footer_msg": "Gabriel Artemie@2023",
            "return_to_previous": false,
            "return_to_main": false,
            "quit": true,
            "options": [
                {
                    "option": "SwitchToSubmenu2",
                    "include_help": true,  // NOT IMPLEMENTED
                    "help": "SwitchToSubmenu2 help",  // NOT IMPLEMENTED
                    "switch":"Second_Menu",
                    "action": null  // NOT IMPLEMENTED
                },
                {
                    "option": "Print_and_wait",
                    "include_help": true,  // NOT IMPLEMENTED
                    "help": "Print_and_wait help",  // NOT IMPLEMENTED
                    "switch":null,
                    "action": null  // NOT IMPLEMENTED
                },
                {
                    "option": "Trigger_an_error",
                    "include_help": true,  // NOT IMPLEMENTED
                    "help": "Trigger_an_error help",  // NOT IMPLEMENTED
                    "switch":null,
                    "action": null  // NOT IMPLEMENTED
                }
            ],
            "style":null // NOT IMPLEMENTED: to use a special style for each submenu
        },
        {
            "title": "Second_Menu",
            "main":false,
            "logo_path": null,  // NOT IMPLEMENTED
            "header_msg": "This is another header message for submenu2",
            "footer_msg": "Gabriel Artemie@2023",
            "return_to_previous": true,
            "return_to_main": true,
            "quit": true,
            "options": [
                {
                    "option": "Accept_an_input",
                    "include_help": true,  // NOT IMPLEMENTED
                    "help": "option1 help",  // NOT IMPLEMENTED
                    "switch":null,
                    "action": null  // NOT IMPLEMENTED
                },
                {
                    "option": "Print_the_state",
                    "include_help": true,  // NOT IMPLEMENTED
                    "help": "option2 help",  // NOT IMPLEMENTED
                    "switch":null,
                    "action": null  // NOT IMPLEMENTED
                }
            ],
            "style":null // NOT IMPLEMENTED: to use a special style for each submenu
        }
    ],
    "error_handling":{
        "name":"Error",
        "include":true,
        "log_path":null  // NOT IMPLEMENTED
    },
    "style_sheet_path":null, //NOT IMPLEMENTED: a path to a separate style sheet
    "default_style":{
        "dimensions":{
            "type":"auto",
            "width":null,
            "height":null
        },
        "padding":{
            "top":1,
            "right":2,
            "bottom":1,
            "left":2
        },
        "border":{
            "type":"light" // You can chouse from "light", "thick" and "double" border style
        }
    }
}

The LayoutFactory

The layout is created by passing the path to the layout.json to the LayoutFactory constructor

from squiffy import LayoutFactory

layout = LayoutFactory('my_app/layout.json') 

The style

The style sheet is still a simple approach for a kinda' retro style type. The inspiration for the style apperance was drawn from the console-menu project by @aergirhall (many many thanks to you for the ideas and I hope you do not dissaprove that I've used them)

From the above layout.json you can guess what styling options are available in this version.

Please see the Future Developments section bellow for details regarding the development of this feature.

Setting a State

A State keeps data that are used by the callback functions. You can add specific configuration in the State from the app initialization and from the callback functions.

The State is configured to be saved whenewer the app is quitting or an error is triggered. So, any configurations passed to the State should implement a saving mechanism.

Let's assume:

from dataclass import datacalss

@dataclass
class MyConfig:

    # a bunch of attributes and configurations

    def save(self) -> None:
        # some saving logic

So the State will be defined as:

state = State({"config":MyConfig()})

Setting the application

This is as simple as passing the State and Layout to the Application constructor and hit run.

app = Application(layout=layout, state=state)

app.run()

Setting callback functions

In order to do some stuff with all this we need some end function. The end functions should use the State and return a signal like OK, Error, Abort

Let's see an example:

from squiffy import State
from squiffy.signals import OK, Error, Abort

def my_func(state:State) -> OK | Error | Abort:

    # do some stuff and return something

In order to save the results of the computation in the State you just pass a dictionary with the name_of_the_data and the actual_data_object to the OK.payload().

If an error occured you can pass the following arguments to the Error: origin, log_message, traceback

from squiffy import State
from squiffy.signals import OK, Error, Abort

def my_func(state:State) -> OK | Error | Abort:

    # all is good and the computation runned smoothly
    resulted_state = {"name_of_the_data":actual_data_object}

    return OK(pyload=resulted_state)

    # an error occured
    return Error()

    # you are fancy and use try-except and traceback.format_exc
    try:
        # some shady stuff
    except Exception:
        return Error(origin="here",log_message="Some shady error occured!", traceback=format_exc())

Finally your function is passed to the app instance as follows

def main() -> None:

    app = Application(layout=layout, state=state)
    app.add(function=my_func, option="Option1", submenu="Submenu1") # tadaaaa

    app.run()

if __name__ == "__main__":
    main()

That is all! You can start building simple and beautifull stuff and show your work bestie the cool stuff you do because you do not have a real life :D. Cheers!

Examples

We enjoy having an example ready to be explored. just write the following and enjoy our small and not-so-creative example.

python -m squiffy.example.example

or if this fails, try to write the following in a .py file.

from squiffy import example

if __name__ == "__main__":
    example.main()

Future Developments

  1. Include the rendering and display of the logo based on a logo_path.
  2. Include a keybinding for visualizing the help information for each option on the menu.
  3. Include special stylesheet for each submenu (not sure I will follow this path tho!)
  4. Include error logging into dedicated file.
  5. Separate the style sheet from the layout sheet.
  6. Refactoring: improvements of the architecture, code redability, commenting and more.
  7. Include keybindings for common options like: return_to_previous, return_to_main, quit and others.
  8. Write tests!

Contributing

We accept contributions, sugestions and any thought on how to improve squiffy or what edge cases should be treated (ofc and new features suggestions).

License

Please see the License section.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

squiffy-0.1.2.tar.gz (24.2 kB view details)

Uploaded Source

Built Distribution

squiffy-0.1.2-py3-none-any.whl (29.7 kB view details)

Uploaded Python 3

File details

Details for the file squiffy-0.1.2.tar.gz.

File metadata

  • Download URL: squiffy-0.1.2.tar.gz
  • Upload date:
  • Size: 24.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/5.1.1 CPython/3.12.4

File hashes

Hashes for squiffy-0.1.2.tar.gz
Algorithm Hash digest
SHA256 6d548a31bd804da26a865e46ced8bb2f0307eefed2d41e5ae46dd8596fac8198
MD5 5bf9d42bc1da0d171beb3f1673f9e25a
BLAKE2b-256 831d8b9f7e4c902bf226e7f6751d9a17d95f313ea2c0d391b8c826378c33f4b3

See more details on using hashes here.

File details

Details for the file squiffy-0.1.2-py3-none-any.whl.

File metadata

  • Download URL: squiffy-0.1.2-py3-none-any.whl
  • Upload date:
  • Size: 29.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/5.1.1 CPython/3.12.4

File hashes

Hashes for squiffy-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 d584480ce6638a8323ccd228f9ae73ddd163b3b79c84f30f4c9d931f5801603f
MD5 9d87871b3b3a38ec6a239ef903cf3acb
BLAKE2b-256 3c94da93fe650fd162deff845c89a0a3ba13078f6bab8f18508bb56fdb088f7f

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page