Skip to content

Commit de1a8ce

Browse files
committed
Fix Network.restore KeyError in loops and spurious unused object warnings (#1814)
1 parent 6143adc commit de1a8ce

3 files changed

Lines changed: 33 additions & 1 deletion

File tree

brian2/core/magic.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -489,3 +489,7 @@ def start_scope():
489489
included by the magic functions such as `run`.
490490
"""
491491
BrianObject._scope_current_key += 1
492+
493+
# Run garbage collection here to destroy stale objects from previous runs
494+
# preventing them from squatting on auto-generated names in the InstanceFollower
495+
gc.collect()

brian2/core/network.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -543,14 +543,15 @@ def add(self, *objs):
543543
"""
544544
for obj in objs:
545545
if isinstance(obj, BrianObject):
546-
if obj._network is not None:
546+
if obj._network is not None and obj._network != self.id:
547547
raise RuntimeError(
548548
f"{obj.name} has already been simulated, cannot "
549549
"add it to the network. If you were "
550550
"trying to remove and add an object to "
551551
"temporarily stop it from being run, "
552552
"set its active flag to False instead."
553553
)
554+
obj._network = self.id
554555
self.objects.add(obj)
555556
else:
556557
# allow adding values from dictionaries

brian2/tests/test_network.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1922,6 +1922,33 @@ def test_negative_duration_in_net_run():
19221922
net.run(-1 * second)
19231923

19241924

1925+
@pytest.mark.codegen_independent
1926+
def test_network_restore_loop():
1927+
# Issue 1814: Verify that running and restoring networks in a loop
1928+
# does not raise KeyError due to auto-generated clocks leaking iteratively
1929+
filename = tempfile.mktemp(suffix="state", prefix="brian_test")
1930+
try:
1931+
start_scope()
1932+
G = NeuronGroup(10, "v:1", name="G")
1933+
G.run_regularly("v += 0.1", dt=1 * ms)
1934+
net = Network(collect())
1935+
net.run(1 * ms)
1936+
net.store(filename=filename)
1937+
1938+
for i in range(2):
1939+
start_scope()
1940+
G = NeuronGroup(10, "v:1", name="G")
1941+
G.run_regularly("v += 0.1", dt=1 * ms)
1942+
net2 = Network(collect())
1943+
net2.restore(filename=filename)
1944+
net2.run(1 * ms)
1945+
finally:
1946+
try:
1947+
os.remove(filename)
1948+
except OSError:
1949+
pass
1950+
1951+
19251952
if __name__ == "__main__":
19261953
BrianLogger.log_level_warn()
19271954
for t in [

0 commit comments

Comments
 (0)