Skip to content

Commit

Permalink
Merge pull request #2469 from SnoopJ/contrib/tox
Browse files Browse the repository at this point in the history
Add optional tox configuration
  • Loading branch information
dgw authored Jul 14, 2023
2 parents 4fe14cc + 56ff790 commit c26914b
Show file tree
Hide file tree
Showing 4 changed files with 191 additions and 11 deletions.
11 changes: 0 additions & 11 deletions contrib/README

This file was deleted.

36 changes: 36 additions & 0 deletions contrib/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
This folder contains contributed files for use with Sopel.

## Service configuration

`sopel.service` and `sopel.cfg` are designed to be distributed by third parties
such as Fedora Project or Arch Linux.

`sopel.cfg` is a default configuration file for Sopel, that assumes the OS is
new enough to have `/run` and `/usr/lib/tmpfiles.d`

`sopel.service` is a systemd service file, and `[email protected]` is a
multi-instance template. Both assume you are using a rather recent Sopel; that
the system has a special user named `sopel` designated for running the bot; and
that this user has access to `/run/sopel` (should be setup by `sopel.conf` in
`/usr/lib/tmpfiles.d`), `/var/log/sopel` and `/var/lib/sopel`

Default installation paths:

```
sopel.cfg /etc
sopel.conf /usr/lib/tmpfiles.d
sopel.service /usr/lib/systemd/system
[email protected] /usr/lib/systemd/system
```

## tox

`tox.ini` and `toxfile.py` provide support for running Sopel's QA automation
against multiple Python versions locally. To run QA for all configured versions
in parallel, run `tox --conf contrib/ -p` from the repository root. You may
also want to set `TOX_CONFIG_FILE=path/to/contrib` to shorten that invocation
to just `tox -p`.

## githooks

Git hooks for development use
47 changes: 47 additions & 0 deletions contrib/tox.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
[tox]
package_root = .
min_version = 4.3.3
envlist =
py{37,38,39,310,311}-qa
skip_missing_interpreters = true
ignore_base_python_conflict = true
labels =
mypy = py{37,38,39,310,311}-mypy
quality = py{37,38,39,310,311}-quality
test = py{37,38,39,310,311}-test


[testenv]
runner = ignore_env_name_mismatch
package = sdist
allowlist_externals =
make
envname =
py37: py37
py38: py38
py39: py39
py310: py310
py311: py311
envdir =
py37: {toxinidir}/.tox/py37
py38: {toxinidir}/.tox/py38
py39: {toxinidir}/.tox/py39
py310: {toxinidir}/.tox/py310
py311: {toxinidir}/.tox/py311
depends =
base
deps =
-r ../dev-requirements.txt
passenv =
PYTEST_ADDOPTS
setenv =
COVERAGE_FILE = {envdir}/.coverage

commands =
qa: make -C.. qa
mypy: make -C.. mypy
quality: make -C.. quality
test: make -C.. test
# NOTE:there's currently no way to specify separate output directories for
# the HTML coverage report, but the CLI report is probably fine anyway
test: make -C.. coverage_report
108 changes: 108 additions & 0 deletions contrib/toxfile.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
from pathlib import Path

from tox.execute.request import StdinSource
from tox.plugin import impl


CWD = Path().resolve()
HERE = Path(__file__).parent.resolve()

if CWD != HERE.parent:
raise RuntimeError("Tox must be run from the sopel repository root")


@impl
def tox_on_install(tox_env, arguments, section, of_type):
EXCLUDED_DEPS = ("sopel-help",)

# NOTE: this hook is a workaround for the cyclic dependency between sopel and sopel-help
if of_type == "deps":
cmd = ["python", "-m", "pip", "install", "--no-deps", "sopel-help"]
tox_env.execute(cmd, stdin=StdinSource.OFF)
elif of_type == "package":
sopel_sdist = arguments[0]
deps = sopel_sdist.deps
deps[:] = [d for d in deps if d.name not in EXCLUDED_DEPS]


# NOTE:The following is included verbatim from upstream (v0.2.0.post2 @ ebed159)
# to allow re-use of tox environments for each Python version. We *can* depend
# on the plugin from tox.ini but it makes sense to use the recommended vendoring
# approach since we have a toxfile.py anyway.
"""
https://github.com/masenf/tox-ignore-env-name-mismatch
MIT License
Copyright (c) 2023 Masen Furer
"""
from contextlib import contextmanager
from typing import Any, Iterator, Optional, Sequence, Tuple

from tox.plugin import impl
from tox.tox_env.api import ToxEnv
from tox.tox_env.info import Info
from tox.tox_env.python.virtual_env.runner import VirtualEnvRunner
from tox.tox_env.register import ToxEnvRegister


class FilteredInfo(Info):
"""Subclass of Info that optionally filters specific keys during compare()."""

def __init__(
self,
*args: Any,
filter_keys: Optional[Sequence[str]] = None,
filter_section: Optional[str] = None,
**kwargs: Any,
):
"""
:param filter_keys: key names to pop from value
:param filter_section: if specified, only pop filter_keys when the compared section matches
All other args and kwargs are passed to super().__init__
"""
self.filter_keys = filter_keys
self.filter_section = filter_section
super().__init__(*args, **kwargs)

@contextmanager
def compare(
self,
value: Any,
section: str,
sub_section: Optional[str] = None,
) -> Iterator[Tuple[bool, Optional[Any]]]:
"""Perform comparison and update cached info after filtering `value`."""
if self.filter_section is None or section == self.filter_section:
try:
value = value.copy()
except AttributeError: # pragma: no cover
pass
else:
for fkey in self.filter_keys or []:
value.pop(fkey, None)
with super().compare(value, section, sub_section) as rv:
yield rv


class IgnoreEnvNameMismatchVirtualEnvRunner(VirtualEnvRunner):
"""EnvRunner that does NOT save the env name as part of the cached info."""

@staticmethod
def id() -> str:
return "ignore_env_name_mismatch"

@property
def cache(self) -> Info:
"""Return a modified Info class that does NOT pass "name" key to `Info.compare`."""
return FilteredInfo(
self.env_dir,
filter_keys=["name"],
filter_section=ToxEnv.__name__,
)


@impl
def tox_register_tox_env(register: ToxEnvRegister) -> None:
"""tox4 entry point: add IgnoreEnvNameMismatchVirtualEnvRunner to registry."""
register.add_run_env(IgnoreEnvNameMismatchVirtualEnvRunner)

0 comments on commit c26914b

Please sign in to comment.