tox: add tox

`tox` is a standard testing tool for Python projects, this allows you to
test locally with all your installed Python version with the following
command:

`tox -m test -p all`

To run the tests in parallel for all supported Python versions.

To run linters or type analysis:

```
tox -m lint -p all
tox -m type -p all
```

This commit *also* disables the `import-error` warning from `pylint`,
not all Python versions have the system-installed Python libraries
available and they can't be fetched from PyPI.

Some linters have been added and the general order linters run in has
been changed. This allows for quicker test failure when running
`tox -m lint`. As a consequence the `test_pylint` test has been removed
as it's role can now be fulfilled by `tox`.

Other assorted linter fixes due to newer versions:
- use a str.join method (`consider-using-join`)
- fix various (newer) mypy and pylint issues
- comments starting with `#` and no space due to `autopep8`

This also changes our CI to use the new `tox` setup and on top of that
pins the versions of linters used. This might move into separate
requirements.txt files later on to allow for easier updating of those
dependencies.
This commit is contained in:
Simon de Vlieger 2023-03-20 11:54:35 +01:00
parent a7b75bea3b
commit d60690ce46
23 changed files with 193 additions and 184 deletions

View file

@ -1,110 +0,0 @@
#
# Run `pylint` on all python sources.
#
import os
import subprocess
import pytest
from .. import test
@pytest.fixture(name="source_files")
def discover_source_files():
# Evaluate whether `path` is a python file. This assumes that the file is
# opened by the caller, anyway, hence it might invoke `file` to detect the
# file type if in doubt.
def is_python_script(path):
if path.endswith(".py"):
return True
mime_valid = [
"text/x-python",
"text/x-script.python",
]
mime_file = subprocess.check_output(
[
"file",
"-bi",
"--",
path,
],
encoding="utf-8",
)
return any(mime_file.startswith(v) for v in mime_valid)
# Enumerate all repository files. This will invoke `git ls-tree` to list
# all files. This also requires a temporary change of directory, since git
# operates on the current directory and does not allow path arguments.
def list_files(path):
cwd = os.getcwd()
os.chdir(path)
files = subprocess.check_output(
[
"git",
"ls-tree",
"-rz",
"--full-tree",
"--name-only",
"HEAD",
],
encoding="utf-8",
)
os.chdir(cwd)
files = files.split('\x00')
return (os.path.join(path, f) for f in files)
if not test.TestBase.have_test_checkout():
pytest.skip("no test-checkout access")
files = list_files(test.TestBase.locate_test_checkout())
files = filter(is_python_script, files)
return list(files)
def test_pylint(source_files):
#
# Run `pylint` on all python sources. We simply use `find` to locate
# all `*.py` files, and then manually select the reverse-domain named
# modules we have.
#
r = subprocess.run(["pylint"] + source_files, check=False)
if r.returncode != 0:
pytest.fail("pylint issues detected")
@pytest.mark.skipif(not test.TestBase.have_mypy(), reason="mypy not available")
def test_mypy():
#
# Run `mypy` on osbuild sources.
#
r = subprocess.run(["mypy", "osbuild/"], check=False)
if r.returncode != 0:
pytest.fail("mypy issues detected")
@pytest.mark.skipif(not test.TestBase.have_isort(), reason="isort not available")
def test_isort(source_files):
#
# Run `isort` on all python sources. We simply use `find` to locate
# all `*.py` files, and then manually select the reverse-domain named
# modules we have.
#
r = subprocess.run(["isort", "--check", "--diff"] + source_files, check=False)
if r.returncode != 0:
pytest.fail("isort issues detected")
@pytest.mark.skipif(not test.TestBase.have_autopep8(), reason="autopep8 not available")
def test_autopep8(source_files):
r = subprocess.run(["autopep8-3", "--diff", "--exit-code"] + source_files, check=False)
if r.returncode != 0:
pytest.fail("autopep8 has detected changes (see diff)")