[Twisted-web] subtle copying in woven driving me crazy.

Douglas Bagnall twisted-web@twistedmatrix.com
Mon, 22 Dec 2003 14:11:34 +1300


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