mirror of
https://github.com/evennia/evennia.git
synced 2026-04-07 00:45:22 +02:00
Implemented typeclass deleting; you can now do del obj.testval and expect the underlying attribute to be safely deleted from the database. Also fixed some reference errors when assigning to db/ndb properties on objects. Resolves issue 116. Fixed a bug in the command-testing system, so the few command tests that are defined should all work now.
This commit is contained in:
parent
19538ff00b
commit
45941e0c69
6 changed files with 76 additions and 33 deletions
|
|
@ -43,7 +43,7 @@ class FakeSession(session.Session):
|
|||
def lineReceived(self, raw_string):
|
||||
pass
|
||||
def msg(self, message, data=None):
|
||||
if VERBOSE:
|
||||
if VERBOSE:
|
||||
print message
|
||||
|
||||
class CommandTest(TestCase):
|
||||
|
|
@ -60,11 +60,11 @@ class CommandTest(TestCase):
|
|||
|
||||
# create a faux player/character for testing.
|
||||
self.char1 = create.create_player("TestingPlayer", "testplayer@test.com", "testpassword", location=self.room1)
|
||||
self.char1.player.user.is_superuser = True
|
||||
self.char1.player.user.is_superuser = True
|
||||
sess = FakeSession()
|
||||
sess.connectionMade()
|
||||
sess.login(self.char1.player)
|
||||
|
||||
sess.session_login(self.char1.player)
|
||||
# create second player and some objects
|
||||
self.char2 = create.create_object(settings.BASE_CHARACTER_TYPECLASS, key="char2", location=self.room1)
|
||||
self.obj1 = create.create_object(settings.BASE_OBJECT_TYPECLASS, key="obj1", location=self.room1)
|
||||
self.obj2 = create.create_object(settings.BASE_OBJECT_TYPECLASS, key="obj2", location=self.room1)
|
||||
|
|
@ -90,12 +90,15 @@ class CommandTest(TestCase):
|
|||
This also mangles the input in various ways to test if the command
|
||||
will be fooled.
|
||||
"""
|
||||
test1 = re.sub(r'\s', '', raw_string) # remove all whitespace inside it
|
||||
test2 = "%s/åäö öäö;-:$£@*~^' 'test" % raw_string # inserting weird characters in call
|
||||
test3 = "%s %s" % (raw_string, raw_string) # multiple calls
|
||||
self.char1.execute_cmd(test1)
|
||||
self.char1.execute_cmd(test2)
|
||||
self.char1.execute_cmd(test3)
|
||||
if not VERBOSE:
|
||||
# only mangle if not VERBOSE, to make fewer return lines
|
||||
test1 = re.sub(r'\s', '', raw_string) # remove all whitespace inside it
|
||||
test2 = "%s/åäö öäö;-:$£@*~^' 'test" % raw_string # inserting weird characters in call
|
||||
test3 = "%s %s" % (raw_string, raw_string) # multiple calls
|
||||
self.char1.execute_cmd(test1)
|
||||
self.char1.execute_cmd(test2)
|
||||
self.char1.execute_cmd(test3)
|
||||
# actual call
|
||||
self.char1.execute_cmd(raw_string)
|
||||
|
||||
#------------------------------------------------------------
|
||||
|
|
@ -104,6 +107,7 @@ class CommandTest(TestCase):
|
|||
|
||||
class TestHome(CommandTest):
|
||||
def test_call(self):
|
||||
self.char1.location = self.room1
|
||||
self.char1.home = self.room2
|
||||
self.execute_cmd("home")
|
||||
self.assertEqual(self.char1.location, self.room2)
|
||||
|
|
|
|||
|
|
@ -133,7 +133,7 @@ class SessionBase(object):
|
|||
SESSIONS.add_loggedin_session(self)
|
||||
|
||||
#call hook
|
||||
self.at_login()
|
||||
self.at_login(player)
|
||||
|
||||
def session_disconnect(self):
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -90,12 +90,12 @@ class TelnetProtocol(StatefulTelnetProtocol, session.Session):
|
|||
string = ansi.parse_ansi(screen.text)
|
||||
self.at_data_out(string)
|
||||
|
||||
def at_login(self):
|
||||
def at_login(self, player):
|
||||
"""
|
||||
Called after authentication. self.logged_in=True at this point.
|
||||
"""
|
||||
if self.player.has_attribute('telnet_markup'):
|
||||
self.telnet_markup = self.player.get_attribute("telnet_markup")
|
||||
if player.has_attribute('telnet_markup'):
|
||||
self.telnet_markup = player.get_attribute("telnet_markup")
|
||||
else:
|
||||
self.telnet_markup = True
|
||||
|
||||
|
|
|
|||
|
|
@ -231,12 +231,12 @@ class WebClientSession(session.Session):
|
|||
#string = parse_html(screen.text)
|
||||
self.at_data_out(screen.text)
|
||||
|
||||
def at_login(self):
|
||||
def at_login(self, player):
|
||||
"""
|
||||
Called after authentication. self.logged_in=True at this point.
|
||||
"""
|
||||
if self.player.has_attribute('telnet_markup'):
|
||||
self.telnet_markup = self.player.get_attribute("telnet_markup")
|
||||
if player.has_attribute('telnet_markup'):
|
||||
self.telnet_markup = player.get_attribute("telnet_markup")
|
||||
else:
|
||||
self.telnet_markup = True
|
||||
|
||||
|
|
|
|||
|
|
@ -789,7 +789,7 @@ class TypedObject(SharedMemoryModel):
|
|||
logger.log_trace()
|
||||
return default
|
||||
return attrib.value
|
||||
else:
|
||||
else:
|
||||
return default
|
||||
|
||||
def del_attribute(self, attribute_name):
|
||||
|
|
@ -863,14 +863,14 @@ class TypedObject(SharedMemoryModel):
|
|||
def __init__(self, obj):
|
||||
object.__setattr__(self, 'obj', obj)
|
||||
def __getattribute__(self, attrname):
|
||||
obj = object.__getattribute__(self, 'obj')
|
||||
obj = object.__getattribute__(self, 'obj')
|
||||
if attrname == 'all':
|
||||
# we allow for overwriting the all() method
|
||||
# with an attribute named 'all'.
|
||||
attr = obj.get_attribute("all")
|
||||
if attr:
|
||||
return attr
|
||||
return object.__getattribute__(self, 'all')
|
||||
return object.__getattribute__(self, 'all')
|
||||
return obj.get_attribute(attrname)
|
||||
def __setattr__(self, attrname, value):
|
||||
obj = object.__getattribute__(self, 'obj')
|
||||
|
|
|
|||
|
|
@ -25,7 +25,6 @@ try:
|
|||
except AttributeError:
|
||||
FULL_PERSISTENCE = True
|
||||
|
||||
|
||||
class MetaTypeClass(type):
|
||||
"""
|
||||
This metaclass just makes sure the class object gets
|
||||
|
|
@ -116,13 +115,15 @@ class TypeClass(object):
|
|||
return object.__getattribute__(self, propname)
|
||||
except AttributeError:
|
||||
try:
|
||||
if FULL_PERSISTENCE and propname != 'ndb':
|
||||
db = object.__getattribute__(dbobj, 'db')
|
||||
value = object.__getattribute__(db, propname)
|
||||
if FULL_PERSISTENCE and propname != 'ndb':
|
||||
if not dbobj.has_attribute(propname):
|
||||
raise AttributeError
|
||||
else:
|
||||
value = dbobj.get_attribute(propname)
|
||||
else:
|
||||
# Not FULL_PERSISTENCE
|
||||
ndb = object.__getattribute__(dbobj, 'ndb')
|
||||
value = object.__getattribute__(ndb, propname)
|
||||
value = getattr(ndb, propname)
|
||||
return value
|
||||
except AttributeError:
|
||||
string = "Object: '%s' not found on %s(%s), nor on its typeclass %s."
|
||||
|
|
@ -157,17 +158,14 @@ class TypeClass(object):
|
|||
if dbobj: # and hasattr(dbobj, propname):
|
||||
#print " ---> dbobj"
|
||||
if hasattr(dbobj, propname):
|
||||
# if attr already exists on dbobj, assign to it.
|
||||
# only if attr already exists on dbobj, assign to it.
|
||||
object.__setattr__(dbobj, propname, value)
|
||||
elif FULL_PERSISTENCE:
|
||||
#print "full __setattr__1", propname
|
||||
db = object.__getattribute__(dbobj, 'db')
|
||||
#print "full __setattr__2", propname
|
||||
object.__setattr__(db, propname, value)
|
||||
else:
|
||||
dbobj.set_attribute(propname, value)
|
||||
else:
|
||||
# not FULL_PERSISTENCE
|
||||
ndb = object.__getattribute__(dbobj, 'ndb')
|
||||
object.__setattr__(ndb, propname, value)
|
||||
setattr(ndb, propname, value)
|
||||
else:
|
||||
object.__setattr__(self, propname, value)
|
||||
|
||||
|
|
@ -179,7 +177,48 @@ class TypeClass(object):
|
|||
return other == self or other == self.dbobj or other == self.dbobj.user
|
||||
else:
|
||||
return other == self or other == self.dbobj
|
||||
|
||||
|
||||
|
||||
def __delattr__(self, propname):
|
||||
"""
|
||||
Transparently deletes data from the typeclass or dbobj by first searching on the typeclass,
|
||||
secondly on the dbobj.db or ndb depending on FULL_PERSISTENCE setting.
|
||||
Will not allow deletion of properties stored directly on dbobj.
|
||||
"""
|
||||
try:
|
||||
protected = object.__getattribute__(self, '_protected_attrs')
|
||||
except AttributeError:
|
||||
protected = PROTECTED
|
||||
logger.log_trace("Thiis is probably due to an unsafe reload.")
|
||||
if propname in protected:
|
||||
string = "%s: '%s' is a protected attribute name."
|
||||
string += " (protected: [%s])" % (", ".join(protected))
|
||||
logger.log_errmsg(string % (self.name, propname))
|
||||
else:
|
||||
try:
|
||||
object.__delattr__(self, propname)
|
||||
except AttributeError:
|
||||
# not on typeclass, try to delete on db/ndb
|
||||
try:
|
||||
dbobj = object.__getattribute__(self, 'dbobj')
|
||||
except AttributeError:
|
||||
logger.log_trace("This is probably due to an unsafe reload.")
|
||||
return # ignore delete
|
||||
try:
|
||||
if FULL_PERSISTENCE:
|
||||
if not dbobj.has_attribute(propname):
|
||||
raise AttributeError
|
||||
dbobj.del_attribute(propname)
|
||||
else:
|
||||
ndb = object.__getattribute__(dbobj, 'ndb')
|
||||
ndb.__delattr__(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,))
|
||||
|
||||
|
||||
def __str__(self):
|
||||
"represent the object"
|
||||
return self.key
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue