Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions policyengine_uk/tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,10 @@ def pytest_collection_modifyitems(config, items):
# a module named "<id(system)>_<path hash>_<file name>" and registers it in
# sys.modules, where it stays after the system is garbage collected. Every
# Simulation builds its own system, so each one leaves about 1,000 modules
# (roughly 10 MB) behind, and the property tests build hundreds: one test
# process grew to 15.7 GB on a 16 GB CI runner. After each test, drop the
# modules of systems that no longer exist; live systems keep theirs. Remove
# this once policyengine-core stops leaking them
# (roughly 10 MB) behind, and the property tests build hundreds: running the
# suite serially used 99% of a 16 GB CI runner's memory. After each test, drop
# the modules of systems that no longer exist; live systems keep theirs.
# Remove this once policyengine-core stops leaking them
# (PolicyEngine/policyengine-core#520).
_VARIABLE_MODULE_NAME = re.compile(r"(\d+)_-?\d+_")

Expand All @@ -66,8 +66,8 @@ def release_dead_variable_modules(max_owners: int = 8) -> int:
for owner, names in owners.items():
if owner not in live:
for name in names:
sys.modules.pop(name, None)
released += len(names)
if sys.modules.pop(name, None) is not None:
released += 1
return released


Expand Down
24 changes: 18 additions & 6 deletions policyengine_uk/tests/test_variable_module_release.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,18 @@
under the system's id and never removes them. The conftest's
``release_dead_variable_modules`` drops those of systems that no longer exist,
which keeps a long test process's memory flat. If core stops leaking the
modules (PolicyEngine/policyengine-core#520), the precondition below fails
and the workaround can go.
modules (PolicyEngine/policyengine-core#520), the first test skips with a
note to remove the workaround, rather than failing every PR after a core
upgrade. If core keeps leaking but names the modules differently, it fails,
because the release would then silently do nothing.
"""

import gc
import sys
from pathlib import Path

import pytest

from policyengine_uk import Simulation

SITUATION = {
Expand Down Expand Up @@ -41,10 +45,18 @@ def test_dead_systems_modules_are_released_and_live_ones_kept(request):
dropped_owner = str(id(dropped.tax_benefit_system))
expected = dropped.calculate("income_tax", 2026)

assert _modules_of(dropped_owner), (
"policyengine-core no longer registers variable modules under the "
"system's id; the conftest workaround may no longer be needed"
)
# The module core loaded the income_tax variable from, for this system.
module = type(dropped.tax_benefit_system.variables["income_tax"]).__module__
if module not in sys.modules:
pytest.skip(
"policyengine-core no longer keeps variable modules in sys.modules "
"(policyengine-core#520 fixed?); remove "
"release_dead_variable_modules from conftest.py and this test"
)
# Core still keeps them, so the conftest pattern must still recognise them,
# or the release would silently do nothing.
assert module.startswith(dropped_owner + "_"), module
assert _conftest(request)._VARIABLE_MODULE_NAME.match(module), module
del dropped
gc.collect()

Expand Down
Loading