Document passing arguments to event handlers
- Dominant language
- Python
- Stars
- 5.4k
- Forks
- 827
- Avg merge
- 15h 39m
- Merged PRs (30d)
- 40
Description
**Summary by @freakboy3742**
We are regularly asked either (a) how to "pass in arguments to event handlers", or (b) for a feature addition to do the same. This isn't something that needs additional functionality - it just needs a better understanding of how Python can be used.
We should add a topic guide describing how to pass in additional details to an event handler, including:
* state variables on the app
* generator functions
* functools.partial
* using something other than `add_background_task` for background work.
Originally framed in the form of a feature request, asking for the ability to pass in coroutines to add_background_task; details follow. The comments following the ticket give a starting point for a discussion in the topic guide.
-----
**Original post by @Cimbali**
### What is the problem or limitation you are having?
Currently `add_background_task` accepts generators and coroutine functions (i.e. functions that return a coroutine). This makes passing an asynchronous function that takes arguments quite awkward.
Suppose I have an async function (“coroutine function”) that takes some arguments:
```
async def func(arg1, arg2):
pass
```
With asyncio, the idiom is call the function, have it return a coroutine, and let asyncio take care of running it:
```
asyncio.run(func('a', 'b'))
```
In toga, the idiom requires toga to call the function, which means we are now fixing the prototype of the function:
```
app.add_background_function(func) # Does not fit func’s prototype!
```
### Describe the solution you'd like
If `add_background_function` supported passing in coroutines, we could do:
```
app.add_background_function(func('a', 'b'))
```
### Describe alternatives you've considered
If I want to pass several arguments to an async function run in the background, the most concise I can do is:
```
async def wrapper(app):
return await func('a', 'b')
app.add_background_function(wrapper)
```
Which in more complex code becomes quite annoying, and means a function closure for every call, plus an additional `await`.
### Additional context
Note you also can’t do:
```
def wrapper(app):
return func('a', 'b')
```
This also returns a coroutine which is awaitable (and `asyncio.run(wrapper(app))` woulc work as expected) but the wrapper isn’t _decorated_ as a coroutine function.
Contributor guide
Research direction
Start by locating the topic-guide documentation for event handlers and the existing add_background_task guidance. Use the examples in this issue to cover app state variables, generator functions, functools.partial, and alternatives for background work. Done means the guide explains how to pass additional details without requiring new functionality.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- documentation
- Issue type
- Documentation
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100