-
- #!/usr/bin/env python3
-
- import argparse
- import os
- import pathlib
- import shutil
- import subprocess
- import sys
- import types
-
-
- class _Registry:
- def __init__(self):
- self.registered = {}
-
- def __call__(self, function):
- self.registered[function.__name__] = function
- return function
-
-
- _register = _Registry()
-
-
- @_register
- def clean(cfg):
- """Remove extraneous files."""
- paths = [cfg.venv_path, ".coverage"] + list(pathlib.Path().glob(".coverage.*"))
-
- for path in paths:
- try:
- shutil.rmtree(path)
- except FileNotFoundError:
- pass
-
-
- @_register
- def init(cfg):
- """Set up a virtualenv, install requirements.txt, dev-requirements.txt, and current dir."""
-
- subprocess.run(
- ["virtualenv", "--python", sys.executable, cfg.venv_path], check=True
- )
- lock(cfg)
- if pathlib.Path("dev-requirements.txt").exists():
- subprocess.run(
- [
- cfg.venv_path / "bin/pip",
- "install",
- "--requirement",
- "dev-requirements.txt",
- ],
- check=True,
- )
- subprocess.run(
- [cfg.venv_path / "bin/pip", "install", "--requirement", "requirements.txt"],
- check=True,
- )
- subprocess.run(
- [cfg.venv_path / "bin/pip", "install", "--editable", "."], check=True
- )
-
-
- @_register
- def lock(cfg):
- """Use pip-compile to generate package hashes from setup.py and write them into requirements.txt."""
- subprocess.run([cfg.venv_path / "bin/pip", "install", "pip-tools"], check=True)
- subprocess.run(
- [
- cfg.venv_path / "bin/pip-compile",
- "--generate-hashes",
- "--output-file",
- "requirements.txt",
- "setup.py",
- ],
- check=True,
- )
- subprocess.run(
- [
- cfg.venv_path / "bin/pip-compile",
- "--generate-hashes",
- "--output-file",
- "dev-requirements.txt",
- "setup.py",
- "dev-requirements.in",
- ],
- check=True,
- )
-
-
- @_register
- def build(cfg):
- """Build source and binary distributions."""
- subprocess.run(
- [cfg.venv_path / "bin/python", "setup.py", "sdist", "bdist_wheel"], check=True
- )
-
-
- @_register
- def upload(cfg):
- """Upload the distributions to PyPI."""
- subprocess.run([cfg.venv_path / "bin/python", "-m", "pip", "install", "twine"])
- dists = [str(path) for path in pathlib.Path("dist").iterdir()]
- subprocess.run([cfg.venv_path / "bin/twine", "upload", *dists], check=True)
-
-
- def _get_default_venv_path():
- """Get the default path of the venv."""
- venv_path = os.environ.get("VENV_PATH")
- if venv_path:
- return pathlib.Path(venv_path)
-
- workon_home = os.environ.get("WORKON_HOME")
- if workon_home is not None:
- project_name = pathlib.Path(os.getcwd()).name
- return pathlib.Path(workon_home) / project_name
-
- return pathlib.Path().resolve() / "venv"
-
-
- def cli():
- parser = argparse.ArgumentParser()
-
- parser.add_argument(
- "--venv",
- default=_get_default_venv_path(),
- type=pathlib.Path,
- help="Path of the venv directory. Defaults, in order: $VENV_PATH, $WORKON_HOME/[current directory name], venv",
- )
-
- subparsers = parser.add_subparsers(dest="command_name")
- for name, function in _register.registered.items():
- subparsers.add_parser(name, help=function.__doc__)
-
- args = parser.parse_args()
- if args.command_name is None:
- parser.print_help()
- sys.exit(2)
-
- function = _register.registered[args.command_name]
- cfg = types.SimpleNamespace()
- cfg.venv_path = args.venv
- function(cfg)
-
-
- if __name__ == "__main__":
- cli()
-