Compare commits

..

6 commits

17 changed files with 44 additions and 34 deletions

View file

@ -20,3 +20,10 @@ repos:
rev: 'v0.0.245' rev: 'v0.0.245'
hooks: hooks:
- id: ruff - id: ruff
- repo: local
hooks:
- id: set-version
language: script
name: sets __version__ in viv.py
entry: ./scripts/bump-dev.sh
files: viv.py$

View file

@ -10,6 +10,7 @@ types: ## run mypy
bump-version: ## update version and tag commit bump-version: ## update version and tag commit
@echo "bumping to version => $(VERSION)" @echo "bumping to version => $(VERSION)"
@sed -i 's/__version__ = ".*"/__version__ = "$(VERSION)"/g' src/viv/viv.py @sed -i 's/__version__ = ".*"/__version__ = "$(VERSION)"/g' src/viv/viv.py
@sed 's/--branch .* g/--branch $(VERSION) g/g' README.md
@git add src/viv/viv.py && git commit -m "chore: bump version" @git add src/viv/viv.py && git commit -m "chore: bump version"
@git tag v$(VERSION) @git tag v$(VERSION)

View file

@ -38,7 +38,7 @@ By default it will symlink `./src/viv/viv.py` to `~/bin/viv`.
You can set `PREFIX` to symlink to a different location. You can set `PREFIX` to symlink to a different location.
```sh ```sh
git clone git@github.com:daylinmorgan/viv.git ~/.viv git clone --depth 1 --branch v22.12a3 git@github.com:daylinmorgan/viv.git ~/.viv
cd ~/.viv cd ~/.viv
make install # or PREFIX=~/.local/bin make install make install # or PREFIX=~/.local/bin make install
``` ```
@ -69,7 +69,7 @@ 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.
```python ```python
__import__("viv").activate("click") __import__("viv").use("click")
``` ```
To remove all `vivenvs`: To remove all `vivenvs`:
@ -89,13 +89,13 @@ no modification of your PYTHONPATH or import of additional modules (including do
It can be auto-generated with for example: `viv freeze <spec> --standalone`. It can be auto-generated with for example: `viv freeze <spec> --standalone`.
The only part necessary to modify if copied verbatim from below is the call to `_viv_activate`. The only part necessary to modify if copied verbatim from below is the call to `_viv_use`.
output of `viv freeze rich --standalone`: output of `viv freeze rich --standalone`:
```python ```python
# <<<<< auto-generated by daylinmorgan/viv (v.22.12a3) # <<<<< auto-generated by daylinmorgan/viv (v.22.12a3)
# fmt: off # fmt: off
def _viv_activate(*pkgs: str, track_exe: bool = False, name: str = "") -> None: # noqa def _viv_use(*pkgs: str, track_exe: bool = False, name: str = "") -> None: # noqa
i,s,m,e,spec=__import__,str,map,lambda x: True if x else False,[*pkgs] # noqa i,s,m,e,spec=__import__,str,map,lambda x: True if x else False,[*pkgs] # noqa
if not {*m(type,pkgs)}=={s}: raise ValueError(f"spec: {pkgs} is invalid") # noqa if not {*m(type,pkgs)}=={s}: raise ValueError(f"spec: {pkgs} is invalid") # noqa
ge,sys,P,ew=i("os").getenv,i("sys"),i("pathlib").Path,i("sys").stderr.write # noqa ge,sys,P,ew=i("os").getenv,i("sys"),i("pathlib").Path,i("sys").stderr.write # noqa
@ -113,7 +113,7 @@ def _viv_activate(*pkgs: str, track_exe: bool = False, name: str = "") -> None:
with (env/"viv-info.json").open("w") as f: # noqa with (env/"viv-info.json").open("w") as f: # noqa
i("json").dump({"created":s(i("datetime").datetime.today()),"id":_id,"spec":spec,"exe":exe},f) # noqa i("json").dump({"created":s(i("datetime").datetime.today()),"id":_id,"spec":spec,"exe":exe},f) # noqa
sys.path = [p for p in (*sys.path,s(*(env/"lib").glob("py*/si*"))) if p!=i("site").USER_SITE] # noqa sys.path = [p for p in (*sys.path,s(*(env/"lib").glob("py*/si*"))) if p!=i("site").USER_SITE] # noqa
_viv_activate("markdown-it-py==2.2.0", "mdurl==0.1.2", "Pygments==2.14.0", "rich==13.3.2") # noqa _viv_use("markdown-it-py==2.2.0", "mdurl==0.1.2", "Pygments==2.14.0", "rich==13.3.2") # noqa
# fmt: on # fmt: on
# >>>>> code golfed with <3 # >>>>> code golfed with <3
``` ```

View file

@ -1,6 +1,6 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
__import__("viv").activate("pyfiglet==0.8.post1") # noqa __import__("viv").use("pyfiglet==0.8.post1") # noqa
from pyfiglet import Figlet from pyfiglet import Figlet

View file

@ -4,7 +4,7 @@ It can be convenient to quickly generate a cli for a short script.
Or to add simple visualization of data using the wonderful rich library. Or to add simple visualization of data using the wonderful rich library.
""" """
__import__("viv").activate("typer", "rich-click") # noqa __import__("viv").use("typer", "rich-click") # noqa
import typer import typer

View file

@ -7,7 +7,7 @@ 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").activate("numpy", "plotext", track_exe=True) # noqa __import__("viv").use("numpy", "plotext", track_exe=True) # noqa
import numpy as np import numpy as np
import plotext as plt import plotext as plt

View file

@ -6,7 +6,7 @@ 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").activate( __import__("viv").use(
"numpy==1.24.0", "numpy==1.24.0",
"pandas==1.5.2", "pandas==1.5.2",
"python-dateutil==2.8.2", "python-dateutil==2.8.2",

View file

@ -7,7 +7,7 @@ Meaning that it will save it within the viv cache not using a hash.
*This environment could then be reused by specifying the name* *This environment could then be reused by specifying the name*
""" """
__import__("viv").activate("rich", name="rich-env") __import__("viv").use("rich", name="rich-env")
from rich.console import Console from rich.console import Console
from rich.markdown import Markdown from rich.markdown import Markdown

View file

@ -6,7 +6,7 @@ modified from:
https://medium.com/analytics-vidhya/a-super-easy-python-script-for-web-scraping-that-anybody-can-use-d3bd6ab86c89 https://medium.com/analytics-vidhya/a-super-easy-python-script-for-web-scraping-that-anybody-can-use-d3bd6ab86c89
""" """
__import__("viv").activate("requests", "bs4", "rich") # noqa __import__("viv").use("requests", "bs4", "rich") # noqa
import requests import requests
from bs4 import BeautifulSoup from bs4 import BeautifulSoup

View file

@ -7,7 +7,7 @@ With this function it's not necessary for
# <<<<< auto-generated by daylinmorgan/viv (v.22.12a3) # <<<<< auto-generated by daylinmorgan/viv (v.22.12a3)
# fmt: off # fmt: off
def _viv_activate(*pkgs: str, track_exe: bool = False, name: str = "") -> None: # noqa def _viv_use(*pkgs: str, track_exe: bool = False, name: str = "") -> None: # noqa
i,s,m,e,spec=__import__,str,map,lambda x: True if x else False,[*pkgs] # noqa i,s,m,e,spec=__import__,str,map,lambda x: True if x else False,[*pkgs] # noqa
if not {*m(type,pkgs)}=={s}: raise ValueError(f"spec: {pkgs} is invalid") # noqa if not {*m(type,pkgs)}=={s}: raise ValueError(f"spec: {pkgs} is invalid") # noqa
ge,sys,P,ew=i("os").getenv,i("sys"),i("pathlib").Path,i("sys").stderr.write # noqa ge,sys,P,ew=i("os").getenv,i("sys"),i("pathlib").Path,i("sys").stderr.write # noqa
@ -25,7 +25,7 @@ def _viv_activate(*pkgs: str, track_exe: bool = False, name: str = "") -> None:
with (env/"viv-info.json").open("w") as f: # noqa with (env/"viv-info.json").open("w") as f: # noqa
i("json").dump({"created":s(i("datetime").datetime.today()),"id":_id,"spec":spec,"exe":exe},f) # noqa i("json").dump({"created":s(i("datetime").datetime.today()),"id":_id,"spec":spec,"exe":exe},f) # noqa
sys.path = [p for p in (*sys.path,s(*(env/"lib").glob("py*/si*"))) if p!=i("site").USER_SITE] # noqa sys.path = [p for p in (*sys.path,s(*(env/"lib").glob("py*/si*"))) if p!=i("site").USER_SITE] # noqa
_viv_activate("pyfiglet==0.8.post1") # noqa _viv_use("pyfiglet==0.8.post1") # noqa
# fmt: on # fmt: on
# >>>>> code golfed with <3 # >>>>> code golfed with <3

View file

@ -3,7 +3,7 @@
https://github.com/Textualize/textual/tree/main/docs/examples/tutorial https://github.com/Textualize/textual/tree/main/docs/examples/tutorial
""" """
__import__("viv").activate("textual") __import__("viv").use("textual")
from time import monotonic from time import monotonic

View file

@ -7,7 +7,7 @@ Embed the viv.py on the sys.path at runtime rather than using PYTHONPATH
__import__("sys").path.append( __import__("sys").path.append(
__import__("os").path.expanduser("~/.viv/src") __import__("os").path.expanduser("~/.viv/src")
) # noqa # isort: off ) # noqa # isort: off
__import__("viv").activate("pyfiglet") # noqa # isort: off __import__("viv").use("pyfiglet") # noqa # isort: off
import sys import sys

View file

@ -1,4 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# ints are not allowed # ints are not allowed
__import__("viv").activate(5) __import__("viv").use(5)

View file

@ -29,7 +29,6 @@ dev = [
] ]
[tool.ruff] [tool.ruff]
line-length = 88
ignore = ["E402"] ignore = ["E402"]
[tool.mypy] [tool.mypy]

5
scripts/bump-dev.sh Executable file
View file

@ -0,0 +1,5 @@
#!/usr/bin/env sh
TAG=$(git describe --tags --always --dirty=-dev)
VERSION="${TAG#v}"
sed -i "s/__version__ = \".*\"/__version__ = \"$VERSION\"/g" src/viv/viv.py
git add src/viv/viv.py

View file

@ -1 +1 @@
from .viv import activate # noqa from .viv import use # noqa

View file

@ -3,7 +3,7 @@
viv -h viv -h
OR OR
__import__("viv").activate("requests", "bs4") __import__("viv").use("requests", "bs4")
""" """
import hashlib import hashlib
@ -30,7 +30,7 @@ from pathlib import Path
from textwrap import dedent, wrap from textwrap import dedent, wrap
from typing import Dict, List, Tuple from typing import Dict, List, Tuple
__version__ = "22.12a3" __version__ = "22.12a3-35-g0d0c66d-dev"
@dataclass @dataclass
@ -38,9 +38,7 @@ class Config:
"""viv config manager""" """viv config manager"""
venvcache: Path = ( venvcache: Path = (
Path(os.getenv("XDG_CACHE_HOME", Path.home() / ".local" / "cache")) Path(os.getenv("XDG_CACHE_HOME", Path.home() / ".cache")) / "viv" / "venvs"
/ "viv"
/ "venvs"
) )
def __post_init__(self): def __post_init__(self):
@ -419,7 +417,7 @@ class ViVenv:
a.table((("key", "value"), *((k, v) for k, v in info.items()))) a.table((("key", "value"), *((k, v) for k, v in info.items())))
def activate(*packages: str, track_exe: bool = False, name: str = "") -> None: def use(*packages: str, track_exe: bool = False, name: str = "") -> None:
"""create a vivenv and append to sys.path """create a vivenv and append to sys.path
Args: Args:
@ -476,18 +474,18 @@ REL_SYS_PATH_TEMPLATE = (
"""__import__("sys").path.append(__import__("os")""" """__import__("sys").path.append(__import__("os")"""
""".path.expanduser("{path_to_viv}")) # noqa""" """.path.expanduser("{path_to_viv}")) # noqa"""
) )
IMPORT_TEMPLATE = """__import__("viv").activate({spec}) # noqa""" IMPORT_TEMPLATE = """__import__("viv").use({spec}) # noqa"""
STANDALONE_TEMPLATE = r""" STANDALONE_TEMPLATE = r"""
# <<<<< auto-generated by daylinmorgan/viv (v.22.12a3) # <<<<< auto-generated by daylinmorgan/viv (v.22.12a3)
# fmt: off # fmt: off
{activate} {use}
# fmt: on # fmt: on
# >>>>> code golfed with <3 # >>>>> code golfed with <3
""" # noqa """ # noqa
STANDALONE_TEMPLATE_ACTIVATE = r""" STANDALONE_TEMPLATE_USE = r"""
def _viv_activate(*pkgs: str, track_exe: bool = False, name: str = "") -> None: def _viv_use(*pkgs: str, track_exe: bool = False, name: str = "") -> None:
i,s,m,e,spec=__import__,str,map,lambda x: True if x else False,[*pkgs] i,s,m,e,spec=__import__,str,map,lambda x: True if x else False,[*pkgs]
if not {{*m(type,pkgs)}}=={{s}}: raise ValueError(f"spec: {{pkgs}} is invalid") if not {{*m(type,pkgs)}}=={{s}}: raise ValueError(f"spec: {{pkgs}} is invalid")
ge,sys,P,ew=i("os").getenv,i("sys"),i("pathlib").Path,i("sys").stderr.write ge,sys,P,ew=i("os").getenv,i("sys"),i("pathlib").Path,i("sys").stderr.write
@ -505,7 +503,7 @@ def _viv_activate(*pkgs: str, track_exe: bool = False, name: str = "") -> None:
with (env/"viv-info.json").open("w") as f: with (env/"viv-info.json").open("w") as f:
i("json").dump({{"created":s(i("datetime").datetime.today()),"id":_id,"spec":spec,"exe":exe}},f) i("json").dump({{"created":s(i("datetime").datetime.today()),"id":_id,"spec":spec,"exe":exe}},f)
sys.path = [p for p in (*sys.path,s(*(env/"lib").glob("py*/si*"))) if p!=i("site").USER_SITE] sys.path = [p for p in (*sys.path,s(*(env/"lib").glob("py*/si*"))) if p!=i("site").USER_SITE]
_viv_activate({spec}) _viv_use({spec})
"""[ # noqa """[ # noqa
1: 1:
] ]
@ -586,8 +584,8 @@ def generate_import(
sys.stdout.write( sys.stdout.write(
STANDALONE_TEMPLATE.format( STANDALONE_TEMPLATE.format(
version=__version__, version=__version__,
activate=noqa( use=noqa(
STANDALONE_TEMPLATE_ACTIVATE.format( STANDALONE_TEMPLATE_USE.format(
spec=", ".join(f'"{pkg}"' for pkg in resolved_spec.splitlines()) spec=", ".join(f'"{pkg}"' for pkg in resolved_spec.splitlines())
) )
), ),
@ -758,7 +756,7 @@ description = f"""
from command line: from command line:
`{a.style("viv -h","bold")}` `{a.style("viv -h","bold")}`
within python script: within python script:
{a.style('__import__("viv").activate("typer", "rich-click")','bold')} {a.style('__import__("viv").use("typer", "rich-click")','bold')}
""" """
@ -807,7 +805,7 @@ class Viv:
"""create import statement from package spec""" """create import statement from package spec"""
if not args.reqs: if not args.reqs:
print("must specify a requirement") error("must specify a requirement")
sys.exit(1) sys.exit(1)
generate_import( generate_import(
@ -848,7 +846,7 @@ class Viv:
pip_path, python_path = (vivenv.path / "bin" / cmd for cmd in ("pip", "python")) pip_path, python_path = (vivenv.path / "bin" / cmd for cmd in ("pip", "python"))
# todo check for vivenv # todo check for vivenv
print(f"executing command within {args.vivenv}") echo(f"executing command within {args.vivenv}")
cmd = ( cmd = (
f"{pip_path} {' '.join(args.cmd)}" f"{pip_path} {' '.join(args.cmd)}"