Skip to content

Stanley5249/sugar-cli

Repository files navigation

🍬Sugar

Disclaimer: This project is not yet production-ready and is actively seeking contributors.

Overview

Sugar leverages Python’s powerful typing system and syntactic sugar to simplify the creation of CLI programs, offering a delightful and user-friendly experience. It draws inspiration from the excellent projects Typer and Python Fire.

Installation

You can install Sugar CLI using either pip or uv, an alternative package manager.

# using pip
pip install sugar-cli

# using uv
uv pip install sugar-cli

Basic Usage

This section is for users unfamiliar with other CLI libraries. Below is a shared code snippet for the following examples.

from sugar import *

def add(a: int, b: int) -> None:
    """Add two numbers."""
    print(f"{a} + {b} = {a + b}")

def sub(a: int, b: int) -> None:
    """Subtract two numbers."""
    print(f"{a} - {b} = {a - b}")

Build the App

App without Subcommands

Use ArgumentApp (example code)

app = ArgumentApp()

@app.command()
def add(a: int, b: int) -> int: ...

or sugar (example code).

app = sugar(add)

App with Subcommands

Use CommandApp (example code)

app = CommandApp()

@app.command()
def add(a: int, b: int) -> int: ...

@app.command()
def sub(a: int, b: int) -> int: ...

or sugar (example code).

app = sugar([add, sub])

Execute the App

Run Mode

Use run() to execute it as a typical CLI program.

if __name__ == "__main__":  
    app.run()

Example:

> python <FILENAME>.py add 1 2
1 + 2 = 3
> python <FILENAME>.py -h
Usage: <FILENAME>.py [MAGIC] <COMMAND> ...

Commands:
  add           Add two numbers.
  sub           Subtract two numbers.

Magic:
  --help, -h    show this help message and exit

Cycle Mode

Use cycle() to enable a shell-like interface.

if __name__ == "__main__":  
    app.cycle()

Example:

> python <FILENAME>.py  
Usage: <FILENAME>.py [MAGIC] <COMMAND> ...

Commands:
  add           Add two numbers.
  sub           Subtract two numbers.

Magic:
  --help, -h    show this help message and exit

>>> add 1 2
1 + 2 = 3
>>> 

Dependencies

Required

Development

  • pytest: For running tests.
  • ruff: For linting and formatting.
  • uv: For dependency management.

Documents

While it would be ideal to eliminate the dependency on docstring-parser, the complexity of handling various styles of docstrings makes it impractical to implement all of them ourselves. We are currently looking for better solutions.

FAQ

What does the name "Sugar" stand for?

Simple
Utility for
Generating
Argument
Runners

While the acronym might be a bit of a stretch, it has a nice ring to it. In reality, "Sugar" refers to syntactic sugar, which makes the code more readable and easier to write.

Why Run a CLI Program as a Shell?

Quick response times are crucial for a good user experience in CLI programs. Running a CLI program as a shell helps avoid repeatedly loading heavy modules, making subsequent commands respond quicker. This is particularly important for researchers using deep learning frameworks like PyTorch and TensorFlow, which can take a second to initialize.

Another way to reduce loading times is through lazy imports. Some projects use the lazy-loader from Scientific-Python, which is an effective solution. Additionally, Sugar offers an experimental submodule for lazy importing within a context manager. For more details, see the Experimental section.

Why Did We Start the Project?

We embarked on this project after being inspired by the Command Line Interface Guidelines, which shed light on the chaotic nature of CLI environments:

The world of the terminal is a mess. Inconsistencies are everywhere, slowing us down and making us second-guess ourselves.

Existing CLI libraries are riddled with ambiguities that frustrated us. For instance, the command --FLAG 1 2 can be interpreted in multiple ways: either 1 is an option for FLAG and 2 is positional, or both 1 and 2 are options for FLAG. This behavior varies based on the parser's design and other factors. We believe that argument parsers should be stateless, meaning the parser's settings should not influence the role of any arguments. Arguments that appear before the first keyword (flag or option) are treated as positional arguments, while arguments that appear between flags are associated with the preceding flag.

This issue is just one example of many that motivated us to develop a new library. While it may not yet be perfect, we are continually seeking better solutions to these problems. Our goal is to establish a standard that enhances productivity and user satisfaction, ultimately becoming the new norm for CLIs.

As Jef Raskin stated in The Humane Interface, "Abandon a standard when it is demonstrably harmful to productivity or user satisfaction." For more details, see Chaos.

Contributing

Contributions are welcome! Please open an issue or submit a pull request on GitHub. For more detailed guidelines, refer to the CONTRIBUTING.md file.

License

This project is licensed under the MIT License. See the LICENSE file for details.

Authors

Releases

No releases published

Packages

No packages published

Languages