Skip to content

Commit 80ba3cb

Browse files
committed
use nox
The top-level test runner has been changed to use ``nox``, adding a ``noxfile.py`` as well as some included modules. The ``tox.ini`` file remains in place so that ``tox`` runs will continue to function in the near term, however it will be eventually removed and improvements and maintenance going forward will be only towards ``noxfile.py``. py313t: yes py314t: yes Change-Id: I26e02f35d52de6eac48d31bbae671f5af34bbc80
1 parent ac7a026 commit 80ba3cb

9 files changed

Lines changed: 531 additions & 4 deletions

File tree

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ alembic.ini
99
*.egg-info
1010
.coverage
1111
.tox/
12+
.nox/
1213
coverage.xml
1314
test_*.lock
1415
test_*.db
@@ -17,4 +18,4 @@ test_*.db
1718
test_*.db.bak
1819
test_*.db.dat
1920
test_*.db.dir
20-
tests/tls/generate/gen/
21+
tests/tls/generate/gen/

MANIFEST.in

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
recursive-include docs *.html *.css *.txt *.js *.jpg *.png *.py Makefile *.rst *.sty
22
recursive-include tests *.py *.dat *.crt *.pem *.key *.sh
3+
recursive-include tools *.py
34

4-
include README* LICENSE CHANGES* log_tests.ini tox.ini hash_port.py
5+
include README* LICENSE CHANGES* log_tests.ini tox.ini hash_port.py noxfile.py
56

67
prune docs/build/output
78

docs/build/unreleased/nox.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
.. change::
2+
:tags: change, tests
3+
4+
The top-level test runner has been changed to use ``nox``, adding a
5+
``noxfile.py`` as well as some included modules. The ``tox.ini`` file
6+
remains in place so that ``tox`` runs will continue to function in the near
7+
term, however it will be eventually removed and improvements and
8+
maintenance going forward will be only towards ``noxfile.py``.

dogpile/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
__version__ = "1.4.2"
1+
__version__ = "1.5.0"
22

33
from .lock import Lock # noqa
44
from .lock import NeedRegenerationException # noqa

noxfile.py

Lines changed: 246 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,246 @@
1+
"""Nox configuration for dogpile.cache."""
2+
3+
from __future__ import annotations
4+
5+
import os
6+
import sys
7+
from typing import List
8+
9+
import nox
10+
11+
if True:
12+
sys.path.insert(0, ".")
13+
from tools.toxnox import tox_parameters
14+
15+
16+
PYTHON_VERSIONS = [
17+
"3.9",
18+
"3.10",
19+
"3.11",
20+
"3.12",
21+
"3.13",
22+
"3.13t",
23+
"3.14",
24+
"3.14t",
25+
]
26+
TARGETS = [
27+
"generic",
28+
"memory",
29+
"memcached",
30+
"redis",
31+
"redis_sentinel",
32+
"valkey",
33+
"valkey_sentinel",
34+
"dbm",
35+
]
36+
FULL = ["_quick", "full"]
37+
38+
pyproject = nox.project.load_toml("pyproject.toml")
39+
40+
nox.options.sessions = ["simple"]
41+
nox.options.tags = ["py-generic-memory-dbm"]
42+
43+
44+
def pifpaf(
45+
cmd: List[str],
46+
module: str,
47+
*,
48+
port_env: str = "TOX_DOGPILE_PORT",
49+
port: str = "11234",
50+
additonal_args: str = "",
51+
) -> None:
52+
"""prepend a pifpaf execution to the given command arguments.
53+
54+
This runs a server like memcached or redis up front before invoking
55+
the subsequent commands.
56+
57+
"""
58+
cmd[:0] = (
59+
f"pifpaf --env-prefix DOGPILE run {module} --port "
60+
f"{os.environ.get(port_env, port)} {additonal_args} --".split()
61+
)
62+
63+
64+
@nox.session(name="simple")
65+
@tox_parameters(
66+
["python", "target", "full"],
67+
[PYTHON_VERSIONS, ["generic-memory-dbm"], FULL],
68+
always_include_in_tag=["target"],
69+
)
70+
def test_simple(session: nox.Session, target: str, full: str) -> None:
71+
"""run a general suite including two built-in backends"""
72+
_tests(session, ["generic", "memory", "dbm"], full=full == "full")
73+
74+
75+
@nox.session(name="backends")
76+
@tox_parameters(
77+
["python", "target", "full"],
78+
[PYTHON_VERSIONS, TARGETS, FULL],
79+
)
80+
def test_backends(session: nox.Session, target: str, full: str) -> None:
81+
"""Run the main test suite, with optional single backend tests"""
82+
83+
_tests(session, [target], full=full == "full")
84+
85+
86+
@nox.session(name="all")
87+
@tox_parameters(
88+
["python", "target", "full"],
89+
[PYTHON_VERSIONS, ["all"], FULL],
90+
always_include_in_tag=["target"],
91+
)
92+
def tests_all(session: nox.Session, target: str, full: str) -> None:
93+
"""Run the main test suite against all backends separately"""
94+
95+
_tests(
96+
session,
97+
TARGETS,
98+
full=full == "full",
99+
)
100+
101+
102+
@nox.session(name="coverage")
103+
@tox_parameters(["target"], [TARGETS], base_tag="coverage")
104+
def coverage(session: nox.Session, target: str) -> None:
105+
"""Run tests with coverage."""
106+
107+
_tests(session, [target], coverage=True)
108+
109+
110+
def _tests(
111+
session: nox.Session,
112+
targets: List[str],
113+
coverage: bool = False,
114+
full: bool = False,
115+
) -> None:
116+
117+
if coverage:
118+
session.install("-e", ".")
119+
else:
120+
session.install(".")
121+
122+
session.install(*nox.project.dependency_groups(pyproject, "tests"))
123+
124+
if coverage:
125+
session.install(*nox.project.dependency_groups(pyproject, "coverage"))
126+
127+
cmd = ["python", "-m", "pytest"]
128+
129+
if coverage:
130+
cmd.extend(
131+
[
132+
"--cov=dogpile",
133+
"--cov-append",
134+
"--cov-report",
135+
"term",
136+
"--cov-report",
137+
"xml",
138+
]
139+
)
140+
141+
if full:
142+
# enables all tags including time_intensive
143+
cmd.extend(["-m", ""])
144+
145+
for target in targets:
146+
# due to the pifpaf thing, it's easier just to run all the
147+
# pytests separately for each backend rather than having all the
148+
# services running and figuring out how to keep them all on distinct
149+
# ports. so iterate through backends and run individual suites.
150+
backend_cmd: List[str] = []
151+
pifpaf_cmd: List[str] = []
152+
153+
# note the default target is "generic", which means run all the
154+
# normal tests but no backend tests
155+
if target == "generic":
156+
backend_cmd.append("-k not backend.py")
157+
elif target == "memory":
158+
backend_cmd.append("tests/cache/test_memory_backend.py")
159+
elif target == "memcached":
160+
session.install(
161+
*nox.project.dependency_groups(
162+
pyproject,
163+
"tests_memcached_full" if full else "tests_memcached",
164+
)
165+
)
166+
167+
pifpaf(pifpaf_cmd, "memcached")
168+
pifpaf(
169+
pifpaf_cmd,
170+
"memcached",
171+
port_env="TOX_DOGPILE_TLS_PORT",
172+
port="11212",
173+
additonal_args="--ssl_chain_cert=tests/tls/server_chain.pem "
174+
"--ssl_key=tests/tls/server.key",
175+
)
176+
177+
backend_cmd.append("tests/cache/test_memcached_backend.py")
178+
elif target == "redis":
179+
session.install(
180+
*nox.project.dependency_groups(pyproject, "tests_redis")
181+
)
182+
pifpaf(pifpaf_cmd, "redis")
183+
backend_cmd.append("tests/cache/test_redis_backend.py")
184+
elif target == "valkey":
185+
session.install(
186+
*nox.project.dependency_groups(pyproject, "tests_valkey")
187+
)
188+
pifpaf(pifpaf_cmd, "valkey")
189+
backend_cmd.append("tests/cache/test_valkey_backend.py")
190+
elif target == "redis_sentinel":
191+
session.install(
192+
*nox.project.dependency_groups(pyproject, "tests_redis")
193+
)
194+
195+
pifpaf(
196+
pifpaf_cmd,
197+
"redis",
198+
additonal_args=f"--sentinel --sentinel "
199+
f"--sentinel-port "
200+
f"{os.environ.get('TOX_DOGPILE_SENTINEL_PORT', '11235')}",
201+
)
202+
backend_cmd.append("tests/cache/test_redis_sentinel_backend.py")
203+
elif target == "valkey_sentinel":
204+
session.install(
205+
*nox.project.dependency_groups(pyproject, "tests_valkey")
206+
)
207+
pifpaf(
208+
pifpaf_cmd,
209+
"valkey",
210+
additonal_args=f"--sentinel --sentinel "
211+
f"--sentinel-port "
212+
f"{os.environ.get('TOX_DOGPILE_SENTINEL_PORT', '11235')}",
213+
)
214+
backend_cmd.append("tests/cache/test_valkey_sentinel_backend.py")
215+
elif target == "dbm":
216+
backend_cmd.append("tests/cache/test_dbm_backend.py")
217+
218+
session.run(*pifpaf_cmd, *cmd, *backend_cmd, *session.posargs)
219+
220+
221+
@nox.session(name="pep484")
222+
def mypy_check(session: nox.Session) -> None:
223+
"""Run mypy type checking."""
224+
225+
session.install(*nox.project.dependency_groups(pyproject, "mypy"))
226+
227+
session.install("-e", ".")
228+
229+
session.run("mypy", "noxfile.py", "./dogpile/")
230+
231+
232+
@nox.session(name="pep8")
233+
def lint(session: nox.Session) -> None:
234+
"""Run linting and formatting checks."""
235+
236+
session.install(*nox.project.dependency_groups(pyproject, "lint"))
237+
238+
file_paths = [
239+
"./dogpile/",
240+
"./tests/",
241+
"./tools/",
242+
"noxfile.py",
243+
"docs/build/conf.py",
244+
]
245+
session.run("flake8", *file_paths)
246+
session.run("black", "--check", *file_paths)

pyproject.toml

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,10 @@ bmemcached = [
4646
"python-binary-memcached",
4747
]
4848
pylibmc = [
49-
"pylibmc",
49+
# pylibmc is still getting commits in 2025 but has not had a release
50+
# since 2022. needs libmemcached headers etc. to build
51+
# "pylibmc",
52+
"pylibmc @ git+https://github.com/lericson/pylibmc.git@master"
5053
]
5154
redis = [
5255
"redis",
@@ -58,6 +61,71 @@ valkey = [
5861
[project.entry-points."mako.cache"]
5962
"dogpile.cache" = "dogpile.cache.plugins.mako_cache:MakoPlugin"
6063

64+
[dependency-groups]
65+
tests = [
66+
"pytest>8",
67+
"pytest-xdist",
68+
"mako",
69+
]
70+
71+
coverage = [
72+
"pytest-cov"
73+
]
74+
75+
tests_redis = [
76+
"dogpile.cache[pifpaf]",
77+
"dogpile.cache[redis]",
78+
]
79+
tests_memcached = [
80+
"dogpile.cache[pifpaf]",
81+
"dogpile.cache[pymemcache]",
82+
"dogpile.cache[memcached]",
83+
"dogpile.cache[bmemcached]",
84+
]
85+
86+
# pylibmc has not had a release for some years and needs to build
87+
# from source, so don't include it in memcached unless the build is the
88+
# "full" option
89+
tests_memcached_full = [
90+
{include-group = "tests_memcached"},
91+
"dogpile.cache[pylibmc]",
92+
]
93+
94+
tests_valkey = [
95+
"dogpile.cache[pifpaf]",
96+
"dogpile.cache[valkey]",
97+
]
98+
99+
100+
lint = [
101+
"flake8==7.2.0",
102+
"flake8-import-order",
103+
"flake8-builtins",
104+
"flake8-future-annotations>=0.0.5",
105+
"flake8-docstrings>=1.6.0",
106+
"flake8-import-single==0.1.5",
107+
"flake8-unused-arguments",
108+
# flake8-rst-docstrings dependency, leaving it here
109+
# in case it requires a version pin
110+
"flake8-rst-docstrings",
111+
"pydocstyle",
112+
"pygments",
113+
"black==25.1.0",
114+
"slotscheck>=0.17.0",
115+
]
116+
117+
mypy = [
118+
"nox", # because we check noxfile.py
119+
"mypy",
120+
"types-decorator",
121+
"types-redis",
122+
"redis",
123+
"valkey",
124+
"Mako",
125+
"decorator",
126+
]
127+
128+
61129
[tool.setuptools]
62130
zip-safe = false
63131
include-package-data = true

0 commit comments

Comments
 (0)