viv/README.md

128 lines
4.3 KiB
Markdown
Raw Normal View History

2022-12-20 14:29:21 -06:00
# Viv
<!-- PROJECT DEMO -->
<div align="center">
<a href="https://github.com/daylinmorgan/viv">
<img src="https://raw.githubusercontent.com/daylinmorgan/viv/main/docs/demo.gif" alt="Logo" width=600 >
</a>
<p align="center">
viv isn't venv
</p>
</div>
<br />
2022-12-19 23:17:43 -06:00
See [usage](https://github.com/daylinmorgan/viv/blob/main/docs/usage.md) for more demo gifs.
2022-12-19 23:17:43 -06:00
## Setup
2022-12-20 10:21:42 -06:00
### Manual (Recommended)
2022-12-20 10:21:42 -06:00
Start by cloning the repo and symlinking the script for access to the CLI.
By default it will symlink `./src/viv/viv.py` to `~/bin/viv`.
2022-12-20 10:21:42 -06:00
You can set `PREFIX` to symlink to a different location.
```sh
git clone git@github.com:daylinmorgan/viv.git ~/.viv
2022-12-21 15:14:38 -06:00
cd ~/.viv
2022-12-20 10:21:42 -06:00
make install # or PREFIX=~/.local/bin make install
```
2022-12-19 23:17:43 -06:00
Place this directory on the python path in your rc file.
```sh
export PYTHONPATH="$PYTHONPATH:$HOME/.viv/src"
```
### Pypi (Not Recommended)
2022-12-19 23:17:43 -06:00
```sh
pip install viv
2022-12-19 23:17:43 -06:00
```
## Usage
Then in any python script with external dependencies you can add this line,
to automate env creation and installation of dependencies.
```python
__import__("viv").activate("click")
```
To remove all `vivenvs`:
2022-12-19 23:17:43 -06:00
```sh
viv remove $(viv list -q)
```
## Standalone Function
The below function can be freely pasted at the top of your scripts and requires
no modification of your PYTHONPATH or import of additional modules.
It can be auto-generated with for example: `viv freeze rich --standalone`.
The only part necessary to modify if copied verbatim from here is the call to `_viv_activate`.
```python
# <<<<< auto-generated by daylinmorgan/viv (v.22.12a3)
# fmt: off
def _viv_activate(*pkgs: str, track_exe: bool = False, name: str = "") -> None: # noqa
i,m,e = __import__,map,lambda x: True if x else False # noqa
if not {*m(type, pkgs)} == {str}: raise ValueError(f"spec: {pkgs} is invalid") # noqa
ge,sys,P,exe = i("os").getenv,i("sys"),i("pathlib").Path,i("sys").executable # noqa
vivcache = (P(ge("XDG_CACHE_HOME",P.home()/".cache"))/"viv"/"venvs");vivcache.mkdir(parents=True, exist_ok=True) # noqa
spec,exe_path = [*pkgs], (str(P(exe).resolve()) if track_exe else "N/A") # noqa
hash = i("hashlib").sha256(); hash.update(str(spec).encode()) # noqa
if track_exe: hash.update(exe_path.encode()) # noqa
_id = hash.hexdigest() # noqa
name, envpath = (lambda n: (n,vivcache/n))(name if name else _id) # noqa
if name not in (d.name for d in vivcache.iterdir()) or ge("VIV_FORCE"): # noqa
run = i("subprocess").run; i("venv").EnvBuilder(with_pip=True, clear=True).create(envpath) # noqa
with (envpath/"pip.conf").open("w") as f:f.write("[global]\ndisable-pip-version-check = true") # noqa
p = run([envpath/"bin"/"pip","install","--force-reinstall", *spec], universal_newlines=True, # noqa
**dict(zip(("stdout","stderr"),[(-1,-2),(None,)*2,][e(ge("VIV_VERBOSE"))]))) # noqa
if (p.returncode!=0)*envpath.is_dir():i("shutil").rmtree(str(envpath)) # noqa
2023-03-08 15:10:11 -06:00
if p.returncode!=0:sys.stderr.write(f"pip had non zero exit ({p.returncode})\n{p.stdout}");sys.exit(p.returncode) # noqa
with (envpath/"viv-info.json").open("w") as f: # noqa
i("json").dump({"created":str(i("datetime").datetime.today()),"id":_id,"spec":spec,"exe":exe},f) # noqa
sys.path = [p for p in (*sys.path, str(*(envpath/"lib").glob("py*/si*"))) if p!=i("site").USER_SITE] # noqa
2023-03-08 15:10:11 -06:00
_viv_activate("markdown-it-py==2.2.0", "mdurl==0.1.2", "Pygments==2.14.0", "rich==13.3.2")
# fmt: on
# >>>>> code golfed with <3
```
2022-12-19 23:17:43 -06:00
## Alternatives
### [pip-run](https://github.com/jaraco/pip-run)
```sh
pip-run (10.0.5)
├── autocommand (2.2.2)
├── jaraco-context (4.3.0)
├── jaraco-functools (3.6.0)
│ └── more-itertools (9.1.0)
├── jaraco-text (3.11.1)
│ ├── autocommand (2.2.2)
│ ├── inflect (6.0.2)
│ │ └── pydantic>=1.9.1 (1.10.5)
│ │ └── typing-extensions>=4.2.0 (4.5.0)
│ ├── jaraco-context>=4.1 (4.3.0)
│ ├── jaraco-functools (3.6.0)
│ │ └── more-itertools (9.1.0)
│ └── more-itertools (9.1.0)
├── more-itertools>=8.3 (9.1.0)
├── packaging (23.0)
├── path>=15.1 (16.6.0)
├── pip>=19.3 (23.0.1)
└── platformdirs (3.1.0)
```
### [pipx](https://github.com/pypa/pipx/)
```sh
pipx (1.1.0)
├── argcomplete>=1.9.4 (2.1.1)
├── packaging>=20.0 (23.0)
└── userpath>=1.6.0 (1.8.0)
└── click (8.1.3)
```