-
-
Notifications
You must be signed in to change notification settings - Fork 335
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Consider converting lowest-level I/O primitives from global functions into methods #475
Comments
Concretely this probably involves:
|
I've been saying we should do this for #542, but actually I'm still feeling a bit indecisive about whether this is a good idea. There are two independent motivations, which is normally a pretty strong argument. But how strong are they really? Basically the issue is that right now, the set of supported low-level operations is determined at import time. Problem 1: If we want to do static analysis, like type-checking and linting (#542), then import time is too late: analysis tools can't tell which functions are actually available, or what their signatures are, because it's hidden behind dynamic code. They want to see the actual functions/methods directly in the source code on disk, without executing anything. The What's the alternative? We could keep the current module-level functions, make them statically visible via code generation (which we already need to do for the runner methods), and wrap the statically generated global functions in Problem 2: Import-time selection is also problematic in case we ever want to support alternative I/O backends in the future (e.g. Qt), because it happens too early: at import time we don't know whether someone is going to do I'm still hopeful that we can support Qt etc. without actually supporting multiple I/O backends (see #399 for discussion of alternatives). So maybe this will never come up. OTOH I'll feel very silly if like 5 years from now we discover some new reason why this is super important, but we're trapped by old decisions. If we switch to defining the method wrappers unconditionally, then this problem goes away... if you try to call like, a kqueue-specific method on a platform that normally has kqueue, but that doesn't becuase we're using a weird I/O backend, then it just means raises |
I guess it would also be fine to make the basic function availability be determined by platform, and then on top of that have functions that error out if you try to call them on the wrong backend. The operations that e.g. Qt can support is going to be a subset of all the operations the platform can support. I'm also wondering if we should drop the distinction between |
This issue is about Trio's handful of primitive I/O functions:
wait_{readable,writable}
,wait_socket_{readable,writable}
, and a few more exotic ones likewait_kevent
,wait_overlapped
, etc.Currently, the public API for these is global functions in
trio.hazmat
:I'm wondering if we should change it so that they're methods on a global object you can fetch:
Implementation-wise, this would be a pretty simple refactoring, because currently the
wait_readable
function is implemented like:So in this approach we'd instead have:
and that's basically it. Though we would need to go through and add explicit
@enable_ki_protection
decorators to all the methods, since currently they're inheriting it from the wrapper. And make sure that all the private methods are underscored or something. But it's fundamentally not that big a change.The bigger implication is for the public API:
Currently you can check which primitives are available by doing checks like
hasattr(trio.hazmat, "wait_readable")
, and this is a static fact for the life of the process. For example, you can do it at import time. Now this wouldn't be true; you'd have to do the checks on the I/O manager object, and you couldn't do it until you were inside an async context.And, of course, this is the whole point: it would make it possible for us to delay deciding which I/O manager we were using until runtime. I'm still not excited about the idea of adding a Qt-backed I/O manager (see Using trio with Qt's event loop? #399 for more discussion), but at least it would be structurally possible if we decided to do it at some point in the future.
The text was updated successfully, but these errors were encountered: