Some optimizations, cleanup and a few bugfixes. Just changing a spurious property retrieval in the typeclass removed an extra, pointless database query.

This commit is contained in:
Griatch 2012-09-18 01:03:35 +02:00
parent 160d4a2807
commit 0dae03156c
5 changed files with 57 additions and 38 deletions

View file

@ -632,16 +632,13 @@ class ObjectDB(TypedObject):
data (object): an optional data object that may or may not
be used by the protocol.
"""
# This is an important function that must always work.
# we use a different __getattribute__ to avoid recursive loops.
if object.__getattribute__(self, 'player'):
object.__getattribute__(self, 'player').msg(message, from_obj=from_obj, data=data)
if _GA(self, 'player'):
_GA(_GA(self, 'player'), "msg")(message, from_obj=from_obj, data=data)
def emit_to(self, message, from_obj=None, data=None):
"Deprecated. Alias for msg"
logger.log_depmsg("emit_to() is deprecated. Use msg() instead.")
self.msg(message, from_obj, data)
_GA(self, "msg")(message, from_obj, data)
def msg_contents(self, message, exclude=None, from_obj=None, data=None):
"""

View file

@ -44,7 +44,6 @@ from django.conf import settings
from django.db import models
from django.contrib.auth.models import User
from django.utils.encoding import smart_str
from django.contrib.contenttypes.models import ContentType
from src.typeclasses.models import _get_cache, _set_cache, _del_cache
from src.server.sessionhandler import SESSIONS
@ -64,6 +63,8 @@ _GA = object.__getattribute__
_SA = object.__setattr__
_DA = object.__delattr__
_TYPECLASS = None
#------------------------------------------------------------
#
# PlayerAttribute
@ -199,8 +200,11 @@ class PlayerDB(TypedObject):
#@obj.setter
def obj_set(self, value):
"Setter. Allows for self.obj = value"
from src.typeclasses.typeclass import TypeClass
if isinstance(value, TypeClass):
global _TYPECLASS
if not _TYPECLASS:
from src.typeclasses.typeclass import TypeClass as _TYPECLASS
if isinstance(value, _TYPECLASS):
value = value.dbobj
try:
_set_cache(self, "obj", value)
@ -260,7 +264,6 @@ class PlayerDB(TypedObject):
#@is_connected.setter
def is_connected_set(self, value):
"Setter. Allows for self.is_connected = value"
print "set_is_connected:", self, value
_set_cache(self, "is_connected", value)
#@is_connected.deleter
def is_connected_del(self):
@ -356,21 +359,19 @@ class PlayerDB(TypedObject):
Evennia -> User
This is the main route for sending data back to the user from the server.
"""
if from_obj:
try:
from_obj.at_msg_send(outgoing_string, to_obj=self, data=data)
_GA(from_obj, "at_msg_send")(outgoing_string, to_obj=self, data=data)
except Exception:
pass
if (object.__getattribute__(self, "character")
and not self.character.at_msg_receive(outgoing_string, from_obj=from_obj, data=data)):
if (_GA(self, "character") and not
_GA(self, "character").at_msg_receive(outgoing_string, from_obj=from_obj, data=data)):
# the at_msg_receive() hook may block receiving of certain messages
return
outgoing_string = utils.to_str(outgoing_string, force_string=True)
for session in object.__getattribute__(self, 'sessions'):
for session in _GA(self, 'sessions'):
session.msg(outgoing_string, data)
@ -383,8 +384,8 @@ class PlayerDB(TypedObject):
def delete(self, *args, **kwargs):
"Make sure to delete user also when deleting player - the two may never exist separately."
try:
if self.user:
self.user.delete()
if _GA(self, "user"):
_GA(_GA(self, "user"), "delete")()
except AssertionError:
pass
try:
@ -398,7 +399,7 @@ class PlayerDB(TypedObject):
def execute_cmd(self, raw_string):
"""
Do something as this playe. This command transparently
Do something as this player. This command transparently
lets its typeclass execute the command.
raw_string - raw command input coming from the command line.
"""
@ -423,8 +424,11 @@ class PlayerDB(TypedObject):
the Player object itself. If no Character exists (since Player is
OOC), None will be returned.
"""
matches = self.__class__.objects.player_search(ostring)
matches = _GA(_GA(_GA(self, "_class__"), "objects"), "player_search")(ostring)
matches = _AT_SEARCH_RESULT(self, ostring, matches, global_search=True)
if matches and return_character and hasattr(matches, "character"):
return matches.character
if matches and return_character:
try:
return _GA(matches, "character")
except:
pass
return matches

View file

@ -56,6 +56,7 @@ _DA = object.__delattr__
_PLOADS = pickle.loads
_PDUMPS = pickle.dumps
# Property Cache mechanism.
def _get_cache(obj, name):
@ -889,6 +890,17 @@ class TypedObject(SharedMemoryModel):
# try to look back to this very database object.)
return _GA(_GA(self, 'typeclass'), propname)
def _hasattr(self, obj, attrname):
"""
Loop-safe version of hasattr, to avoid running a lookup that
will be rerouted up the typeclass. Returns True/False.
"""
try:
_GA(obj, attrname)
return True
except AttributeError:
return False
#@property
_dbid_cache = None
def __dbid_get(self):
@ -1504,7 +1516,7 @@ class TypedObject(SharedMemoryModel):
def nattr(self, attribute_name=None, value=None, delete=False):
"""
This is the equivalence of self.attr but for non-persistent
stores.
stores. Will not raise error but return None.
"""
if attribute_name == None:
# act as a list method
@ -1515,11 +1527,11 @@ class TypedObject(SharedMemoryModel):
if not val.startswith['_']]
elif delete == True:
if hasattr(self.ndb, attribute_name):
_DA(self.db, attribute_name)
_DA(_GA(self, "db"), attribute_name)
elif value == None:
# act as a getter.
if hasattr(self.ndb, attribute_name):
_GA(self.ndb, attribute_name)
_GA(_GA(self, "ndb"), attribute_name)
else:
return None
else:

View file

@ -11,7 +11,6 @@ used by the typesystem or django itself.
"""
from src.utils.logger import log_trace, log_errmsg
from django.conf import settings
__all__ = ("TypeClass",)
@ -115,10 +114,11 @@ class TypeClass(object):
return _GA(dbobj, propname)
except AttributeError:
try:
#XXX deprecated
return _GA(dbobj,"get_attribute_raise")(propname)
except AttributeError:
string = "Object: '%s' not found on %s(#%s), nor on its typeclass %s."
raise AttributeError(string % (propname, dbobj, dbobj.dbid, dbobj.typeclass_path))
raise AttributeError(string % (propname, dbobj, _GA(dbobj, "dbid"), _GA(dbobj, "typeclass_path")))
def __setattr__(self, propname, value):
"""
@ -134,7 +134,6 @@ class TypeClass(object):
string += " (protected: [%s])" % (", ".join(PROTECTED))
log_errmsg(string % (self.name, propname))
return
try:
dbobj = _GA(self, 'dbobj')
except AttributeError:
@ -148,19 +147,20 @@ class TypeClass(object):
_GA(dbobj, propname)
_SA(dbobj, propname, value)
except AttributeError:
#XXX deprecated
dbobj.set_attribute(propname, value)
else:
_SA(self, propname, value)
def __eq__(self, other):
"""
dbobj-recognized comparison
"""
try:
return other == self or other == _GA(self, dbobj) or other == _GA(self, dbobj).user
except AttributeError:
# if self.dbobj.user fails it means the two previous comparisons failed already
return False
def __eq__(self, other):
"""
dbobj-recognized comparison
"""
try:
return other == self or other == _GA(self, dbobj) or other == _GA(self, dbobj).user
except AttributeError:
# if self.dbobj.user fails it means the two previous comparisons failed already
return False
def __delattr__(self, propname):

View file

@ -34,7 +34,13 @@ def is_iter(iterable):
they are actually iterable), since string iterations
are usually not what we want to do with a string.
"""
return hasattr(iterable, '__iter__')
# use a try..except here to avoid a property
# lookup when using this from a typeclassed entity
try:
_GA(iterable, '__iter__')
return True
except AttributeError:
return False
def make_iter(obj):
"Makes sure that the object is always iterable."