mirror of
https://github.com/daylinmorgan/viv.git
synced 2024-11-10 03:13:14 -06:00
Compare commits
17 commits
0ec266775c
...
819257c9bd
Author | SHA1 | Date | |
---|---|---|---|
819257c9bd | |||
158acbcbce | |||
6ddd608d23 | |||
9ab5e20add | |||
15442a406a | |||
f04729fd5e | |||
4f99120485 | |||
b5b02f82a6 | |||
f2c156daf6 | |||
a015592fb0 | |||
c97bc81f08 | |||
b7883a9aa9 | |||
cc8d333801 | |||
3126a64463 | |||
bf9249656a | |||
a616e91e4b | |||
9a33a99480 |
6 changed files with 114 additions and 50 deletions
1
.github/workflows/docs.yml
vendored
1
.github/workflows/docs.yml
vendored
|
@ -20,7 +20,6 @@ jobs:
|
||||||
|
|
||||||
- name: Deploy
|
- name: Deploy
|
||||||
uses: peaceiris/actions-gh-pages@v3
|
uses: peaceiris/actions-gh-pages@v3
|
||||||
if: ${{ github.ref == 'refs/heads/main' }}
|
|
||||||
with:
|
with:
|
||||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
# publish_dir: ./site
|
# publish_dir: ./site
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
USAGE={a.bold}{a.cyan} viv isn't venv{a.end}\n\n\ttasks:\n
|
USAGE={a.bold}{a.cyan} viv tasks{a.end}:\n
|
||||||
PHONIFY=1
|
PHONIFY=1
|
||||||
HELP_SEP={a.b_blue}>>>{a.end}
|
HELP_SEP={a.b_blue}>>>{a.end}
|
||||||
|
|
||||||
|
|
11
Makefile
11
Makefile
|
@ -7,7 +7,7 @@ lint: ## run pre-commit hooks
|
||||||
types: ## run mypy
|
types: ## run mypy
|
||||||
mypy src/viv
|
mypy src/viv
|
||||||
|
|
||||||
bump-version: ## update version and tag commit
|
bump: ## 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
|
||||||
@git add src/viv/viv.py && git commit -m "chore: bump version" --no-verify
|
@git add src/viv/viv.py && git commit -m "chore: bump version" --no-verify
|
||||||
|
@ -15,18 +15,9 @@ bump-version: ## update version and tag commit
|
||||||
@git tag -d latest || true
|
@git tag -d latest || true
|
||||||
@git tag latest
|
@git tag latest
|
||||||
|
|
||||||
|
|
||||||
venv: ## generate environment
|
venv: ## generate environment
|
||||||
pdm install
|
pdm install
|
||||||
|
|
||||||
# TAPES = demo freeze list-info-remove
|
|
||||||
# GIFS := $(foreach n, $(TAPES), docs/$(n).gif)
|
|
||||||
# docs: $(GIFS) # generate usage examples
|
|
||||||
|
|
||||||
# docs/%.gif: docs/%.tape
|
|
||||||
# viv rm $$(viv l -q)
|
|
||||||
# cd docs; vhs < $*.tape
|
|
||||||
|
|
||||||
clean: ## remove build artifacts
|
clean: ## remove build artifacts
|
||||||
rm -rf {build,dist}
|
rm -rf {build,dist}
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,10 @@
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
Try before you buy!
|
||||||
|
```sh
|
||||||
|
python3 <(curl -fsSL gh.dayl.in/viv/viv.py) run pycowsay -- "Viv isn't venv\!"
|
||||||
|
```
|
||||||
---
|
---
|
||||||
|
|
||||||
`Viv` is a standalone dependency-free `venv` creator.
|
`Viv` is a standalone dependency-free `venv` creator.
|
||||||
|
|
|
@ -296,7 +296,7 @@
|
||||||
d="M 262.18259,332.01108 H 98.56229 c -2.373369,0 -3.474782,-0.68927 -3.474782,-2.84947 V 196.72908 c 0,-1.09431 0.696377,-2.24547 2.259674,-2.24547 l 171.657068,0.16344 c 0.98062,0.007 2.50128,0.3624 2.50128,1.75516 l -5.7842,131.33112 c 0,2.26678 0.10659,4.24222 -3.53874,4.27775 z"
|
d="M 262.18259,332.01108 H 98.56229 c -2.373369,0 -3.474782,-0.68927 -3.474782,-2.84947 V 196.72908 c 0,-1.09431 0.696377,-2.24547 2.259674,-2.24547 l 171.657068,0.16344 c 0.98062,0.007 2.50128,0.3624 2.50128,1.75516 l -5.7842,131.33112 c 0,2.26678 0.10659,4.24222 -3.53874,4.27775 z"
|
||||||
style="fill:url(#linearGradient2675);stroke-width:0.710589" /><g
|
style="fill:url(#linearGradient2675);stroke-width:0.710589" /><g
|
||||||
id="g2303"
|
id="g2303"
|
||||||
transform="matrix(1.0141096,0,0,1.0141096,120.25928,195.81719)"><path
|
transform="matrix(0.95699137,0,0,0.95699137,118.57865,202.02858)"><path
|
||||||
id="path1948"
|
id="path1948"
|
||||||
style="fill:url(#linearGradient1478);fill-opacity:1"
|
style="fill:url(#linearGradient1478);fill-opacity:1"
|
||||||
d="m 60.510156,6.3979729 c -4.583653,0.021298 -8.960939,0.4122177 -12.8125,1.09375 C 36.35144,9.4962267 34.291407,13.691825 34.291406,21.429223 v 10.21875 h 26.8125 v 3.40625 h -26.8125 -10.0625 c -7.792459,0 -14.6157592,4.683717 -16.7500002,13.59375 -2.46182,10.212966 -2.5710151,16.586023 0,27.25 1.9059283,7.937852 6.4575432,13.593748 14.2500002,13.59375 h 9.21875 v -12.25 c 0,-8.849902 7.657144,-16.656248 16.75,-16.65625 h 26.78125 c 7.454951,0 13.406253,-6.138164 13.40625,-13.625 v -25.53125 c 0,-7.266339 -6.12998,-12.7247775 -13.40625,-13.9375001 -4.605987,-0.7667253 -9.385097,-1.1150483 -13.96875,-1.09375 z m -14.5,8.2187501 c 2.769547,0 5.03125,2.298646 5.03125,5.125 -2e-6,2.816336 -2.261703,5.09375 -5.03125,5.09375 -2.779476,-1e-6 -5.03125,-2.277415 -5.03125,-5.09375 -1e-6,-2.826353 2.251774,-5.125 5.03125,-5.125 z" /><path
|
d="m 60.510156,6.3979729 c -4.583653,0.021298 -8.960939,0.4122177 -12.8125,1.09375 C 36.35144,9.4962267 34.291407,13.691825 34.291406,21.429223 v 10.21875 h 26.8125 v 3.40625 h -26.8125 -10.0625 c -7.792459,0 -14.6157592,4.683717 -16.7500002,13.59375 -2.46182,10.212966 -2.5710151,16.586023 0,27.25 1.9059283,7.937852 6.4575432,13.593748 14.2500002,13.59375 h 9.21875 v -12.25 c 0,-8.849902 7.657144,-16.656248 16.75,-16.65625 h 26.78125 c 7.454951,0 13.406253,-6.138164 13.40625,-13.625 v -25.53125 c 0,-7.266339 -6.12998,-12.7247775 -13.40625,-13.9375001 -4.605987,-0.7667253 -9.385097,-1.1150483 -13.96875,-1.09375 z m -14.5,8.2187501 c 2.769547,0 5.03125,2.298646 5.03125,5.125 -2e-6,2.816336 -2.261703,5.09375 -5.03125,5.09375 -2.779476,-1e-6 -5.03125,-2.277415 -5.03125,-5.09375 -1e-6,-2.826353 2.251774,-5.125 5.03125,-5.125 z" /><path
|
||||||
|
@ -306,7 +306,7 @@
|
||||||
id="path1894"
|
id="path1894"
|
||||||
style="opacity:0.44382;fill:url(#radialGradient1480);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:20;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
style="opacity:0.44382;fill:url(#radialGradient1480);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:20;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
transform="matrix(0.73406,0,0,0.809524,16.24958,27.00935)"
|
transform="matrix(0.73406,0,0,0.809524,16.24958,27.00935)"
|
||||||
d="m 110.46717,132.28575 a 48.948285,8.6066792 0 1 1 -97.896571,0 48.948285,8.6066792 0 1 1 97.896571,0 z" /></g><path
|
d="m 110.46717,132.28575 a 48.948285,8.6066809 0 1 1 -97.896571,0 48.948285,8.6066809 0 1 1 97.896571,0 z" /></g><path
|
||||||
id="rect7393"
|
id="rect7393"
|
||||||
style="fill:url(#linearGradient2672);stroke-width:0.710589"
|
style="fill:url(#linearGradient2672);stroke-width:0.710589"
|
||||||
d="m 115.10481,165.35798 c -2.95605,0 -4.89596,1.63364 -5.74867,2.88997 l -13.749902,21.88686 c -0.753225,1.30748 -0.09238,2.24546 1.129837,2.24546 l 170.733305,0.24871 c 2.26678,-0.17765 3.29003,-0.86692 0.0426,-3.33977 l -24.7285,-20.29159 c -1.7978,-1.80135 -4.60462,-3.63964 -8.10783,-3.63964 z" /><path
|
d="m 115.10481,165.35798 c -2.95605,0 -4.89596,1.63364 -5.74867,2.88997 l -13.749902,21.88686 c -0.753225,1.30748 -0.09238,2.24546 1.129837,2.24546 l 170.733305,0.24871 c 2.26678,-0.17765 3.29003,-0.86692 0.0426,-3.33977 l -24.7285,-20.29159 c -1.7978,-1.80135 -4.60462,-3.63964 -8.10783,-3.63964 z" /><path
|
||||||
|
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
142
src/viv/viv.py
142
src/viv/viv.py
|
@ -52,7 +52,7 @@ from typing import (
|
||||||
from urllib.error import HTTPError
|
from urllib.error import HTTPError
|
||||||
from urllib.request import urlopen
|
from urllib.request import urlopen
|
||||||
|
|
||||||
__version__ = "23.5a3"
|
__version__ = "23.5a4-4-g158acbc-dev"
|
||||||
|
|
||||||
|
|
||||||
class Config:
|
class Config:
|
||||||
|
@ -226,7 +226,8 @@ class Ansi:
|
||||||
Args:
|
Args:
|
||||||
output: text output from subprocess, usually from p.stdout
|
output: text output from subprocess, usually from p.stdout
|
||||||
"""
|
"""
|
||||||
|
if not output:
|
||||||
|
return
|
||||||
echo("subprocess output:")
|
echo("subprocess output:")
|
||||||
new_output = [f"{self.red}->{self.end} {line}" for line in output.splitlines()]
|
new_output = [f"{self.red}->{self.end} {line}" for line in output.splitlines()]
|
||||||
sys.stdout.write("\n".join(new_output) + "\n")
|
sys.stdout.write("\n".join(new_output) + "\n")
|
||||||
|
@ -559,11 +560,12 @@ class ViVenv:
|
||||||
name: str = "",
|
name: str = "",
|
||||||
path: Path | None = None,
|
path: Path | None = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
self.spec = spec
|
self.spec = self._validate_spec(spec)
|
||||||
self.exe = str(Path(sys.executable).resolve()) if track_exe else "N/A"
|
self.exe = str(Path(sys.executable).resolve()) if track_exe else "N/A"
|
||||||
self.id = id if id else get_hash(spec, track_exe)
|
self.id = id if id else get_hash(spec, track_exe)
|
||||||
self.name = name if name else self.id
|
self.name = name if name else self.id
|
||||||
self.path = path if path else c.venvcache / self.name
|
self.path = path if path else c.venvcache / self.name
|
||||||
|
self.exists = self.name in [d.name for d in c.venvcache.iterdir()]
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def load(cls, name: str) -> "ViVenv":
|
def load(cls, name: str) -> "ViVenv":
|
||||||
|
@ -583,6 +585,18 @@ class ViVenv:
|
||||||
|
|
||||||
return vivenv
|
return vivenv
|
||||||
|
|
||||||
|
def _validate_spec(self, spec: List[str]) -> List[str]:
|
||||||
|
"""ensure spec is at least of sequence of strings
|
||||||
|
|
||||||
|
Args:
|
||||||
|
spec: sequence of package specifications
|
||||||
|
"""
|
||||||
|
if not set(map(type, spec)) == {str}:
|
||||||
|
error("unexepected input in package spec")
|
||||||
|
error(f"check your packages definitions: {spec}", code=1)
|
||||||
|
|
||||||
|
return sorted(spec)
|
||||||
|
|
||||||
def create(self, quiet: bool = False) -> None:
|
def create(self, quiet: bool = False) -> None:
|
||||||
if not quiet:
|
if not quiet:
|
||||||
echo(f"new unique vivenv -> {self.name}")
|
echo(f"new unique vivenv -> {self.name}")
|
||||||
|
@ -636,12 +650,9 @@ def use(*packages: str, track_exe: bool = False, name: str = "") -> Path:
|
||||||
track_exe: if true make env python exe specific
|
track_exe: if true make env python exe specific
|
||||||
name: use as vivenv name, if not provided id is used
|
name: use as vivenv name, if not provided id is used
|
||||||
"""
|
"""
|
||||||
validate_spec(packages)
|
|
||||||
vivenv = ViVenv(list(packages), track_exe=track_exe, name=name)
|
vivenv = ViVenv(list(packages), track_exe=track_exe, name=name)
|
||||||
|
|
||||||
if vivenv.name not in [d.name for d in c.venvcache.iterdir()] or os.getenv(
|
if not vivenv.exists or os.getenv("VIV_FORCE"):
|
||||||
"VIV_FORCE"
|
|
||||||
):
|
|
||||||
vivenv.create()
|
vivenv.create()
|
||||||
vivenv.install_pkgs()
|
vivenv.install_pkgs()
|
||||||
vivenv.dump_info(write=True)
|
vivenv.dump_info(write=True)
|
||||||
|
@ -650,18 +661,6 @@ def use(*packages: str, track_exe: bool = False, name: str = "") -> Path:
|
||||||
return vivenv.path
|
return vivenv.path
|
||||||
|
|
||||||
|
|
||||||
def validate_spec(spec: Tuple[str, ...]) -> None:
|
|
||||||
"""ensure spec is at least of sequence of strings
|
|
||||||
|
|
||||||
Args:
|
|
||||||
spec: sequence of package specifications
|
|
||||||
"""
|
|
||||||
# ? make this a part of ViVenv?
|
|
||||||
if not set(map(type, spec)) == {str}:
|
|
||||||
error("unexepected input in package spec")
|
|
||||||
error(f"check your packages definitions: {spec}", code=1)
|
|
||||||
|
|
||||||
|
|
||||||
def modify_sys_path(new_path: Path) -> None:
|
def modify_sys_path(new_path: Path) -> None:
|
||||||
# remove user-site
|
# remove user-site
|
||||||
for i, path in enumerate(sys.path):
|
for i, path in enumerate(sys.path):
|
||||||
|
@ -939,12 +938,11 @@ class Viv:
|
||||||
)
|
)
|
||||||
|
|
||||||
def _match_vivenv(self, name_id: str) -> ViVenv: # type: ignore[return]
|
def _match_vivenv(self, name_id: str) -> ViVenv: # type: ignore[return]
|
||||||
# TODO: improve matching algorithm to favor names over id's
|
|
||||||
matches: List[ViVenv] = []
|
matches: List[ViVenv] = []
|
||||||
for k, v in self.vivenvs.items():
|
for k, v in self.vivenvs.items():
|
||||||
if name_id == k or v.name == name_id:
|
if name_id == k or v.name == name_id:
|
||||||
matches.append(v)
|
matches.append(v)
|
||||||
elif k.startswith(name_id) or v.id.startswith(name_id):
|
elif k.startswith(name_id) or (v.id.startswith(name_id) and v.id == v.name):
|
||||||
matches.append(v)
|
matches.append(v)
|
||||||
elif v.name.startswith(name_id):
|
elif v.name.startswith(name_id):
|
||||||
matches.append(v)
|
matches.append(v)
|
||||||
|
@ -1013,7 +1011,7 @@ class Viv:
|
||||||
a.table(rows)
|
a.table(rows)
|
||||||
|
|
||||||
def exe(self, args: Namespace) -> None:
|
def exe(self, args: Namespace) -> None:
|
||||||
"""run python/pip in vivenv"""
|
"""run python/pip in existing vivenv"""
|
||||||
|
|
||||||
vivenv = self._match_vivenv(args.vivenv)
|
vivenv = self._match_vivenv(args.vivenv)
|
||||||
|
|
||||||
|
@ -1025,7 +1023,7 @@ class Viv:
|
||||||
f"{pip_path} {' '.join(args.cmd)}"
|
f"{pip_path} {' '.join(args.cmd)}"
|
||||||
if args.exe == "pip"
|
if args.exe == "pip"
|
||||||
else f"{python_path} {' '.join(args.cmd)}"
|
else f"{python_path} {' '.join(args.cmd)}"
|
||||||
)
|
) + " ".join(args.rest)
|
||||||
|
|
||||||
echo(f"executing {cmd}")
|
echo(f"executing {cmd}")
|
||||||
run(shlex.split(cmd), verbose=True)
|
run(shlex.split(cmd), verbose=True)
|
||||||
|
@ -1048,16 +1046,19 @@ class Viv:
|
||||||
make_executable(src)
|
make_executable(src)
|
||||||
echo("symlinking cli")
|
echo("symlinking cli")
|
||||||
|
|
||||||
if not cli.is_file():
|
if cli.is_file() and confirm(
|
||||||
|
f"Existing file at {a.style(str(cli),'bold')}, "
|
||||||
|
"would you like to overwrite it?"
|
||||||
|
):
|
||||||
|
cli.unlink()
|
||||||
cli.symlink_to(src)
|
cli.symlink_to(src)
|
||||||
else:
|
else:
|
||||||
cli.unlink()
|
|
||||||
cli.symlink_to(src)
|
cli.symlink_to(src)
|
||||||
|
|
||||||
echo("Remember to include the following line in your shell rc file:")
|
echo("Remember to include the following line in your shell rc file:")
|
||||||
sys.stderr.write(
|
sys.stderr.write(
|
||||||
' export PYTHONPATH="$PYTHONPATH:$HOME/'
|
' export PYTHONPATH="$PYTHONPATH:$HOME/'
|
||||||
f'{src.relative_to(Path.home())}"\n'
|
f'{src.relative_to(Path.home()).parent}"\n'
|
||||||
)
|
)
|
||||||
|
|
||||||
def manage(self, args: Namespace) -> None:
|
def manage(self, args: Namespace) -> None:
|
||||||
|
@ -1179,6 +1180,10 @@ class Viv:
|
||||||
"`python3 <(curl -fsSL gh.dayl.in/viv/viv.py) manage install`"
|
"`python3 <(curl -fsSL gh.dayl.in/viv/viv.py) manage install`"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def _pick_bin(self, args: Namespace) -> Tuple[str, str]:
|
||||||
|
default = re.split(r"[=><~!*]+", args.reqs[0])[0]
|
||||||
|
return default, (default if not args.bin else args.bin)
|
||||||
|
|
||||||
def shim(self, args: Namespace) -> None:
|
def shim(self, args: Namespace) -> None:
|
||||||
"""\
|
"""\
|
||||||
generate viv-powered cli apps
|
generate viv-powered cli apps
|
||||||
|
@ -1192,8 +1197,7 @@ class Viv:
|
||||||
if not args.reqs:
|
if not args.reqs:
|
||||||
error("please specify at lease one dependency", code=1)
|
error("please specify at lease one dependency", code=1)
|
||||||
|
|
||||||
default_bin = re.split(r"[=><~!*]+", args.reqs[0])[0]
|
default_bin, bin = self._pick_bin(args)
|
||||||
bin = default_bin if not args.bin else args.bin
|
|
||||||
output = (
|
output = (
|
||||||
c.binparent / default_bin if not args.output else args.output.absolute()
|
c.binparent / default_bin if not args.output else args.output.absolute()
|
||||||
)
|
)
|
||||||
|
@ -1240,6 +1244,43 @@ class Viv:
|
||||||
|
|
||||||
make_executable(output)
|
make_executable(output)
|
||||||
|
|
||||||
|
def run(self, args: Namespace) -> None:
|
||||||
|
"""\
|
||||||
|
run an app with an on-demand venv
|
||||||
|
|
||||||
|
examples:
|
||||||
|
viv r pycowsay -- "Viv isn't venv\!"
|
||||||
|
viv r rich -b python -- -m rich
|
||||||
|
"""
|
||||||
|
if not args.reqs:
|
||||||
|
error("please specify at lease one dependency", code=1)
|
||||||
|
|
||||||
|
_, bin = self._pick_bin(args)
|
||||||
|
spec = combined_spec(args.reqs, args.requirements)
|
||||||
|
vivenv = ViVenv(spec)
|
||||||
|
|
||||||
|
# TODO: respect a VIV_RUN_MODE env variable as the same as keep i.e.
|
||||||
|
# ephemeral (default), semi-ephemeral (persist inside /tmp), or
|
||||||
|
# persist (use c.cache)
|
||||||
|
|
||||||
|
if not vivenv.exists or os.getenv("VIV_FORCE"):
|
||||||
|
if not args.keep:
|
||||||
|
with tempfile.TemporaryDirectory(prefix="viv-") as tmpdir:
|
||||||
|
vivenv.path = Path(tmpdir)
|
||||||
|
vivenv.create()
|
||||||
|
vivenv.install_pkgs()
|
||||||
|
sys.exit(
|
||||||
|
subprocess.run(
|
||||||
|
[vivenv.path / "bin" / bin, *args.rest]
|
||||||
|
).returncode
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
vivenv.create()
|
||||||
|
vivenv.install_pkgs()
|
||||||
|
vivenv.dump_info(write=True)
|
||||||
|
|
||||||
|
sys.exit(subprocess.run([vivenv.path / "bin" / bin, *args.rest]).returncode)
|
||||||
|
|
||||||
def _get_subcmd_parser(
|
def _get_subcmd_parser(
|
||||||
self,
|
self,
|
||||||
subparsers: _SubParsersAction[ArgumentParser],
|
subparsers: _SubParsersAction[ArgumentParser],
|
||||||
|
@ -1409,11 +1450,10 @@ class Viv:
|
||||||
"purge", help="remove traces of viv", aliases="p", parents=[p_manage_shared]
|
"purge", help="remove traces of viv", aliases="p", parents=[p_manage_shared]
|
||||||
).set_defaults(func=self.manage, cmd="purge")
|
).set_defaults(func=self.manage, cmd="purge")
|
||||||
|
|
||||||
(
|
p_shim = self._get_subcmd_parser(
|
||||||
p_shim := self._get_subcmd_parser(
|
subparsers, "shim", parents=[p_freeze_shim_shared]
|
||||||
subparsers, "shim", parents=[p_freeze_shim_shared]
|
)
|
||||||
)
|
|
||||||
).set_defaults(func=self.shim, cmd="shim")
|
|
||||||
p_shim.add_argument(
|
p_shim.add_argument(
|
||||||
"-f",
|
"-f",
|
||||||
"--freeze",
|
"--freeze",
|
||||||
|
@ -1427,11 +1467,41 @@ class Viv:
|
||||||
type=Path,
|
type=Path,
|
||||||
metavar="<path>",
|
metavar="<path>",
|
||||||
)
|
)
|
||||||
p_shim.add_argument("-b", "--bin", help="console_script/script to invoke")
|
p_shim.add_argument(
|
||||||
|
"-b", "--bin", help="console_script/script to invoke", metavar="<bin>"
|
||||||
|
)
|
||||||
|
|
||||||
args = parser.parse_args()
|
p_run = self._get_subcmd_parser(subparsers, "run")
|
||||||
|
|
||||||
args.func(args)
|
p_run.add_argument(
|
||||||
|
"-r",
|
||||||
|
"--requirements",
|
||||||
|
help="path/to/requirements.txt file",
|
||||||
|
metavar="<path>",
|
||||||
|
)
|
||||||
|
p_run.add_argument(
|
||||||
|
"-k",
|
||||||
|
"--keep",
|
||||||
|
help="preserve environment",
|
||||||
|
action="store_true",
|
||||||
|
)
|
||||||
|
p_run.add_argument("reqs", help="requirements specifiers", nargs="*")
|
||||||
|
|
||||||
|
p_run.add_argument(
|
||||||
|
"-b", "--bin", help="console_script/script to invoke", metavar="<bin>"
|
||||||
|
)
|
||||||
|
|
||||||
|
if "--" in sys.argv:
|
||||||
|
i = sys.argv.index("--")
|
||||||
|
args = parser.parse_args(sys.argv[1:i])
|
||||||
|
args.rest = sys.argv[i + 1 :]
|
||||||
|
else:
|
||||||
|
args = parser.parse_args()
|
||||||
|
args.rest = []
|
||||||
|
|
||||||
|
args.func(
|
||||||
|
args,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def main() -> None:
|
def main() -> None:
|
||||||
|
|
Loading…
Reference in a new issue