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

Reply via email to