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.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.objects.manager import ObjectManager
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()
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__
SA = object.__setattr__
DA = object.__delattr__
_GA = object.__getattribute__
_SA = object.__setattr__
_DA = object.__delattr__
#------------------------------------------------------------
#
@ -214,10 +214,10 @@ class ObjectDB(TypedObject):
def aliases_get(self):
"Getter. Allows for value = self.aliases"
try:
return GA(self, "_cached_aliases")
return _GA(self, "_cached_aliases")
except AttributeError:
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
#@aliases.setter
def aliases_set(self, aliases):
@ -225,13 +225,13 @@ class ObjectDB(TypedObject):
for alias in make_iter(aliases):
new_alias = Alias(db_key=alias, db_obj=self)
new_alias.save()
SA(self, "_cached_aliases", aliases)
_SA(self, "_cached_aliases", aliases)
#@aliases.deleter
def aliases_del(self):
"Deleter. Allows for del self.aliases"
for alias in Alias.objects.filter(db_obj=self):
alias.delete()
DA(self, "_cached_aliases")
_DA(self, "_cached_aliases")
aliases = property(aliases_get, aliases_set, aliases_del)
# player property (wraps db_player)
@ -242,26 +242,26 @@ class ObjectDB(TypedObject):
We have to be careful here since Player is also
a TypedObject, so as to not create a loop.
"""
return get_cache(self, "player")
return _get_cache(self, "player")
#@player.setter
def player_set(self, player):
"Setter. Allows for self.player = value"
if isinstance(player, TypeClass):
player = player.dbobj
set_cache(self, "player", player)
_set_cache(self, "player", player)
#@player.deleter
def player_del(self):
"Deleter. Allows for del self.player"
self.db_player = None
self.save()
del_cache(self, "player")
_del_cache(self, "player")
player = property(player_get, player_set, player_del)
# location property (wraps db_location)
#@property
def location_get(self):
"Getter. Allows for value = self.location."
loc = get_cache(self, "location")
loc = _get_cache(self, "location")
if loc:
return loc.typeclass
return None
@ -281,7 +281,7 @@ class ObjectDB(TypedObject):
loc = location.dbobj
else:
loc = location.dbobj
set_cache(self, "location", loc)
_set_cache(self, "location", loc)
except Exception:
string = "Cannot set location: "
string += "%s is not a valid location."
@ -293,14 +293,14 @@ class ObjectDB(TypedObject):
"Deleter. Allows for del self.location"
self.db_location = None
self.save()
del_cache()
_del_cache(self, "location")
location = property(location_get, location_set, location_del)
# home property (wraps db_home)
#@property
def home_get(self):
"Getter. Allows for value = self.home"
home = get_cache(self, "home")
home = _get_cache(self, "home")
if home:
return home.typeclass
return None
@ -318,7 +318,7 @@ class ObjectDB(TypedObject):
hom = home.dbobj
else:
hom = home.dbobj
set_cache(self, "home", hom)
_set_cache(self, "home", hom)
except Exception:
string = "Cannot set home: "
string += "%s is not a valid home."
@ -330,14 +330,14 @@ class ObjectDB(TypedObject):
"Deleter. Allows for del self.home."
self.db_home = None
self.save()
del_cache(self, "home")
_del_cache(self, "home")
home = property(home_get, home_set, home_del)
# destination property (wraps db_destination)
#@property
def destination_get(self):
"Getter. Allows for value = self.destination."
dest = get_cache(self, "destination")
dest = _get_cache(self, "destination")
if dest:
return dest.typeclass
return None
@ -357,7 +357,7 @@ class ObjectDB(TypedObject):
dest = destination.dbobj
else:
dest = destination.dbobj
set_cache(self, "destination", dest)
_set_cache(self, "destination", dest)
except Exception:
string = "Cannot set destination: "
string += "%s is not a valid destination."
@ -369,7 +369,7 @@ class ObjectDB(TypedObject):
"Deleter. Allows for del self.destination"
self.db_destination = None
self.save()
del_cache(self, "destination")
_del_cache(self, "destination")
destination = property(destination_get, destination_set, destination_del)
# cmdset_storage property.
@ -403,17 +403,10 @@ class ObjectDB(TypedObject):
#
# this is required to properly handle attributes and typeclass loading.
#attribute_model_path = "src.objects.models"
#attribute_model_name = "ObjAttribute"
typeclass_paths = settings.OBJECT_TYPECLASS_PATHS
attribute_class = ObjAttribute
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"
_typeclass_paths = settings.OBJECT_TYPECLASS_PATHS
_attribute_class = ObjAttribute
_db_model_name = "objectdb" # used by attributes to safely store objects
_default_typeclass_path = settings.BASE_OBJECT_TYPECLASS or "src.objects.objects.Object"
#@property
def sessions_get(self):
@ -533,7 +526,7 @@ class ObjectDB(TypedObject):
if ignore_errors:
return results
# 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

View file

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

View file

@ -11,7 +11,7 @@ handled by Scripts.
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.
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:
- 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.
- Weather patterns in-game
- merge a new cmdset with the default one for changing which
commands are available at a particular time
- give the player/object a time-limited bonus/effect
commands are available at a particular time
- give the player/object a time-limited bonus/effect
"""
from django.conf import settings
@ -45,7 +45,7 @@ class ScriptAttribute(Attribute):
verbose_name = "Script Attribute"
verbose_name_plural = "Script Attributes"
#------------------------------------------------------------
#
# ScriptDB
@ -54,7 +54,7 @@ class ScriptAttribute(Attribute):
class ScriptDB(TypedObject):
"""
The Script database representation.
The Script database representation.
The TypedObject supplies the following (inherited) properties:
key - main name
@ -62,10 +62,10 @@ class ScriptDB(TypedObject):
typeclass_path - the path to the decorating typeclass
typeclass - auto-linked typeclass
date_created - time stamp of object creation
permissions - perm strings
dbref - #id of object
permissions - perm strings
dbref - #id of object
db - persistent attribute storage
ndb - non-persistent attribute storage
ndb - non-persistent attribute storage
The ScriptDB adds the following properties:
desc - optional description of script
@ -74,21 +74,21 @@ class ScriptDB(TypedObject):
start_delay - if the script should start repeating right away
repeats - how many times the script should repeat
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
#
# These databse fields are all set using their corresponding properties,
# 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
# optional description.
# optional description.
db_desc = models.CharField('desc', max_length=255, blank=True)
# 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',
@ -106,7 +106,7 @@ class ScriptDB(TypedObject):
# Database manager
objects = ScriptManager()
class Meta:
"Define Django meta options"
verbose_name = "Script"
@ -115,8 +115,8 @@ class ScriptDB(TypedObject):
# @property decorators that allows to access these fields using
# normal python operations (without having to remember to save()
# etc). So e.g. a property 'attr' has a get/set/del decorator
# defined that allows the user to do self.attr = value,
# value = self.attr and del self.attr respectively (where self
# defined that allows the user to do self.attr = value,
# value = self.attr and del self.attr respectively (where self
# is the script in question).
# desc property (wraps db_desc)
@ -186,7 +186,7 @@ class ScriptDB(TypedObject):
self.db_start_delay = False
self.save()
start_delay = property(start_delay_get, start_delay_set, start_delay_del)
# repeats property (wraps db_repeats)
#@property
def repeats_get(self):
@ -221,7 +221,7 @@ class ScriptDB(TypedObject):
self.save()
persistent = property(persistent_get, persistent_set, persistent_del)
# is_active property (wraps db_is_active)
# is_active property (wraps db_is_active)
#@property
def is_active_get(self):
"Getter. Allows for value = self.is_active"
@ -245,33 +245,26 @@ class ScriptDB(TypedObject):
#
# this is required to properly handle attributes and typeclass loading
#attribute_model_path = "src.scripts.models"
#attribute_model_name = "ScriptAttribute"
typeclass_paths = settings.SCRIPT_TYPECLASS_PATHS
attribute_class = ScriptAttribute
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"
_typeclass_paths = settings.SCRIPT_TYPECLASS_PATHS
_attribute_class = ScriptAttribute
_db_model_name = "scriptdb" # used by attributes to safely store objects
_default_typeclass_path = settings.BASE_SCRIPT_TYPECLASS or "src.scripts.scripts.DoNothing"
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
to be created under those circumstances. Already created,
permanent scripts are set to already be active so they
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".
self.is_active = True
self.is_active = True
return super(ScriptDB, self).at_typeclass_error()
delete_iter = 0
def delete(self):
if self.delete_iter > 0:
return
return
self.delete_iter += 1
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.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
GA = object.__getattribute__
SA = object.__setattr__
DA = object.__delattr__
PLOADS = pickle.loads
PDUMPS = pickle.dumps
_CTYPEGET = ContentType.objects.get
_GA = object.__getattribute__
_SA = object.__setattr__
_DA = object.__delattr__
_PLOADS = pickle.loads
_PDUMPS = pickle.dumps
# Property Cache mechanism.
def get_cache(obj, name):
def _get_cache(obj, name):
"On-model Cache handler."
try:
return GA(obj, "_cached_db_%s" % name)
return _GA(obj, "_cached_db_%s" % name)
except AttributeError:
val = GA(obj, "db_%s" % name)
if val: SA(obj, "_cached_db_%s" % name, val)
val = _GA(obj, "db_%s" % name)
if val: _SA(obj, "_cached_db_%s" % name, val)
return val
def set_cache(obj, name, val):
def _set_cache(obj, name, val):
"On-model Cache setter"
SA(obj, "db_%s" % name, val)
GA(obj, "save")()
SA(obj, "_cached_db_%s" % name, val)
_SA(obj, "db_%s" % name, val)
_GA(obj, "save")()
_SA(obj, "_cached_db_%s" % name, val)
def del_cache(obj, name):
def _del_cache(obj, name):
"On-model cache deleter"
try:
DA(obj, "_cached_db_%s" % name)
_DA(obj, "_cached_db_%s" % name)
except AttributeError:
pass
@ -290,61 +290,61 @@ class Attribute(SharedMemoryModel):
# key property (wraps db_key)
#@property
def key_get(self):
def __key_get(self):
"Getter. Allows for value = self.key"
return get_cache(self, "key")
return _get_cache(self, "key")
#@key.setter
def key_set(self, value):
def __key_set(self, value):
"Setter. Allows for self.key = value"
set_cache(self, "key", value)
_set_cache(self, "key", value)
#@key.deleter
def key_del(self):
def __key_del(self):
"Deleter. Allows for del self.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)
#@property
def obj_get(self):
def __obj_get(self):
"Getter. Allows for value = self.obj"
return get_cache(self, "obj")
return _get_cache(self, "obj")
#@obj.setter
def obj_set(self, value):
def __obj_set(self, value):
"Setter. Allows for self.obj = value"
set_cache(self, "obj", value)
_set_cache(self, "obj", value)
#@obj.deleter
def obj_del(self):
def __obj_del(self):
"Deleter. Allows for del self.obj"
self.db_obj = None
self.save()
del_cache(self, "obj")
obj = property(obj_get, obj_set, obj_del)
_del_cache(self, "obj")
obj = property(__obj_get, __obj_set, __obj_del)
# date_created property (wraps db_date_created)
#@property
def date_created_get(self):
def __date_created_get(self):
"Getter. Allows for value = self.date_created"
return get_cache(self, "date_created")
return _get_cache(self, "date_created")
#@date_created.setter
def date_created_set(self, value):
def __date_created_set(self, value):
"Setter. Allows for self.date_created = value"
raise Exception("Cannot edit date_created!")
#@date_created.deleter
def date_created_del(self):
def __date_created_del(self):
"Deleter. Allows for del self.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)
#@property
def value_get(self):
def __value_get(self):
"""
Getter. Allows for value = self.value. Reads from cache if possible.
"""
if self.no_cache:
# re-create data from database and cache it
try:
value = self.from_attr(PLOADS(to_str(self.db_value)))
value = self.__from_attr(_PLOADS(to_str(self.db_value)))
except pickle.UnpicklingError:
value = self.db_value
self.cached_value = value
@ -355,36 +355,36 @@ class Attribute(SharedMemoryModel):
return self.cached_value
#@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.
"""
new_value = self.to_attr(new_value)
self.cached_value = self.from_attr(new_value)
new_value = self.__to_attr(new_value)
self.cached_value = self.__from_attr(new_value)
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()
#@value.deleter
def value_del(self):
def __value_del(self):
"Deleter. Allows for del attr.value. This removes the entire attribute."
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)
#@property
def lock_storage_get(self):
def __lock_storage_get(self):
"Getter. Allows for value = self.lock_storage"
return get_cache(self, "lock_storage")
return _get_cache(self, "lock_storage")
#@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()"""
self.db_lock_storage = value
self.save()
#@lock_storage.deleter
def lock_storage_del(self):
def __lock_storage_del(self):
"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)
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
def to_attr(self, data):
def __to_attr(self, data):
"""
Convert data to proper attr data format before saving
@ -434,10 +434,10 @@ class Attribute(SharedMemoryModel):
dtype = type(item)
if dtype in (basestring, int, float): # check the most common types first, for speed
return item
elif hasattr(item, "id") and hasattr(item, "db_model_name") and hasattr(item, "db_key"):
db_model_name = item.db_model_name
elif hasattr(item, "id") and hasattr(item, "_db_model_name") and hasattr(item, "db_key"):
db_model_name = item._db_model_name # don't use _GA here, could be 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)
elif dtype == tuple:
return tuple(iter_db2id(val) for val in item)
@ -452,13 +452,13 @@ class Attribute(SharedMemoryModel):
if dtype in (basestring, int, float):
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)
# have the protected property db_model_name hardcoded on themselves for speed.
db_model_name = data.db_model_name
# have the protected property _db_model_name hardcoded on themselves for speed.
db_model_name = data._db_model_name # don't use _GA here, could be typeclass
if db_model_name == "typeclass":
# 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))
elif hasattr(data, "__iter__"):
return ("iter", iter_db2id(data))
@ -466,7 +466,7 @@ class Attribute(SharedMemoryModel):
return ("simple", data)
def from_attr(self, datatuple):
def __from_attr(self, datatuple):
"""
Retrieve data from a previously stored attribute. This
is always a dict with keys type and data.
@ -488,7 +488,7 @@ class Attribute(SharedMemoryModel):
"""
Convert db-stored dbref back to object
"""
mclass = CTYPEGET(model=data.db_model).model_class()
mclass = _CTYPEGET(model=data.db_model).model_class()
try:
return mclass.objects.dbref_search(data.id)
@ -636,9 +636,11 @@ class TypeNickHandler(object):
# remove the found nick(s)
query.delete()
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.
Defaults to searching the current object."""
Defaults to searching the current object.
"""
if not obj:
# defaults to the current object
obj = self.obj
@ -739,101 +741,101 @@ class TypedObject(SharedMemoryModel):
# key property (wraps db_key)
#@property
def key_get(self):
def __key_get(self):
"Getter. Allows for value = self.key"
return get_cache(self, "key")
return _get_cache(self, "key")
#@key.setter
def key_set(self, value):
def __key_set(self, value):
"Setter. Allows for self.key = value"
set_cache(self, "key", value)
_set_cache(self, "key", value)
#@key.deleter
def key_del(self):
def __key_del(self):
"Deleter. Allows for del self.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)
#@property
def name_get(self):
def __name_get(self):
"Getter. Allows for value = self.name"
return get_cache(self, "key")
return _get_cache(self, "key")
#@name.setter
def name_set(self, value):
def __name_set(self, value):
"Setter. Allows for self.name = value"
set_cache(self, "key", value)
_set_cache(self, "key", value)
#@name.deleter
def name_del(self):
def __name_del(self):
"Deleter. Allows for del self.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
#@property
def typeclass_path_get(self):
def __typeclass_path_get(self):
"Getter. Allows for value = self.typeclass_path"
return get_cache(self, "typeclass_path")
return _get_cache(self, "typeclass_path")
#@typeclass_path.setter
def typeclass_path_set(self, value):
def __typeclass_path_set(self, value):
"Setter. Allows for self.typeclass_path = value"
set_cache(self, "typeclass_path", value)
_set_cache(self, "typeclass_path", value)
#@typeclass_path.deleter
def typeclass_path_del(self):
def __typeclass_path_del(self):
"Deleter. Allows for del self.typeclass_path"
self.db_typeclass_path = ""
self.save()
del_cache(self, "typeclass_path")
typeclass_path = property(typeclass_path_get, typeclass_path_set, typeclass_path_del)
_del_cache(self, "typeclass_path")
typeclass_path = property(__typeclass_path_get, __typeclass_path_set, __typeclass_path_del)
# date_created property
#@property
def date_created_get(self):
def __date_created_get(self):
"Getter. Allows for value = self.date_created"
return get_cache(self, "date_created")
return _get_cache(self, "date_created")
#@date_created.setter
def date_created_set(self, value):
def __date_created_set(self, value):
"Setter. Allows for self.date_created = value"
raise Exception("Cannot change date_created!")
#@date_created.deleter
def date_created_del(self):
def __date_created_del(self):
"Deleter. Allows for del self.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
#@property
def permissions_get(self):
def __permissions_get(self):
"Getter. Allows for value = self.name. Returns a list of permissions."
perms = get_cache(self, "permissions")
perms = _get_cache(self, "permissions")
if perms:
return [perm.strip() for perm in perms.split(',')]
return []
#@permissions.setter
def permissions_set(self, value):
def __permissions_set(self, value):
"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)])
set_cache(self, "permissions", value)
_set_cache(self, "permissions", value)
#@permissions.deleter
def permissions_del(self):
def __permissions_del(self):
"Deleter. Allows for del self.name"
self.db_permissions = ""
self.save()
del_cache(self, "permissions")
permissions = property(permissions_get, permissions_set, permissions_del)
_del_cache(self, "permissions")
permissions = property(__permissions_get, __permissions_set, __permissions_del)
# lock_storage property (wraps db_lock_storage)
#@property
def lock_storage_get(self):
def __lock_storage_get(self):
"Getter. Allows for value = self.lock_storage"
return get_cache(self, "lock_storage")
return _get_cache(self, "lock_storage")
#@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()"""
set_cache(self, "lock_storage", value)
_set_cache(self, "lock_storage", value)
#@lock_storage.deleter
def lock_storage_del(self):
def __lock_storage_del(self):
"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)
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
typeclass_paths = settings.OBJECT_TYPECLASS_PATHS
attribute_class = Attribute # replaced by relevant attribute class for child
db_model_name = "typeclass" # used by attributes to safely store objects
_typeclass_paths = settings.OBJECT_TYPECLASS_PATHS
_attribute_class = Attribute # replaced by relevant attribute class for child
_db_model_name = "typeclass" # used by attributes to safely store objects
def __eq__(self, other):
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.
"""
try:
return GA(self, propname)
return _GA(self, propname)
except AttributeError:
# check if the attribute exists on the typeclass instead
# (we make sure to not incur a loop by not triggering the
# typeclass' __getattribute__, since that one would
# try to look back to this very database object.)
typeclass = GA(self, 'typeclass')
typeclass = _GA(self, 'typeclass')
if typeclass:
return GA(typeclass, propname)
return _GA(typeclass, propname)
else:
raise AttributeError
#@property
def dbref_get(self):
def __dbref_get(self):
"""
Returns the object's dbref id on the form #NN.
Alternetively, use obj.id directly to get dbref
without any #.
"""
return "#%s" % str(GA(self, "id"))
dbref = property(dbref_get)
return "#%s" % str(_GA(self, "id"))
dbref = property(__dbref_get)
# typeclass property
#@property
def typeclass_get(self):
def __typeclass_get(self):
"""
Getter. Allows for value = self.typeclass.
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
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
the custom self.__getattribute__ more than necessary.
"""
path = GA(self, "typeclass_path")
typeclass = GA(self, "_cached_typeclass")
path = _GA(self, "typeclass_path")
typeclass = _GA(self, "_cached_typeclass")
try:
if typeclass and GA(typeclass, "path") == path:
if typeclass and _GA(typeclass, "path") == path:
# don't call at_init() when returning from cache
return typeclass
except AttributeError:
@ -915,25 +917,25 @@ class TypedObject(SharedMemoryModel):
errstring = ""
if not path:
# 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:
# 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
# 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:
# try to import and analyze the result
typeclass = GA(self, "_path_import")(tpath)
typeclass = _GA(self, "_path_import")(tpath)
if callable(typeclass):
# we succeeded to import. Cache and return.
SA(self, 'db_typeclass_path', tpath)
GA(self, 'save')()
SA(self, "_cached_db_typeclass_path", tpath)
_SA(self, 'db_typeclass_path', tpath)
_GA(self, 'save')()
_SA(self, "_cached_db_typeclass_path", tpath)
typeclass = typeclass(self)
SA(self, "_cached_typeclass", typeclass)
_SA(self, "_cached_typeclass", typeclass)
try:
typeclass.at_init()
except Exception:
@ -946,16 +948,16 @@ class TypedObject(SharedMemoryModel):
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
# method to use e.g. self.is_typeclass() to detect that the result is not the one asked for.
GA(self, "_display_errmsg")(errstring)
return GA(self, "get_default_typeclass")(cache=False, silent=False, save=False)
_GA(self, "_display_errmsg")(errstring)
return _GA(self, "_get_default_typeclass")(cache=False, silent=False, save=False)
#@typeclass.deleter
def typeclass_del(self):
def __typeclass_del(self):
"Deleter. Disallow 'del self.typeclass'"
raise Exception("The typeclass property should never be deleted, only changed in-place!")
# typeclass property
typeclass = property(typeclass_get, fdel=typeclass_del)
typeclass = property(__typeclass_get, fdel=__typeclass_del)
def _path_import(self, path):
"""
@ -1014,7 +1016,7 @@ class TypedObject(SharedMemoryModel):
else:
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
load for whatever reason.
@ -1022,34 +1024,34 @@ class TypedObject(SharedMemoryModel):
Default operation is to load a default typeclass.
"""
defpath = GA(self, "default_typeclass_path")
typeclass = GA(self, "_path_import")(defpath)
defpath = _GA(self, "_default_typeclass_path")
typeclass = _GA(self, "_path_import")(defpath)
# if not silent:
# #errstring = "\n\nUsing Default class '%s'." % defpath
# GA(self, "_display_errmsg")(errstring)
# _GA(self, "_display_errmsg")(errstring)
if not callable(typeclass):
# 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.
failpath = defpath
defpath = "src.objects.objects.Object"
typeclass = GA(self, "_path_import")(defpath)
typeclass = _GA(self, "_path_import")(defpath)
if not silent:
#errstring = " %s\n%s" % (typeclass, errstring)
errstring = " Default class '%s' failed to load." % failpath
errstring += "\n Using Evennia's default class '%s'." % defpath
GA(self, "_display_errmsg")(errstring)
_GA(self, "_display_errmsg")(errstring)
if not callable(typeclass):
# 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)
typeclass = typeclass(self)
if save:
SA(self, 'db_typeclass_path', defpath)
GA(self, 'save')()
_SA(self, 'db_typeclass_path', defpath)
_GA(self, 'save')()
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:
typeclass.at_init()
except Exception:
@ -1070,17 +1072,17 @@ class TypedObject(SharedMemoryModel):
parents.
"""
try:
typeclass = GA(typeclass, "path")
typeclass = _GA(typeclass, "path")
except AttributeError:
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:
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))
else:
# check parent chain
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
@ -1135,13 +1137,13 @@ class TypedObject(SharedMemoryModel):
new_typeclass = self.typeclass
if self.typeclass_path == new_typeclass.path:
# the typeclass loading worked as expected
DA(self, "_cached_db_typeclass_path")
SA(self, "_cached_typeclass", None)
_DA(self, "_cached_db_typeclass_path")
_SA(self, "_cached_typeclass", None)
elif no_default:
# something went wrong; the default was loaded instead,
# and we don't allow that; instead we return to previous.
SA(self, "typeclass_path", old_typeclass_path)
SA(self, "_cached_typeclass", None)
_SA(self, "typeclass_path", old_typeclass_path)
_SA(self, "_cached_typeclass", None)
return False
if clean_attributes:
@ -1181,7 +1183,7 @@ class TypedObject(SharedMemoryModel):
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()
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.
"""
attrib_obj = None
attrclass = GA(self, "attribute_class")
attrclass = _GA(self, "_attribute_class")
try:
# use old attribute
attrib_obj = attrclass.objects.filter(
@ -1216,7 +1218,7 @@ class TypedObject(SharedMemoryModel):
"""
attrib_obj = default
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]
except IndexError:
return default
@ -1230,7 +1232,7 @@ class TypedObject(SharedMemoryModel):
attribute_name: (str) The attribute's name.
"""
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
except IndexError:
raise AttributeError
@ -1242,7 +1244,7 @@ class TypedObject(SharedMemoryModel):
attribute_name: (str) The attribute's name.
"""
try:
self.attribute_class.objects.filter(
_GA(self, "_attribute_class").objects.filter(
db_obj=self).filter(db_key__iexact=attribute_name)[0].delete()
except IndexError:
pass
@ -1255,7 +1257,7 @@ class TypedObject(SharedMemoryModel):
attribute_name: (str) The attribute's name.
"""
try:
self.attribute_class.objects.filter(
_GA(self, "_attribute_class").objects.filter(
db_obj=self).filter(db_key__iexact=attribute_name)[0].delete()
except IndexError:
raise AttributeError
@ -1264,7 +1266,7 @@ class TypedObject(SharedMemoryModel):
"""
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):
"""
@ -1291,7 +1293,7 @@ class TypedObject(SharedMemoryModel):
self.set_attribute(attribute_name, value)
#@property
def db_get(self):
def __db_get(self):
"""
A second convenience wrapper for the the attribute methods. It
allows for the syntax
@ -1310,35 +1312,35 @@ class TypedObject(SharedMemoryModel):
class DbHolder(object):
"Holder for allowing property access of attributes"
def __init__(self, obj):
SA(self, 'obj', obj)
_SA(self, 'obj', obj)
def __getattribute__(self, attrname):
if attrname == 'all':
# we allow for overwriting the all() method
# with an attribute named 'all'.
attr = GA(self, 'obj').get_attribute("all")
attr = _GA(self, 'obj').get_attribute("all")
if attr:
return attr
return GA(self, 'all')
return GA(self, 'obj').get_attribute(attrname)
return _GA(self, 'all')
return _GA(self, 'obj').get_attribute(attrname)
def __setattr__(self, attrname, value):
GA(self, 'obj').set_attribute(attrname, value)
_GA(self, 'obj').set_attribute(attrname, value)
def __delattr__(self, attrname):
GA(self, 'obj').del_attribute(attrname)
_GA(self, 'obj').del_attribute(attrname)
def all(self):
return GA(self, 'obj').get_all_attributes()
return _GA(self, 'obj').get_all_attributes()
self._db_holder = DbHolder(self)
return self._db_holder
#@db.setter
def db_set(self, value):
def __db_set(self, value):
"Stop accidentally replacing the db object"
string = "Cannot assign directly to db object! "
string += "Use db.attr=value instead."
raise Exception(string)
#@db.deleter
def db_del(self):
def __db_del(self):
"Stop accidental deletion."
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
@ -1358,19 +1360,19 @@ class TypedObject(SharedMemoryModel):
if not val.startswith['_']]
elif delete == True:
if hasattr(self.ndb, attribute_name):
DA(self.db, attribute_name)
_DA(self.db, attribute_name)
elif value == None:
# act as a getter.
if hasattr(self.ndb, attribute_name):
GA(self.ndb, attribute_name)
_GA(self.ndb, attribute_name)
else:
return None
else:
# act as a setter
SA(self.db, attribute_name, value)
_SA(self.db, attribute_name, value)
#@property
def ndb_get(self):
def __ndb_get(self):
"""
A non-persistent store (ndb: NonDataBase). Everything stored
to this is guaranteed to be cleared when a server is shutdown.
@ -1388,22 +1390,22 @@ class TypedObject(SharedMemoryModel):
def __getattribute__(self, key):
# return None if no matching attribute was found.
try:
return GA(self, key)
return _GA(self, key)
except AttributeError:
return None
self._ndb_holder = NdbHolder()
return self._ndb_holder
#@ndb.setter
def ndb_set(self, value):
def __ndb_set(self, value):
"Stop accidentally replacing the db object"
string = "Cannot assign directly to ndb object! "
string = "Use ndb.attr=value instead."
raise Exception(string)
#@ndb.deleter
def ndb_del(self):
def __ndb_del(self):
"Stop accidental deletion."
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
@ -1437,9 +1439,9 @@ class TypedObject(SharedMemoryModel):
if perm in [p.lower() for p in self.permissions]:
# simplest case - we have a direct match
return True
if perm in PERMISSION_HIERARCHY:
if perm in _PERMISSION_HIERARCHY:
# check if we have a higher hierarchy position
ppos = PERMISSION_HIERARCHY.index(perm)
return any(True for hpos, hperm in enumerate(PERMISSION_HIERARCHY)
ppos = _PERMISSION_HIERARCHY.index(perm)
return any(True for hpos, hperm in enumerate(_PERMISSION_HIERARCHY)
if hperm in [p.lower() for p in self.permissions] and hpos > ppos)
return False

View file

@ -14,9 +14,9 @@ from src.utils.logger import log_trace, log_errmsg
from django.conf import settings
# these are called so many times it's worth to avoid lookup calls
GA = object.__getattribute__
SA = object.__setattr__
DA = object.__delattr__
_GA = object.__getattribute__
_SA = object.__setattr__
_DA = object.__delattr__
# To ensure the sanity of the model, there are a
# 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
# unless it's really a TypedObject.
dbobj_cls = GA(dbobj, '__class__')
dbobj_mro = GA(dbobj_cls, '__mro__')
dbobj_cls = _GA(dbobj, '__class__')
dbobj_mro = _GA(dbobj_cls, '__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))
# store the reference to the database model instance
SA(self, 'dbobj', dbobj)
_SA(self, 'dbobj', dbobj)
def __getattribute__(self, propname):
"""
@ -93,25 +93,25 @@ class TypeClass(object):
accessible through getattr.
"""
if propname == 'dbobj':
return GA(self, 'dbobj')
return _GA(self, 'dbobj')
if propname.startswith('__') and propname.endswith('__'):
# python specials are parsed as-is (otherwise things like
# isinstance() fail to identify the typeclass)
return GA(self, propname)
return _GA(self, propname)
#print "get %s (dbobj:%s)" % (propname, type(dbobj))
try:
return GA(self, propname)
return _GA(self, propname)
except AttributeError:
try:
dbobj = GA(self, 'dbobj')
dbobj = _GA(self, 'dbobj')
except AttributeError:
log_trace("Typeclass CRITICAL ERROR! dbobj not found for Typeclass %s!" % self)
raise
try:
return GA(dbobj, propname)
return _GA(dbobj, propname)
except AttributeError:
try:
return GA(dbobj,"get_attribute_raise")(propname)
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.dbref, dbobj.typeclass_path))
@ -132,7 +132,7 @@ class TypeClass(object):
return
try:
dbobj = GA(self, 'dbobj')
dbobj = _GA(self, 'dbobj')
except AttributeError:
dbobj = None
log_trace("This is probably due to an unsafe reload.")
@ -141,19 +141,19 @@ class TypeClass(object):
try:
# only set value on propname if propname already exists
# on dbobj. __getattribute__ will raise attribute error otherwise.
GA(dbobj, propname)
SA(dbobj, propname, value)
_GA(dbobj, propname)
_SA(dbobj, propname, value)
except AttributeError:
dbobj.set_attribute(propname, value)
else:
SA(self, propname, value)
_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
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
@ -172,11 +172,11 @@ class TypeClass(object):
return
try:
DA(self, propname)
_DA(self, propname)
except AttributeError:
# not on typeclass, try to delete on db/ndb
try:
dbobj = GA(self, 'dbobj')
dbobj = _GA(self, 'dbobj')
except AttributeError:
log_trace("This is probably due to an unsafe reload.")
return # ignore delete