diff --git a/.coverage_dir/.empty b/.coverage_dir/.empty new file mode 100644 index 000000000..e69de29bb diff --git a/.coveragerc b/.coveragerc index 5fa231e3a..7eca787ed 100644 --- a/.coveragerc +++ b/.coveragerc @@ -1,2 +1,3 @@ [run] omit=*/tests/* +parallel=true diff --git a/.gitignore b/.gitignore index 8fe18592c..a078e6b0d 100644 --- a/.gitignore +++ b/.gitignore @@ -26,6 +26,8 @@ MANIFEST *~ .pytest_cache .coverage +.coverage_dir +coverage.xml # Rever rever/ diff --git a/.travis.yml b/.travis.yml index ee92f332a..a01e36d03 100644 --- a/.travis.yml +++ b/.travis.yml @@ -36,24 +36,29 @@ matrix: - python: 3.6 env: - TOXENV=py36-test-deps + H5PY_ENFORCE_COVERAGE=yes - python: 3.6 env: - TOXENV=py36-test-deps HDF5_VERSION=1.10.3 HDF5_DIR=$HDF5_CACHE_DIR/$HDF5_VERSION + H5PY_ENFORCE_COVERAGE=yes - python: 3.6 env: - TOXENV=py36-test-deps-pre + H5PY_ENFORCE_COVERAGE=yes - python: 3.6 env: - TOXENV=py36-test-mindeps + H5PY_ENFORCE_COVERAGE=yes - python: 3.6 env: - TOXENV=py36-test-deps TOX_TESTENV_PASSENV=LANG LC_ALL LANG=C LC_ALL=C + H5PY_ENFORCE_COVERAGE=yes # Python 3.7 - python: 3.7 @@ -61,18 +66,21 @@ matrix: - TOXENV=py37-test-deps HDF5_VERSION=1.10.4 HDF5_DIR=$HDF5_CACHE_DIR/$HDF5_VERSION + H5PY_ENFORCE_COVERAGE=yes - python: 3.7 env: - TOXENV=py37-test-deps HDF5_VERSION=1.10.5 HDF5_DIR=$HDF5_CACHE_DIR/$HDF5_VERSION + H5PY_ENFORCE_COVERAGE=yes - python: 3.7 env: - TOXENV=py37-test-deps HDF5_VERSION=1.10.5 HDF5_DIR=$HDF5_CACHE_DIR/$HDF5_VERSION + H5PY_ENFORCE_COVERAGE=yes os: linux-ppc64le # MPI tests @@ -82,6 +90,7 @@ matrix: - TOXENV=py36-test-mindeps-mpi4py - CC="mpicc" - HDF5_MPI="ON" + - H5PY_ENFORCE_COVERAGE=yes addons: apt: packages: @@ -93,12 +102,14 @@ matrix: - python: 3.7 env: - TOXENV=py37-test-mindeps-tables + H5PY_ENFORCE_COVERAGE=yes - python: 3.7 env: - TOXENV=apidocs - HDF5_VERSION=1.10.5 - HDF5_DIR=$HDF5_CACHE_DIR/$HDF5_VERSION + - H5PY_ENFORCE_COVERAGE=yes script: - tox - if [[ -z "$TRAVIS_TAG" ]]; then @@ -115,10 +126,12 @@ matrix: - TOXENV=nightly HDF5_VERSION=1.10.5 HDF5_DIR=$HDF5_CACHE_DIR/$HDF5_VERSION + H5PY_ENFORCE_COVERAGE=yes - python: pypy3 env: - TOXENV=pypy3-test-deps + - H5PY_ENFORCE_COVERAGE=yes allow_failures: - python: pypy3 - python: 'nightly' @@ -135,4 +148,4 @@ script: - tox after_success: - - codecov + - python ci/upload_coverage.py diff --git a/MANIFEST.in b/MANIFEST.in index 39084c756..59d1c9518 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -36,6 +36,8 @@ exclude *.yaml recursive-exclude * __pycache__ recursive-exclude * *.py[co] exclude .coveragerc +exclude .coverage_dir +recursive-exclude .coverage_dir * exclude .mailmap exclude github_deploy_key_h5py_h5py.enc diff --git a/appveyor.yml b/appveyor.yml index 4538c5980..ede4702c5 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -2,6 +2,7 @@ environment: HDF5_VERSION: "1.8.17" TOX_TESTENV_PASSENV: "HDF5_DIR" + H5PY_ENFORCE_COVERAGE: "YES" matrix: @@ -94,4 +95,4 @@ cache: - "C:\\hdf5" on_success: - - "py -3.6 -m codecov" + - "py -3.6 ci\\upload_coverage.py" diff --git a/azure-pipelines.yml b/azure-pipelines.yml index cc94405a4..ba8fb0931 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -23,25 +23,30 @@ jobs: py36: python.version: '3.6' TOXENV: py36-test-deps,py36-test-mindeps,py36-test-deps-pre,py36-test-mindeps-tables + H5PY_ENFORCE_COVERAGE: yes py37: python.version: '3.7' TOXENV: py37-test-deps,py37-test-mindeps,py37-test-deps-pre,py37-test-deps-tables + H5PY_ENFORCE_COVERAGE: yes # test against newer HDF5 py36-deps-hdf51103: python.version: '3.6' TOXENV: py36-test-deps HDF5_VERSION: 1.10.3 HDF5_DIR: $(HDF5_CACHE_DIR)/$(HDF5_VERSION) + H5PY_ENFORCE_COVERAGE: yes py37-deps-hdf51104: python.version: '3.7' TOXENV: py37-test-deps HDF5_VERSION: 1.10.4 HDF5_DIR: $(HDF5_CACHE_DIR)/$(HDF5_VERSION) + H5PY_ENFORCE_COVERAGE: yes py37-deps-hdf51105: python.version: '3.7' TOXENV: py37-test-deps HDF5_VERSION: 1.10.5 HDF5_DIR: $(HDF5_CACHE_DIR)/$(HDF5_VERSION) + H5PY_ENFORCE_COVERAGE: yes # do mpi tests # py36-deps-hdf51105-mpi: # python.version: '3.6' @@ -80,12 +85,14 @@ jobs: HDF5_VERSION: 1.10.1 HDF5_DIR: $(HDF5_CACHE_DIR)/$(HDF5_VERSION) HDF5_VSVERSION: "15-64" + H5PY_ENFORCE_COVERAGE: yes py37: python.version: '3.7' TOXENV: py37-test-deps,py37-test-mindeps,py37-test-deps-pre HDF5_VERSION: 1.10.1 HDF5_DIR: $(HDF5_CACHE_DIR)/$(HDF5_VERSION) HDF5_VSVERSION: "15-64" + H5PY_ENFORCE_COVERAGE: yes maxParallel: 4 steps: @@ -106,9 +113,11 @@ jobs: py36: python.version: '3.6' TOXENV: py36-test-deps,py36-test-mindeps,py36-test-deps-pre + H5PY_ENFORCE_COVERAGE: yes py37: python.version: '3.7' TOXENV: py37-test-deps,py37-test-mindeps,py37-test-deps-pre + H5PY_ENFORCE_COVERAGE: yes # test against newer HDF5 # py36-deps-hdf51103: # python.version: '3.6' diff --git a/ci/azure-pipelines-steps.yml b/ci/azure-pipelines-steps.yml index 1e7057a2a..d0573ff85 100644 --- a/ci/azure-pipelines-steps.yml +++ b/ci/azure-pipelines-steps.yml @@ -71,6 +71,9 @@ steps: tox displayName: 'tox' -- script: | - codecov -t 813fb6da-087d-4b36-a185-5a530cab3455 +- task: PythonScript@0 + inputs: + scriptSource: 'filePath' + scriptPath: 'ci/upload_coverage.py' + arguments: --codecov-token 813fb6da-087d-4b36-a185-5a530cab3455 displayName: 'codecov' diff --git a/ci/upload_coverage.py b/ci/upload_coverage.py new file mode 100644 index 000000000..106a6d045 --- /dev/null +++ b/ci/upload_coverage.py @@ -0,0 +1,81 @@ +""" +Helper script to combine coverage (as codecov seems to have problems...). +Written in python to be cross-platform +""" + +import argparse +from os import chdir, listdir, environ +from pathlib import Path +import platform +from pprint import pprint +import shlex +from subprocess import run, PIPE +import sys + +THIS_FILE = Path(__file__) +GIT_MAIN_DIR = THIS_FILE.parent.parent.resolve() +COVERAGE_DIR = GIT_MAIN_DIR.joinpath('.coverage_dir') +PYVERSION = '{}.{}'.format(sys.version_info[0], sys.version_info[1]) + + +def msg(*args): + print('ERR:', *args, file=sys.stderr) + + +def pmsg(*args): + pprint(*args, stream=sys.stderr) + + +def run_with_python(args, **kwargs): + if platform.system() == 'Windows': + exe = ['py', '-' + PYVERSION, '-m'] + else: + exe = [] + cmd = exe + args + msg("Running:", *cmd) + res = run(cmd, check=True, stdout=PIPE, stderr=PIPE, **kwargs) + msg("STDOUT:") + sys.stdout.buffer.write(res.stdout) + msg("STDERR:") + sys.stderr.buffer.write(res.stdout) + return res + + +def send_coverage(*, workdir, coverage_files, codecov_token): + chdir(workdir) + run_with_python(['coverage', 'combine'] + coverage_files) + msg(f"Combined coverage, listing {GIT_MAIN_DIR}") + pmsg(sorted(listdir(GIT_MAIN_DIR))) + run_with_python(['coverage', 'xml', '--ignore-errors']) + msg(f"Created coverage xml, listing {GIT_MAIN_DIR}") + pmsg(sorted(listdir(GIT_MAIN_DIR))) + codecov_args = ["--required"] + if codecov_token is not None: + codecov_args.extend(['-t', codecov_token]) + codecov_args.extend(['--file', 'coverage.xml']) + run_with_python(['codecov'] + codecov_args) + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument("--codecov-token", default=None) + args = parser.parse_args() + msg(f"Working in {GIT_MAIN_DIR}, listing coverage dir {COVERAGE_DIR}") + pmsg(sorted(listdir(COVERAGE_DIR))) + coverage_files = [str(f) for f in COVERAGE_DIR.glob('coverage-*')] + if coverage_files: + send_coverage( + workdir=GIT_MAIN_DIR, + coverage_files=coverage_files, + codecov_token=args.codecov_token, + ) + else: + msg("No coverage files found") + if environ.get("H5PY_ENFORCE_COVERAGE") is not None: + raise RuntimeError( + "Coverage required, no coverage found, failing..." + ) + + +if __name__ == '__main__': + main() diff --git a/tox.ini b/tox.ini index 1b019ffaf..6e0422b3c 100644 --- a/tox.ini +++ b/tox.ini @@ -35,7 +35,7 @@ changedir = passenv = HDF5_DIR setenv = - COVERAGE_FILE={toxinidir}/.coverage + COVERAGE_FILE={toxinidir}/.coverage_dir/coverage-{envname} # needed otherwise coverage cannot find the file when reporting pip_pre =