Repository: projectmesa/mesa
Pull request #2218 (2024-08-17 12:40:42)

Require Mesa models to be initialized with `super().__init__()`
Remove the workaround for when the model super has not been called, and thereby require Mesa models to be initialized with `super().__init__()`.

```Python
class MyModel(mesa.Model):
    def __init__(self):
        super().__init__()  # This is now required!
```
This is needed to correctly add Agents to the model and setup other Mesa model variables.

This warning was present since Mesa 2.2.0 (https://github.com/projectmesa/mesa/pull/1928), so there has been some time to update for existing users.

This PR contains a second commit that names experimental warning in PropertyLayer correctly in space.py.

github-actions[bot]: Performance benchmarks:

| Model        | Size   | Init time [95% CI]      | Run time [95% CI]       |
|--------------|--------|-------------------------|-------------------------|
| Schelling    | small  | 🔵 +0.7% [+0.3%, +1.1%] | 🔵 -0.3% [-0.5%, -0.1%] |
| Schelling    | large  | 🔵 +1.4% [+0.9%, +1.9%] | 🔵 -1.7% [-2.5%, -0.9%] |
| WolfSheep    | small  | 🔵 +0.0% [-1.3%, +1.2%] | 🔵 -0.6% [-0.9%, -0.3%] |
| WolfSheep    | large  | 🔵 +0.7% [+0.5%, +1.0%] | 🔵 -0.3% [-1.1%, +0.5%] |
| BoidFlockers | small  | 🔵 +0.4% [-0.2%, +1.0%] | 🔵 -1.0% [-1.7%, -0.1%] |
| BoidFlockers | large  | 🔵 +1.0% [+0.3%, +1.7%] | 🔵 -0.2% [-0.9%, +0.3%] |


Patch:
diff --git a/mesa/agent.py b/mesa/agent.py
index 2f0e842d..91655784 100644
--- a/mesa/agent.py
+++ b/mesa/agent.py
@@ -11,9 +11,7 @@ from __future__ import annotations
 import contextlib
 import copy
 import operator
-import warnings
 import weakref
-from collections import defaultdict
 from collections.abc import Callable, Iterable, Iterator, MutableSet, Sequence
 from random import Random
 
@@ -52,17 +50,11 @@ class Agent:
         # register agent
         try:
             self.model.agents_[type(self)][self] = None
-        except AttributeError:
+        except AttributeError as err:
             # model super has not been called
-            self.model.agents_ = defaultdict(dict)
-            self.model.agents_[type(self)][self] = None
-            self.model.agentset_experimental_warning_given = False
-
-            warnings.warn(
-                "The Mesa Model class was not initialized. In the future, you need to explicitly initialize the Model by calling super().__init__() on initialization.",
-                FutureWarning,
-                stacklevel=2,
-            )
+            raise RuntimeError(
+                "The Mesa Model class was not initialized. You must explicitly initialize the Model by calling super().__init__() on initialization."
+            ) from err
 
     def remove(self) -> None:
         """Remove and delete the agent from the model."""
@@ -100,8 +92,6 @@ class AgentSet(MutableSet, Sequence):
         which means that agents not referenced elsewhere in the program may be automatically removed from the AgentSet.
     """
 
-    agentset_experimental_warning_given = False
-
     def __init__(self, agents: Iterable[Agent], model: Model):
         """
         Initializes the AgentSet with a collection of agents and a reference to the model.
diff --git a/mesa/space.py b/mesa/space.py
index a6d070f0..39433cb3 100644
--- a/mesa/space.py
+++ b/mesa/space.py
@@ -586,7 +586,7 @@ class PropertyLayer:
         aggregate_property(operation): Performs an aggregate operation over all cells.
     """
 
-    agentset_experimental_warning_given = False
+    propertylayer_experimental_warning_given = False
 
     def __init__(
         self, name: str, width: int, height: int, default_value, dtype=np.float64
@@ -633,14 +633,14 @@ class PropertyLayer:
 
         self.data = np.full((width, height), default_value, dtype=dtype)
 
-        if not self.__class__.agentset_experimental_warning_given:
+        if not self.__class__.propertylayer_experimental_warning_given:
             warnings.warn(
                 "The new PropertyLayer and _PropertyGrid classes experimental. It may be changed or removed in any and all future releases, including patch releases.\n"
                 "We would love to hear what you think about this new feature. If you have any thoughts, share them with us here: https://github.com/projectmesa/mesa/discussions/1932",
                 FutureWarning,
                 stacklevel=2,
             )
-            self.__class__.agentset_experimental_warning_given = True
+            self.__class__.propertylayer_experimental_warning_given = True
 
     def set_cell(self, position: Coordinate, value):
         """
diff --git a/mesa/visualization/solara_viz.py b/mesa/visualization/solara_viz.py
index 4f159884..fba73207 100644
--- a/mesa/visualization/solara_viz.py
+++ b/mesa/visualization/solara_viz.py
@@ -70,7 +70,7 @@ def Card(
                 )
             elif space_drawer:
                 # if specified, draw agent space with an alternate renderer
-                space_drawer(model, agent_portrayal)
+                space_drawer(model, agent_portrayal, dependencies=dependencies)
         elif "Measure" in layout_type:
             rv.CardTitle(children=["Measure"])
             measure = measures[layout_type["Measure"]]


Test patch:
diff --git a/tests/test_solara_viz.py b/tests/test_solara_viz.py
index f3422b87..5fef7e0b 100644
--- a/tests/test_solara_viz.py
+++ b/tests/test_solara_viz.py
@@ -136,7 +136,9 @@ def test_call_space_drawer(mocker):
             space_drawer=altspace_drawer,
         )
     )
-    altspace_drawer.assert_called_with(model, agent_portrayal)
+    altspace_drawer.assert_called_with(
+        model, agent_portrayal, dependencies=dependencies
+    )
 
 
 def test_slider():