Skip to content

Instantly share code, notes, and snippets.

@energizah
Last active February 12, 2019 02:01
Show Gist options
  • Save energizah/3cbab5783d5e9eb93ee8e0c561f9f25e to your computer and use it in GitHub Desktop.
Save energizah/3cbab5783d5e9eb93ee8e0c561f9f25e to your computer and use it in GitHub Desktop.
#!/usr/bin/env python3
import argparse
import functools
import os
import pathlib
import shutil
import subprocess
import sys
import types
import urllib.request
class _Registry:
def __init__(self):
self.registered = {}
def __call__(self, function=None, name=None):
if function is None and name is None:
raise TypeError("Pass a function or name.")
if function is None:
return functools.partial(self, name=name)
self.registered[function.__name__.replace("_", "-")] = function
return function
_register = _Registry()
@_register
def clean(cfg):
"""Remove extraneous files."""
paths = (
[str(cfg.venv_path), ".coverage"]
+ list(pathlib.Path().glob(".coverage.*"))
+ ["dist"]
)
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, str(cfg.venv_path)], check=True
)
if not pathlib.Path("requirements.txt").exists():
raise FileNotFoundError("Run `lock` first, to create requirements.txt.")
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,
)
if pathlib.Path("dev-requirements.in").exists():
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)
@_register
def update_pycli(cfg):
"""Update this script to the latest github version."""
url = "https://gist.githubusercontent.com/energizerhub/3cbab5783d5e9eb93ee8e0c561f9f25e/raw/pycli"
with open(pathlib.Path(__file__), "wb") as current_script:
data = urllib.request.urlopen(url).read()
current_script.write(data)
def _get_default_venv_path():
"""Get the default path of the venv."""
if (pathlib.Path().resolve() / "venv").exists():
return pathlib.Path().resolve() / "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 (if exists already), $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()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment