diff --git a/src/tests/test.py b/src/tests/test.py index be9f851..673d706 100644 --- a/src/tests/test.py +++ b/src/tests/test.py @@ -12,6 +12,70 @@ except ImportError: import documentation as doc # good with `python src/tests/test.py` +try: + from PyQt5 import QtGui, QtWidgets +except ImportError: + pass +else: + class PlainActionCreator: + def __init__(self): + self.messages = [] + self.action = QtWidgets.QAction() + self.action.triggered.connect(self.ActionCallbackNoArg) + self.action.triggered.connect(self.ActionCallbackOneArg) + self.action.triggered.connect(self.ActionCallbackAnyArgs) + + def ActionCallbackNoArg(self): + self.messages.append(('ActionCallbackNoArg',)) + + def ActionCallbackOneArg(self, value): + self.messages.append(('ActionCallbackOneArg', value)) + + def ActionCallbackAnyArgs(self, *args, **kwargs): + self.messages.append(('ActionCallbackAnyArgs', args, kwargs)) + + + @decorator + def dummy_decorator(f, *args, **kwargs): + return f(*args, **kwargs) + + + class DecoratedActionCreator(PlainActionCreator): + @dummy_decorator + def ActionCallbackNoArg(self): + self.messages.append(('ActionCallbackNoArg',)) + + @dummy_decorator + def ActionCallbackOneArg(self, value): + self.messages.append(('ActionCallbackOneArg', value)) + + @dummy_decorator + def ActionCallbackAnyArgs(self, *args, **kwargs): + self.messages.append(('ActionCallbackAnyArgs', args, kwargs)) + + class QtActionTestCase(unittest.TestCase): + def test_qt_decorator_signature_preserving_interaction_methods(self): + """ + This test that decorated methods have the signature respected by qt. + The problem does not show up on free functions. + """ + # Sanity: Qt respect "plain" method signatures. + plain = PlainActionCreator() + plain.action.trigger() + self.assertEqual( + plain.messages, + [ + ('ActionCallbackNoArg',), + ('ActionCallbackOneArg', False), + ('ActionCallbackAnyArgs', (False,), {}), + ], + ) + # Qt should also respect decorated method signatures. + decorated = DecoratedActionCreator() + decorated.action.trigger() # If qt/decorator interaction fail this should cause an error. + self.assertEqual(decorated.messages, plain.messages) + + @contextmanager def assertRaises(etype): """This works in Python 2.6 too"""