Gevent patching policy proposal
This issue is a proposal for a more strict gevent patching policy.
Proposal
This policy try to conciliate both of the following requirements:
- No import can implicitly monkey-patch
- An external library might not be post-patchable
The proposed solution goes this way:
- Instead of importing the external libraries that requires monkey-patching, we tag those libraries with the proper requirements:
from somelib.foo import bar
becomes:
somelib = requires_patching('somelib.foo', socket=True)
Note that bar
is not accessible yet.
- The proper patching is applied at the beginning of the application startup:
def main():
patch(select=True)
# [...]
bar = somelib.foo.bar
In this case, both select
and socket
will get patched. The objects exposed
by somelib
are now available.
- Any detectable misuse of this policy will raise an exception as early as possible so the developer can fix his code.
Issue
The unavoidable side-effect is that you can't use any of the external library objects during module definition. For instance, consider the following code:
from somelib.foo import Bar
class MyBar(Bar):
# [...]
It cannot be directly converted to:
somelib = requires_patching('somelib.foo', socket=True)
class MyBar(somelib.foo.Bar):
# [...]
Because somelib.foo.Bar
is not yet available. There are however a few ways
this code can be refactored to avoid the following issue:
- Use composition instead of inheritance
- Move the class definition to a cached function
@lru_cache
def get_bar_class():
class MyBar(somelib.foo.Bar):
[...]
Implementation
See this snippet for a working implementation.
Edited by Vincent Michel