Description
The shell_utils library provides some handy utilities for when you need to automate certain processes using shell commands.
Where you might otherwise write a bash script or muck around with the subprocess, os, and sys modules in a Python script shell_utils provides
some patterns and shortcuts for your automation scripts.
Let's say we have a new project we need to automate some build process(es) for. We might be tempted to write a Makefile or bash script(s) to help with that task. If that works for you, great. However, if you're like me, you prefer to python-all-the-things.
We can use shell-utils to create an automation script that will behave much the same way a Makefile would, but with all the Python goodness we want.
Some familiarity with the click library will be helpful.
pip3 install shell_utils
shell_utils generate_runner
This will produce an executable python script with the following code
#!/usr/bin/env python3
import os
from pathlib import Path
from shell_utils import shell, cd, env, path, quiet
import click
@click.group()
def main():
"""
Development tasks; programmatically generated
"""
# ensure we're running commands from project root
root = Path(__file__).parent.absolute()
cwd = Path().absolute()
if root != cwd:
click.secho(f'Navigating from {cwd} to {root}',
fg='yellow')
os.chdir(root)
if __name__ == '__main__':
main()
Now let's say that we're using sphinx to generate the documentation we have in our project's docs directory.
If we wanted to create a command that would re-generate our documentation and open a browser window when it's finished,
we could add the following code to our generated run.py script
@main.command()
@click.option('--no-browser', is_flag=True, help="Don't open browser after building docs.")
def docs(no_browser):
"""
Generate Sphinx HTML documentation, including API docs.
"""
shell(
"""
rm -f docs/shell_utils.rst
rm -f docs/modules.rst
rm -rf docs/shell_utils*
sphinx-apidoc -o docs/ shell_utils
"""
)
with cd('docs'):
shell('make clean')
shell('make html')
shell('cp -rf docs/_build/html/ public/')
if no_browser:
return
shell('open public/index.html')
Then, we can execute the following command to do what we intended:
./run.py docs
The strings sent to the shell function will be executed in a bash subprocess shell. Before they are executed,
the shell function will print the command to stdout, similar to a Makefile.
Also, notice we change directories into docs using a context manager, that way the commands passed to the shell function
will execute within that directory. Once we're out of the context manager's scope, further shell function commands are once-again run
from the project root.
functions and context managers
shell
Executes the given command in a bash shell. It's just a thin wrapper around subprocess.run that adds a couple handy features,
such as printing the command it's about to run before executing it.
from shell_utils import shell
p1 = shell('echo hello, world')
print(p1)
p2 = shell('echo goodbye, cruel world', capture=True)
print('captured the string:', p2.stdout)
outputs
user@hostname executing...
echo goodbye, cruel world
captured the string: goodbye, cruel world
cd
Temporarily changes the current working directory while within the context scope.
Within a python shell...
from shell_utils import shell, cd
with cd('~'):
shell('echo $PWD')
shell('mkdir -p foo')
with cd('foo'):
shell('echo $PWD')
shell('echo $PWD')
outputs
user@hostname executing...
echo $PWD
/Users/user
user@hostname executing...
mkdir -p foo
user@hostname executing...
echo $PWD
/Users/user/foo
user@hostname executing...
echo $PWD
/Users/user
env
Temporarily changes environment variables
from shell_utils import env
import os
print(os.getenv('foo', 'nothing'))
with env(foo='bar'):
print(os.getenv('foo'))
print(os.getenv('foo', 'nothing again'))
outputs
nothing
bar
nothing again
path
A special case of the env context manager that alters your $PATH. It expands ~ to your home directory and returns
the elements of the $PATH variable as a list.
from shell_utils import path
import os
def print_path():
print('$PATH ==', os.getenv('PATH'))
print_path()
with path('~', prepend=True) as plist:
print_path()
print(plist)
outputs
$PATH == /Users/user/.venvs/shell-utils-py3.7/bin:/usr/local/sbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Library/TeX/texbin
$PATH == /Users/user:/Users/user/.venvs/shell-utils-py3.7/bin:/usr/local/sbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Library/TeX/texbin
['/Users/user', '/Users/user/.venvs/shell-utils-py3.7/bin', '/usr/local/sbin', '/usr/local/bin', '/usr/bin', '/bin', '/usr/sbin', '/sbin', '/Library/TeX/texbin']
Metadata
Release files for shell-utils 2.3.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| shell_utils-2.3.1.tar.gz | 7.5 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| shell_utils-2.3.1-py2.py3-none-any.whl | Python 2, Python 3 | none | any | Details |
Total release size: 22.3 kB
Release files / shell_utils-2.3.1.tar.gz
| Download URL | shell_utils-2.3.1.tar.gz |
|---|---|
| Size | 7.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
08e45b3675a3de7b413008016689a5025adfedb6f46f729e55cb7ebb2afaf963
|
|
BLAKE2b-256 checksum How to use checksums |
a967d74b0d95e120126113ee62f3085d684fbd48e33091bcf6e74684e8809875
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/0.11.5 CPython/3.7.0 Darwin/17.7.0
|
Release files / shell_utils-2.3.1-py2.py3-none-any.whl
| Download URL | shell_utils-2.3.1-py2.py3-none-any.whl |
|---|---|
| Size | 14.8 kB |
| Tags | Python 2 Python 3 |
|
SHA-256 checksum How to use checksums |
9e304e60d739936f13f888ee38acd5ebe8f022f845ae0da1f89eb3e3bbbcc8cf
|
|
BLAKE2b-256 checksum How to use checksums |
80a264efc899b64924a5fd3186d6f17df6650c1641d5966fe7908267a7030bef
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/0.11.5 CPython/3.7.0 Darwin/17.7.0
|
Security for shell-utils 2.3.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.