diff --git a/Makefile b/Makefile deleted file mode 100644 index dd2c761..0000000 --- a/Makefile +++ /dev/null @@ -1,92 +0,0 @@ -.PHONY: clean clean-test clean-pyc clean-build docs help -.DEFAULT_GOAL := help - -define BROWSER_PYSCRIPT -import os, webbrowser, sys - -try: - from urllib import pathname2url -except: - from urllib.request import pathname2url - -webbrowser.open("file://" + pathname2url(os.path.abspath(sys.argv[1]))) -endef -export BROWSER_PYSCRIPT - -define PRINT_HELP_PYSCRIPT -import re, sys - -for line in sys.stdin: - match = re.match(r'^([a-zA-Z_-]+):.*?## (.*)$$', line) - if match: - target, help = match.groups() - print("%-20s %s" % (target, help)) -endef -export PRINT_HELP_PYSCRIPT - -BROWSER := python -c "$$BROWSER_PYSCRIPT" - -help: - @python -c "$$PRINT_HELP_PYSCRIPT" < $(MAKEFILE_LIST) - -clean: clean-build clean-pyc clean-test ## remove all build, test, coverage and Python artifacts - -clean-build: ## remove build artifacts - rm -fr build/ - rm -fr dist/ - rm -fr .eggs/ - find . -name '*.egg-info' -exec rm -fr {} + - find . -name '*.egg' -exec rm -f {} + - -clean-pyc: ## remove Python file artifacts - find . -name '*.pyc' -exec rm -f {} + - find . -name '*.pyo' -exec rm -f {} + - find . -name '*~' -exec rm -f {} + - find . -name '__pycache__' -exec rm -fr {} + - -clean-test: ## remove test and coverage artifacts - rm -fr .tox/ - rm -f .coverage - rm -fr htmlcov/ - rm -fr .pytest_cache - -lint: ## check style with flake8 - flake8 sequence tests - -pretty: ## reformat files to make them look pretty - find sequence tests -name '*.py' | xargs isort - black setup.py sequence tests - -test: ## run tests quickly with the default Python - pytest --cov=sequence - -test-all: ## run tests on every Python version with tox - tox - -coverage: ## check code coverage quickly with the default Python - coverage run --source sequence -m pytest - coverage report -m - coverage html - $(BROWSER) htmlcov/index.html - -docs: ## generate Sphinx HTML documentation, including API docs - rm -f docs/api/sequence.rst - rm -f docs/api/modules.rst - sphinx-apidoc --force -o docs/api sequence tests - $(MAKE) -C docs clean - $(MAKE) -C docs html - $(BROWSER) docs/_build/html/index.html - -servedocs: docs ## compile the docs watching for changes - watchmedo shell-command -p '*.rst' -c '$(MAKE) -C docs html' -R -D . - -release: dist ## package and upload a release - twine upload dist/* - -dist: clean ## builds source and wheel package - python setup.py sdist - python setup.py bdist_wheel - ls -l dist - -install: clean ## install the package to the active Python's site-packages - python setup.py install diff --git a/README.rst b/README.rst index 4d43e0c..e54fad8 100644 --- a/README.rst +++ b/README.rst @@ -406,6 +406,9 @@ file:: If you would like your subsidence profile to change with time, see the section above, `Time-varying parameters`_. +.. end-input-files + + Output File ----------- @@ -427,8 +430,6 @@ You can now run the simulation (from within the *example* folder):: $ sequence run -.. end-input-files - Plotting output --------------- diff --git a/docs/readme.rst b/docs/readme.rst deleted file mode 100644 index 72a3355..0000000 --- a/docs/readme.rst +++ /dev/null @@ -1 +0,0 @@ -.. include:: ../README.rst diff --git a/news/60.misc b/news/60.misc new file mode 100644 index 0000000..ec66582 --- /dev/null +++ b/news/60.misc @@ -0,0 +1,3 @@ +Set up `nox `_ to automate testing and routine package +maintenance. + diff --git a/noxfile.py b/noxfile.py new file mode 100644 index 0000000..11f0624 --- /dev/null +++ b/noxfile.py @@ -0,0 +1,144 @@ +import os +import pathlib +import shutil +from itertools import chain + +import nox + + +@nox.session +def tests(session: nox.Session) -> None: + """Run the tests.""" + session.install("pytest") + session.install(".[dev]") + session.run("pytest", "--cov=sequence", "-vvv") + session.run("coverage", "report", "--ignore-errors", "--show-missing") + # "--fail-under=100", + + +@nox.session +def notebooks(session: nox.Session) -> None: + """Run the notebooks.""" + session.install(".[dev,notebook]") + session.run("pytest", "--nbmake", "notebooks/") + + +@nox.session +def cli(session: nox.Session) -> None: + """Test the command line interface.""" + session.install(".") + session.run("sequence", "--version") + session.run("sequence", "--help") + session.run("sequence", "generate", "--help") + session.run("sequence", "plot", "--help") + session.run("sequence", "run", "--help") + session.run("sequence", "setup", "--help") + + INFILES = ("bathymetry.csv", "sealevel.csv", "sequence.toml", "subsidence.csv") + + for infile in INFILES: + session.run("sequence", "generate", infile) + session.run("sequence", "generate", "sequence.yaml") + + tmp_dir = pathlib.Path(session.create_tmp()).absolute() + session.cd(tmp_dir) + for infile in INFILES: + (tmp_dir / infile).unlink(missing_ok=True) + + session.run("sequence", "setup") + for infile in INFILES: + assert pathlib.Path(infile).is_file() + assert not pathlib.Path("sequence.yaml").exists() + + +@nox.session +def lint(session: nox.Session) -> None: + """Look for lint.""" + session.install("pre-commit") + session.run("pre-commit", "run", "--all-files") + + towncrier(session) + + +@nox.session +def towncrier(session: nox.Session) -> None: + """Check that there is a news fragment.""" + session.install("towncrier") + session.run("towncrier", "check", "--compare-with", "origin/develop") + + +@nox.session +def docs(session: nox.Session) -> None: + """Build the docs.""" + session.install(".[doc]") + + session.chdir("docs") + if os.path.exists("_build"): + shutil.rmtree("_build") + session.run("sphinx-apidoc", "--force", "-o", "api", "../sequence") + session.run("sphinx-build", "-b", "html", "-W", ".", "_build/html") + + +@nox.session +def build(session: nox.Session) -> None: + """Build sdist and wheel dists.""" + session.install("pip") + session.install("wheel") + session.install("setuptools") + session.run("python", "--version") + session.run("pip", "--version") + session.run( + "python", "setup.py", "bdist_wheel", "sdist", "--dist-dir", "./wheelhouse" + ) + + +@nox.session +def release(session): + """Tag, build and publish a new release to PyPI.""" + session.install("zest.releaser[recommended]") + session.install("zestreleaser.towncrier") + session.run("fullrelease") + + +@nox.session +def publish_testpypi(session): + """Publish wheelhouse/* to TestPyPI.""" + session.run("twine", "check", "wheelhouse/*") + session.run( + "twine", + "upload", + "--skip-existing", + "--repository-url", + "https://test.pypi.org/legacy/", + "wheelhouse/*.tar.gz", + ) + + +@nox.session +def publish_pypi(session): + """Publish wheelhouse/* to PyPI.""" + session.run("twine", "check", "wheelhouse/*") + session.run( + "twine", + "upload", + "--skip-existing", + "wheelhouse/*.tar.gz", + ) + + +@nox.session(python=False) +def clean(session): + """Remove all .venv's, build files and caches in the directory.""" + PROJECT = "sequence" + ROOT = pathlib.Path(__file__).parent + + shutil.rmtree("build", ignore_errors=True) + shutil.rmtree("wheelhouse", ignore_errors=True) + shutil.rmtree(f"{PROJECT}.egg-info", ignore_errors=True) + shutil.rmtree(".pytest_cache", ignore_errors=True) + shutil.rmtree(".venv", ignore_errors=True) + for p in chain(ROOT.rglob("*.py[co]"), ROOT.rglob("__pycache__")): + if p.is_dir(): + p.rmdir() + else: + p.unlink() diff --git a/pyproject.toml b/pyproject.toml index 1e3d9e7..8309ea9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -48,9 +48,11 @@ changelog = "https://github.com/sequence-dev/sequence/blob/develop/CHANGES.rst" [project.optional-dependencies] dev = [ "black", + "coverage", "flake8", "isort", "nbmake", + "nox", "pre-commit", "pytest", "pytest-cov", @@ -59,16 +61,7 @@ dev = [ "towncrier", ] doc = [ - "pandoc", - "nbformat", - "jupyter_client", - "ipython", "sphinx", - "sphinx_rtd_theme", - "tornado", - "entrypoints", - "nbsphinx>=0.2.12", - "sphinxcontrib_github_alt", "pygments>=2.4", "sphinx-inline-tabs", "furo",