diff --git a/CHANGELOG.md b/CHANGELOG.md index 7dbf7f00d8..db087a6e68 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,11 @@ ## Evennia Main branch +- Feature: Support Python 3.12 (Griatch). Currently supporting 3.10,3.11 and + 3.12. Note that 3.10 support will be removed in a future release. +- Feature: Update `evennia[extra]` scipy dependency to 1.12 to support latest + Python. Note that this may change which (equivalent) path is being picked when + following an xyzgrid contrib pathfinding. - Feature: *Backwards incompatible*: `DefaultObject.get_numbered_name` now gets object's name via `.get_display_name` for better compatibility with recog systems. - Feature: *Backwards incompatible*: Removed the (#dbref) display from diff --git a/evennia/VERSION_REQS.txt b/evennia/VERSION_REQS.txt index b7f535cd4f..e2a6dec300 100644 --- a/evennia/VERSION_REQS.txt +++ b/evennia/VERSION_REQS.txt @@ -4,7 +4,7 @@ # `value = number` and only specific names supported by the handler. PYTHON_MIN = 3.10 -PYTHON_MAX_TESTED = 3.11.100 +PYTHON_MAX_TESTED = 3.12.100 TWISTED_MIN = 23.10 DJANGO_MIN = 4.0.2 DJANGO_MAX_TESTED = 4.2.100 diff --git a/evennia/contrib/base_systems/components/tests.py b/evennia/contrib/base_systems/components/tests.py index 43a1c5c666..b11ce68937 100644 --- a/evennia/contrib/base_systems/components/tests.py +++ b/evennia/contrib/base_systems/components/tests.py @@ -98,28 +98,28 @@ class TestComponents(EvenniaTest): self.assertIsInstance(self.char1.test_b, ComponentTestB) def test_character_assigns_default_value(self): - self.assertEquals(self.char1.test_a.my_int, 1) - self.assertEquals(self.char1.test_a.my_list, []) + self.assertEqual(self.char1.test_a.my_int, 1) + self.assertEqual(self.char1.test_a.my_list, []) def test_character_assigns_default_provided_values(self): - self.assertEquals(self.char1.test_b.my_int, 3) - self.assertEquals(self.char1.test_b.my_list, [1, 2, 3]) + self.assertEqual(self.char1.test_b.my_int, 3) + self.assertEqual(self.char1.test_b.my_list, [1, 2, 3]) def test_character_has_autocreated_values(self): att_name = "test_b::my_list" - self.assertEquals(self.char1.attributes.get(att_name), [1, 2, 3]) + self.assertEqual(self.char1.attributes.get(att_name), [1, 2, 3]) def test_component_inheritance_properly_overrides_slots(self): - self.assertEquals(self.char1.ic_a.name, "inherited_test_a") + self.assertEqual(self.char1.ic_a.name, "inherited_test_a") component_names = set(c[0] for c in self.char1._get_class_components()) self.assertNotIn("shadowed_test_a", component_names) def test_component_inheritance_assigns_proper_values(self): - self.assertEquals(self.char1.ic_a.my_int, 1) - self.assertEquals(self.char1.ic_a.my_other_int, 4) + self.assertEqual(self.char1.ic_a.my_int, 1) + self.assertEqual(self.char1.ic_a.my_other_int, 4) def test_host_mixins_assigns_components(self): - self.assertEquals(self.char1.test_d.mixed_in, 8) + self.assertEqual(self.char1.test_d.mixed_in, 8) def test_character_can_register_runtime_component(self): rct = RuntimeComponentTestC.create(self.char1) @@ -127,15 +127,15 @@ class TestComponents(EvenniaTest): test_c = self.char1.components.get("test_c") self.assertTrue(test_c) - self.assertEquals(test_c.my_int, 6) - self.assertEquals(test_c.my_dict, {}) + self.assertEqual(test_c.my_int, 6) + self.assertEqual(test_c.my_dict, {}) def test_handler_can_add_default_component(self): self.char1.components.add_default("test_c") test_c = self.char1.components.get("test_c") self.assertTrue(test_c) - self.assertEquals(test_c.my_int, 6) + self.assertEqual(test_c.my_int, 6) def test_handler_has_returns_true_for_any_components(self): rct = RuntimeComponentTestC.create(self.char1) @@ -199,7 +199,7 @@ class TestComponents(EvenniaTest): self.assertTrue(self.char1.tags.has(key="test_c", category="components")) self.assertTrue(self.char1.tags.has(key="added_value", category="test_c::added_tag")) - self.assertEquals(test_c.added_tag, "added_value") + self.assertEqual(test_c.added_tag, "added_value") def test_host_has_added_default_component_tags(self): self.char1.components.add_default("test_c") @@ -207,7 +207,7 @@ class TestComponents(EvenniaTest): self.assertTrue(self.char1.tags.has(key="test_c", category="components")) self.assertTrue(self.char1.tags.has(key="added_value", category="test_c::added_tag")) - self.assertEquals(test_c.added_tag, "added_value") + self.assertEqual(test_c.added_tag, "added_value") def test_host_remove_component_tags(self): rct = RuntimeComponentTestC.create(self.char1) @@ -235,7 +235,7 @@ class TestComponents(EvenniaTest): test_b.single_tag = "second value" self.assertTrue(self.char1.tags.has(key="second value", category="test_b::single_tag")) - self.assertEquals(test_b.single_tag, "second value") + self.assertEqual(test_b.single_tag, "second value") self.assertFalse(self.char1.tags.has(key="first_value", category="test_b::single_tag")) def test_component_tags_default_value_is_overridden_when_enforce_single(self): @@ -268,11 +268,11 @@ class TestComponents(EvenniaTest): def test_mutables_are_not_shared_when_autocreate(self): self.char1.test_a.my_list.append(1) - self.assertNotEquals(self.char1.test_a.my_list, self.char2.test_a.my_list) + self.assertNotEqual(self.char1.test_a.my_list, self.char2.test_a.my_list) def test_replacing_class_component_slot_with_runtime_component(self): self.char1.components.add_default("replacement_inherited_test_a") - self.assertEquals(self.char1.ic_a.replacement_field, 6) + self.assertEqual(self.char1.ic_a.replacement_field, 6) class CharWithSignal(ComponentHolderMixin, DefaultCharacter): diff --git a/evennia/contrib/grid/xyzgrid/tests.py b/evennia/contrib/grid/xyzgrid/tests.py index 28e06cfe73..a3cd7441d1 100644 --- a/evennia/contrib/grid/xyzgrid/tests.py +++ b/evennia/contrib/grid/xyzgrid/tests.py @@ -7,10 +7,10 @@ from random import randint from unittest import mock from django.test import TestCase +from evennia.utils.test_resources import (BaseEvenniaCommandTest, + BaseEvenniaTest) from parameterized import parameterized -from evennia.utils.test_resources import BaseEvenniaCommandTest, BaseEvenniaTest - from . import commands, xymap, xymap_legend, xyzgrid, xyzroom MAP1 = """ @@ -676,14 +676,14 @@ class TestMap3(_MapTest): ((0, 0), (1, 0), ()), # no node at (1, 0)! ((2, 0), (5, 0), ("e", "e")), # straight path ((0, 0), (1, 1), ("ne",)), - ((4, 1), (4, 3), ("nw", "ne")), - ((4, 1), (4, 3), ("nw", "ne")), + ((4, 1), (4, 3), ("ne", "nw")), + ((4, 1), (4, 3), ("ne", "nw")), ((2, 2), (3, 5), ("nw", "ne")), - ((2, 2), (1, 5), ("nw", "n", "n")), - ((5, 5), (0, 0), ("sw", "s", "sw", "w", "sw", "sw")), - ((5, 5), (0, 0), ("sw", "s", "sw", "w", "sw", "sw")), + ((2, 2), (1, 5), ("nw", "ne", "w")), + ((5, 5), (0, 0), ("sw", "nw", "sw", "s", "s", "sw")), + ((5, 5), (0, 0), ("sw", "nw", "sw", "s", "s", "sw")), ((5, 2), (1, 2), ("sw", "nw", "w", "nw", "s")), - ((4, 1), (1, 1), ("s", "w", "nw")), + ((4, 1), (1, 1), ("nw", "w", "sw")), ] ) def test_shortest_path(self, startcoord, endcoord, expected_directions): @@ -915,7 +915,7 @@ class TestMap8(_MapTest): ((5, 1), (0, 3), ("w", "w", "n", "w")), ((1, 1), (2, 2), ("n", "w", "s")), ((5, 3), (5, 3), ()), - ((5, 3), (0, 4), ("s", "n", "w", "n")), + ((5, 3), (0, 4), ("s", "n", "n", "w")), ((1, 4), (3, 3), ("e", "w", "e")), ] ) diff --git a/evennia/contrib/grid/xyzgrid/xymap.py b/evennia/contrib/grid/xyzgrid/xymap.py index 25e89ffdc5..41135b52ba 100644 --- a/evennia/contrib/grid/xyzgrid/xymap.py +++ b/evennia/contrib/grid/xyzgrid/xymap.py @@ -99,7 +99,7 @@ from os.path import isdir, isfile from os.path import join as pathjoin try: - from scipy import zeros + from numpy import zeros from scipy.sparse import csr_matrix from scipy.sparse.csgraph import dijkstra except ImportError as err: @@ -108,7 +108,6 @@ except ImportError as err: "the SciPy package. Install with `pip install scipy'." ) from django.conf import settings - from evennia.prototypes import prototypes as protlib from evennia.prototypes.spawner import flatten_prototype from evennia.utils import logger @@ -669,7 +668,8 @@ class XYMap: """ global _XYZROOMCLASS if not _XYZROOMCLASS: - from evennia.contrib.grid.xyzgrid.xyzroom import XYZRoom as _XYZROOMCLASS + from evennia.contrib.grid.xyzgrid.xyzroom import \ + XYZRoom as _XYZROOMCLASS x, y = xy wildcard = "*" spawned = [] diff --git a/evennia/contrib/grid/xyzgrid/xymap_legend.py b/evennia/contrib/grid/xyzgrid/xymap_legend.py index a898bfe63c..1a42fc3eb4 100644 --- a/evennia/contrib/grid/xyzgrid/xymap_legend.py +++ b/evennia/contrib/grid/xyzgrid/xymap_legend.py @@ -10,7 +10,7 @@ usually shows as an Exit, but the length of the link has no in-game equivalent. """ try: - from scipy import zeros + from numpy import zeros except ImportError as err: raise ImportError( f"{err}\nThe XYZgrid contrib requires the SciPy package. Install with `pip install scipy'." @@ -20,11 +20,11 @@ import uuid from collections import defaultdict from django.core import exceptions as django_exceptions - from evennia.prototypes import spawner from evennia.utils.utils import class_from_module -from .utils import BIGVAL, MAPSCAN, REVERSE_DIRECTIONS, MapError, MapParserError +from .utils import (BIGVAL, MAPSCAN, REVERSE_DIRECTIONS, MapError, + MapParserError) NodeTypeclass = None ExitTypeclass = None diff --git a/evennia/scripts/tests.py b/evennia/scripts/tests.py index 46d514caba..6d251eed54 100644 --- a/evennia/scripts/tests.py +++ b/evennia/scripts/tests.py @@ -244,7 +244,7 @@ class TestMonitorHandler(TestCase): """Add an object to the monitor handler and then remove it""" self.handler.add(obj, fieldname, callback, idstring=idstring) self.handler.remove(obj, fieldname, idstring=idstring) - self.assertEquals(self.handler.monitors[obj][fieldname], {}) + self.assertEqual(self.handler.monitors[obj][fieldname], {}) def test_add_with_invalid_function(self): obj = mock.Mock() @@ -266,7 +266,7 @@ class TestMonitorHandler(TestCase): self.handler.add(obj[1], fieldname[1], callback, idstring=idstring[1], persistent=True) output = self.handler.all() - self.assertEquals( + self.assertEqual( output, [ (obj[0], fieldname[0], idstring[0], False, {}), @@ -286,7 +286,7 @@ class TestMonitorHandler(TestCase): self.handler.clear() self.assertNotIn(obj, self.handler.monitors) - self.assertEquals(defaultdict(lambda: defaultdict(dict)), self.handler.monitors) + self.assertEqual(defaultdict(lambda: defaultdict(dict)), self.handler.monitors) def test_add_remove_attribute(self): """Tests that adding and removing an object attribute to the monitor handler works correctly""" @@ -309,7 +309,7 @@ class TestMonitorHandler(TestCase): """Remove attribute from the handler and assert that it is gone""" self.handler.remove(obj, fieldname, idstring=idstring, category=category) - self.assertEquals(self.handler.monitors[index][name], {}) + self.assertEqual(self.handler.monitors[index][name], {}) class TestOnDemandTask(EvenniaTest): @@ -643,7 +643,7 @@ class TestOnDemandHandler(EvenniaTest): self.handler.set_dt("rose", "flower", 100) self.handler.set_dt("daffodil", "flower", 150) - self.assertEquals( + self.assertEqual( [task.start_time for task in self.handler.tasks.values()], [START_TIME - 100, START_TIME - 150], ) @@ -667,7 +667,7 @@ class TestOnDemandHandler(EvenniaTest): self.handler.set_stage("rose", "flower", "bud") self.handler.set_stage("daffodil", "flower", "wilted") - self.assertEquals( + self.assertEqual( [task.start_time for task in self.handler.tasks.values()], [START_TIME - 100, START_TIME - 150], ) diff --git a/evennia/utils/idmapper/tests.py b/evennia/utils/idmapper/tests.py index 2703256616..d6674817d2 100644 --- a/evennia/utils/idmapper/tests.py +++ b/evennia/utils/idmapper/tests.py @@ -65,7 +65,7 @@ class SharedMemorysTest(TestCase): # article_list = Article.objects.all().select_related('category') # last_article = article_list[0] # for article in article_list[1:]: - # self.assertEquals(article.category2 is last_article.category2, False) + # self.assertEqual(article.category2 is last_article.category2, False) # last_article = article def testObjectDeletion(self): diff --git a/evennia/web/api/tests.py b/evennia/web/api/tests.py index ab2b050444..4af37b2603 100644 --- a/evennia/web/api/tests.py +++ b/evennia/web/api/tests.py @@ -181,9 +181,9 @@ class TestEvenniaRESTApi(BaseEvenniaTest): attr_data = {"db_key": attr_name, "db_value": "test_value"} response = self.client.post(view_url, data=attr_data) self.assertEqual(response.status_code, 200, f"Response was: {response.data}") - self.assertEquals(view.obj.attributes.get(attr_name), "test_value") + self.assertEqual(view.obj.attributes.get(attr_name), "test_value") # now test removing it attr_data = {"db_key": attr_name} response = self.client.post(view_url, data=attr_data) self.assertEqual(response.status_code, 200, f"Response was: {response.data}") - self.assertEquals(view.obj.attributes.get(attr_name), None) + self.assertEqual(view.obj.attributes.get(attr_name), None) diff --git a/pyproject.toml b/pyproject.toml index a1147b8def..011269cab5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -112,7 +112,7 @@ extra = [ "django-extensions >= 3.1.0", # xyzroom contrib - "scipy == 1.9.3", + "scipy == 1.12.0", # Git contrib "gitpython >= 3.1.27",