🍥️ 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 entrydony.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 keypressdony.echo(): styled text outputdony.error(): ✕ error messagedony.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)
| File | Size | Uploaded | |
|---|---|---|---|
| dony-0.6.0.tar.gz | 44.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| 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
|