diff --git a/src/commands/default/tests.py b/src/commands/default/tests.py index 12f60e05d1..b5298449a1 100644 --- a/src/commands/default/tests.py +++ b/src/commands/default/tests.py @@ -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) diff --git a/src/server/session.py b/src/server/session.py index 3206afa923..db60a63617 100644 --- a/src/server/session.py +++ b/src/server/session.py @@ -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): """ diff --git a/src/server/telnet.py b/src/server/telnet.py index 77ede5b216..80c5ceb44c 100644 --- a/src/server/telnet.py +++ b/src/server/telnet.py @@ -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 diff --git a/src/server/webclient.py b/src/server/webclient.py index 1ccd496836..431072df10 100644 --- a/src/server/webclient.py +++ b/src/server/webclient.py @@ -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 diff --git a/src/typeclasses/models.py b/src/typeclasses/models.py index cdd3329212..dc9831ffe0 100644 --- a/src/typeclasses/models.py +++ b/src/typeclasses/models.py @@ -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') diff --git a/src/typeclasses/typeclass.py b/src/typeclasses/typeclass.py index 645472d023..d27027631b 100644 --- a/src/typeclasses/typeclass.py +++ b/src/typeclasses/typeclass.py @@ -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