221 lines
5.2 KiB
Python
221 lines
5.2 KiB
Python
import os
|
|
import sys
|
|
|
|
from datetime import datetime
|
|
|
|
from invoke import task
|
|
|
|
ROOT = os.path.dirname(__file__)
|
|
|
|
CLEAN_PATTERNS = [
|
|
"build",
|
|
"dist",
|
|
"cover",
|
|
"docs/_build",
|
|
"**/*.pyc",
|
|
".tox",
|
|
"**/__pycache__",
|
|
"reports",
|
|
"*.egg-info",
|
|
]
|
|
|
|
|
|
def color(code):
|
|
"""A simple ANSI color wrapper factory"""
|
|
return lambda t: "\033[{0}{1}\033[0;m".format(code, t)
|
|
|
|
|
|
green = color("1;32m")
|
|
red = color("1;31m")
|
|
blue = color("1;30m")
|
|
cyan = color("1;36m")
|
|
purple = color("1;35m")
|
|
white = color("1;39m")
|
|
|
|
|
|
def header(text):
|
|
"""Display an header"""
|
|
print(" ".join((blue(">>"), cyan(text))))
|
|
sys.stdout.flush()
|
|
|
|
|
|
def info(text, *args, **kwargs):
|
|
"""Display informations"""
|
|
text = text.format(*args, **kwargs)
|
|
print(" ".join((purple(">>>"), text)))
|
|
sys.stdout.flush()
|
|
|
|
|
|
def success(text):
|
|
"""Display a success message"""
|
|
print(" ".join((green(">>"), white(text))))
|
|
sys.stdout.flush()
|
|
|
|
|
|
def error(text):
|
|
"""Display an error message"""
|
|
print(red("✘ {0}".format(text)))
|
|
sys.stdout.flush()
|
|
|
|
|
|
def exit(text=None, code=-1):
|
|
if text:
|
|
error(text)
|
|
sys.exit(-1)
|
|
|
|
|
|
def build_args(*args):
|
|
return " ".join(a for a in args if a)
|
|
|
|
|
|
@task
|
|
def clean(ctx):
|
|
"""Cleanup all build artifacts"""
|
|
header(clean.__doc__)
|
|
with ctx.cd(ROOT):
|
|
for pattern in CLEAN_PATTERNS:
|
|
info("Removing {0}", pattern)
|
|
ctx.run("rm -rf {0}".format(pattern))
|
|
|
|
|
|
@task
|
|
def deps(ctx):
|
|
"""Install or update development dependencies"""
|
|
header(deps.__doc__)
|
|
with ctx.cd(ROOT):
|
|
ctx.run(
|
|
"pip install -r requirements/develop.pip -r requirements/doc.pip", pty=True
|
|
)
|
|
|
|
|
|
@task
|
|
def demo(ctx):
|
|
"""Run the demo"""
|
|
header(demo.__doc__)
|
|
with ctx.cd(ROOT):
|
|
ctx.run("python examples/todo.py")
|
|
|
|
|
|
@task
|
|
def test(ctx, profile=False):
|
|
"""Run tests suite"""
|
|
header(test.__doc__)
|
|
kwargs = build_args(
|
|
"--benchmark-skip",
|
|
"--profile" if profile else None,
|
|
)
|
|
with ctx.cd(ROOT):
|
|
ctx.run("pytest {0}".format(kwargs), pty=True)
|
|
|
|
|
|
@task
|
|
def benchmark(
|
|
ctx,
|
|
max_time=2,
|
|
save=False,
|
|
compare=False,
|
|
histogram=False,
|
|
profile=False,
|
|
tox=False,
|
|
):
|
|
"""Run benchmarks"""
|
|
header(benchmark.__doc__)
|
|
ts = datetime.now()
|
|
kwargs = build_args(
|
|
"--benchmark-max-time={0}".format(max_time),
|
|
"--benchmark-autosave" if save else None,
|
|
"--benchmark-compare" if compare else None,
|
|
"--benchmark-histogram=histograms/{0:%Y%m%d-%H%M%S}".format(ts)
|
|
if histogram
|
|
else None,
|
|
"--benchmark-cprofile=tottime" if profile else None,
|
|
)
|
|
cmd = "pytest tests/benchmarks {0}".format(kwargs)
|
|
if tox:
|
|
envs = ctx.run("tox -l", hide=True).stdout.splitlines()
|
|
envs = ",".join(e for e in envs if e != "doc")
|
|
cmd = "tox -e {envs} -- {cmd}".format(envs=envs, cmd=cmd)
|
|
ctx.run(cmd, pty=True)
|
|
|
|
|
|
@task
|
|
def cover(ctx, html=False):
|
|
"""Run tests suite with coverage"""
|
|
header(cover.__doc__)
|
|
extra = "--cov-report html" if html else ""
|
|
with ctx.cd(ROOT):
|
|
ctx.run(
|
|
"pytest --benchmark-skip --cov flask_restx --cov-report term --cov-report xml {0}".format(
|
|
extra
|
|
),
|
|
pty=True,
|
|
)
|
|
|
|
|
|
@task
|
|
def tox(ctx):
|
|
"""Run tests against Python versions"""
|
|
header(tox.__doc__)
|
|
ctx.run("tox", pty=True)
|
|
|
|
|
|
@task
|
|
def qa(ctx):
|
|
"""Run a quality report"""
|
|
header(qa.__doc__)
|
|
with ctx.cd(ROOT):
|
|
info("Ensure PyPI can render README and CHANGELOG")
|
|
info("Building dist package")
|
|
dist = ctx.run("python setup.py sdist", pty=True, warn=False, hide=True)
|
|
if dist.failed:
|
|
error("Unable to build sdist package")
|
|
exit("Quality check failed", dist.return_code)
|
|
readme_results = ctx.run("twine check dist/*", pty=True, warn=True, hide=True)
|
|
if readme_results.failed:
|
|
print(readme_results.stdout)
|
|
error("README and/or CHANGELOG is not renderable by PyPI")
|
|
else:
|
|
success("README and CHANGELOG are renderable by PyPI")
|
|
if readme_results.failed:
|
|
exit("Quality check failed", readme_results.return_code)
|
|
success("Quality check OK")
|
|
|
|
|
|
@task
|
|
def doc(ctx):
|
|
"""Build the documentation"""
|
|
header(doc.__doc__)
|
|
with ctx.cd(os.path.join(ROOT, "doc")):
|
|
ctx.run("make html", pty=True)
|
|
|
|
|
|
@task
|
|
def assets(ctx):
|
|
"""Fetch web assets"""
|
|
header(assets.__doc__)
|
|
with ctx.cd(ROOT):
|
|
ctx.run("npm install")
|
|
ctx.run("mkdir -p flask_restx/static")
|
|
ctx.run(
|
|
"cp node_modules/swagger-ui-dist/{swagger-ui*.{css,js}{,.map},favicon*.png,oauth2-redirect.html} flask_restx/static"
|
|
)
|
|
# Until next release we need to install droid sans separately
|
|
ctx.run(
|
|
"cp node_modules/typeface-droid-sans/index.css flask_restx/static/droid-sans.css"
|
|
)
|
|
ctx.run("cp -R node_modules/typeface-droid-sans/files flask_restx/static/")
|
|
|
|
|
|
@task
|
|
def dist(ctx):
|
|
"""Package for distribution"""
|
|
header(dist.__doc__)
|
|
with ctx.cd(ROOT):
|
|
ctx.run("python setup.py bdist_wheel", pty=True)
|
|
|
|
|
|
@task(clean, deps, test, doc, qa, assets, dist, default=True)
|
|
def all(ctx):
|
|
"""Run tests, reports and packaging"""
|
|
pass
|