From 20e8e8aa61e1fcf06f9ba8d672270eb99d4fd848 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tin=20Tvrtkovi=C4=87?= Date: Mon, 24 Jun 2024 12:26:48 +0200 Subject: [PATCH] Support 3.13 (#184) * Support 3.13 * Drop 3.7 * Modernize pytest-asyncio * Bump pytest --- .github/workflows/main.yml | 4 +- README.md | 3 + pdm.lock | 117 +++++---------------------- pyproject.toml | 33 ++++---- tests/test_os.py | 38 --------- tests/test_simple.py | 7 +- tests/test_stdio.py | 2 - tests/test_tempfile.py | 7 -- tests/threadpool/test_binary.py | 16 ---- tests/threadpool/test_concurrency.py | 2 - tests/threadpool/test_open.py | 1 - tests/threadpool/test_text.py | 14 ---- tox.ini | 10 +-- 13 files changed, 48 insertions(+), 206 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 06070d3..f788f81 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -16,7 +16,7 @@ jobs: matrix: os: [ubuntu-latest, windows-latest] python-version: - ["3.7", "3.8", "3.9", "3.10", "3.11", "3.12", "pypy-3.9"] + ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13", "pypy-3.9"] steps: - uses: "actions/checkout@v3" @@ -103,7 +103,7 @@ jobs: - uses: "actions/checkout@v3" - uses: "actions/setup-python@v4" with: - python-version: "3.x" + python-version: "3.12" - name: "Install PDM and twine" run: "python -m pip install pdm twine check-wheel-contents" diff --git a/README.md b/README.md index cad133d..568e26d 100644 --- a/README.md +++ b/README.md @@ -187,6 +187,9 @@ async def test_stuff(): - Switch to more modern async idioms: Remove types.coroutine and make AiofilesContextManager an awaitable instead a coroutine. - Add `aiofiles.os.path.abspath` and `aiofiles.os.getcwd`. [#174](https://github.com/Tinche/aiofiles/issues/181) +- _aiofiles_ is now tested on Python 3.13 too. + [#184](https://github.com/Tinche/aiofiles/pull/184) +- Dropped Python 3.7 support. If you require it, use version 23.2.1. #### 23.2.1 (2023-08-09) diff --git a/pdm.lock b/pdm.lock index 0b946e8..d4857d8 100644 --- a/pdm.lock +++ b/pdm.lock @@ -3,10 +3,9 @@ [metadata] groups = ["default", "lint", "test"] -cross_platform = true -static_urls = false -lock_version = "4.3" -content_hash = "sha256:252ff80ac0b18f02691c9ddf3493abfdf79ab6af3dfb2487ce04e5e1f3f676cc" +strategy = ["cross_platform"] +lock_version = "4.4.1" +content_hash = "sha256:69e28717f9aa635f1716e0e6fa5d6063b55a8c8e2ae7a0d508fe5d0d218e506a" [[package]] name = "black" @@ -20,7 +19,6 @@ dependencies = [ "pathspec>=0.9.0", "platformdirs>=2", "tomli>=1.1.0; python_version < \"3.11\"", - "typed-ast>=1.4.2; python_version < \"3.8\" and implementation_name == \"cpython\"", "typing-extensions>=3.10.0.0; python_version < \"3.10\"", ] files = [ @@ -58,7 +56,6 @@ requires_python = ">=3.7" summary = "Composable command line interface toolkit" dependencies = [ "colorama; platform_system == \"Windows\"", - "importlib-metadata; python_version < \"3.8\"", ] files = [ {file = "click-8.1.6-py3-none-any.whl", hash = "sha256:fa244bb30b3b5ee2cae3da8f55c9e5e0c0e86093306301fb418eb9dc40fbded5"}, @@ -178,7 +175,6 @@ version = "5.0.4" requires_python = ">=3.6.1" summary = "the modular source code checker: pep8 pyflakes and co" dependencies = [ - "importlib-metadata<4.3,>=1.1.0; python_version < \"3.8\"", "mccabe<0.8.0,>=0.7.0", "pycodestyle<2.10.0,>=2.9.0", "pyflakes<2.6.0,>=2.5.0", @@ -188,20 +184,6 @@ files = [ {file = "flake8-5.0.4.tar.gz", hash = "sha256:6fbe320aad8d6b95cec8b8e47bc933004678dc63095be98528b7bdd2a9f510db"}, ] -[[package]] -name = "importlib-metadata" -version = "4.2.0" -requires_python = ">=3.6" -summary = "Read metadata from Python packages" -dependencies = [ - "typing-extensions>=3.6.4; python_version < \"3.8\"", - "zipp>=0.5", -] -files = [ - {file = "importlib_metadata-4.2.0-py3-none-any.whl", hash = "sha256:057e92c15bc8d9e8109738a48db0ccb31b4d9d5cfbee5a8670879a30be66304b"}, - {file = "importlib_metadata-4.2.0.tar.gz", hash = "sha256:b7e52a1f8dec14a75ea73e0891f3060099ca1d8e6a462a4dff11c3e119ea1b31"}, -] - [[package]] name = "iniconfig" version = "2.0.0" @@ -267,9 +249,6 @@ name = "platformdirs" version = "2.6.2" requires_python = ">=3.7" summary = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." -dependencies = [ - "typing-extensions>=4.4; python_version < \"3.8\"", -] files = [ {file = "platformdirs-2.6.2-py3-none-any.whl", hash = "sha256:83c8f6d04389165de7c9b6f0c682439697887bca0aa2f1c87ef1826be3584490"}, {file = "platformdirs-2.6.2.tar.gz", hash = "sha256:e1fea1fe471b9ff8332e229df3cb7de4f53eeea4998d3b6bfff542115e998bd2"}, @@ -277,15 +256,12 @@ files = [ [[package]] name = "pluggy" -version = "1.2.0" -requires_python = ">=3.7" +version = "1.5.0" +requires_python = ">=3.8" summary = "plugin and hook calling mechanisms for python" -dependencies = [ - "importlib-metadata>=0.12; python_version < \"3.8\"", -] files = [ - {file = "pluggy-1.2.0-py3-none-any.whl", hash = "sha256:c2fd55a7d7a3863cba1a013e4e2414658b1d07b6bc57b3919e0c63c9abb99849"}, - {file = "pluggy-1.2.0.tar.gz", hash = "sha256:d12f0c4b579b15f5e054301bb226ee85eeeba08ffec228092f8defbaa3a4c4b3"}, + {file = "pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669"}, + {file = "pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1"}, ] [[package]] @@ -320,35 +296,33 @@ files = [ [[package]] name = "pytest" -version = "7.4.0" -requires_python = ">=3.7" +version = "8.2.2" +requires_python = ">=3.8" summary = "pytest: simple powerful testing with Python" dependencies = [ "colorama; sys_platform == \"win32\"", "exceptiongroup>=1.0.0rc8; python_version < \"3.11\"", - "importlib-metadata>=0.12; python_version < \"3.8\"", "iniconfig", "packaging", - "pluggy<2.0,>=0.12", - "tomli>=1.0.0; python_version < \"3.11\"", + "pluggy<2.0,>=1.5", + "tomli>=1; python_version < \"3.11\"", ] files = [ - {file = "pytest-7.4.0-py3-none-any.whl", hash = "sha256:78bf16451a2eb8c7a2ea98e32dc119fd2aa758f1d5d66dbf0a59d69a3969df32"}, - {file = "pytest-7.4.0.tar.gz", hash = "sha256:b4bf8c45bd59934ed84001ad51e11b4ee40d40a1229d2c79f9c592b0a3f6bd8a"}, + {file = "pytest-8.2.2-py3-none-any.whl", hash = "sha256:c434598117762e2bd304e526244f67bf66bbd7b5d6cf22138be51ff661980343"}, + {file = "pytest-8.2.2.tar.gz", hash = "sha256:de4bb8104e201939ccdc688b27a89a7be2079b22e2bd2b07f806b6ba71117977"}, ] [[package]] name = "pytest-asyncio" -version = "0.21.1" -requires_python = ">=3.7" +version = "0.23.7" +requires_python = ">=3.8" summary = "Pytest support for asyncio" dependencies = [ - "pytest>=7.0.0", - "typing-extensions>=3.7.2; python_version < \"3.8\"", + "pytest<9,>=7.0.0", ] files = [ - {file = "pytest-asyncio-0.21.1.tar.gz", hash = "sha256:40a7eae6dded22c7b604986855ea48400ab15b069ae38116e8c01238e9eeb64d"}, - {file = "pytest_asyncio-0.21.1-py3-none-any.whl", hash = "sha256:8666c1c8ac02631d7c51ba282e0c69a8a452b211ffedf2599099845da5c5c37b"}, + {file = "pytest_asyncio-0.23.7-py3-none-any.whl", hash = "sha256:009b48127fbe44518a547bddd25611551b0e43ccdbf1e67d12479f569832c20b"}, + {file = "pytest_asyncio-0.23.7.tar.gz", hash = "sha256:5f5c72948f4c49e7db4f29f2521d4031f1c27f86e57b046126654083d4770268"}, ] [[package]] @@ -379,7 +353,6 @@ summary = "tox is a generic virtualenv management and test command line tool" dependencies = [ "colorama>=0.4.1; platform_system == \"Windows\"", "filelock>=3.0.0", - "importlib-metadata>=0.12; python_version < \"3.8\"", "packaging>=14", "pluggy>=0.12.0", "py>=1.4.17", @@ -392,49 +365,6 @@ files = [ {file = "tox-3.28.0.tar.gz", hash = "sha256:d0d28f3fe6d6d7195c27f8b054c3e99d5451952b54abdae673b71609a581f640"}, ] -[[package]] -name = "typed-ast" -version = "1.5.5" -requires_python = ">=3.6" -summary = "a fork of Python 2 and 3 ast modules with type comment support" -files = [ - {file = "typed_ast-1.5.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:4bc1efe0ce3ffb74784e06460f01a223ac1f6ab31c6bc0376a21184bf5aabe3b"}, - {file = "typed_ast-1.5.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5f7a8c46a8b333f71abd61d7ab9255440d4a588f34a21f126bbfc95f6049e686"}, - {file = "typed_ast-1.5.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:597fc66b4162f959ee6a96b978c0435bd63791e31e4f410622d19f1686d5e769"}, - {file = "typed_ast-1.5.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d41b7a686ce653e06c2609075d397ebd5b969d821b9797d029fccd71fdec8e04"}, - {file = "typed_ast-1.5.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:5fe83a9a44c4ce67c796a1b466c270c1272e176603d5e06f6afbc101a572859d"}, - {file = "typed_ast-1.5.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d5c0c112a74c0e5db2c75882a0adf3133adedcdbfd8cf7c9d6ed77365ab90a1d"}, - {file = "typed_ast-1.5.5-cp310-cp310-win_amd64.whl", hash = "sha256:e1a976ed4cc2d71bb073e1b2a250892a6e968ff02aa14c1f40eba4f365ffec02"}, - {file = "typed_ast-1.5.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c631da9710271cb67b08bd3f3813b7af7f4c69c319b75475436fcab8c3d21bee"}, - {file = "typed_ast-1.5.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b445c2abfecab89a932b20bd8261488d574591173d07827c1eda32c457358b18"}, - {file = "typed_ast-1.5.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cc95ffaaab2be3b25eb938779e43f513e0e538a84dd14a5d844b8f2932593d88"}, - {file = "typed_ast-1.5.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:61443214d9b4c660dcf4b5307f15c12cb30bdfe9588ce6158f4a005baeb167b2"}, - {file = "typed_ast-1.5.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:6eb936d107e4d474940469e8ec5b380c9b329b5f08b78282d46baeebd3692dc9"}, - {file = "typed_ast-1.5.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e48bf27022897577d8479eaed64701ecaf0467182448bd95759883300ca818c8"}, - {file = "typed_ast-1.5.5-cp311-cp311-win_amd64.whl", hash = "sha256:83509f9324011c9a39faaef0922c6f720f9623afe3fe220b6d0b15638247206b"}, - {file = "typed_ast-1.5.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:2188bc33d85951ea4ddad55d2b35598b2709d122c11c75cffd529fbc9965508e"}, - {file = "typed_ast-1.5.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0635900d16ae133cab3b26c607586131269f88266954eb04ec31535c9a12ef1e"}, - {file = "typed_ast-1.5.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:57bfc3cf35a0f2fdf0a88a3044aafaec1d2f24d8ae8cd87c4f58d615fb5b6311"}, - {file = "typed_ast-1.5.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:fe58ef6a764de7b4b36edfc8592641f56e69b7163bba9f9c8089838ee596bfb2"}, - {file = "typed_ast-1.5.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d09d930c2d1d621f717bb217bf1fe2584616febb5138d9b3e8cdd26506c3f6d4"}, - {file = "typed_ast-1.5.5-cp37-cp37m-win_amd64.whl", hash = "sha256:d40c10326893ecab8a80a53039164a224984339b2c32a6baf55ecbd5b1df6431"}, - {file = "typed_ast-1.5.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:fd946abf3c31fb50eee07451a6aedbfff912fcd13cf357363f5b4e834cc5e71a"}, - {file = "typed_ast-1.5.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:ed4a1a42df8a3dfb6b40c3d2de109e935949f2f66b19703eafade03173f8f437"}, - {file = "typed_ast-1.5.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:045f9930a1550d9352464e5149710d56a2aed23a2ffe78946478f7b5416f1ede"}, - {file = "typed_ast-1.5.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:381eed9c95484ceef5ced626355fdc0765ab51d8553fec08661dce654a935db4"}, - {file = "typed_ast-1.5.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:bfd39a41c0ef6f31684daff53befddae608f9daf6957140228a08e51f312d7e6"}, - {file = "typed_ast-1.5.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8c524eb3024edcc04e288db9541fe1f438f82d281e591c548903d5b77ad1ddd4"}, - {file = "typed_ast-1.5.5-cp38-cp38-win_amd64.whl", hash = "sha256:7f58fabdde8dcbe764cef5e1a7fcb440f2463c1bbbec1cf2a86ca7bc1f95184b"}, - {file = "typed_ast-1.5.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:042eb665ff6bf020dd2243307d11ed626306b82812aba21836096d229fdc6a10"}, - {file = "typed_ast-1.5.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:622e4a006472b05cf6ef7f9f2636edc51bda670b7bbffa18d26b255269d3d814"}, - {file = "typed_ast-1.5.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1efebbbf4604ad1283e963e8915daa240cb4bf5067053cf2f0baadc4d4fb51b8"}, - {file = "typed_ast-1.5.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f0aefdd66f1784c58f65b502b6cf8b121544680456d1cebbd300c2c813899274"}, - {file = "typed_ast-1.5.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:48074261a842acf825af1968cd912f6f21357316080ebaca5f19abbb11690c8a"}, - {file = "typed_ast-1.5.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:429ae404f69dc94b9361bb62291885894b7c6fb4640d561179548c849f8492ba"}, - {file = "typed_ast-1.5.5-cp39-cp39-win_amd64.whl", hash = "sha256:335f22ccb244da2b5c296e6f96b06ee9bed46526db0de38d2f0e5a6597b81155"}, - {file = "typed_ast-1.5.5.tar.gz", hash = "sha256:94282f7a354f36ef5dbce0ef3467ebf6a258e370ab33d5b40c249fa996e590dd"}, -] - [[package]] name = "typing-extensions" version = "4.7.1" @@ -453,20 +383,9 @@ summary = "Virtual Python Environment builder" dependencies = [ "distlib<1,>=0.3.1", "filelock<4,>=3.2", - "importlib-metadata>=0.12; python_version < \"3.8\"", "platformdirs<3,>=2", ] files = [ {file = "virtualenv-20.16.2-py2.py3-none-any.whl", hash = "sha256:635b272a8e2f77cb051946f46c60a54ace3cb5e25568228bd6b57fc70eca9ff3"}, {file = "virtualenv-20.16.2.tar.gz", hash = "sha256:0ef5be6d07181946891f5abc8047fda8bc2f0b4b9bf222c64e6e8963baee76db"}, ] - -[[package]] -name = "zipp" -version = "3.15.0" -requires_python = ">=3.7" -summary = "Backport of pathlib-compatible object wrapper for zip files" -files = [ - {file = "zipp-3.15.0-py3-none-any.whl", hash = "sha256:48904fc76a60e542af151aded95726c1a5c34ed43ab4134b597665c86d7ad556"}, - {file = "zipp-3.15.0.tar.gz", hash = "sha256:112929ad649da941c23de50f356a2b5570c954b65150642bccdd66bf194d224b"}, -] diff --git a/pyproject.toml b/pyproject.toml index ea660cc..b0a948c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,19 +6,19 @@ authors = [ {name = "Tin Tvrtkovic", email = "tinchester@gmail.com"}, ] dependencies = [] -requires-python = ">=3.7" +requires-python = ">=3.8" readme = "README.md" license = {text = "Apache-2.0"} classifiers = [ "Development Status :: 5 - Production/Stable", "License :: OSI Approved :: Apache Software License", "Operating System :: OS Independent", - "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy", "Framework :: AsyncIO", @@ -29,19 +29,6 @@ Changelog = "https://github.com/Tinche/aiofiles#history" "Bug Tracker" = "https://github.com/Tinche/aiofiles/issues" repository = "https://github.com/Tinche/aiofiles" -[tool.pdm.dev-dependencies] -test = [ - "pytest>=7.2.0", - "pytest-asyncio>=0.19.0", - "coverage>=6.4.4", - "tox>=3.25.1", -] -lint = [ - "black>=22.8.0", - "flake8>=5.0.4", - "isort==5.11.5", -] - [build-system] requires = ["hatchling"] build-backend = "hatchling.build" @@ -63,3 +50,19 @@ skip-magic-trailing-comma = true [tool.isort] profile = "black" known_first_party = ["aiofiles"] + +[tool.pdm.dev-dependencies] +test = [ + "pytest>=8.2.2", + "pytest-asyncio>=0.23.7", + "coverage>=6.4.4", + "tox>=3.25.1", +] +lint = [ + "black>=22.8.0", + "flake8>=5.0.4", + "isort==5.11.5", +] + +[tool.pytest.ini_options] +asyncio_mode = "auto" diff --git a/tests/test_os.py b/tests/test_os.py index fbda8ea..76159d7 100644 --- a/tests/test_os.py +++ b/tests/test_os.py @@ -12,7 +12,6 @@ import aiofiles.os -@pytest.mark.asyncio async def test_stat(): """Test the stat call.""" filename = join(dirname(__file__), "resources", "test_file1.txt") @@ -23,7 +22,6 @@ async def test_stat(): @pytest.mark.skipif(platform.system() == "Windows", reason="No statvfs on Windows") -@pytest.mark.asyncio async def test_statvfs(): """Test the statvfs call.""" @@ -32,7 +30,6 @@ async def test_statvfs(): assert statvfs_res.f_bsize == os.statvfs("/").f_bsize -@pytest.mark.asyncio async def test_remove(): """Test the remove call.""" filename = join(dirname(__file__), "resources", "test_file2.txt") @@ -44,7 +41,6 @@ async def test_remove(): assert exists(filename) is False -@pytest.mark.asyncio async def test_unlink(): """Test the unlink call.""" filename = join(dirname(__file__), "resources", "test_file2.txt") @@ -56,7 +52,6 @@ async def test_unlink(): assert exists(filename) is False -@pytest.mark.asyncio async def test_mkdir_and_rmdir(): """Test the mkdir and rmdir call.""" directory = join(dirname(__file__), "resources", "test_dir") @@ -66,7 +61,6 @@ async def test_mkdir_and_rmdir(): assert exists(directory) is False -@pytest.mark.asyncio async def test_rename(): """Test the rename call.""" old_filename = join(dirname(__file__), "resources", "test_file1.txt") @@ -77,7 +71,6 @@ async def test_rename(): assert exists(old_filename) and exists(new_filename) is False -@pytest.mark.asyncio async def test_renames(): """Test the renames call.""" old_filename = join(dirname(__file__), "resources", "test_file1.txt") @@ -94,7 +87,6 @@ async def test_renames(): ) -@pytest.mark.asyncio async def test_replace(): """Test the replace call.""" old_filename = join(dirname(__file__), "resources", "test_file1.txt") @@ -123,7 +115,6 @@ async def test_replace(): platform.system() in ("Darwin", "Windows"), reason="sendfile() doesn't work on mac and Win", ) -@pytest.mark.asyncio async def test_sendfile_file(tmpdir): """Test the sendfile functionality, file-to-file.""" filename = join(dirname(__file__), "resources", "test_file1.txt") @@ -154,7 +145,6 @@ async def test_sendfile_file(tmpdir): @pytest.mark.skipif( platform.system() in ("Windows"), reason="sendfile() doesn't work on Win" ) -@pytest.mark.asyncio async def test_sendfile_socket(unused_tcp_port): """Test the sendfile functionality, file-to-socket.""" filename = join(dirname(__file__), "resources", "test_file1.txt") @@ -186,7 +176,6 @@ async def serve_file(_, writer): await server.wait_closed() -@pytest.mark.asyncio async def test_exists(): """Test path.exists call.""" filename = join(dirname(__file__), "resources", "test_file1.txt") @@ -194,7 +183,6 @@ async def test_exists(): assert result -@pytest.mark.asyncio async def test_isfile(): """Test path.isfile call.""" filename = join(dirname(__file__), "resources", "test_file1.txt") @@ -202,7 +190,6 @@ async def test_isfile(): assert result -@pytest.mark.asyncio async def test_isdir(): """Test path.isdir call.""" filename = join(dirname(__file__), "resources") @@ -210,7 +197,6 @@ async def test_isdir(): assert result -@pytest.mark.asyncio async def test_islink(): """Test the path.islink call.""" src_filename = join(dirname(__file__), "resources", "test_file1.txt") @@ -220,7 +206,6 @@ async def test_islink(): await aiofiles.os.remove(dst_filename) -@pytest.mark.asyncio async def test_ismount(): """Test the path.ismount call.""" filename = join(dirname(__file__), "resources") @@ -228,7 +213,6 @@ async def test_ismount(): assert await aiofiles.os.path.ismount("/") -@pytest.mark.asyncio async def test_getsize(): """Test path.getsize call.""" filename = join(dirname(__file__), "resources", "test_file1.txt") @@ -236,7 +220,6 @@ async def test_getsize(): assert result == 10 -@pytest.mark.asyncio async def test_samefile(): """Test path.samefile call.""" filename = join(dirname(__file__), "resources", "test_file1.txt") @@ -244,7 +227,6 @@ async def test_samefile(): assert result -@pytest.mark.asyncio async def test_sameopenfile(): """Test path.samefile call.""" filename = join(dirname(__file__), "resources", "test_file1.txt") @@ -252,7 +234,6 @@ async def test_sameopenfile(): assert result -@pytest.mark.asyncio async def test_getmtime(): """Test path.getmtime call.""" filename = join(dirname(__file__), "resources", "test_file1.txt") @@ -260,7 +241,6 @@ async def test_getmtime(): assert result -@pytest.mark.asyncio async def test_getatime(): """Test path.getatime call.""" filename = join(dirname(__file__), "resources", "test_file1.txt") @@ -268,7 +248,6 @@ async def test_getatime(): assert result -@pytest.mark.asyncio async def test_getctime(): """Test path. call.""" filename = join(dirname(__file__), "resources", "test_file1.txt") @@ -276,7 +255,6 @@ async def test_getctime(): assert result -@pytest.mark.asyncio async def test_link(): """Test the link call.""" src_filename = join(dirname(__file__), "resources", "test_file1.txt") @@ -298,7 +276,6 @@ async def test_link(): ) -@pytest.mark.asyncio async def test_symlink(): """Test the symlink call.""" src_filename = join(dirname(__file__), "resources", "test_file1.txt") @@ -316,7 +293,6 @@ async def test_symlink(): @pytest.mark.skipif( platform.system() == "Windows", reason="Doesn't work on Win properly" ) -@pytest.mark.asyncio async def test_readlink(): """Test the readlink call.""" src_filename = join(dirname(__file__), "resources", "test_file1.txt") @@ -327,7 +303,6 @@ async def test_readlink(): await aiofiles.os.remove(dst_filename) -@pytest.mark.asyncio async def test_listdir_empty_dir(): """Test the listdir call when the dir is empty.""" directory = join(dirname(__file__), "resources", "empty_dir") @@ -337,7 +312,6 @@ async def test_listdir_empty_dir(): await aiofiles.os.rmdir(directory) -@pytest.mark.asyncio async def test_listdir_dir_with_only_one_file(): """Test the listdir call when the dir has one file.""" some_dir = join(dirname(__file__), "resources", "some_dir") @@ -351,7 +325,6 @@ async def test_listdir_dir_with_only_one_file(): await aiofiles.os.rmdir(some_dir) -@pytest.mark.asyncio async def test_listdir_dir_with_only_one_dir(): """Test the listdir call when the dir has one dir.""" some_dir = join(dirname(__file__), "resources", "some_dir") @@ -364,7 +337,6 @@ async def test_listdir_dir_with_only_one_dir(): await aiofiles.os.rmdir(some_dir) -@pytest.mark.asyncio async def test_listdir_dir_with_multiple_files(): """Test the listdir call when the dir has multiple files.""" some_dir = join(dirname(__file__), "resources", "some_dir") @@ -383,7 +355,6 @@ async def test_listdir_dir_with_multiple_files(): await aiofiles.os.rmdir(some_dir) -@pytest.mark.asyncio async def test_listdir_dir_with_a_file_and_a_dir(): """Test the listdir call when the dir has files and other dirs.""" some_dir = join(dirname(__file__), "resources", "some_dir") @@ -401,7 +372,6 @@ async def test_listdir_dir_with_a_file_and_a_dir(): await aiofiles.os.rmdir(some_dir) -@pytest.mark.asyncio async def test_listdir_non_existing_dir(): """Test the listdir call when the dir doesn't exist.""" some_dir = join(dirname(__file__), "resources", "some_dir") @@ -409,7 +379,6 @@ async def test_listdir_non_existing_dir(): await aiofiles.os.listdir(some_dir) -@pytest.mark.asyncio async def test_scantdir_empty_dir(): """Test the scandir call when the dir is empty.""" empty_dir = join(dirname(__file__), "resources", "empty_dir") @@ -422,7 +391,6 @@ async def test_scantdir_empty_dir(): await aiofiles.os.rmdir(empty_dir) -@pytest.mark.asyncio async def test_scandir_dir_with_only_one_file(): """Test the scandir call when the dir has one file.""" some_dir = join(dirname(__file__), "resources", "some_dir") @@ -437,7 +405,6 @@ async def test_scandir_dir_with_only_one_file(): await aiofiles.os.rmdir(some_dir) -@pytest.mark.asyncio async def test_scandir_dir_with_only_one_dir(): """Test the scandir call when the dir has one dir.""" some_dir = join(dirname(__file__), "resources", "some_dir") @@ -451,7 +418,6 @@ async def test_scandir_dir_with_only_one_dir(): await aiofiles.os.rmdir(some_dir) -@pytest.mark.asyncio async def test_scandir_non_existing_dir(): """Test the scandir call when the dir doesn't exist.""" some_dir = join(dirname(__file__), "resources", "some_dir") @@ -460,7 +426,6 @@ async def test_scandir_non_existing_dir(): @pytest.mark.skipif(platform.system() == "Windows", reason="Doesn't work on Win") -@pytest.mark.asyncio async def test_access(): temp_file = Path(__file__).parent.joinpath("resources", "os_access_temp.txt") temp_dir = Path(__file__).parent.joinpath("resources", "os_access_temp") @@ -514,14 +479,12 @@ async def test_access(): assert not await aiofiles.os.access(temp_dir, mode) -@pytest.mark.asyncio async def test_getcwd(): """Test the getcwd call.""" cwd = await aiofiles.os.getcwd() assert cwd == os.getcwd() -@pytest.mark.asyncio async def test_abspath_given_abspath(): """Test the abspath call with an absolute path.""" filename = join(dirname(__file__), "resources", "test_file1.txt") @@ -529,7 +492,6 @@ async def test_abspath_given_abspath(): assert file_abs_path == filename -@pytest.mark.asyncio async def test_abspath(): """Test the abspath call.""" relative_filename = "./tests/resources/test_file1.txt" diff --git a/tests/test_simple.py b/tests/test_simple.py index 6bde49e..2f748b3 100644 --- a/tests/test_simple.py +++ b/tests/test_simple.py @@ -1,11 +1,9 @@ """Simple tests verifying basic functionality.""" import asyncio from aiofiles import threadpool -import pytest -@pytest.mark.asyncio -async def test_serve_small_bin_file_sync(event_loop, tmpdir, unused_tcp_port): +async def test_serve_small_bin_file_sync(tmpdir, unused_tcp_port): """Fire up a small simple file server, and fetch a file. The file is read into memory synchronously, so this test doesn't actually @@ -34,8 +32,7 @@ async def serve_file(reader, writer): await server.wait_closed() -@pytest.mark.asyncio -async def test_serve_small_bin_file(event_loop, tmpdir, unused_tcp_port): +async def test_serve_small_bin_file(tmpdir, unused_tcp_port): """Fire up a small simple file server, and fetch a file.""" # First we'll write a small file. filename = "test.bin" diff --git a/tests/test_stdio.py b/tests/test_stdio.py index 1a0b6a2..1cf401e 100644 --- a/tests/test_stdio.py +++ b/tests/test_stdio.py @@ -3,7 +3,6 @@ from aiofiles import stderr, stderr_bytes, stdin, stdin_bytes, stdout, stdout_bytes -@pytest.mark.asyncio async def test_stdio(capsys): await stdout.write("hello") await stderr.write("world") @@ -14,7 +13,6 @@ async def test_stdio(capsys): await stdin.read() -@pytest.mark.asyncio async def test_stdio_bytes(capsysbinary): await stdout_bytes.write(b"hello") await stderr_bytes.write(b"world") diff --git a/tests/test_tempfile.py b/tests/test_tempfile.py index b4d6ffd..68a247c 100644 --- a/tests/test_tempfile.py +++ b/tests/test_tempfile.py @@ -8,7 +8,6 @@ from aiofiles import tempfile -@pytest.mark.asyncio @pytest.mark.parametrize("mode", ["r+", "w+", "rb+", "wb+"]) async def test_temporary_file(mode): """Test temporary file.""" @@ -25,7 +24,6 @@ async def test_temporary_file(mode): assert line == data -@pytest.mark.asyncio @pytest.mark.parametrize("mode", ["r+", "w+", "rb+", "wb+"]) @pytest.mark.skipif( sys.version_info >= (3, 12), @@ -49,7 +47,6 @@ async def test_named_temporary_file(mode): assert not os.path.exists(filename) -@pytest.mark.asyncio @pytest.mark.parametrize("mode", ["r+", "w+", "rb+", "wb+"]) @pytest.mark.skipif( sys.version_info < (3, 12), @@ -72,7 +69,6 @@ async def test_named_temporary_file_312(mode): assert not os.path.exists(filename) -@pytest.mark.asyncio @pytest.mark.parametrize("mode", ["r+", "w+", "rb+", "wb+"]) @pytest.mark.skipif( sys.version_info < (3, 12), reason=("3.12+ supports delete_on_close") @@ -100,7 +96,6 @@ async def test_named_temporary_delete_on_close(mode): assert not os.path.exists(filename) -@pytest.mark.asyncio @pytest.mark.parametrize("mode", ["r+", "w+", "rb+", "wb+"]) async def test_spooled_temporary_file(mode): """Test spooled temporary file.""" @@ -124,7 +119,6 @@ async def test_spooled_temporary_file(mode): @pytest.mark.skipif( platform.system() == "Windows", reason="Doesn't work on Win properly" ) -@pytest.mark.asyncio @pytest.mark.parametrize( "test_string, newlines", [("LF\n", "\n"), ("CRLF\r\n", "\r\n")] ) @@ -146,7 +140,6 @@ async def test_spooled_temporary_file_newlines(test_string, newlines): assert f.newlines == newlines -@pytest.mark.asyncio @pytest.mark.parametrize("prefix, suffix", [("a", "b"), ("c", "d"), ("e", "f")]) async def test_temporary_directory(prefix, suffix, tmp_path): """Test temporary directory.""" diff --git a/tests/threadpool/test_binary.py b/tests/threadpool/test_binary.py index faf72a0..b350397 100644 --- a/tests/threadpool/test_binary.py +++ b/tests/threadpool/test_binary.py @@ -5,7 +5,6 @@ import pytest -@pytest.mark.asyncio @pytest.mark.parametrize("mode", ["rb", "rb+", "ab+"]) @pytest.mark.parametrize("buffering", [-1, 0]) async def test_simple_iteration(mode, buffering): @@ -35,7 +34,6 @@ async def test_simple_iteration(mode, buffering): assert file.closed -@pytest.mark.asyncio @pytest.mark.parametrize("mode", ["rb", "rb+", "ab+"]) @pytest.mark.parametrize("buffering", [-1, 0]) async def test_simple_readlines(mode, buffering): @@ -54,7 +52,6 @@ async def test_simple_readlines(mode, buffering): assert actual == expected -@pytest.mark.asyncio @pytest.mark.parametrize("mode", ["rb+", "wb", "ab"]) @pytest.mark.parametrize("buffering", [-1, 0]) async def test_simple_flush(mode, buffering, tmpdir): @@ -79,7 +76,6 @@ async def test_simple_flush(mode, buffering, tmpdir): assert b"0" == full_file.read_binary() -@pytest.mark.asyncio @pytest.mark.parametrize("mode", ["rb+", "wb+", "ab+"]) async def test_simple_peek(mode, tmpdir): """Test flushing to a file.""" @@ -103,7 +99,6 @@ async def test_simple_peek(mode, tmpdir): assert peeked.startswith(read) -@pytest.mark.asyncio @pytest.mark.parametrize("mode", ["rb", "rb+", "ab+"]) @pytest.mark.parametrize("buffering", [-1, 0]) async def test_simple_read(mode, buffering): @@ -118,7 +113,6 @@ async def test_simple_read(mode, buffering): assert actual == open(filename, mode="rb").read() -@pytest.mark.asyncio @pytest.mark.parametrize("mode", ["rb", "rb+", "ab+"]) @pytest.mark.parametrize("buffering", [-1, 0]) async def test_staggered_read(mode, buffering): @@ -149,7 +143,6 @@ async def test_staggered_read(mode, buffering): assert actual == expected -@pytest.mark.asyncio @pytest.mark.parametrize("mode", ["rb", "rb+", "ab+"]) @pytest.mark.parametrize("buffering", [-1, 0]) async def test_simple_seek(mode, buffering, tmpdir): @@ -166,7 +159,6 @@ async def test_simple_seek(mode, buffering, tmpdir): assert b"4" == (await file.read(1)) -@pytest.mark.asyncio @pytest.mark.parametrize("mode", ["wb", "rb", "rb+", "wb+", "ab", "ab+"]) @pytest.mark.parametrize("buffering", [-1, 0]) async def test_simple_close_ctx_mgr_iter(mode, buffering, tmpdir): @@ -185,7 +177,6 @@ async def test_simple_close_ctx_mgr_iter(mode, buffering, tmpdir): assert file._file.closed -@pytest.mark.asyncio @pytest.mark.parametrize("mode", ["wb", "rb", "rb+", "wb+", "ab", "ab+"]) @pytest.mark.parametrize("buffering", [-1, 0]) async def test_simple_close_ctx_mgr(mode, buffering, tmpdir): @@ -206,7 +197,6 @@ async def test_simple_close_ctx_mgr(mode, buffering, tmpdir): assert file._file.closed -@pytest.mark.asyncio @pytest.mark.parametrize("mode", ["rb", "rb+", "ab+"]) @pytest.mark.parametrize("buffering", [-1, 0]) async def test_simple_readinto(mode, buffering): @@ -222,7 +212,6 @@ async def test_simple_readinto(mode, buffering): assert array == open(filename, mode="rb").read(4) -@pytest.mark.asyncio @pytest.mark.parametrize("mode", ["rb+", "wb", "ab+"]) @pytest.mark.parametrize("buffering", [-1, 0]) async def test_simple_truncate(mode, buffering, tmpdir): @@ -248,7 +237,6 @@ async def test_simple_truncate(mode, buffering, tmpdir): assert b"" == full_file.read_binary() -@pytest.mark.asyncio @pytest.mark.parametrize("mode", ["wb", "rb+", "wb+", "ab", "ab+"]) @pytest.mark.parametrize("buffering", [-1, 0]) async def test_simple_write(mode, buffering, tmpdir): @@ -268,7 +256,6 @@ async def test_simple_write(mode, buffering, tmpdir): assert content == full_file.read_binary() -@pytest.mark.asyncio async def test_simple_detach(tmpdir): """Test detaching for buffered streams.""" filename = "file.bin" @@ -288,7 +275,6 @@ async def test_simple_detach(tmpdir): assert b"0123456789" == raw_file.read(10) -@pytest.mark.asyncio async def test_simple_readall(tmpdir): """Test the readall function by reading a large file in. @@ -310,7 +296,6 @@ async def test_simple_readall(tmpdir): assert file.closed -@pytest.mark.asyncio @pytest.mark.parametrize("mode", ["rb", "rb+", "ab+"]) @pytest.mark.parametrize("buffering", [-1, 0]) async def test_name_property(mode, buffering): @@ -323,7 +308,6 @@ async def test_name_property(mode, buffering): assert file.closed -@pytest.mark.asyncio @pytest.mark.parametrize("mode", ["rb", "rb+", "ab+"]) @pytest.mark.parametrize("buffering", [-1, 0]) async def test_mode_property(mode, buffering): diff --git a/tests/threadpool/test_concurrency.py b/tests/threadpool/test_concurrency.py index 1411089..fa2ec0a 100644 --- a/tests/threadpool/test_concurrency.py +++ b/tests/threadpool/test_concurrency.py @@ -3,12 +3,10 @@ from os.path import join import time import asyncio -import pytest import aiofiles.threadpool -@pytest.mark.asyncio async def test_slow_file(monkeypatch, unused_tcp_port): """Monkey patch open and file.read(), and assert the loop still works.""" filename = join(dirname(__file__), "..", "resources", "multiline_file.txt") diff --git a/tests/threadpool/test_open.py b/tests/threadpool/test_open.py index b65cab9..654e06b 100644 --- a/tests/threadpool/test_open.py +++ b/tests/threadpool/test_open.py @@ -3,7 +3,6 @@ import pytest -@pytest.mark.asyncio @pytest.mark.parametrize("mode", ["r", "rb"]) async def test_file_not_found(mode): filename = "non_existent" diff --git a/tests/threadpool/test_text.py b/tests/threadpool/test_text.py index 8d04039..6f573ca 100644 --- a/tests/threadpool/test_text.py +++ b/tests/threadpool/test_text.py @@ -5,7 +5,6 @@ import pytest -@pytest.mark.asyncio @pytest.mark.parametrize("mode", ["r", "r+", "a+"]) async def test_simple_iteration(mode): """Test iterating over lines from a file.""" @@ -36,7 +35,6 @@ async def test_simple_iteration(mode): assert file.closed -@pytest.mark.asyncio @pytest.mark.parametrize("mode", ["r", "r+", "a+"]) async def test_simple_readlines(mode): """Test the readlines functionality.""" @@ -56,7 +54,6 @@ async def test_simple_readlines(mode): assert actual == expected -@pytest.mark.asyncio @pytest.mark.parametrize("mode", ["r+", "w", "a"]) async def test_simple_flush(mode, tmpdir): """Test flushing to a file.""" @@ -79,7 +76,6 @@ async def test_simple_flush(mode, tmpdir): assert file.closed -@pytest.mark.asyncio @pytest.mark.parametrize("mode", ["r", "r+", "a+"]) async def test_simple_read(mode): """Just read some bytes from a test file.""" @@ -95,7 +91,6 @@ async def test_simple_read(mode): assert file.closed -@pytest.mark.asyncio @pytest.mark.parametrize("mode", ["w", "a"]) async def test_simple_read_fail(mode, tmpdir): """Try reading some bytes and fail.""" @@ -113,7 +108,6 @@ async def test_simple_read_fail(mode, tmpdir): assert file.closed -@pytest.mark.asyncio @pytest.mark.parametrize("mode", ["r", "r+", "a+"]) async def test_staggered_read(mode): """Read bytes repeatedly.""" @@ -145,7 +139,6 @@ async def test_staggered_read(mode): assert file.closed -@pytest.mark.asyncio @pytest.mark.parametrize("mode", ["r", "r+", "a+"]) async def test_simple_seek(mode, tmpdir): """Test seeking and then reading.""" @@ -162,7 +155,6 @@ async def test_simple_seek(mode, tmpdir): assert file.closed -@pytest.mark.asyncio @pytest.mark.parametrize("mode", ["w", "r", "r+", "w+", "a", "a+"]) async def test_simple_close(mode, tmpdir): """Open a file, read a byte, and close it.""" @@ -180,7 +172,6 @@ async def test_simple_close(mode, tmpdir): assert file._file.closed -@pytest.mark.asyncio @pytest.mark.parametrize("mode", ["r+", "w", "a+"]) async def test_simple_truncate(mode, tmpdir): """Test truncating files.""" @@ -205,7 +196,6 @@ async def test_simple_truncate(mode, tmpdir): assert "" == full_file.read() -@pytest.mark.asyncio @pytest.mark.parametrize("mode", ["w", "r+", "w+", "a", "a+"]) async def test_simple_write(mode, tmpdir): """Test writing into a file.""" @@ -225,7 +215,6 @@ async def test_simple_write(mode, tmpdir): assert file.closed -@pytest.mark.asyncio async def test_simple_detach(tmpdir): """Test detaching for buffered streams.""" filename = "file.bin" @@ -245,7 +234,6 @@ async def test_simple_detach(tmpdir): assert b"0123456789" == raw_file.read(10) -@pytest.mark.asyncio @pytest.mark.parametrize("mode", ["r", "r+", "a+"]) async def test_simple_iteration_ctx_mgr(mode): """Test iterating over lines from a file.""" @@ -264,7 +252,6 @@ async def test_simple_iteration_ctx_mgr(mode): assert file.closed -@pytest.mark.asyncio @pytest.mark.parametrize("mode", ["r", "r+", "a+"]) async def test_name_property(mode): """Test iterating over lines from a file.""" @@ -276,7 +263,6 @@ async def test_name_property(mode): assert file.closed -@pytest.mark.asyncio @pytest.mark.parametrize("mode", ["r", "r+", "a+"]) async def test_mode_property(mode): """Test iterating over lines from a file.""" diff --git a/tox.ini b/tox.ini index 54cd0b7..321b5a0 100644 --- a/tox.ini +++ b/tox.ini @@ -1,21 +1,21 @@ [gh-actions] python = - 3.7: py37 3.8: py38 3.9: py39 3.10: py310 - 3.11: py311, lint - 3.12: py312 + 3.11: py311 + 3.12: py312, lint + 3.13: py313 pypy-3.7: pypy3 [tox] -envlist = py37, py38, py39, py310, py311, py312, pypy3, lint +envlist = py38, py39, py310, py311, py312, py313, pypy3, lint isolated_build = true skipsdist = true [testenv:lint] skip_install = true -basepython = python3.11 +basepython = python3.12 allowlist_externals = make pdm