Repository: projectmesa/mesa
Pull request #1581 (2023-01-08 17:02:08)

Make HexGrid private and create HexSingleGrid and HexMultiGrid
Made HexGrid private and created two new grid classes as discussed in the dev meeting. This is a breaking change to defer until 2.0.

codecov[bot]: # [Codecov](https://codecov.io/gh/projectmesa/mesa/pull/1581?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=projectmesa) Report
Base: **82.07**% // Head: **82.07**% // No change to project coverage :thumbsup:
> Coverage data is based on head [(`224f327`)](https://codecov.io/gh/projectmesa/mesa/pull/1581?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=projectmesa) compared to base [(`c7b2ccf`)](https://codecov.io/gh/projectmesa/mesa/commit/c7b2ccf818047b99da690493f807b21a0080df9a?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=projectmesa).
> Patch coverage: 100.00% of modified lines in pull request are covered.

<details><summary>Additional details and impacted files</summary>


```diff
@@           Coverage Diff           @@
##             main    #1581   +/-   ##
=======================================
  Coverage   82.07%   82.07%           
=======================================
  Files          18       18           
  Lines        1389     1389           
  Branches      271      234   -37     
=======================================
  Hits         1140     1140           
  Misses        205      205           
  Partials       44       44           
```


| [Impacted Files](https://codecov.io/gh/projectmesa/mesa/pull/1581?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=projectmesa) | Coverage Δ | |
|---|---|---|
| [mesa/space.py](https://codecov.io/gh/projectmesa/mesa/pull/1581?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=projectmesa#diff-bWVzYS9zcGFjZS5weQ==) | `91.18% <100.00%> (+0.02%)` | :arrow_up: |
| [mesa/visualization/ModularVisualization.py](https://codecov.io/gh/projectmesa/mesa/pull/1581?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=projectmesa#diff-bWVzYS92aXN1YWxpemF0aW9uL01vZHVsYXJWaXN1YWxpemF0aW9uLnB5) | `68.12% <0.00%> (-0.20%)` | :arrow_down: |

Help us with your feedback. Take ten seconds to tell us [how you rate us](https://about.codecov.io/nps?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=projectmesa). Have a feature suggestion? [Share it here.](https://app.codecov.io/gh/feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=projectmesa)

</details>

[:umbrella: View full report at Codecov](https://codecov.io/gh/projectmesa/mesa/pull/1581?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=projectmesa).   
:loudspeaker: Do you have feedback about the report comment? [Let us know in this issue](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=projectmesa).

jeremander: To ease backward compatibility, can you keep `HexGrid` and deprecate it?  For example, have `HexGrid` subclass `HexSingleGrid` and issue a `DeprecationWarning` upon construction?
Tortar: This seems like a good idea :+1: 
Tortar: But I have not much time to work on this now, also it should be done with care I think since if we issue it in `__init__` we will overwrite the `__init__` method in the superclass so this should be managed somehow
Tortar: Actually did it
Tortar: I don't see any merge conflict @rht , however I resolved one sometime ago 
rht: I have rebased the branch. RTD build has a failure that is unrelated to this PR
```
ImportError: urllib3 v2.0 only supports OpenSSL 1.1.1+, currently the 'ssl' module is compiled with OpenSSL 1.0.2n  7 Dec 2017. See: https://github.com/urllib3/urllib3/issues/2168
```

@EwoutH any idea about the situation?

Patch:
diff --git a/mesa/space.py b/mesa/space.py
index 165d5ed7..9dc64245 100644
--- a/mesa/space.py
+++ b/mesa/space.py
@@ -646,8 +646,8 @@ class MultiGrid(_Grid):
         )
 
 
-class HexGrid(SingleGrid):
-    """Hexagonal Grid: Extends SingleGrid to handle hexagonal neighbors.
+class _HexGrid:
+    """Hexagonal Grid which handles hexagonal neighbors.
 
     Functions according to odd-q rules.
     See http://www.redblobgames.com/grids/hexagons/#coordinates for more.
@@ -821,6 +821,55 @@ class HexGrid(SingleGrid):
         return list(self.iter_neighbors(pos, include_center, radius))
 
 
+class HexSingleGrid(_HexGrid, SingleGrid):
+    """Hexagonal SingleGrid: a SingleGrid where neighbors are computed
+    according to a hexagonal tiling of the grid.
+
+    Functions according to odd-q rules.
+    See http://www.redblobgames.com/grids/hexagons/#coordinates for more.
+
+    Properties:
+        width, height: The grid's width and height.
+        torus: Boolean which determines whether to treat the grid as a torus.
+    """
+
+
+class HexMultiGrid(_HexGrid, MultiGrid):
+    """Hexagonal MultiGrid: a MultiGrid where neighbors are computed
+    according to a hexagonal tiling of the grid.
+
+    Functions according to odd-q rules.
+    See http://www.redblobgames.com/grids/hexagons/#coordinates for more.
+
+    Properties:
+        width, height: The grid's width and height.
+        torus: Boolean which determines whether to treat the grid as a torus.
+    """
+
+
+class HexGrid(HexSingleGrid):
+    """Hexagonal Grid: a Grid where neighbors are computed
+    according to a hexagonal tiling of the grid.
+
+    Functions according to odd-q rules.
+    See http://www.redblobgames.com/grids/hexagons/#coordinates for more.
+
+    Properties:
+        width, height: The grid's width and height.
+        torus: Boolean which determines whether to treat the grid as a torus.
+    """
+
+    def __init__(self, width: int, height: int, torus: bool) -> None:
+        super().__init__(width, height, torus)
+        warn(
+            (
+                "HexGrid is being deprecated; use instead HexSingleGrid or HexMultiGrid "
+                "depending on your use case."
+            ),
+            DeprecationWarning,
+        )
+
+
 class ContinuousSpace:
     """Continuous space where each agent can have an arbitrary position.
 


Test patch:
diff --git a/tests/test_grid.py b/tests/test_grid.py
index f9eb6dbe..7b4c590d 100644
--- a/tests/test_grid.py
+++ b/tests/test_grid.py
@@ -5,7 +5,7 @@ import random
 import unittest
 from unittest.mock import Mock, patch
 
-from mesa.space import HexGrid, MultiGrid, SingleGrid
+from mesa.space import HexSingleGrid, MultiGrid, SingleGrid
 
 # Initial agent positions for testing
 #
@@ -153,7 +153,7 @@ class TestSingleGrid(unittest.TestCase):
         self.grid.move_agent(agent, (1, 0))
         assert agent.pos == (1, 0)
         # move it off the torus and check for the exception
-        if not self.torus:
+        if not self.grid.torus:
             with self.assertRaises(Exception):
                 self.grid.move_agent(agent, [-1, 1])
             with self.assertRaises(Exception):
@@ -397,7 +397,7 @@ class TestMultiGrid(unittest.TestCase):
         assert len(neighbors) == 11
 
 
-class TestHexGrid(unittest.TestCase):
+class TestHexSingleGrid(unittest.TestCase):
     """
     Testing a hexagonal singlegrid.
     """
@@ -408,7 +408,7 @@ class TestHexGrid(unittest.TestCase):
         """
         width = 3
         height = 5
-        self.grid = HexGrid(width, height, torus=False)
+        self.grid = HexSingleGrid(width, height, torus=False)
         self.agents = []
         counter = 0
         for x in range(width):
@@ -425,7 +425,6 @@ class TestHexGrid(unittest.TestCase):
         """
         Test the hexagonal neighborhood methods on the non-toroid.
         """
-
         neighborhood = self.grid.get_neighborhood((1, 1))
         assert len(neighborhood) == 6
 
@@ -452,20 +451,18 @@ class TestHexGrid(unittest.TestCase):
         assert sum(x + y for x, y in neighborhood) == 39
 
 
-class TestHexGridTorus(TestSingleGrid):
+class TestHexSingleGridTorus(TestSingleGrid):
     """
     Testing a hexagonal toroidal singlegrid.
     """
 
-    torus = True
-
     def setUp(self):
         """
         Create a test non-toroidal grid and populate it with Mock Agents
         """
         width = 3
         height = 5
-        self.grid = HexGrid(width, height, torus=True)
+        self.grid = HexSingleGrid(width, height, torus=True)
         self.agents = []
         counter = 0
         for x in range(width):
@@ -482,7 +479,6 @@ class TestHexGridTorus(TestSingleGrid):
         """
         Test the hexagonal neighborhood methods on the toroid.
         """
-
         neighborhood = self.grid.get_neighborhood((1, 1))
         assert len(neighborhood) == 6