Skip to content

Commit

Permalink
Switch to more modern async idioms (#176)
Browse files Browse the repository at this point in the history
I converted AiofilesContextManager to an awaitable from a coroutine, and the interface was simplified as a result. In addition to that, open is now a proper async function and types.coroutine is not used anymore.
  • Loading branch information
onlined committed Nov 10, 2023
1 parent 3f7638b commit 213ee8b
Show file tree
Hide file tree
Showing 3 changed files with 12 additions and 57 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ async def test_stuff():
- Import `os.link` conditionally to fix importing on android.
[#175](https://github.com/Tinche/aiofiles/issues/175)
- Remove spurious items from `aiofiles.os.__all__` when running on Windows.
- Switch to more modern async idioms: Remove types.coroutine and make AiofilesContextManager an awaitable instead a coroutine.

#### 23.2.1 (2023-08-09)

Expand Down
62 changes: 9 additions & 53 deletions src/aiofiles/base.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"""Various base classes."""
from types import coroutine
from collections.abc import Coroutine
from collections.abc import Awaitable
from contextlib import AbstractAsyncContextManager
from asyncio import get_running_loop


Expand Down Expand Up @@ -45,66 +45,22 @@ def _file(self, v):
pass # discard writes


class _ContextManager(Coroutine):
class AiofilesContextManager(Awaitable, AbstractAsyncContextManager):
"""An adjusted async context manager for aiofiles."""

__slots__ = ("_coro", "_obj")

def __init__(self, coro):
self._coro = coro
self._obj = None

def send(self, value):
return self._coro.send(value)

def throw(self, typ, val=None, tb=None):
if val is None:
return self._coro.throw(typ)
elif tb is None:
return self._coro.throw(typ, val)
else:
return self._coro.throw(typ, val, tb)

def close(self):
return self._coro.close()

@property
def gi_frame(self):
return self._coro.gi_frame

@property
def gi_running(self):
return self._coro.gi_running

@property
def gi_code(self):
return self._coro.gi_code

def __next__(self):
return self.send(None)

@coroutine
def __iter__(self):
resp = yield from self._coro
return resp

def __await__(self):
resp = yield from self._coro
return resp

async def __anext__(self):
resp = await self._coro
return resp

async def __aenter__(self):
self._obj = await self._coro
if self._obj is None:
self._obj = yield from self._coro.__await__()
return self._obj

async def __aexit__(self, exc_type, exc, tb):
self._obj.close()
self._obj = None


class AiofilesContextManager(_ContextManager):
"""An adjusted async context manager for aiofiles."""
async def __aenter__(self):
return await self

async def __aexit__(self, exc_type, exc_val, exc_tb):
await get_running_loop().run_in_executor(
Expand Down
6 changes: 2 additions & 4 deletions src/aiofiles/threadpool/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
FileIO,
TextIOBase,
)
from types import coroutine

from ..base import AiofilesContextManager
from .binary import (
Expand Down Expand Up @@ -63,8 +62,7 @@ def open(
)


@coroutine
def _open(
async def _open(
file,
mode="r",
buffering=-1,
Expand All @@ -91,7 +89,7 @@ def _open(
closefd=closefd,
opener=opener,
)
f = yield from loop.run_in_executor(executor, cb)
f = await loop.run_in_executor(executor, cb)

return wrap(f, loop=loop, executor=executor)

Expand Down

0 comments on commit 213ee8b

Please sign in to comment.