Skip to content

Commit 26ef93f

Browse files
committed
Merge branch 'develop' into feature/filter-converged
# Conflicts: # CHANGELOG.md
2 parents 3778d13 + 60d8aef commit 26ef93f

File tree

8 files changed

+66
-101
lines changed

8 files changed

+66
-101
lines changed

.github/workflows/run-tests-workflow.yaml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,10 @@ jobs:
3131
with:
3232
key: tox-${{ github.ref }}-${{ runner.os }}-${{ hashFiles('tox.ini', 'requirements.txt') }}
3333
path: .tox
34+
- name: Set up memcached
35+
uses: niden/actions-memcached@v7
3436
- name: Test Base Modules
35-
run: tox
37+
run: tox -e base
3638
if: inputs.tests_to_run == 'base'
3739
- name: Test Modules that rely on PyTorch
3840
run: tox -e torch

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
## Unreleased
44

5+
- No longer using docker within tests to start a memcached server
6+
[PR #444](https://github.com/aai-institute/pyDVL/pull/444)
57
- Faster semi-value computation with per-index check of stopping criteria (optional)
68
[PR #437](https://github.com/aai-institute/pyDVL/pull/437)
79
- Improvements and fixes to notebooks

CONTRIBUTING.md

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -95,11 +95,14 @@ run only certain tests using patterns (`-k`) or marker (`-m`).
9595
tox -e base -- <optional arguments>
9696
```
9797

98-
One important argument is `--do-not-start-memcache`. This prevents the test
99-
fixture from starting a new memcache server for testing and instead expects an
100-
already running local server listening on port 11211 (memcached's default port).
101-
If you run single tests within PyCharm, you will want to add this option to the
102-
run configurations.
98+
Two important arguments are `--memcached-service` which allows to change the
99+
default of `localhost:11211` (memcached's default) to a different address, and
100+
`-n` which sets the number of parallel workers for pytest-xdist. There are two
101+
layers of parallelization in the tests. An inner one within the tests
102+
themselves, i.e. the parallelism in the algorithms, and an outer one by
103+
pytest-xdist. The latter is controlled by the `-n` argument. If you experience
104+
segmentation faults with the tests, try running them with `-n 0` to disable
105+
parallelization.
103106

104107
To test modules that rely on PyTorch, use:
105108

@@ -326,7 +329,22 @@ Refer to its official
326329
[readme](https://github.com/nektos/act#installation-through-package-managers)
327330
for more installation options.
328331

329-
#### Cheatsheat
332+
#### act cheatsheet
333+
334+
By default, `act` will run **all workflows** in `.github/workflows`. You can
335+
use the `-W` flag to specify a specific workflow file to run, or you can rely
336+
on the job id to be unique (but then you'll see warnings for the workflows
337+
without that job id).
338+
339+
```shell
340+
# Run only the main tests for python 3.8 after a push event (implicit)
341+
act -W .github/workflows/run-tests-workflow.yaml \
342+
-j run-tests \
343+
--input tests_to_run=base\
344+
--input python_version=3.8
345+
```
346+
347+
Other common flags are:
330348

331349
```shell
332350
# List all actions for all events:

requirements-dev.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ nbconvert>=7.2.9
1515
nbstripout == 0.6.1
1616
pytest==7.2.2
1717
pytest-cov
18-
pytest-docker==2.0.0
1918
pytest-mock
2019
pytest-timeout
2120
pytest-lazy-fixture

tests/conftest.py

Lines changed: 22 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1+
from __future__ import annotations
2+
13
import functools
4+
import logging
25
import os
36
from collections import defaultdict
47
from dataclasses import asdict
@@ -31,10 +34,10 @@ def is_memcache_responsive(hostname, port):
3134

3235
def pytest_addoption(parser):
3336
parser.addoption(
34-
"--do-not-start-memcache",
37+
"--memcached-service",
3538
action="store_true",
36-
help="When this flag is used, memcache won't be started by a fixture"
37-
" and is instead expected to be already running",
39+
default="localhost:11211",
40+
help="Address of memcached server to use for tests.",
3841
)
3942
group = parser.getgroup("tolerate")
4043
group.addoption(
@@ -82,64 +85,17 @@ def pytorch_seed(seed):
8285

8386

8487
@pytest.fixture(scope="session")
85-
def do_not_start_memcache(request):
86-
return request.config.getoption("--do-not-start-memcache")
87-
88-
89-
@pytest.fixture(scope="session")
90-
def docker_services(
91-
docker_compose_command,
92-
docker_compose_file,
93-
docker_compose_project_name,
94-
docker_setup,
95-
docker_cleanup,
96-
do_not_start_memcache,
97-
):
98-
"""Start all services from a docker compose file (`docker-compose up`).
99-
After test are finished, shutdown all services (`docker-compose down`)."""
100-
from pytest_docker.plugin import get_docker_services
101-
102-
if do_not_start_memcache:
103-
yield
104-
else:
105-
with get_docker_services(
106-
docker_compose_command,
107-
docker_compose_file,
108-
docker_compose_project_name,
109-
docker_setup,
110-
docker_cleanup,
111-
) as docker_service:
112-
yield docker_service
113-
114-
115-
@pytest.fixture(scope="session")
116-
def memcached_service(docker_ip, docker_services, do_not_start_memcache):
117-
"""Ensure that memcached service is up and responsive.
118-
119-
If `do_not_start_memcache` is True then we just return the default values
120-
'localhost', 11211
121-
"""
122-
if do_not_start_memcache:
123-
return "localhost", 11211
124-
else:
125-
# `port_for` takes a container port and returns the corresponding host port
126-
port = docker_services.port_for("memcached", 11211)
127-
hostname, port = docker_ip, port
128-
docker_services.wait_until_responsive(
129-
timeout=30.0,
130-
pause=0.5,
131-
check=lambda: is_memcache_responsive(hostname, port),
132-
)
133-
return hostname, port
88+
def memcached_service(request) -> tuple[str, int]:
89+
opt = request.config.getoption("--memcached-service", default="localhost:11211")
90+
host, port = opt.split(":")
91+
return host, int(port)
13492

13593

13694
@pytest.fixture(scope="function")
13795
def memcache_client_config(memcached_service) -> MemcachedClientConfig:
138-
client_config = MemcachedClientConfig(
96+
return MemcachedClientConfig(
13997
server=memcached_service, connect_timeout=1.0, timeout=1, no_delay=True
14098
)
141-
Client(**asdict(client_config)).flush_all()
142-
return client_config
14399

144100

145101
@pytest.fixture(scope="function")
@@ -151,11 +107,9 @@ def memcached_client(memcache_client_config) -> Tuple[Client, MemcachedClientCon
151107
c.flush_all()
152108
return c, memcache_client_config
153109
except Exception as e:
154-
print(
155-
f"Could not connect to memcached server "
156-
f'{memcache_client_config["server"]}: {e}'
157-
)
158-
raise e
110+
raise ConnectionError(
111+
f"Could not connect to memcached at {memcache_client_config.server}"
112+
) from e
159113

160114

161115
@pytest.fixture(scope="function")
@@ -400,6 +354,14 @@ def pytest_configure(config):
400354
)
401355
config._tolerate_session = TolerateErrorsSession(config)
402356

357+
worker_id = os.environ.get("PYTEST_XDIST_WORKER")
358+
if worker_id is not None:
359+
logging.basicConfig(
360+
format="%(asctime)s %(levelname)s %(message)s",
361+
filename=f"tests_{worker_id}.log",
362+
level=logging.DEBUG,
363+
)
364+
403365

404366
def pytest_runtest_setup(item: pytest.Item):
405367
marker = item.get_closest_marker("tolerate")

tests/docker-compose.yml

Lines changed: 0 additions & 8 deletions
This file was deleted.

tests/utils/test_caching.py

Lines changed: 11 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -70,68 +70,58 @@ def foo(indices: NDArray[np.int_], *args, **kwargs) -> float:
7070
assert hits_after - hits_before >= n_runs - 2
7171

7272

73-
def test_memcached_repeated_training(memcached_client):
73+
def test_memcached_repeated_training(memcached_client, worker_id: str):
7474
_, config = memcached_client
7575

7676
@memcached(
7777
client_config=config,
7878
time_threshold=0, # Always cache results
7979
allow_repeated_evaluations=True,
8080
rtol_stderr=0.01,
81-
# Note that we typically do NOT want to ignore run_id
82-
ignore_args=["job_id", "run_id"],
8381
)
84-
def foo(indices: NDArray[np.int_]) -> float:
85-
# from pydvl.utils.logging import logger
86-
# logger.info(f"run_id: {run_id}, running...")
82+
def foo(indices: NDArray[np.int_], uid: str) -> float:
8783
return float(np.sum(indices)) + np.random.normal(scale=10)
8884

8985
n = 7
90-
foo(np.arange(n))
86+
foo(np.arange(n), worker_id)
9187
for _ in range(10_000):
92-
result = foo(np.arange(n))
88+
result = foo(np.arange(n), worker_id)
9389

9490
assert (result - np.sum(np.arange(n))) < 1
9591
assert foo.stats.sets < foo.stats.hits
9692

9793

98-
def test_memcached_faster_with_repeated_training(memcached_client):
94+
def test_memcached_faster_with_repeated_training(memcached_client, worker_id: str):
9995
_, config = memcached_client
10096

10197
@memcached(
10298
client_config=config,
10399
time_threshold=0, # Always cache results
104100
allow_repeated_evaluations=True,
105101
rtol_stderr=0.1,
106-
# Note that we typically do NOT want to ignore run_id
107-
ignore_args=["job_id", "run_id"],
108102
)
109-
def foo_cache(indices: NDArray[np.int_]) -> float:
110-
# from pydvl.utils.logging import logger
111-
# logger.info(f"run_id: {run_id}, running...")
103+
def foo_cache(indices: NDArray[np.int_], uid: str) -> float:
112104
sleep(0.01)
113105
return float(np.sum(indices)) + np.random.normal(scale=1)
114106

115-
def foo_no_cache(indices: NDArray[np.int_]) -> float:
116-
# from pydvl.utils.logging import logger
117-
# logger.info(f"run_id: {run_id}, running...")
107+
def foo_no_cache(indices: NDArray[np.int_], uid: str) -> float:
118108
sleep(0.01)
119109
return float(np.sum(indices)) + np.random.normal(scale=1)
120110

121111
n = 3
122-
foo_cache(np.arange(n))
123-
foo_no_cache(np.arange(n))
112+
foo_cache(np.arange(n), worker_id)
113+
foo_no_cache(np.arange(n), worker_id)
124114

125115
start = time()
126116
for _ in range(300):
127-
result_fast = foo_cache(np.arange(n))
117+
result_fast = foo_cache(np.arange(n), worker_id)
128118
end = time()
129119
fast_time = end - start
130120

131121
start = time()
132122
results_slow = []
133123
for _ in range(300):
134-
result = foo_no_cache(np.arange(n))
124+
result = foo_no_cache(np.arange(n), worker_id)
135125
results_slow.append(result)
136126
end = time()
137127
slow_time = end - start

tox.ini

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[tox]
2-
envlist = base, report, docs
2+
envlist = base
33
wheel = true
44

55
[testenv]
@@ -12,12 +12,12 @@ setenv =
1212
[testenv:base]
1313
description = Tests base modules
1414
commands =
15-
pytest -n auto --cov "{envsitepackagesdir}/pydvl" -m "not torch" {posargs}
15+
pytest -n auto --dist worksteal --cov "{envsitepackagesdir}/pydvl" -m "not torch" {posargs}
1616

1717
[testenv:torch]
1818
description = Tests modules that rely on pytorch
1919
commands =
20-
pytest -n auto --cov "{envsitepackagesdir}/pydvl" -m torch {posargs}
20+
pytest -n auto --dist worksteal --cov "{envsitepackagesdir}/pydvl" -m torch {posargs}
2121
extras =
2222
influence
2323

@@ -26,7 +26,7 @@ description = Tests notebooks
2626
setenv =
2727
PYTHONPATH={toxinidir}/notebooks
2828
commands =
29-
pytest -n auto notebooks/ --cov "{envsitepackagesdir}/pydvl" {posargs}
29+
pytest -n auto --dist worksteal notebooks/ --cov "{envsitepackagesdir}/pydvl" {posargs}
3030
deps =
3131
{[testenv]deps}
3232
jupyter==1.0.0

0 commit comments

Comments
 (0)