From 4830560ac5439e1091a1902c02658458795e03c5 Mon Sep 17 00:00:00 2001 From: Griatch Date: Sun, 14 Oct 2012 19:29:56 +0200 Subject: [PATCH] Added better error checking for when trying to set an attribute on an object stored in an attribute but which after retrieved and cached was deleted. The fix doesn't fully fix the problem of stale caching but does give more information. Related to Issue 295. Also fixed a curiously phrased import. --- src/objects/objects.py | 4 ++-- src/typeclasses/models.py | 13 +++++++++++-- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/objects/objects.py b/src/objects/objects.py index 10bddd7896..98e106891a 100644 --- a/src/objects/objects.py +++ b/src/objects/objects.py @@ -15,6 +15,7 @@ That an object is controlled by a player/user is just defined by its they control by simply linking to a new object's user property. """ +from django.conf import settings from src.typeclasses.typeclass import TypeClass from src.commands import cmdset, command __all__ = ("Object", "Character", "Room", "Exit") @@ -728,8 +729,7 @@ class Character(Object): self.locks.add(";".join(["get:false()", # noone can pick up the character "call:false()"])) # no commands can be called on character from outside # add the default cmdset - from settings import CMDSET_DEFAULT - self.cmdset.add_default(CMDSET_DEFAULT, permanent=True) + self.cmdset.add_default(settings.CMDSET_DEFAULT, permanent=True) # no other character should be able to call commands on the Character. self.cmdset.outside_access = False diff --git a/src/typeclasses/models.py b/src/typeclasses/models.py index 3cb3f5415a..baf87265f5 100644 --- a/src/typeclasses/models.py +++ b/src/typeclasses/models.py @@ -34,7 +34,7 @@ except ImportError: import traceback from collections import defaultdict -from django.db import models +from django.db import models, IntegrityError from django.conf import settings from django.utils.encoding import smart_str from django.contrib.contenttypes.models import ContentType @@ -377,6 +377,7 @@ class Attribute(SharedMemoryModel): self.no_cache = False self.db_value = to_unicode(_PDUMPS(to_str(new_value))) self.save() + #@value.deleter def __value_del(self): "Deleter. Allows for del attr.value. This removes the entire attribute." @@ -1291,7 +1292,15 @@ class TypedObject(SharedMemoryModel): # no match; create new attribute attrib_obj = attrclass(db_key=attribute_name, db_obj=self) # re-set an old attribute value - attrib_obj.value = new_value + try: + attrib_obj.value = new_value + except IntegrityError: + # this can happen if the cache was stale and the databse object is + # missing. If so we need to clean self.hashid from the cache + if _GA(self, "hashid") in _ATTRIBUTE_CACHE: + del _ATTRIBUTE_CACHE[_GA(self, "hashid")] + self.delete() + raise IntegrityError("Attribute could not be saved - object %s was deleted from database." % self.key) _ATTRIBUTE_CACHE[_GA(self, "hashid")][attribute_name] = attrib_obj def get_attribute_obj(self, attribute_name, default=None):