mirror of
https://github.com/ARM-software/workload-automation.git
synced 2025-09-01 10:52:33 +01:00
pluginloader: Replaced extension loader with WA3 plugin loader
In the process removed modules and boot_strap.py. Also Renamed extensions Plugins. Louie is now monkey patched rather than containing a modified version in external
This commit is contained in:
12
wlauto/external/louie/LICENSE
vendored
12
wlauto/external/louie/LICENSE
vendored
@@ -1,12 +0,0 @@
|
||||
This directory contains Louie package that has been modified by ARM Ltd.
|
||||
Original Louie package is licensed under BSD license. ARM Ltd. changes are
|
||||
licensed under Apache version 2 license.
|
||||
|
||||
Original Louie package may be found here:
|
||||
|
||||
https://pypi.python.org/pypi/Louie/1.1
|
||||
|
||||
The text of the BSD License may be viewed here:
|
||||
|
||||
http://opensource.org/licenses/bsd-license.php
|
||||
|
46
wlauto/external/louie/__init__.py
vendored
46
wlauto/external/louie/__init__.py
vendored
@@ -1,46 +0,0 @@
|
||||
__all__ = [
|
||||
'dispatcher',
|
||||
'error',
|
||||
'plugin',
|
||||
'robustapply',
|
||||
'saferef',
|
||||
'sender',
|
||||
'signal',
|
||||
'version',
|
||||
|
||||
'connect',
|
||||
'disconnect',
|
||||
'get_all_receivers',
|
||||
'reset',
|
||||
'send',
|
||||
'send_exact',
|
||||
'send_minimal',
|
||||
'send_robust',
|
||||
|
||||
'install_plugin',
|
||||
'remove_plugin',
|
||||
'Plugin',
|
||||
'QtWidgetPlugin',
|
||||
'TwistedDispatchPlugin',
|
||||
|
||||
'Anonymous',
|
||||
'Any',
|
||||
|
||||
'All',
|
||||
'Signal',
|
||||
]
|
||||
|
||||
import louie.dispatcher, louie.error, louie.plugin, louie.robustapply, \
|
||||
louie.saferef, louie.sender, louie.signal, louie.version
|
||||
|
||||
from louie.dispatcher import \
|
||||
connect, disconnect, get_all_receivers, reset, \
|
||||
send, send_exact, send_minimal, send_robust
|
||||
|
||||
from louie.plugin import \
|
||||
install_plugin, remove_plugin, Plugin, \
|
||||
QtWidgetPlugin, TwistedDispatchPlugin
|
||||
|
||||
from louie.sender import Anonymous, Any
|
||||
|
||||
from louie.signal import All, Signal
|
591
wlauto/external/louie/dispatcher.py
vendored
591
wlauto/external/louie/dispatcher.py
vendored
@@ -1,591 +0,0 @@
|
||||
"""Multiple-producer-multiple-consumer signal-dispatching.
|
||||
|
||||
``dispatcher`` is the core of Louie, providing the primary API and the
|
||||
core logic for the system.
|
||||
|
||||
Internal attributes:
|
||||
|
||||
- ``WEAKREF_TYPES``: Tuple of types/classes which represent weak
|
||||
references to receivers, and thus must be dereferenced on retrieval
|
||||
to retrieve the callable object
|
||||
|
||||
- ``connections``::
|
||||
|
||||
{ senderkey (id) : { signal : [receivers...] } }
|
||||
|
||||
- ``senders``: Used for cleaning up sender references on sender
|
||||
deletion::
|
||||
|
||||
{ senderkey (id) : weakref(sender) }
|
||||
|
||||
- ``senders_back``: Used for cleaning up receiver references on receiver
|
||||
deletion::
|
||||
|
||||
{ receiverkey (id) : [senderkey (id)...] }
|
||||
"""
|
||||
|
||||
import os
|
||||
import weakref
|
||||
|
||||
try:
|
||||
set
|
||||
except NameError:
|
||||
from sets import Set as set, ImmutableSet as frozenset
|
||||
|
||||
from louie import error
|
||||
from louie import robustapply
|
||||
from louie import saferef
|
||||
from louie.sender import Any, Anonymous
|
||||
from louie.signal import All
|
||||
from prioritylist import PriorityList
|
||||
|
||||
|
||||
# Support for statistics.
|
||||
if __debug__:
|
||||
connects = 0
|
||||
disconnects = 0
|
||||
sends = 0
|
||||
|
||||
def print_stats():
|
||||
print ('\n'
|
||||
'Louie connects: %i\n'
|
||||
'Louie disconnects: %i\n'
|
||||
'Louie sends: %i\n'
|
||||
'\n') % (connects, disconnects, sends)
|
||||
|
||||
if 'PYDISPATCH_STATS' in os.environ:
|
||||
import atexit
|
||||
atexit.register(print_stats)
|
||||
|
||||
|
||||
|
||||
WEAKREF_TYPES = (weakref.ReferenceType, saferef.BoundMethodWeakref)
|
||||
|
||||
|
||||
connections = {}
|
||||
senders = {}
|
||||
senders_back = {}
|
||||
plugins = []
|
||||
|
||||
def reset():
|
||||
"""Reset the state of Louie.
|
||||
|
||||
Useful during unit testing. Should be avoided otherwise.
|
||||
"""
|
||||
global connections, senders, senders_back, plugins
|
||||
connections = {}
|
||||
senders = {}
|
||||
senders_back = {}
|
||||
plugins = []
|
||||
|
||||
|
||||
def connect(receiver, signal=All, sender=Any, weak=True, priority=0):
|
||||
"""Connect ``receiver`` to ``sender`` for ``signal``.
|
||||
|
||||
- ``receiver``: A callable Python object which is to receive
|
||||
messages/signals/events. Receivers must be hashable objects.
|
||||
|
||||
If weak is ``True``, then receiver must be weak-referencable (more
|
||||
precisely ``saferef.safe_ref()`` must be able to create a
|
||||
reference to the receiver).
|
||||
|
||||
Receivers are fairly flexible in their specification, as the
|
||||
machinery in the ``robustapply`` module takes care of most of the
|
||||
details regarding figuring out appropriate subsets of the sent
|
||||
arguments to apply to a given receiver.
|
||||
|
||||
Note: If ``receiver`` is itself a weak reference (a callable), it
|
||||
will be de-referenced by the system's machinery, so *generally*
|
||||
weak references are not suitable as receivers, though some use
|
||||
might be found for the facility whereby a higher-level library
|
||||
passes in pre-weakrefed receiver references.
|
||||
|
||||
- ``signal``: The signal to which the receiver should respond.
|
||||
|
||||
If ``All``, receiver will receive all signals from the indicated
|
||||
sender (which might also be ``All``, but is not necessarily
|
||||
``All``).
|
||||
|
||||
Otherwise must be a hashable Python object other than ``None``
|
||||
(``DispatcherError`` raised on ``None``).
|
||||
|
||||
- ``sender``: The sender to which the receiver should respond.
|
||||
|
||||
If ``Any``, receiver will receive the indicated signals from any
|
||||
sender.
|
||||
|
||||
If ``Anonymous``, receiver will only receive indicated signals
|
||||
from ``send``/``send_exact`` which do not specify a sender, or
|
||||
specify ``Anonymous`` explicitly as the sender.
|
||||
|
||||
Otherwise can be any python object.
|
||||
|
||||
- ``weak``: Whether to use weak references to the receiver.
|
||||
|
||||
By default, the module will attempt to use weak references to
|
||||
the receiver objects. If this parameter is ``False``, then strong
|
||||
references will be used.
|
||||
|
||||
- ``priority``: specifies the priority by which a reciever should
|
||||
get notified
|
||||
|
||||
Returns ``None``, may raise ``DispatcherTypeError``.
|
||||
"""
|
||||
if signal is None:
|
||||
raise error.DispatcherTypeError(
|
||||
'Signal cannot be None (receiver=%r sender=%r)'
|
||||
% (receiver, sender))
|
||||
if weak:
|
||||
receiver = saferef.safe_ref(receiver, on_delete=_remove_receiver)
|
||||
senderkey = id(sender)
|
||||
if connections.has_key(senderkey):
|
||||
signals = connections[senderkey]
|
||||
else:
|
||||
connections[senderkey] = signals = {}
|
||||
# Keep track of senders for cleanup.
|
||||
# Is Anonymous something we want to clean up?
|
||||
if sender not in (None, Anonymous, Any):
|
||||
def remove(object, senderkey=senderkey):
|
||||
_remove_sender(senderkey=senderkey)
|
||||
# Skip objects that can not be weakly referenced, which means
|
||||
# they won't be automatically cleaned up, but that's too bad.
|
||||
try:
|
||||
weak_sender = weakref.ref(sender, remove)
|
||||
senders[senderkey] = weak_sender
|
||||
except:
|
||||
pass
|
||||
receiver_id = id(receiver)
|
||||
# get current set, remove any current references to
|
||||
# this receiver in the set, including back-references
|
||||
if signals.has_key(signal):
|
||||
receivers = signals[signal]
|
||||
_remove_old_back_refs(senderkey, signal, receiver, receivers)
|
||||
else:
|
||||
receivers = signals[signal] = PriorityList()
|
||||
try:
|
||||
current = senders_back.get(receiver_id)
|
||||
if current is None:
|
||||
senders_back[receiver_id] = current = []
|
||||
if senderkey not in current:
|
||||
current.append(senderkey)
|
||||
except:
|
||||
pass
|
||||
receivers.add(receiver, priority)
|
||||
# Update stats.
|
||||
if __debug__:
|
||||
global connects
|
||||
connects += 1
|
||||
|
||||
|
||||
def disconnect(receiver, signal=All, sender=Any, weak=True):
|
||||
"""Disconnect ``receiver`` from ``sender`` for ``signal``.
|
||||
|
||||
- ``receiver``: The registered receiver to disconnect.
|
||||
|
||||
- ``signal``: The registered signal to disconnect.
|
||||
|
||||
- ``sender``: The registered sender to disconnect.
|
||||
|
||||
- ``weak``: The weakref state to disconnect.
|
||||
|
||||
``disconnect`` reverses the process of ``connect``, the semantics for
|
||||
the individual elements are logically equivalent to a tuple of
|
||||
``(receiver, signal, sender, weak)`` used as a key to be deleted
|
||||
from the internal routing tables. (The actual process is slightly
|
||||
more complex but the semantics are basically the same).
|
||||
|
||||
Note: Using ``disconnect`` is not required to cleanup routing when
|
||||
an object is deleted; the framework will remove routes for deleted
|
||||
objects automatically. It's only necessary to disconnect if you
|
||||
want to stop routing to a live object.
|
||||
|
||||
Returns ``None``, may raise ``DispatcherTypeError`` or
|
||||
``DispatcherKeyError``.
|
||||
"""
|
||||
if signal is None:
|
||||
raise error.DispatcherTypeError(
|
||||
'Signal cannot be None (receiver=%r sender=%r)'
|
||||
% (receiver, sender))
|
||||
if weak:
|
||||
receiver = saferef.safe_ref(receiver)
|
||||
senderkey = id(sender)
|
||||
try:
|
||||
signals = connections[senderkey]
|
||||
receivers = signals[signal]
|
||||
except KeyError:
|
||||
raise error.DispatcherKeyError(
|
||||
'No receivers found for signal %r from sender %r'
|
||||
% (signal, sender)
|
||||
)
|
||||
try:
|
||||
# also removes from receivers
|
||||
_remove_old_back_refs(senderkey, signal, receiver, receivers)
|
||||
except ValueError:
|
||||
raise error.DispatcherKeyError(
|
||||
'No connection to receiver %s for signal %s from sender %s'
|
||||
% (receiver, signal, sender)
|
||||
)
|
||||
_cleanup_connections(senderkey, signal)
|
||||
# Update stats.
|
||||
if __debug__:
|
||||
global disconnects
|
||||
disconnects += 1
|
||||
|
||||
|
||||
def get_receivers(sender=Any, signal=All):
|
||||
"""Get list of receivers from global tables.
|
||||
|
||||
This function allows you to retrieve the raw list of receivers
|
||||
from the connections table for the given sender and signal pair.
|
||||
|
||||
Note: There is no guarantee that this is the actual list stored in
|
||||
the connections table, so the value should be treated as a simple
|
||||
iterable/truth value rather than, for instance a list to which you
|
||||
might append new records.
|
||||
|
||||
Normally you would use ``live_receivers(get_receivers(...))`` to
|
||||
retrieve the actual receiver objects as an iterable object.
|
||||
"""
|
||||
try:
|
||||
return connections[id(sender)][signal]
|
||||
except KeyError:
|
||||
return []
|
||||
|
||||
|
||||
def live_receivers(receivers):
|
||||
"""Filter sequence of receivers to get resolved, live receivers.
|
||||
|
||||
This is a generator which will iterate over the passed sequence,
|
||||
checking for weak references and resolving them, then returning
|
||||
all live receivers.
|
||||
"""
|
||||
for receiver in receivers:
|
||||
if isinstance(receiver, WEAKREF_TYPES):
|
||||
# Dereference the weak reference.
|
||||
receiver = receiver()
|
||||
if receiver is not None:
|
||||
# Check installed plugins to make sure this receiver is
|
||||
# live.
|
||||
live = True
|
||||
for plugin in plugins:
|
||||
if not plugin.is_live(receiver):
|
||||
live = False
|
||||
break
|
||||
if live:
|
||||
yield receiver
|
||||
|
||||
|
||||
def get_all_receivers(sender=Any, signal=All):
|
||||
"""Get list of all receivers from global tables.
|
||||
|
||||
This gets all receivers which should receive the given signal from
|
||||
sender, each receiver should be produced only once by the
|
||||
resulting generator.
|
||||
"""
|
||||
yielded = set()
|
||||
for receivers in (
|
||||
# Get receivers that receive *this* signal from *this* sender.
|
||||
get_receivers(sender, signal),
|
||||
# Add receivers that receive *all* signals from *this* sender.
|
||||
get_receivers(sender, All),
|
||||
# Add receivers that receive *this* signal from *any* sender.
|
||||
get_receivers(Any, signal),
|
||||
# Add receivers that receive *all* signals from *any* sender.
|
||||
get_receivers(Any, All),
|
||||
):
|
||||
for receiver in receivers:
|
||||
if receiver: # filter out dead instance-method weakrefs
|
||||
try:
|
||||
if not receiver in yielded:
|
||||
yielded.add(receiver)
|
||||
yield receiver
|
||||
except TypeError:
|
||||
# dead weakrefs raise TypeError on hash...
|
||||
pass
|
||||
|
||||
|
||||
def send(signal=All, sender=Anonymous, *arguments, **named):
|
||||
"""Send ``signal`` from ``sender`` to all connected receivers.
|
||||
|
||||
- ``signal``: (Hashable) signal value; see ``connect`` for details.
|
||||
|
||||
- ``sender``: The sender of the signal.
|
||||
|
||||
If ``Any``, only receivers registered for ``Any`` will receive the
|
||||
message.
|
||||
|
||||
If ``Anonymous``, only receivers registered to receive messages
|
||||
from ``Anonymous`` or ``Any`` will receive the message.
|
||||
|
||||
Otherwise can be any Python object (normally one registered with
|
||||
a connect if you actually want something to occur).
|
||||
|
||||
- ``arguments``: Positional arguments which will be passed to *all*
|
||||
receivers. Note that this may raise ``TypeError`` if the receivers
|
||||
do not allow the particular arguments. Note also that arguments
|
||||
are applied before named arguments, so they should be used with
|
||||
care.
|
||||
|
||||
- ``named``: Named arguments which will be filtered according to the
|
||||
parameters of the receivers to only provide those acceptable to
|
||||
the receiver.
|
||||
|
||||
Return a list of tuple pairs ``[(receiver, response), ...]``
|
||||
|
||||
If any receiver raises an error, the error propagates back through
|
||||
send, terminating the dispatch loop, so it is quite possible to
|
||||
not have all receivers called if a raises an error.
|
||||
"""
|
||||
# Call each receiver with whatever arguments it can accept.
|
||||
# Return a list of tuple pairs [(receiver, response), ... ].
|
||||
responses = []
|
||||
for receiver in live_receivers(get_all_receivers(sender, signal)):
|
||||
# Wrap receiver using installed plugins.
|
||||
original = receiver
|
||||
for plugin in plugins:
|
||||
receiver = plugin.wrap_receiver(receiver)
|
||||
response = robustapply.robust_apply(
|
||||
receiver, original,
|
||||
signal=signal,
|
||||
sender=sender,
|
||||
*arguments,
|
||||
**named
|
||||
)
|
||||
responses.append((receiver, response))
|
||||
# Update stats.
|
||||
if __debug__:
|
||||
global sends
|
||||
sends += 1
|
||||
return responses
|
||||
|
||||
|
||||
def send_minimal(signal=All, sender=Anonymous, *arguments, **named):
|
||||
"""Like ``send``, but does not attach ``signal`` and ``sender``
|
||||
arguments to the call to the receiver."""
|
||||
# Call each receiver with whatever arguments it can accept.
|
||||
# Return a list of tuple pairs [(receiver, response), ... ].
|
||||
responses = []
|
||||
for receiver in live_receivers(get_all_receivers(sender, signal)):
|
||||
# Wrap receiver using installed plugins.
|
||||
original = receiver
|
||||
for plugin in plugins:
|
||||
receiver = plugin.wrap_receiver(receiver)
|
||||
response = robustapply.robust_apply(
|
||||
receiver, original,
|
||||
*arguments,
|
||||
**named
|
||||
)
|
||||
responses.append((receiver, response))
|
||||
# Update stats.
|
||||
if __debug__:
|
||||
global sends
|
||||
sends += 1
|
||||
return responses
|
||||
|
||||
|
||||
def send_exact(signal=All, sender=Anonymous, *arguments, **named):
|
||||
"""Send ``signal`` only to receivers registered for exact message.
|
||||
|
||||
``send_exact`` allows for avoiding ``Any``/``Anonymous`` registered
|
||||
handlers, sending only to those receivers explicitly registered
|
||||
for a particular signal on a particular sender.
|
||||
"""
|
||||
responses = []
|
||||
for receiver in live_receivers(get_receivers(sender, signal)):
|
||||
# Wrap receiver using installed plugins.
|
||||
original = receiver
|
||||
for plugin in plugins:
|
||||
receiver = plugin.wrap_receiver(receiver)
|
||||
response = robustapply.robust_apply(
|
||||
receiver, original,
|
||||
signal=signal,
|
||||
sender=sender,
|
||||
*arguments,
|
||||
**named
|
||||
)
|
||||
responses.append((receiver, response))
|
||||
return responses
|
||||
|
||||
|
||||
def send_robust(signal=All, sender=Anonymous, *arguments, **named):
|
||||
"""Send ``signal`` from ``sender`` to all connected receivers catching
|
||||
errors
|
||||
|
||||
- ``signal``: (Hashable) signal value, see connect for details
|
||||
|
||||
- ``sender``: The sender of the signal.
|
||||
|
||||
If ``Any``, only receivers registered for ``Any`` will receive the
|
||||
message.
|
||||
|
||||
If ``Anonymous``, only receivers registered to receive messages
|
||||
from ``Anonymous`` or ``Any`` will receive the message.
|
||||
|
||||
Otherwise can be any Python object (normally one registered with
|
||||
a connect if you actually want something to occur).
|
||||
|
||||
- ``arguments``: Positional arguments which will be passed to *all*
|
||||
receivers. Note that this may raise ``TypeError`` if the receivers
|
||||
do not allow the particular arguments. Note also that arguments
|
||||
are applied before named arguments, so they should be used with
|
||||
care.
|
||||
|
||||
- ``named``: Named arguments which will be filtered according to the
|
||||
parameters of the receivers to only provide those acceptable to
|
||||
the receiver.
|
||||
|
||||
Return a list of tuple pairs ``[(receiver, response), ... ]``
|
||||
|
||||
If any receiver raises an error (specifically, any subclass of
|
||||
``Exception``), the error instance is returned as the result for
|
||||
that receiver.
|
||||
"""
|
||||
# Call each receiver with whatever arguments it can accept.
|
||||
# Return a list of tuple pairs [(receiver, response), ... ].
|
||||
responses = []
|
||||
for receiver in live_receivers(get_all_receivers(sender, signal)):
|
||||
original = receiver
|
||||
for plugin in plugins:
|
||||
receiver = plugin.wrap_receiver(receiver)
|
||||
try:
|
||||
response = robustapply.robust_apply(
|
||||
receiver, original,
|
||||
signal=signal,
|
||||
sender=sender,
|
||||
*arguments,
|
||||
**named
|
||||
)
|
||||
except Exception, err:
|
||||
responses.append((receiver, err))
|
||||
else:
|
||||
responses.append((receiver, response))
|
||||
return responses
|
||||
|
||||
|
||||
def _remove_receiver(receiver):
|
||||
"""Remove ``receiver`` from connections."""
|
||||
if not senders_back:
|
||||
# During module cleanup the mapping will be replaced with None.
|
||||
return False
|
||||
backKey = id(receiver)
|
||||
for senderkey in senders_back.get(backKey, ()):
|
||||
try:
|
||||
signals = connections[senderkey].keys()
|
||||
except KeyError:
|
||||
pass
|
||||
else:
|
||||
for signal in signals:
|
||||
try:
|
||||
receivers = connections[senderkey][signal]
|
||||
except KeyError:
|
||||
pass
|
||||
else:
|
||||
try:
|
||||
receivers.remove(receiver)
|
||||
except Exception:
|
||||
pass
|
||||
_cleanup_connections(senderkey, signal)
|
||||
try:
|
||||
del senders_back[backKey]
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
|
||||
def _cleanup_connections(senderkey, signal):
|
||||
"""Delete empty signals for ``senderkey``. Delete ``senderkey`` if
|
||||
empty."""
|
||||
try:
|
||||
receivers = connections[senderkey][signal]
|
||||
except:
|
||||
pass
|
||||
else:
|
||||
if not receivers:
|
||||
# No more connected receivers. Therefore, remove the signal.
|
||||
try:
|
||||
signals = connections[senderkey]
|
||||
except KeyError:
|
||||
pass
|
||||
else:
|
||||
del signals[signal]
|
||||
if not signals:
|
||||
# No more signal connections. Therefore, remove the sender.
|
||||
_remove_sender(senderkey)
|
||||
|
||||
|
||||
def _remove_sender(senderkey):
|
||||
"""Remove ``senderkey`` from connections."""
|
||||
_remove_back_refs(senderkey)
|
||||
try:
|
||||
del connections[senderkey]
|
||||
except KeyError:
|
||||
pass
|
||||
# Senderkey will only be in senders dictionary if sender
|
||||
# could be weakly referenced.
|
||||
try:
|
||||
del senders[senderkey]
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
def _remove_back_refs(senderkey):
|
||||
"""Remove all back-references to this ``senderkey``."""
|
||||
try:
|
||||
signals = connections[senderkey]
|
||||
except KeyError:
|
||||
signals = None
|
||||
else:
|
||||
for signal, receivers in signals.iteritems():
|
||||
for receiver in receivers:
|
||||
_kill_back_ref(receiver, senderkey)
|
||||
|
||||
|
||||
def _remove_old_back_refs(senderkey, signal, receiver, receivers):
|
||||
"""Kill old ``senders_back`` references from ``receiver``.
|
||||
|
||||
This guards against multiple registration of the same receiver for
|
||||
a given signal and sender leaking memory as old back reference
|
||||
records build up.
|
||||
|
||||
Also removes old receiver instance from receivers.
|
||||
"""
|
||||
try:
|
||||
index = receivers.index(receiver)
|
||||
# need to scan back references here and remove senderkey
|
||||
except ValueError:
|
||||
return False
|
||||
else:
|
||||
old_receiver = receivers[index]
|
||||
del receivers[index]
|
||||
found = 0
|
||||
signals = connections.get(signal)
|
||||
if signals is not None:
|
||||
for sig, recs in connections.get(signal, {}).iteritems():
|
||||
if sig != signal:
|
||||
for rec in recs:
|
||||
if rec is old_receiver:
|
||||
found = 1
|
||||
break
|
||||
if not found:
|
||||
_kill_back_ref(old_receiver, senderkey)
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def _kill_back_ref(receiver, senderkey):
|
||||
"""Do actual removal of back reference from ``receiver`` to
|
||||
``senderkey``."""
|
||||
receiverkey = id(receiver)
|
||||
senders = senders_back.get(receiverkey, ())
|
||||
while senderkey in senders:
|
||||
try:
|
||||
senders.remove(senderkey)
|
||||
except:
|
||||
break
|
||||
if not senders:
|
||||
try:
|
||||
del senders_back[receiverkey]
|
||||
except KeyError:
|
||||
pass
|
||||
return True
|
||||
|
||||
|
22
wlauto/external/louie/error.py
vendored
22
wlauto/external/louie/error.py
vendored
@@ -1,22 +0,0 @@
|
||||
"""Error types for Louie."""
|
||||
|
||||
|
||||
class LouieError(Exception):
|
||||
"""Base class for all Louie errors"""
|
||||
|
||||
|
||||
class DispatcherError(LouieError):
|
||||
"""Base class for all Dispatcher errors"""
|
||||
|
||||
|
||||
class DispatcherKeyError(KeyError, DispatcherError):
|
||||
"""Error raised when unknown (sender, signal) specified"""
|
||||
|
||||
|
||||
class DispatcherTypeError(TypeError, DispatcherError):
|
||||
"""Error raised when inappropriate signal-type specified (None)"""
|
||||
|
||||
|
||||
class PluginTypeError(TypeError, LouieError):
|
||||
"""Error raise when trying to install more than one plugin of a
|
||||
certain type."""
|
108
wlauto/external/louie/plugin.py
vendored
108
wlauto/external/louie/plugin.py
vendored
@@ -1,108 +0,0 @@
|
||||
"""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
|
||||
|
128
wlauto/external/louie/prioritylist.py
vendored
128
wlauto/external/louie/prioritylist.py
vendored
@@ -1,128 +0,0 @@
|
||||
"""OrderedList class
|
||||
|
||||
This class keeps its elements ordered according to their priority.
|
||||
"""
|
||||
from collections import defaultdict
|
||||
import numbers
|
||||
from bisect import insort
|
||||
|
||||
class PriorityList(object):
|
||||
|
||||
def __init__(self):
|
||||
"""
|
||||
Returns an OrderedReceivers object that externaly behaves
|
||||
like a list but it maintains the order of its elements
|
||||
according to their priority.
|
||||
"""
|
||||
self.elements = defaultdict(list)
|
||||
self.is_ordered = True
|
||||
self.priorities = []
|
||||
self.size = 0
|
||||
self._cached_elements = None
|
||||
|
||||
def __del__(self):
|
||||
pass
|
||||
|
||||
def __iter__(self):
|
||||
"""
|
||||
this method makes PriorityList class iterable
|
||||
"""
|
||||
self._order_elements()
|
||||
for priority in reversed(self.priorities): # highest priority first
|
||||
for element in self.elements[priority]:
|
||||
yield element
|
||||
|
||||
def __getitem__(self, index):
|
||||
self._order_elements()
|
||||
return self._to_list()[index]
|
||||
|
||||
def __delitem__(self, index):
|
||||
self._order_elements()
|
||||
if isinstance(index, numbers.Integral):
|
||||
index = int(index)
|
||||
if index < 0:
|
||||
index_range = [len(self)+index]
|
||||
else:
|
||||
index_range = [index]
|
||||
elif isinstance(index, slice):
|
||||
index_range = range(index.start or 0, index.stop, index.step or 1)
|
||||
else:
|
||||
raise ValueError('Invalid index {}'.format(index))
|
||||
current_global_offset = 0
|
||||
priority_counts = {priority : count for (priority, count) in
|
||||
zip(self.priorities, [len(self.elements[p]) for p in self.priorities])}
|
||||
for priority in self.priorities:
|
||||
if not index_range:
|
||||
break
|
||||
priority_offset = 0
|
||||
while index_range:
|
||||
del_index = index_range[0]
|
||||
if priority_counts[priority] + current_global_offset <= del_index:
|
||||
current_global_offset += priority_counts[priority]
|
||||
break
|
||||
within_priority_index = del_index - (current_global_offset + priority_offset)
|
||||
self._delete(priority, within_priority_index)
|
||||
priority_offset += 1
|
||||
index_range.pop(0)
|
||||
|
||||
def __len__(self):
|
||||
return self.size
|
||||
|
||||
def add(self, new_element, priority=0, force_ordering=True):
|
||||
"""
|
||||
adds a new item in the list.
|
||||
|
||||
- ``new_element`` the element to be inserted in the PriorityList
|
||||
- ``priority`` is the priority of the element which specifies its
|
||||
order withing the List
|
||||
- ``force_ordering`` indicates whether elements should be ordered
|
||||
right now. If set to False, ordering happens on demand (lazy)
|
||||
"""
|
||||
self._add_element(new_element, priority)
|
||||
if priority not in self.priorities:
|
||||
self._add_priority(priority, force_ordering)
|
||||
|
||||
def index(self, element):
|
||||
return self._to_list().index(element)
|
||||
|
||||
def remove(self, element):
|
||||
index = self.index(element)
|
||||
self.__delitem__(index)
|
||||
|
||||
def _order_elements(self):
|
||||
if not self.is_ordered:
|
||||
self.priorities = sorted(self.priorities)
|
||||
self.is_ordered = True
|
||||
|
||||
def _to_list(self):
|
||||
if self._cached_elements == None:
|
||||
self._order_elements()
|
||||
self._cached_elements = []
|
||||
for priority in self.priorities:
|
||||
self._cached_elements += self.elements[priority]
|
||||
return self._cached_elements
|
||||
|
||||
def _add_element(self, element, priority):
|
||||
self.elements[priority].append(element)
|
||||
self.size += 1
|
||||
self._cached_elements = None
|
||||
|
||||
def _delete(self, priority, priority_index):
|
||||
del self.elements[priority][priority_index]
|
||||
self.size -= 1
|
||||
if len(self.elements[priority]) == 0:
|
||||
self.priorities.remove(priority)
|
||||
self._cached_elements = None
|
||||
|
||||
def _add_priority(self, priority, force_ordering):
|
||||
if force_ordering and self.is_ordered:
|
||||
insort(self.priorities, priority)
|
||||
elif not force_ordering:
|
||||
self.priorities.append(priority)
|
||||
self.is_ordered = False
|
||||
elif not self.is_ordered:
|
||||
self.priorities.append(priority)
|
||||
self._order_elements()
|
||||
else:
|
||||
raise AssertionError('Should never get here.')
|
||||
|
58
wlauto/external/louie/robustapply.py
vendored
58
wlauto/external/louie/robustapply.py
vendored
@@ -1,58 +0,0 @@
|
||||
"""Robust apply mechanism.
|
||||
|
||||
Provides a function 'call', which can sort out what arguments a given
|
||||
callable object can take, and subset the given arguments to match only
|
||||
those which are acceptable.
|
||||
"""
|
||||
|
||||
def function(receiver):
|
||||
"""Get function-like callable object for given receiver.
|
||||
|
||||
returns (function_or_method, codeObject, fromMethod)
|
||||
|
||||
If fromMethod is true, then the callable already has its first
|
||||
argument bound.
|
||||
"""
|
||||
if hasattr(receiver, '__call__'):
|
||||
# receiver is a class instance; assume it is callable.
|
||||
# Reassign receiver to the actual method that will be called.
|
||||
c = receiver.__call__
|
||||
if hasattr(c, 'im_func') or hasattr(c, 'im_code'):
|
||||
receiver = c
|
||||
if hasattr(receiver, 'im_func'):
|
||||
# receiver is an instance-method.
|
||||
return receiver, receiver.im_func.func_code, 1
|
||||
elif not hasattr(receiver, 'func_code'):
|
||||
raise ValueError(
|
||||
'unknown reciever type %s %s' % (receiver, type(receiver)))
|
||||
return receiver, receiver.func_code, 0
|
||||
|
||||
|
||||
def robust_apply(receiver, signature, *arguments, **named):
|
||||
"""Call receiver with arguments and appropriate subset of named.
|
||||
``signature`` is the callable used to determine the call signature
|
||||
of the receiver, in case ``receiver`` is a callable wrapper of the
|
||||
actual receiver."""
|
||||
signature, code_object, startIndex = function(signature)
|
||||
acceptable = code_object.co_varnames[
|
||||
startIndex + len(arguments):
|
||||
code_object.co_argcount
|
||||
]
|
||||
for name in code_object.co_varnames[
|
||||
startIndex:startIndex + len(arguments)
|
||||
]:
|
||||
if named.has_key(name):
|
||||
raise TypeError(
|
||||
'Argument %r specified both positionally '
|
||||
'and as a keyword for calling %r'
|
||||
% (name, signature)
|
||||
)
|
||||
if not (code_object.co_flags & 8):
|
||||
# fc does not have a **kwds type parameter, therefore
|
||||
# remove unacceptable arguments.
|
||||
for arg in named.keys():
|
||||
if arg not in acceptable:
|
||||
del named[arg]
|
||||
return receiver(*arguments, **named)
|
||||
|
||||
|
179
wlauto/external/louie/saferef.py
vendored
179
wlauto/external/louie/saferef.py
vendored
@@ -1,179 +0,0 @@
|
||||
"""Refactored 'safe reference from dispatcher.py"""
|
||||
|
||||
import weakref
|
||||
import traceback
|
||||
|
||||
|
||||
def safe_ref(target, on_delete=None):
|
||||
"""Return a *safe* weak reference to a callable target.
|
||||
|
||||
- ``target``: The object to be weakly referenced, if it's a bound
|
||||
method reference, will create a BoundMethodWeakref, otherwise
|
||||
creates a simple weakref.
|
||||
|
||||
- ``on_delete``: If provided, will have a hard reference stored to
|
||||
the callable to be called after the safe reference goes out of
|
||||
scope with the reference object, (either a weakref or a
|
||||
BoundMethodWeakref) as argument.
|
||||
"""
|
||||
if hasattr(target, 'im_self'):
|
||||
if target.im_self is not None:
|
||||
# Turn a bound method into a BoundMethodWeakref instance.
|
||||
# Keep track of these instances for lookup by disconnect().
|
||||
assert hasattr(target, 'im_func'), (
|
||||
"safe_ref target %r has im_self, but no im_func, "
|
||||
"don't know how to create reference"
|
||||
% target
|
||||
)
|
||||
reference = BoundMethodWeakref(target=target, on_delete=on_delete)
|
||||
return reference
|
||||
if callable(on_delete):
|
||||
return weakref.ref(target, on_delete)
|
||||
else:
|
||||
return weakref.ref(target)
|
||||
|
||||
|
||||
class BoundMethodWeakref(object):
|
||||
"""'Safe' and reusable weak references to instance methods.
|
||||
|
||||
BoundMethodWeakref objects provide a mechanism for referencing a
|
||||
bound method without requiring that the method object itself
|
||||
(which is normally a transient object) is kept alive. Instead,
|
||||
the BoundMethodWeakref object keeps weak references to both the
|
||||
object and the function which together define the instance method.
|
||||
|
||||
Attributes:
|
||||
|
||||
- ``key``: The identity key for the reference, calculated by the
|
||||
class's calculate_key method applied to the target instance method.
|
||||
|
||||
- ``deletion_methods``: Sequence of callable objects taking single
|
||||
argument, a reference to this object which will be called when
|
||||
*either* the target object or target function is garbage
|
||||
collected (i.e. when this object becomes invalid). These are
|
||||
specified as the on_delete parameters of safe_ref calls.
|
||||
|
||||
- ``weak_self``: Weak reference to the target object.
|
||||
|
||||
- ``weak_func``: Weak reference to the target function.
|
||||
|
||||
Class Attributes:
|
||||
|
||||
- ``_all_instances``: Class attribute pointing to all live
|
||||
BoundMethodWeakref objects indexed by the class's
|
||||
calculate_key(target) method applied to the target objects.
|
||||
This weak value dictionary is used to short-circuit creation so
|
||||
that multiple references to the same (object, function) pair
|
||||
produce the same BoundMethodWeakref instance.
|
||||
"""
|
||||
|
||||
_all_instances = weakref.WeakValueDictionary()
|
||||
|
||||
def __new__(cls, target, on_delete=None, *arguments, **named):
|
||||
"""Create new instance or return current instance.
|
||||
|
||||
Basically this method of construction allows us to
|
||||
short-circuit creation of references to already- referenced
|
||||
instance methods. The key corresponding to the target is
|
||||
calculated, and if there is already an existing reference,
|
||||
that is returned, with its deletion_methods attribute updated.
|
||||
Otherwise the new instance is created and registered in the
|
||||
table of already-referenced methods.
|
||||
"""
|
||||
key = cls.calculate_key(target)
|
||||
current = cls._all_instances.get(key)
|
||||
if current is not None:
|
||||
current.deletion_methods.append(on_delete)
|
||||
return current
|
||||
else:
|
||||
base = super(BoundMethodWeakref, cls).__new__(cls)
|
||||
cls._all_instances[key] = base
|
||||
base.__init__(target, on_delete, *arguments, **named)
|
||||
return base
|
||||
|
||||
def __init__(self, target, on_delete=None):
|
||||
"""Return a weak-reference-like instance for a bound method.
|
||||
|
||||
- ``target``: The instance-method target for the weak reference,
|
||||
must have im_self and im_func attributes and be
|
||||
reconstructable via the following, which is true of built-in
|
||||
instance methods::
|
||||
|
||||
target.im_func.__get__( target.im_self )
|
||||
|
||||
- ``on_delete``: Optional callback which will be called when
|
||||
this weak reference ceases to be valid (i.e. either the
|
||||
object or the function is garbage collected). Should take a
|
||||
single argument, which will be passed a pointer to this
|
||||
object.
|
||||
"""
|
||||
def remove(weak, self=self):
|
||||
"""Set self.isDead to True when method or instance is destroyed."""
|
||||
methods = self.deletion_methods[:]
|
||||
del self.deletion_methods[:]
|
||||
try:
|
||||
del self.__class__._all_instances[self.key]
|
||||
except KeyError:
|
||||
pass
|
||||
for function in methods:
|
||||
try:
|
||||
if callable(function):
|
||||
function(self)
|
||||
except Exception:
|
||||
try:
|
||||
traceback.print_exc()
|
||||
except AttributeError, e:
|
||||
print ('Exception during saferef %s '
|
||||
'cleanup function %s: %s' % (self, function, e))
|
||||
self.deletion_methods = [on_delete]
|
||||
self.key = self.calculate_key(target)
|
||||
self.weak_self = weakref.ref(target.im_self, remove)
|
||||
self.weak_func = weakref.ref(target.im_func, remove)
|
||||
self.self_name = str(target.im_self)
|
||||
self.func_name = str(target.im_func.__name__)
|
||||
|
||||
def calculate_key(cls, target):
|
||||
"""Calculate the reference key for this reference.
|
||||
|
||||
Currently this is a two-tuple of the id()'s of the target
|
||||
object and the target function respectively.
|
||||
"""
|
||||
return (id(target.im_self), id(target.im_func))
|
||||
calculate_key = classmethod(calculate_key)
|
||||
|
||||
def __str__(self):
|
||||
"""Give a friendly representation of the object."""
|
||||
return "%s(%s.%s)" % (
|
||||
self.__class__.__name__,
|
||||
self.self_name,
|
||||
self.func_name,
|
||||
)
|
||||
|
||||
__repr__ = __str__
|
||||
|
||||
def __nonzero__(self):
|
||||
"""Whether we are still a valid reference."""
|
||||
return self() is not None
|
||||
|
||||
def __cmp__(self, other):
|
||||
"""Compare with another reference."""
|
||||
if not isinstance(other, self.__class__):
|
||||
return cmp(self.__class__, type(other))
|
||||
return cmp(self.key, other.key)
|
||||
|
||||
def __call__(self):
|
||||
"""Return a strong reference to the bound method.
|
||||
|
||||
If the target cannot be retrieved, then will return None,
|
||||
otherwise returns a bound instance method for our object and
|
||||
function.
|
||||
|
||||
Note: You may call this method any number of times, as it does
|
||||
not invalidate the reference.
|
||||
"""
|
||||
target = self.weak_self()
|
||||
if target is not None:
|
||||
function = self.weak_func()
|
||||
if function is not None:
|
||||
return function.__get__(target)
|
||||
return None
|
39
wlauto/external/louie/sender.py
vendored
39
wlauto/external/louie/sender.py
vendored
@@ -1,39 +0,0 @@
|
||||
"""Sender classes."""
|
||||
|
||||
|
||||
class _SENDER(type):
|
||||
"""Base metaclass for sender classes."""
|
||||
|
||||
def __str__(cls):
|
||||
return '<Sender: %s>' % (cls.__name__, )
|
||||
|
||||
|
||||
class Any(object):
|
||||
"""Used to represent either 'any sender'.
|
||||
|
||||
The Any class can be used with connect, disconnect, send, or
|
||||
sendExact to denote that the sender paramater should react to any
|
||||
sender, not just a particular sender.
|
||||
"""
|
||||
|
||||
__metaclass__ = _SENDER
|
||||
|
||||
|
||||
class Anonymous(object):
|
||||
"""Singleton used to signal 'anonymous sender'.
|
||||
|
||||
The Anonymous class is used to signal that the sender of a message
|
||||
is not specified (as distinct from being 'any sender').
|
||||
Registering callbacks for Anonymous will only receive messages
|
||||
sent without senders. Sending with anonymous will only send
|
||||
messages to those receivers registered for Any or Anonymous.
|
||||
|
||||
Note: The default sender for connect is Any, while the default
|
||||
sender for send is Anonymous. This has the effect that if you do
|
||||
not specify any senders in either function then all messages are
|
||||
routed as though there was a single sender (Anonymous) being used
|
||||
everywhere.
|
||||
"""
|
||||
|
||||
__metaclass__ = _SENDER
|
||||
|
30
wlauto/external/louie/signal.py
vendored
30
wlauto/external/louie/signal.py
vendored
@@ -1,30 +0,0 @@
|
||||
"""Signal class.
|
||||
|
||||
This class is provided as a way to consistently define and document
|
||||
signal types. Signal classes also have a useful string
|
||||
representation.
|
||||
|
||||
Louie does not require you to use a subclass of Signal for signals.
|
||||
"""
|
||||
|
||||
|
||||
class _SIGNAL(type):
|
||||
"""Base metaclass for signal classes."""
|
||||
|
||||
def __str__(cls):
|
||||
return '<Signal: %s>' % (cls.__name__, )
|
||||
|
||||
|
||||
class Signal(object):
|
||||
|
||||
__metaclass__ = _SIGNAL
|
||||
|
||||
|
||||
class All(Signal):
|
||||
"""Used to represent 'all signals'.
|
||||
|
||||
The All class can be used with connect, disconnect, send, or
|
||||
sendExact to denote that the signal should react to all signals,
|
||||
not just a particular signal.
|
||||
"""
|
||||
|
0
wlauto/external/louie/test/__init__.py
vendored
0
wlauto/external/louie/test/__init__.py
vendored
5
wlauto/external/louie/test/conftest.py
vendored
5
wlauto/external/louie/test/conftest.py
vendored
@@ -1,5 +0,0 @@
|
||||
import sys
|
||||
import os
|
||||
|
||||
sys.path.insert(0, os.path.dirname(os.path.dirname(__file__)))
|
||||
|
0
wlauto/external/louie/test/fixture.py
vendored
0
wlauto/external/louie/test/fixture.py
vendored
154
wlauto/external/louie/test/test_dispatcher.py
vendored
154
wlauto/external/louie/test/test_dispatcher.py
vendored
@@ -1,154 +0,0 @@
|
||||
import unittest
|
||||
|
||||
import louie
|
||||
from louie import dispatcher
|
||||
|
||||
|
||||
def x(a):
|
||||
return a
|
||||
|
||||
|
||||
class Dummy(object):
|
||||
pass
|
||||
|
||||
|
||||
class Callable(object):
|
||||
|
||||
def __call__(self, a):
|
||||
return a
|
||||
|
||||
def a(self, a):
|
||||
return a
|
||||
|
||||
|
||||
class TestDispatcher(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
louie.reset()
|
||||
|
||||
def _isclean(self):
|
||||
"""Assert that everything has been cleaned up automatically"""
|
||||
assert len(dispatcher.senders_back) == 0, dispatcher.senders_back
|
||||
assert len(dispatcher.connections) == 0, dispatcher.connections
|
||||
assert len(dispatcher.senders) == 0, dispatcher.senders
|
||||
|
||||
def test_Exact(self):
|
||||
a = Dummy()
|
||||
signal = 'this'
|
||||
louie.connect(x, signal, a)
|
||||
expected = [(x, a)]
|
||||
result = louie.send('this', a, a=a)
|
||||
assert result == expected, (
|
||||
"Send didn't return expected result:\n\texpected:%s\n\tgot:%s"
|
||||
% (expected, result))
|
||||
louie.disconnect(x, signal, a)
|
||||
assert len(list(louie.get_all_receivers(a, signal))) == 0
|
||||
self._isclean()
|
||||
|
||||
def test_AnonymousSend(self):
|
||||
a = Dummy()
|
||||
signal = 'this'
|
||||
louie.connect(x, signal)
|
||||
expected = [(x, a)]
|
||||
result = louie.send(signal, None, a=a)
|
||||
assert result == expected, (
|
||||
"Send didn't return expected result:\n\texpected:%s\n\tgot:%s"
|
||||
% (expected, result))
|
||||
louie.disconnect(x, signal)
|
||||
assert len(list(louie.get_all_receivers(None, signal))) == 0
|
||||
self._isclean()
|
||||
|
||||
def test_AnyRegistration(self):
|
||||
a = Dummy()
|
||||
signal = 'this'
|
||||
louie.connect(x, signal, louie.Any)
|
||||
expected = [(x, a)]
|
||||
result = louie.send('this', object(), a=a)
|
||||
assert result == expected, (
|
||||
"Send didn't return expected result:\n\texpected:%s\n\tgot:%s"
|
||||
% (expected, result))
|
||||
louie.disconnect(x, signal, louie.Any)
|
||||
expected = []
|
||||
result = louie.send('this', object(), a=a)
|
||||
assert result == expected, (
|
||||
"Send didn't return expected result:\n\texpected:%s\n\tgot:%s"
|
||||
% (expected, result))
|
||||
assert len(list(louie.get_all_receivers(louie.Any, signal))) == 0
|
||||
self._isclean()
|
||||
|
||||
def test_AllRegistration(self):
|
||||
a = Dummy()
|
||||
signal = 'this'
|
||||
louie.connect(x, louie.All, a)
|
||||
expected = [(x, a)]
|
||||
result = louie.send('this', a, a=a)
|
||||
assert result == expected, (
|
||||
"Send didn't return expected result:\n\texpected:%s\n\tgot:%s"
|
||||
% (expected, result))
|
||||
louie.disconnect(x, louie.All, a)
|
||||
assert len(list(louie.get_all_receivers(a, louie.All))) == 0
|
||||
self._isclean()
|
||||
|
||||
def test_GarbageCollected(self):
|
||||
a = Callable()
|
||||
b = Dummy()
|
||||
signal = 'this'
|
||||
louie.connect(a.a, signal, b)
|
||||
expected = []
|
||||
del a
|
||||
result = louie.send('this', b, a=b)
|
||||
assert result == expected, (
|
||||
"Send didn't return expected result:\n\texpected:%s\n\tgot:%s"
|
||||
% (expected, result))
|
||||
assert len(list(louie.get_all_receivers(b, signal))) == 0, (
|
||||
"Remaining handlers: %s" % (louie.get_all_receivers(b, signal),))
|
||||
self._isclean()
|
||||
|
||||
def test_GarbageCollectedObj(self):
|
||||
class x:
|
||||
def __call__(self, a):
|
||||
return a
|
||||
a = Callable()
|
||||
b = Dummy()
|
||||
signal = 'this'
|
||||
louie.connect(a, signal, b)
|
||||
expected = []
|
||||
del a
|
||||
result = louie.send('this', b, a=b)
|
||||
assert result == expected, (
|
||||
"Send didn't return expected result:\n\texpected:%s\n\tgot:%s"
|
||||
% (expected, result))
|
||||
assert len(list(louie.get_all_receivers(b, signal))) == 0, (
|
||||
"Remaining handlers: %s" % (louie.get_all_receivers(b, signal),))
|
||||
self._isclean()
|
||||
|
||||
def test_MultipleRegistration(self):
|
||||
a = Callable()
|
||||
b = Dummy()
|
||||
signal = 'this'
|
||||
louie.connect(a, signal, b)
|
||||
louie.connect(a, signal, b)
|
||||
louie.connect(a, signal, b)
|
||||
louie.connect(a, signal, b)
|
||||
louie.connect(a, signal, b)
|
||||
louie.connect(a, signal, b)
|
||||
result = louie.send('this', b, a=b)
|
||||
assert len(result) == 1, result
|
||||
assert len(list(louie.get_all_receivers(b, signal))) == 1, (
|
||||
"Remaining handlers: %s" % (louie.get_all_receivers(b, signal),))
|
||||
del a
|
||||
del b
|
||||
del result
|
||||
self._isclean()
|
||||
|
||||
def test_robust(self):
|
||||
"""Test the sendRobust function."""
|
||||
def fails():
|
||||
raise ValueError('this')
|
||||
a = object()
|
||||
signal = 'this'
|
||||
louie.connect(fails, louie.All, a)
|
||||
result = louie.send_robust('this', a, a=a)
|
||||
err = result[0][1]
|
||||
assert isinstance(err, ValueError)
|
||||
assert err.args == ('this', )
|
145
wlauto/external/louie/test/test_plugin.py
vendored
145
wlauto/external/louie/test/test_plugin.py
vendored
@@ -1,145 +0,0 @@
|
||||
"""Louie plugin tests."""
|
||||
|
||||
import unittest
|
||||
|
||||
import louie
|
||||
|
||||
try:
|
||||
import qt
|
||||
if not hasattr(qt.qApp, 'for_testing'):
|
||||
_app = qt.QApplication([])
|
||||
_app.for_testing = True
|
||||
qt.qApp = _app
|
||||
except ImportError:
|
||||
qt = None
|
||||
|
||||
|
||||
class ReceiverBase(object):
|
||||
|
||||
def __init__(self):
|
||||
self.args = []
|
||||
self.live = True
|
||||
|
||||
def __call__(self, arg):
|
||||
self.args.append(arg)
|
||||
|
||||
class Receiver1(ReceiverBase):
|
||||
pass
|
||||
|
||||
class Receiver2(ReceiverBase):
|
||||
pass
|
||||
|
||||
|
||||
class Plugin1(louie.Plugin):
|
||||
|
||||
def is_live(self, receiver):
|
||||
"""ReceiverBase instances are only live if their `live`
|
||||
attribute is True"""
|
||||
if isinstance(receiver, ReceiverBase):
|
||||
return receiver.live
|
||||
return True
|
||||
|
||||
|
||||
class Plugin2(louie.Plugin):
|
||||
|
||||
def is_live(self, receiver):
|
||||
"""Pretend all Receiver2 instances are not live."""
|
||||
if isinstance(receiver, Receiver2):
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def test_only_one_instance():
|
||||
louie.reset()
|
||||
plugin1a = Plugin1()
|
||||
plugin1b = Plugin1()
|
||||
louie.install_plugin(plugin1a)
|
||||
# XXX: Move these tests into test cases so we can use unittest's
|
||||
# 'assertRaises' method.
|
||||
try:
|
||||
louie.install_plugin(plugin1b)
|
||||
except louie.error.PluginTypeError:
|
||||
pass
|
||||
else:
|
||||
raise Exception('PluginTypeError not raised')
|
||||
|
||||
|
||||
def test_is_live():
|
||||
louie.reset()
|
||||
# Create receivers.
|
||||
receiver1a = Receiver1()
|
||||
receiver1b = Receiver1()
|
||||
receiver2a = Receiver2()
|
||||
receiver2b = Receiver2()
|
||||
# Connect signals.
|
||||
louie.connect(receiver1a, 'sig')
|
||||
louie.connect(receiver1b, 'sig')
|
||||
louie.connect(receiver2a, 'sig')
|
||||
louie.connect(receiver2b, 'sig')
|
||||
# Check reception without plugins.
|
||||
louie.send('sig', arg='foo')
|
||||
assert receiver1a.args == ['foo']
|
||||
assert receiver1b.args == ['foo']
|
||||
assert receiver2a.args == ['foo']
|
||||
assert receiver2b.args == ['foo']
|
||||
# Install plugin 1.
|
||||
plugin1 = Plugin1()
|
||||
louie.install_plugin(plugin1)
|
||||
# Make some receivers not live.
|
||||
receiver1a.live = False
|
||||
receiver2b.live = False
|
||||
# Check reception.
|
||||
louie.send('sig', arg='bar')
|
||||
assert receiver1a.args == ['foo']
|
||||
assert receiver1b.args == ['foo', 'bar']
|
||||
assert receiver2a.args == ['foo', 'bar']
|
||||
assert receiver2b.args == ['foo']
|
||||
# Remove plugin 1, install plugin 2.
|
||||
plugin2 = Plugin2()
|
||||
louie.remove_plugin(plugin1)
|
||||
louie.install_plugin(plugin2)
|
||||
# Check reception.
|
||||
louie.send('sig', arg='baz')
|
||||
assert receiver1a.args == ['foo', 'baz']
|
||||
assert receiver1b.args == ['foo', 'bar', 'baz']
|
||||
assert receiver2a.args == ['foo', 'bar']
|
||||
assert receiver2b.args == ['foo']
|
||||
# Install plugin 1 alongside plugin 2.
|
||||
louie.install_plugin(plugin1)
|
||||
# Check reception.
|
||||
louie.send('sig', arg='fob')
|
||||
assert receiver1a.args == ['foo', 'baz']
|
||||
assert receiver1b.args == ['foo', 'bar', 'baz', 'fob']
|
||||
assert receiver2a.args == ['foo', 'bar']
|
||||
assert receiver2b.args == ['foo']
|
||||
|
||||
|
||||
if qt is not None:
|
||||
def test_qt_plugin():
|
||||
louie.reset()
|
||||
# Create receivers.
|
||||
class Receiver(qt.QWidget):
|
||||
def __init__(self):
|
||||
qt.QObject.__init__(self)
|
||||
self.args = []
|
||||
def receive(self, arg):
|
||||
self.args.append(arg)
|
||||
receiver1 = Receiver()
|
||||
receiver2 = Receiver()
|
||||
# Connect signals.
|
||||
louie.connect(receiver1.receive, 'sig')
|
||||
louie.connect(receiver2.receive, 'sig')
|
||||
# Destroy receiver2 so only a shell is left.
|
||||
receiver2.close(True)
|
||||
# Check reception without plugins.
|
||||
louie.send('sig', arg='foo')
|
||||
assert receiver1.args == ['foo']
|
||||
assert receiver2.args == ['foo']
|
||||
# Install plugin.
|
||||
plugin = louie.QtWidgetPlugin()
|
||||
louie.install_plugin(plugin)
|
||||
# Check reception with plugins.
|
||||
louie.send('sig', arg='bar')
|
||||
assert receiver1.args == ['foo', 'bar']
|
||||
assert receiver2.args == ['foo']
|
||||
|
@@ -1,41 +0,0 @@
|
||||
import unittest
|
||||
|
||||
import louie
|
||||
from louie import dispatcher
|
||||
|
||||
class Callable(object):
|
||||
|
||||
def __init__(self, val):
|
||||
self.val = val
|
||||
|
||||
def __call__(self):
|
||||
return self.val
|
||||
|
||||
|
||||
one = Callable(1)
|
||||
two = Callable(2)
|
||||
three = Callable(3)
|
||||
|
||||
class TestPriorityDispatcher(unittest.TestCase):
|
||||
|
||||
def test_ConnectNotify(self):
|
||||
louie.connect(
|
||||
two,
|
||||
'one',
|
||||
priority=200
|
||||
)
|
||||
louie.connect(
|
||||
one,
|
||||
'one',
|
||||
priority=100
|
||||
)
|
||||
louie.connect(
|
||||
three,
|
||||
'one',
|
||||
priority=300
|
||||
)
|
||||
result = [ i[1] for i in louie.send('one')]
|
||||
if not result == [1, 2, 3]:
|
||||
print result
|
||||
assert(False)
|
||||
|
62
wlauto/external/louie/test/test_prioritylist.py
vendored
62
wlauto/external/louie/test/test_prioritylist.py
vendored
@@ -1,62 +0,0 @@
|
||||
import unittest
|
||||
|
||||
import louie.prioritylist
|
||||
from louie.prioritylist import PriorityList
|
||||
|
||||
#def populate_list(plist):
|
||||
|
||||
class TestPriorityList(unittest.TestCase):
|
||||
|
||||
def test_Insert(self):
|
||||
pl = PriorityList()
|
||||
elements = {3: "element 3",
|
||||
2: "element 2",
|
||||
1: "element 1",
|
||||
5: "element 5",
|
||||
4: "element 4"
|
||||
}
|
||||
for key in elements:
|
||||
pl.add(elements[key], priority=key)
|
||||
|
||||
match = zip(sorted(elements.values()), pl[:])
|
||||
for pair in match:
|
||||
assert(pair[0]==pair[1])
|
||||
|
||||
def test_Delete(self):
|
||||
pl = PriorityList()
|
||||
elements = {2: "element 3",
|
||||
1: "element 2",
|
||||
0: "element 1",
|
||||
4: "element 5",
|
||||
3: "element 4"
|
||||
}
|
||||
for key in elements:
|
||||
pl.add(elements[key], priority=key)
|
||||
del elements[2]
|
||||
del pl[2]
|
||||
match = zip(sorted(elements.values()) , pl[:])
|
||||
for pair in match:
|
||||
assert(pair[0]==pair[1])
|
||||
|
||||
def test_Multiple(self):
|
||||
pl = PriorityList()
|
||||
pl.add('1', 1)
|
||||
pl.add('2.1', 2)
|
||||
pl.add('3', 3)
|
||||
pl.add('2.2', 2)
|
||||
it = iter(pl)
|
||||
assert(it.next() == '1')
|
||||
assert(it.next() == '2.1')
|
||||
assert(it.next() == '2.2')
|
||||
assert(it.next() == '3')
|
||||
|
||||
def test_IteratorBreak(self):
|
||||
pl = PriorityList()
|
||||
pl.add('1', 1)
|
||||
pl.add('2.1', 2)
|
||||
pl.add('3', 3)
|
||||
pl.add('2.2', 2)
|
||||
for i in pl:
|
||||
if i == '2.1':
|
||||
break
|
||||
assert(pl.index('3') == 3)
|
34
wlauto/external/louie/test/test_robustapply.py
vendored
34
wlauto/external/louie/test/test_robustapply.py
vendored
@@ -1,34 +0,0 @@
|
||||
import unittest
|
||||
|
||||
from louie.robustapply import robust_apply
|
||||
|
||||
|
||||
def no_argument():
|
||||
pass
|
||||
|
||||
|
||||
def one_argument(blah):
|
||||
pass
|
||||
|
||||
|
||||
def two_arguments(blah, other):
|
||||
pass
|
||||
|
||||
|
||||
class TestRobustApply(unittest.TestCase):
|
||||
|
||||
def test_01(self):
|
||||
robust_apply(no_argument, no_argument)
|
||||
|
||||
def test_02(self):
|
||||
self.assertRaises(TypeError, robust_apply, no_argument, no_argument,
|
||||
'this' )
|
||||
|
||||
def test_03(self):
|
||||
self.assertRaises(TypeError, robust_apply, one_argument, one_argument)
|
||||
|
||||
def test_04(self):
|
||||
"""Raise error on duplication of a particular argument"""
|
||||
self.assertRaises(TypeError, robust_apply, one_argument, one_argument,
|
||||
'this', blah='that')
|
||||
|
83
wlauto/external/louie/test/test_saferef.py
vendored
83
wlauto/external/louie/test/test_saferef.py
vendored
@@ -1,83 +0,0 @@
|
||||
import unittest
|
||||
|
||||
from louie.saferef import safe_ref
|
||||
|
||||
|
||||
class _Sample1(object):
|
||||
def x(self):
|
||||
pass
|
||||
|
||||
|
||||
def _sample2(obj):
|
||||
pass
|
||||
|
||||
|
||||
class _Sample3(object):
|
||||
def __call__(self, obj):
|
||||
pass
|
||||
|
||||
|
||||
class TestSaferef(unittest.TestCase):
|
||||
|
||||
# XXX: The original tests had a test for closure, and it had an
|
||||
# off-by-one problem, perhaps due to scope issues. It has been
|
||||
# removed from this test suite.
|
||||
|
||||
def setUp(self):
|
||||
ts = []
|
||||
ss = []
|
||||
for x in xrange(5000):
|
||||
t = _Sample1()
|
||||
ts.append(t)
|
||||
s = safe_ref(t.x, self._closure)
|
||||
ss.append(s)
|
||||
ts.append(_sample2)
|
||||
ss.append(safe_ref(_sample2, self._closure))
|
||||
for x in xrange(30):
|
||||
t = _Sample3()
|
||||
ts.append(t)
|
||||
s = safe_ref(t, self._closure)
|
||||
ss.append(s)
|
||||
self.ts = ts
|
||||
self.ss = ss
|
||||
self.closure_count = 0
|
||||
|
||||
def tearDown(self):
|
||||
if hasattr(self, 'ts'):
|
||||
del self.ts
|
||||
if hasattr(self, 'ss'):
|
||||
del self.ss
|
||||
|
||||
def test_In(self):
|
||||
"""Test the `in` operator for safe references (cmp)"""
|
||||
for t in self.ts[:50]:
|
||||
assert safe_ref(t.x) in self.ss
|
||||
|
||||
def test_Valid(self):
|
||||
"""Test that the references are valid (return instance methods)"""
|
||||
for s in self.ss:
|
||||
assert s()
|
||||
|
||||
def test_ShortCircuit(self):
|
||||
"""Test that creation short-circuits to reuse existing references"""
|
||||
sd = {}
|
||||
for s in self.ss:
|
||||
sd[s] = 1
|
||||
for t in self.ts:
|
||||
if hasattr(t, 'x'):
|
||||
assert sd.has_key(safe_ref(t.x))
|
||||
else:
|
||||
assert sd.has_key(safe_ref(t))
|
||||
|
||||
def test_Representation(self):
|
||||
"""Test that the reference object's representation works
|
||||
|
||||
XXX Doesn't currently check the results, just that no error
|
||||
is raised
|
||||
"""
|
||||
repr(self.ss[-1])
|
||||
|
||||
def _closure(self, ref):
|
||||
"""Dumb utility mechanism to increment deletion counter"""
|
||||
self.closure_count += 1
|
||||
|
8
wlauto/external/louie/version.py
vendored
8
wlauto/external/louie/version.py
vendored
@@ -1,8 +0,0 @@
|
||||
"""Louie version information."""
|
||||
|
||||
|
||||
NAME = 'Louie'
|
||||
DESCRIPTION = 'Signal dispatching mechanism'
|
||||
VERSION = '1.1'
|
||||
|
||||
|
Reference in New Issue
Block a user