Skip to main content

Your all-in-one for beautiful, prod-ready CLIs

Project description

🦄 Term

Type-safe Python CLI prompts with validations, retries, custom messages, etc.

Examples

Check out the examples in ./examples! You can run them locally with:

uv run --all-extras -m examples.cli
uv run --all-extras -m examples.colors
uv run --all-extras -m examples.spinner
uv run --all-extras -m examples.prompts

CLI

# examples/basic_cli.py
from term import Command

class Lint(Command):
    files: tuple[str, ...]

    async def run(self):
        print(f"Linting {', '.join(self.files)}")

class MyCli(Command):
    subcommand: Lint | None = None
    verbose: bool = False

    async def run(self):
        print(f"Running the main command with {self.verbose}")

if __name__ == "__main__":
    cli: MyCli = MyCli.parse()
    cli.start()
uv run -m examples.basic_cli -h (Main help page)

image

uv run -m examples.basic_cli lint (Subcommand help page)

image

uv run -m examples.basic_cli (Normal run)

image

uv run -m examples.basic_cli lint (Missing args error)

image

uv run -m examples.basic_cli lin (Typo)

image

❓ Prompting

First, you'll need to import the term module:

import term

answer = term.prompt("Are you going to use Term?", default=True, parser=bool)

🌈 Colors

# demo.py
import term

# Style text
print(term.style("This is blue", fg="blue"), "and", term.style("this is red", fg="red"))

# Print with colors directly
term.print("Some colorful text", fg="green", reverse=True, bold=True, italic=True)

# Store a styler and reuse it
wrong = term.styler(fg="red", strikethrough=True)
print("The old version said", wrong("Pluto was a planet"))
print("The old version said", wrong("the Earth was flat"))
uv run demo.py

image

uv run -m term.colors

image

🌀 Spinners

# demo.py
import asyncio
from term import Spinner

async def main():
    async with Spinner("Downloading assets") as s:
        for i in range(1, 6):
            await asyncio.sleep(0.5)
            s.title = f"Downloading assets [{i}/5]"

asyncio.run(main())
uv run demo.py

uv run -m term.spinner

🐍 Type-checking

This library is fully type-checked. This means that all types will be correctly inferred from the arguments you pass in.

In this example your editor will correctly infer the type:

hours = term.prompt(
    "How many hours are there in a year?",
    parser=lambda x: float(x) if x < 24 else timedelta(days=x),
)
reveal_type(hours)  # Type of "res" is "float | timedelta"

Why do I care?

Type checking will help you catch issues way earlier in the development cycle. It will also provide nice autocomplete features in your editor that will make you faster 󱐋.

Integrations

Parsers (v6e, pydantic, etc.)

Term can be integrated with many parsers. The default recommended parser is v6e, which is automatically used if installed in your local environment to parse types more accurately. If you wish you specify any parser (from v6e or elsewhere) manually, you can do so quite easily:

CLI

import v6e
from term import Command, config

class MyCli(Command):
    files: list[Path] = config(parser=v6e.path().exists().list())

    async def run(self):
        files = [f.as_posix() for f in self.files]
        print(f"Linting {', '.join(files)}")

if __name__ == "__main__":
    cli: MyCli = MyCli.parse()
    cli.start()

Prompting

import v6e

hours = term.prompt(
    "How many hours are there in a year?",
    parser=v6e.float().lte(24).union(v6e.timedelta()),
)
reveal_type(hours)  # Type of "res" is "float | timedelta"

Project details


Release history Release notifications | RSS feed

This version

0.1.0

Download files

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

Source Distribution

clypi-0.1.0.tar.gz (37.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

clypi-0.1.0-py3-none-any.whl (22.8 kB view details)

Uploaded Python 3

File details

Details for the file clypi-0.1.0.tar.gz.

File metadata

  • Download URL: clypi-0.1.0.tar.gz
  • Upload date:
  • Size: 37.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.6.2

File hashes

Hashes for clypi-0.1.0.tar.gz
Algorithm Hash digest
SHA256 b31c2dbadd8019e172320512193394a29c27ef27886bcf6846a7c1bd0b4ce9f4
MD5 9ada94fcf2aab6da5974e0ec6a2254f1
BLAKE2b-256 ea8d11abea9c42d356fc59385f7676c1ee41caf1444087060e96fe91a515c3b4

See more details on using hashes here.

File details

Details for the file clypi-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: clypi-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 22.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.6.2

File hashes

Hashes for clypi-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 85cff06016378fcfdbc677533449c67b172b0969cc660a155ebca1f3103852ca
MD5 09d90c74132fb10d00c92d5454acb4ce
BLAKE2b-256 b8961d7bc3284a86fa6a0c7b2dfa41f468ee6957bbcaa2078c039ef5c792e2a3

See more details on using hashes here.

Supported by

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