Skip to main content

🍥️ dony

A lightweight Python command runner with shell execution and user interactions.

Commands are just Python functions. You run them by running Python files directly (python deploy.py).

Installation

pip install dony

Optional dependencies:

brew install fzf     # For fuzzy selection
brew install shfmt   # For shell command formatting

Example

import asyncio
import dony

@dony.command()
async def deploy():
    """Deploy application"""

    if not await dony.confirm("Deploy to production?"):
        return

    env = await dony.select("Select environment:", ["staging", "production"])

    await dony.shell(f"""
        npm run build
        npm test
        ./deploy.sh {env}
    """)

    await dony.success(f"Deployed to {env}")

if __name__ == "__main__":
    asyncio.run(deploy())

Run with python deploy.py

CLI Support

For CLI support, use fire or any other CLI framework:

import asyncio
import dony
import fire

@dony.command()
async def build(env: str = None):
    """Build application"""

    env = env or await dony.select("Select environment:", ["staging", "production"])

    await dony.shell(f"""
        npm run build --env={env}
        npm test
    """)

    await dony.success(f"Built for {env}")

if __name__ == "__main__":
    fire.Fire(build)

Run interactively: python build.py Run with CLI args: python build.py --env=production

Recipes

Working from git repo root

import asyncio
from functools import partial
import dony

async def main():
    shell = partial(dony.shell, run_from=dony.find_repo_root(__file__))

    await shell("npm run build")
    await shell("npm test")

if __name__ == "__main__":
    asyncio.run(main())

Things to know

  • @dony.command(): marker decorator for commands (currently a no-op)
  • Available prompts based on questionary:
    • dony.input(): free-text entry
    • dony.confirm(): yes/no ([Y/n] or [y/N])
    • dony.select(): option picker (supports fuzzy)
    • dony.select_many(): multiple option picker (supports fuzzy)
    • dony.press_any_key(): pause until keypress
    • dony.echo(): styled text output
    • dony.error(): ✕ error message
    • dony.success(): ✓ success message

API Reference

async def dony.shell(
    command: str,
    run_from: Optional[Union[str, Path]] = None,   # Working directory
    dry_run: bool = False,                         # Print without executing
    quiet: bool = False,                           # Suppress printing output
    capture_output: bool = True,                   # Return output as string
    abort_on_failure: bool = True,                 # Prepends 'set -e'
    abort_on_unset_variable: bool = True,          # Prepends 'set -u'
    trace_execution: bool = False,                 # Prepends 'set -x'
    show_command: bool = True,                     # Print formatted command
    confirm: bool = False,                         # Ask before executing
) -> str:
    ...

def dony.find_repo_root(path: Union[str, Path]) -> Path:
    """Find the git root directory starting from the given path."""
    ...

License

MIT License

Author

Mark Lidenberg marklidenberg@gmail.com

Metadata

Release files for dony 0.6.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for dony 0.6.0
File Size Uploaded
dony-0.6.0.tar.gz 44.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for dony 0.6.0
File Interpreter ABI Platform
dony-0.6.0-py3-none-any.whl Python 3 none any Details

Total release size: 58.9 kB

Release files / dony-0.6.0.tar.gz

Download URL dony-0.6.0.tar.gz
Size 44.5 kB
Tags Source
SHA-256 checksum
How to use checksums
410f759a12693f7b1db43b3818ee2d1bc33c6c4e66b07ef2988bb9a994260347
BLAKE2b-256 checksum
How to use checksums
962e689103ada44071c68b8c802e7f08b6e4c2a509201549a7d4af4054ff9a52
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.7.2

Release files / dony-0.6.0-py3-none-any.whl

Download URL dony-0.6.0-py3-none-any.whl
Size 14.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
11e8534feb0e6cb40a7f83f3d503f797dd5d0937566f00da0f3826017c752471
BLAKE2b-256 checksum
How to use checksums
64d9ecb63676e3ec16b67b226728996213863131da140716c5318fc0feffd368
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.7.2

Release history Release notifications | RSS feed

This release

0.6.0 This release

2 release files

0.5.1

2 release files

0.5.0

2 release files

0.4.4

2 release files

0.4.3

2 release files

0.4.2

2 release files

0.4.1

2 release files

0.4.0

2 release files

0.3.1

2 release files

0.3.0

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.1.9

2 release files

0.1.8

2 release files

0.1.7

2 release files

0.1.6

2 release files

0.1.5

2 release files

0.1.4

2 release files

0.1.3

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page