Added check to location setter that makes sure to stop a location-loop forming. This closes #454.
This commit is contained in:
parent
471e1bbf9b
commit
393a3e5e73
2 changed files with 54 additions and 2 deletions
|
|
@ -17,6 +17,7 @@ transparently through the decorating TypeClass.
|
||||||
import traceback
|
import traceback
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
from django.core.exceptions import ObjectDoesNotExist
|
||||||
|
|
||||||
from src.typeclasses.models import (TypedObject, TagHandler, NickHandler,
|
from src.typeclasses.models import (TypedObject, TagHandler, NickHandler,
|
||||||
AliasHandler, AttributeHandler)
|
AliasHandler, AttributeHandler)
|
||||||
|
|
@ -26,7 +27,8 @@ from src.commands.cmdsethandler import CmdSetHandler
|
||||||
from src.commands import cmdhandler
|
from src.commands import cmdhandler
|
||||||
from src.scripts.scripthandler import ScriptHandler
|
from src.scripts.scripthandler import ScriptHandler
|
||||||
from src.utils import logger
|
from src.utils import logger
|
||||||
from src.utils.utils import make_iter, to_str, to_unicode, variable_from_module
|
from src.utils.utils import (make_iter, to_str, to_unicode,
|
||||||
|
variable_from_module, dbref)
|
||||||
|
|
||||||
from django.utils.translation import ugettext as _
|
from django.utils.translation import ugettext as _
|
||||||
|
|
||||||
|
|
@ -180,6 +182,56 @@ class ObjectDB(TypedObject):
|
||||||
_GA(self, "save")()
|
_GA(self, "save")()
|
||||||
cmdset_storage = property(__cmdset_storage_get, __cmdset_storage_set, __cmdset_storage_del)
|
cmdset_storage = property(__cmdset_storage_get, __cmdset_storage_set, __cmdset_storage_del)
|
||||||
|
|
||||||
|
# location getsetter
|
||||||
|
def __location_get(self):
|
||||||
|
"Get location"
|
||||||
|
loc = _GA(_GA(self, "dbobj"), "db_location")
|
||||||
|
return _GA(loc, "typeclass") if loc else loc
|
||||||
|
|
||||||
|
def __location_set(self, location):
|
||||||
|
"Set location, checking for loops and allowing dbref"
|
||||||
|
if isinstance(location, (basestring, int)):
|
||||||
|
# allow setting of #dbref
|
||||||
|
dbid = dbref(location, reqhash=False)
|
||||||
|
if dbid:
|
||||||
|
try:
|
||||||
|
location = ObjectDB.objects.get(id=dbid)
|
||||||
|
except ObjectDoesNotExist:
|
||||||
|
# maybe it is just a name that happens to look like a dbid
|
||||||
|
pass
|
||||||
|
try:
|
||||||
|
def is_loc_loop(loc, depth=0):
|
||||||
|
"Recursively traverse target location, trying to catch a loop."
|
||||||
|
if depth > 10:
|
||||||
|
return
|
||||||
|
elif loc == self:
|
||||||
|
raise RuntimeError
|
||||||
|
elif loc == None:
|
||||||
|
raise RuntimeWarning
|
||||||
|
return is_loc_loop(_GA(_GA(loc, "dbobj"), "db_location"), depth + 1)
|
||||||
|
try:
|
||||||
|
is_loc_loop(location)
|
||||||
|
except RuntimeWarning:
|
||||||
|
pass
|
||||||
|
# actually set the field
|
||||||
|
_SA(_GA(self, "dbobj"), "db_location", _GA(location, "dbobj") if location else location)
|
||||||
|
_GA(_GA(self, "dbobj"), "save")(update_fields=["db_location"])
|
||||||
|
except RuntimeError:
|
||||||
|
errmsg = "Error: %s.location = %s creates a location loop." % (self.key, location)
|
||||||
|
logger.log_errmsg(errmsg)
|
||||||
|
raise RuntimeError(errmsg)
|
||||||
|
except Exception, e:
|
||||||
|
errmsg = "Error (%s): %s is not a valid location." % (str(e), location)
|
||||||
|
logger.log_errmsg(errmsg)
|
||||||
|
raise Exception(errmsg)
|
||||||
|
|
||||||
|
def __location_del(self):
|
||||||
|
"Cleably delete the location reference"
|
||||||
|
_SA(_GA(self, "dbobj"), "db_location", None)
|
||||||
|
_GA(_GA(self, "dbobj"), "save")(upate_fields=["db_location"])
|
||||||
|
location = property(__location_get, __location_set, __location_del)
|
||||||
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
"Define Django meta options"
|
"Define Django meta options"
|
||||||
verbose_name = "Object"
|
verbose_name = "Object"
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
Django ID mapper
|
Django ID mapper
|
||||||
|
|
||||||
Modified for Evennia by making sure that no model references
|
Modified for Evennia by making sure that no model references
|
||||||
leave caching unexpectedly (no use if WeakRefs).
|
leave caching unexpectedly (no use of WeakRefs).
|
||||||
|
|
||||||
Also adds cache_size() for monitoring the size of the cache.
|
Also adds cache_size() for monitoring the size of the cache.
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue