From 4e3789cede300f5782f145e7a5727ddafbaa1789 Mon Sep 17 00:00:00 2001 From: Griatch Date: Sat, 10 May 2014 13:31:50 +0200 Subject: [PATCH] Added lazy-loading of on-model handlers. --- src/commands/cmdsethandler.py | 5 ++-- src/comms/models.py | 4 +-- src/help/models.py | 5 ++-- src/objects/models.py | 15 +++++----- src/players/models.py | 15 +++++----- src/scripts/models.py | 6 ++-- src/typeclasses/models.py | 9 +++--- src/utils/utils.py | 53 +++++++++++++++++++++++++++++++++++ 8 files changed, 83 insertions(+), 29 deletions(-) diff --git a/src/commands/cmdsethandler.py b/src/commands/cmdsethandler.py index 049b668d3a..25618d8063 100644 --- a/src/commands/cmdsethandler.py +++ b/src/commands/cmdsethandler.py @@ -157,7 +157,7 @@ class CmdSetHandler(object): will re-calculate the 'current' cmdset. """ - def __init__(self, obj): + def __init__(self, obj, init_true=True): """ This method is called whenever an object is recreated. @@ -178,7 +178,8 @@ class CmdSetHandler(object): # the subset of the cmdset_paths that are to be stored in the database self.permanent_paths = [""] - #self.update(init_mode=True) is then called from the object __init__. + if init_true: + self.update(init_mode=True) #is then called from the object __init__ def __str__(self): "Display current commands" diff --git a/src/comms/models.py b/src/comms/models.py index 39c6d18b26..431c44fc00 100644 --- a/src/comms/models.py +++ b/src/comms/models.py @@ -27,7 +27,7 @@ from src.utils.idmapper.models import SharedMemoryModel from src.comms import managers from src.comms.managers import identify_object from src.locks.lockhandler import LockHandler -from src.utils.utils import crop, make_iter +from src.utils.utils import crop, make_iter, LazyLoadHandler __all__ = ("Msg", "TempMsg", "ChannelDB") @@ -102,7 +102,7 @@ class Msg(SharedMemoryModel): def __init__(self, *args, **kwargs): SharedMemoryModel.__init__(self, *args, **kwargs) - self.locks = LockHandler(self) + _SA(self, "locks", LazyLoadHandler(self, "locks", LockHandler)) self.extra_senders = [] class Meta: diff --git a/src/help/models.py b/src/help/models.py index 287b06e7f3..187a39c7e8 100644 --- a/src/help/models.py +++ b/src/help/models.py @@ -14,6 +14,7 @@ from src.utils.idmapper.models import SharedMemoryModel from src.help.manager import HelpEntryManager from src.typeclasses.models import Tag, TagHandler from src.locks.lockhandler import LockHandler +from src.utils.utils import LazyLoadHandler __all__ = ("HelpEntry",) @@ -66,8 +67,8 @@ class HelpEntry(SharedMemoryModel): def __init__(self, *args, **kwargs): SharedMemoryModel.__init__(self, *args, **kwargs) - self.locks = LockHandler(self) - self.tags = TagHandler(self) + self.locks = LazyLoadHandler(self, "locks", LockHandler) + self.tags = LazyLoadHandler(self, "tags", TagHandler) class Meta: "Define Django meta options" diff --git a/src/objects/models.py b/src/objects/models.py index 90e7257199..9f11ffe8bf 100644 --- a/src/objects/models.py +++ b/src/objects/models.py @@ -28,7 +28,7 @@ from src.commands import cmdhandler from src.scripts.scripthandler import ScriptHandler from src.utils import logger from src.utils.utils import (make_iter, to_str, to_unicode, - variable_from_module, dbref) + variable_from_module, dbref, LazyLoadHandler) from django.utils.translation import ugettext as _ @@ -135,13 +135,12 @@ class ObjectDB(TypedObject): "Parent must be initialized first." TypedObject.__init__(self, *args, **kwargs) # handlers - _SA(self, "cmdset", CmdSetHandler(self)) - _GA(self, "cmdset").update(init_mode=True) - _SA(self, "scripts", ScriptHandler(self)) - _SA(self, "attributes", AttributeHandler(self)) - _SA(self, "nicks", NickHandler(self)) - _SA(self, "tags", TagHandler(self)) - _SA(self, "aliases", AliasHandler(self)) + _SA(self, "cmdset", LazyLoadHandler(self, "cmdset", CmdSetHandler, True)) + _SA(self, "scripts", LazyLoadHandler(self, "scripts", ScriptHandler)) + _SA(self, "attributes", LazyLoadHandler(self, "attributes", AttributeHandler)) + _SA(self, "nicks", LazyLoadHandler(self, "nicks", NickHandler)) + _SA(self, "tags", LazyLoadHandler(self, "tags", TagHandler)) + _SA(self, "aliases", LazyLoadHandler(self, "aliases", AliasHandler)) # make sure to sync the contents cache when initializing #_GA(self, "contents_update")() diff --git a/src/players/models.py b/src/players/models.py index a688c69ba9..41a2a9f857 100644 --- a/src/players/models.py +++ b/src/players/models.py @@ -29,7 +29,7 @@ from src.scripts.scripthandler import ScriptHandler from src.commands.cmdsethandler import CmdSetHandler from src.commands import cmdhandler from src.utils import utils, logger -from src.utils.utils import to_str, make_iter +from src.utils.utils import to_str, make_iter, LazyLoadHandler from django.utils.translation import ugettext as _ @@ -115,13 +115,12 @@ class PlayerDB(TypedObject, AbstractUser): "Parent must be initiated first" TypedObject.__init__(self, *args, **kwargs) # handlers - _SA(self, "cmdset", CmdSetHandler(self)) - _GA(self, "cmdset").update(init_mode=True) - _SA(self, "scripts", ScriptHandler(self)) - _SA(self, "attributes", AttributeHandler(self)) - _SA(self, "nicks", NickHandler(self)) - _SA(self, "tags", TagHandler(self)) - _SA(self, "aliases", AliasHandler(self)) + _SA(self, "cmdset", LazyLoadHandler(self, "cmdset", CmdSetHandler, True)) + _SA(self, "scripts", LazyLoadHandler(self, "scripts", ScriptHandler)) + _SA(self, "attributes", LazyLoadHandler(self, "attributes", AttributeHandler)) + _SA(self, "nicks", LazyLoadHandler(self, "nicks", NickHandler)) + _SA(self, "tags", LazyLoadHandler(self, "tags", TagHandler)) + _SA(self, "aliases", LazyLoadHandler(self, "aliases", AliasHandler)) # alias to the objs property def __characters_get(self): diff --git a/src/scripts/models.py b/src/scripts/models.py index 85e0af347d..2942d2d43c 100644 --- a/src/scripts/models.py +++ b/src/scripts/models.py @@ -29,7 +29,7 @@ from django.db import models from django.core.exceptions import ObjectDoesNotExist from src.typeclasses.models import TypedObject, TagHandler, AttributeHandler from src.scripts.manager import ScriptManager -from src.utils.utils import dbref, to_str +from src.utils.utils import dbref, to_str, LazyLoadHandler __all__ = ("ScriptDB",) _GA = object.__getattribute__ @@ -110,8 +110,8 @@ class ScriptDB(TypedObject): def __init__(self, *args, **kwargs): super(ScriptDB, self).__init__(*args, **kwargs) - _SA(self, "attributes", AttributeHandler(self)) - _SA(self, "tags", TagHandler(self)) + _SA(self, "attributes", LazyLoadHandler(self, "attributes", AttributeHandler)) + _SA(self, "tags", LazyLoadHandler(self, "tags", TagHandler)) #_SA(self, "aliases", AliasHandler(self)) diff --git a/src/typeclasses/models.py b/src/typeclasses/models.py index 81931693db..55592929a5 100644 --- a/src/typeclasses/models.py +++ b/src/typeclasses/models.py @@ -29,6 +29,7 @@ these to create custom managers. import sys import re import traceback +import weakref from django.db import models from django.conf import settings @@ -44,7 +45,7 @@ from src.server.models import ServerConfig from src.typeclasses import managers from src.locks.lockhandler import LockHandler from src.utils import logger -from src.utils.utils import make_iter, is_iter, to_str, inherits_from +from src.utils.utils import make_iter, is_iter, to_str, inherits_from, LazyLoadHandler from src.utils.dbserialize import to_pickle, from_pickle from src.utils.picklefield import PickledObjectField @@ -706,9 +707,9 @@ class TypedObject(SharedMemoryModel): super(SharedMemoryModel, self).__init__(*args, **kwargs) #SharedMemoryModel.__init__(self, *args, **kwargs) _SA(self, "dbobj", self) # this allows for self-reference - _SA(self, "locks", LockHandler(self)) - _SA(self, "permissions", PermissionHandler(self)) - _SA(self, "nattributes", NAttributeHandler(self)) + _SA(self, "locks", LazyLoadHandler(self, "locks", LockHandler)) + _SA(self, "permissions", LazyLoadHandler(self, "permissions", PermissionHandler)) + _SA(self, "nattributes", LazyLoadHandler(self, "nattributes", NAttributeHandler)) class Meta: """ diff --git a/src/utils/utils.py b/src/utils/utils.py index 2f0f1c7728..e4aa70f430 100644 --- a/src/utils/utils.py +++ b/src/utils/utils.py @@ -1028,3 +1028,56 @@ def get_evennia_pids(): if server_pid and portal_pid: return int(server_pid), int(portal_pid) return None, None + + +# lazy load handlers + +import weakref +class LazyLoadHandler(object): + """ + Load handlers only when they are actually accessed + """ + def __init__(self, obj, name, cls, *args): + """ + Set up a delayed load of a class. The 'name' must be named the + same as the variable to which the LazyLoadHandler is assigned. + """ + _SA(self, "obj", weakref.ref(obj)) + _SA(self, "name", name) + _SA(self, "cls", cls) + _SA(self, "args", args) + + def _instantiate(self): + """ + Initialize handler as cls(obj, *args) + """ + obj = _GA(self, "obj")() + instance = _GA(self, "cls")(obj, *_GA(self, "args")) + _SA(obj, _GA(self, "name"), instance) + return instance + + def __getattribute__(self, name): + """ + Access means loading the handler + """ + return getattr(_GA(self, "_instantiate")(), name) + + def __setattr__(self, name, value): + """ + Setting means loading the handler + """ + setattr(_GA(self, "_instantiate")(), name, value) + + def __delattr__(self, name): + """ + Deleting also triggers loading of handler + """ + delattr(_GA(self, "_instantiate")(), name) + + def __repr__(self): + return repr(_GA(self, "_instantiate")()) + def __str__(self): + return str(_GA(self, "_instantiate")()) + def __unicode__(self): + return str(_GA(self, "_instantiate")()) +