Hello Again,
> The first thing to say is that you shouldn't send us pseudo code. It will
> help you understand what's going on if you write a small example and play
> with it. And that will help us help you because we'll be able to see
> exactly what's going on and run your code ourselves.
That is right, hopefully this new mail will explain what am I asking.
> Note that in the above snippet, you're using inlineCallbacks but you're not
> yielding anything. If you try calling this main() function, it will give
> you an exception: Failure instance: Traceback: <type
> 'exceptions.AttributeError'>: 'NoneType' object has no attribute 'send'
>
> That's just an example of the subtleties (and it's not so sublte in this
> case), and underlines why you should send us real code.
>
> Are you actually trying to call main()?
You are right again, my mistake.
Anyway, I tried running the code you wrote and it works as expected.
My problem is handling exceptions raised on remote calls (via pb).
Attached three scripts are:
server.py: Server implementation, a basic perspective broker example
that includes a custom checker, which in turn uses inlineCallbacks.
client1.py: Client implementation 1, uses inlineCallbacks
client2.py: Client implementation 2, uses plain deferreds
Clients should be same in functionality AFAIK (noting that I am new to
inlineCallbacks). Both clients have wrong passwords configured, so
that they will fail in checker with a custom exception derived from
pb.Error.
My problem is, with the plain deferred version (client2.py), it is
easy to handle (inspect) the error in a errback since I got a Failure
object. However, for inline callbacks, the only way I can catch the
error is using this ugly code (copied from client1.py):
try:
... (pb related calls)
except:
print 'Login Failed:',
print sys.exc_info()[0]
Even this does not catch the error:
try:
... (pb related calls)
except Exception, e:
print 'Login Failed:',
print sys.exc_info()[0]
Furthermore, inlineCallbacks version also prints this deprecation warning:
/usr/lib/python2.5/site-packages/twisted/python/failure.py:331:
DeprecationWarning: raising string exceptions is deprecated
return g.throw(self.type, self.value, self.tb)
Is there a better way to do this, or am I missing something? BTW I am
running this on a Ubuntu 8.10 (Twisted 8.1).
Regards,
Maik
#! /usr/bin/python
from zope.interface import implements
from twisted.cred import portal, checkers, credentials, error
from twisted.cred.checkers import ICredentialsChecker
from twisted.spread import pb
from twisted.internet import reactor, defer
class AuthError(pb.Error):
pass
class Server(pb.Viewable):
def view_echo(self, avatar, message):
print 'Message received from avatar %s: %s' % (avatar, message)
class ServerRealm:
implements(portal.IRealm)
def __init__(self, server):
self.server = server
def requestAvatar(self, avatarID, mind, *interfaces):
assert pb.IPerspective in interfaces
avatar = User(avatarID, self.server)
return pb.IPerspective, avatar, lambda a=avatar:a.detached(mind)
class User(pb.Avatar):
def __init__(self, name, server):
self.name = name
self.server = server
def detached(self, mind):
pass
def perspective_getAppServer(self):
return self.server
class UserChecker:
implements(ICredentialsChecker)
credentialInterfaces = (credentials.IUsernamePassword, \
credentials.IUsernameHashedPassword)
@defer.inlineCallbacks
def requestAvatarId(self, credentials):
pwdList = {'user': 'pass'}
if pwdList.has_key(credentials.username):
matched = yield
credentials.checkPassword(pwdList[credentials.username])
if matched:
print 'OK: Login successful'
defer.returnValue(None)
print 'ERR: Login failed'
raise AuthError
appServer = Server()
realm = ServerRealm(appServer)
checker = UserChecker()
p = portal.Portal(realm, [checker])
reactor.listenTCP(8000, pb.PBServerFactory(p))
print "Server started listening"
reactor.run()
#! /usr/bin/python
import sys
from twisted.spread import pb
from twisted.internet import reactor, defer
from twisted.cred import credentials
class AuthError(pb.Error):
pass
class Client(pb.Referenceable):
@defer.inlineCallbacks
def connect(self):
factory = pb.PBClientFactory()
reactor.connectTCP("localhost", 8000, factory)
try:
perspective = yield
factory.login(credentials.UsernamePassword("user", "passX"), client=self)
print "connected to server"
self.appServer = yield perspective.callRemote("getAppServer")
yield self.appServer.callRemote("echo", "Test message")
except:
print 'Login Failed:',
print sys.exc_info()[0]
reactor.stop()
Client().connect()
reactor.run()
#! /usr/bin/python
from twisted.spread import pb
from twisted.internet import reactor, defer
from twisted.cred import credentials
from twisted.python.failure import Failure
class AuthError(pb.Error):
pass
class Client(pb.Referenceable):
def connect(self):
factory = pb.PBClientFactory()
reactor.connectTCP("localhost", 8000, factory)
d = factory.login(credentials.UsernamePassword("user", "passX"),
client=self)
d.addCallbacks(self.cb_connected, self.eb_failed)
def cb_connected(self, perspective):
print "connected to server"
return
perspective.callRemote("getAppServer").addCallback(self.cb_gotAppServer)
def eb_failed(self, failure):
print 'Login failed:', failure.type
def cb_gotAppServer(self, appServer):
self.appServer = appServer
return self.appServer.callRemote("echo", "Test
message").addCallback(self.cb_stopReactor)
def cb_stopReactor(self, ignore):
reactor.stop()
Client().connect()
reactor.run()
_______________________________________________
Twisted-Python mailing list
[email protected]
http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python