dev-utils/dev_utils/__main__.py

135 lines
3.4 KiB
Python

import importlib.resources
import shutil
import subprocess
import sys
import textwrap
import typing as t
from pathlib import Path
import typer
from typer.main import get_group
from dev_utils import __version__
IS_WINDOWS = sys.platform == "win32"
app = typer.Typer(
context_settings={
"max_content_width": 80,
}
)
def version_callback(value: bool):
if value:
typer.echo(f"{__version__}")
raise typer.Exit()
@app.callback()
def main(
version: t.Optional[bool] = typer.Option(
None,
"--version",
callback=version_callback,
is_eager=True,
help="Show the version and exit.",
),
):
"""A collection of provisioning tools for common tasks during (mostly python) development."""
@app.command()
def precommit(max_tries: int = typer.Option(3)):
"""If precommit is available, run it until it succeeds or `max_tries` is exceeded."""
if precommit := shutil.which("pre-commit"):
cmdlist = [precommit, "run", "--all-files"]
while max_tries > 0:
res = subprocess.run(cmdlist)
if res.returncode == 0:
break
max_tries -= 1
@app.command()
def venv(
base_python: t.Optional[str] = typer.Option(None),
name: str = typer.Option("venv"),
do_update: bool = typer.Option(True),
):
"""Make a venv"""
venv_location = Path.cwd().joinpath(name)
cmdlist = [
"python" if not base_python else base_python,
"-m",
"venv",
str(venv_location),
]
res = subprocess.run(cmdlist)
if not res.returncode == 0:
raise typer.Exit()
if not do_update:
raise typer.Exit()
if IS_WINDOWS:
venv_python = str(venv_location.joinpath("Scripts", "python.exe"))
else:
venv_python = str(venv_location.joinpath("bin", "python"))
cmdlist = [
venv_python,
"-m",
"pip",
"install",
"--upgrade",
"pip",
"setuptools",
"wheel",
]
subprocess.run(cmdlist)
raise typer.Exit()
@app.command()
def direnv_init(
replace: bool = typer.Option(False),
target_dir: Path = typer.Option(Path.home().joinpath(".config", "direnv")),
):
"""Configure the user's direnv rc file"""
if IS_WINDOWS:
typer.echo("Direnv is not available on windows")
raise typer.Exit()
open_mode = "w" if replace else "a"
ref = importlib.resources.files("dev_utils.resources").joinpath("direnvrc.txt")
target_dir.mkdir(exist_ok=True, parents=True)
target_file = target_dir.joinpath("direnvrc")
with importlib.resources.as_file(ref) as datapath:
target_file.open(open_mode).write(datapath.read_text())
typer.echo(
f"{'Wrote' if replace else 'Appended'} direnvrc contents to {target_file}"
)
raise typer.Exit()
@app.command()
def direnv(python_version: t.Optional[str] = typer.Option(None)):
"""Emit the contents of a .envrc file suitable for python development."""
if IS_WINDOWS:
typer.echo("Direnv is not available on windows")
raise typer.Exit()
version_string = python_version if python_version else ""
typer.echo(
textwrap.dedent(
f"""\
export VIRTUAL_ENV=./venv
layout python-venv {version_string}
export PYTHONBREAKPOINT="pudb.set_trace"
"""
)
)
raise typer.Exit()
# must be below all @app.command()s.
_subcommand_names = list(typer.main.get_command(app).commands)