From 77f57ba977abcd61332f2ea86cf294871cc69633 Mon Sep 17 00:00:00 2001 From: retoor Date: Wed, 4 Dec 2024 20:45:33 +0000 Subject: [PATCH] Add sayncio_patch.py.md --- sayncio_patch.py.md | 66 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 sayncio_patch.py.md diff --git a/sayncio_patch.py.md b/sayncio_patch.py.md new file mode 100644 index 0000000..dcdbd50 --- /dev/null +++ b/sayncio_patch.py.md @@ -0,0 +1,66 @@ +# AsyncPatch + +# A mixin written by me to use to enable async on all your non async classes! It's not only a patch to use it but actually really executes the code in the event loop! + +## How to use +```python + +# (C) retoor 2024-12-01 + +import os +import AsyncioPatch from asyncio_patch.py + +# Non async traditional class. +class Reader: + + def readline(self): + return os.stdin.readline() + +# Extend the class with the mixin. +class AsyncReader(Reader, AsyncioPatch): + pass + +# Use it for blocking code. +async def main(): + reader = AsyncReader() + + # method 1 + print(await reader.areadline()) + + # method 2 + print(await reader.readline_async()) + +asyncio.run(main()) +``` + +## Source code +```python +import asyncio + +class AsyncioPatch: + def __getattr__(self, name): + if name.endswith("_async"): + name = name.split("_async")[0] + elif name.startswith("a"): + name = name[1:] + else: + return self.__dict__.get(name, None) + return self.patch_async(getattr(self, name)) + + + def patch_async(self, method, *args, **kwargs): + async def patched_async(*args, **kwargs): + loop = asyncio.get_running_loop() + import functools + patched_call = functools.partial(method, *args, **kwargs) + return await loop.run_in_executor(None, patched_call) + return patched_async + + async def __aenter__(self): + fn = self.patch_async(self.__enter__) + return await fn() + + async def __aexit__(self, *args, **kwargs): + fn = self.patch_async(self.__exit__,*args, **kwargs) + return await fn() +``` \ No newline at end of file