Re: [Twisted-Python] Multiple clients

2010-06-18 Thread Szabolcs Balogh
I have used the following code, which is working until I called it multiple 
time:

class ImapProtocol(twisted.mail.imap4.IMAP4Client):

...
implementation
...


class ImapFactory(twisted.internet.protocol.ClientFactory):

def __init__(self, account):

self.account = account
self.deferred = twisted.internet.defer.Deferred()

self.protocol = ImapProtocol

def clientConnectionFailed(self, connection, reason):

Called when the client has failed to connect


self.deferred.errback(reason)


class ImapClient(gobject.GObject):

def __init__(self, account):

super(ImapClient, self).__init__()

self.account = account
self.host = self.account.get_server_address()
self.port = self.account.get_server_port()
self.ssl = self.account.get_use_ssl()

def got_mailbox_list(self, result):

twisted.internet.reactor.stop()

def handle_error(self, error):

twisted.internet.reactor.stop()

def get_mailbox_list(self):

Get the list of existing mailboxes.


imapfactory = ImapFactory(self.account, self.LIST_MAILBOX)
imapfactory.deferred.addCallback(self.got_mailbox_list)
imapfactory.deferred.addErrback(self.handle_error)
if self.ssl:
# Using SSL for encrypted connections
contextfactory = twisted.internet.ssl.ClientContextFactory()
twisted.internet.reactor.connectSSL(self.host, self.port, 
imapfactory,  contextfactory, 4)
else:
# Server doesn't require SSL
twisted.internet.reactor.connectTCP(self.host, self.port, 
imapfactory, 4)

twisted.internet.reactor.run()



I call it in the following way:

imap_client = imapclient.ImapClient(account)
imap_client.get_mailbox_list()

If I call it only once, it executes successfully, but if I call it twice it 
get blocks and never finishes...

So how can I start the reactor and use the connectSSL/connectTCP methods 
multiple times? How to add new clients to an existing reactor?


On Friday 18 June 2010 16:01:02 exar...@twistedmatrix.com wrote:
 On 10:36 am, bszabo...@gmail.com wrote:
 Hy,
 
 Can somebody send me a small example how to use multiple clients at
 same
 time? For example to connect to 3 different IMAP server. I need this
 because
 I'm working on an email client engine. I can connect to POP/IMAP/SMTP
 server
 to download and send messages, but I have created those methods
 separated,
 and each time when I check for new messages or send a message I use
 reactor.run() and reactor.stop(). But calling it multiple times is a
 problem.
 
 Why?
 
 So I need something:
 - when I press button1, the application checks for new messages on POP
 server.
 - when I press button2, the application checks for new messages on IMAP
 server.
 
 How about:
 
   def onbutton1(self):
   checkPOP()
 
   def onbutton2(self):
   checkIMAP()
 
 I know how to check for messages on IMAP/POP server, but I don't know
 how to
 do it periodically with twisted...
 
 Periodically as in once every N seconds?  Check out reactor.callLater
 or twisted.internet.task.LoopingCall.
 
 Jean-Paul
 
 ___
 Twisted-Python mailing list
 Twisted-Python@twistedmatrix.com
 http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python

___
Twisted-Python mailing list
Twisted-Python@twistedmatrix.com
http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python


Re: [Twisted-Python] Multiple clients

2010-06-18 Thread Phil Mayers
On 18/06/10 15:34, Szabolcs Balogh wrote:
  def get_mailbox_list(self):
  twisted.internet.reactor.run()


The reactor isn't restartable. You can only start it once.

___
Twisted-Python mailing list
Twisted-Python@twistedmatrix.com
http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python


Re: [Twisted-Python] Multiple clients

2010-06-18 Thread Szabolcs Balogh
On Friday 18 June 2010 17:49:27 Phil Mayers wrote:
 On 18/06/10 15:34, Szabolcs Balogh wrote:
   def get_mailbox_list(self):
   twisted.internet.reactor.run()
 
 The reactor isn't restartable. You can only start it once.
 
 ___
 Twisted-Python mailing list
 Twisted-Python@twistedmatrix.com
 http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python

Than how can I start checking for messages for different accounts (When I have 
finished checking the messages for the first account to start checking for the 
next account, and so on...)?


___
Twisted-Python mailing list
Twisted-Python@twistedmatrix.com
http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python


Re: [Twisted-Python] Multiple clients

2010-06-18 Thread Jason J. W. Williams
Couldn't you use callLater to fire the first account check every N
interval and then just attach the subsequent accounts for that
interval as callbacks to the first check inside your callLater func?

-J

On Fri, Jun 18, 2010 at 9:25 AM, Szabolcs Balogh bszabo...@gmail.com wrote:
 On Friday 18 June 2010 17:49:27 Phil Mayers wrote:
 On 18/06/10 15:34, Szabolcs Balogh wrote:
       def get_mailbox_list(self):
           twisted.internet.reactor.run()

 The reactor isn't restartable. You can only start it once.

 ___
 Twisted-Python mailing list
 Twisted-Python@twistedmatrix.com
 http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python

 Than how can I start checking for messages for different accounts (When I have
 finished checking the messages for the first account to start checking for the
 next account, and so on...)?


 ___
 Twisted-Python mailing list
 Twisted-Python@twistedmatrix.com
 http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python


___
Twisted-Python mailing list
Twisted-Python@twistedmatrix.com
http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python


Re: [Twisted-Python] Multiple clients

2010-06-18 Thread Phil Mayers
On 18/06/10 16:25, Szabolcs Balogh wrote:
 On Friday 18 June 2010 17:49:27 Phil Mayers wrote:
 On 18/06/10 15:34, Szabolcs Balogh wrote:
   def get_mailbox_list(self):
   twisted.internet.reactor.run()

 The reactor isn't restartable. You can only start it once.

 ___
 Twisted-Python mailing list
 Twisted-Python@twistedmatrix.com
 http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python

 Than how can I start checking for messages for different accounts (When I have
 finished checking the messages for the first account to start checking for the
 next account, and so on...)?

Others have already answered this, but one way to explain it:

You don't call the reactor like a function. You start the reactor, and 
arrange for *it* to call *your* code in response to events.

One type of events being timer ticks.

___
Twisted-Python mailing list
Twisted-Python@twistedmatrix.com
http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python


Re: [Twisted-Python] Multiple clients

2010-06-18 Thread Itamar Turner-Trauring
 It sounds good, but if I don't call reactor.run() after connectSSL doesn't
 happens anything... If I call reactor.run() after connectSSL, it works
 properly...

There are two types of client connections:

1. Connections you open when you first run the program. Call these before
reactor.run() is called.

2. Connections that happen as result of events. Events are all dispatched
by the reactor, so e.g. gui click or data received over network connection
will result in functions being called by the reactor.  These functions can
also open new connections.

The key here is to distinguish between the order of the code in the text
file, and the order the code runs in. In the following example, the
connectTCP will happen *after* reactor.run():


# this will get called 10 seconds after reactor.run():
def happensLater():
reactor.connectTCP()

reactor.callLater(10, happensLater)
reactor.run()



___
Twisted-Python mailing list
Twisted-Python@twistedmatrix.com
http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python


Re: [Twisted-Python] Multiple clients

2010-06-18 Thread Szabolcs Balogh
On Friday 18 June 2010 20:25:50 Itamar Turner-Trauring wrote:
  It sounds good, but if I don't call reactor.run() after connectSSL
  doesn't happens anything... If I call reactor.run() after connectSSL, it
  works properly...
 
 There are two types of client connections:
 
 1. Connections you open when you first run the program. Call these before
 reactor.run() is called.
 
 2. Connections that happen as result of events. Events are all dispatched
 by the reactor, so e.g. gui click or data received over network connection
 will result in functions being called by the reactor.  These functions can
 also open new connections.
 
 The key here is to distinguish between the order of the code in the text
 file, and the order the code runs in. In the following example, the
 connectTCP will happen *after* reactor.run():
 
 
 # this will get called 10 seconds after reactor.run():
 def happensLater():
 reactor.connectTCP()
 
 reactor.callLater(10, happensLater)
 reactor.run()
 
 
 
 ___
 Twisted-Python mailing list
 Twisted-Python@twistedmatrix.com
 http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python

It is possible to:
 - start the reactor when I initialize my program (eg. in main)
 - call connectTCP or connectSSL when I want and every time I want?

Something like this:

def check_messages(account):
# connect to imap server and check for new mailboxes/messages
reactor.connectSSL(...)


if __name__ == __main__:
reactor.run()

check_message(account1)
check_message(account2)
...
do something else
...
check_message(accountn)


Because I can't implement this :}

I have started the implementation based on Twisted Network Programming 
Essential, but this book doesn't treat multiple connections...

___
Twisted-Python mailing list
Twisted-Python@twistedmatrix.com
http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python


Re: [Twisted-Python] Multiple clients

2010-06-18 Thread Jason J. W. Williams
If you're not using twistd to launch your app you'll have to run
reactor.run(). Otherwise, the eventloop won't ever start.

In terms of exposing something like get_messages()...couldn't that
issue the callLater with a very tiny value? Or issue the first
connectTCP, which the others chained via addCallback?

-J

On Fri, Jun 18, 2010 at 11:55 AM, Szabolcs Balogh bszabo...@gmail.com wrote:
 On Friday 18 June 2010 20:25:50 Itamar Turner-Trauring wrote:
  It sounds good, but if I don't call reactor.run() after connectSSL
  doesn't happens anything... If I call reactor.run() after connectSSL, it
  works properly...

 There are two types of client connections:

 1. Connections you open when you first run the program. Call these before
 reactor.run() is called.

 2. Connections that happen as result of events. Events are all dispatched
 by the reactor, so e.g. gui click or data received over network connection
 will result in functions being called by the reactor.  These functions can
 also open new connections.

 The key here is to distinguish between the order of the code in the text
 file, and the order the code runs in. In the following example, the
 connectTCP will happen *after* reactor.run():


 # this will get called 10 seconds after reactor.run():
 def happensLater():
     reactor.connectTCP()

 reactor.callLater(10, happensLater)
 reactor.run()



 ___
 Twisted-Python mailing list
 Twisted-Python@twistedmatrix.com
 http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python

 It is possible to:
  - start the reactor when I initialize my program (eg. in main)
  - call connectTCP or connectSSL when I want and every time I want?

 Something like this:

 def check_messages(account):
        # connect to imap server and check for new mailboxes/messages
        reactor.connectSSL(...)


 if __name__ == __main__:
        reactor.run()

        check_message(account1)
        check_message(account2)
        ...
        do something else
        ...
        check_message(accountn)


 Because I can't implement this :}

 I have started the implementation based on Twisted Network Programming
 Essential, but this book doesn't treat multiple connections...

 ___
 Twisted-Python mailing list
 Twisted-Python@twistedmatrix.com
 http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python


___
Twisted-Python mailing list
Twisted-Python@twistedmatrix.com
http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python


Re: [Twisted-Python] Multiple clients

2010-06-18 Thread Kevin Horn
On Fri, Jun 18, 2010 at 12:55 PM, Szabolcs Balogh bszabo...@gmail.comwrote:


 It is possible to:
  - start the reactor when I initialize my program (eg. in main)
  - call connectTCP or connectSSL when I want and every time I want?


Yes, this is exactly what you are supposed to do.  Call the reactor _once_
and once only.

The call connectTCP or whatever whenever is appropriate for your program.


 Something like this:

 def check_messages(account):
# connect to imap server and check for new mailboxes/messages
reactor.connectSSL(...)


 if __name__ == __main__:
reactor.run()

check_message(account1)
check_message(account2)
...
do something else
...
check_message(accountn)


 Because I can't implement this :}

 I have started the implementation based on Twisted Network Programming
 Essential, but this book doesn't treat multiple connections...


The above won't work, because run() blocks.  So in your example here,
check_messages() won't be called until after the run() call returns, which
means the reactor won't be running, which means check_messages won't work.

look into callWhenRunning:
http://twistedmatrix.com/documents/10.0.0/api/twisted.internet.interfaces.IReactorCore.html#callWhenRunning

and do something like:

def start_checking():
(do your check_messages stuff here)

if __name__ == '__main__':
reactor.callWhenRunning(start_checking)

reactor.run()

using callWhenRunning isn't necessary, but I find that it clarifies things
for me sometimes

reactor.run() is usually the _last_ thing I call in my Twisted programs,
unless I have some shutdown cleanup to do, and even that is usually better
done in the reactor shutdown hook
(see:
http://twistedmatrix.com/documents/10.0.0/api/twisted.internet.interfaces.IReactorCore.html#addSystemEventTrigger
)

you also need to figure out how to structure your program flow using
deferreds, which is not always easy, and depends greatly on your specific
application.

remember that deferreds are just a way of organizing callback functions

you can chain deferreds something like this (assuming your functions
return Deferreds):

d = check_first_one()
d.addCallback(check_second_one, ...)

etc...

which will make check_second_one start after check_first_one completes

You can also use a deferredList, which is often handy when you want to keep
track of several deferred operations which are operating simultaneously
(I haven't used one in a while, so I don't have a simple example off the top
of my head, but there's a simple example in the Twisted book)

Hope this helps,

Kevin Horn
___
Twisted-Python mailing list
Twisted-Python@twistedmatrix.com
http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python