viv/docs/usage.md

203 lines
5.1 KiB
Markdown
Raw Normal View History

# Usage
2024-01-03 15:58:44 -06:00
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 `--`:
```sh
viv run frogmouth -- gh daylinmorgan/viv
```
To run a python module use the `-b/--bin` flag and specify `python`:
```sh
viv run rich -b python -- -m rich
```
Make an ephemeral `jupyter` environment with your needed deps:
```sh
viv run jupyter pandas -r requirements-dev.txt -- notebook
```
Generate an executable shell script that will on demand create a vivenv as needed:
```sh
viv shim ruff
```
Output:
```python
#!/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:
```sh
viv run rich typer -b python -- ./cli.py --help
```
Using `-s/--script`:
```sh
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:
```python
#!/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](https://peps.python.org/pep-0723/) 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.
```python
__import__("viv").use("click")
```
2024-01-03 15:58:44 -06:00
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.
```python
__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.
2024-01-03 15:58:44 -06:00
Command:
```sh
2024-01-03 15:58:44 -06:00
viv freeze rich typer
```
2024-01-03 15:58:44 -06:00
Output:
```python
__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`.
2024-01-03 15:58:44 -06:00
Command:
```sh
2024-01-03 15:58:44 -06:00
viv freeze rich typer --path rel
```
Output:
```python
__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
```
2024-01-03 15:58:44 -06:00
## 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`.
2024-01-03 15:58:44 -06:00
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`:
```sh
2024-01-03 15:58:44 -06:00
viv env remove d4b342b3
```
2024-01-03 15:58:44 -06:00
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:
```sh
2024-01-03 15:58:44 -06:00
viv list --filter "created-before:2024-01-01"
```
2024-01-03 15:58:44 -06:00
Associated with a particular file:
```sh
viv list --filter "files:./script.py"
```
2024-01-03 15:58:44 -06:00
Or no files:
```sh
2024-01-03 15:58:44 -06:00
viv list --filter "files:None"
```
2024-01-03 15:58:44 -06:00
```{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`, and `files`.
To remove all `vivenvs` you can use the below command:
```sh
2024-01-03 15:58:44 -06:00
viv env remove $(viv list -q)
```
2024-01-03 15:58:44 -06:00
To remove `viv` all together you can use the included `purge` command:
```sh
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](https://github.com/daylinmorgan/viv/blob/dev/examples/black) for output of below command.
`viv freeze` also supports `--standalone`
```sh
python3 <(curl -fsSL viv.dayl.in/viv.py) shim black -o ./black --standalone --freeze
```