https://github.com/brianpugh/cyclopts

Intuitive, easy CLIs based on python type hints.

https://github.com/brianpugh/cyclopts

Science Score: 26.0%

This score indicates how likely this project is to be science-related based on various indicators:

  • CITATION.cff file
  • codemeta.json file
    Found codemeta.json file
  • .zenodo.json file
    Found .zenodo.json file
  • DOI references
  • Academic publication links
  • Committers with academic emails
  • Institutional organization owner
  • JOSS paper metadata
  • Scientific vocabulary similarity
    Low similarity (16.0%) to scientific vocabulary

Keywords

argument-parser cli python shell typehints

Keywords from Contributors

project packaging archival interactive generic sequences charts optimizer distribution transformer
Last synced: 5 months ago · JSON representation

Repository

Intuitive, easy CLIs based on python type hints.

Basic Info
  • Host: GitHub
  • Owner: BrianPugh
  • License: apache-2.0
  • Language: Python
  • Default Branch: main
  • Homepage:
  • Size: 3.57 MB
Statistics
  • Stars: 802
  • Watchers: 5
  • Forks: 22
  • Open Issues: 20
  • Releases: 92
Topics
argument-parser cli python shell typehints
Created over 2 years ago · Last pushed 6 months ago
Metadata Files
Readme Contributing Funding License

README.md

![Python compat](https://img.shields.io/badge/>=python-3.9-blue.svg) [![PyPI](https://img.shields.io/pypi/v/cyclopts.svg)](https://pypi.org/project/cyclopts/) [![ReadTheDocs](https://readthedocs.org/projects/cyclopts/badge/?version=latest)](https://cyclopts.readthedocs.io) [![codecov](https://codecov.io/gh/BrianPugh/cyclopts/graph/badge.svg?token=HA393WIYUK)](https://codecov.io/gh/BrianPugh/cyclopts)

Documentation: https://cyclopts.readthedocs.io

Source Code: https://github.com/BrianPugh/cyclopts


Cyclopts is a modern, easy-to-use command-line interface (CLI) framework that aims to provide an intuitive & efficient developer experience.

Why Cyclopts?

  • Intuitive API: Quickly write CLI applications using a terse, intuitive syntax.

  • Advanced Type Hinting: Full support of all builtin types and even user-specified (yes, including Pydantic, Dataclasses, and Attrs).

  • Rich Help Generation: Automatically generates beautiful help pages from docstrings and other contextual data.

  • Extendable: Easily customize converters, validators, token parsing, and application launching.

Installation

Cyclopts requires Python >=3.9; to install Cyclopts, run:

console pip install cyclopts

Quick Start

  • Import cyclopts.run() and give it a function to run.

```python from cyclopts import run

def foo(loops: int): for i in range(loops): print(f"Looping! {i}")

run(foo) ```

Execute the script from the command line:

console $ python start.py 3 Looping! 0 Looping! 1 Looping! 2

When you need more control:

  • Create an application using cyclopts.App.
  • Register commands with the command decorator.
  • Register a default function with the default decorator.

```python from cyclopts import App

app = App()

@app.command def foo(loops: int): for i in range(loops): print(f"Looping! {i}")

@app.default def default_action(): print("Hello world! This runs when no command is specified.")

app() ```

Execute the script from the command line:

```console $ python demo.py Hello world! This runs when no command is specified.

$ python demo.py foo 3 Looping! 0 Looping! 1 Looping! 2 ``` With just a few additional lines of code, we have a full-featured CLI app. See the docs for more advanced usage.

Compared to Typer

Cyclopts is what you thought Typer was. Cyclopts's includes information from docstrings, support more complex types (even Unions and Literals!), and include proper validation support. See the documentation for a complete Typer comparison.

Consider the following short 29-line Cyclopts application:

```python import cyclopts from typing import Literal

app = cyclopts.App()

@app.command def deploy( env: Literal["dev", "staging", "prod"], replicas: int | Literal["default", "performance"] = "default", ): """Deploy code to an environment.

Parameters
----------
env
    Environment to deploy to.
replicas
    Number of workers to spin up.
"""
if replicas == "default":
    replicas = 10
elif replicas == "performance":
    replicas = 20

print(f"Deploying to {env} with {replicas} replicas.")

if name == "main": app() ```

```console $ my-script deploy --help Usage: my-script.py deploy [ARGS] [OPTIONS]

Deploy code to an environment.

╭─ Parameters ────────────────────────────────────────────────────────────────────────────────────╮ │ * ENV --env Environment to deploy to. [choices: dev, staging, prod] [required] │ │ REPLICAS --replicas Number of workers to spin up. [choices: default, performance] [default: │ │ default] │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────╯

$ my-script deploy staging Deploying to staging with 10 replicas.

$ my-script deploy staging 7 Deploying to staging with 7 replicas.

$ my-script deploy staging performance Deploying to staging with 20 replicas.

$ my-script deploy nonexistent-env ╭─ Error ────────────────────────────────────────────────────────────────────────────────────────────╮ │ Error converting value "nonexistent-env" to typing.Literal['dev', 'staging', 'prod'] for "--env". │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────╯

$ my-script --version 0.0.0 ```

In its current state, this application would be impossible to implement in Typer. However, lets see how close we can get with Typer (47-lines):

```python import typer from typing import Annotated, Literal from enum import Enum

app = typer.Typer()

class Environment(str, Enum): dev = "dev" staging = "staging" prod = "prod"

def replica_parser(value: str): if value == "default": return 10 elif value == "performance": return 20 else: return int(value)

def versioncallback(value: bool): if value: print("0.0.0") raise typer.Exit()

@app.callback() def callback( version: Annotated[ bool | None, typer.Option("--version", callback=versioncallback) ] = None, ): pass

@app.command(help="Deploy code to an environment.") def deploy( env: Annotated[Environment, typer.Argument(help="Environment to deploy to.")], replicas: Annotated[ int, typer.Argument( parser=replicaparser, help="Number of workers to spin up.", ), ] = replicaparser("default"), ): print(f"Deploying to {env.name} with {replicas} replicas.")

if name == "main": app() ```

```console $ my-script deploy --help

Usage: my-script deploy [OPTIONS] ENV:{dev|staging|prod} [REPLICAS]

Deploy code to an environment.

╭─ Arguments ─────────────────────────────────────────────────────────────────────────────────────╮ │ * env ENV:{dev|staging|prod} Environment to deploy to. [default: None] [required] │ │ replicas [REPLICAS] Number of workers to spin up. [default: 10] │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─ Options ───────────────────────────────────────────────────────────────────────────────────────╮ │ --help Show this message and exit. │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────╯

$ my-script deploy staging Deploying to staging with 10 replicas.

$ my-script deploy staging 7 Deploying to staging with 7 replicas.

$ my-script deploy staging performance Deploying to staging with 20 replicas.

$ my-script deploy nonexistent-env Usage: my-script.py deploy [OPTIONS] ENV:{dev|staging|prod} [REPLICAS] Try 'my-script.py deploy --help' for help. ╭─ Error ─────────────────────────────────────────────────────────────────────────────────────────╮ │ Invalid value for '[REPLICAS]': nonexistent-env │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────╯

$ my-script --version 0.0.0 ```

The Typer implementation is 47 lines long, while the Cyclopts implementation is just 29 (38% shorter!). Not only is the Cyclopts implementation significantly shorter, but the code is easier to read. Since Typer does not support Unions, the choices for replica could not be displayed on the help page. Cyclopts is much more terse, much more readable, and much more intuitive to use.

Owner

  • Name: Brian Pugh
  • Login: BrianPugh
  • Kind: user
  • Location: Washington D.C.

Deep Learning Scientist and blockchain enthusiast

GitHub Events

Total
  • Create event: 186
  • Release event: 42
  • Issues event: 189
  • Watch event: 407
  • Delete event: 139
  • Issue comment event: 646
  • Push event: 330
  • Pull request review comment event: 49
  • Pull request review event: 45
  • Pull request event: 279
  • Fork event: 11
Last Year
  • Create event: 186
  • Release event: 42
  • Issues event: 189
  • Watch event: 407
  • Delete event: 139
  • Issue comment event: 646
  • Push event: 330
  • Pull request review comment event: 49
  • Pull request review event: 45
  • Pull request event: 279
  • Fork event: 11

Committers

Last synced: 11 months ago

All Time
  • Total Commits: 903
  • Total Committers: 14
  • Avg Commits per committer: 64.5
  • Development Distribution Score (DDS): 0.093
Past Year
  • Commits: 600
  • Committers: 12
  • Avg Commits per committer: 50.0
  • Development Distribution Score (DDS): 0.078
Top Committers
Name Email Commits
Brian Pugh b****7@g****m 819
dependabot[bot] 4****] 64
Or Hayat o****t@v****m 6
Tin Tvrtković t****r@g****m 3
Josh Cannon j****n@g****m 2
breathe b****e 1
William Brockhus p****w@g****m 1
Pablo Speciale p****e 1
Kiyoon Kim k****n 1
Kian-Meng Ang k****g@c****g 1
Florian Daude f****e@h****r 1
Bulygin Evgeniy Andreevich t****z@g****m 1
Anders Jellinggaard a****d@3****m 1
Aneesh Agrawal a****h@a****m 1
Committer Domains (Top 20 + Academic)

Issues and Pull Requests

Last synced: 5 months ago

All Time
  • Total issues: 164
  • Total pull requests: 518
  • Average time to close issues: 12 days
  • Average time to close pull requests: 2 days
  • Total issue authors: 86
  • Total pull request authors: 18
  • Average comments per issue: 2.74
  • Average comments per pull request: 1.13
  • Merged pull requests: 358
  • Bot issues: 2
  • Bot pull requests: 226
Past Year
  • Issues: 121
  • Pull requests: 316
  • Average time to close issues: 5 days
  • Average time to close pull requests: 1 day
  • Issue authors: 68
  • Pull request authors: 13
  • Average comments per issue: 2.17
  • Average comments per pull request: 1.3
  • Merged pull requests: 224
  • Bot issues: 2
  • Bot pull requests: 125
Top Authors
Issue Authors
  • BrianPugh (12)
  • Ravencentric (8)
  • OrHayat (7)
  • thejcannon (5)
  • domWalters (4)
  • seowalex (4)
  • rbonthond (4)
  • vhdirk (4)
  • BruceEckel (4)
  • wohali (4)
  • taranlu-houzz (4)
  • hans-d (3)
  • HAOCHENYE (3)
  • beskep (3)
  • mezuzza (3)
Pull Request Authors
  • BrianPugh (256)
  • dependabot[bot] (226)
  • thejcannon (4)
  • Tinche (4)
  • OrHayat (4)
  • aneeshusa (4)
  • nachocab (3)
  • daudef (2)
  • breathe (2)
  • andersjel (2)
  • pablospe (2)
  • kiyoon (2)
  • YodaDaCoda (2)
  • ESPR3SS0 (1)
  • gremlation (1)
Top Labels
Issue Labels
enhancement (30) bug (20) v3 (6) v2 (6) usage (5) documentation (3) dependencies (2)
Pull Request Labels
dependencies (225) python (54) documentation (2) v4 (2)

Packages

  • Total packages: 1
  • Total downloads:
    • pypi 3,772,271 last-month
  • Total dependent packages: 8
  • Total dependent repositories: 0
  • Total versions: 92
  • Total maintainers: 1
pypi.org: cyclopts

Intuitive, easy CLIs based on type hints.

  • Versions: 92
  • Dependent Packages: 8
  • Dependent Repositories: 0
  • Downloads: 3,772,271 Last month
Rankings
Dependent packages count: 9.6%
Average: 38.8%
Dependent repos count: 68.0%
Maintainers (1)
Last synced: 6 months ago

Dependencies

.github/workflows/deploy.yaml actions
  • actions/cache v3 composite
  • actions/checkout v4 composite
  • actions/setup-python v4 composite
  • actions/upload-artifact v3 composite
  • snok/install-poetry v1 composite
.github/workflows/tests.yaml actions
  • actions/cache v3 composite
  • actions/checkout v4 composite
  • actions/setup-python v4 composite
  • andstor/file-existence-action v2 composite
  • codecov/codecov-action v3 composite
  • snok/install-poetry v1 composite
poetry.lock pypi
  • alabaster 0.7.13
  • appnope 0.1.3
  • arguably 1.2.5
  • asttokens 2.4.1
  • attrs 23.1.0
  • babel 2.13.1
  • backcall 0.2.0
  • certifi 2023.7.22
  • cfgv 3.4.0
  • charset-normalizer 3.3.2
  • click 8.1.7
  • colorama 0.4.6
  • coverage 7.3.2
  • decorator 5.1.1
  • distlib 0.3.7
  • docstring-parser 0.15
  • docutils 0.18.1
  • exceptiongroup 1.1.3
  • executing 2.0.1
  • filelock 3.13.1
  • fire 0.5.0
  • gitdb 4.0.11
  • gitpython 3.1.40
  • identify 2.5.31
  • idna 3.4
  • imagesize 1.4.1
  • importlib-metadata 6.8.0
  • iniconfig 2.0.0
  • ipdb 0.13.13
  • ipython 8.12.3
  • jedi 0.19.1
  • jinja2 3.1.2
  • line-profiler 4.1.2
  • markdown-it-py 3.0.0
  • markupsafe 2.1.3
  • matplotlib-inline 0.1.6
  • mdit-py-plugins 0.4.0
  • mdurl 0.1.2
  • myst-parser 2.0.0
  • nodeenv 1.8.0
  • packaging 23.2
  • parso 0.8.3
  • pexpect 4.8.0
  • pickleshare 0.7.5
  • platformdirs 3.11.0
  • pluggy 1.3.0
  • pre-commit 3.5.0
  • prompt-toolkit 3.0.39
  • ptyprocess 0.7.0
  • pure-eval 0.2.2
  • pygments 2.16.1
  • pytest 7.4.3
  • pytest-cov 4.1.0
  • pytest-mock 3.12.0
  • pytz 2023.3.post1
  • pyyaml 6.0.1
  • requests 2.31.0
  • rich 13.6.0
  • setuptools 68.2.2
  • six 1.16.0
  • smmap 5.0.1
  • snowballstemmer 2.2.0
  • sphinx 7.1.2
  • sphinx-autodoc-typehints 1.25.2
  • sphinx-copybutton 0.5.2
  • sphinx-rtd-theme 1.3.0
  • sphinxcontrib-applehelp 1.0.4
  • sphinxcontrib-devhelp 1.0.2
  • sphinxcontrib-htmlhelp 2.0.1
  • sphinxcontrib-jquery 4.1
  • sphinxcontrib-jsmath 1.0.1
  • sphinxcontrib-qthelp 1.0.3
  • sphinxcontrib-serializinghtml 1.1.5
  • stack-data 0.6.3
  • termcolor 2.3.0
  • tomli 2.0.1
  • traitlets 5.13.0
  • typer 0.9.0
  • typing-extensions 4.8.0
  • urllib3 2.0.7
  • virtualenv 20.24.6
  • wcwidth 0.2.9
  • zipp 3.17.0
pyproject.toml pypi
  • attrs >=23.1.0
  • docstring-parser ^0.15
  • python ^3.8
  • rich >=13.6.0
  • typing-extensions >=4.8.0