From 43127830cccc4219205050ec2b2752c2b365e4c2 Mon Sep 17 00:00:00 2001 From: Stanley Kudrow Date: Fri, 20 Jun 2025 10:45:35 +0300 Subject: [PATCH 01/26] rebase after the PR #219 --- CHANGELOG.md | 2 ++ src/aiofiles/base.py | 37 +++++++++++++++++------- src/aiofiles/os.py | 65 +++++++++++++++++++++--------------------- src/aiofiles/ospath.py | 26 ++++++++--------- 4 files changed, 74 insertions(+), 56 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b327ffb..88278e1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## 25.1.0 (UNRELEASED) +- Use `asyncio.to_thread` in the `wrap` asynchroniser + [#213](https://github.com/Tinche/aiofiles/pull/213) - Switch to [uv](https://docs.astral.sh/uv/) + add Python v3.14 support. ([#219](https://github.com/Tinche/aiofiles/pull/219)) - Add `ruff` formatter and linter. diff --git a/src/aiofiles/base.py b/src/aiofiles/base.py index ef1f81d..b3c1ae0 100644 --- a/src/aiofiles/base.py +++ b/src/aiofiles/base.py @@ -1,18 +1,35 @@ -from asyncio import get_running_loop -from collections.abc import Awaitable +from asyncio import get_running_loop, to_thread +from collections.abc import Awaitable, Callable, Coroutine from contextlib import AbstractAsyncContextManager -from functools import partial, wraps +from functools import wraps +from warnings import warn -def wrap(func): +def to_coro(func: Callable) -> Callable: + """Converts the routine `func` into a coroutine. + + The returned coroutine function runs the decorated function + in a separate thread. + + Args: + func: A routine (regular function). + + Returns: + A coroutine function. + """ + @wraps(func) - async def run(*args, loop=None, executor=None, **kwargs): - if loop is None: - loop = get_running_loop() - pfunc = partial(func, *args, **kwargs) - return await loop.run_in_executor(executor, pfunc) + async def _wrapper(*args, **kwargs) -> Coroutine: + return await to_thread(func, *args, **kwargs) + + return _wrapper + - return run +def wrap(func: Callable) -> Callable: + warn( + "scheduled to removal, consider using to_coro", DeprecationWarning, stacklevel=1 + ) + return to_coro(func) class AsyncBase: diff --git a/src/aiofiles/os.py b/src/aiofiles/os.py index 153d65d..a998d0b 100644 --- a/src/aiofiles/os.py +++ b/src/aiofiles/os.py @@ -3,59 +3,58 @@ import os from . import ospath as path -from .base import wrap +from .base import to_coro __all__ = [ - "path", - "stat", + "access", + "getcwd", + "listdir", + "makedirs", + "mkdir", + "readlink", + "remove", + "removedirs", "rename", "renames", "replace", - "remove", - "unlink", - "mkdir", - "makedirs", "rmdir", - "removedirs", - "symlink", - "readlink", - "listdir", + "path", "scandir", - "access", - "wrap", - "getcwd", + "stat", + "symlink", + "unlink", ] -access = wrap(os.access) +access = to_coro(os.access) -getcwd = wrap(os.getcwd) +getcwd = to_coro(os.getcwd) -listdir = wrap(os.listdir) +listdir = to_coro(os.listdir) -makedirs = wrap(os.makedirs) -mkdir = wrap(os.mkdir) +makedirs = to_coro(os.makedirs) +mkdir = to_coro(os.mkdir) -readlink = wrap(os.readlink) -remove = wrap(os.remove) -removedirs = wrap(os.removedirs) -rename = wrap(os.rename) -renames = wrap(os.renames) -replace = wrap(os.replace) -rmdir = wrap(os.rmdir) +readlink = to_coro(os.readlink) +remove = to_coro(os.remove) +removedirs = to_coro(os.removedirs) +rename = to_coro(os.rename) +renames = to_coro(os.renames) +replace = to_coro(os.replace) +rmdir = to_coro(os.rmdir) -scandir = wrap(os.scandir) -stat = wrap(os.stat) -symlink = wrap(os.symlink) +scandir = to_coro(os.scandir) +stat = to_coro(os.stat) +symlink = to_coro(os.symlink) -unlink = wrap(os.unlink) +unlink = to_coro(os.unlink) if hasattr(os, "link"): __all__ += ["link"] - link = wrap(os.link) + link = to_coro(os.link) if hasattr(os, "sendfile"): __all__ += ["sendfile"] - sendfile = wrap(os.sendfile) + sendfile = to_coro(os.sendfile) if hasattr(os, "statvfs"): __all__ += ["statvfs"] - statvfs = wrap(os.statvfs) + statvfs = to_coro(os.statvfs) diff --git a/src/aiofiles/ospath.py b/src/aiofiles/ospath.py index f47f150..b879c79 100644 --- a/src/aiofiles/ospath.py +++ b/src/aiofiles/ospath.py @@ -2,7 +2,7 @@ from os import path -from .base import wrap +from .base import to_coro __all__ = [ "abspath", @@ -19,19 +19,19 @@ "sameopenfile", ] -abspath = wrap(path.abspath) +abspath = to_coro(path.abspath) -getatime = wrap(path.getatime) -getctime = wrap(path.getctime) -getmtime = wrap(path.getmtime) -getsize = wrap(path.getsize) +getatime = to_coro(path.getatime) +getctime = to_coro(path.getctime) +getmtime = to_coro(path.getmtime) +getsize = to_coro(path.getsize) -exists = wrap(path.exists) +exists = to_coro(path.exists) -isdir = wrap(path.isdir) -isfile = wrap(path.isfile) -islink = wrap(path.islink) -ismount = wrap(path.ismount) +isdir = to_coro(path.isdir) +isfile = to_coro(path.isfile) +islink = to_coro(path.islink) +ismount = to_coro(path.ismount) -samefile = wrap(path.samefile) -sameopenfile = wrap(path.sameopenfile) +samefile = to_coro(path.samefile) +sameopenfile = to_coro(path.sameopenfile) From 74350869c1fa07ec491654ea24bcf41de5e861bf Mon Sep 17 00:00:00 2001 From: Stanley Kudrow Date: Sat, 21 Jun 2025 14:17:13 +0300 Subject: [PATCH 02/26] update the #213 record in the CHANGELOG --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 88278e1..8989c18 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ ## 25.1.0 (UNRELEASED) -- Use `asyncio.to_thread` in the `wrap` asynchroniser +- Use `asyncio.to_thread` in the `to_coro` decorator that deprecates the `wrap` decorator [#213](https://github.com/Tinche/aiofiles/pull/213) - Switch to [uv](https://docs.astral.sh/uv/) + add Python v3.14 support. ([#219](https://github.com/Tinche/aiofiles/pull/219)) From deada0d4b85214c9747da1a02a62fd1dbc126086 Mon Sep 17 00:00:00 2001 From: Stanley Kudrow Date: Sat, 21 Jun 2025 14:27:16 +0300 Subject: [PATCH 03/26] remove the 'run_prefix' from the Justfile --- Justfile | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Justfile b/Justfile index ccae1b8..5039573 100644 --- a/Justfile +++ b/Justfile @@ -1,19 +1,19 @@ +src_dir := "src" tests_dir := "tests" -code_dirs := "src" + " " + tests_dir -run_prefix := if env_var_or_default("VIRTUAL_ENV", "") == "" { "uv run " } else { "" } +code_dirs := src_dir + " " + tests_dir check: - {{ run_prefix }}ruff format --check {{ code_dirs }} - {{ run_prefix }}ruff check {{ code_dirs }} + ruff format --check {{ code_dirs }} + ruff check {{ code_dirs }} coverage: - {{ run_prefix }}coverage run -m pytest {{ tests_dir }} + coverage run -m pytest {{ tests_dir }} format: - {{ run_prefix }}ruff format {{ code_dirs }} + ruff format {{ code_dirs }} lint: format - {{ run_prefix }}ruff check --fix {{ code_dirs }} + ruff check --fix {{ code_dirs }} test: - {{ run_prefix }}pytest -x --ff {{ tests_dir }} \ No newline at end of file + pytest -x --ff {{ tests_dir }} \ No newline at end of file From a99011412ea489756ec7c14d4f70052ca52825d8 Mon Sep 17 00:00:00 2001 From: Stanley Kudrow Date: Sat, 21 Jun 2025 14:29:55 +0300 Subject: [PATCH 04/26] add pytest addopts in the pyproject.toml --- pyproject.toml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index 3efac5f..67dc815 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -68,6 +68,10 @@ source = [ [tool.pytest.ini_options] minversion = "8.3" +addopts = [ + "-x", + "--ff", +] asyncio_mode = "auto" asyncio_default_fixture_loop_scope = "function" From 59fc35a8b16153e85ea06fc46edb5f0a0e9ad435 Mon Sep 17 00:00:00 2001 From: Stanley Kudrow Date: Sat, 21 Jun 2025 14:30:55 +0300 Subject: [PATCH 05/26] remove opts from the Justfile test rule --- Justfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Justfile b/Justfile index 5039573..0fe290e 100644 --- a/Justfile +++ b/Justfile @@ -16,4 +16,4 @@ lint: format ruff check --fix {{ code_dirs }} test: - pytest -x --ff {{ tests_dir }} \ No newline at end of file + pytest {{ tests_dir }} From a1658b31c9f0419db4ecfd8cd297377c40e1e20c Mon Sep 17 00:00:00 2001 From: Stanley Kudrow Date: Sat, 21 Jun 2025 20:30:11 +0300 Subject: [PATCH 06/26] update the #213 record --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8989c18..703ee07 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ ## 25.1.0 (UNRELEASED) -- Use `asyncio.to_thread` in the `to_coro` decorator that deprecates the `wrap` decorator +- Add the `to_coro` decorator with the `asyncio.to_thread` under the hood in favour of the deprecated `wrap` decorator [#213](https://github.com/Tinche/aiofiles/pull/213) - Switch to [uv](https://docs.astral.sh/uv/) + add Python v3.14 support. ([#219](https://github.com/Tinche/aiofiles/pull/219)) From f1e84c7d7077c0e2cd60a8ba7e4842f3b5b6c395 Mon Sep 17 00:00:00 2001 From: Stanley Kudrow Date: Sat, 21 Jun 2025 20:32:52 +0300 Subject: [PATCH 07/26] update the #213 record - ok now --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 703ee07..db8d539 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ ## 25.1.0 (UNRELEASED) -- Add the `to_coro` decorator with the `asyncio.to_thread` under the hood in favour of the deprecated `wrap` decorator +- Add the `to_coro` decorator (with the `asyncio.to_thread` under the hood) in favour of the deprecated `wrap` decorator. [#213](https://github.com/Tinche/aiofiles/pull/213) - Switch to [uv](https://docs.astral.sh/uv/) + add Python v3.14 support. ([#219](https://github.com/Tinche/aiofiles/pull/219)) From 540d8800cc0e31dc4de2d8aaf3a47e8696b615f0 Mon Sep 17 00:00:00 2001 From: Stanley Kudrow Date: Sun, 10 Aug 2025 08:21:27 +0300 Subject: [PATCH 08/26] add .python-version with Python 3.9(.21) --- .python-version | 1 + 1 file changed, 1 insertion(+) create mode 100644 .python-version diff --git a/.python-version b/.python-version new file mode 100644 index 0000000..bd28b9c --- /dev/null +++ b/.python-version @@ -0,0 +1 @@ +3.9 From ca6d9952c67b78cdcb2ceefdee438be6e9fd34e9 Mon Sep 17 00:00:00 2001 From: Stanley Kudrow Date: Sun, 10 Aug 2025 08:21:54 +0300 Subject: [PATCH 09/26] update Justfile rules --- Justfile | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/Justfile b/Justfile index 0fe290e..5bd7221 100644 --- a/Justfile +++ b/Justfile @@ -2,18 +2,25 @@ src_dir := "src" tests_dir := "tests" code_dirs := src_dir + " " + tests_dir +build: + uv build + +sync: + uv sync --group lint --group test --group tox + check: ruff format --check {{ code_dirs }} ruff check {{ code_dirs }} + mypy {{ code_dirs }} coverage: coverage run -m pytest {{ tests_dir }} -format: - ruff format {{ code_dirs }} +format *files=".": + ruff format {{ files }} lint: format ruff check --fix {{ code_dirs }} -test: - pytest {{ tests_dir }} +test *args: + pytest {{ args }} From 328624916c04dfa95736ffb0df1c0e95fedebc37 Mon Sep 17 00:00:00 2001 From: Stanley Kudrow Date: Sun, 10 Aug 2025 08:22:11 +0300 Subject: [PATCH 10/26] specify test dir for pytest --- pyproject.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/pyproject.toml b/pyproject.toml index 67dc815..3d136ad 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -72,6 +72,7 @@ addopts = [ "-x", "--ff", ] +testpaths = ["tests"] asyncio_mode = "auto" asyncio_default_fixture_loop_scope = "function" From 4b96a9bf01a1265aa8bf29693af9242e284dbf34 Mon Sep 17 00:00:00 2001 From: Stanley Kudrow Date: Sun, 10 Aug 2025 08:22:43 +0300 Subject: [PATCH 11/26] update the #213 record --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index db8d539..00fa688 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ ## 25.1.0 (UNRELEASED) -- Add the `to_coro` decorator (with the `asyncio.to_thread` under the hood) in favour of the deprecated `wrap` decorator. +- Implement the `wrap` decorator with the `asyncio.to_thread` under the hood. [#213](https://github.com/Tinche/aiofiles/pull/213) - Switch to [uv](https://docs.astral.sh/uv/) + add Python v3.14 support. ([#219](https://github.com/Tinche/aiofiles/pull/219)) From a97b4628d39d9e3bfdd6cf1c3c1d1684b2514a09 Mon Sep 17 00:00:00 2001 From: Stanley Kudrow Date: Sun, 10 Aug 2025 08:23:34 +0300 Subject: [PATCH 12/26] implement wrap with asyncio.to_thread --- src/aiofiles/base.py | 10 +--------- src/aiofiles/os.py | 40 ++++++++++++++++++++-------------------- src/aiofiles/ospath.py | 26 +++++++++++++------------- 3 files changed, 34 insertions(+), 42 deletions(-) diff --git a/src/aiofiles/base.py b/src/aiofiles/base.py index b3c1ae0..37cbfcf 100644 --- a/src/aiofiles/base.py +++ b/src/aiofiles/base.py @@ -2,10 +2,9 @@ from collections.abc import Awaitable, Callable, Coroutine from contextlib import AbstractAsyncContextManager from functools import wraps -from warnings import warn -def to_coro(func: Callable) -> Callable: +def wrap(func: Callable) -> Callable: """Converts the routine `func` into a coroutine. The returned coroutine function runs the decorated function @@ -25,13 +24,6 @@ async def _wrapper(*args, **kwargs) -> Coroutine: return _wrapper -def wrap(func: Callable) -> Callable: - warn( - "scheduled to removal, consider using to_coro", DeprecationWarning, stacklevel=1 - ) - return to_coro(func) - - class AsyncBase: def __init__(self, file, loop, executor): self._file = file diff --git a/src/aiofiles/os.py b/src/aiofiles/os.py index a998d0b..6b95b91 100644 --- a/src/aiofiles/os.py +++ b/src/aiofiles/os.py @@ -3,7 +3,7 @@ import os from . import ospath as path -from .base import to_coro +from .base import wrap __all__ = [ "access", @@ -25,36 +25,36 @@ "unlink", ] -access = to_coro(os.access) +access = wrap(os.access) -getcwd = to_coro(os.getcwd) +getcwd = wrap(os.getcwd) -listdir = to_coro(os.listdir) +listdir = wrap(os.listdir) -makedirs = to_coro(os.makedirs) -mkdir = to_coro(os.mkdir) +makedirs = wrap(os.makedirs) +mkdir = wrap(os.mkdir) -readlink = to_coro(os.readlink) -remove = to_coro(os.remove) -removedirs = to_coro(os.removedirs) -rename = to_coro(os.rename) -renames = to_coro(os.renames) -replace = to_coro(os.replace) -rmdir = to_coro(os.rmdir) +readlink = wrap(os.readlink) +remove = wrap(os.remove) +removedirs = wrap(os.removedirs) +rename = wrap(os.rename) +renames = wrap(os.renames) +replace = wrap(os.replace) +rmdir = wrap(os.rmdir) -scandir = to_coro(os.scandir) -stat = to_coro(os.stat) -symlink = to_coro(os.symlink) +scandir = wrap(os.scandir) +stat = wrap(os.stat) +symlink = wrap(os.symlink) -unlink = to_coro(os.unlink) +unlink = wrap(os.unlink) if hasattr(os, "link"): __all__ += ["link"] - link = to_coro(os.link) + link = wrap(os.link) if hasattr(os, "sendfile"): __all__ += ["sendfile"] - sendfile = to_coro(os.sendfile) + sendfile = wrap(os.sendfile) if hasattr(os, "statvfs"): __all__ += ["statvfs"] - statvfs = to_coro(os.statvfs) + statvfs = wrap(os.statvfs) diff --git a/src/aiofiles/ospath.py b/src/aiofiles/ospath.py index b879c79..f47f150 100644 --- a/src/aiofiles/ospath.py +++ b/src/aiofiles/ospath.py @@ -2,7 +2,7 @@ from os import path -from .base import to_coro +from .base import wrap __all__ = [ "abspath", @@ -19,19 +19,19 @@ "sameopenfile", ] -abspath = to_coro(path.abspath) +abspath = wrap(path.abspath) -getatime = to_coro(path.getatime) -getctime = to_coro(path.getctime) -getmtime = to_coro(path.getmtime) -getsize = to_coro(path.getsize) +getatime = wrap(path.getatime) +getctime = wrap(path.getctime) +getmtime = wrap(path.getmtime) +getsize = wrap(path.getsize) -exists = to_coro(path.exists) +exists = wrap(path.exists) -isdir = to_coro(path.isdir) -isfile = to_coro(path.isfile) -islink = to_coro(path.islink) -ismount = to_coro(path.ismount) +isdir = wrap(path.isdir) +isfile = wrap(path.isfile) +islink = wrap(path.islink) +ismount = wrap(path.ismount) -samefile = to_coro(path.samefile) -sameopenfile = to_coro(path.sameopenfile) +samefile = wrap(path.samefile) +sameopenfile = wrap(path.sameopenfile) From d9294a1b68c89e3fcc8ca7f79d36ce64a532633d Mon Sep 17 00:00:00 2001 From: Stanley Kudrow Date: Sun, 10 Aug 2025 08:23:43 +0300 Subject: [PATCH 13/26] mypy tests --- tests/threadpool/test_open.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/threadpool/test_open.py b/tests/threadpool/test_open.py index ec1ef63..5b2de25 100644 --- a/tests/threadpool/test_open.py +++ b/tests/threadpool/test_open.py @@ -46,7 +46,7 @@ async def test_file_async_context_aexit(): async def test_filetask_async_context_aexit(): async def _process_test_file(file_ctx, sleep_time: float = 1.0): - nonlocal file_ref + nonlocal file_ref # type: ignore async with file_ctx as fp: file_ref = file_ctx._obj await asyncio.sleep(sleep_time) From 0c1110e75fb416fcbe65e9f1d53cc59d93244803 Mon Sep 17 00:00:00 2001 From: Stanley Kudrow Date: Sun, 10 Aug 2025 08:29:17 +0300 Subject: [PATCH 14/26] mypy only the source code --- Justfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Justfile b/Justfile index 5bd7221..31b6385 100644 --- a/Justfile +++ b/Justfile @@ -11,7 +11,7 @@ sync: check: ruff format --check {{ code_dirs }} ruff check {{ code_dirs }} - mypy {{ code_dirs }} + mypy {{ code_dir }} # lint only the source code coverage: coverage run -m pytest {{ tests_dir }} From d42a4539bb1201e03c56309f80ade40403f56172 Mon Sep 17 00:00:00 2001 From: Stanley Kudrow Date: Sun, 10 Aug 2025 08:30:16 +0300 Subject: [PATCH 15/26] specify src_dir for mypy --- Justfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Justfile b/Justfile index 31b6385..4380843 100644 --- a/Justfile +++ b/Justfile @@ -11,7 +11,7 @@ sync: check: ruff format --check {{ code_dirs }} ruff check {{ code_dirs }} - mypy {{ code_dir }} # lint only the source code + mypy {{ src_dir }} # lint only the source code coverage: coverage run -m pytest {{ tests_dir }} From e17cf031c93425ab5b4abbaed39d56385fa56ab7 Mon Sep 17 00:00:00 2001 From: Stanley Kudrow Date: Sun, 10 Aug 2025 08:35:27 +0300 Subject: [PATCH 16/26] combine format and lint rules under the lint recipe --- Justfile | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Justfile b/Justfile index 4380843..e131d2c 100644 --- a/Justfile +++ b/Justfile @@ -16,11 +16,9 @@ check: coverage: coverage run -m pytest {{ tests_dir }} -format *files=".": +lint *files=".": ruff format {{ files }} - -lint: format - ruff check --fix {{ code_dirs }} + ruff check --fix {{ files }} test *args: pytest {{ args }} From d0f5e879af5c4c3c49d88e307ae4ae8747fa40a0 Mon Sep 17 00:00:00 2001 From: Stanley Kudrow Date: Sun, 10 Aug 2025 08:42:28 +0300 Subject: [PATCH 17/26] remove .python-version --- .python-version | 1 - 1 file changed, 1 deletion(-) delete mode 100644 .python-version diff --git a/.python-version b/.python-version deleted file mode 100644 index bd28b9c..0000000 --- a/.python-version +++ /dev/null @@ -1 +0,0 @@ -3.9 From a2f95189be6e8572627ab701584f072832a40493 Mon Sep 17 00:00:00 2001 From: Stanley Kudrow Date: Sun, 10 Aug 2025 09:12:22 +0300 Subject: [PATCH 18/26] add just default rule and recipe doc comments --- Justfile | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Justfile b/Justfile index e131d2c..9f80398 100644 --- a/Justfile +++ b/Justfile @@ -2,23 +2,33 @@ src_dir := "src" tests_dir := "tests" code_dirs := src_dir + " " + tests_dir +# list available rules +default: + just --list + +# build the project build: uv build +# install dependencies sync: uv sync --group lint --group test --group tox +# check the code check: ruff format --check {{ code_dirs }} ruff check {{ code_dirs }} mypy {{ src_dir }} # lint only the source code +# run coverage coverage: coverage run -m pytest {{ tests_dir }} +# lint the code (including formatting) lint *files=".": ruff format {{ files }} ruff check --fix {{ files }} +# run the tests test *args: pytest {{ args }} From 4c7de0eec3e78f74ce4fc84063ab304526b6dd8f Mon Sep 17 00:00:00 2001 From: Stanley Kudrow Date: Tue, 12 Aug 2025 23:25:04 +0300 Subject: [PATCH 19/26] prefixate commands with (uv) {{ run }} if no VIRTUAL_ENV envvar is set --- Justfile | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/Justfile b/Justfile index 9f80398..d83508f 100644 --- a/Justfile +++ b/Justfile @@ -2,6 +2,9 @@ src_dir := "src" tests_dir := "tests" code_dirs := src_dir + " " + tests_dir +# https://just.systems/man/en/functions.html#environment-variables +run := if env("VIRTUAL_ENV", "") == "" { "uv run " } else { "" } + # list available rules default: just --list @@ -16,19 +19,19 @@ sync: # check the code check: - ruff format --check {{ code_dirs }} - ruff check {{ code_dirs }} - mypy {{ src_dir }} # lint only the source code + {{ run }} ruff format --check {{ code_dirs }} + {{ run }} ruff check {{ code_dirs }} + {{ run }} mypy {{ src_dir }} # lint only the source code # run coverage coverage: - coverage run -m pytest {{ tests_dir }} + {{ run }} coverage run -m pytest {{ tests_dir }} # lint the code (including formatting) lint *files=".": - ruff format {{ files }} - ruff check --fix {{ files }} + {{ run }} ruff format {{ files }} + {{ run }} ruff check --fix {{ files }} # run the tests test *args: - pytest {{ args }} + {{ run }} pytest {{ args }} From 1879a4682abc9f9e69dfb5f286bb53355dd05dd6 Mon Sep 17 00:00:00 2001 From: Stanley Kudrow Date: Sat, 30 Aug 2025 12:28:28 +0300 Subject: [PATCH 20/26] add RUF specific-rules --- pyproject.toml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 3d136ad..6bd05ef 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -117,6 +117,7 @@ select = [ "PTH", # flake8-use-pathlib (PTH) "PYI", # flake8-pyi (PYI) "Q", # flake8-quotes (Q) + "RUF", # Ruff-specific rules (RUF) "RET", # flake8-return (RET) "RSE", # flake8-raise (RSE) "S", # flake8-bandit (S) @@ -136,7 +137,8 @@ ignore = [ ] fixable = [ "COM", - "I" + "I", + "RUF022", # https://docs.astral.sh/ruff/rules/unsorted-dunder-all/ ] [tool.ruff.lint.per-file-ignores] From b2fffdcc32d38bd43f42acc659733984d129fb86 Mon Sep 17 00:00:00 2001 From: Stanley Kudrow Date: Sat, 30 Aug 2025 12:29:12 +0300 Subject: [PATCH 21/26] sort imports in __all__ with RUF022 --- src/aiofiles/__init__.py | 8 ++++---- src/aiofiles/os.py | 2 +- src/aiofiles/ospath.py | 2 +- src/aiofiles/tempfile/__init__.py | 2 +- src/aiofiles/threadpool/__init__.py | 6 +++--- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/aiofiles/__init__.py b/src/aiofiles/__init__.py index 5f62158..e62baa4 100644 --- a/src/aiofiles/__init__.py +++ b/src/aiofiles/__init__.py @@ -13,11 +13,11 @@ __all__ = [ "open", - "tempfile", - "stdin", - "stdout", "stderr", + "stderr_bytes", + "stdin", "stdin_bytes", + "stdout", "stdout_bytes", - "stderr_bytes", + "tempfile", ] diff --git a/src/aiofiles/os.py b/src/aiofiles/os.py index 6b95b91..6c35415 100644 --- a/src/aiofiles/os.py +++ b/src/aiofiles/os.py @@ -11,6 +11,7 @@ "listdir", "makedirs", "mkdir", + "path", "readlink", "remove", "removedirs", @@ -18,7 +19,6 @@ "renames", "replace", "rmdir", - "path", "scandir", "stat", "symlink", diff --git a/src/aiofiles/ospath.py b/src/aiofiles/ospath.py index f47f150..c4beb64 100644 --- a/src/aiofiles/ospath.py +++ b/src/aiofiles/ospath.py @@ -6,11 +6,11 @@ __all__ = [ "abspath", + "exists", "getatime", "getctime", "getmtime", "getsize", - "exists", "isdir", "isfile", "islink", diff --git a/src/aiofiles/tempfile/__init__.py b/src/aiofiles/tempfile/__init__.py index b1c32c8..dd72d5b 100644 --- a/src/aiofiles/tempfile/__init__.py +++ b/src/aiofiles/tempfile/__init__.py @@ -15,9 +15,9 @@ __all__ = [ "NamedTemporaryFile", - "TemporaryFile", "SpooledTemporaryFile", "TemporaryDirectory", + "TemporaryFile", ] diff --git a/src/aiofiles/threadpool/__init__.py b/src/aiofiles/threadpool/__init__.py index 8054034..2541ea6 100644 --- a/src/aiofiles/threadpool/__init__.py +++ b/src/aiofiles/threadpool/__init__.py @@ -25,12 +25,12 @@ __all__ = ( "open", - "stdin", - "stdout", "stderr", + "stderr_bytes", + "stdin", "stdin_bytes", + "stdout", "stdout_bytes", - "stderr_bytes", ) From 21398178da95bcdd30da084a519140d50e88895e Mon Sep 17 00:00:00 2001 From: Stanley Kudrow Date: Sat, 30 Aug 2025 12:35:43 +0300 Subject: [PATCH 22/26] glue the 'uv run' prefix to the start of commands --- Justfile | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Justfile b/Justfile index d83508f..d0aae5e 100644 --- a/Justfile +++ b/Justfile @@ -19,19 +19,19 @@ sync: # check the code check: - {{ run }} ruff format --check {{ code_dirs }} - {{ run }} ruff check {{ code_dirs }} - {{ run }} mypy {{ src_dir }} # lint only the source code + {{ run }}ruff format --check {{ code_dirs }} + {{ run }}ruff check {{ code_dirs }} + {{ run }}mypy {{ src_dir }} # lint only the source code # run coverage coverage: - {{ run }} coverage run -m pytest {{ tests_dir }} + {{ run }}coverage run -m pytest {{ tests_dir }} # lint the code (including formatting) lint *files=".": - {{ run }} ruff format {{ files }} - {{ run }} ruff check --fix {{ files }} + {{ run }}ruff format {{ files }} + {{ run }}ruff check --fix {{ files }} # run the tests test *args: - {{ run }} pytest {{ args }} + {{ run }}pytest {{ args }} From 5e223d850c7842dbc8f65b9b8e4f59a59b95479a Mon Sep 17 00:00:00 2001 From: Stanley Kudrow Date: Sat, 30 Aug 2025 12:57:05 +0300 Subject: [PATCH 23/26] rename lint to check for tox and CI --- .github/workflows/main.yml | 4 ++-- tox.ini | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 8022123..9773586 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -28,9 +28,9 @@ jobs: V: ${{ matrix.python-version }} run: "uv run --group tox tox -e py$(echo $V | tr -d . | sed 's/^py//')" - - name: "Lint" + - name: "Check code" if: matrix.python-version == '3.13' && runner.os == 'Linux' - run: "uv run --group tox tox -e lint" + run: "uv run --group tox tox -e check" - name: "Upload coverage data" uses: "actions/upload-artifact@v4" diff --git a/tox.ini b/tox.ini index 9257f0f..4c9e595 100644 --- a/tox.ini +++ b/tox.ini @@ -2,17 +2,17 @@ requires = tox>=4.26 min_version = 4.26 -env_list = py39, py31{0,1,2,3,4}, pypy39, lint +env_list = py39, py31{0,1,2,3,4}, pypy39, check no_package = false -[testenv:lint] +[testenv:check] skip_install = true basepython = python3.13 allowlist_externals = just commands = just check dependency_groups = - lint + check [testenv] runner = uv-venv-lock-runner From 7d72e9e5a6ec2b5230b5c41a38f747b6f3f79c2f Mon Sep 17 00:00:00 2001 From: Stanley Kudrow Date: Sat, 30 Aug 2025 12:59:36 +0300 Subject: [PATCH 24/26] fix dependency-groups -> back to 'lint' --- tox.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index 4c9e595..5768ba5 100644 --- a/tox.ini +++ b/tox.ini @@ -12,7 +12,7 @@ allowlist_externals = just commands = just check dependency_groups = - check + lint [testenv] runner = uv-venv-lock-runner From 31aead870fd3f308f521f47984a5390eec18c255 Mon Sep 17 00:00:00 2001 From: Stanley Kudrow Date: Sun, 21 Sep 2025 13:23:45 +0300 Subject: [PATCH 25/26] update and sort aiofiles utils in the README.md --- README.md | 53 ++++++++++++++++++++++++++++------------------------- 1 file changed, 28 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index 7b402bc..5dfa631 100644 --- a/README.md +++ b/README.md @@ -68,8 +68,8 @@ and delegate to an executor: - `flush` - `isatty` - `read` -- `readall` - `read1` +- `readall` - `readinto` - `readline` - `readlines` @@ -91,36 +91,39 @@ In case of failure, one of the usual exceptions will be raised. The `aiofiles.os` module contains executor-enabled coroutine versions of several useful `os` functions that deal with files: -- `stat` -- `statvfs` +- `access` +- `getcwd` +- `link` +- `listdir` +- `makedirs` +- `mkdir` +- `path`: + - `path.abspath` + - `path.exists` + - `path.getatime` + - `path.getctime` + - `path.getmtime` + - `path.getsize` + - `path.isdir` + - `path.isfile` + - `path.islink` + - `path.ismount` + - `path.samefile` + - `path.sameopenfile` +- `readlink` +- `remove` +- `removedirs` - `sendfile` - `rename` - `renames` - `replace` -- `remove` -- `unlink` -- `mkdir` -- `makedirs` - `rmdir` -- `removedirs` -- `link` -- `symlink` -- `readlink` -- `listdir` - `scandir` -- `access` -- `getcwd` -- `path.abspath` -- `path.exists` -- `path.isfile` -- `path.isdir` -- `path.islink` -- `path.ismount` -- `path.getsize` -- `path.getatime` -- `path.getctime` -- `path.samefile` -- `path.sameopenfile` +- `sendfile` +- `stat` +- `statvfs` +- `symlink` +- `unlink` ### Tempfile From 6517a103f27741a3feb8f1ce5b1a892dabe32247 Mon Sep 17 00:00:00 2001 From: Stanley Kudrow Date: Sun, 21 Sep 2025 13:24:15 +0300 Subject: [PATCH 26/26] modify the #213 changelog record --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 00fa688..97bd7e6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ ## 25.1.0 (UNRELEASED) -- Implement the `wrap` decorator with the `asyncio.to_thread` under the hood. +- Call the `asyncio.to_thread` int the `wrap` decorator. [#213](https://github.com/Tinche/aiofiles/pull/213) - Switch to [uv](https://docs.astral.sh/uv/) + add Python v3.14 support. ([#219](https://github.com/Tinche/aiofiles/pull/219))