Skip to content

Improve waitSignal/waitSignals TimeoutError messages and catch arguments #151

@MShekow

Description

@MShekow

Hi. I've started thinking about implementing these 2 features (as they are closely related). Originally @nicoddemus suggested that SignalBlocker could show the following message:

TimeoutError:  `text_received` emitted with ['WAIT_CLIENTS', 'PROCESSING'] 
but did not satisfy the `is_disconnected` callback.

I investigated a bit and it seems that it's not possible to get the actual name of the signal (here: text_received) within SignalBlocker. The reason is that Signal objects don't have a __name__ attribute. PyQt4/5 signals have an internal signal field which contains the name of the signal itself, prefixed with a '2' (don't ask me why, I'll ask in the pyqt mailing list), whereas PySide signals have no attributes at all, their str() representation is just something like <PySide.QtCore.SignalInstance object at 0x05D82880>.

I'm not sure how to continue now. For SignalBlocker it's not much of an issue, as the wait() call of the blocker expects just one signal anyway, and the code line number in the stack trace of a failed test will allow the test engineer to figure out which signal exactly failed.

However, I'd also like to add this feature to MultiSignalBlocker. Here it would be nice to have a human-readable form of all caught signals, including their parameters. From what we currently know, it wouldn't be possible to get the name of the emitted signals.

After a bit more digging, I found that there could be a solution, if we can get _AbstractSignalBlocker to inherit from QObject. Because then we can get the signal by getting the signal's sender and iterating over its attributes, as follows:

# the following code (Python 3) works when placed inside SignalBlocker._quit_loop_by_signal() and
# you manually change that _AbstractSignalBlocker inherits from QObject of some Qt framework
def get_signal_name():
    sender = self.sender()
    possible_signal_names = [possible_signal_name for possible_signal_name in sender.__dict__]
    if not possible_signal_names:
        # e.g. PyQt5 has an empty __dict__ for some reason...
        possible_signal_names = dir(self.sender())
    for possible_signal_name in possible_signal_names:
        possible_signal = getattr(sender, possible_signal_name, None)
        if possible_signal and str(self._signals[0]) == str(possible_signal):
            return possible_signal_name
    return "UNKNOWN SIGNAL"

Is there a way to have _AbstractSignalBlocker inherit from the configuration-specific QObject implementation?

Cheers!
Marius

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions