Make sure Typeclass.at_init() is always called on cache initialization for any typeclass. Resolve #2641

This commit is contained in:
Griatch 2022-02-07 20:45:48 +01:00
parent a427594f25
commit 5e2372f79d
6 changed files with 27 additions and 8 deletions

View file

@ -157,8 +157,6 @@ class ScriptDB(TypedObject):
# deprecated ...
pass
if isinstance(value, (str, int)):
from evennia.objects.models import ObjectDB
value = to_str(value)
if value.isdigit() or value.startswith("#"):
dbid = dbref(value, reqhash=False)

View file

@ -473,6 +473,14 @@ class ScriptBase(ScriptDB, metaclass=TypeclassBase):
super().delete()
return True
def at_init(self):
"""
Called when the Script is cached in the idmapper. This is usually more reliable
than overriding `__init__` since the latter can be called at unexpected times.
"""
pass
def at_script_creation(self):
"""
Should be overridden in child.

View file

@ -11,9 +11,11 @@ from evennia.scripts.scripts import DoNothing, ExtendedLoopingCall
class TestScript(BaseEvenniaTest):
def test_create(self):
"Check the script can be created via the convenience method."
obj, errors = DefaultScript.create("useless-machine")
self.assertTrue(obj, errors)
self.assertFalse(errors, errors)
with mock.patch("evennia.scripts.scripts.DefaultScript.at_init") as mockinit:
obj, errors = DefaultScript.create("useless-machine")
self.assertTrue(obj, errors)
self.assertFalse(errors, errors)
mockinit.assert_called()
class TestScriptDB(TestCase):

View file

@ -395,7 +395,7 @@ class Evennia:
mode (str): One of shutdown, reload or reset
"""
from evennia.objects.models import ObjectDB
from evennia.typeclasses.models import TypedObject
# start server time and maintenance task
self.maintenance_task = LoopingCall(_server_maintenance)
@ -404,8 +404,10 @@ class Evennia:
# update eventual changed defaults
self.update_defaults()
[o.at_init() for o in ObjectDB.get_all_cached_instances()]
[p.at_init() for p in AccountDB.get_all_cached_instances()]
# run at_init() on all cached entities on reconnect
[[entity.at_init()
for entity in typeclass_db.get_all_cached_instances()]
for typeclass_db in TypedObject.__subclasses__()]
# call correct server hook based on start file value
if mode == "reload":

View file

@ -485,6 +485,14 @@ class TypedObject(SharedMemoryModel):
# Object manipulation methods
#
def at_init(self):
"""
Called when this object is loaded into cache. This is more reliable
than to override `__init__`.
"""
pass
@classmethod
def search(cls, query, **kwargs):
"""

View file

@ -313,6 +313,7 @@ class SharedMemoryModel(Model, metaclass=SharedMemoryModelBase):
"""
pk = instance._get_pk_val()
if pk is not None:
new = new or pk not in cls.__dbclass__.__instance_cache__
cls.__dbclass__.__instance_cache__[pk] = instance
if new:
try: