Pycard and Twisted Python
2 new models are added, both for twisted+Pycard. The first is the model twistedWxReactorModel.TwistedApplication?, that use the twisted wxreactor. The second one, twistedThreadModel.TwistedThreadModelApplication?, is more advanced, and manage the concurrency of twisted and Pycard launching 2 threads. In the main thread there is the twisted reactor loop, in the child thread there is the wxPython loop. This model take care of inter-thread communication between twisted and Pycard, and accept an adjuntive (the first) parameter that is a "twisted main loop" class, derived from twistedThreadModel.TwistedThreadApplication?. I will put some examples online soon.
Moved all twisted related models to a subpackage named "twistedsupport". Now you need to import those models from Pycard.twistedsupport, for example, to use !twistedThreadModelApplication you need to do:
from Pycard.twistedsupport import twistedThreadModel
Also, many changes on !twistedThreadModel. Now you can call methods and functions from the wx thread and from the twisted thread with result, so, they are both bi-directional, calling, in the respective main object, !callInTwisted from the Pycard app, and !callInGui from the twisted loop, both with the same arguments, they accept a first argument that is a string with the name of the method or attribute you whish to call, and all arguments and keywordarguments you want. I say attribute cause now they can both be used also to get attributes and not only to execute methods. Note that calling anything from the twisted loop inside the gui loop, with !callInGui, will return a deferred.
Another thing added in !twistedThreadModel, is a layer of abstraction to permit transparent calling of methods and attributes with the TwistedLoop and the WxLoop objects.
Some examples:
- To call something in the twisted loop from the Pycard main background:
self.callInTwisted('myfunc', 'myarg') # will call myfunc('myarg') in the main twisted loop and return what myfunc return self.TwistedLoop.myfunc('myarg') # Equivalent! self.callInTwisted('myattribute') # Will return the content of "myattribute" in twisted main loop self.TwistedLoop.myattribute # The same!
- To call something from the Twisted loop in the Pycard main background:
def MyResult(result): return result self.callInGui('myfunc', 'myarg').addCallback(MyResult) # MyResult function will return the return of the # myfunc('myarg') method of the main pycard background self.WxLoop.myfunc('myarg').addCallback(MyResult) # The same! def MyPrint(result): print(result) self.callInGui('myattribute').addCallback(MyPrint) # MyPrint will print the content of # the "myattribute" in the main pycard background self.WxLoop.myattribute.addCallback(MyPrint) # The Same!
Why the WxLoop and !callInGui method return a callback? Cause to have a returned result from the pycard Background we need to wait that an event is fired in the wx loop and that the processing of what we call will end to give us a result, and this will freeze our reactor loop, and as in twisted, we can't accept that. So, the actual implementation is something similar on doing a defer.deferToThread() call.
