Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 6 additions & 8 deletions src/qasync/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -824,8 +824,7 @@ def wrapper(*args, **kwargs):
# Qt ignores trailing args from a signal but python does
# not so inspect the slot signature and if it's not
# callable try removing args until it is.
task = None
while len(args):
while True:
try:
inspect.signature(fn).bind(*args, **kwargs)
except TypeError:
Expand All @@ -834,15 +833,14 @@ def wrapper(*args, **kwargs):
args = list(args)
args.pop()
continue
else:
raise TypeError(
"asyncSlot was not callable from Signal. Potential signature mismatch."
)
else:
task = asyncio.ensure_future(fn(*args, **kwargs))
task.add_done_callback(_error_handler)
break
if task is None:
raise TypeError(
"asyncSlot was not callable from Signal. Potential signature mismatch."
)
return task
return task

return wrapper

Expand Down
47 changes: 46 additions & 1 deletion tests/test_qeventloop.py
Original file line number Diff line number Diff line change
Expand Up @@ -793,6 +793,51 @@ async def mycoro():
assert not loop.is_running()


def test_async_slot(loop):
no_args_called = asyncio.Event()
with_args_called = asyncio.Event()
trailing_args_called = asyncio.Event()

async def slot_no_args():
no_args_called.set()

async def slot_with_args(flag: bool):
assert flag
with_args_called.set()

async def slot_trailing_args(flag: bool):
assert flag
trailing_args_called.set()

async def slot_signature_mismatch(_: bool): ...

async def main():
# passing kwargs to the underlying Slot such as name, arguments, return
sig = qasync._make_signaller(qasync.QtCore)
sig.signal.connect(qasync.asyncSlot(name="slot")(slot_no_args))
sig.signal.emit()

sig1 = qasync._make_signaller(qasync.QtCore, bool)
sig1.signal.connect(qasync.asyncSlot(bool)(slot_with_args))
sig1.signal.emit(True)

# when a signal produces more arguments than a slot, trailing args are removed
sig2 = qasync._make_signaller(qasync.QtCore, bool, bool)
sig2.signal.connect(qasync.asyncSlot()(slot_trailing_args))
sig2.signal.emit(True, False)

# signature mismatch when called
with pytest.raises(TypeError):
qasync.asyncSlot(bool)(slot_signature_mismatch)()

all_done = asyncio.gather(
no_args_called.wait(), with_args_called.wait(), trailing_args_called.wait()
)
await asyncio.wait_for(all_done, timeout=1.0)

loop.run_until_complete(main())


@pytest.mark.parametrize(
"async_wrap, expect_async_called, expect_exception",
[(False, False, True), (True, True, False)],
Expand Down Expand Up @@ -829,7 +874,6 @@ async def main():
await coro # avoid warnings about unawaited coroutines
assert res == 1
main_called = True


exceptions = []
loop.set_exception_handler(lambda loop, context: exceptions.append(context))
Expand Down Expand Up @@ -917,6 +961,7 @@ async def coro():

thread.join() # Ensure thread cleanup


def teardown_module(module):
"""
Remove handlers from all loggers
Expand Down
Loading