diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index f8b9e1d..fe484c7 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -44,6 +44,13 @@ jobs: - name: Run run: tox + - name: Upload coverage + uses: actions/upload-artifact@v4 + with: + name: coverage-${{ matrix.python }} + path: .coverage.* + if-no-files-found: ignore + ruff: name: "Ruff ${{ matrix.python }} on ${{ matrix.platform }}" runs-on: "${{ matrix.platform }}" @@ -75,3 +82,46 @@ jobs: - name: Run run: tox -e lint + + coverage: + name: Coverage report + runs-on: ubuntu-latest + needs: test + + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: 3.12 + cache: pip + cache-dependency-path: | + **/pyproject.toml + **/tox.ini + + - name: Download coverage data + uses: actions/download-artifact@v4 + with: + pattern: coverage-* + merge-multiple: true + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + python -m pip install coverage[toml] + + - name: Coverage report + run: | + coverage combine + coverage html + coverage report --format=markdown >> $GITHUB_STEP_SUMMARY + coverage report --fail-under=70 + + - name: Upload report + uses: actions/upload-artifact@v4 + with: + path: htmlcov + name: htmlcov diff --git a/pyproject.toml b/pyproject.toml index 254a3d6..fb1fe1a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -36,6 +36,7 @@ dependencies = [ [project.optional-dependencies] test = [ "pytest", + "coverage[toml]", ] [project.urls] @@ -44,6 +45,34 @@ Repository = "https://github.com/python-wheel-build/elfdeps" [project.scripts] elfdeps = "elfdeps.__main__:main" +[tool.coverage.run] +branch = true +parallel = true +relative_files = true +source = [ + "elfdeps", + "tests/", +] + +[tool.coverage.paths] +source = [ + "src/elfdeps", + ".tox/py*/**/site-packages/elfdeps", +] +tests =[ + "tests/", +] + +[tool.coverage.report] +show_missing = true +skip_covered = true +exclude_lines = [ + "pragma: no cover", + "@abc.abstractmethod", + "@typing.overload", + "if typing.TYPE_CHECKING", +] + [tool.setuptools_scm] # do not include +gREV local version, required for Test PyPI upload local_scheme = "no-local-version" diff --git a/src/elfdeps/__main__.py b/src/elfdeps/__main__.py index 42b0b78..408cd3d 100644 --- a/src/elfdeps/__main__.py +++ b/src/elfdeps/__main__.py @@ -9,8 +9,8 @@ from . import _archives, _elfdeps -ZIPEXT = frozenset({".zip", ".whl"}) -TAREXT = frozenset({".tar", ".tar.gz", ".tgz", ".tar.bz2", "tbz2", "tar.xz", "txz"}) +ZIPEXT = (".zip", ".whl") +TAREXT = (".tar", ".tar.gz", ".tgz", ".tar.bz2", ".tbz2", ".tar.xz", ".txz") parser = argparse.ArgumentParser("elfdeps") parser.add_argument("filename", type=pathlib.Path) @@ -89,9 +89,9 @@ def main(argv: list[str] | None = None) -> None: unique=args.unique, ) filename: pathlib.Path = args.filename - if filename.suffix in ZIPEXT: + if filename.name.endswith(ZIPEXT): infos = list(zip_requires(filename, settings=settings)) - elif filename.suffix in TAREXT: + elif filename.name.endswith(TAREXT): infos = list(tar_requires(filename, settings=settings)) else: infos = [_elfdeps.analyze_file(filename, settings=settings)] diff --git a/tests/test_main.py b/tests/test_main.py new file mode 100644 index 0000000..5e83e5a --- /dev/null +++ b/tests/test_main.py @@ -0,0 +1,33 @@ +import pathlib +import subprocess +import sys +import tarfile +import zipfile + + +def test_main_binary() -> None: + python = pathlib.Path(sys.executable).resolve() + out = subprocess.check_output(["elfdeps", python], text=True) + assert str(python) in out + + +def test_main_tarfile(tmp_path: pathlib.Path): + tname = tmp_path / "test.tar.gz" + python = pathlib.Path(sys.executable).resolve() + with tarfile.TarFile.open(tname, mode="w:gz") as tf: + # FIXME: remove '.so' suffix + tf.add(python, "python-binary.so") + tf.add(__file__, "test.py") + out = subprocess.check_output(["elfdeps", str(tname)], text=True) + assert "python-binary" in out + + +def test_main_zipfile(tmp_path: pathlib.Path) -> None: + zname = tmp_path / "test.zip" + python = pathlib.Path(sys.executable).resolve() + with zipfile.ZipFile(zname, mode="w") as zf: + # FIXME: remove '.so' suffix + zf.write(python, "python-binary.so") + zf.write(__file__, "test.py") + out = subprocess.check_output(["elfdeps", str(zname)], text=True) + assert "python-binary" in out diff --git a/tox.ini b/tox.ini index c832bc3..6295337 100644 --- a/tox.ini +++ b/tox.ini @@ -1,14 +1,29 @@ # SPDX-License-Identifier: Apache-2.0 [tox] -envlist=py3{10,11,12},lint +envlist=py3{10,11,12},lint,coverage-report [testenv] package = wheel wheel_build_env = pkg extras = test +set_env = + COVERAGE_PROCESS_START={toxinidir}/pyproject.toml +commands_pre = + py3{10,11,12}: {envpython} -c 'import pathlib; pathlib.Path("{env_site_packages_dir}/cov.pth").write_text("import coverage; coverage.process_startup()")' commands = - python -m pytest tests + coverage run -m pytest {posargs:tests} + +[testenv:coverage-report] +description = Report coverage over all test runs. +basepython = py312 +depends = py3{10,11,12} +deps = coverage[toml] +skip_install = true +parallel_show_output = true +commands = + coverage combine + coverage report [testenv:lint] basepython = python3