From c0ae76b51779f3200d7890cc1d03d1cd84c8ab89 Mon Sep 17 00:00:00 2001 From: "Christian Y. Brenninkmeijer" Date: Fri, 6 Feb 2026 13:30:23 +0000 Subject: [PATCH 1/4] don't allow set after a model has been created. --- spynnaker/pyNN/config_setup.py | 2 ++ spynnaker/pyNN/models/abstract_pynn_model.py | 27 +++++++++++++++----- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/spynnaker/pyNN/config_setup.py b/spynnaker/pyNN/config_setup.py index cb60d44464..3e1f1e39bb 100644 --- a/spynnaker/pyNN/config_setup.py +++ b/spynnaker/pyNN/config_setup.py @@ -22,6 +22,7 @@ fec_cfg_paths_skipped) from spynnaker.pyNN.data.spynnaker_data_writer import SpynnakerDataWriter +from spynnaker.pyNN.models.neuron import AbstractPyNNNeuronModel SPYNNAKER_CFG = "spynnaker.cfg" @@ -43,6 +44,7 @@ def unittest_setup() -> None: clear_cfg_files(True) add_spynnaker_cfg() SpynnakerDataWriter.mock() + AbstractPyNNNeuronModel.reset_all() def add_spynnaker_cfg() -> None: diff --git a/spynnaker/pyNN/models/abstract_pynn_model.py b/spynnaker/pyNN/models/abstract_pynn_model.py index 9cb0e94ce7..4a50da3cd6 100644 --- a/spynnaker/pyNN/models/abstract_pynn_model.py +++ b/spynnaker/pyNN/models/abstract_pynn_model.py @@ -40,6 +40,13 @@ class AbstractPyNNModel(AbstractProvidesDefaults, metaclass=AbstractBase): _max_atoms_per_core: Dict[type, Optional[Tuple[int, ...]]] = defaultdict( lambda: None) + _model_created = False + + # Using new as most supers do not call the init + def __new__(cls, *args, **kwargs): + AbstractPyNNModel._model_created = True + return super(AbstractPyNNModel, cls).__new__(cls) + @classmethod def verify_may_set(cls, param: str) -> None: """ If a Population has been created, this method will raise an @@ -51,13 +58,18 @@ def verify_may_set(cls, param: str) -> None: in the Population constructor instead. """ SpynnakerDataView.check_user_can_act() - if SpynnakerDataView.get_n_populations() == 0: - return - raise SpynnakerException( - "Global set is not supported after a Population has been " - "created. Either move it above the creation of all Populations " - f"or provide {param} during the creation of each Population it " - "applies to.") + if SpynnakerDataView.get_n_populations() > 0: + raise SpynnakerException( + "Global set is not supported after a Population has been " + "created. Either move it above the creation of all " + "Populations or provide {param} during the creation of each " + "Population it applies to.") + if AbstractPyNNModel._model_created: + raise SpynnakerException( + "Global set is not supported after a Model has been " + "created. Either move it above the creation of all " + "Models or provide {param} during the creation of each " + "Population it applies to.") @classmethod def set_model_max_atoms_per_dimension_per_core( @@ -115,6 +127,7 @@ def reset_all(cls) -> None: Reset the maximum values for all classes. """ AbstractPyNNModel._max_atoms_per_core.clear() + AbstractPyNNModel._model_created = False @classproperty def absolute_max_atoms_per_core( # pylint: disable=no-self-argument From 19993846126fd4fb1dea43c97898433334f0db52 Mon Sep 17 00:00:00 2001 From: "Christian Y. Brenninkmeijer" Date: Fri, 6 Feb 2026 13:37:34 +0000 Subject: [PATCH 2/4] typing --- spynnaker/pyNN/models/abstract_pynn_model.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spynnaker/pyNN/models/abstract_pynn_model.py b/spynnaker/pyNN/models/abstract_pynn_model.py index 4a50da3cd6..8f70bd750a 100644 --- a/spynnaker/pyNN/models/abstract_pynn_model.py +++ b/spynnaker/pyNN/models/abstract_pynn_model.py @@ -43,7 +43,7 @@ class AbstractPyNNModel(AbstractProvidesDefaults, metaclass=AbstractBase): _model_created = False # Using new as most supers do not call the init - def __new__(cls, *args, **kwargs): + def __new__(cls, *args: Any, **kwargs: Any) -> "AbstractPyNNModel": AbstractPyNNModel._model_created = True return super(AbstractPyNNModel, cls).__new__(cls) From 37cee80bbf6f33e99e1701a183731f033b587196 Mon Sep 17 00:00:00 2001 From: "Christian Y. Brenninkmeijer" Date: Fri, 6 Feb 2026 14:45:40 +0000 Subject: [PATCH 3/4] ""use" args --- spynnaker/pyNN/models/abstract_pynn_model.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/spynnaker/pyNN/models/abstract_pynn_model.py b/spynnaker/pyNN/models/abstract_pynn_model.py index 8f70bd750a..f752484b86 100644 --- a/spynnaker/pyNN/models/abstract_pynn_model.py +++ b/spynnaker/pyNN/models/abstract_pynn_model.py @@ -42,8 +42,9 @@ class AbstractPyNNModel(AbstractProvidesDefaults, metaclass=AbstractBase): _model_created = False - # Using new as most supers do not call the init + # Using new as most super classes do not call the init def __new__(cls, *args: Any, **kwargs: Any) -> "AbstractPyNNModel": + _ = (args, kwargs) AbstractPyNNModel._model_created = True return super(AbstractPyNNModel, cls).__new__(cls) From 3d98db19e2d51e87ec616a4d04c1c39460926666 Mon Sep 17 00:00:00 2001 From: "Christian Y. Brenninkmeijer" Date: Fri, 6 Feb 2026 14:49:39 +0000 Subject: [PATCH 4/4] f string --- spynnaker/pyNN/models/abstract_pynn_model.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spynnaker/pyNN/models/abstract_pynn_model.py b/spynnaker/pyNN/models/abstract_pynn_model.py index f752484b86..5df4b08b54 100644 --- a/spynnaker/pyNN/models/abstract_pynn_model.py +++ b/spynnaker/pyNN/models/abstract_pynn_model.py @@ -63,13 +63,13 @@ def verify_may_set(cls, param: str) -> None: raise SpynnakerException( "Global set is not supported after a Population has been " "created. Either move it above the creation of all " - "Populations or provide {param} during the creation of each " + f"Populations or provide {param} during the creation of each " "Population it applies to.") if AbstractPyNNModel._model_created: raise SpynnakerException( "Global set is not supported after a Model has been " "created. Either move it above the creation of all " - "Models or provide {param} during the creation of each " + f"Models or provide {param} during the creation of each " "Population it applies to.") @classmethod