Shell helper utilities for python
Project description
shil | |
Shell-util library for python. Includes helpers for subprocess invocation, shell-formatters / pretty-printers, and more. |
Overview
The shil
library provides various shell-utilities for python.
Features
Shell-formatters / pretty-printers
- A somewhat usable parser / grammar for bash
- Console support for rich & rich protocols
Subprocess Invocation
There's a lot of shell-related libraries out there, especially for invocation (see for example this list).
The interface for shil
is hopefully unsurprising, and something that's convenient but not fancy. It's a utility, and not a huge framework.
The main goal is to provide an API that is simple and stable, without a ton of dependencies.
>>> import shil
>>> proc = shil.invoke('echo hello world')
>>> assert proc.succeeded
>>> assert proc.stdout.strip()=='hello world'
>>>
Beyond such basics, shil includes support for rich output and uses pydantic for datastructures.
See the API docs for more detailed information.
Installation
See pypi for available releases.
$ pip install shil
Usage (CLI)
The shil library publishes a small CLI tool, mostly just for testing & demoing the API behaviour. See the CLI docs for the latest (autogenerated) help.
Usage (API)
See also:
- the unit-tests for some examples of library usage
- the smoke-tests for example usage of stand-alone scripts
OOP-style Dispatch
This uses shil.Invocation
and returns shil.InvocationResponse
.
>>> import shil
>>> req = cmd = shil.Invocation(command='printf hello-world\n')
>>> resp = cmd()
>>> print(resp.stdout)
hello-world
>>>
Functional approach to dispatch
Use shil.invoke
, get back shil.InvocationResponse
>>> import shil
>>> resp = shil.invoke(command='printf hello-world\n')
>>> print(resp.stdout)
hello-world
>>>
Loading data when command-output is JSON
>>> import shil
>>> cmd = shil.Invocation(command="""echo '{"foo":"bar"}'""", load_json=True)
>>> resp = cmd()
>>> print(resp.data)
{'foo': 'bar'}
>>> assert type(resp.data) == type({})
>>> assert resp.data['foo'] == 'bar'
>>>
Serialization with Pydantic
>>> import json, shil
>>> req = cmd = shil.Invocation(command="""echo pipes-are-allowed|grep allowed""")
>>> resp = cmd()
>>> keys = resp.dict().keys()
>>> expected = 'stdout stderr failed failure success succeeded data'.split()
>>> assert all([k in keys for k in expected])
>>>
Caller determines logging
Works like this with basic logger:
>>> import logging, shil
>>> logger = logging.getLogger()
>>> resp = shil.invoke('ls /tmp', command_logger=logger.critical, output_logger=logger.warning)
>>>
Supports using rich-logger too:
>>> import shil
>>> from rich.console import Console
>>> console = Console(stderr=True)
>>> resp = shil.invoke('ls /tmp', command_logger=console.log)
>>>
Rich-console Support
Besides using rich-logger as above, you can use the rich-protocol more directly.
Printing works the way you'd expect for Invocation
and InvocationResponse
.
import rich
import shil
req = cmd = shil.Invocation(command='echo {"foo":"bar"}')
resp = cmd()
rich.print(req)
rich.print(resp)
By default, output looks roughly like this:
Stay DRY with Runners
Runner's are basically just partials on shil.invoke
. It's simple but this can help reduce copying around repetitive configuration.
>>> import shil
>>> from rich.console import Console
>>> console=Console(stderr=True)
>>> runner = shil.Runner(output_logger=console.log, command_logger=console.log)
>>> resp = runner('ls /tmp')
>>> assert isinstance(resp,(shil.InvocationResult,))
>>>
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Hashes for shil-2024.2.10.0.27-py3-none-any.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 72aa6671b859a03186aae7030b94a95b04d2b1ff9bb05428379aff08273329c8 |
|
MD5 | 3fb99b799ceae57da4a5ec1d300eae7e |
|
BLAKE2b-256 | 6f05862cce88c0eb4cae26452e13a385ff5d8ccdd70831b8cde29c545351a367 |