subtle copying in woven driving me crazy.
I thought it was reasonable to give my player storing object a requestAvatarId method and call it a checker, and it seemed to work until it was found that new players couldn't log in. Eventually I discovered that: class Checker(dict): __implements__ = checkers.ICredentialsChecker def __init__(self): log.debug(id(self)) def requestAvatarId(self, credentials): log.debug(id(self)) gives two different numbers. Of course seperating the checker from the player model fixed this problem, and is no doubt correcter. Similarly: class SomePage(page.Page): def __init__(self, children_dict): page.Page.__init__(self) self.children_dict = children_dict log.debug(id(self.children_dict)) def getDynamicChild(self, path, request): log.debug(id(self.children_dict)) return self.children_dict.get(path, error.NoResource()) gives two different id numbers! So you can't manipulate the children by referring to the original dictionary in some other context. Again, there is an easy way around this, once you realise what is happening, and that other way is perhaps better, but this has caused me some bewilderment. Is this behaviour intentional? or necessary? It should perhaps be better documented. douglas
Douglas Bagnall wrote:
I thought it was reasonable to give my player storing object a requestAvatarId method and call it a checker, and it seemed to work until it was found that new players couldn't log in. Eventually I discovered that:
...
gives two different numbers.
Similarly:
...
gives two different id numbers!
twisted.web (and Twisted in general) isn't doing any copying of your credential checkers or your Resources. Can you show the code that's instantiating SomePage and Checker, and a little more context in general? You're probably confused about how often this code is being called. -- Twisted | Christopher Armstrong: International Man of Twistery Radix | Release Manager, Twisted Project ---------+ http://radix.twistedmatrix.com/
Christopher Armstrong wrote
gives two different id numbers!
twisted.web (and Twisted in general) isn't doing any copying of your credential checkers or your Resources. Can you show the code that's instantiating SomePage and Checker, and a little more context in general? You're probably confused about how often this code is being called.
Yeah. That was my initial assumption, and I stuck to it, until, as the subject mentions, I went crazy. The full context can be seen at: http://cvs.sf.net/viewcvs.py/upstage/Upstage/upstage/ PlayerDict is a dictionary subclass that alters __setitem__ and __delitem__ to save itself to disk when changed, with a checker interface tacked on. player_dict is its only instance, created in the global scope of the player module. grep agrees, and says that player_dict is never reassigned. I've never touched reload in my life, so as I understand Python import rules, this will only run once. To make sure I have peppered the module with log.debugs, which only appear once, and to be surer I tried stringing the imports in a series. Anyway, all through the global scope of all the touched modules, player_dict has the same identity, as you'd expect. Then in the adminWrapper function definition: log.debug("\n\nin web.py global space\n id is %s"%id(player_dict)) def adminWrapper(admin_dir): """Ties it together""" p = Portal(AdminRealm(admin_dir)) p.registerChecker(AllowAnonymousAccess(), IAnonymous) log.debug("in adminWrapper id is %s"%id(player_dict)) p.registerChecker(player_dict, IUsernamePassword) #p.registerChecker(players_wrapper, IUsernamePassword) upw = guard.UsernamePasswordWrapper(p, callback=dumbRedirect) r = guard.SessionWrapper(upw) r.sessionLifetime = 6 * 3600 return r ...playerdict obviously still has the same identity. It is only when the checker is used, in the requestAvatarId method in the player.PlayerDict class, that a different id is returned: def requestAvatarId(self, credentials): log.debug('\n\nIn requestAvatarId, player_dict id is', id(self)) #log.debug('in requestAvatarId, player_dict is', self) player = self.get(credentials.username) log.debug(credentials.username, player) pw_md5 = md5.new(credentials.password).hexdigest() #log.debug("given: %s\nsaved: %s" %(pw_md5,player.password)) if player and pw_md5 == player.password: log.debug("returning OK for player %s" %player) return credentials.username return failure.Failure(error.UnauthorizedLogin()) The dictionary here contains the same stuff as the original did at start up. I can only assume that requestAvatarId has somehow been wrested from its true self, which has been supplanted by a copy. Now, I'd happily accept that I'd done that, if only I knew *how*. Some points: - my guard code is based on quite an old (>3 months) canonical version. Would it be worth me trying something newer, or simpleguard? - I've heard mutterings against new style classes on the twisted list. Could subclassing dict mix badly with cred/guard? - the other case I mentioned, where an object appeared to change between the __init__ and render of a page.Page, involved a similar dictionary subclass. - python 2.3.2, twisted 1.1.1/ 1.1.0, debian sid. thanks for any help, even if it is likely to make me feel quite stupid. douglas
Douglas Bagnall wrote:
Christopher Armstrong wrote
You're probably confused about how often this code is being called.
Yeah. That was my initial assumption, and I stuck to it, until, as the subject mentions, I went crazy.
The full context can be seen at: http://cvs.sf.net/viewcvs.py/upstage/Upstage/upstage/
I just skimmed through your code and couldn't find anything obvious; the only thing noticeable so far is that you inconsistently mix tabs and spaces. 'tabnanny' will show you where, I recommend fixing that problem before going further, as all sorts of subtle bugs can happen because of it :) I'll try to take a harder look at this code later. -- Twisted | Christopher Armstrong: International Man of Twistery Radix | Release Manager, Twisted Project ---------+ http://radix.twistedmatrix.com/
participants (2)
-
Christopher Armstrong
-
Douglas Bagnall