5.2 KiB
Usage
Viv works by ensuring scripts or a given command are run in an appropriate environment with all specified dependencies.
:::{tip}
viv
is a single script and available at viv.dayl.in/viv.py
meaning every instance of viv
in these examples could be python3 <(curl -fsSL viv.dayl.in/viv.py)
:::
Run CLI Apps
Run a python app that provides an entrypoint and separate args with --
:
viv run frogmouth -- gh daylinmorgan/viv
Run a python module use the -b/--bin
flag and specify python
:
viv run rich -b python -- -m rich
Make an ephemeral jupyter
environment with your needed deps:
viv run jupyter pandas -r requirements-dev.txt -- notebook
Generate an executable shell script that will on demand create a vivenv as needed:
viv shim ruff
Output:
#!/usr/bin/env python3
# AUTOGENERATED by viv (v2023.1003)
# see `python3 <(curl -fsSL viv.dayl.in/viv.py) --help`
import subprocess
import sys
if __name__ == "__main__":
vivenv = __import__("viv").use("ruff") # noqa
sys.exit(subprocess.run([vivenv / "bin" / "ruff", *sys.argv[1:]]).returncode)
Run Python Scripts
It's possible to use the viv
CLI to run a python script.
There are several options for invoking a script.
Using the interpreter:
viv run rich typer -b python -- ./cli.py --help
Using -s/--script
:
viv run rich typer -s ./cli.py -- --help
# or with a remote script
viv run rich -s https://raw.githubusercontent.com/Textualize/rich/master/examples/fullscreen.py
If viv
is available on your path it's possible to
invoke it with embedded metadata thanks to shebangs:
#!/usr/bin/env -S viv run --keep --script
# /// script
# requires-python = ">3.10"
# dependencies = [
# "matplotlib",
# "pandas"
# ]
# ///
:::{note}
If using a shebang on a python script -s/--script
must be the last argument
:::
:::{seealso} Check out PEP723 for more info about inline script metadata. :::
In any python script with external dependencies you can also add this line prior to imports
to automate vivenv
creation and installation of dependencies.
__import__("viv").use("click")
If your dependencies are sensitive to the version of python
(numpy, cpython-based apps, etc. ) then you can specify track_exe
.
Which will lead to viv
creating a unique vivenv based on the detected python executable.
__import__("viv").use("numpy", track_exe=True)
If you'd like to pin your dependencies to a resolved environment you
can use the convenience command viv freeze
to output a list of pinned packages.
Command:
viv freeze rich typer
Output:
__import__("viv").use("rich==13.7.0", "typer==0.9.0", "click==8.1.7", "markdown-it-py==3.0.0", "Pygments==2.17.2", "typing_extensions==4.9.0", "mdurl==0.1.2") # noqa
Additionally, you can make this work regardless of PYTHONPATH
by using --path
.
Command:
viv freeze rich typer --path rel
Output:
__import__("sys").path.append(__import__("os").path.expanduser("~/.local/share/viv/")) # noqa
__import__("viv").use("rich==13.7.0", "typer==0.9.0", "click==8.1.7", "markdown-it-py==3.0.0", "Pygments==2.17.2", "typing_extensions==4.9.0", "mdurl==0.1.2") # noqa
Manage Viv
Interacting with the viv cache
Depending on how you invoke viv
, it will persist it's virtual environments (vivenvs).
To see all currently existing vivenvs use can use viv list
.
Viv will attempt to track any usages of the vivenvs including the scripts that invoke them.
You can remove any existing vivenvs using viv env remove
:
viv env remove d4b342b3
To get more information about vivenvs you can use viv list --verbose
or viv env info <hash>
:::{note}
For commands that expect a vivenv hash/name you can use as few characters as you
as you like and viv
will match it against the existing vivenvs in the cache.
:::
You can list vivenvs given a criteria using --filter
for example:
Created before 2024-01-01:
viv list --filter "created-before:2024-01-01"
Associated with a particular file:
viv list --filter "files:./script.py"
Or no files:
viv list --filter "files:None"
:::{note}
--filter "files:None"
will also apply to vivenvs
in which the original file is no longer on the disk
:::
The available filtering criteria are accessed-after
,
accessed-before
, created-before
, created-after
, spec
and files
.
To remove all vivenvs
you can use the below command:
viv env remove $(viv list -q)
To remove viv
all together you can use the included purge
command:
python3 <(curl -fsSL viv.dayl.in/viv.py) manage purge
Bonus: viv
standalone
--standalone
will auto-generate a mini function version of viv
to accomplish the same basic task as using a local copy of viv
.
After generating this standalone shim
you can freely use this script across unix machines which have python>3.8
.
See examples/black for output of below command.
viv freeze
also supports --standalone
python3 <(curl -fsSL viv.dayl.in/viv.py) shim black -o ./black --standalone --freeze