Continuing work on API, making local-use class properties _private to make things easier to explore.

This commit is contained in:
Griatch 2012-03-31 13:06:29 +02:00
parent 1ce5c6b84a
commit fc156b5a54
5 changed files with 308 additions and 328 deletions

View file

@ -21,7 +21,7 @@ from django.contrib.contenttypes.models import ContentType
from src.utils.idmapper.models import SharedMemoryModel from src.utils.idmapper.models import SharedMemoryModel
from src.typeclasses.models import Attribute, TypedObject, TypeNick, TypeNickHandler from src.typeclasses.models import Attribute, TypedObject, TypeNick, TypeNickHandler
from src.typeclasses.models import get_cache, set_cache, del_cache from src.typeclasses.models import _get_cache, _set_cache, _del_cache
from src.typeclasses.typeclass import TypeClass from src.typeclasses.typeclass import TypeClass
from src.objects.manager import ObjectManager from src.objects.manager import ObjectManager
from src.players.models import PlayerDB from src.players.models import PlayerDB
@ -34,11 +34,11 @@ from src.utils.utils import make_iter, to_unicode, to_str, mod_import
#PlayerDB = ContentType.objects.get(app_label="players", model="playerdb").model_class() #PlayerDB = ContentType.objects.get(app_label="players", model="playerdb").model_class()
AT_SEARCH_RESULT = mod_import(*settings.SEARCH_AT_RESULT.rsplit('.', 1)) _AT_SEARCH_RESULT = mod_import(*settings.SEARCH_AT_RESULT.rsplit('.', 1))
GA = object.__getattribute__ _GA = object.__getattribute__
SA = object.__setattr__ _SA = object.__setattr__
DA = object.__delattr__ _DA = object.__delattr__
#------------------------------------------------------------ #------------------------------------------------------------
# #
@ -214,10 +214,10 @@ class ObjectDB(TypedObject):
def aliases_get(self): def aliases_get(self):
"Getter. Allows for value = self.aliases" "Getter. Allows for value = self.aliases"
try: try:
return GA(self, "_cached_aliases") return _GA(self, "_cached_aliases")
except AttributeError: except AttributeError:
aliases = list(Alias.objects.filter(db_obj=self).values_list("db_key", flat=True)) aliases = list(Alias.objects.filter(db_obj=self).values_list("db_key", flat=True))
SA(self, "_cached_aliases", aliases) _SA(self, "_cached_aliases", aliases)
return aliases return aliases
#@aliases.setter #@aliases.setter
def aliases_set(self, aliases): def aliases_set(self, aliases):
@ -225,13 +225,13 @@ class ObjectDB(TypedObject):
for alias in make_iter(aliases): for alias in make_iter(aliases):
new_alias = Alias(db_key=alias, db_obj=self) new_alias = Alias(db_key=alias, db_obj=self)
new_alias.save() new_alias.save()
SA(self, "_cached_aliases", aliases) _SA(self, "_cached_aliases", aliases)
#@aliases.deleter #@aliases.deleter
def aliases_del(self): def aliases_del(self):
"Deleter. Allows for del self.aliases" "Deleter. Allows for del self.aliases"
for alias in Alias.objects.filter(db_obj=self): for alias in Alias.objects.filter(db_obj=self):
alias.delete() alias.delete()
DA(self, "_cached_aliases") _DA(self, "_cached_aliases")
aliases = property(aliases_get, aliases_set, aliases_del) aliases = property(aliases_get, aliases_set, aliases_del)
# player property (wraps db_player) # player property (wraps db_player)
@ -242,26 +242,26 @@ class ObjectDB(TypedObject):
We have to be careful here since Player is also We have to be careful here since Player is also
a TypedObject, so as to not create a loop. a TypedObject, so as to not create a loop.
""" """
return get_cache(self, "player") return _get_cache(self, "player")
#@player.setter #@player.setter
def player_set(self, player): def player_set(self, player):
"Setter. Allows for self.player = value" "Setter. Allows for self.player = value"
if isinstance(player, TypeClass): if isinstance(player, TypeClass):
player = player.dbobj player = player.dbobj
set_cache(self, "player", player) _set_cache(self, "player", player)
#@player.deleter #@player.deleter
def player_del(self): def player_del(self):
"Deleter. Allows for del self.player" "Deleter. Allows for del self.player"
self.db_player = None self.db_player = None
self.save() self.save()
del_cache(self, "player") _del_cache(self, "player")
player = property(player_get, player_set, player_del) player = property(player_get, player_set, player_del)
# location property (wraps db_location) # location property (wraps db_location)
#@property #@property
def location_get(self): def location_get(self):
"Getter. Allows for value = self.location." "Getter. Allows for value = self.location."
loc = get_cache(self, "location") loc = _get_cache(self, "location")
if loc: if loc:
return loc.typeclass return loc.typeclass
return None return None
@ -281,7 +281,7 @@ class ObjectDB(TypedObject):
loc = location.dbobj loc = location.dbobj
else: else:
loc = location.dbobj loc = location.dbobj
set_cache(self, "location", loc) _set_cache(self, "location", loc)
except Exception: except Exception:
string = "Cannot set location: " string = "Cannot set location: "
string += "%s is not a valid location." string += "%s is not a valid location."
@ -293,14 +293,14 @@ class ObjectDB(TypedObject):
"Deleter. Allows for del self.location" "Deleter. Allows for del self.location"
self.db_location = None self.db_location = None
self.save() self.save()
del_cache() _del_cache(self, "location")
location = property(location_get, location_set, location_del) location = property(location_get, location_set, location_del)
# home property (wraps db_home) # home property (wraps db_home)
#@property #@property
def home_get(self): def home_get(self):
"Getter. Allows for value = self.home" "Getter. Allows for value = self.home"
home = get_cache(self, "home") home = _get_cache(self, "home")
if home: if home:
return home.typeclass return home.typeclass
return None return None
@ -318,7 +318,7 @@ class ObjectDB(TypedObject):
hom = home.dbobj hom = home.dbobj
else: else:
hom = home.dbobj hom = home.dbobj
set_cache(self, "home", hom) _set_cache(self, "home", hom)
except Exception: except Exception:
string = "Cannot set home: " string = "Cannot set home: "
string += "%s is not a valid home." string += "%s is not a valid home."
@ -330,14 +330,14 @@ class ObjectDB(TypedObject):
"Deleter. Allows for del self.home." "Deleter. Allows for del self.home."
self.db_home = None self.db_home = None
self.save() self.save()
del_cache(self, "home") _del_cache(self, "home")
home = property(home_get, home_set, home_del) home = property(home_get, home_set, home_del)
# destination property (wraps db_destination) # destination property (wraps db_destination)
#@property #@property
def destination_get(self): def destination_get(self):
"Getter. Allows for value = self.destination." "Getter. Allows for value = self.destination."
dest = get_cache(self, "destination") dest = _get_cache(self, "destination")
if dest: if dest:
return dest.typeclass return dest.typeclass
return None return None
@ -357,7 +357,7 @@ class ObjectDB(TypedObject):
dest = destination.dbobj dest = destination.dbobj
else: else:
dest = destination.dbobj dest = destination.dbobj
set_cache(self, "destination", dest) _set_cache(self, "destination", dest)
except Exception: except Exception:
string = "Cannot set destination: " string = "Cannot set destination: "
string += "%s is not a valid destination." string += "%s is not a valid destination."
@ -369,7 +369,7 @@ class ObjectDB(TypedObject):
"Deleter. Allows for del self.destination" "Deleter. Allows for del self.destination"
self.db_destination = None self.db_destination = None
self.save() self.save()
del_cache(self, "destination") _del_cache(self, "destination")
destination = property(destination_get, destination_set, destination_del) destination = property(destination_get, destination_set, destination_del)
# cmdset_storage property. # cmdset_storage property.
@ -403,17 +403,10 @@ class ObjectDB(TypedObject):
# #
# this is required to properly handle attributes and typeclass loading. # this is required to properly handle attributes and typeclass loading.
#attribute_model_path = "src.objects.models" _typeclass_paths = settings.OBJECT_TYPECLASS_PATHS
#attribute_model_name = "ObjAttribute" _attribute_class = ObjAttribute
typeclass_paths = settings.OBJECT_TYPECLASS_PATHS _db_model_name = "objectdb" # used by attributes to safely store objects
attribute_class = ObjAttribute _default_typeclass_path = settings.BASE_OBJECT_TYPECLASS or "src.objects.objects.Object"
db_model_name = "objectdb" # used by attributes to safely store objects
# this is used by all typedobjects as a fallback
try:
default_typeclass_path = settings.BASE_OBJECT_TYPECLASS
except Exception:
default_typeclass_path = "src.objects.objects.Object"
#@property #@property
def sessions_get(self): def sessions_get(self):
@ -533,7 +526,7 @@ class ObjectDB(TypedObject):
if ignore_errors: if ignore_errors:
return results return results
# this import is cache after the first call. # this import is cache after the first call.
return AT_SEARCH_RESULT(self, ostring, results, global_search) return _AT_SEARCH_RESULT(self, ostring, results, global_search)
# #
# Execution/action methods # Execution/action methods

View file

@ -47,13 +47,13 @@ from django.utils.encoding import smart_str
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from src.server.sessionhandler import SESSIONS from src.server.sessionhandler import SESSIONS
from src.players import manager from src.players import manager
from src.typeclasses.models import Attribute, TypedObject, TypeNick, TypeNickHandler from src.typeclasses.models import Attribute, TypedObject, TypeNick, TypeNickHandler
from src.utils import logger, utils from src.utils import logger, utils
from src.commands.cmdsethandler import CmdSetHandler from src.commands.cmdsethandler import CmdSetHandler
from src.commands import cmdhandler from src.commands import cmdhandler
AT_SEARCH_RESULT = utils.mod_import(*settings.SEARCH_AT_RESULT.rsplit('.', 1)) _AT_SEARCH_RESULT = utils.mod_import(*settings.SEARCH_AT_RESULT.rsplit('.', 1))
#------------------------------------------------------------ #------------------------------------------------------------
# #
@ -67,7 +67,7 @@ class PlayerAttribute(Attribute):
but are intended to store OOC information specific to each user but are intended to store OOC information specific to each user
and game (example would be configurations etc). and game (example would be configurations etc).
""" """
db_obj = models.ForeignKey("PlayerDB") db_obj = models.ForeignKey("PlayerDB")
class Meta: class Meta:
"Define Django meta options" "Define Django meta options"
@ -81,11 +81,11 @@ class PlayerAttribute(Attribute):
class PlayerNick(TypeNick): class PlayerNick(TypeNick):
""" """
The default nick types used by Evennia are: The default nick types used by Evennia are:
inputline (default) - match against all input inputline (default) - match against all input
player - match against player searches player - match against player searches
obj - match against object searches obj - match against object searches
channel - used to store own names for channels channel - used to store own names for channels
""" """
db_obj = models.ForeignKey("PlayerDB", verbose_name="player") db_obj = models.ForeignKey("PlayerDB", verbose_name="player")
@ -99,7 +99,7 @@ class PlayerNick(TypeNick):
class PlayerNickHandler(TypeNickHandler): class PlayerNickHandler(TypeNickHandler):
""" """
Handles nick access and setting. Accessed through ObjectDB.nicks Handles nick access and setting. Accessed through ObjectDB.nicks
""" """
NickClass = PlayerNick NickClass = PlayerNick
@ -112,52 +112,52 @@ class PlayerNickHandler(TypeNickHandler):
class PlayerDB(TypedObject): class PlayerDB(TypedObject):
""" """
This is a special model using Django's 'profile' functionality This is a special model using Django's 'profile' functionality
and extends the default Django User model. It is defined as such and extends the default Django User model. It is defined as such
by use of the variable AUTH_PROFILE_MODULE in the settings. by use of the variable AUTH_PROFILE_MODULE in the settings.
One accesses the fields/methods. We try use this model as much One accesses the fields/methods. We try use this model as much
as possible rather than User, since we can customize this to as possible rather than User, since we can customize this to
our liking. our liking.
The TypedObject supplies the following (inherited) properties: The TypedObject supplies the following (inherited) properties:
key - main name key - main name
typeclass_path - the path to the decorating typeclass typeclass_path - the path to the decorating typeclass
typeclass - auto-linked typeclass typeclass - auto-linked typeclass
date_created - time stamp of object creation date_created - time stamp of object creation
permissions - perm strings permissions - perm strings
dbref - #id of object dbref - #id of object
db - persistent attribute storage db - persistent attribute storage
ndb - non-persistent attribute storage ndb - non-persistent attribute storage
The PlayerDB adds the following properties: The PlayerDB adds the following properties:
user - Connected User object. django field, needs to be save():d. user - Connected User object. django field, needs to be save():d.
obj - game object controlled by player obj - game object controlled by player
character - alias for obj character - alias for obj
name - alias for user.username name - alias for user.username
sessions - sessions connected to this player sessions - sessions connected to this player
is_superuser - bool if this player is a superuser is_superuser - bool if this player is a superuser
""" """
# #
# PlayerDB Database model setup # PlayerDB Database model setup
# #
# inherited fields (from TypedObject): # inherited fields (from TypedObject):
# db_key, db_typeclass_path, db_date_created, db_permissions # db_key, db_typeclass_path, db_date_created, db_permissions
# this is the one-to-one link between the customized Player object and # this is the one-to-one link between the customized Player object and
# this profile model. It is required by django. # this profile model. It is required by django.
user = models.ForeignKey(User, unique=True, db_index=True, user = models.ForeignKey(User, unique=True, db_index=True,
help_text="The <I>User</I> object holds django-specific authentication for each Player. A unique User should be created and tied to each Player, the two should never be switched or changed around. The User will be deleted automatically when the Player is.") help_text="The <I>User</I> object holds django-specific authentication for each Player. A unique User should be created and tied to each Player, the two should never be switched or changed around. The User will be deleted automatically when the Player is.")
# the in-game object connected to this player (if any). # the in-game object connected to this player (if any).
# Use the property 'obj' to access. # Use the property 'obj' to access.
db_obj = models.ForeignKey("objects.ObjectDB", null=True, blank=True, db_obj = models.ForeignKey("objects.ObjectDB", null=True, blank=True,
verbose_name="character", help_text='In-game object.') verbose_name="character", help_text='In-game object.')
# database storage of persistant cmdsets. # database storage of persistant cmdsets.
db_cmdset_storage = models.CharField('cmdset', max_length=255, null=True, db_cmdset_storage = models.CharField('cmdset', max_length=255, null=True,
help_text="optional python path to a cmdset class. If creating a Character, this will default to settings.CMDSET_DEFAULT.") help_text="optional python path to a cmdset class. If creating a Character, this will default to settings.CMDSET_DEFAULT.")
# Database manager # Database manager
objects = manager.PlayerManager() objects = manager.PlayerManager()
class Meta: class Meta:
@ -166,18 +166,18 @@ class PlayerDB(TypedObject):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
"Parent must be initiated first" "Parent must be initiated first"
TypedObject.__init__(self, *args, **kwargs) TypedObject.__init__(self, *args, **kwargs)
# handlers # handlers
self.cmdset = CmdSetHandler(self) self.cmdset = CmdSetHandler(self)
self.cmdset.update(init_mode=True) self.cmdset.update(init_mode=True)
self.nicks = PlayerNickHandler(self) self.nicks = PlayerNickHandler(self)
# Wrapper properties to easily set database fields. These are # Wrapper properties to easily set database fields. These are
# @property decorators that allows to access these fields using # @property decorators that allows to access these fields using
# normal python operations (without having to remember to save() # normal python operations (without having to remember to save()
# etc). So e.g. a property 'attr' has a get/set/del decorator # etc). So e.g. a property 'attr' has a get/set/del decorator
# defined that allows the user to do self.attr = value, # defined that allows the user to do self.attr = value,
# value = self.attr and del self.attr respectively (where self # value = self.attr and del self.attr respectively (where self
# is the object in question). # is the object in question).
# obj property (wraps db_obj) # obj property (wraps db_obj)
@ -190,13 +190,13 @@ class PlayerDB(TypedObject):
"Setter. Allows for self.obj = value" "Setter. Allows for self.obj = value"
from src.typeclasses.typeclass import TypeClass from src.typeclasses.typeclass import TypeClass
if isinstance(value, TypeClass): if isinstance(value, TypeClass):
value = value.dbobj value = value.dbobj
try: try:
self.db_obj = value self.db_obj = value
self.save() self.save()
except Exception: except Exception:
logger.log_trace() logger.log_trace()
raise Exception("Cannot assign %s as a player object!" % value) raise Exception("Cannot assign %s as a player object!" % value)
#@obj.deleter #@obj.deleter
def obj_del(self): def obj_del(self):
"Deleter. Allows for del self.obj" "Deleter. Allows for del self.obj"
@ -204,8 +204,8 @@ class PlayerDB(TypedObject):
self.save() self.save()
obj = property(obj_get, obj_set, obj_del) obj = property(obj_get, obj_set, obj_del)
# whereas the name 'obj' is consistent with the rest of the code, # whereas the name 'obj' is consistent with the rest of the code,
# 'character' is a more intuitive property name, so we # 'character' is a more intuitive property name, so we
# define this too, as an alias to player.obj. # define this too, as an alias to player.obj.
#@property #@property
def character_get(self): def character_get(self):
@ -234,7 +234,7 @@ class PlayerDB(TypedObject):
if utils.is_iter(value): if utils.is_iter(value):
value = ",".join([str(val).strip() for val in value]) value = ",".join([str(val).strip() for val in value])
self.db_cmdset_storage = value self.db_cmdset_storage = value
self.save() self.save()
#@cmdset_storage.deleter #@cmdset_storage.deleter
def cmdset_storage_del(self): def cmdset_storage_del(self):
"Deleter. Allows for del self.name" "Deleter. Allows for del self.name"
@ -249,26 +249,19 @@ class PlayerDB(TypedObject):
# #
# PlayerDB main class properties and methods # PlayerDB main class properties and methods
# #
def __str__(self): def __str__(self):
return smart_str("%s(player %i)" % (self.name, self.id)) return smart_str("%s(player %i)" % (self.name, self.id))
def __unicode__(self): def __unicode__(self):
return u"%s(player#%i)" % (self.name, self.id) return u"%s(player#%i)" % (self.name, self.id)
# this is used by all typedobjects as a fallback
try:
default_typeclass_path = settings.BASE_PLAYER_TYPECLASS
except Exception:
default_typeclass_path = "src.players.player.Player"
# this is required to properly handle attributes and typeclass loading # this is required to properly handle attributes and typeclass loading
#attribute_model_path = "src.players.models" _typeclass_paths = settings.PLAYER_TYPECLASS_PATHS
#attribute_model_name = "PlayerAttribute" _attribute_class = PlayerAttribute
typeclass_paths = settings.PLAYER_TYPECLASS_PATHS _db_model_name = "playerdb" # used by attributes to safely store objects
attribute_class = PlayerAttribute _default_typeclass_path = settings.BASE_PLAYER_TYPECLASS or "src.players.player.Player"
db_model_name = "playerdb" # used by attributes to safely store objects
# name property (wraps self.user.username) # name property (wraps self.user.username)
#@property #@property
@ -299,7 +292,7 @@ class PlayerDB(TypedObject):
#@sessions.deleter #@sessions.deleter
def sessions_del(self): def sessions_del(self):
"Deleter. Protects the sessions property from deletion" "Deleter. Protects the sessions property from deletion"
raise Exception("Cannot delete sessions manually!") raise Exception("Cannot delete sessions manually!")
sessions = property(sessions_get, sessions_set, sessions_del) sessions = property(sessions_get, sessions_set, sessions_del)
#@property #@property
@ -309,12 +302,12 @@ class PlayerDB(TypedObject):
is_superuser = property(is_superuser_get) is_superuser = property(is_superuser_get)
# #
# PlayerDB class access methods # PlayerDB class access methods
# #
def msg(self, outgoing_string, from_obj=None, data=None): def msg(self, outgoing_string, from_obj=None, data=None):
""" """
Evennia -> User Evennia -> User
This is the main route for sending data back to the user from the server. This is the main route for sending data back to the user from the server.
""" """
@ -324,10 +317,10 @@ class PlayerDB(TypedObject):
except Exception: except Exception:
pass pass
if (object.__getattribute__(self, "character") if (object.__getattribute__(self, "character")
and not self.character.at_msg_receive(outgoing_string, from_obj=from_obj, data=data)): and not self.character.at_msg_receive(outgoing_string, from_obj=from_obj, data=data)):
# the at_msg_receive() hook may block receiving of certain messages # the at_msg_receive() hook may block receiving of certain messages
return return
outgoing_string = utils.to_str(outgoing_string, force_string=True) outgoing_string = utils.to_str(outgoing_string, force_string=True)
@ -340,31 +333,31 @@ class PlayerDB(TypedObject):
Swaps character, if possible Swaps character, if possible
""" """
return self.__class__.objects.swap_character(self, new_character, delete_old_character=delete_old_character) return self.__class__.objects.swap_character(self, new_character, delete_old_character=delete_old_character)
# #
# Execution/action methods # Execution/action methods
# #
def execute_cmd(self, raw_string): def execute_cmd(self, raw_string):
""" """
Do something as this playe. This command transparently Do something as this playe. This command transparently
lets its typeclass execute the command. lets its typeclass execute the command.
raw_string - raw command input coming from the command line. raw_string - raw command input coming from the command line.
""" """
# nick replacement - we require full-word matching. # nick replacement - we require full-word matching.
raw_string = utils.to_unicode(raw_string) raw_string = utils.to_unicode(raw_string)
raw_list = raw_string.split(None) raw_list = raw_string.split(None)
raw_list = [" ".join(raw_list[:i+1]) for i in range(len(raw_list)) if raw_list[:i+1]] raw_list = [" ".join(raw_list[:i+1]) for i in range(len(raw_list)) if raw_list[:i+1]]
for nick in PlayerNick.objects.filter(db_obj=self, db_type__in=("inputline","channel")): for nick in PlayerNick.objects.filter(db_obj=self, db_type__in=("inputline","channel")):
if nick.db_nick in raw_list: if nick.db_nick in raw_list:
raw_string = raw_string.replace(nick.db_nick, nick.db_real, 1) raw_string = raw_string.replace(nick.db_nick, nick.db_real, 1)
break break
return cmdhandler.cmdhandler(self.typeclass, raw_string) return cmdhandler.cmdhandler(self.typeclass, raw_string)
def search(self, ostring, global_search=False, attribute_name=None, use_nicks=False, def search(self, ostring, global_search=False, attribute_name=None, use_nicks=False,
location=None, ignore_errors=False, player=False): location=None, ignore_errors=False, player=False):
""" """
A shell method mimicking the ObjectDB equivalent, for easy inclusion from A shell method mimicking the ObjectDB equivalent, for easy inclusion from
@ -373,8 +366,8 @@ class PlayerDB(TypedObject):
if self.character: if self.character:
# run the normal search # run the normal search
return self.character.search(ostring, global_search=global_search, attribute_name=attribute_name, return self.character.search(ostring, global_search=global_search, attribute_name=attribute_name,
use_nicks=use_nicks, location=location, use_nicks=use_nicks, location=location,
ignore_errors=ignore_errors, player=player) ignore_errors=ignore_errors, player=player)
if player: if player:
# seach for players # seach for players
@ -383,7 +376,6 @@ class PlayerDB(TypedObject):
# more limited player-only search. Still returns an Object. # more limited player-only search. Still returns an Object.
ObjectDB = ContentType.objects.get(app_label="objects", model="objectdb").model_class() ObjectDB = ContentType.objects.get(app_label="objects", model="objectdb").model_class()
matches = ObjectDB.objects.object_search(ostring, caller=self, global_search=global_search) matches = ObjectDB.objects.object_search(ostring, caller=self, global_search=global_search)
# deal with results # deal with results
matches = AT_SEARCH_RESULT(self, ostring, matches, global_search=global_search) matches = _AT_SEARCH_RESULT(self, ostring, matches, global_search=global_search)
return matches return matches

View file

@ -11,7 +11,7 @@ handled by Scripts.
Scripts have to check for themselves that they should be applied at a Scripts have to check for themselves that they should be applied at a
particular moment of time; this is handled by the is_valid() hook. particular moment of time; this is handled by the is_valid() hook.
Scripts can also implement at_start and at_end hooks for preparing and Scripts can also implement at_start and at_end hooks for preparing and
cleaning whatever effect they have had on the game object. cleaning whatever effect they have had on the game object.
Common examples of uses of Scripts: Common examples of uses of Scripts:
- load the default cmdset to the player object's cmdhandler - load the default cmdset to the player object's cmdhandler
@ -20,8 +20,8 @@ Common examples of uses of Scripts:
start combat or enter a dark room. start combat or enter a dark room.
- Weather patterns in-game - Weather patterns in-game
- merge a new cmdset with the default one for changing which - merge a new cmdset with the default one for changing which
commands are available at a particular time commands are available at a particular time
- give the player/object a time-limited bonus/effect - give the player/object a time-limited bonus/effect
""" """
from django.conf import settings from django.conf import settings
@ -45,7 +45,7 @@ class ScriptAttribute(Attribute):
verbose_name = "Script Attribute" verbose_name = "Script Attribute"
verbose_name_plural = "Script Attributes" verbose_name_plural = "Script Attributes"
#------------------------------------------------------------ #------------------------------------------------------------
# #
# ScriptDB # ScriptDB
@ -54,7 +54,7 @@ class ScriptAttribute(Attribute):
class ScriptDB(TypedObject): class ScriptDB(TypedObject):
""" """
The Script database representation. The Script database representation.
The TypedObject supplies the following (inherited) properties: The TypedObject supplies the following (inherited) properties:
key - main name key - main name
@ -62,10 +62,10 @@ class ScriptDB(TypedObject):
typeclass_path - the path to the decorating typeclass typeclass_path - the path to the decorating typeclass
typeclass - auto-linked typeclass typeclass - auto-linked typeclass
date_created - time stamp of object creation date_created - time stamp of object creation
permissions - perm strings permissions - perm strings
dbref - #id of object dbref - #id of object
db - persistent attribute storage db - persistent attribute storage
ndb - non-persistent attribute storage ndb - non-persistent attribute storage
The ScriptDB adds the following properties: The ScriptDB adds the following properties:
desc - optional description of script desc - optional description of script
@ -74,21 +74,21 @@ class ScriptDB(TypedObject):
start_delay - if the script should start repeating right away start_delay - if the script should start repeating right away
repeats - how many times the script should repeat repeats - how many times the script should repeat
persistent - if script should survive a server reboot persistent - if script should survive a server reboot
is_active - bool if script is currently running is_active - bool if script is currently running
""" """
# #
# ScriptDB Database Model setup # ScriptDB Database Model setup
# #
# These databse fields are all set using their corresponding properties, # These databse fields are all set using their corresponding properties,
# named same as the field, but withtou the db_* prefix. # named same as the field, but withtou the db_* prefix.
# inherited fields (from TypedObject): # inherited fields (from TypedObject):
# db_key, db_typeclass_path, db_date_created, db_permissions # db_key, db_typeclass_path, db_date_created, db_permissions
# optional description. # optional description.
db_desc = models.CharField('desc', max_length=255, blank=True) db_desc = models.CharField('desc', max_length=255, blank=True)
# A reference to the database object affected by this Script, if any. # A reference to the database object affected by this Script, if any.
db_obj = models.ForeignKey("objects.ObjectDB", null=True, blank=True, verbose_name='scripted object', db_obj = models.ForeignKey("objects.ObjectDB", null=True, blank=True, verbose_name='scripted object',
@ -106,7 +106,7 @@ class ScriptDB(TypedObject):
# Database manager # Database manager
objects = ScriptManager() objects = ScriptManager()
class Meta: class Meta:
"Define Django meta options" "Define Django meta options"
verbose_name = "Script" verbose_name = "Script"
@ -115,8 +115,8 @@ class ScriptDB(TypedObject):
# @property decorators that allows to access these fields using # @property decorators that allows to access these fields using
# normal python operations (without having to remember to save() # normal python operations (without having to remember to save()
# etc). So e.g. a property 'attr' has a get/set/del decorator # etc). So e.g. a property 'attr' has a get/set/del decorator
# defined that allows the user to do self.attr = value, # defined that allows the user to do self.attr = value,
# value = self.attr and del self.attr respectively (where self # value = self.attr and del self.attr respectively (where self
# is the script in question). # is the script in question).
# desc property (wraps db_desc) # desc property (wraps db_desc)
@ -186,7 +186,7 @@ class ScriptDB(TypedObject):
self.db_start_delay = False self.db_start_delay = False
self.save() self.save()
start_delay = property(start_delay_get, start_delay_set, start_delay_del) start_delay = property(start_delay_get, start_delay_set, start_delay_del)
# repeats property (wraps db_repeats) # repeats property (wraps db_repeats)
#@property #@property
def repeats_get(self): def repeats_get(self):
@ -221,7 +221,7 @@ class ScriptDB(TypedObject):
self.save() self.save()
persistent = property(persistent_get, persistent_set, persistent_del) persistent = property(persistent_get, persistent_set, persistent_del)
# is_active property (wraps db_is_active) # is_active property (wraps db_is_active)
#@property #@property
def is_active_get(self): def is_active_get(self):
"Getter. Allows for value = self.is_active" "Getter. Allows for value = self.is_active"
@ -245,33 +245,26 @@ class ScriptDB(TypedObject):
# #
# this is required to properly handle attributes and typeclass loading # this is required to properly handle attributes and typeclass loading
#attribute_model_path = "src.scripts.models" _typeclass_paths = settings.SCRIPT_TYPECLASS_PATHS
#attribute_model_name = "ScriptAttribute" _attribute_class = ScriptAttribute
typeclass_paths = settings.SCRIPT_TYPECLASS_PATHS _db_model_name = "scriptdb" # used by attributes to safely store objects
attribute_class = ScriptAttribute _default_typeclass_path = settings.BASE_SCRIPT_TYPECLASS or "src.scripts.scripts.DoNothing"
db_model_name = "scriptdb" # used by attributes to safely store objects
# this is used by all typedobjects as a fallback
try:
default_typeclass_path = settings.BASE_SCRIPT_TYPECLASS
except:
default_typeclass_path = "src.scripts.scripts.DoNothing"
def at_typeclass_error(self): def at_typeclass_error(self):
""" """
If this is called, it means the typeclass has a critical If this is called, it means the typeclass has a critical
error and cannot even be loaded. We don't allow a script error and cannot even be loaded. We don't allow a script
to be created under those circumstances. Already created, to be created under those circumstances. Already created,
permanent scripts are set to already be active so they permanent scripts are set to already be active so they
won't get activated now (next reboot the bug might be fixed) won't get activated now (next reboot the bug might be fixed)
""" """
# By setting is_active=True, we trick the script not to run "again". # By setting is_active=True, we trick the script not to run "again".
self.is_active = True self.is_active = True
return super(ScriptDB, self).at_typeclass_error() return super(ScriptDB, self).at_typeclass_error()
delete_iter = 0 delete_iter = 0
def delete(self): def delete(self):
if self.delete_iter > 0: if self.delete_iter > 0:
return return
self.delete_iter += 1 self.delete_iter += 1
super(ScriptDB, self).delete() super(ScriptDB, self).delete()

View file

@ -43,35 +43,35 @@ from src.locks.lockhandler import LockHandler
from src.utils import logger, utils from src.utils import logger, utils
from src.utils.utils import make_iter, is_iter, has_parent, to_unicode, to_str from src.utils.utils import make_iter, is_iter, has_parent, to_unicode, to_str
PERMISSION_HIERARCHY = [p.lower() for p in settings.PERMISSION_HIERARCHY] _PERMISSION_HIERARCHY = [p.lower() for p in settings.PERMISSION_HIERARCHY]
CTYPEGET = ContentType.objects.get _CTYPEGET = ContentType.objects.get
GA = object.__getattribute__ _GA = object.__getattribute__
SA = object.__setattr__ _SA = object.__setattr__
DA = object.__delattr__ _DA = object.__delattr__
PLOADS = pickle.loads _PLOADS = pickle.loads
PDUMPS = pickle.dumps _PDUMPS = pickle.dumps
# Property Cache mechanism. # Property Cache mechanism.
def get_cache(obj, name): def _get_cache(obj, name):
"On-model Cache handler." "On-model Cache handler."
try: try:
return GA(obj, "_cached_db_%s" % name) return _GA(obj, "_cached_db_%s" % name)
except AttributeError: except AttributeError:
val = GA(obj, "db_%s" % name) val = _GA(obj, "db_%s" % name)
if val: SA(obj, "_cached_db_%s" % name, val) if val: _SA(obj, "_cached_db_%s" % name, val)
return val return val
def set_cache(obj, name, val): def _set_cache(obj, name, val):
"On-model Cache setter" "On-model Cache setter"
SA(obj, "db_%s" % name, val) _SA(obj, "db_%s" % name, val)
GA(obj, "save")() _GA(obj, "save")()
SA(obj, "_cached_db_%s" % name, val) _SA(obj, "_cached_db_%s" % name, val)
def del_cache(obj, name): def _del_cache(obj, name):
"On-model cache deleter" "On-model cache deleter"
try: try:
DA(obj, "_cached_db_%s" % name) _DA(obj, "_cached_db_%s" % name)
except AttributeError: except AttributeError:
pass pass
@ -290,61 +290,61 @@ class Attribute(SharedMemoryModel):
# key property (wraps db_key) # key property (wraps db_key)
#@property #@property
def key_get(self): def __key_get(self):
"Getter. Allows for value = self.key" "Getter. Allows for value = self.key"
return get_cache(self, "key") return _get_cache(self, "key")
#@key.setter #@key.setter
def key_set(self, value): def __key_set(self, value):
"Setter. Allows for self.key = value" "Setter. Allows for self.key = value"
set_cache(self, "key", value) _set_cache(self, "key", value)
#@key.deleter #@key.deleter
def key_del(self): def __key_del(self):
"Deleter. Allows for del self.key" "Deleter. Allows for del self.key"
raise Exception("Cannot delete attribute key!") raise Exception("Cannot delete attribute key!")
key = property(key_get, key_set, key_del) key = property(__key_get, __key_set, __key_del)
# obj property (wraps db_obj) # obj property (wraps db_obj)
#@property #@property
def obj_get(self): def __obj_get(self):
"Getter. Allows for value = self.obj" "Getter. Allows for value = self.obj"
return get_cache(self, "obj") return _get_cache(self, "obj")
#@obj.setter #@obj.setter
def obj_set(self, value): def __obj_set(self, value):
"Setter. Allows for self.obj = value" "Setter. Allows for self.obj = value"
set_cache(self, "obj", value) _set_cache(self, "obj", value)
#@obj.deleter #@obj.deleter
def obj_del(self): def __obj_del(self):
"Deleter. Allows for del self.obj" "Deleter. Allows for del self.obj"
self.db_obj = None self.db_obj = None
self.save() self.save()
del_cache(self, "obj") _del_cache(self, "obj")
obj = property(obj_get, obj_set, obj_del) obj = property(__obj_get, __obj_set, __obj_del)
# date_created property (wraps db_date_created) # date_created property (wraps db_date_created)
#@property #@property
def date_created_get(self): def __date_created_get(self):
"Getter. Allows for value = self.date_created" "Getter. Allows for value = self.date_created"
return get_cache(self, "date_created") return _get_cache(self, "date_created")
#@date_created.setter #@date_created.setter
def date_created_set(self, value): def __date_created_set(self, value):
"Setter. Allows for self.date_created = value" "Setter. Allows for self.date_created = value"
raise Exception("Cannot edit date_created!") raise Exception("Cannot edit date_created!")
#@date_created.deleter #@date_created.deleter
def date_created_del(self): def __date_created_del(self):
"Deleter. Allows for del self.date_created" "Deleter. Allows for del self.date_created"
raise Exception("Cannot delete date_created!") raise Exception("Cannot delete date_created!")
date_created = property(date_created_get, date_created_set, date_created_del) date_created = property(__date_created_get, __date_created_set, __date_created_del)
# value property (wraps db_value) # value property (wraps db_value)
#@property #@property
def value_get(self): def __value_get(self):
""" """
Getter. Allows for value = self.value. Reads from cache if possible. Getter. Allows for value = self.value. Reads from cache if possible.
""" """
if self.no_cache: if self.no_cache:
# re-create data from database and cache it # re-create data from database and cache it
try: try:
value = self.from_attr(PLOADS(to_str(self.db_value))) value = self.__from_attr(_PLOADS(to_str(self.db_value)))
except pickle.UnpicklingError: except pickle.UnpicklingError:
value = self.db_value value = self.db_value
self.cached_value = value self.cached_value = value
@ -355,36 +355,36 @@ class Attribute(SharedMemoryModel):
return self.cached_value return self.cached_value
#@value.setter #@value.setter
def value_set(self, new_value): def __value_set(self, new_value):
""" """
Setter. Allows for self.value = value. We make sure to cache everything. Setter. Allows for self.value = value. We make sure to cache everything.
""" """
new_value = self.to_attr(new_value) new_value = self.__to_attr(new_value)
self.cached_value = self.from_attr(new_value) self.cached_value = self.__from_attr(new_value)
self.no_cache = False self.no_cache = False
self.db_value = to_unicode(PDUMPS(to_str(new_value))) self.db_value = to_unicode(_PDUMPS(to_str(new_value)))
self.save() self.save()
#@value.deleter #@value.deleter
def value_del(self): def __value_del(self):
"Deleter. Allows for del attr.value. This removes the entire attribute." "Deleter. Allows for del attr.value. This removes the entire attribute."
self.delete() self.delete()
value = property(value_get, value_set, value_del) value = property(__value_get, __value_set, __value_del)
# lock_storage property (wraps db_lock_storage) # lock_storage property (wraps db_lock_storage)
#@property #@property
def lock_storage_get(self): def __lock_storage_get(self):
"Getter. Allows for value = self.lock_storage" "Getter. Allows for value = self.lock_storage"
return get_cache(self, "lock_storage") return _get_cache(self, "lock_storage")
#@lock_storage.setter #@lock_storage.setter
def lock_storage_set(self, value): def __lock_storage_set(self, value):
"""Saves the lock_storage. This is usually not called directly, but through self.lock()""" """Saves the lock_storage. This is usually not called directly, but through self.lock()"""
self.db_lock_storage = value self.db_lock_storage = value
self.save() self.save()
#@lock_storage.deleter #@lock_storage.deleter
def lock_storage_del(self): def __lock_storage_del(self):
"Deleter is disabled. Use the lockhandler.delete (self.lock.delete) instead""" "Deleter is disabled. Use the lockhandler.delete (self.lock.delete) instead"""
logger.log_errmsg("Lock_Storage (on %s) cannot be deleted. Use obj.lock.delete() instead." % self) logger.log_errmsg("Lock_Storage (on %s) cannot be deleted. Use obj.lock.delete() instead." % self)
lock_storage = property(lock_storage_get, lock_storage_set, lock_storage_del) lock_storage = property(__lock_storage_get, __lock_storage_set, __lock_storage_del)
# #
@ -401,7 +401,7 @@ class Attribute(SharedMemoryModel):
# operators on various data # operators on various data
def to_attr(self, data): def __to_attr(self, data):
""" """
Convert data to proper attr data format before saving Convert data to proper attr data format before saving
@ -434,10 +434,10 @@ class Attribute(SharedMemoryModel):
dtype = type(item) dtype = type(item)
if dtype in (basestring, int, float): # check the most common types first, for speed if dtype in (basestring, int, float): # check the most common types first, for speed
return item return item
elif hasattr(item, "id") and hasattr(item, "db_model_name") and hasattr(item, "db_key"): elif hasattr(item, "id") and hasattr(item, "_db_model_name") and hasattr(item, "db_key"):
db_model_name = item.db_model_name db_model_name = item._db_model_name # don't use _GA here, could be typeclass
if db_model_name == "typeclass": if db_model_name == "typeclass":
db_model_name = GA(item.dbobj, "db_model_name") db_model_name = _GA(item.dbobj, "_db_model_name")
return PackedDBobject(item.id, db_model_name, item.db_key) return PackedDBobject(item.id, db_model_name, item.db_key)
elif dtype == tuple: elif dtype == tuple:
return tuple(iter_db2id(val) for val in item) return tuple(iter_db2id(val) for val in item)
@ -452,13 +452,13 @@ class Attribute(SharedMemoryModel):
if dtype in (basestring, int, float): if dtype in (basestring, int, float):
return ("simple",data) return ("simple",data)
elif hasattr(data, "id") and hasattr(data, "db_model_name") and hasattr(data, 'db_key'): elif hasattr(data, "id") and hasattr(data, "_db_model_name") and hasattr(data, 'db_key'):
# all django models (objectdb,scriptdb,playerdb,channel,msg,typeclass) # all django models (objectdb,scriptdb,playerdb,channel,msg,typeclass)
# have the protected property db_model_name hardcoded on themselves for speed. # have the protected property _db_model_name hardcoded on themselves for speed.
db_model_name = data.db_model_name db_model_name = data._db_model_name # don't use _GA here, could be typeclass
if db_model_name == "typeclass": if db_model_name == "typeclass":
# typeclass cannot help us, we want the actual child object model name # typeclass cannot help us, we want the actual child object model name
db_model_name = GA(data.dbobj, "db_model_name") db_model_name = _GA(data.dbobj,"_db_model_name")
return ("dbobj", PackedDBobject(data.id, db_model_name, data.db_key)) return ("dbobj", PackedDBobject(data.id, db_model_name, data.db_key))
elif hasattr(data, "__iter__"): elif hasattr(data, "__iter__"):
return ("iter", iter_db2id(data)) return ("iter", iter_db2id(data))
@ -466,7 +466,7 @@ class Attribute(SharedMemoryModel):
return ("simple", data) return ("simple", data)
def from_attr(self, datatuple): def __from_attr(self, datatuple):
""" """
Retrieve data from a previously stored attribute. This Retrieve data from a previously stored attribute. This
is always a dict with keys type and data. is always a dict with keys type and data.
@ -488,7 +488,7 @@ class Attribute(SharedMemoryModel):
""" """
Convert db-stored dbref back to object Convert db-stored dbref back to object
""" """
mclass = CTYPEGET(model=data.db_model).model_class() mclass = _CTYPEGET(model=data.db_model).model_class()
try: try:
return mclass.objects.dbref_search(data.id) return mclass.objects.dbref_search(data.id)
@ -636,9 +636,11 @@ class TypeNickHandler(object):
# remove the found nick(s) # remove the found nick(s)
query.delete() query.delete()
def get(self, nick=None, nick_type="inputline", obj=None): def get(self, nick=None, nick_type="inputline", obj=None):
"""Retrieves a given nick (with a specified nick_type) on an object. If no nick is given, returns a list """
Retrieves a given nick (with a specified nick_type) on an object. If no nick is given, returns a list
of all nicks on the object, or the empty list. of all nicks on the object, or the empty list.
Defaults to searching the current object.""" Defaults to searching the current object.
"""
if not obj: if not obj:
# defaults to the current object # defaults to the current object
obj = self.obj obj = self.obj
@ -739,101 +741,101 @@ class TypedObject(SharedMemoryModel):
# key property (wraps db_key) # key property (wraps db_key)
#@property #@property
def key_get(self): def __key_get(self):
"Getter. Allows for value = self.key" "Getter. Allows for value = self.key"
return get_cache(self, "key") return _get_cache(self, "key")
#@key.setter #@key.setter
def key_set(self, value): def __key_set(self, value):
"Setter. Allows for self.key = value" "Setter. Allows for self.key = value"
set_cache(self, "key", value) _set_cache(self, "key", value)
#@key.deleter #@key.deleter
def key_del(self): def __key_del(self):
"Deleter. Allows for del self.key" "Deleter. Allows for del self.key"
raise Exception("Cannot delete objectdb key!") raise Exception("Cannot delete objectdb key!")
key = property(key_get, key_set, key_del) key = property(__key_get, __key_set, __key_del)
# name property (wraps db_key too - alias to self.key) # name property (wraps db_key too - alias to self.key)
#@property #@property
def name_get(self): def __name_get(self):
"Getter. Allows for value = self.name" "Getter. Allows for value = self.name"
return get_cache(self, "key") return _get_cache(self, "key")
#@name.setter #@name.setter
def name_set(self, value): def __name_set(self, value):
"Setter. Allows for self.name = value" "Setter. Allows for self.name = value"
set_cache(self, "key", value) _set_cache(self, "key", value)
#@name.deleter #@name.deleter
def name_del(self): def __name_del(self):
"Deleter. Allows for del self.name" "Deleter. Allows for del self.name"
raise Exception("Cannot delete name!") raise Exception("Cannot delete name!")
name = property(name_get, name_set, name_del) name = property(__name_get, __name_set, __name_del)
# typeclass_path property # typeclass_path property
#@property #@property
def typeclass_path_get(self): def __typeclass_path_get(self):
"Getter. Allows for value = self.typeclass_path" "Getter. Allows for value = self.typeclass_path"
return get_cache(self, "typeclass_path") return _get_cache(self, "typeclass_path")
#@typeclass_path.setter #@typeclass_path.setter
def typeclass_path_set(self, value): def __typeclass_path_set(self, value):
"Setter. Allows for self.typeclass_path = value" "Setter. Allows for self.typeclass_path = value"
set_cache(self, "typeclass_path", value) _set_cache(self, "typeclass_path", value)
#@typeclass_path.deleter #@typeclass_path.deleter
def typeclass_path_del(self): def __typeclass_path_del(self):
"Deleter. Allows for del self.typeclass_path" "Deleter. Allows for del self.typeclass_path"
self.db_typeclass_path = "" self.db_typeclass_path = ""
self.save() self.save()
del_cache(self, "typeclass_path") _del_cache(self, "typeclass_path")
typeclass_path = property(typeclass_path_get, typeclass_path_set, typeclass_path_del) typeclass_path = property(__typeclass_path_get, __typeclass_path_set, __typeclass_path_del)
# date_created property # date_created property
#@property #@property
def date_created_get(self): def __date_created_get(self):
"Getter. Allows for value = self.date_created" "Getter. Allows for value = self.date_created"
return get_cache(self, "date_created") return _get_cache(self, "date_created")
#@date_created.setter #@date_created.setter
def date_created_set(self, value): def __date_created_set(self, value):
"Setter. Allows for self.date_created = value" "Setter. Allows for self.date_created = value"
raise Exception("Cannot change date_created!") raise Exception("Cannot change date_created!")
#@date_created.deleter #@date_created.deleter
def date_created_del(self): def __date_created_del(self):
"Deleter. Allows for del self.date_created" "Deleter. Allows for del self.date_created"
raise Exception("Cannot delete date_created!") raise Exception("Cannot delete date_created!")
date_created = property(date_created_get, date_created_set, date_created_del) date_created = property(__date_created_get, __date_created_set, __date_created_del)
# permissions property # permissions property
#@property #@property
def permissions_get(self): def __permissions_get(self):
"Getter. Allows for value = self.name. Returns a list of permissions." "Getter. Allows for value = self.name. Returns a list of permissions."
perms = get_cache(self, "permissions") perms = _get_cache(self, "permissions")
if perms: if perms:
return [perm.strip() for perm in perms.split(',')] return [perm.strip() for perm in perms.split(',')]
return [] return []
#@permissions.setter #@permissions.setter
def permissions_set(self, value): def __permissions_set(self, value):
"Setter. Allows for self.name = value. Stores as a comma-separated string." "Setter. Allows for self.name = value. Stores as a comma-separated string."
value = ",".join([utils.to_unicode(val).strip() for val in make_iter(value)]) value = ",".join([utils.to_unicode(val).strip() for val in make_iter(value)])
set_cache(self, "permissions", value) _set_cache(self, "permissions", value)
#@permissions.deleter #@permissions.deleter
def permissions_del(self): def __permissions_del(self):
"Deleter. Allows for del self.name" "Deleter. Allows for del self.name"
self.db_permissions = "" self.db_permissions = ""
self.save() self.save()
del_cache(self, "permissions") _del_cache(self, "permissions")
permissions = property(permissions_get, permissions_set, permissions_del) permissions = property(__permissions_get, __permissions_set, __permissions_del)
# lock_storage property (wraps db_lock_storage) # lock_storage property (wraps db_lock_storage)
#@property #@property
def lock_storage_get(self): def __lock_storage_get(self):
"Getter. Allows for value = self.lock_storage" "Getter. Allows for value = self.lock_storage"
return get_cache(self, "lock_storage") return _get_cache(self, "lock_storage")
#@lock_storage.setter #@lock_storage.setter
def lock_storage_set(self, value): def __lock_storage_set(self, value):
"""Saves the lock_storagetodate. This is usually not called directly, but through self.lock()""" """Saves the lock_storagetodate. This is usually not called directly, but through self.lock()"""
set_cache(self, "lock_storage", value) _set_cache(self, "lock_storage", value)
#@lock_storage.deleter #@lock_storage.deleter
def lock_storage_del(self): def __lock_storage_del(self):
"Deleter is disabled. Use the lockhandler.delete (self.lock.delete) instead""" "Deleter is disabled. Use the lockhandler.delete (self.lock.delete) instead"""
logger.log_errmsg("Lock_Storage (on %s) cannot be deleted. Use obj.lock.delete() instead." % self) logger.log_errmsg("Lock_Storage (on %s) cannot be deleted. Use obj.lock.delete() instead." % self)
lock_storage = property(lock_storage_get, lock_storage_set, lock_storage_del) lock_storage = property(__lock_storage_get, __lock_storage_set, __lock_storage_del)
@ -844,9 +846,9 @@ class TypedObject(SharedMemoryModel):
# #
# these are identifiers for fast Attribute access and caching # these are identifiers for fast Attribute access and caching
typeclass_paths = settings.OBJECT_TYPECLASS_PATHS _typeclass_paths = settings.OBJECT_TYPECLASS_PATHS
attribute_class = Attribute # replaced by relevant attribute class for child _attribute_class = Attribute # replaced by relevant attribute class for child
db_model_name = "typeclass" # used by attributes to safely store objects _db_model_name = "typeclass" # used by attributes to safely store objects
def __eq__(self, other): def __eq__(self, other):
return other and hasattr(other, 'id') and self.id == other.id return other and hasattr(other, 'id') and self.id == other.id
@ -866,31 +868,31 @@ class TypedObject(SharedMemoryModel):
have to be very careful to avoid loops. have to be very careful to avoid loops.
""" """
try: try:
return GA(self, propname) return _GA(self, propname)
except AttributeError: except AttributeError:
# check if the attribute exists on the typeclass instead # check if the attribute exists on the typeclass instead
# (we make sure to not incur a loop by not triggering the # (we make sure to not incur a loop by not triggering the
# typeclass' __getattribute__, since that one would # typeclass' __getattribute__, since that one would
# try to look back to this very database object.) # try to look back to this very database object.)
typeclass = GA(self, 'typeclass') typeclass = _GA(self, 'typeclass')
if typeclass: if typeclass:
return GA(typeclass, propname) return _GA(typeclass, propname)
else: else:
raise AttributeError raise AttributeError
#@property #@property
def dbref_get(self): def __dbref_get(self):
""" """
Returns the object's dbref id on the form #NN. Returns the object's dbref id on the form #NN.
Alternetively, use obj.id directly to get dbref Alternetively, use obj.id directly to get dbref
without any #. without any #.
""" """
return "#%s" % str(GA(self, "id")) return "#%s" % str(_GA(self, "id"))
dbref = property(dbref_get) dbref = property(__dbref_get)
# typeclass property # typeclass property
#@property #@property
def typeclass_get(self): def __typeclass_get(self):
""" """
Getter. Allows for value = self.typeclass. Getter. Allows for value = self.typeclass.
The typeclass is a class object found at self.typeclass_path; The typeclass is a class object found at self.typeclass_path;
@ -898,15 +900,15 @@ class TypedObject(SharedMemoryModel):
types of objects that the game needs. This property types of objects that the game needs. This property
handles loading and initialization of the typeclass on the fly. handles loading and initialization of the typeclass on the fly.
Note: The liberal use of GA and __setattr__ (instead Note: The liberal use of _GA and __setattr__ (instead
of normal dot notation) is due to optimization: it avoids calling of normal dot notation) is due to optimization: it avoids calling
the custom self.__getattribute__ more than necessary. the custom self.__getattribute__ more than necessary.
""" """
path = GA(self, "typeclass_path") path = _GA(self, "typeclass_path")
typeclass = GA(self, "_cached_typeclass") typeclass = _GA(self, "_cached_typeclass")
try: try:
if typeclass and GA(typeclass, "path") == path: if typeclass and _GA(typeclass, "path") == path:
# don't call at_init() when returning from cache # don't call at_init() when returning from cache
return typeclass return typeclass
except AttributeError: except AttributeError:
@ -915,25 +917,25 @@ class TypedObject(SharedMemoryModel):
errstring = "" errstring = ""
if not path: if not path:
# this means we should get the default obj without giving errors. # this means we should get the default obj without giving errors.
return GA(self, "get_default_typeclass")(cache=True, silent=True, save=True) return _GA(self, "_get_default_typeclass")(cache=True, silent=True, save=True)
else: else:
# handle loading/importing of typeclasses, searching all paths. # handle loading/importing of typeclasses, searching all paths.
# (self.typeclass_paths is a shortcut to settings.TYPECLASS_*_PATHS # (self._typeclass_paths is a shortcut to settings.TYPECLASS_*_PATHS
# where '*' is either OBJECT, SCRIPT or PLAYER depending on the typed # where '*' is either OBJECT, SCRIPT or PLAYER depending on the typed
# entities). # entities).
typeclass_paths = [path] + ["%s.%s" % (prefix, path) for prefix in GA(self, 'typeclass_paths')] typeclass_paths = [path] + ["%s.%s" % (prefix, path) for prefix in _GA(self, '_typeclass_paths')]
for tpath in typeclass_paths: for tpath in typeclass_paths:
# try to import and analyze the result # try to import and analyze the result
typeclass = GA(self, "_path_import")(tpath) typeclass = _GA(self, "_path_import")(tpath)
if callable(typeclass): if callable(typeclass):
# we succeeded to import. Cache and return. # we succeeded to import. Cache and return.
SA(self, 'db_typeclass_path', tpath) _SA(self, 'db_typeclass_path', tpath)
GA(self, 'save')() _GA(self, 'save')()
SA(self, "_cached_db_typeclass_path", tpath) _SA(self, "_cached_db_typeclass_path", tpath)
typeclass = typeclass(self) typeclass = typeclass(self)
SA(self, "_cached_typeclass", typeclass) _SA(self, "_cached_typeclass", typeclass)
try: try:
typeclass.at_init() typeclass.at_init()
except Exception: except Exception:
@ -946,16 +948,16 @@ class TypedObject(SharedMemoryModel):
errstring += "\n%s" % typeclass # this will hold a growing error message. errstring += "\n%s" % typeclass # this will hold a growing error message.
# If we reach this point we couldn't import any typeclasses. Return default. It's up to the calling # If we reach this point we couldn't import any typeclasses. Return default. It's up to the calling
# method to use e.g. self.is_typeclass() to detect that the result is not the one asked for. # method to use e.g. self.is_typeclass() to detect that the result is not the one asked for.
GA(self, "_display_errmsg")(errstring) _GA(self, "_display_errmsg")(errstring)
return GA(self, "get_default_typeclass")(cache=False, silent=False, save=False) return _GA(self, "_get_default_typeclass")(cache=False, silent=False, save=False)
#@typeclass.deleter #@typeclass.deleter
def typeclass_del(self): def __typeclass_del(self):
"Deleter. Disallow 'del self.typeclass'" "Deleter. Disallow 'del self.typeclass'"
raise Exception("The typeclass property should never be deleted, only changed in-place!") raise Exception("The typeclass property should never be deleted, only changed in-place!")
# typeclass property # typeclass property
typeclass = property(typeclass_get, fdel=typeclass_del) typeclass = property(__typeclass_get, fdel=__typeclass_del)
def _path_import(self, path): def _path_import(self, path):
""" """
@ -1014,7 +1016,7 @@ class TypedObject(SharedMemoryModel):
else: else:
logger.log_trace(cmessage) logger.log_trace(cmessage)
def get_default_typeclass(self, cache=False, silent=False, save=False): def _get_default_typeclass(self, cache=False, silent=False, save=False):
""" """
This is called when a typeclass fails to This is called when a typeclass fails to
load for whatever reason. load for whatever reason.
@ -1022,34 +1024,34 @@ class TypedObject(SharedMemoryModel):
Default operation is to load a default typeclass. Default operation is to load a default typeclass.
""" """
defpath = GA(self, "default_typeclass_path") defpath = _GA(self, "_default_typeclass_path")
typeclass = GA(self, "_path_import")(defpath) typeclass = _GA(self, "_path_import")(defpath)
# if not silent: # if not silent:
# #errstring = "\n\nUsing Default class '%s'." % defpath # #errstring = "\n\nUsing Default class '%s'." % defpath
# GA(self, "_display_errmsg")(errstring) # _GA(self, "_display_errmsg")(errstring)
if not callable(typeclass): if not callable(typeclass):
# if typeclass still doesn't exist at this point, we're in trouble. # if typeclass still doesn't exist at this point, we're in trouble.
# fall back to hardcoded core class which is wrong for e.g. scripts/players etc. # fall back to hardcoded core class which is wrong for e.g. scripts/players etc.
failpath = defpath failpath = defpath
defpath = "src.objects.objects.Object" defpath = "src.objects.objects.Object"
typeclass = GA(self, "_path_import")(defpath) typeclass = _GA(self, "_path_import")(defpath)
if not silent: if not silent:
#errstring = " %s\n%s" % (typeclass, errstring) #errstring = " %s\n%s" % (typeclass, errstring)
errstring = " Default class '%s' failed to load." % failpath errstring = " Default class '%s' failed to load." % failpath
errstring += "\n Using Evennia's default class '%s'." % defpath errstring += "\n Using Evennia's default class '%s'." % defpath
GA(self, "_display_errmsg")(errstring) _GA(self, "_display_errmsg")(errstring)
if not callable(typeclass): if not callable(typeclass):
# if this is still giving an error, Evennia is wrongly configured or buggy # if this is still giving an error, Evennia is wrongly configured or buggy
raise Exception("CRITICAL ERROR: The final fallback typeclass %s cannot load!!" % defpath) raise Exception("CRITICAL ERROR: The final fallback typeclass %s cannot load!!" % defpath)
typeclass = typeclass(self) typeclass = typeclass(self)
if save: if save:
SA(self, 'db_typeclass_path', defpath) _SA(self, 'db_typeclass_path', defpath)
GA(self, 'save')() _GA(self, 'save')()
if cache: if cache:
SA(self, "_cached_db_typeclass_path", defpath) _SA(self, "_cached_db_typeclass_path", defpath)
SA(self, "_cached_typeclass", typeclass) _SA(self, "_cached_typeclass", typeclass)
try: try:
typeclass.at_init() typeclass.at_init()
except Exception: except Exception:
@ -1070,17 +1072,17 @@ class TypedObject(SharedMemoryModel):
parents. parents.
""" """
try: try:
typeclass = GA(typeclass, "path") typeclass = _GA(typeclass, "path")
except AttributeError: except AttributeError:
pass pass
typeclasses = [typeclass] + ["%s.%s" % (path, typeclass) for path in GA(self, "typeclass_paths")] typeclasses = [typeclass] + ["%s.%s" % (path, typeclass) for path in _GA(self, "_typeclass_paths")]
if exact: if exact:
current_path = GA(self, "_cached_db_typeclass_path") current_path = _GA(self, "_cached_db_typeclass_path")
return typeclass and any((current_path == typec for typec in typeclasses)) return typeclass and any((current_path == typec for typec in typeclasses))
else: else:
# check parent chain # check parent chain
return any((cls for cls in self.typeclass.__class__.mro() return any((cls for cls in self.typeclass.__class__.mro()
if any(("%s.%s" % (GA(cls,"__module__"), GA(cls,"__name__")) == typec for typec in typeclasses)))) if any(("%s.%s" % (_GA(cls,"__module__"), _GA(cls,"__name__")) == typec for typec in typeclasses))))
# #
# Object manipulation methods # Object manipulation methods
@ -1135,13 +1137,13 @@ class TypedObject(SharedMemoryModel):
new_typeclass = self.typeclass new_typeclass = self.typeclass
if self.typeclass_path == new_typeclass.path: if self.typeclass_path == new_typeclass.path:
# the typeclass loading worked as expected # the typeclass loading worked as expected
DA(self, "_cached_db_typeclass_path") _DA(self, "_cached_db_typeclass_path")
SA(self, "_cached_typeclass", None) _SA(self, "_cached_typeclass", None)
elif no_default: elif no_default:
# something went wrong; the default was loaded instead, # something went wrong; the default was loaded instead,
# and we don't allow that; instead we return to previous. # and we don't allow that; instead we return to previous.
SA(self, "typeclass_path", old_typeclass_path) _SA(self, "typeclass_path", old_typeclass_path)
SA(self, "_cached_typeclass", None) _SA(self, "_cached_typeclass", None)
return False return False
if clean_attributes: if clean_attributes:
@ -1181,7 +1183,7 @@ class TypedObject(SharedMemoryModel):
attribute_name: (str) The attribute's name. attribute_name: (str) The attribute's name.
""" """
return GA(self, "attribute_class").objects.filter(db_obj=self).filter( return _GA(self, "_attribute_class").objects.filter(db_obj=self).filter(
db_key__iexact=attribute_name).count() db_key__iexact=attribute_name).count()
def set_attribute(self, attribute_name, new_value=None): def set_attribute(self, attribute_name, new_value=None):
@ -1194,7 +1196,7 @@ class TypedObject(SharedMemoryModel):
a str, the object will be stored as a pickle. a str, the object will be stored as a pickle.
""" """
attrib_obj = None attrib_obj = None
attrclass = GA(self, "attribute_class") attrclass = _GA(self, "_attribute_class")
try: try:
# use old attribute # use old attribute
attrib_obj = attrclass.objects.filter( attrib_obj = attrclass.objects.filter(
@ -1216,7 +1218,7 @@ class TypedObject(SharedMemoryModel):
""" """
attrib_obj = default attrib_obj = default
try: try:
attrib_obj = self.attribute_class.objects.filter( attrib_obj = _GA(self, "_attribute_class").objects.filter(
db_obj=self).filter(db_key__iexact=attribute_name)[0] db_obj=self).filter(db_key__iexact=attribute_name)[0]
except IndexError: except IndexError:
return default return default
@ -1230,7 +1232,7 @@ class TypedObject(SharedMemoryModel):
attribute_name: (str) The attribute's name. attribute_name: (str) The attribute's name.
""" """
try: try:
return self.attribute_class.objects.filter( return _GA(self, "_attribute_class").objects.filter(
db_obj=self).filter(db_key__iexact=attribute_name)[0].value db_obj=self).filter(db_key__iexact=attribute_name)[0].value
except IndexError: except IndexError:
raise AttributeError raise AttributeError
@ -1242,7 +1244,7 @@ class TypedObject(SharedMemoryModel):
attribute_name: (str) The attribute's name. attribute_name: (str) The attribute's name.
""" """
try: try:
self.attribute_class.objects.filter( _GA(self, "_attribute_class").objects.filter(
db_obj=self).filter(db_key__iexact=attribute_name)[0].delete() db_obj=self).filter(db_key__iexact=attribute_name)[0].delete()
except IndexError: except IndexError:
pass pass
@ -1255,7 +1257,7 @@ class TypedObject(SharedMemoryModel):
attribute_name: (str) The attribute's name. attribute_name: (str) The attribute's name.
""" """
try: try:
self.attribute_class.objects.filter( _GA(self, "_attribute_class").objects.filter(
db_obj=self).filter(db_key__iexact=attribute_name)[0].delete() db_obj=self).filter(db_key__iexact=attribute_name)[0].delete()
except IndexError: except IndexError:
raise AttributeError raise AttributeError
@ -1264,7 +1266,7 @@ class TypedObject(SharedMemoryModel):
""" """
Returns all attributes defined on the object. Returns all attributes defined on the object.
""" """
return list(self.attribute_class.objects.filter(db_obj=self)) return list(_GA(self,"_attribute_class").objects.filter(db_obj=self))
def attr(self, attribute_name=None, value=None, delete=False): def attr(self, attribute_name=None, value=None, delete=False):
""" """
@ -1291,7 +1293,7 @@ class TypedObject(SharedMemoryModel):
self.set_attribute(attribute_name, value) self.set_attribute(attribute_name, value)
#@property #@property
def db_get(self): def __db_get(self):
""" """
A second convenience wrapper for the the attribute methods. It A second convenience wrapper for the the attribute methods. It
allows for the syntax allows for the syntax
@ -1310,35 +1312,35 @@ class TypedObject(SharedMemoryModel):
class DbHolder(object): class DbHolder(object):
"Holder for allowing property access of attributes" "Holder for allowing property access of attributes"
def __init__(self, obj): def __init__(self, obj):
SA(self, 'obj', obj) _SA(self, 'obj', obj)
def __getattribute__(self, attrname): def __getattribute__(self, attrname):
if attrname == 'all': if attrname == 'all':
# we allow for overwriting the all() method # we allow for overwriting the all() method
# with an attribute named 'all'. # with an attribute named 'all'.
attr = GA(self, 'obj').get_attribute("all") attr = _GA(self, 'obj').get_attribute("all")
if attr: if attr:
return attr return attr
return GA(self, 'all') return _GA(self, 'all')
return GA(self, 'obj').get_attribute(attrname) return _GA(self, 'obj').get_attribute(attrname)
def __setattr__(self, attrname, value): def __setattr__(self, attrname, value):
GA(self, 'obj').set_attribute(attrname, value) _GA(self, 'obj').set_attribute(attrname, value)
def __delattr__(self, attrname): def __delattr__(self, attrname):
GA(self, 'obj').del_attribute(attrname) _GA(self, 'obj').del_attribute(attrname)
def all(self): def all(self):
return GA(self, 'obj').get_all_attributes() return _GA(self, 'obj').get_all_attributes()
self._db_holder = DbHolder(self) self._db_holder = DbHolder(self)
return self._db_holder return self._db_holder
#@db.setter #@db.setter
def db_set(self, value): def __db_set(self, value):
"Stop accidentally replacing the db object" "Stop accidentally replacing the db object"
string = "Cannot assign directly to db object! " string = "Cannot assign directly to db object! "
string += "Use db.attr=value instead." string += "Use db.attr=value instead."
raise Exception(string) raise Exception(string)
#@db.deleter #@db.deleter
def db_del(self): def __db_del(self):
"Stop accidental deletion." "Stop accidental deletion."
raise Exception("Cannot delete the db object!") raise Exception("Cannot delete the db object!")
db = property(db_get, db_set, db_del) db = property(__db_get, __db_set, __db_del)
# #
# NON-PERSISTENT storage methods # NON-PERSISTENT storage methods
@ -1358,19 +1360,19 @@ class TypedObject(SharedMemoryModel):
if not val.startswith['_']] if not val.startswith['_']]
elif delete == True: elif delete == True:
if hasattr(self.ndb, attribute_name): if hasattr(self.ndb, attribute_name):
DA(self.db, attribute_name) _DA(self.db, attribute_name)
elif value == None: elif value == None:
# act as a getter. # act as a getter.
if hasattr(self.ndb, attribute_name): if hasattr(self.ndb, attribute_name):
GA(self.ndb, attribute_name) _GA(self.ndb, attribute_name)
else: else:
return None return None
else: else:
# act as a setter # act as a setter
SA(self.db, attribute_name, value) _SA(self.db, attribute_name, value)
#@property #@property
def ndb_get(self): def __ndb_get(self):
""" """
A non-persistent store (ndb: NonDataBase). Everything stored A non-persistent store (ndb: NonDataBase). Everything stored
to this is guaranteed to be cleared when a server is shutdown. to this is guaranteed to be cleared when a server is shutdown.
@ -1388,22 +1390,22 @@ class TypedObject(SharedMemoryModel):
def __getattribute__(self, key): def __getattribute__(self, key):
# return None if no matching attribute was found. # return None if no matching attribute was found.
try: try:
return GA(self, key) return _GA(self, key)
except AttributeError: except AttributeError:
return None return None
self._ndb_holder = NdbHolder() self._ndb_holder = NdbHolder()
return self._ndb_holder return self._ndb_holder
#@ndb.setter #@ndb.setter
def ndb_set(self, value): def __ndb_set(self, value):
"Stop accidentally replacing the db object" "Stop accidentally replacing the db object"
string = "Cannot assign directly to ndb object! " string = "Cannot assign directly to ndb object! "
string = "Use ndb.attr=value instead." string = "Use ndb.attr=value instead."
raise Exception(string) raise Exception(string)
#@ndb.deleter #@ndb.deleter
def ndb_del(self): def __ndb_del(self):
"Stop accidental deletion." "Stop accidental deletion."
raise Exception("Cannot delete the ndb object!") raise Exception("Cannot delete the ndb object!")
ndb = property(ndb_get, ndb_set, ndb_del) ndb = property(__ndb_get, __ndb_set, __ndb_del)
# #
# Lock / permission methods # Lock / permission methods
@ -1437,9 +1439,9 @@ class TypedObject(SharedMemoryModel):
if perm in [p.lower() for p in self.permissions]: if perm in [p.lower() for p in self.permissions]:
# simplest case - we have a direct match # simplest case - we have a direct match
return True return True
if perm in PERMISSION_HIERARCHY: if perm in _PERMISSION_HIERARCHY:
# check if we have a higher hierarchy position # check if we have a higher hierarchy position
ppos = PERMISSION_HIERARCHY.index(perm) ppos = _PERMISSION_HIERARCHY.index(perm)
return any(True for hpos, hperm in enumerate(PERMISSION_HIERARCHY) return any(True for hpos, hperm in enumerate(_PERMISSION_HIERARCHY)
if hperm in [p.lower() for p in self.permissions] and hpos > ppos) if hperm in [p.lower() for p in self.permissions] and hpos > ppos)
return False return False

View file

@ -14,9 +14,9 @@ from src.utils.logger import log_trace, log_errmsg
from django.conf import settings from django.conf import settings
# these are called so many times it's worth to avoid lookup calls # these are called so many times it's worth to avoid lookup calls
GA = object.__getattribute__ _GA = object.__getattribute__
SA = object.__setattr__ _SA = object.__setattr__
DA = object.__delattr__ _DA = object.__delattr__
# To ensure the sanity of the model, there are a # To ensure the sanity of the model, there are a
# few property names we won't allow the admin to # few property names we won't allow the admin to
@ -75,13 +75,13 @@ class TypeClass(object):
""" """
# typecheck of dbobj - we can't allow it to be added here # typecheck of dbobj - we can't allow it to be added here
# unless it's really a TypedObject. # unless it's really a TypedObject.
dbobj_cls = GA(dbobj, '__class__') dbobj_cls = _GA(dbobj, '__class__')
dbobj_mro = GA(dbobj_cls, '__mro__') dbobj_mro = _GA(dbobj_cls, '__mro__')
if not any('src.typeclasses.models.TypedObject' in str(mro) for mro in dbobj_mro): if not any('src.typeclasses.models.TypedObject' in str(mro) for mro in dbobj_mro):
raise Exception("dbobj is not a TypedObject: %s: %s" % (dbobj_cls, dbobj_mro)) raise Exception("dbobj is not a TypedObject: %s: %s" % (dbobj_cls, dbobj_mro))
# store the reference to the database model instance # store the reference to the database model instance
SA(self, 'dbobj', dbobj) _SA(self, 'dbobj', dbobj)
def __getattribute__(self, propname): def __getattribute__(self, propname):
""" """
@ -93,25 +93,25 @@ class TypeClass(object):
accessible through getattr. accessible through getattr.
""" """
if propname == 'dbobj': if propname == 'dbobj':
return GA(self, 'dbobj') return _GA(self, 'dbobj')
if propname.startswith('__') and propname.endswith('__'): if propname.startswith('__') and propname.endswith('__'):
# python specials are parsed as-is (otherwise things like # python specials are parsed as-is (otherwise things like
# isinstance() fail to identify the typeclass) # isinstance() fail to identify the typeclass)
return GA(self, propname) return _GA(self, propname)
#print "get %s (dbobj:%s)" % (propname, type(dbobj)) #print "get %s (dbobj:%s)" % (propname, type(dbobj))
try: try:
return GA(self, propname) return _GA(self, propname)
except AttributeError: except AttributeError:
try: try:
dbobj = GA(self, 'dbobj') dbobj = _GA(self, 'dbobj')
except AttributeError: except AttributeError:
log_trace("Typeclass CRITICAL ERROR! dbobj not found for Typeclass %s!" % self) log_trace("Typeclass CRITICAL ERROR! dbobj not found for Typeclass %s!" % self)
raise raise
try: try:
return GA(dbobj, propname) return _GA(dbobj, propname)
except AttributeError: except AttributeError:
try: try:
return GA(dbobj,"get_attribute_raise")(propname) return _GA(dbobj,"get_attribute_raise")(propname)
except AttributeError: except AttributeError:
string = "Object: '%s' not found on %s(%s), nor on its typeclass %s." string = "Object: '%s' not found on %s(%s), nor on its typeclass %s."
raise AttributeError(string % (propname, dbobj, dbobj.dbref, dbobj.typeclass_path)) raise AttributeError(string % (propname, dbobj, dbobj.dbref, dbobj.typeclass_path))
@ -132,7 +132,7 @@ class TypeClass(object):
return return
try: try:
dbobj = GA(self, 'dbobj') dbobj = _GA(self, 'dbobj')
except AttributeError: except AttributeError:
dbobj = None dbobj = None
log_trace("This is probably due to an unsafe reload.") log_trace("This is probably due to an unsafe reload.")
@ -141,19 +141,19 @@ class TypeClass(object):
try: try:
# only set value on propname if propname already exists # only set value on propname if propname already exists
# on dbobj. __getattribute__ will raise attribute error otherwise. # on dbobj. __getattribute__ will raise attribute error otherwise.
GA(dbobj, propname) _GA(dbobj, propname)
SA(dbobj, propname, value) _SA(dbobj, propname, value)
except AttributeError: except AttributeError:
dbobj.set_attribute(propname, value) dbobj.set_attribute(propname, value)
else: else:
SA(self, propname, value) _SA(self, propname, value)
def __eq__(self, other): def __eq__(self, other):
""" """
dbobj-recognized comparison dbobj-recognized comparison
""" """
try: try:
return other == self or other == GA(self, dbobj) or other == GA(self, dbobj).user return other == self or other == _GA(self, dbobj) or other == _GA(self, dbobj).user
except AttributeError: except AttributeError:
# if self.dbobj.user fails it means the two previous comparisons failed already # if self.dbobj.user fails it means the two previous comparisons failed already
return False return False
@ -172,11 +172,11 @@ class TypeClass(object):
return return
try: try:
DA(self, propname) _DA(self, propname)
except AttributeError: except AttributeError:
# not on typeclass, try to delete on db/ndb # not on typeclass, try to delete on db/ndb
try: try:
dbobj = GA(self, 'dbobj') dbobj = _GA(self, 'dbobj')
except AttributeError: except AttributeError:
log_trace("This is probably due to an unsafe reload.") log_trace("This is probably due to an unsafe reload.")
return # ignore delete return # ignore delete