mirror of
https://github.com/daylinmorgan/viv.git
synced 2025-02-22 07:15:49 -06:00
Compare commits
No commits in common. "852ce927c0476ace28ac96c0cb1296aa75520ea7" and "6d52afe4fe3896886090ace88dce51a65d92839a" have entirely different histories.
852ce927c0
...
6d52afe4fe
36 changed files with 915 additions and 3488 deletions
32
.github/ISSUE_TEMPLATE/bug.yml
vendored
32
.github/ISSUE_TEMPLATE/bug.yml
vendored
|
@ -1,32 +0,0 @@
|
||||||
name: Bug Report
|
|
||||||
description: File a bug report
|
|
||||||
labels: ["bug"]
|
|
||||||
body:
|
|
||||||
- type: markdown
|
|
||||||
attributes:
|
|
||||||
value: |
|
|
||||||
A bug is when something works differently than it is expected to.
|
|
||||||
## Remember to search before filing a new report
|
|
||||||
Please search for this bug in the issue tracker, and use a bug report title that
|
|
||||||
would have made your bug report turn up in the search results for your search query.
|
|
||||||
- type: textarea
|
|
||||||
id: version
|
|
||||||
attributes:
|
|
||||||
label: "Viv & python/pip version info"
|
|
||||||
description: Please include the output of `viv manage show --system` or `python3 <(curl -fsSL viv.dayl.in/viv.py) manage show --system`
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: textarea
|
|
||||||
id: repro
|
|
||||||
attributes:
|
|
||||||
label: Steps to Reproduce and Observed Behavior
|
|
||||||
description: What exactly can someone else do, in order to observe the problem that you observed? Include the output and all error messages.
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: textarea
|
|
||||||
id: expected
|
|
||||||
attributes:
|
|
||||||
label: Expected Behavior
|
|
||||||
description: What did you expect to happen instead?
|
|
||||||
validations:
|
|
||||||
required: true
|
|
15
.github/workflows/release.yml
vendored
15
.github/workflows/release.yml
vendored
|
@ -9,27 +9,24 @@ permissions:
|
||||||
contents: write
|
contents: write
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
run-tests:
|
|
||||||
uses: ./.github/workflows/test.yml
|
|
||||||
|
|
||||||
build-n-publish:
|
build-n-publish:
|
||||||
needs: run-tests
|
|
||||||
permissions:
|
permissions:
|
||||||
id-token: write
|
id-token: write
|
||||||
uses: ./.github/workflows/pypi.yml
|
uses: ./.github/workflows/pypi.yml
|
||||||
|
|
||||||
create-release:
|
create-release:
|
||||||
needs: build-n-publish
|
|
||||||
env:
|
env:
|
||||||
GH_TOKEN: ${{ github.token }}
|
GH_TOKEN: ${{ github.token }}
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: update latest branch
|
- name: update latest tag
|
||||||
run: |
|
uses: richardsimko/update-tag@v1
|
||||||
git checkout -B latest
|
with:
|
||||||
git push --force-with-lease -u origin latest
|
tag_name: latest
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
- name: Generate New Release
|
- name: Generate New Release
|
||||||
run: gh release create ${{ github.ref }}
|
run: gh release create ${{ github.ref }}
|
||||||
|
|
37
.github/workflows/test.yml
vendored
37
.github/workflows/test.yml
vendored
|
@ -1,37 +0,0 @@
|
||||||
name: 🧪 Run Tests
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
workflow_call:
|
|
||||||
workflow_dispatch:
|
|
||||||
push:
|
|
||||||
paths:
|
|
||||||
- 'src/**/*.py'
|
|
||||||
- 'tests/**/*.py'
|
|
||||||
- 'pyproject.toml'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
run-tests:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
python-version: ['3.8','3.9','3.10','3.11', '3.12']
|
|
||||||
os:
|
|
||||||
- ubuntu-latest
|
|
||||||
- windows-latest
|
|
||||||
# - macos-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Set up PDM
|
|
||||||
uses: pdm-project/setup-pdm@v3
|
|
||||||
with:
|
|
||||||
python-version: ${{ matrix.python-version}}
|
|
||||||
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pdm sync -d -G test
|
|
||||||
|
|
||||||
- name: Run Tests
|
|
||||||
run: pdm run -v pytest tests
|
|
||||||
|
|
||||||
|
|
7
.gitignore
vendored
7
.gitignore
vendored
|
@ -170,11 +170,8 @@ poetry.toml
|
||||||
|
|
||||||
# End of https://www.toptal.com/developers/gitignore/api/python
|
# End of https://www.toptal.com/developers/gitignore/api/python
|
||||||
.task.mk
|
.task.mk
|
||||||
|
# copy of README.md
|
||||||
|
docs/index.md
|
||||||
docs/cli.md
|
docs/cli.md
|
||||||
docs/viv.py
|
docs/viv.py
|
||||||
docs/svgs
|
docs/svgs
|
||||||
docs/public
|
|
||||||
/tests/.viv-cache
|
|
||||||
/scripts/tomli
|
|
||||||
/scripts/packaging
|
|
||||||
|
|
|
@ -1,9 +1,13 @@
|
||||||
# See https://pre-commit.com for more information
|
# See https://pre-commit.com for more information
|
||||||
# See https://pre-commit.com/hooks.html for more hooks
|
# See https://pre-commit.com/hooks.html for more hooks
|
||||||
repos:
|
repos:
|
||||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
- repo: https://github.com/psf/black
|
||||||
rev: v0.1.10
|
rev: 23.3.0
|
||||||
|
hooks:
|
||||||
|
- id: black
|
||||||
|
language_version: python
|
||||||
|
- repo: https://github.com/charliermarsh/ruff-pre-commit
|
||||||
|
rev: 'v0.0.270'
|
||||||
hooks:
|
hooks:
|
||||||
- id: ruff-format
|
|
||||||
- id: ruff
|
- id: ruff
|
||||||
args: [ --fix ]
|
args: [--fix, --exit-non-zero-on-fix, --show-fixes]
|
||||||
|
|
6
.task.cfg.mk
Normal file
6
.task.cfg.mk
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
USAGE={a.bold}{a.cyan} viv tasks{a.end}:\n
|
||||||
|
PHONIFY=1
|
||||||
|
HELP_SEP={a.b_blue}>>>{a.end}
|
||||||
|
|
||||||
|
-include .task.mk
|
||||||
|
$(if $(filter help,$(MAKECMDGOALS)),$(if $(wildcard .task.mk),,.task.mk: ; curl -fsSL https://raw.githubusercontent.com/daylinmorgan/task.mk/v23.1.2/task.mk -o .task.mk))
|
38
Makefile
Normal file
38
Makefile
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
VERSION ?= $(shell git describe --tags --always --dirty=-dev | sed 's/^v//g')
|
||||||
|
|
||||||
|
venv: ## generate environment
|
||||||
|
pdm install
|
||||||
|
|
||||||
|
assets/viv-help.svg:
|
||||||
|
FORCE_COLOR=1 viv --help | yartsu -t 'viv --help' -w 70 -o $@
|
||||||
|
|
||||||
|
.PHONY: dev-install
|
||||||
|
dev-install:
|
||||||
|
ln -sf $(PWD)/src/viv/viv.py ~/.local/share/viv/viv.py
|
||||||
|
|
||||||
|
## docs |> update docs files
|
||||||
|
docs: docs/viv.py docs/index.md
|
||||||
|
|
||||||
|
docs/viv.py: src/viv/viv.py
|
||||||
|
@cp $< $@
|
||||||
|
|
||||||
|
docs/index.md: README.md
|
||||||
|
@printf -- '---\nhide: [navigation]\n---\n\n' > $@
|
||||||
|
@cat $< >> $@
|
||||||
|
|
||||||
|
examples/black: .FORCE
|
||||||
|
rm -f $@
|
||||||
|
viv shim black -y -s -f -o $@
|
||||||
|
|
||||||
|
clean: ## remove build artifacts
|
||||||
|
rm -rf {build,dist}
|
||||||
|
|
||||||
|
EXAMPLES = cli.py sys_path.py exe_specific.py frozen_import.py named_env.py scrape.py
|
||||||
|
generate-example-vivens: ##
|
||||||
|
for f in $(EXAMPLES); \
|
||||||
|
do python examples/$$f; done
|
||||||
|
|
||||||
|
|
||||||
|
.FORCE:
|
||||||
|
.PHONY: .FORCE
|
||||||
|
-include .task.cfg.mk
|
59
README.md
59
README.md
|
@ -29,18 +29,20 @@
|
||||||
|
|
||||||
Try before you buy!
|
Try before you buy!
|
||||||
```sh
|
```sh
|
||||||
python3 <(curl -fsSL viv.dayl.in/viv.py) run frogmouth -- gh daylinmorgan/viv
|
python3 <(curl -fsSL viv.dayl.in/viv.py) run pycowsay -- "viv isn't venv\!"
|
||||||
```
|
```
|
||||||
---
|
---
|
||||||
|
|
||||||
`Viv` is a standalone dependency-free `venv` creator (just needs python + pip).
|
`Viv` is a standalone dependency-free `venv` creator [^1].
|
||||||
`Viv` helps you ignore silly things like managing temporary or rarely used virtual environments,
|
`Viv` helps you ignore silly things like managing temporary or rarely used virtual environments,
|
||||||
while still unleashing the full power of python scripting with it's entire ecosystem at your disposal.
|
while still unleashing the full power of python scripting with it's entire ecosystem at your disposal.
|
||||||
|
|
||||||
`Viv`'s uncompromising insistence on portability means that it will always,
|
`Viv`'s uncompromising insistence on portability means that it will always:
|
||||||
only use the standard library and never exceed a single script.
|
|
||||||
|
|
||||||
See the [documentation](https://viv.dayl.in) or the [examples](https://github.com/daylinmorgan/viv/tree/main/examples) to get started.
|
1. only use the standard library
|
||||||
|
2. never exceed a single script.
|
||||||
|
|
||||||
|
For that reason any usage of the `cli` can be accomplished using a remote copy as seen in the below install command.
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
@ -50,9 +52,8 @@ Run the below command to install `viv`.
|
||||||
python3 <(curl -fsSL viv.dayl.in/viv.py) manage install
|
python3 <(curl -fsSL viv.dayl.in/viv.py) manage install
|
||||||
```
|
```
|
||||||
|
|
||||||
To access `viv` from within scripts you should add its location to your `PYTHONPATH`.
|
To access `viv` from within scripts you should add it's location to your `PYTHONPATH`.
|
||||||
By default `viv` will be installed to `$XDG_DATA_HOME/viv` or `~/.local/share/viv`;
|
By default `viv` will be installed to `$XDG_DATA_HOME/viv` or `~/.local/share/viv` you can customize this with `--src`.
|
||||||
you can customize this with `--src`.
|
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
export PYTHONPATH="$PYTHONPATH:$HOME/.local/share/viv"
|
export PYTHONPATH="$PYTHONPATH:$HOME/.local/share/viv"
|
||||||
|
@ -64,48 +65,34 @@ export PYTHONPATH="$PYTHONPATH:$HOME/.local/share/viv"
|
||||||
pip install viv
|
pip install viv
|
||||||
```
|
```
|
||||||
|
|
||||||
Why is this *not recommended?* Mainly because `viv` is all about hacking your `sys.path`.
|
Why is this *not recommended*? Mainly, because `viv` is all about hacking your `sys.path`.
|
||||||
Placing it in its own virtual environment or installing in a user site directory may complicate this endeavor.
|
Placing it in it's own virtual environment or installing in a user site directory may complicate this endeavor.
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
In any Python script with external dependencies you can add this line
|
In any python script with external dependencies you can add this line,
|
||||||
to automate `vivenv` creation and installation of dependencies.
|
to automate `vivenv` creation and installation of dependencies.
|
||||||
|
|
||||||
As a cli:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
viv run frogmouth -- gh daylinmorgan/viv
|
|
||||||
```
|
|
||||||
|
|
||||||
As a python module:
|
|
||||||
|
|
||||||
```python
|
```python
|
||||||
__import__("viv").use("click")
|
__import__("viv").use("click")
|
||||||
```
|
```
|
||||||
|
|
||||||
As an app installer:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
viv shim ruff
|
|
||||||
```
|
|
||||||
|
|
||||||
To remove all `vivenvs` you can use the below command:
|
To remove all `vivenvs` you can use the below command:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
viv env remove $(viv list -q)
|
viv cache remove $(viv list -q)
|
||||||
```
|
```
|
||||||
|
|
||||||
To remove `viv` altogether you can use the included `purge` command:
|
To remove `viv` all together you can use the included `purge` command:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
python3 <(curl -fsSL viv.dayl.in/viv.py) manage purge
|
python3 <(curl -fsSL viv.dayl.in/viv.py) manage purge
|
||||||
```
|
```
|
||||||
|
|
||||||
## Equivalent commands from alternatives
|
## Equivalent commands from alternatives
|
||||||
|
|
||||||
### [pip-run](https://github.com/jaraco/pip-run)
|
### [pip-run](https://github.com/jaraco/pip-run)
|
||||||
|
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
pip-run cowsay -- -m cowsay "moove over, pip-run"
|
pip-run cowsay -- -m cowsay "moove over, pip-run"
|
||||||
python3 <(curl -fsSL viv.dayl.in/viv.py) run cowsay -- "moove over, pip-run"
|
python3 <(curl -fsSL viv.dayl.in/viv.py) run cowsay -- "moove over, pip-run"
|
||||||
|
@ -113,7 +100,7 @@ python3 <(curl -fsSL viv.dayl.in/viv.py) run cowsay -- "moove over, pip-run"
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
python -m pip-run requests -- -c "import requests; print(requests.get('https://pypi.org/project/pip-run').status_code)"
|
python -m pip-run requests -- -c "import requests; print(requests.get('https://pypi.org/project/pip-run').status_code)"
|
||||||
python -m viv run requests -b python -- -c "import requests; print(requests.get('https://pypi.org/project/viv').status_code)"
|
python -m viv requests -b python -- -c "import requests; print(requests.get('https://pypi.org/project/viv').status_code)"
|
||||||
```
|
```
|
||||||
|
|
||||||
### [pipx](https://github.com/pypa/pipx/)
|
### [pipx](https://github.com/pypa/pipx/)
|
||||||
|
@ -131,19 +118,19 @@ python3 <(curl -fsSL viv.dayl.in/viv.py) run \
|
||||||
|
|
||||||
## Bonus: use `viv` with just standalone snippet (37LOC)
|
## Bonus: use `viv` with just standalone snippet (37LOC)
|
||||||
|
|
||||||
`--standalone` will auto-generate a mini-function version of `viv`
|
`--standalone` will auto-generate a mini function version of `viv` to accomplish the same basic task as using a local copy 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`.
|
||||||
After generating this standalone shim you can freely use this script
|
See [examples/black](https://github.com/daylinmorgan/viv/blob/dev/examples/black) for output of below command.
|
||||||
across Unix machines which have Python > 3.8.
|
|
||||||
See [examples/black](https://github.com/daylinmorgan/viv/blob/dev/examples/black)
|
|
||||||
for output of the below command.
|
|
||||||
|
|
||||||
`viv freeze` also supports `--standalone`.
|
`viv freeze` also supports `--standalone`
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
python3 <(curl -fsSL viv.dayl.in/viv.py) shim black -o ./black --standalone --freeze
|
python3 <(curl -fsSL viv.dayl.in/viv.py) shim black -o ./black --standalone --freeze
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
[^1]: You do need to have `pip` but surely you have `pip` already.
|
||||||
|
|
||||||
[conda-shield]: https://img.shields.io/conda/vn/conda-forge/viv
|
[conda-shield]: https://img.shields.io/conda/vn/conda-forge/viv
|
||||||
[conda-url]: https://anaconda.org/conda-forge/viv
|
[conda-url]: https://anaconda.org/conda-forge/viv
|
||||||
[pypi-shield]: https://img.shields.io/pypi/v/viv
|
[pypi-shield]: https://img.shields.io/pypi/v/viv
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<svg class="rich-terminal shadow" viewBox="0 0 890.3333333333334 521.5333333333333" xmlns="http://www.w3.org/2000/svg">
|
<svg class="rich-terminal shadow" viewBox="0 0 890.3333333333334 545.9333333333333" xmlns="http://www.w3.org/2000/svg">
|
||||||
<!-- Generated with Rich https://www.textualize.io & yartsu https://github.com/daylinmorgan/yartsu -->
|
<!-- Generated with Rich https://www.textualize.io & yartsu https://github.com/daylinmorgan/yartsu -->
|
||||||
<style>
|
<style>
|
||||||
|
|
||||||
|
@ -19,14 +19,14 @@
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
}
|
}
|
||||||
|
|
||||||
.terminal-4099597553-matrix {
|
.terminal-1538990771-matrix {
|
||||||
font-family: Fira Code, monospace;
|
font-family: Fira Code, monospace;
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
line-height: 24.4px;
|
line-height: 24.4px;
|
||||||
font-variant-east-asian: full-width;
|
font-variant-east-asian: full-width;
|
||||||
}
|
}
|
||||||
|
|
||||||
.terminal-4099597553-title {
|
.terminal-1538990771-title {
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
font-family: arial;
|
font-family: arial;
|
||||||
|
@ -36,98 +36,102 @@
|
||||||
-webkit-filter: drop-shadow( 2px 5px 2px rgba(0, 0, 0, .7));
|
-webkit-filter: drop-shadow( 2px 5px 2px rgba(0, 0, 0, .7));
|
||||||
filter: drop-shadow( 2px 5px 2px rgba(0, 0, 0, .7));
|
filter: drop-shadow( 2px 5px 2px rgba(0, 0, 0, .7));
|
||||||
}
|
}
|
||||||
.terminal-4099597553-r1 { fill: #94e2d5;font-weight: bold }
|
.terminal-1538990771-r1 { fill: #94e2d5;font-weight: bold }
|
||||||
.terminal-4099597553-r2 { fill: #c6d0f5 }
|
.terminal-1538990771-r2 { fill: #c6d0f5 }
|
||||||
.terminal-4099597553-r3 { fill: #f5c2e7;font-weight: bold }
|
.terminal-1538990771-r3 { fill: #f5c2e7;font-weight: bold }
|
||||||
.terminal-4099597553-r4 { fill: #c6d0f5;font-weight: bold }
|
.terminal-1538990771-r4 { fill: #c6d0f5;font-weight: bold }
|
||||||
.terminal-4099597553-r5 { fill: #f9e2af;font-weight: bold }
|
.terminal-1538990771-r5 { fill: #f9e2af;font-weight: bold }
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<defs>
|
<defs>
|
||||||
<clipPath id="terminal-4099597553-clip-terminal">
|
<clipPath id="terminal-1538990771-clip-terminal">
|
||||||
<rect x="0" y="0" width="853.0" height="438.2" />
|
<rect x="0" y="0" width="853.0" height="462.59999999999997" />
|
||||||
</clipPath>
|
</clipPath>
|
||||||
<clipPath id="terminal-4099597553-line-0">
|
<clipPath id="terminal-1538990771-line-0">
|
||||||
<rect x="0" y="1.5" width="854" height="24.65"/>
|
<rect x="0" y="1.5" width="854" height="24.65"/>
|
||||||
</clipPath>
|
</clipPath>
|
||||||
<clipPath id="terminal-4099597553-line-1">
|
<clipPath id="terminal-1538990771-line-1">
|
||||||
<rect x="0" y="25.9" width="854" height="24.65"/>
|
<rect x="0" y="25.9" width="854" height="24.65"/>
|
||||||
</clipPath>
|
</clipPath>
|
||||||
<clipPath id="terminal-4099597553-line-2">
|
<clipPath id="terminal-1538990771-line-2">
|
||||||
<rect x="0" y="50.3" width="854" height="24.65"/>
|
<rect x="0" y="50.3" width="854" height="24.65"/>
|
||||||
</clipPath>
|
</clipPath>
|
||||||
<clipPath id="terminal-4099597553-line-3">
|
<clipPath id="terminal-1538990771-line-3">
|
||||||
<rect x="0" y="74.7" width="854" height="24.65"/>
|
<rect x="0" y="74.7" width="854" height="24.65"/>
|
||||||
</clipPath>
|
</clipPath>
|
||||||
<clipPath id="terminal-4099597553-line-4">
|
<clipPath id="terminal-1538990771-line-4">
|
||||||
<rect x="0" y="99.1" width="854" height="24.65"/>
|
<rect x="0" y="99.1" width="854" height="24.65"/>
|
||||||
</clipPath>
|
</clipPath>
|
||||||
<clipPath id="terminal-4099597553-line-5">
|
<clipPath id="terminal-1538990771-line-5">
|
||||||
<rect x="0" y="123.5" width="854" height="24.65"/>
|
<rect x="0" y="123.5" width="854" height="24.65"/>
|
||||||
</clipPath>
|
</clipPath>
|
||||||
<clipPath id="terminal-4099597553-line-6">
|
<clipPath id="terminal-1538990771-line-6">
|
||||||
<rect x="0" y="147.9" width="854" height="24.65"/>
|
<rect x="0" y="147.9" width="854" height="24.65"/>
|
||||||
</clipPath>
|
</clipPath>
|
||||||
<clipPath id="terminal-4099597553-line-7">
|
<clipPath id="terminal-1538990771-line-7">
|
||||||
<rect x="0" y="172.3" width="854" height="24.65"/>
|
<rect x="0" y="172.3" width="854" height="24.65"/>
|
||||||
</clipPath>
|
</clipPath>
|
||||||
<clipPath id="terminal-4099597553-line-8">
|
<clipPath id="terminal-1538990771-line-8">
|
||||||
<rect x="0" y="196.7" width="854" height="24.65"/>
|
<rect x="0" y="196.7" width="854" height="24.65"/>
|
||||||
</clipPath>
|
</clipPath>
|
||||||
<clipPath id="terminal-4099597553-line-9">
|
<clipPath id="terminal-1538990771-line-9">
|
||||||
<rect x="0" y="221.1" width="854" height="24.65"/>
|
<rect x="0" y="221.1" width="854" height="24.65"/>
|
||||||
</clipPath>
|
</clipPath>
|
||||||
<clipPath id="terminal-4099597553-line-10">
|
<clipPath id="terminal-1538990771-line-10">
|
||||||
<rect x="0" y="245.5" width="854" height="24.65"/>
|
<rect x="0" y="245.5" width="854" height="24.65"/>
|
||||||
</clipPath>
|
</clipPath>
|
||||||
<clipPath id="terminal-4099597553-line-11">
|
<clipPath id="terminal-1538990771-line-11">
|
||||||
<rect x="0" y="269.9" width="854" height="24.65"/>
|
<rect x="0" y="269.9" width="854" height="24.65"/>
|
||||||
</clipPath>
|
</clipPath>
|
||||||
<clipPath id="terminal-4099597553-line-12">
|
<clipPath id="terminal-1538990771-line-12">
|
||||||
<rect x="0" y="294.3" width="854" height="24.65"/>
|
<rect x="0" y="294.3" width="854" height="24.65"/>
|
||||||
</clipPath>
|
</clipPath>
|
||||||
<clipPath id="terminal-4099597553-line-13">
|
<clipPath id="terminal-1538990771-line-13">
|
||||||
<rect x="0" y="318.7" width="854" height="24.65"/>
|
<rect x="0" y="318.7" width="854" height="24.65"/>
|
||||||
</clipPath>
|
</clipPath>
|
||||||
<clipPath id="terminal-4099597553-line-14">
|
<clipPath id="terminal-1538990771-line-14">
|
||||||
<rect x="0" y="343.1" width="854" height="24.65"/>
|
<rect x="0" y="343.1" width="854" height="24.65"/>
|
||||||
</clipPath>
|
</clipPath>
|
||||||
<clipPath id="terminal-4099597553-line-15">
|
<clipPath id="terminal-1538990771-line-15">
|
||||||
<rect x="0" y="367.5" width="854" height="24.65"/>
|
<rect x="0" y="367.5" width="854" height="24.65"/>
|
||||||
</clipPath>
|
</clipPath>
|
||||||
<clipPath id="terminal-4099597553-line-16">
|
<clipPath id="terminal-1538990771-line-16">
|
||||||
<rect x="0" y="391.9" width="854" height="24.65"/>
|
<rect x="0" y="391.9" width="854" height="24.65"/>
|
||||||
</clipPath>
|
</clipPath>
|
||||||
|
<clipPath id="terminal-1538990771-line-17">
|
||||||
|
<rect x="0" y="416.3" width="854" height="24.65"/>
|
||||||
|
</clipPath>
|
||||||
</defs>
|
</defs>
|
||||||
|
|
||||||
<rect fill="#1e1e2e" stroke="rgba(255,255,255,0.35)" stroke-width="1" x="10.1667" y="1" width="870" height="487.2" rx="8"/><text class="terminal-4099597553-title" fill="#c6d0f5" text-anchor="middle" x="435" y="27">viv --help</text>
|
<rect fill="#1e1e2e" stroke="rgba(255,255,255,0.35)" stroke-width="1" x="10.1667" y="1" width="870" height="511.6" rx="8"/><text class="terminal-1538990771-title" fill="#c6d0f5" text-anchor="middle" x="435" y="27">viv --help</text>
|
||||||
<g transform="translate(32,22)">
|
<g transform="translate(32,22)">
|
||||||
<circle cx="0" cy="0" r="7" fill="#ff5f57"/>
|
<circle cx="0" cy="0" r="7" fill="#ff5f57"/>
|
||||||
<circle cx="22" cy="0" r="7" fill="#febc2e"/>
|
<circle cx="22" cy="0" r="7" fill="#febc2e"/>
|
||||||
<circle cx="44" cy="0" r="7" fill="#28c840"/>
|
<circle cx="44" cy="0" r="7" fill="#28c840"/>
|
||||||
</g>
|
</g>
|
||||||
|
|
||||||
<g transform="translate(18.166666666666664, 41) scale(.95)" clip-path="url(#terminal-4099597553-clip-terminal)">
|
<g transform="translate(18.166666666666664, 41) scale(.95)" clip-path="url(#terminal-1538990771-clip-terminal)">
|
||||||
|
|
||||||
<g class="terminal-4099597553-matrix">
|
<g class="terminal-1538990771-matrix">
|
||||||
<text class="terminal-4099597553-r1" x="0" y="20" textLength="61" clip-path="url(#terminal-4099597553-line-0)">usage</text><text class="terminal-4099597553-r2" x="61" y="20" textLength="353.8" clip-path="url(#terminal-4099597553-line-0)">: viv [-h] [-V] <sub-cmd> ...</text><text class="terminal-4099597553-r2" x="854" y="20" textLength="12.2" clip-path="url(#terminal-4099597553-line-0)">
|
<text class="terminal-1538990771-r1" x="0" y="20" textLength="61" clip-path="url(#terminal-1538990771-line-0)">usage</text><text class="terminal-1538990771-r2" x="61" y="20" textLength="353.8" clip-path="url(#terminal-1538990771-line-0)">: viv [-h] [-V] <sub-cmd> ...</text><text class="terminal-1538990771-r2" x="854" y="20" textLength="12.2" clip-path="url(#terminal-1538990771-line-0)">
|
||||||
</text><text class="terminal-4099597553-r2" x="854" y="44.4" textLength="12.2" clip-path="url(#terminal-4099597553-line-1)">
|
</text><text class="terminal-1538990771-r2" x="854" y="44.4" textLength="12.2" clip-path="url(#terminal-1538990771-line-1)">
|
||||||
</text><text class="terminal-4099597553-r3" x="0" y="68.8" textLength="12.2" clip-path="url(#terminal-4099597553-line-2)">v</text><text class="terminal-4099597553-r1" x="12.2" y="68.8" textLength="24.4" clip-path="url(#terminal-4099597553-line-2)">iv</text><text class="terminal-4099597553-r3" x="48.8" y="68.8" textLength="12.2" clip-path="url(#terminal-4099597553-line-2)">i</text><text class="terminal-4099597553-r1" x="61" y="68.8" textLength="48.8" clip-path="url(#terminal-4099597553-line-2)">sn't</text><text class="terminal-4099597553-r3" x="122" y="68.8" textLength="12.2" clip-path="url(#terminal-4099597553-line-2)">v</text><text class="terminal-4099597553-r1" x="134.2" y="68.8" textLength="36.6" clip-path="url(#terminal-4099597553-line-2)">env</text><text class="terminal-4099597553-r2" x="854" y="68.8" textLength="12.2" clip-path="url(#terminal-4099597553-line-2)">
|
</text><text class="terminal-1538990771-r3" x="0" y="68.8" textLength="12.2" clip-path="url(#terminal-1538990771-line-2)">v</text><text class="terminal-1538990771-r1" x="12.2" y="68.8" textLength="24.4" clip-path="url(#terminal-1538990771-line-2)">iv</text><text class="terminal-1538990771-r3" x="48.8" y="68.8" textLength="12.2" clip-path="url(#terminal-1538990771-line-2)">i</text><text class="terminal-1538990771-r1" x="61" y="68.8" textLength="48.8" clip-path="url(#terminal-1538990771-line-2)">sn't</text><text class="terminal-1538990771-r3" x="122" y="68.8" textLength="12.2" clip-path="url(#terminal-1538990771-line-2)">v</text><text class="terminal-1538990771-r1" x="134.2" y="68.8" textLength="36.6" clip-path="url(#terminal-1538990771-line-2)">env</text><text class="terminal-1538990771-r2" x="854" y="68.8" textLength="12.2" clip-path="url(#terminal-1538990771-line-2)">
|
||||||
</text><text class="terminal-4099597553-r2" x="0" y="93.2" textLength="183" clip-path="url(#terminal-4099597553-line-3)">command line: `</text><text class="terminal-4099597553-r4" x="183" y="93.2" textLength="475.8" clip-path="url(#terminal-4099597553-line-3)">viv run typer rich-click -s ./script.py</text><text class="terminal-4099597553-r2" x="658.8" y="93.2" textLength="12.2" clip-path="url(#terminal-4099597553-line-3)">`</text><text class="terminal-4099597553-r2" x="854" y="93.2" textLength="12.2" clip-path="url(#terminal-4099597553-line-3)">
|
</text><text class="terminal-1538990771-r2" x="0" y="93.2" textLength="183" clip-path="url(#terminal-1538990771-line-3)">command line: `</text><text class="terminal-1538990771-r4" x="183" y="93.2" textLength="475.8" clip-path="url(#terminal-1538990771-line-3)">viv run typer rich-click -s ./script.py</text><text class="terminal-1538990771-r2" x="658.8" y="93.2" textLength="12.2" clip-path="url(#terminal-1538990771-line-3)">`</text><text class="terminal-1538990771-r2" x="854" y="93.2" textLength="12.2" clip-path="url(#terminal-1538990771-line-3)">
|
||||||
</text><text class="terminal-4099597553-r2" x="0" y="117.6" textLength="146.4" clip-path="url(#terminal-4099597553-line-4)">python api: </text><text class="terminal-4099597553-r4" x="146.4" y="117.6" textLength="536.8" clip-path="url(#terminal-4099597553-line-4)">__import__("viv").use("typer", "rich-click")</text><text class="terminal-4099597553-r2" x="854" y="117.6" textLength="12.2" clip-path="url(#terminal-4099597553-line-4)">
|
</text><text class="terminal-1538990771-r2" x="0" y="117.6" textLength="146.4" clip-path="url(#terminal-1538990771-line-4)">python api: </text><text class="terminal-1538990771-r4" x="146.4" y="117.6" textLength="536.8" clip-path="url(#terminal-1538990771-line-4)">__import__("viv").use("typer", "rich-click")</text><text class="terminal-1538990771-r2" x="854" y="117.6" textLength="12.2" clip-path="url(#terminal-1538990771-line-4)">
|
||||||
</text><text class="terminal-4099597553-r2" x="854" y="142" textLength="12.2" clip-path="url(#terminal-4099597553-line-5)">
|
</text><text class="terminal-1538990771-r2" x="854" y="142" textLength="12.2" clip-path="url(#terminal-1538990771-line-5)">
|
||||||
</text><text class="terminal-4099597553-r1" x="0" y="166.4" textLength="85.4" clip-path="url(#terminal-4099597553-line-6)">options</text><text class="terminal-4099597553-r2" x="85.4" y="166.4" textLength="12.2" clip-path="url(#terminal-4099597553-line-6)">:</text><text class="terminal-4099597553-r2" x="854" y="166.4" textLength="12.2" clip-path="url(#terminal-4099597553-line-6)">
|
</text><text class="terminal-1538990771-r1" x="0" y="166.4" textLength="85.4" clip-path="url(#terminal-1538990771-line-6)">options</text><text class="terminal-1538990771-r2" x="85.4" y="166.4" textLength="12.2" clip-path="url(#terminal-1538990771-line-6)">:</text><text class="terminal-1538990771-r2" x="854" y="166.4" textLength="12.2" clip-path="url(#terminal-1538990771-line-6)">
|
||||||
</text><text class="terminal-4099597553-r5" x="24.4" y="190.8" textLength="24.4" clip-path="url(#terminal-4099597553-line-7)">-h</text><text class="terminal-4099597553-r2" x="48.8" y="190.8" textLength="24.4" clip-path="url(#terminal-4099597553-line-7)">, </text><text class="terminal-4099597553-r5" x="73.2" y="190.8" textLength="73.2" clip-path="url(#terminal-4099597553-line-7)">--help</text><text class="terminal-4099597553-r2" x="146.4" y="190.8" textLength="463.6" clip-path="url(#terminal-4099597553-line-7)">       show this help message and exit</text><text class="terminal-4099597553-r2" x="854" y="190.8" textLength="12.2" clip-path="url(#terminal-4099597553-line-7)">
|
</text><text class="terminal-1538990771-r5" x="24.4" y="190.8" textLength="24.4" clip-path="url(#terminal-1538990771-line-7)">-h</text><text class="terminal-1538990771-r2" x="48.8" y="190.8" textLength="24.4" clip-path="url(#terminal-1538990771-line-7)">, </text><text class="terminal-1538990771-r5" x="73.2" y="190.8" textLength="73.2" clip-path="url(#terminal-1538990771-line-7)">--help</text><text class="terminal-1538990771-r2" x="146.4" y="190.8" textLength="463.6" clip-path="url(#terminal-1538990771-line-7)">       show this help message and exit</text><text class="terminal-1538990771-r2" x="854" y="190.8" textLength="12.2" clip-path="url(#terminal-1538990771-line-7)">
|
||||||
</text><text class="terminal-4099597553-r5" x="24.4" y="215.2" textLength="24.4" clip-path="url(#terminal-4099597553-line-8)">-V</text><text class="terminal-4099597553-r2" x="48.8" y="215.2" textLength="24.4" clip-path="url(#terminal-4099597553-line-8)">, </text><text class="terminal-4099597553-r5" x="73.2" y="215.2" textLength="109.8" clip-path="url(#terminal-4099597553-line-8)">--version</text><text class="terminal-4099597553-r2" x="183" y="215.2" textLength="512.4" clip-path="url(#terminal-4099597553-line-8)">    show program's version number and exit</text><text class="terminal-4099597553-r2" x="854" y="215.2" textLength="12.2" clip-path="url(#terminal-4099597553-line-8)">
|
</text><text class="terminal-1538990771-r5" x="24.4" y="215.2" textLength="24.4" clip-path="url(#terminal-1538990771-line-8)">-V</text><text class="terminal-1538990771-r2" x="48.8" y="215.2" textLength="24.4" clip-path="url(#terminal-1538990771-line-8)">, </text><text class="terminal-1538990771-r5" x="73.2" y="215.2" textLength="109.8" clip-path="url(#terminal-1538990771-line-8)">--version</text><text class="terminal-1538990771-r2" x="183" y="215.2" textLength="512.4" clip-path="url(#terminal-1538990771-line-8)">    show program's version number and exit</text><text class="terminal-1538990771-r2" x="854" y="215.2" textLength="12.2" clip-path="url(#terminal-1538990771-line-8)">
|
||||||
</text><text class="terminal-4099597553-r2" x="854" y="239.6" textLength="12.2" clip-path="url(#terminal-4099597553-line-9)">
|
</text><text class="terminal-1538990771-r2" x="854" y="239.6" textLength="12.2" clip-path="url(#terminal-1538990771-line-9)">
|
||||||
</text><text class="terminal-4099597553-r1" x="0" y="264" textLength="134.2" clip-path="url(#terminal-4099597553-line-10)">subcommands</text><text class="terminal-4099597553-r2" x="134.2" y="264" textLength="12.2" clip-path="url(#terminal-4099597553-line-10)">:</text><text class="terminal-4099597553-r2" x="854" y="264" textLength="12.2" clip-path="url(#terminal-4099597553-line-10)">
|
</text><text class="terminal-1538990771-r1" x="0" y="264" textLength="134.2" clip-path="url(#terminal-1538990771-line-10)">subcommands</text><text class="terminal-1538990771-r2" x="134.2" y="264" textLength="12.2" clip-path="url(#terminal-1538990771-line-10)">:</text><text class="terminal-1538990771-r2" x="854" y="264" textLength="12.2" clip-path="url(#terminal-1538990771-line-10)">
|
||||||
</text><text class="terminal-4099597553-r5" x="24.4" y="288.4" textLength="109.8" clip-path="url(#terminal-4099597553-line-11)"><sub-cmd></text><text class="terminal-4099597553-r2" x="854" y="288.4" textLength="12.2" clip-path="url(#terminal-4099597553-line-11)">
|
</text><text class="terminal-1538990771-r5" x="24.4" y="288.4" textLength="109.8" clip-path="url(#terminal-1538990771-line-11)"><sub-cmd></text><text class="terminal-1538990771-r2" x="854" y="288.4" textLength="12.2" clip-path="url(#terminal-1538990771-line-11)">
|
||||||
</text><text class="terminal-4099597553-r5" x="48.8" y="312.8" textLength="97.6" clip-path="url(#terminal-4099597553-line-12)">list (l)</text><text class="terminal-4099597553-r2" x="146.4" y="312.8" textLength="231.8" clip-path="url(#terminal-4099597553-line-12)">       list vivenvs</text><text class="terminal-4099597553-r2" x="854" y="312.8" textLength="12.2" clip-path="url(#terminal-4099597553-line-12)">
|
</text><text class="terminal-1538990771-r5" x="48.8" y="312.8" textLength="97.6" clip-path="url(#terminal-1538990771-line-12)">list (l)</text><text class="terminal-1538990771-r2" x="146.4" y="312.8" textLength="231.8" clip-path="url(#terminal-1538990771-line-12)">       list vivenvs</text><text class="terminal-1538990771-r2" x="854" y="312.8" textLength="12.2" clip-path="url(#terminal-1538990771-line-12)">
|
||||||
</text><text class="terminal-4099597553-r5" x="48.8" y="337.2" textLength="97.6" clip-path="url(#terminal-4099597553-line-13)">shim (s)</text><text class="terminal-4099597553-r2" x="146.4" y="337.2" textLength="439.2" clip-path="url(#terminal-4099597553-line-13)">       generate viv-powered cli apps</text><text class="terminal-4099597553-r2" x="854" y="337.2" textLength="12.2" clip-path="url(#terminal-4099597553-line-13)">
|
</text><text class="terminal-1538990771-r5" x="48.8" y="337.2" textLength="97.6" clip-path="url(#terminal-1538990771-line-13)">shim (s)</text><text class="terminal-1538990771-r2" x="146.4" y="337.2" textLength="439.2" clip-path="url(#terminal-1538990771-line-13)">       generate viv-powered cli apps</text><text class="terminal-1538990771-r2" x="854" y="337.2" textLength="12.2" clip-path="url(#terminal-1538990771-line-13)">
|
||||||
</text><text class="terminal-4099597553-r5" x="48.8" y="361.6" textLength="85.4" clip-path="url(#terminal-4099597553-line-14)">run (r)</text><text class="terminal-4099597553-r2" x="134.2" y="361.6" textLength="585.6" clip-path="url(#terminal-4099597553-line-14)">        run an app/script with an on-demand venv</text><text class="terminal-4099597553-r2" x="854" y="361.6" textLength="12.2" clip-path="url(#terminal-4099597553-line-14)">
|
</text><text class="terminal-1538990771-r5" x="48.8" y="361.6" textLength="85.4" clip-path="url(#terminal-1538990771-line-14)">run (r)</text><text class="terminal-1538990771-r2" x="134.2" y="361.6" textLength="585.6" clip-path="url(#terminal-1538990771-line-14)">        run an app/script with an on-demand venv</text><text class="terminal-1538990771-r2" x="854" y="361.6" textLength="12.2" clip-path="url(#terminal-1538990771-line-14)">
|
||||||
</text><text class="terminal-4099597553-r5" x="48.8" y="386" textLength="85.4" clip-path="url(#terminal-4099597553-line-15)">env (e)</text><text class="terminal-4099597553-r2" x="134.2" y="386" textLength="427" clip-path="url(#terminal-4099597553-line-15)">        manage the viv vivenv cache</text><text class="terminal-4099597553-r2" x="854" y="386" textLength="12.2" clip-path="url(#terminal-4099597553-line-15)">
|
</text><text class="terminal-1538990771-r5" x="48.8" y="386" textLength="85.4" clip-path="url(#terminal-1538990771-line-15)">exe (e)</text><text class="terminal-1538990771-r2" x="134.2" y="386" textLength="536.8" clip-path="url(#terminal-1538990771-line-15)">        run binary/script in existing vivenv</text><text class="terminal-1538990771-r2" x="854" y="386" textLength="12.2" clip-path="url(#terminal-1538990771-line-15)">
|
||||||
</text><text class="terminal-4099597553-r5" x="48.8" y="410.4" textLength="122" clip-path="url(#terminal-4099597553-line-16)">freeze (f)</text><text class="terminal-4099597553-r2" x="170.8" y="410.4" textLength="561.2" clip-path="url(#terminal-4099597553-line-16)">     create import statement from package spec</text><text class="terminal-4099597553-r2" x="854" y="410.4" textLength="12.2" clip-path="url(#terminal-4099597553-line-16)">
|
</text><text class="terminal-1538990771-r5" x="48.8" y="410.4" textLength="109.8" clip-path="url(#terminal-1538990771-line-16)">cache (c)</text><text class="terminal-1538990771-r2" x="158.6" y="410.4" textLength="402.6" clip-path="url(#terminal-1538990771-line-16)">      manage the viv vivenv cache</text><text class="terminal-1538990771-r2" x="854" y="410.4" textLength="12.2" clip-path="url(#terminal-1538990771-line-16)">
|
||||||
</text><text class="terminal-4099597553-r5" x="48.8" y="434.8" textLength="122" clip-path="url(#terminal-4099597553-line-17)">manage (m)</text><text class="terminal-4099597553-r2" x="170.8" y="434.8" textLength="268.4" clip-path="url(#terminal-4099597553-line-17)">     manage viv itself</text><text class="terminal-4099597553-r2" x="854" y="434.8" textLength="12.2" clip-path="url(#terminal-4099597553-line-17)">
|
</text><text class="terminal-1538990771-r5" x="48.8" y="434.8" textLength="122" clip-path="url(#terminal-1538990771-line-17)">freeze (f)</text><text class="terminal-1538990771-r2" x="170.8" y="434.8" textLength="561.2" clip-path="url(#terminal-1538990771-line-17)">     create import statement from package spec</text><text class="terminal-1538990771-r2" x="854" y="434.8" textLength="12.2" clip-path="url(#terminal-1538990771-line-17)">
|
||||||
|
</text><text class="terminal-1538990771-r5" x="48.8" y="459.2" textLength="122" clip-path="url(#terminal-1538990771-line-18)">manage (m)</text><text class="terminal-1538990771-r2" x="170.8" y="459.2" textLength="268.4" clip-path="url(#terminal-1538990771-line-18)">     manage viv itself</text><text class="terminal-1538990771-r2" x="854" y="459.2" textLength="12.2" clip-path="url(#terminal-1538990771-line-18)">
|
||||||
</text>
|
</text>
|
||||||
</g>
|
</g>
|
||||||
</g>
|
</g>
|
||||||
|
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 13 KiB |
23
docs/conf.py
23
docs/conf.py
|
@ -1,23 +0,0 @@
|
||||||
project = "Viv"
|
|
||||||
copyright = "2023, Daylin Morgan"
|
|
||||||
author = "Daylin Morgan"
|
|
||||||
|
|
||||||
extensions = ["myst_parser", "sphinx_copybutton"]
|
|
||||||
myst_enable_extensions = ["colon_fence", "deflist"]
|
|
||||||
|
|
||||||
templates_path = ["_templates"]
|
|
||||||
exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]
|
|
||||||
html_extra_path = ["viv.py"]
|
|
||||||
|
|
||||||
|
|
||||||
html_theme = "shibuya"
|
|
||||||
# html_static_path = ["_static"]
|
|
||||||
html_logo = "../assets/logo.svg"
|
|
||||||
|
|
||||||
html_theme_options = {
|
|
||||||
"github_url": "https://github.com/daylinmorgan/viv",
|
|
||||||
"nav_links": [
|
|
||||||
{"title": "Documentation", "url": "installation"},
|
|
||||||
{"title": "CLI Reference", "url": "cli"},
|
|
||||||
],
|
|
||||||
}
|
|
|
@ -1,45 +0,0 @@
|
||||||
# Configuration
|
|
||||||
|
|
||||||
## Environment Variables
|
|
||||||
|
|
||||||
`VIV_RUN_MODE`
|
|
||||||
: **ephemeral** (default):
|
|
||||||
: `viv run` will generate a temporary directory that is removed following execution
|
|
||||||
: **semi-ephemeral**
|
|
||||||
: `viv run` will set the `VIV_CACHE` directory to `$TEMPDIR/viv-ephemeral-cache-$USER`
|
|
||||||
: persist
|
|
||||||
: `viv run` will always use the standard `VIV_CACHE` which maximizes reusable vivenvs
|
|
||||||
|
|
||||||
`VIV_CACHE`
|
|
||||||
: Path to use for vivenv cache by default `$XDG_CACHE_HOME/viv` or `$HOME/.cache/viv`
|
|
||||||
|
|
||||||
`VIV_LOG_PATH`
|
|
||||||
: Path to use for log file by default `$XDG_DATA_HOME/viv/viv.log` or `$HOME/.local/share/viv/viv.log`
|
|
||||||
|
|
||||||
`VIV_BIN_DIR`
|
|
||||||
: Path to use for shims by default `$HOME/.local/bin`
|
|
||||||
|
|
||||||
`VIV_NO_SETUPTOOLS`
|
|
||||||
: Don't add setuptools to generated vivenvs.
|
|
||||||
: Many legacy packages expect setuptools to be available
|
|
||||||
and don't appropriately declare it as a dependency.
|
|
||||||
To minimize frustration `setuptools` is added to every dependency
|
|
||||||
list.
|
|
||||||
|
|
||||||
`VIV_FORCE`
|
|
||||||
: Remove existence check and recreate vivenv
|
|
||||||
|
|
||||||
`VIV_SPEC`
|
|
||||||
: Space separated list of dependencies in addition to those in script
|
|
||||||
|
|
||||||
`VIV_VERBOSE`
|
|
||||||
: Show `pip` output in real time
|
|
||||||
|
|
||||||
`VIV_DEBUG`
|
|
||||||
: Set log level to `DEBUG`
|
|
||||||
|
|
||||||
`FORCE_COLOR`
|
|
||||||
: Force output to use ANSI escape codes
|
|
||||||
|
|
||||||
`NO_COLOR`
|
|
||||||
: Remove all ANSI escape codes from output
|
|
|
@ -1,40 +0,0 @@
|
||||||
---
|
|
||||||
layout: landing
|
|
||||||
cover: http://viv.dayl.in/_static/logo.svg
|
|
||||||
desciption: Viv isn't venv
|
|
||||||
---
|
|
||||||
|
|
||||||
# viv isn't venv
|
|
||||||
|
|
||||||
Try before you buy!
|
|
||||||
```sh
|
|
||||||
python3 <(curl -fsSL viv.dayl.in/viv.py) run frogmouth -- gh daylinmorgan/viv
|
|
||||||
```
|
|
||||||
|
|
||||||
:::{container} buttons
|
|
||||||
|
|
||||||
[Docs](/installation)
|
|
||||||
[Github](https://github.com/daylinmorgan/viv)
|
|
||||||
|
|
||||||
:::
|
|
||||||
|
|
||||||
|
|
||||||
`Viv` is a standalone dependency-free `venv` creator (just needs python + pip).
|
|
||||||
`Viv` helps you ignore silly things like managing temporary or rarely used virtual environments,
|
|
||||||
while still unleashing the full power of python scripting with it's entire ecosystem at your disposal.
|
|
||||||
|
|
||||||
`Viv`'s uncompromising insistence on portability means that it will always,
|
|
||||||
only use the standard library and never exceed a single script.
|
|
||||||
|
|
||||||
|
|
||||||
```{toctree}
|
|
||||||
:hidden:
|
|
||||||
:maxdepth: 2
|
|
||||||
|
|
||||||
installation.md
|
|
||||||
usage.md
|
|
||||||
configuration.md
|
|
||||||
vs-others.md
|
|
||||||
cli.md
|
|
||||||
```
|
|
||||||
|
|
|
@ -1,56 +0,0 @@
|
||||||
# Installation
|
|
||||||
|
|
||||||
## Automated
|
|
||||||
|
|
||||||
Run the below command to install `viv`.
|
|
||||||
|
|
||||||
```sh
|
|
||||||
python3 <(curl -fsSL viv.dayl.in/viv.py) manage install
|
|
||||||
```
|
|
||||||
|
|
||||||
To access `viv` from within scripts you should add its location to your `PYTHONPATH`.
|
|
||||||
By default `viv` will be installed to `$XDG_DATA_HOME/viv` or `~/.local/share/viv`,
|
|
||||||
and symlinked to `$XDG_BIN_HOME` or `~/.local/bin/.`
|
|
||||||
You can customize these locations at install with with `--src` and `--cli` respectively.
|
|
||||||
|
|
||||||
```sh
|
|
||||||
export PYTHONPATH="$PYTHONPATH:$HOME/.local/share/viv"
|
|
||||||
# or
|
|
||||||
export PYTHONPATH="$PYTHONPATH:$(viv manage show --pythonpath)"
|
|
||||||
```
|
|
||||||
|
|
||||||
:::{note}
|
|
||||||
You can install an older version by specifying `--ref`
|
|
||||||
:::
|
|
||||||
|
|
||||||
## Manual
|
|
||||||
|
|
||||||
Viv is a single standalone script meaning all that's really necessary is
|
|
||||||
that it exists locally and is appropriately added to your path.
|
|
||||||
You can get the latest stable version from [here](https://viv.dayl.in/viv.py)
|
|
||||||
or from [github](https://github.com/daylinmorgan/viv/blob/latest/src/viv/viv.py).
|
|
||||||
|
|
||||||
Must be added to your `$PATH` for use as a CLI app and `$PYTHONPATH` for uses as a python module.
|
|
||||||
|
|
||||||
## Never
|
|
||||||
|
|
||||||
Viv is a standalone script accessible at `https://viv.dayl.in/viv.py`
|
|
||||||
meaning it's not strictly necessary you every actually install it.
|
|
||||||
Every instance of the `viv` CLI can be seamlessly replaced with `python3 <(curl -fsSL viv.dayl.in/viv.py)`.
|
|
||||||
|
|
||||||
## PyPI Options (Not Recommended)
|
|
||||||
|
|
||||||
Why is this *not recommended?*
|
|
||||||
Mainly because `viv` is all about hacking your `sys.path`.
|
|
||||||
Placing it in its own virtual environment
|
|
||||||
or installing in a user site directory may complicate this endeavor.
|
|
||||||
|
|
||||||
```sh
|
|
||||||
pip install viv
|
|
||||||
# or
|
|
||||||
pipx install viv
|
|
||||||
```
|
|
||||||
|
|
||||||
*Note*: If installed by `pipx`, it should still be possible to
|
|
||||||
use `viv` as a module by adding it to the `$PYTHONPATH`.
|
|
||||||
See above for more info.
|
|
202
docs/usage.md
202
docs/usage.md
|
@ -1,202 +0,0 @@
|
||||||
# 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 `--`:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
viv run frogmouth -- gh daylinmorgan/viv
|
|
||||||
```
|
|
||||||
|
|
||||||
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")
|
|
||||||
```
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
Command:
|
|
||||||
```sh
|
|
||||||
viv freeze rich typer
|
|
||||||
```
|
|
||||||
|
|
||||||
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`.
|
|
||||||
|
|
||||||
Command:
|
|
||||||
```sh
|
|
||||||
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
|
|
||||||
```
|
|
||||||
|
|
||||||
## 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`:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
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:
|
|
||||||
```sh
|
|
||||||
viv list --filter "created-before:2024-01-01"
|
|
||||||
```
|
|
||||||
|
|
||||||
Associated with a particular file:
|
|
||||||
```sh
|
|
||||||
viv list --filter "files:./script.py"
|
|
||||||
```
|
|
||||||
|
|
||||||
Or no files:
|
|
||||||
```sh
|
|
||||||
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:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
viv env remove $(viv list -q)
|
|
||||||
```
|
|
||||||
|
|
||||||
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
|
|
||||||
```
|
|
||||||
|
|
|
@ -1,31 +0,0 @@
|
||||||
# Vs Others
|
|
||||||
|
|
||||||
## Equivalent commands from alternatives
|
|
||||||
|
|
||||||
### [pip-run](https://github.com/jaraco/pip-run)
|
|
||||||
|
|
||||||
|
|
||||||
```sh
|
|
||||||
pip-run cowsay -- -m cowsay "moove over, pip-run"
|
|
||||||
python3 <(curl -fsSL viv.dayl.in/viv.py) run cowsay -- "moove over, pip-run"
|
|
||||||
```
|
|
||||||
|
|
||||||
```sh
|
|
||||||
python -m pip-run requests -- -c "import requests; print(requests.get('https://pypi.org/project/pip-run').status_code)"
|
|
||||||
python -m viv run requests -b python -- -c "import requests; print(requests.get('https://pypi.org/project/viv').status_code)"
|
|
||||||
```
|
|
||||||
|
|
||||||
### [pipx](https://github.com/pypa/pipx/)
|
|
||||||
|
|
||||||
```sh
|
|
||||||
pipx install pycowsay
|
|
||||||
viv shim pycowsay
|
|
||||||
```
|
|
||||||
|
|
||||||
```sh
|
|
||||||
pipx run https://gist.githubusercontent.com/cs01/fa721a17a326e551ede048c5088f9e0f/raw/6bdfbb6e9c1132b1c38fdd2f195d4a24c540c324/pipx-demo.py
|
|
||||||
python3 <(curl -fsSL viv.dayl.in/viv.py) run \
|
|
||||||
-s https://gist.githubusercontent.com/cs01/fa721a17a326e551ede048c5088f9e0f/raw/6bdfbb6e9c1132b1c38fdd2f195d4a24c540c324/pipx-demo.py
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,6 @@ it will generate a new vivenv.
|
||||||
It may be important to require a exe specificty if you are frequently running
|
It may be important to require a exe specificty if you are frequently running
|
||||||
different version of pythons and rely on c extension modules as in numpy.
|
different version of pythons and rely on c extension modules as in numpy.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__import__("viv").use("numpy", "plotext", track_exe=True) # noqa
|
__import__("viv").use("numpy", "plotext", track_exe=True) # noqa
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
|
@ -6,7 +6,6 @@ This import statement was generated using
|
||||||
Using viv freeze ensures future runs of this
|
Using viv freeze ensures future runs of this
|
||||||
script will use the same essential environment
|
script will use the same essential environment
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__import__("viv").use(
|
__import__("viv").use(
|
||||||
"numpy==1.24.0",
|
"numpy==1.24.0",
|
||||||
"pandas==1.5.2",
|
"pandas==1.5.2",
|
||||||
|
|
17
examples/pep722.py
Executable file
17
examples/pep722.py
Executable file
|
@ -0,0 +1,17 @@
|
||||||
|
#!/usr/bin/env -S viv run -s
|
||||||
|
# In order to run, this script needs the following 3rd party libraries
|
||||||
|
#
|
||||||
|
# Script Dependencies:
|
||||||
|
# requests
|
||||||
|
# rich # Needed for the output
|
||||||
|
#
|
||||||
|
# # Not needed - just to show that fragments in URLs do not
|
||||||
|
# # get treated as comments
|
||||||
|
# pip @ https://github.com/pypa/pip/archive/1.3.1.zip#sha1=2e15a2d4e7e9f394a9c7a6c905c6a239402a6442
|
||||||
|
|
||||||
|
import requests
|
||||||
|
from rich.pretty import pprint
|
||||||
|
|
||||||
|
resp = requests.get("https://peps.python.org/api/peps.json")
|
||||||
|
data = resp.json()
|
||||||
|
pprint([(k, v["title"]) for k, v in data.items()][:10])
|
|
@ -1,15 +0,0 @@
|
||||||
#!/usr/bin/env -S viv run -s
|
|
||||||
# /// script
|
|
||||||
# requires-python = ">=3.11"
|
|
||||||
# dependencies = [
|
|
||||||
# "requests<3",
|
|
||||||
# "rich",
|
|
||||||
# ]
|
|
||||||
# ///
|
|
||||||
|
|
||||||
import requests
|
|
||||||
from rich import print
|
|
||||||
|
|
||||||
resp = requests.get("https://peps.python.org/api/peps.json")
|
|
||||||
data = resp.json()
|
|
||||||
print([(k, v["title"]) for k, v in data.items()][:10])
|
|
|
@ -1,17 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
# /// script
|
|
||||||
# requires-python = ">=3.11"
|
|
||||||
# dependencies = [
|
|
||||||
# "requests<3",
|
|
||||||
# "rich",
|
|
||||||
# ]
|
|
||||||
# ///
|
|
||||||
|
|
||||||
__import__("viv").run()
|
|
||||||
|
|
||||||
import requests
|
|
||||||
from rich import print
|
|
||||||
|
|
||||||
resp = requests.get("https://peps.python.org/api/peps.json")
|
|
||||||
data = resp.json()
|
|
||||||
print([(k, v["title"]) for k, v in data.items()][:10])
|
|
0
examples/stopwatch.py
Normal file → Executable file
0
examples/stopwatch.py
Normal file → Executable file
|
@ -2,13 +2,14 @@
|
||||||
"""
|
"""
|
||||||
Embed the viv.py on the sys.path at runtime rather than using PYTHONPATH
|
Embed the viv.py on the sys.path at runtime rather than using PYTHONPATH
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
old_sys_path = sys.path.copy() # noqa
|
old_sys_path = sys.path.copy() # noqa
|
||||||
|
|
||||||
|
|
||||||
__import__("sys").path.append(__import__("os").path.expanduser("~/.local/share/viv")) # noqa # isort: off
|
__import__("sys").path.append(
|
||||||
|
__import__("os").path.expanduser("~/.local/share/viv")
|
||||||
|
) # noqa # isort: off
|
||||||
__import__("viv").use("rich") # noqa # isort: off
|
__import__("viv").use("rich") # noqa # isort: off
|
||||||
|
|
||||||
from difflib import unified_diff
|
from difflib import unified_diff
|
||||||
|
|
35
mkdocs.yml
Normal file
35
mkdocs.yml
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
site_name: viv
|
||||||
|
site_url: https://viv.dayl.in
|
||||||
|
repo_url: https://github.com/daylinmorgan/viv
|
||||||
|
edit_uri: edit/main/docs/
|
||||||
|
repo_name: daylinmorgan/viv
|
||||||
|
|
||||||
|
nav:
|
||||||
|
- home: index.md
|
||||||
|
- cli: cli.md
|
||||||
|
|
||||||
|
theme:
|
||||||
|
name: material
|
||||||
|
logo: https://raw.githubusercontent.com/daylinmorgan/viv/main/assets/logo.svg
|
||||||
|
favicon: https://raw.githubusercontent.com/daylinmorgan/viv/main/assets/logo.svg
|
||||||
|
features:
|
||||||
|
- navigation.tabs
|
||||||
|
- navigation.indexes
|
||||||
|
|
||||||
|
palette:
|
||||||
|
# Palette toggle for dark mode
|
||||||
|
- scheme: slate
|
||||||
|
primary: deep purple
|
||||||
|
toggle:
|
||||||
|
icon: material/brightness-4
|
||||||
|
name: Switch to light mode
|
||||||
|
|
||||||
|
# Palette toggle for light mode
|
||||||
|
- scheme: default
|
||||||
|
primary: deep purple
|
||||||
|
toggle:
|
||||||
|
icon: material/brightness-7
|
||||||
|
name: Switch to dark mode
|
||||||
|
|
||||||
|
markdown_extensions:
|
||||||
|
- footnotes
|
18
noxfile.py
18
noxfile.py
|
@ -1,7 +1,6 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import shutil
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
import nox
|
import nox
|
||||||
|
@ -43,11 +42,11 @@ def docs(session):
|
||||||
if not Path("docs/svgs").is_dir():
|
if not Path("docs/svgs").is_dir():
|
||||||
svgs(session)
|
svgs(session)
|
||||||
|
|
||||||
shutil.copyfile("src/viv/viv.py", "docs/viv.py")
|
session.run("make", "docs", external=True)
|
||||||
if session.interactive:
|
if session.interactive:
|
||||||
session.run("sphinx-autobuild", "docs", "site", "--port", "8787")
|
session.run("mkdocs", "serve")
|
||||||
else:
|
else:
|
||||||
session.run("sphinx-build", "docs", "site")
|
session.run("mkdocs", "build")
|
||||||
|
|
||||||
|
|
||||||
@nox.session
|
@nox.session
|
||||||
|
@ -55,7 +54,10 @@ def release(session):
|
||||||
session.run("./scripts/release.py", external=True)
|
session.run("./scripts/release.py", external=True)
|
||||||
|
|
||||||
|
|
||||||
@nox.session(python=["3.8", "3.9", "3.10", "3.11", "3.12"])
|
# @nox.session(
|
||||||
def test(session):
|
# python=["3.8", "3.9", "3.10", "3.11"]
|
||||||
pdm_install(session, "test")
|
# )
|
||||||
session.run("pytest", "tests/")
|
# def test(session):
|
||||||
|
# pdm_install(session,'test')
|
||||||
|
# session.run('pytest')
|
||||||
|
#
|
||||||
|
|
|
@ -21,28 +21,18 @@ viv = "viv:main"
|
||||||
|
|
||||||
[tool.pdm]
|
[tool.pdm]
|
||||||
version = { source = "scm" }
|
version = { source = "scm" }
|
||||||
# need python 3.9 for these which I usually have anyways
|
|
||||||
ignore_package_warnings = ["sphinx*", "myst-parser"]
|
|
||||||
|
|
||||||
[tool.pdm.dev-dependencies]
|
[tool.pdm.dev-dependencies]
|
||||||
dev = [
|
dev = [
|
||||||
|
"pre-commit>=3",
|
||||||
"mypy>=0.991",
|
"mypy>=0.991",
|
||||||
"astor>=0.8.1",
|
|
||||||
]
|
]
|
||||||
docs = [
|
docs = [
|
||||||
"sphinx",
|
"mkdocs-material>=9.1.15",
|
||||||
"sphinx-autobuild",
|
"yartsu"
|
||||||
"sphinx-copybutton",
|
|
||||||
"myst-parser",
|
|
||||||
"shibuya",
|
|
||||||
"yartsu",
|
|
||||||
]
|
|
||||||
test = [
|
|
||||||
"pytest",
|
|
||||||
"sampleproject"
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[tool.ruff.lint]
|
[tool.ruff]
|
||||||
select = ["E","F","I"]
|
select = ["E","F","I"]
|
||||||
ignore = ["E402"]
|
ignore = ["E402"]
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@ CLI_DOC_PATH = DOCS_PATH / "cli.md"
|
||||||
cmds := dict.fromkeys(
|
cmds := dict.fromkeys(
|
||||||
(
|
(
|
||||||
"list",
|
"list",
|
||||||
|
"exe",
|
||||||
"manage",
|
"manage",
|
||||||
"freeze",
|
"freeze",
|
||||||
"shim",
|
"shim",
|
||||||
|
@ -23,10 +24,7 @@ CLI_DOC_PATH = DOCS_PATH / "cli.md"
|
||||||
[],
|
[],
|
||||||
)
|
)
|
||||||
).update(
|
).update(
|
||||||
{
|
{"manage": ["update", "purge", "show", "install"], "cache": ["info", "remove"]},
|
||||||
"manage": ["update", "purge", "show", "install"],
|
|
||||||
"env": ["exe", "info", "remove"],
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -35,7 +33,7 @@ cli_doc = """\
|
||||||
hide: [navigation]
|
hide: [navigation]
|
||||||
---
|
---
|
||||||
|
|
||||||
# CLI Reference
|
# cli
|
||||||
|
|
||||||

|

|
||||||
"""
|
"""
|
||||||
|
|
|
@ -46,14 +46,11 @@ def release():
|
||||||
next = f"{datetime.now().year}.{inc_build(build)}"
|
next = f"{datetime.now().year}.{inc_build(build)}"
|
||||||
msg = f"bump {current} -> {next}"
|
msg = f"bump {current} -> {next}"
|
||||||
FILE.write_text(
|
FILE.write_text(
|
||||||
re.sub(r'__version__ = ".*"', f'__version__ = "{next}"', FILE.read_text())
|
re.sub(r'__version__ = "[\d\.]+"', f'__version__ = "{next}"', FILE.read_text())
|
||||||
)
|
)
|
||||||
subprocess.run(["git", "add", FILE])
|
subprocess.run(["git", "add", FILE])
|
||||||
subprocess.run(["git", "commit", "-m", msg, "--no-verify"])
|
subprocess.run(["git", "commit", "-m", msg, "--no-verify"])
|
||||||
subprocess.run(["git", "tag", f"v{next}"])
|
subprocess.run(["git", "tag", f"v{next}"])
|
||||||
FILE.write_text(
|
|
||||||
re.sub(r'__version__ = ".*"', f'__version__ = "{next}-dev"', FILE.read_text())
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
|
@ -1,222 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
import ast
|
|
||||||
import re
|
|
||||||
import subprocess
|
|
||||||
import textwrap
|
|
||||||
from pathlib import Path
|
|
||||||
from typing import List
|
|
||||||
|
|
||||||
import astor
|
|
||||||
|
|
||||||
|
|
||||||
def remove_docs_and_comments(code):
|
|
||||||
parsed = ast.parse(code)
|
|
||||||
for node in ast.walk(parsed):
|
|
||||||
if isinstance(node, ast.Expr) and isinstance(node.value, ast.Str):
|
|
||||||
# set value to empty string which should be ignored by astor.to_source
|
|
||||||
node.value = ast.Constant(value="")
|
|
||||||
elif (
|
|
||||||
(isinstance(node, ast.FunctionDef) or isinstance(node, ast.ClassDef))
|
|
||||||
and len(node.body) == 1
|
|
||||||
and isinstance(node.body[0], ast.Expr)
|
|
||||||
and isinstance(node.body[0].value, ast.Constant)
|
|
||||||
):
|
|
||||||
# add pass to empty functions and class definition
|
|
||||||
node.body = [ast.Pass()]
|
|
||||||
formatted_code = astor.to_source(parsed)
|
|
||||||
pattern = r'^.*"""""".*$' # remove empty """"""
|
|
||||||
formatted_code = re.sub(pattern, "", formatted_code, flags=re.MULTILINE)
|
|
||||||
return formatted_code
|
|
||||||
|
|
||||||
|
|
||||||
class Package:
|
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
name: str,
|
|
||||||
url: str,
|
|
||||||
files: List[tuple[str, List[List[int]]]],
|
|
||||||
rev: str,
|
|
||||||
basepath: Path,
|
|
||||||
imports: str = "",
|
|
||||||
prefix: str = "",
|
|
||||||
suffix: str = "",
|
|
||||||
indent: bool = False,
|
|
||||||
):
|
|
||||||
self.name = name
|
|
||||||
self.files = files
|
|
||||||
self.url = url
|
|
||||||
self.rev = rev
|
|
||||||
self.basepath = basepath
|
|
||||||
self.imports = imports
|
|
||||||
self.prefix = prefix
|
|
||||||
self.suffix = suffix
|
|
||||||
self.indent = indent
|
|
||||||
|
|
||||||
self.ensure()
|
|
||||||
self.generate_vendored_source()
|
|
||||||
self.replace_identifiers()
|
|
||||||
|
|
||||||
def ensure(self):
|
|
||||||
dir = Path(__file__).parent / self.name
|
|
||||||
if not dir.is_dir():
|
|
||||||
subprocess.run(["git", "clone", self.url, dir])
|
|
||||||
subprocess.run(["git", "-C", dir, "checkout", self.rev])
|
|
||||||
|
|
||||||
@property
|
|
||||||
def start_delim(self) -> str:
|
|
||||||
return f"#### START VENDORED {self.name.upper()} ####"
|
|
||||||
|
|
||||||
@property
|
|
||||||
def end_delim(self) -> str:
|
|
||||||
return f"#### END VENDORED {self.name.upper()} ####"
|
|
||||||
|
|
||||||
def generate_vendored_source(self):
|
|
||||||
self.src_text = ""
|
|
||||||
for f, slices in self.files:
|
|
||||||
og_text = (self.basepath / f"{f}.py").read_text()
|
|
||||||
for indices in slices:
|
|
||||||
self.src_text = "\n".join(
|
|
||||||
(
|
|
||||||
self.src_text,
|
|
||||||
*[
|
|
||||||
line
|
|
||||||
for line in og_text.splitlines()[slice(*indices)]
|
|
||||||
if line.strip("\r\n")
|
|
||||||
],
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
def replace_identifiers(self):
|
|
||||||
patterns = set.union(
|
|
||||||
*[
|
|
||||||
set(re.findall(regex, self.src_text, re.MULTILINE))
|
|
||||||
for regex in (
|
|
||||||
r"^class (?P<class>[a-zA-Z_]*)(?:\(.*\))?:",
|
|
||||||
r"^(?P<ident>[a-zA-Z_]*) =",
|
|
||||||
r"^def (?P<function>[a-zA-Z_]+)\(",
|
|
||||||
)
|
|
||||||
]
|
|
||||||
) - {
|
|
||||||
"Key",
|
|
||||||
} # prevent KeyError false positive by leaving Key alone
|
|
||||||
|
|
||||||
for pat in patterns:
|
|
||||||
self.src_text = re.sub(
|
|
||||||
r'(?P<lead>[\s("\[={])' + pat,
|
|
||||||
f"\g<lead>v_{self.name}_{pat}",
|
|
||||||
self.src_text,
|
|
||||||
)
|
|
||||||
|
|
||||||
def insert(self, base_text: str) -> str:
|
|
||||||
start, rest = re.split(self.start_delim, base_text)
|
|
||||||
_, rest = re.split(self.end_delim, base_text)
|
|
||||||
src = textwrap.indent(
|
|
||||||
remove_docs_and_comments(self.src_text.strip()),
|
|
||||||
prefix=" " * (4 if self.indent else 0),
|
|
||||||
)
|
|
||||||
return "\n".join(
|
|
||||||
(
|
|
||||||
start.strip(),
|
|
||||||
"\n",
|
|
||||||
self.start_delim,
|
|
||||||
self.prefix + self.imports + src + self.suffix,
|
|
||||||
self.end_delim,
|
|
||||||
"\n",
|
|
||||||
rest.strip(),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
PACKAGES = [
|
|
||||||
Package(
|
|
||||||
name="packaging",
|
|
||||||
url="https://github.com/pypa/packaging.git",
|
|
||||||
# v24.0
|
|
||||||
rev="7a983f7f0068669ead9d4f7571be24d6c0d83eb9",
|
|
||||||
files=(
|
|
||||||
("_structures", [[5, 61]]),
|
|
||||||
("version", [[17, 563]]),
|
|
||||||
("utils", [[54, 100]]),
|
|
||||||
("specifiers", [[18, 1017]]),
|
|
||||||
),
|
|
||||||
basepath=Path(__file__).parent / "packaging/src/packaging",
|
|
||||||
prefix="""
|
|
||||||
# MODIFIED FROM https://github.com/pypa/packaging
|
|
||||||
# see repo for original licenses
|
|
||||||
# This software is made available under the terms of *either* of the licenses
|
|
||||||
# found in LICENSE.APACHE or LICENSE.BSD. Contributions to this software is made
|
|
||||||
# under the terms of *both* these licenses.
|
|
||||||
""",
|
|
||||||
imports="""
|
|
||||||
import abc # noqa
|
|
||||||
import itertools # noqa
|
|
||||||
import re # noqa
|
|
||||||
from typing import ( # noqa
|
|
||||||
Any,
|
|
||||||
Callable,
|
|
||||||
Iterable,
|
|
||||||
Iterator,
|
|
||||||
List,
|
|
||||||
NamedTuple,
|
|
||||||
Optional,
|
|
||||||
Set,
|
|
||||||
SupportsInt,
|
|
||||||
Tuple,
|
|
||||||
TypeVar,
|
|
||||||
Union,
|
|
||||||
)
|
|
||||||
""",
|
|
||||||
suffix="""
|
|
||||||
Version = v_packaging_Version
|
|
||||||
SpecifierSet = v_packaging_SpecifierSet
|
|
||||||
""",
|
|
||||||
),
|
|
||||||
Package(
|
|
||||||
name="tomli",
|
|
||||||
url="https://github.com/hukkin/tomli.git",
|
|
||||||
# rev="2.0.1",
|
|
||||||
rev="a6138675bcca68eea5b8abec7c2ec06d57f965a0",
|
|
||||||
files=(
|
|
||||||
("_types", [[7, 11]]),
|
|
||||||
("_re", [[14, 107]]),
|
|
||||||
("_parser", [[20, 691]]),
|
|
||||||
),
|
|
||||||
prefix="""
|
|
||||||
if sys.version_info >= (3, 11):
|
|
||||||
from tomllib import loads as toml_loads
|
|
||||||
else:
|
|
||||||
# MODIFIED FROM https://github.com/hukkin/tomli
|
|
||||||
# see below for original license
|
|
||||||
# SPDX-License-Identifier: MIT
|
|
||||||
# SPDX-FileCopyrightText: 2021 Taneli Hukkinen
|
|
||||||
# Licensed to PSF under a Contributor Agreement.
|
|
||||||
""",
|
|
||||||
imports="""
|
|
||||||
import string # noqa
|
|
||||||
from collections.abc import Iterable # noqa
|
|
||||||
from functools import lru_cache # noqa
|
|
||||||
from datetime import date, datetime, time, timedelta, timezone, tzinfo # noqa
|
|
||||||
from types import MappingProxyType # noqa
|
|
||||||
from typing import IO, Any, Callable, NamedTuple # noqa
|
|
||||||
""",
|
|
||||||
basepath=Path(__file__).parent / "tomli/src/tomli",
|
|
||||||
suffix="""
|
|
||||||
toml_loads = v_tomli_loads
|
|
||||||
""",
|
|
||||||
indent=True,
|
|
||||||
),
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
viv_source_path = Path(__file__).parent.parent / "src/viv/viv.py"
|
|
||||||
viv_source = viv_source_path.read_text()
|
|
||||||
|
|
||||||
for pkg in PACKAGES:
|
|
||||||
viv_source = pkg.insert(viv_source)
|
|
||||||
|
|
||||||
viv_source_path.write_text(viv_source)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
|
@ -1 +1 @@
|
||||||
from .viv import __version__, use, main, run # noqa
|
from .viv import __version__, use, main # noqa
|
||||||
|
|
2271
src/viv/viv.py
2271
src/viv/viv.py
File diff suppressed because it is too large
Load diff
45
task
45
task
|
@ -1,45 +0,0 @@
|
||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
# VERSION = $(git describe --tags --always --dirty=-dev | sed 's/^v//g')
|
|
||||||
|
|
||||||
function task:venv {
|
|
||||||
: "setup up pdm venv"
|
|
||||||
pdm install
|
|
||||||
}
|
|
||||||
|
|
||||||
function task:dev-install {
|
|
||||||
: "symlink development version"
|
|
||||||
mkdir -p ~/.local/share/viv
|
|
||||||
mkdir -p ~/.local/bin
|
|
||||||
ln -sf "$(pwd)/src/viv/viv.py" ~/.local/share/viv/viv.py
|
|
||||||
ln -sf ~/.local/share/viv/viv.py ~/.local/bin/viv
|
|
||||||
}
|
|
||||||
|
|
||||||
function task:_black {
|
|
||||||
: "generate black example shim"
|
|
||||||
rm -f examples/black
|
|
||||||
viv shim black -y -s -f -o examples/black
|
|
||||||
}
|
|
||||||
|
|
||||||
function task:clean {
|
|
||||||
: "clean build artifacts"
|
|
||||||
rm -rf build dist
|
|
||||||
}
|
|
||||||
|
|
||||||
function task:examples {
|
|
||||||
: "run examples to generate vivenvs"
|
|
||||||
examples="cli sys_path exe_specific frozen_import named_env scrape"
|
|
||||||
for f in $examples; do
|
|
||||||
python "examples/$f.py"
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
function task:_help-logo {
|
|
||||||
FORCE_COLOR=1 viv --help | yartsu -t 'viv --help' -w 70 -o assets/viv-help.svg
|
|
||||||
}
|
|
||||||
|
|
||||||
# ---- do-task boilerplate ----
|
|
||||||
function task:help { : "Show this help"; echo "do:";w=$(("$(compgen -A function | wc -L)" - 3));while read -r name; do [[ ! $name =~ ^task:_ ]] && [[ $name =~ ^task: ]] && paste <(printf '\033[1;32m%*s\033[0m\n' "$w" "${name#task:}") <(type "$name" | sed -nEe 's/^[[:space:]]*: ?"(.*)";/\1/p'); done < <(compgen -A function); }
|
|
||||||
while read -r name; do [[ $name == "task:$1" ]] && { shift; task="$name"; }; done < <(compgen -A function)
|
|
||||||
[[ -n "$1" && -z "$task" ]] && printf "\033[1;31m%s\033\0[m is not a task\n" "$1"
|
|
||||||
"${task:-task:help}" "$@" && exit "$?"
|
|
|
@ -1,12 +0,0 @@
|
||||||
import os
|
|
||||||
import shutil
|
|
||||||
from pathlib import Path
|
|
||||||
|
|
||||||
cache = (Path(__file__).parent / ".viv-cache").absolute()
|
|
||||||
if cache.is_dir():
|
|
||||||
shutil.rmtree(cache)
|
|
||||||
|
|
||||||
# remove local settings
|
|
||||||
os.environ = {k: v for k, v in os.environ.items() if not k.startswith("VIV_")}
|
|
||||||
|
|
||||||
os.environ["VIV_CACHE"] = str(cache)
|
|
|
@ -1,52 +0,0 @@
|
||||||
import pytest
|
|
||||||
from viv.viv import _read_metadata_block, _uses_viv, _Viv_Mode
|
|
||||||
|
|
||||||
RUN_METADATA_SCRIPT = """
|
|
||||||
#!/usr/bin/env -S viv run -s
|
|
||||||
# /// script
|
|
||||||
# requires-python = ">3.10"
|
|
||||||
# dependencies = [
|
|
||||||
# "rich"
|
|
||||||
# ]
|
|
||||||
# ///
|
|
||||||
"""
|
|
||||||
|
|
||||||
USE_SCRIPT = """
|
|
||||||
#!/usr/bin/env python3
|
|
||||||
__import__("viv").use("rich")
|
|
||||||
|
|
||||||
from rich import print
|
|
||||||
print("pretty!")
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
def test_metadata():
|
|
||||||
metadata = _read_metadata_block(RUN_METADATA_SCRIPT)
|
|
||||||
assert metadata == {"requires-python": ">3.10", "dependencies": ["rich"]}
|
|
||||||
|
|
||||||
|
|
||||||
def test_uses():
|
|
||||||
assert _uses_viv(RUN_METADATA_SCRIPT) == _Viv_Mode.NONE
|
|
||||||
assert (
|
|
||||||
_uses_viv(RUN_METADATA_SCRIPT + """\n__import__("viv").run()\n""")
|
|
||||||
== _Viv_Mode.RUN
|
|
||||||
)
|
|
||||||
assert _uses_viv(USE_SCRIPT) == _Viv_Mode.USE
|
|
||||||
assert _uses_viv("# from viv import use") == _Viv_Mode.NONE
|
|
||||||
|
|
||||||
|
|
||||||
def test_uses_fail(caplog):
|
|
||||||
with pytest.raises(SystemExit):
|
|
||||||
_uses_viv("""__import__("viv").run()\n__import__("viv").use()""")
|
|
||||||
with pytest.raises(SystemExit):
|
|
||||||
_uses_viv("""__import__("viv").unknown()""")
|
|
||||||
|
|
||||||
assert [
|
|
||||||
(
|
|
||||||
"viv",
|
|
||||||
40,
|
|
||||||
"Unexpected number of viv references in script.\n"
|
|
||||||
"Expected only 1, found: run, use",
|
|
||||||
),
|
|
||||||
("viv", 40, "Unknown function unknown associated with viv."),
|
|
||||||
] == caplog.record_tuples
|
|
|
@ -1,17 +0,0 @@
|
||||||
import sys
|
|
||||||
|
|
||||||
import pytest
|
|
||||||
from viv import use
|
|
||||||
|
|
||||||
|
|
||||||
def test_use():
|
|
||||||
with pytest.raises(ImportError):
|
|
||||||
import pyjokes # noqa
|
|
||||||
|
|
||||||
use("pyjokes")
|
|
||||||
import pyjokes # noqa
|
|
||||||
|
|
||||||
with pytest.raises(ImportError):
|
|
||||||
from sample.simple import add_one # noqa
|
|
||||||
|
|
||||||
assert len([p for p in sys.path if "site-packages" in p]) == 1
|
|
|
@ -1,17 +0,0 @@
|
||||||
from viv.viv import SpecifierSet, Version, toml_loads
|
|
||||||
|
|
||||||
|
|
||||||
def test_packaging():
|
|
||||||
assert Version("3.6") in SpecifierSet(">=3.6")
|
|
||||||
|
|
||||||
|
|
||||||
def test_tomli():
|
|
||||||
assert {"requires-python": ">3.6", "dependencies": ["rich", "typer"]} == toml_loads(
|
|
||||||
"""
|
|
||||||
requires-python = ">3.6"
|
|
||||||
dependencies = [
|
|
||||||
"rich",
|
|
||||||
"typer"
|
|
||||||
]
|
|
||||||
"""
|
|
||||||
)
|
|
Loading…
Add table
Reference in a new issue