fma wrote:uasyncio.core relies on the fact that (unix) poller uses a file descriptor, and so calls polled object fileno() method. But UART, which is said to be pollable, does not have such method. So, I guess I need to overwrite the entire run_forever() method, replacing arg.fileno() with just arg. Am I write?
But then, what if I want to poll both standard objects (socket, file...) which do have fileno() method and needs to be polled on their fd, and specific pyboard objects, like UART, which don't have fd?
Doing such analysis and proposing (concurrent) solution(s) to the situation is the essence of programming.
So, based on the analysis above, I can propose different ways to solve it:
1. We implement function inlining in uPy compiler so we're not afraid of functional abstraction. (Because currently, function calls are expensive, and that's why uasyncio main loop written as pretty big flat code). This is the most productive solution, especially if someone volunteers to implement it.
2. We add "if" or exception handling to call .fileno() only of it exists, and use arg as is otherwise. To this, I don't agree, as it hurts performance .
3. We say that UART should have .fileno() method and that it's essentially part of stream interface, so any object which can be used as stream should implement it.
4. We change function signature of .add_reader() and friends - instead of accepting "file descriptor", as CPython asyncio mandates, it would accept "file-like object", and .add_reader() can decide what to do with it (it will be likely overridden for particular implementation anyway).
4 is the most compromise variant, which would be good choice for a winner. But it adds another discrepancy with CPython asyncio . So, I'd like to have better discussion of this, in particular consider burdening @dpgeorge with choice 3 . And as he doesn't appear here too often, that would warrant a github ticket with reference back to this post.