Skip to content

Commit

Permalink
Adopt bindep functionality from tox-bindep plugin (#93)
Browse files Browse the repository at this point in the history
  • Loading branch information
ssbarnea authored Aug 8, 2024
1 parent 9276078 commit 6866b3b
Show file tree
Hide file tree
Showing 15 changed files with 141 additions and 24 deletions.
20 changes: 16 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
# tox-extra

This [tox plugin](https://github.com/topics/tox-plugin) adds few extra checks
This [tox plugin](https://github.com/topics/tox-plugin) adds a few extra checks
like:

- ensure exit code 1 if git reports dirty or untracked files _after_ the run
- [tox-extra](#tox-extra)
- [Checks Git Dirty Status](#checks-git-dirty-status)
- [Checks system dependencies using bindep](#checks-system-dependencies-using-bindep)

## Checks Git Dirty Status

It ensures exit code 1 if git reports dirty or untracked files _after_ the run.

Usage example:

```
```shell
$ tox -e py
...
ERROR: Git reported dirty status. Git should never report dirty status at the end of testing, regardless if status is passed, failed or aborted.
Expand All @@ -23,11 +29,17 @@ __________________________________________ summary _____________________________
ERROR: py: failed
```
The goal of this plugin is to help developers be aware about files modified by tests
The goal of this plugin is to help developers be aware of files modified by tests
or untracked files before they commit the code. This plugin also does not take into
consideration the global `.gitignore`, something that can make git miss reporting
some untracked files, the goal being to assure that when a new developer clones and
runs the tests they do not endup with an unexpected git status.
If you have any cases where you expect to have git report dirty, please
add `--allow-dirty` to the command call to disable this check.
## Checks system dependencies using bindep
If a `bindep.txt` config file is found, tox will run `bindep test` to
check if dependencies, including test ones, are present. There is no need to
install bindep your self.
2 changes: 2 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ classifiers = [
]
keywords = ["git", "tox", "tox-plugin"]
dependencies = [
"bindep>2.8.1",
"gitpython",
"packaging",
"tox",
Expand Down Expand Up @@ -66,6 +67,7 @@ omit = [".tox/*/lib/python*/site-packages/*"]
include = ["src/*"]
fail_under = 100.0
skip_covered = true
show_missing = true

[tool.coverage.paths]
source = ["src"]
Expand Down
50 changes: 50 additions & 0 deletions src/tox_extra/bindep.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
"""Bindep check feature implementations."""

from __future__ import print_function

import os
import subprocess
import sys


def check_bindep() -> None:
"""Check bindeps requirements or exit."""
if os.path.isfile("bindep.txt"):
# as 'bindep --profiles' does not show user defined profiles like 'test'
# it makes no sense to list them.
cmd = [sys.executable, "-m", "bindep", "-b", "test"]
# # determine profiles
# result = subprocess.run(
# [sys.executable, "-m", "bindep", "--profiles"],
# check=False,
# universal_newlines=True,
# stdout=subprocess.PIPE,
# )
# if result.returncode:
# print("Bindep failed to list profiles: %s", result.stdout)
# sys.exit(result.returncode)
# lines = result.stdout.splitlines()
# try:
# profiles = lines[lines.index("Configuration profiles:") + 1 :]
# if "test" in profiles:
# cmd.append("test")
# except ValueError:
# pass

result = subprocess.run(
cmd,
check=False,
universal_newlines=True,
stderr=subprocess.PIPE,
stdout=subprocess.PIPE,
)
if result.returncode:
print(
f"Running '{' '.join(cmd)}' returned {result.returncode}, "
"likely missing system dependencies."
)
if result.stdout:
print(result.stdout)
if result.stderr:
print(result.stderr, file=sys.stderr)
sys.exit(result.returncode)
11 changes: 10 additions & 1 deletion src/tox_extra/hooks.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,16 @@
import os
import sys
from argparse import ArgumentParser
from typing import List
from typing import Any, List

import git
from tox.execute import Outcome
from tox.plugin import impl
from tox.tox_env.api import ToxEnv
from tox.tox_env.errors import Fail

from tox_extra.bindep import check_bindep

MSG_GIT_DIRTY = (
"Git reported dirty status. "
"Git should never report dirty status at the end of "
Expand Down Expand Up @@ -49,6 +51,13 @@ def tox_add_option(parser: ArgumentParser) -> None:
)


@impl
# pylint: disable=unused-argument
def tox_on_install(tox_env: ToxEnv, arguments: Any, section: str, of_type: str) -> None:
"""Runs just before installing package."""
check_bindep()


@impl
# pylint: disable=unused-argument
def tox_after_run_commands(
Expand Down
18 changes: 18 additions & 0 deletions tests/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
"""Tests."""

import functools
import os


def preserve_cwd(function):
"""Decorator for restoring cwd."""

@functools.wraps(function)
def decorator(*args, **kwargs):
cwd = os.getcwd()
try:
return function(*args, **kwargs)
finally:
os.chdir(cwd)

return decorator
1 change: 1 addition & 0 deletions tests/fixtures/bindep_0/bindep.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
this-package-is-missing
2 changes: 2 additions & 0 deletions tests/fixtures/bindep_0/tox.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[tox]
skipsdist = true
1 change: 1 addition & 0 deletions tests/fixtures/bindep_1/bindep.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
bash [test]
2 changes: 2 additions & 0 deletions tests/fixtures/bindep_1/tox.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[tox]
skipsdist = true
1 change: 1 addition & 0 deletions tests/fixtures/bindep_2/bindep.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
GARBAGE DATA
2 changes: 2 additions & 0 deletions tests/fixtures/bindep_2/tox.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[tox]
skipsdist = true
Empty file.
26 changes: 26 additions & 0 deletions tests/test_bindep.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
"""Unit tests."""

import os
from runpy import run_module

import pytest

from . import preserve_cwd


@preserve_cwd
@pytest.mark.parametrize(
("folder", "expected_rc"),
(
pytest.param("tests/fixtures/bindep_0", 1, id="0"),
pytest.param("tests/fixtures/bindep_1", 0, id="1"),
pytest.param("tests/fixtures/bindep_2", 1, id="2"),
),
)
def test_bindep(folder: str, expected_rc: int) -> None:
"""Tests that running tox with a bindep file that is missing deps fails."""
os.chdir(folder)
with pytest.raises(SystemExit) as exc:
run_module("tox", run_name="__main__")
assert exc.type == SystemExit
assert exc.value.code == expected_rc
17 changes: 2 additions & 15 deletions tests/test_plugin.py
Original file line number Diff line number Diff line change
@@ -1,33 +1,20 @@
"""Hosts tests for the plugin."""

import functools
import os
from pathlib import Path
from runpy import run_module
from subprocess import PIPE, check_output, run

import pytest

from . import preserve_cwd

TOX_SAMPLE = """
[tox]
skipsdist = true
"""


def preserve_cwd(function):
"""Decorator for restoring cwd."""

@functools.wraps(function)
def decorator(*args, **kwargs):
cwd = os.getcwd()
try:
return function(*args, **kwargs)
finally:
os.chdir(cwd)

return decorator


@preserve_cwd
def test_fail_if_dirty(tmp_path, monkeypatch: pytest.MonkeyPatch) -> None:
"""Validated that it fails when drity."""
Expand Down
12 changes: 8 additions & 4 deletions tox.ini
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
[tox]
minversion = 4.0.2
skipsdist = true
ignore_path = tests
envlist =
lint
Expand All @@ -10,9 +9,12 @@ envlist =

[testenv]
usedevelop = true
description =
Run tests
devel: using devel branch of tox (unreleased)
skip_install = false
extras = test
deps =
-e ".[test]"
devel: tox @ git+https://github.com/tox-dev/tox.git@main
passenv =
SSH_AUTH_SOCK
Expand All @@ -25,14 +27,16 @@ setenv =
GIT_COMMITTER_EMAIL[email protected]
PIP_DISABLE_PIP_VERSION_CHECK = 1
commands =
coverage run -m pytest {posargs}
sh -c "coverage combine -q --data-file={env:COVERAGE_FILE} {env:COVERAGE_FILE}.* && coverage xml && coverage report"
python -m coverage run -m pytest {posargs}
sh -c "python -m coverage combine -q --data-file={env:COVERAGE_FILE} {env:COVERAGE_FILE}.* && coverage report && coverage xml"
allowlist_externals =
sh
rm
package = editable

[testenv:lint]
skip_install = true
description = Run linting
deps =
pre_commit
commands =
Expand Down

0 comments on commit 6866b3b

Please sign in to comment.