Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make bypass setup and run update invalid in static models #693

Merged
merged 13 commits into from
Feb 13, 2025
Merged
81 changes: 81 additions & 0 deletions tests/core/test_base_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -807,3 +807,84 @@ def from_config(

if expected_message:
assert str(exc.value) == expected_message


@pytest.mark.parametrize(
"static, vars_populated_by_init, vars_updated, data_vars, expected_exception, "
"expected_message",
[
# Test case where _setup is bypassed and _update is run
pytest.param(
True,
("var1", "var2"),
("var3",),
{"var1": 1, "var2": 2},
pytest.raises(ConfigurationError),
"Static model test_model will not run the setup method, but "
"requires the update method to run once. This is an invalid "
"configuration. Please, make sure that either both methods are run once"
" by not providing any variables in vars_populated_by_first_update and "
"vars_updated or that both are bypassed by providing all variables in "
"vars_populated_by_init.",
id="static_setup_bypassed_update_run",
),
],
)
def test_bypass_setup_but_run_update_fails(
static,
vars_populated_by_init,
vars_updated,
data_vars,
expected_exception,
expected_message,
fixture_data,
fixture_config,
):
"""Test the _bypass_setup_due_to_static_configuration method."""
from virtual_ecosystem.core.base_model import BaseModel
from virtual_ecosystem.core.config import Config
from virtual_ecosystem.core.core_components import (
CoreComponents,
)
from virtual_ecosystem.core.data import Data

class TestModel(
BaseModel,
model_name="test_model",
model_update_bounds=("1 day", "1 month"),
vars_required_for_init=(),
vars_updated=vars_updated,
vars_required_for_update=(),
vars_populated_by_init=vars_populated_by_init,
vars_populated_by_first_update=(),
):
def _setup(self, *args: Any, **kwargs: Any) -> None:
pass

def spinup(self) -> None:
pass

def _update(self, time_index: int, **kwargs: Any) -> None:
pass

def cleanup(self) -> None:
pass

@classmethod
def from_config(
cls, data: Data, core_components: CoreComponents, config: Config
) -> BaseModel:
return super().from_config(
data=data, core_components=core_components, config=config
)

for var in data_vars.keys():
fixture_data[var] = fixture_data["existing_var"].copy()

core_components = CoreComponents(config=fixture_config)

with expected_exception as exc:
TestModel(data=fixture_data, core_components=core_components, static=static)

if expected_message:
assert str(exc.value) == expected_message
15 changes: 13 additions & 2 deletions virtual_ecosystem/core/base_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,18 @@ def __init__(
# Check the configured update interval is within model bounds
self._check_update_speed()

if not self._bypass_setup_due_to_static_configuration():
bypass_setup = self._bypass_setup_due_to_static_configuration()
if bypass_setup and self._run_initial_static_update:
raise ConfigurationError(
f"Static model {self.model_name} will not run the setup method, but "
"requires the update method to run once. This is an invalid "
"configuration. Please, make sure that either both methods are run once"
" by not providing any variables in vars_populated_by_first_update and "
"vars_updated or that both are bypassed by providing all variables in "
"vars_populated_by_init."
)

if not bypass_setup:
self._setup(**kwargs)

def _bypass_setup_due_to_static_configuration(self) -> bool:
Expand Down Expand Up @@ -338,7 +349,7 @@ def _run_update_due_to_static_configuration(self) -> bool:
)

elif self._static:
if found == 0:
if found == 0 and expected > 0:
return True
elif found == expected:
return False
Expand Down