Support Python 3.12. Update optional scipy req to 1.12.0

This commit is contained in:
Griatch 2024-03-17 00:53:28 +01:00
parent abb83fc4d8
commit 11834dfe49
10 changed files with 48 additions and 43 deletions

View file

@ -2,6 +2,11 @@
## Evennia Main branch ## 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 - Feature: *Backwards incompatible*: `DefaultObject.get_numbered_name` now gets object's
name via `.get_display_name` for better compatibility with recog systems. name via `.get_display_name` for better compatibility with recog systems.
- Feature: *Backwards incompatible*: Removed the (#dbref) display from - Feature: *Backwards incompatible*: Removed the (#dbref) display from

View file

@ -4,7 +4,7 @@
# `value = number` and only specific names supported by the handler. # `value = number` and only specific names supported by the handler.
PYTHON_MIN = 3.10 PYTHON_MIN = 3.10
PYTHON_MAX_TESTED = 3.11.100 PYTHON_MAX_TESTED = 3.12.100
TWISTED_MIN = 23.10 TWISTED_MIN = 23.10
DJANGO_MIN = 4.0.2 DJANGO_MIN = 4.0.2
DJANGO_MAX_TESTED = 4.2.100 DJANGO_MAX_TESTED = 4.2.100

View file

@ -98,28 +98,28 @@ class TestComponents(EvenniaTest):
self.assertIsInstance(self.char1.test_b, ComponentTestB) self.assertIsInstance(self.char1.test_b, ComponentTestB)
def test_character_assigns_default_value(self): def test_character_assigns_default_value(self):
self.assertEquals(self.char1.test_a.my_int, 1) self.assertEqual(self.char1.test_a.my_int, 1)
self.assertEquals(self.char1.test_a.my_list, []) self.assertEqual(self.char1.test_a.my_list, [])
def test_character_assigns_default_provided_values(self): def test_character_assigns_default_provided_values(self):
self.assertEquals(self.char1.test_b.my_int, 3) self.assertEqual(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_list, [1, 2, 3])
def test_character_has_autocreated_values(self): def test_character_has_autocreated_values(self):
att_name = "test_b::my_list" 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): 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()) component_names = set(c[0] for c in self.char1._get_class_components())
self.assertNotIn("shadowed_test_a", component_names) self.assertNotIn("shadowed_test_a", component_names)
def test_component_inheritance_assigns_proper_values(self): def test_component_inheritance_assigns_proper_values(self):
self.assertEquals(self.char1.ic_a.my_int, 1) self.assertEqual(self.char1.ic_a.my_int, 1)
self.assertEquals(self.char1.ic_a.my_other_int, 4) self.assertEqual(self.char1.ic_a.my_other_int, 4)
def test_host_mixins_assigns_components(self): 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): def test_character_can_register_runtime_component(self):
rct = RuntimeComponentTestC.create(self.char1) rct = RuntimeComponentTestC.create(self.char1)
@ -127,15 +127,15 @@ class TestComponents(EvenniaTest):
test_c = self.char1.components.get("test_c") test_c = self.char1.components.get("test_c")
self.assertTrue(test_c) self.assertTrue(test_c)
self.assertEquals(test_c.my_int, 6) self.assertEqual(test_c.my_int, 6)
self.assertEquals(test_c.my_dict, {}) self.assertEqual(test_c.my_dict, {})
def test_handler_can_add_default_component(self): def test_handler_can_add_default_component(self):
self.char1.components.add_default("test_c") self.char1.components.add_default("test_c")
test_c = self.char1.components.get("test_c") test_c = self.char1.components.get("test_c")
self.assertTrue(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): def test_handler_has_returns_true_for_any_components(self):
rct = RuntimeComponentTestC.create(self.char1) 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="test_c", category="components"))
self.assertTrue(self.char1.tags.has(key="added_value", category="test_c::added_tag")) 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): def test_host_has_added_default_component_tags(self):
self.char1.components.add_default("test_c") 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="test_c", category="components"))
self.assertTrue(self.char1.tags.has(key="added_value", category="test_c::added_tag")) 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): def test_host_remove_component_tags(self):
rct = RuntimeComponentTestC.create(self.char1) rct = RuntimeComponentTestC.create(self.char1)
@ -235,7 +235,7 @@ class TestComponents(EvenniaTest):
test_b.single_tag = "second value" test_b.single_tag = "second value"
self.assertTrue(self.char1.tags.has(key="second value", category="test_b::single_tag")) 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")) 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): 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): def test_mutables_are_not_shared_when_autocreate(self):
self.char1.test_a.my_list.append(1) 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): def test_replacing_class_component_slot_with_runtime_component(self):
self.char1.components.add_default("replacement_inherited_test_a") 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): class CharWithSignal(ComponentHolderMixin, DefaultCharacter):

View file

@ -7,10 +7,10 @@ from random import randint
from unittest import mock from unittest import mock
from django.test import TestCase from django.test import TestCase
from evennia.utils.test_resources import (BaseEvenniaCommandTest,
BaseEvenniaTest)
from parameterized import parameterized from parameterized import parameterized
from evennia.utils.test_resources import BaseEvenniaCommandTest, BaseEvenniaTest
from . import commands, xymap, xymap_legend, xyzgrid, xyzroom from . import commands, xymap, xymap_legend, xyzgrid, xyzroom
MAP1 = """ MAP1 = """
@ -676,14 +676,14 @@ class TestMap3(_MapTest):
((0, 0), (1, 0), ()), # no node at (1, 0)! ((0, 0), (1, 0), ()), # no node at (1, 0)!
((2, 0), (5, 0), ("e", "e")), # straight path ((2, 0), (5, 0), ("e", "e")), # straight path
((0, 0), (1, 1), ("ne",)), ((0, 0), (1, 1), ("ne",)),
((4, 1), (4, 3), ("nw", "ne")), ((4, 1), (4, 3), ("ne", "nw")),
((4, 1), (4, 3), ("nw", "ne")), ((4, 1), (4, 3), ("ne", "nw")),
((2, 2), (3, 5), ("nw", "ne")), ((2, 2), (3, 5), ("nw", "ne")),
((2, 2), (1, 5), ("nw", "n", "n")), ((2, 2), (1, 5), ("nw", "ne", "w")),
((5, 5), (0, 0), ("sw", "s", "sw", "w", "sw", "sw")), ((5, 5), (0, 0), ("sw", "nw", "sw", "s", "s", "sw")),
((5, 5), (0, 0), ("sw", "s", "sw", "w", "sw", "sw")), ((5, 5), (0, 0), ("sw", "nw", "sw", "s", "s", "sw")),
((5, 2), (1, 2), ("sw", "nw", "w", "nw", "s")), ((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): def test_shortest_path(self, startcoord, endcoord, expected_directions):
@ -915,7 +915,7 @@ class TestMap8(_MapTest):
((5, 1), (0, 3), ("w", "w", "n", "w")), ((5, 1), (0, 3), ("w", "w", "n", "w")),
((1, 1), (2, 2), ("n", "w", "s")), ((1, 1), (2, 2), ("n", "w", "s")),
((5, 3), (5, 3), ()), ((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")), ((1, 4), (3, 3), ("e", "w", "e")),
] ]
) )

View file

@ -99,7 +99,7 @@ from os.path import isdir, isfile
from os.path import join as pathjoin from os.path import join as pathjoin
try: try:
from scipy import zeros from numpy import zeros
from scipy.sparse import csr_matrix from scipy.sparse import csr_matrix
from scipy.sparse.csgraph import dijkstra from scipy.sparse.csgraph import dijkstra
except ImportError as err: except ImportError as err:
@ -108,7 +108,6 @@ except ImportError as err:
"the SciPy package. Install with `pip install scipy'." "the SciPy package. Install with `pip install scipy'."
) )
from django.conf import settings from django.conf import settings
from evennia.prototypes import prototypes as protlib from evennia.prototypes import prototypes as protlib
from evennia.prototypes.spawner import flatten_prototype from evennia.prototypes.spawner import flatten_prototype
from evennia.utils import logger from evennia.utils import logger
@ -669,7 +668,8 @@ class XYMap:
""" """
global _XYZROOMCLASS global _XYZROOMCLASS
if not _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 x, y = xy
wildcard = "*" wildcard = "*"
spawned = [] spawned = []

View file

@ -10,7 +10,7 @@ usually shows as an Exit, but the length of the link has no in-game equivalent.
""" """
try: try:
from scipy import zeros from numpy import zeros
except ImportError as err: except ImportError as err:
raise ImportError( raise ImportError(
f"{err}\nThe XYZgrid contrib requires the SciPy package. Install with `pip install scipy'." 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 collections import defaultdict
from django.core import exceptions as django_exceptions from django.core import exceptions as django_exceptions
from evennia.prototypes import spawner from evennia.prototypes import spawner
from evennia.utils.utils import class_from_module 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 NodeTypeclass = None
ExitTypeclass = None ExitTypeclass = None

View file

@ -244,7 +244,7 @@ class TestMonitorHandler(TestCase):
"""Add an object to the monitor handler and then remove it""" """Add an object to the monitor handler and then remove it"""
self.handler.add(obj, fieldname, callback, idstring=idstring) self.handler.add(obj, fieldname, callback, idstring=idstring)
self.handler.remove(obj, fieldname, 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): def test_add_with_invalid_function(self):
obj = mock.Mock() obj = mock.Mock()
@ -266,7 +266,7 @@ class TestMonitorHandler(TestCase):
self.handler.add(obj[1], fieldname[1], callback, idstring=idstring[1], persistent=True) self.handler.add(obj[1], fieldname[1], callback, idstring=idstring[1], persistent=True)
output = self.handler.all() output = self.handler.all()
self.assertEquals( self.assertEqual(
output, output,
[ [
(obj[0], fieldname[0], idstring[0], False, {}), (obj[0], fieldname[0], idstring[0], False, {}),
@ -286,7 +286,7 @@ class TestMonitorHandler(TestCase):
self.handler.clear() self.handler.clear()
self.assertNotIn(obj, self.handler.monitors) 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): def test_add_remove_attribute(self):
"""Tests that adding and removing an object attribute to the monitor handler works correctly""" """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""" """Remove attribute from the handler and assert that it is gone"""
self.handler.remove(obj, fieldname, idstring=idstring, category=category) 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): class TestOnDemandTask(EvenniaTest):
@ -643,7 +643,7 @@ class TestOnDemandHandler(EvenniaTest):
self.handler.set_dt("rose", "flower", 100) self.handler.set_dt("rose", "flower", 100)
self.handler.set_dt("daffodil", "flower", 150) self.handler.set_dt("daffodil", "flower", 150)
self.assertEquals( self.assertEqual(
[task.start_time for task in self.handler.tasks.values()], [task.start_time for task in self.handler.tasks.values()],
[START_TIME - 100, START_TIME - 150], [START_TIME - 100, START_TIME - 150],
) )
@ -667,7 +667,7 @@ class TestOnDemandHandler(EvenniaTest):
self.handler.set_stage("rose", "flower", "bud") self.handler.set_stage("rose", "flower", "bud")
self.handler.set_stage("daffodil", "flower", "wilted") self.handler.set_stage("daffodil", "flower", "wilted")
self.assertEquals( self.assertEqual(
[task.start_time for task in self.handler.tasks.values()], [task.start_time for task in self.handler.tasks.values()],
[START_TIME - 100, START_TIME - 150], [START_TIME - 100, START_TIME - 150],
) )

View file

@ -65,7 +65,7 @@ class SharedMemorysTest(TestCase):
# article_list = Article.objects.all().select_related('category') # article_list = Article.objects.all().select_related('category')
# last_article = article_list[0] # last_article = article_list[0]
# for article in article_list[1:]: # 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 # last_article = article
def testObjectDeletion(self): def testObjectDeletion(self):

View file

@ -181,9 +181,9 @@ class TestEvenniaRESTApi(BaseEvenniaTest):
attr_data = {"db_key": attr_name, "db_value": "test_value"} attr_data = {"db_key": attr_name, "db_value": "test_value"}
response = self.client.post(view_url, data=attr_data) response = self.client.post(view_url, data=attr_data)
self.assertEqual(response.status_code, 200, f"Response was: {response.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 # now test removing it
attr_data = {"db_key": attr_name} attr_data = {"db_key": attr_name}
response = self.client.post(view_url, data=attr_data) response = self.client.post(view_url, data=attr_data)
self.assertEqual(response.status_code, 200, f"Response was: {response.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)

View file

@ -112,7 +112,7 @@ extra = [
"django-extensions >= 3.1.0", "django-extensions >= 3.1.0",
# xyzroom contrib # xyzroom contrib
"scipy == 1.9.3", "scipy == 1.12.0",
# Git contrib # Git contrib
"gitpython >= 3.1.27", "gitpython >= 3.1.27",