Dear Twisted users, To my amazement I have reproduced this strange behaviour in an even simpler program. Attached are a pb client/server which illustrate unexpected behaviour of the id of a pb.RemoteCache. To run the example, run server.py and then client.py (with resources.py in the same working directory).
You will see output like this (line numbers added by me) ==== 1. RemoteCache 29403544 initialized 2. Client received RemoteCache: id=29403544 3. RemoteCache: while responding to observe_add I think my id is 29403760 4. Client: The RemoteCache's ide is 29403544 ... ==== 1. When the RemoteCache is initialized it thinks its id is 29403544. 2. The client agrees that it has received a RemoteCache with id 29403544. 3. When the RemoteCache is inside observe_add it thinks its id is 29403760. 4. The client still thinks the RemoteCache's id is 29403544. If you let the program run it will continue to loop between the RemoteCache reporting its id while in observe_add, and the client reporting the id of the RemoteCache. The two reported ids are always the same unequal numbers. The question appears to be "Why does the id reported by a RemoteCache's while inside an observe_* method differ the id reported by objects owning references to that RemoteCache?" Thank you for your time, Daniel On Wed, Apr 30, 2014 at 11:00 AM, Daniel Sank <sank.dan...@gmail.com> wrote: > Dear twisted users, > > I think I have found some surprising behavior in perspective broker. I > define a subclass of pb.RemoteCache which has a method managed by a > descriptor. The descriptor keeps track of the instances it manages in a set. > > When the RemoteCache is first received by the client, it accesses the > descriptor-ified method inside setCopyableState. At that time the > RemoteCache's id is a certain value X. Then later when the RemoteCache is > notified of a change by the server side Cacheable, it again accesses the > descriptor-ified method, but at this time it's id is Y, and Y!=X. > > I attach to this post a simple working example which displays the behavior > described above. To run, first run server.py and then run client.py. You > will see a little bit of output, the most important part being > > === > Client received RemoteCache: id=45952496 > > Asking server to update > TD 45921680 (test.RemoteCache.add) accessed by <test.RemoteCache instance > at 2BD2DC8>: id=45952456 > RemoteCache id=45952496 > === > > To understand the details of the output please see descriptor.py. The id > of the RemoteCache is first reported as 45952496 when the client receives > it. Then, when the descriptor is accessed, the id of the accessing instance > is reported as 45952456, which is different. Then, when in the last line we > print out the id of the RemoteCache we're back to 45952496. > > Is there some reason that a RemoteCache's id can change during its life > time? > > -- > Daniel Sank > Department of Physics > Broida Hall > University of California > Santa Barbara, CA 93117 > (805)893-3899 > -- Daniel Sank Department of Physics Broida Hall University of California Santa Barbara, CA 93117 (805)893-3899
import weakref import resources from twisted.internet import reactor def main(): c = resources.Client(reactor) c.connect() reactor.run() if __name__ == "__main__": main()
import twisted.spread.pb as pb import twisted.cred.portal as portal from twisted.internet import reactor from twisted.internet.defer import inlineCallbacks from twisted.cred import credentials from zope.interface import implements class Cacheable(pb.Cacheable): """I'm a cacheable object which notifies observers when data is added""" def __init__(self): self.observers = {} def add(self, x): for p in self.observers: self.observers[p].callRemote("add", x) def getStateToCacheAndObserveFor(self, perspective, observer): self.observers[perspective] = observer return None class RemoteCache(pb.RemoteCache): """I find out about data added to the Cacheable""" def __init__(self): print("RemoteCache %d initialized"%(id(self),)) def setCopyableState(self, state): pass def observe_add(self, obj): msg = "RemoteCache: while responding to observe_add I think my id is" print("%s %d"%(msg, id(self))) pb.setUnjellyableForClass(Cacheable, RemoteCache) class Server(object): implements(portal.IRealm) def __init__(self): self.thing = Cacheable() self.users = set() def requestAvatar(self, avatarID, mind, *interfaces): assert pb.IPerspective in interfaces p = Perspective(avatarID, mind, self) self.users.add(p) return pb.IPerspective, p, lambda a=p:a.detached() def start(self): for p in self.users: p.mind.callRemote("take", self.thing) def update(self): self.thing.add("foobar") class Perspective(pb.Avatar): def __init__(self, name, mind, server): self.name = name self.mind = mind self.server = server def detached(self): self.mind = None def perspective_start(self): self.server.start() def perspective_update(self): self.server.update() class Client(pb.Referenceable): def __init__(self, reactor): self.reactor = reactor def connect(self): factory = pb.PBClientFactory() reactor.connectTCP("localhost", 8800, factory) def1 = factory.login(credentials.UsernamePassword("alice", "1234"), client=self) def1.addCallback(self.connected) def connected(self, perspective): self.perspective = perspective self.reactor.callLater(1.0, self.start) def start(self): self.perspective.callRemote("start") def update(self): self.perspective.callRemote("update") self.reactor.callLater(1, self.showId) def remote_take(self, d): self.d = d print("Client received RemoteCache: id=%d"%(id(d),)) self.reactor.callLater(2.0, self.update) def showId(self): print("Client: The RemoteCache's id is %d"%id(self.d)) self.reactor.callLater(1, self.update)
import twisted.spread.pb as pb import resources from twisted.internet import reactor from twisted.cred import portal, checkers def main(): realm = resources.Server() checker = checkers.InMemoryUsernamePasswordDatabaseDontUse() checker.addUser("alice", "1234") p = portal.Portal(realm, [checker]) reactor.listenTCP(8800, pb.PBServerFactory(p)) reactor.run() if __name__ == "__main__": main()
_______________________________________________ Twisted-Python mailing list Twisted-Python@twistedmatrix.com http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python