From 9ef1456bb92989c679626cafe4e22a24d43c6aeb Mon Sep 17 00:00:00 2001 From: holgern Date: Tue, 11 Feb 2020 21:09:25 +0100 Subject: [PATCH] Add conftest and doctest --- .travis.yml | 3 +- Makefile | 67 ++++++++++++++++ build_tools/travis/after_success.sh | 19 +++++ build_tools/travis/test_docs.sh | 6 ++ build_tools/travis/test_script.sh | 51 ++++++++++++ conftest.py | 83 +++++++++++++++++++ doc/Makefile | 118 ++++++++++++++++++++++++---- 7 files changed, 331 insertions(+), 16 deletions(-) create mode 100644 Makefile create mode 100644 build_tools/travis/after_success.sh create mode 100644 build_tools/travis/test_docs.sh create mode 100644 build_tools/travis/test_script.sh create mode 100644 conftest.py diff --git a/.travis.yml b/.travis.yml index 8f690c549..ad11b2b61 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,7 +9,7 @@ cache: env: global: # Directory where tests are run from - - TEST_DIR=/tmp/sklearn + - TEST_DIR=/tmp/skopt - OMP_NUM_THREADS=4 - OPENBLAS_NUM_THREADS=4 @@ -57,6 +57,7 @@ script: then pytest --cov=skopt --durations=10; else pytest --durations=10; fi +- bash build_tools/travis/test_docs.sh after_success: - if [ ${COVERAGE} == "true" ]; then diff --git a/Makefile b/Makefile new file mode 100644 index 000000000..13d6b3799 --- /dev/null +++ b/Makefile @@ -0,0 +1,67 @@ +# simple makefile to simplify repetitive build env management tasks under posix + +# caution: testing won't work on windows, see README + +PYTHON ?= python +CYTHON ?= cython +PYTEST ?= pytest +CTAGS ?= ctags + +# skip doctests on 32bit python +BITS := $(shell python -c 'import struct; print(8 * struct.calcsize("P"))') + +all: clean inplace test + +clean-ctags: + rm -f tags + +clean: clean-ctags + $(PYTHON) setup.py clean + rm -rf dist + # TODO: Remove in when all modules are removed. + $(PYTHON) sklearn/_build_utils/deprecated_modules.py + +in: inplace # just a shortcut +inplace: + $(PYTHON) setup.py build_ext -i + +test-code: in + $(PYTEST) --showlocals -v skopt --durations=20 +test-sphinxext: + $(PYTEST) --showlocals -v doc/sphinxext/ +test-doc: +ifeq ($(BITS),64) + $(PYTEST) $(shell find doc -name '*.rst' | sort) +endif +test-code-parallel: in + $(PYTEST) -n auto --showlocals -v skopt --durations=20 + +test-coverage: + rm -rf coverage .coverage + $(PYTEST) skopt --showlocals -v --cov=sklearn --cov-report=html:coverage +test-coverage-parallel: + rm -rf coverage .coverage .coverage.* + $(PYTEST) skopt -n auto --showlocals -v --cov=sklearn --cov-report=html:coverage + +test: test-code test-sphinxext test-doc + +trailing-spaces: + find skopt -name "*.py" -exec perl -pi -e 's/[ \t]*$$//' {} \; + +ctags: + # make tags for symbol based navigation in emacs and vim + # Install with: sudo apt-get install exuberant-ctags + $(CTAGS) --python-kinds=-i -R skopt + +doc: inplace + $(MAKE) -C doc html + +doc-noplot: inplace + $(MAKE) -C doc html-noplot + +code-analysis: + flake8 sklearn | grep -v __init__ | grep -v external + pylint -E -i y skopt/ -d E1103,E0611,E1101 + +flake8-diff: + ./build_tools/circle/linting.sh diff --git a/build_tools/travis/after_success.sh b/build_tools/travis/after_success.sh new file mode 100644 index 000000000..494f86b6e --- /dev/null +++ b/build_tools/travis/after_success.sh @@ -0,0 +1,19 @@ +#!/bin/bash +# This script is meant to be called by the "after_success" step defined in +# .travis.yml. See https://docs.travis-ci.com/ for more details. + +# License: 3-clause BSD + +set -e + +if [[ "$COVERAGE" == "true" ]]; then + # Need to run codecov from a git checkout, so we copy .coverage + # from TEST_DIR where pytest has been run + cp $TEST_DIR/.coverage $TRAVIS_BUILD_DIR + + # Ignore codecov failures as the codecov server is not + # very reliable but we don't want travis to report a failure + # in the github UI just because the coverage report failed to + # be published. + codecov --root $TRAVIS_BUILD_DIR || echo "codecov upload failed" +fi \ No newline at end of file diff --git a/build_tools/travis/test_docs.sh b/build_tools/travis/test_docs.sh new file mode 100644 index 000000000..d43b480fa --- /dev/null +++ b/build_tools/travis/test_docs.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +set -e +set -x + +make test-doc diff --git a/build_tools/travis/test_script.sh b/build_tools/travis/test_script.sh new file mode 100644 index 000000000..a14e50706 --- /dev/null +++ b/build_tools/travis/test_script.sh @@ -0,0 +1,51 @@ +#!/bin/bash +# This script is meant to be called by the "script" step defined in +# .travis.yml. See https://docs.travis-ci.com/ for more details. +# The behavior of the script is controlled by environment variabled defined +# in the .travis.yml in the top level folder of the project. + +# License: 3-clause BSD + +set -e + +python --version +python -c "import numpy; print('numpy %s' % numpy.__version__)" +python -c "import scipy; print('scipy %s' % scipy.__version__)" +python -c "\ +try: + import sklearn + print('sklearn %s' % sklearn.__version__) +except ImportError: + pass +" +python -c "import multiprocessing as mp; print('%d CPUs' % mp.cpu_count())" + +run_tests() { + TEST_CMD="pytest --showlocals --durations=20 --pyargs" + + # Get into a temp directory to run test from the installed scikit-learn and + # check if we do not leave artifacts + mkdir -p $TEST_DIR + # We need the setup.cfg for the pytest settings + cp setup.cfg $TEST_DIR + cd $TEST_DIR + + # Skip tests that require large downloads over the network to save bandwidth + # usage as travis workers are stateless and therefore traditional local + # disk caching does not work. + export SKOPT_SKIP_NETWORK_TESTS=1 + + if [[ "$COVERAGE" == "true" ]]; then + TEST_CMD="$TEST_CMD --cov sklearn" + fi + + if [[ -n "$CHECK_WARNINGS" ]]; then + TEST_CMD="$TEST_CMD -Werror::DeprecationWarning -Werror::FutureWarning" + fi + + set -x # print executed commands to the terminal + + $TEST_CMD skopt +} + +run_tests \ No newline at end of file diff --git a/conftest.py b/conftest.py new file mode 100644 index 000000000..e2149e22e --- /dev/null +++ b/conftest.py @@ -0,0 +1,83 @@ +# Even if empty this file is useful so that when running from the root folder +# ./sklearn is added to sys.path by pytest. See +# https://docs.pytest.org/en/latest/pythonpath.html for more details. For +# example, this allows to build extensions in place and run pytest +# doc/modules/clustering.rst and use sklearn from the local folder rather than +# the one from site-packages. + +import platform +import sys +from distutils.version import LooseVersion +import os + +import pytest +from _pytest.doctest import DoctestItem +from sklearn.utils import _IS_32BIT + + +PYTEST_MIN_VERSION = '3.3.0' + +if LooseVersion(pytest.__version__) < PYTEST_MIN_VERSION: + raise ImportError('Your version of pytest is too old, you should have ' + 'at least pytest >= {} installed.' + .format(PYTEST_MIN_VERSION)) + + +def pytest_addoption(parser): + parser.addoption("--skip-network", action="store_true", default=False, + help="skip network tests") + + +def pytest_collection_modifyitems(config, items): + # FeatureHasher is not compatible with PyPy + if platform.python_implementation() == 'PyPy': + skip_marker = pytest.mark.skip( + reason='FeatureHasher is not compatible with PyPy') + for item in items: + if item.name.endswith(('_hash.FeatureHasher', + 'text.HashingVectorizer')): + item.add_marker(skip_marker) + + # Skip tests which require internet if the flag is provided + if config.getoption("--skip-network"): + skip_network = pytest.mark.skip( + reason="test requires internet connectivity") + for item in items: + if "network" in item.keywords: + item.add_marker(skip_network) + + # numpy changed the str/repr formatting of numpy arrays in 1.14. We want to + # run doctests only for numpy >= 1.14. + skip_doctests = False + try: + import numpy as np + if LooseVersion(np.__version__) < LooseVersion('1.14'): + reason = 'doctests are only run for numpy >= 1.14' + skip_doctests = True + elif _IS_32BIT: + reason = ('doctest are only run when the default numpy int is ' + '64 bits.') + skip_doctests = True + elif sys.platform.startswith("win32"): + reason = ("doctests are not run for Windows because numpy arrays " + "repr is inconsistent across platforms.") + skip_doctests = True + except ImportError: + pass + + if skip_doctests: + skip_marker = pytest.mark.skip(reason=reason) + + for item in items: + if isinstance(item, DoctestItem): + item.add_marker(skip_marker) + + +def pytest_configure(config): + import sys + sys._is_pytest_session = True + + +def pytest_unconfigure(config): + import sys + del sys._is_pytest_session diff --git a/doc/Makefile b/doc/Makefile index a0e8bf588..05ba06142 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -1,22 +1,110 @@ -# Minimal makefile for Sphinx documentation +# Makefile for Sphinx documentation # # You can set these variables from the command line. -SPHINXOPTS = -W --keep-going -SPHINXBUILD = sphinx-build -SPHINXPROJ = scikit-optimize -SOURCEDIR = source -BUILDDIR = build +SPHINXOPTS = -j auto +SPHINXBUILD ?= sphinx-build +PAPER = +BUILDDIR = _build +ifneq ($(EXAMPLES_PATTERN),) + EXAMPLES_PATTERN_OPTS := -D sphinx_gallery_conf.filename_pattern="$(EXAMPLES_PATTERN)" +endif + +# Internal variables. +PAPEROPT_a4 = -D latex_paper_size=a4 +PAPEROPT_letter = -D latex_paper_size=letter +ALLSPHINXOPTS = -T -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS)\ + $(EXAMPLES_PATTERN_OPTS) . + + +.PHONY: help clean html dirhtml pickle json latex latexpdf changes linkcheck doctest optipng + +all: html-noplot -# Put it first so that "make" without argument is like "make help". help: - @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + @echo "Please use \`make ' where is one of" + @echo " html to make standalone HTML files" + @echo " dirhtml to make HTML files named index.html in directories" + @echo " pickle to make pickle files" + @echo " json to make JSON files" + @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" + @echo " latexpdf to make LaTeX files and run them through pdflatex" + @echo " changes to make an overview of all changed/added/deprecated items" + @echo " linkcheck to check all external links for integrity" + @echo " doctest to run all doctests embedded in the documentation (if enabled)" + +clean: + -rm -rf $(BUILDDIR)/* + -rm -rf auto_examples/ + -rm -rf generated/* + -rm -rf modules/generated/ + +html: + # These two lines make the build a bit more lengthy, and the + # the embedding of images more robust + rm -rf $(BUILDDIR)/html/_images + #rm -rf _build/doctrees/ + $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/html" + +html-noplot: + $(SPHINXBUILD) -D plot_gallery=0 -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." + +dirhtml: + $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." + +pickle: + $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle + @echo + @echo "Build finished; now you can process the pickle files." + +json: + $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json + @echo + @echo "Build finished; now you can process the JSON files." + +latex: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo + @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." + @echo "Run \`make' in that directory to run these through (pdf)latex" \ + "(use \`make latexpdf' here to do that automatically)." + +latexpdf: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through pdflatex..." + make -C $(BUILDDIR)/latex all-pdf + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +changes: + $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes + @echo + @echo "The overview file is in $(BUILDDIR)/changes." + +linkcheck: + $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck + @echo + @echo "Link check complete; look for any errors in the above output " \ + "or in $(BUILDDIR)/linkcheck/output.txt." + +doctest: + $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest + @echo "Testing of doctests in the sources finished, look at the " \ + "results in $(BUILDDIR)/doctest/output.txt." + +# download-data: +# python -c "from sklearn.datasets._lfw import _check_fetch_lfw; _check_fetch_lfw()" -.PHONY: help Makefile +# Optimize PNG files. Needs OptiPNG. Change the -P argument to the number of +# cores you have available, so -P 64 if you have a real computer ;) +optipng: + find _build auto_examples */generated -name '*.png' -print0 \ + | xargs -0 -n 1 -P 4 optipng -o10 -# Catch-all target: route all unknown targets to Sphinx using the new -# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). -%: Makefile - mkdir ./source/notebooks - cp -r ../examples/* ./source/notebooks - @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) +dist: html latexpdf + cp _build/latex/user_guide.pdf _build/html/_downloads/scikit-optimize-docs.pdf