* Passing a Python subclass of a C++ class now works, the extra Python stuff isn't just discarded
* EventParameter objects are no longer automagically unwrapped - there's no more reason to pass an EventParameter to this method anyway, and it might be unexpected if it is treated specially.
This matches the behaviour of asyncio. It schedules with the current task's manager and chain. If no current manager is found, it prints a warning. (The user can just add the coroutine to a task manager themselves and pass the resulting task into gather() if needed.)
See discussion here:
https://discourse.panda3d.org/t/task-gather-does-not-seem-to-work/27313
The intended purpose of this function is to restore an exception
that has already been raised and saved with PyErr_Fetch. It should
not be used to raise new exceptions nor should it be used to clear
the current exception.
The especially egregious example is
`PyErr_Restore(exc_type, nullptr, nullptr);`
as the null value may not be handled correctly.
This introduces AsyncFuture as a new base class of AsyncTask. It's modelled after asyncio's Future class, except that it is thread-safe and you can use result() to block the current thread waiting for the future to finish (of course this is not necessary for use with coroutines).
AsyncFuture should be used for any operation that finishes in the future, to get the benefit of awaitability within coroutines as well as a standard interface for querying status and results of the operation as well as cancelling it. As such, it's been implemented in various places, including texture.prepare() and win.trigger_copy().
Note that AsyncFuture is intended to be used *once*; it cannot be used more than once. As an example of how this works, tex.prepare() will return the same future as long as the prepare isn't complete, but when it is done, subsequent calls to tex.prepare() will return a new future.