mirror of
https://github.com/ARM-software/workload-automation.git
synced 2025-01-19 20:34:30 +00:00
109 lines
3.2 KiB
Python
109 lines
3.2 KiB
Python
|
"""Common plugins for Louie."""
|
||
|
|
||
|
from louie import dispatcher
|
||
|
from louie import error
|
||
|
|
||
|
|
||
|
def install_plugin(plugin):
|
||
|
cls = plugin.__class__
|
||
|
for p in dispatcher.plugins:
|
||
|
if p.__class__ is cls:
|
||
|
raise error.PluginTypeError(
|
||
|
'Plugin of type %r already installed.' % cls)
|
||
|
dispatcher.plugins.append(plugin)
|
||
|
|
||
|
def remove_plugin(plugin):
|
||
|
dispatcher.plugins.remove(plugin)
|
||
|
|
||
|
|
||
|
class Plugin(object):
|
||
|
"""Base class for Louie plugins.
|
||
|
|
||
|
Plugins are used to extend or alter the behavior of Louie
|
||
|
in a uniform way without having to modify the Louie code
|
||
|
itself.
|
||
|
"""
|
||
|
|
||
|
def is_live(self, receiver):
|
||
|
"""Return True if the receiver is still live.
|
||
|
|
||
|
Only called for receivers who have already been determined to
|
||
|
be live by default Louie semantics.
|
||
|
"""
|
||
|
return True
|
||
|
|
||
|
def wrap_receiver(self, receiver):
|
||
|
"""Return a callable that passes arguments to the receiver.
|
||
|
|
||
|
Useful when you want to change the behavior of all receivers.
|
||
|
"""
|
||
|
return receiver
|
||
|
|
||
|
|
||
|
class QtWidgetPlugin(Plugin):
|
||
|
"""A Plugin for Louie that knows how to handle Qt widgets
|
||
|
when using PyQt built with SIP 4 or higher.
|
||
|
|
||
|
Weak references are not useful when dealing with QWidget
|
||
|
instances, because even after a QWidget is closed and destroyed,
|
||
|
only the C++ object is destroyed. The Python 'shell' object
|
||
|
remains, but raises a RuntimeError when an attempt is made to call
|
||
|
an underlying QWidget method.
|
||
|
|
||
|
This plugin alleviates this behavior, and if a QWidget instance is
|
||
|
found that is just an empty shell, it prevents Louie from
|
||
|
dispatching to any methods on those objects.
|
||
|
"""
|
||
|
|
||
|
def __init__(self):
|
||
|
try:
|
||
|
import qt
|
||
|
except ImportError:
|
||
|
self.is_live = self._is_live_no_qt
|
||
|
else:
|
||
|
self.qt = qt
|
||
|
|
||
|
def is_live(self, receiver):
|
||
|
"""If receiver is a method on a QWidget, only return True if
|
||
|
it hasn't been destroyed."""
|
||
|
if (hasattr(receiver, 'im_self') and
|
||
|
isinstance(receiver.im_self, self.qt.QWidget)
|
||
|
):
|
||
|
try:
|
||
|
receiver.im_self.x()
|
||
|
except RuntimeError:
|
||
|
return False
|
||
|
return True
|
||
|
|
||
|
def _is_live_no_qt(self, receiver):
|
||
|
return True
|
||
|
|
||
|
|
||
|
class TwistedDispatchPlugin(Plugin):
|
||
|
"""Plugin for Louie that wraps all receivers in callables
|
||
|
that return Twisted Deferred objects.
|
||
|
|
||
|
When the wrapped receiver is called, it adds a call to the actual
|
||
|
receiver to the reactor event loop, and returns a Deferred that is
|
||
|
called back with the result.
|
||
|
"""
|
||
|
|
||
|
def __init__(self):
|
||
|
# Don't import reactor ourselves, but make access to it
|
||
|
# easier.
|
||
|
from twisted import internet
|
||
|
from twisted.internet.defer import Deferred
|
||
|
self._internet = internet
|
||
|
self._Deferred = Deferred
|
||
|
|
||
|
def wrap_receiver(self, receiver):
|
||
|
def wrapper(*args, **kw):
|
||
|
d = self._Deferred()
|
||
|
def called(dummy):
|
||
|
return receiver(*args, **kw)
|
||
|
d.addCallback(called)
|
||
|
self._internet.reactor.callLater(0, d.callback, None)
|
||
|
return d
|
||
|
return wrapper
|
||
|
|