diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index a1afea2..ab40fee 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -17,25 +17,23 @@ jobs: strategy: matrix: linter: - - lint - - mypy + - pylama aiofile tests + - mypy aiofile tests steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Setting up python 3.10 - uses: actions/setup-python@v2 + uses: actions/setup-python@v5 with: - python-version: "3.10" + python-version: "3.12" architecture: x64 - - name: Installing tox - run: python -m pip install tox + - name: Poetry install + run: python -m pip install poetry && poetry install - - name: tox ${{ matrix.linter }} - run: tox - env: - TOXENV: ${{ matrix.linter }} + - name: ${{ matrix.linter }} + run: poetry run ${{ matrix.linter }} tests: strategy: diff --git a/aiofile/__init__.py b/aiofile/__init__.py index 444e91e..50c257d 100644 --- a/aiofile/__init__.py +++ b/aiofile/__init__.py @@ -3,7 +3,6 @@ BinaryFileWrapper, FileIOWrapperBase, LineReader, Reader, TextFileWrapper, Writer, async_open, ) - from .version import ( __author__, __version__, author_info, package_info, package_license, project_home, team_email, version_info, diff --git a/aiofile/aio.py b/aiofile/aio.py index c9e542b..f6b316d 100644 --- a/aiofile/aio.py +++ b/aiofile/aio.py @@ -149,7 +149,7 @@ def from_fp(cls, fp: FileIOType, **kwargs: Any) -> "AIOFile": return afp def _run_in_thread( - self, func: "Callable[..., _T]", *args: Any, **kwargs: Any + self, func: "Callable[..., _T]", *args: Any, **kwargs: Any, ) -> "asyncio.Future[_T]": return self.__context.loop.run_in_executor( self._executor, partial(func, *args, **kwargs), diff --git a/aiofile/utils.py b/aiofile/utils.py index 4f7c83e..d3d02b7 100644 --- a/aiofile/utils.py +++ b/aiofile/utils.py @@ -335,7 +335,7 @@ async def readline(self, size: int = -1, newline: str = "\n") -> str: def async_open( file_specifier: Union[str, Path, FileIOType], - mode: str = "r", *args: Any, **kwargs: Any + mode: str = "r", *args: Any, **kwargs: Any, ) -> Union[BinaryFileWrapper, TextFileWrapper]: if isinstance(file_specifier, (str, Path)): afp = AIOFile(str(file_specifier), mode, *args, **kwargs) diff --git a/aiofile/version.py b/aiofile/version.py index 9f149f7..06500a6 100644 --- a/aiofile/version.py +++ b/aiofile/version.py @@ -1,12 +1,13 @@ import importlib.metadata -package_metadata = importlib.metadata.metadata('aiofile') -__author__ = package_metadata['Author'] -__version__ = package_metadata['Version'] -author_info = [(package_metadata['Author'], package_metadata['Author-email'])] -package_info = package_metadata['Summary'] -package_license = package_metadata['License'] -project_home = package_metadata['Home-page'] -team_email = package_metadata['Author-email'] -version_info = tuple(map(int, __version__.split('.'))) \ No newline at end of file +package_metadata = importlib.metadata.metadata("aiofile") + +__author__ = package_metadata["Author"] +__version__ = package_metadata["Version"] +author_info = [(package_metadata["Author"], package_metadata["Author-email"])] +package_info = package_metadata["Summary"] +package_license = package_metadata["License"] +project_home = package_metadata["Home-page"] +team_email = package_metadata["Author-email"] +version_info = tuple(map(int, __version__.split("."))) diff --git a/poetry.lock b/poetry.lock index 8fb1391..1fef0ea 100644 --- a/poetry.lock +++ b/poetry.lock @@ -382,6 +382,75 @@ files = [ [package.dependencies] pytest-subtests = ">=0.12.0" +[[package]] +name = "mccabe" +version = "0.7.0" +description = "McCabe checker, plugin for flake8" +optional = false +python-versions = ">=3.6" +files = [ + {file = "mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e"}, + {file = "mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325"}, +] + +[[package]] +name = "mypy" +version = "1.11.2" +description = "Optional static typing for Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "mypy-1.11.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d42a6dd818ffce7be66cce644f1dff482f1d97c53ca70908dff0b9ddc120b77a"}, + {file = "mypy-1.11.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:801780c56d1cdb896eacd5619a83e427ce436d86a3bdf9112527f24a66618fef"}, + {file = "mypy-1.11.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:41ea707d036a5307ac674ea172875f40c9d55c5394f888b168033177fce47383"}, + {file = "mypy-1.11.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6e658bd2d20565ea86da7d91331b0eed6d2eee22dc031579e6297f3e12c758c8"}, + {file = "mypy-1.11.2-cp310-cp310-win_amd64.whl", hash = "sha256:478db5f5036817fe45adb7332d927daa62417159d49783041338921dcf646fc7"}, + {file = "mypy-1.11.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:75746e06d5fa1e91bfd5432448d00d34593b52e7e91a187d981d08d1f33d4385"}, + {file = "mypy-1.11.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a976775ab2256aadc6add633d44f100a2517d2388906ec4f13231fafbb0eccca"}, + {file = "mypy-1.11.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:cd953f221ac1379050a8a646585a29574488974f79d8082cedef62744f0a0104"}, + {file = "mypy-1.11.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:57555a7715c0a34421013144a33d280e73c08df70f3a18a552938587ce9274f4"}, + {file = "mypy-1.11.2-cp311-cp311-win_amd64.whl", hash = "sha256:36383a4fcbad95f2657642a07ba22ff797de26277158f1cc7bd234821468b1b6"}, + {file = "mypy-1.11.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:e8960dbbbf36906c5c0b7f4fbf2f0c7ffb20f4898e6a879fcf56a41a08b0d318"}, + {file = "mypy-1.11.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:06d26c277962f3fb50e13044674aa10553981ae514288cb7d0a738f495550b36"}, + {file = "mypy-1.11.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6e7184632d89d677973a14d00ae4d03214c8bc301ceefcdaf5c474866814c987"}, + {file = "mypy-1.11.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:3a66169b92452f72117e2da3a576087025449018afc2d8e9bfe5ffab865709ca"}, + {file = "mypy-1.11.2-cp312-cp312-win_amd64.whl", hash = "sha256:969ea3ef09617aff826885a22ece0ddef69d95852cdad2f60c8bb06bf1f71f70"}, + {file = "mypy-1.11.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:37c7fa6121c1cdfcaac97ce3d3b5588e847aa79b580c1e922bb5d5d2902df19b"}, + {file = "mypy-1.11.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4a8a53bc3ffbd161b5b2a4fff2f0f1e23a33b0168f1c0778ec70e1a3d66deb86"}, + {file = "mypy-1.11.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2ff93107f01968ed834f4256bc1fc4475e2fecf6c661260066a985b52741ddce"}, + {file = "mypy-1.11.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:edb91dded4df17eae4537668b23f0ff6baf3707683734b6a818d5b9d0c0c31a1"}, + {file = "mypy-1.11.2-cp38-cp38-win_amd64.whl", hash = "sha256:ee23de8530d99b6db0573c4ef4bd8f39a2a6f9b60655bf7a1357e585a3486f2b"}, + {file = "mypy-1.11.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:801ca29f43d5acce85f8e999b1e431fb479cb02d0e11deb7d2abb56bdaf24fd6"}, + {file = "mypy-1.11.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:af8d155170fcf87a2afb55b35dc1a0ac21df4431e7d96717621962e4b9192e70"}, + {file = "mypy-1.11.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f7821776e5c4286b6a13138cc935e2e9b6fde05e081bdebf5cdb2bb97c9df81d"}, + {file = "mypy-1.11.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:539c570477a96a4e6fb718b8d5c3e0c0eba1f485df13f86d2970c91f0673148d"}, + {file = "mypy-1.11.2-cp39-cp39-win_amd64.whl", hash = "sha256:3f14cd3d386ac4d05c5a39a51b84387403dadbd936e17cb35882134d4f8f0d24"}, + {file = "mypy-1.11.2-py3-none-any.whl", hash = "sha256:b499bc07dbdcd3de92b0a8b29fdf592c111276f6a12fe29c30f6c417dd546d12"}, + {file = "mypy-1.11.2.tar.gz", hash = "sha256:7f9993ad3e0ffdc95c2a14b66dee63729f021968bff8ad911867579c65d13a79"}, +] + +[package.dependencies] +mypy-extensions = ">=1.0.0" +tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} +typing-extensions = ">=4.6.0" + +[package.extras] +dmypy = ["psutil (>=4.0)"] +install-types = ["pip"] +mypyc = ["setuptools (>=50)"] +reports = ["lxml"] + +[[package]] +name = "mypy-extensions" +version = "1.0.0" +description = "Type system extensions for programs checked with the mypy type checker." +optional = false +python-versions = ">=3.5" +files = [ + {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"}, + {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, +] + [[package]] name = "packaging" version = "24.1" @@ -408,6 +477,72 @@ files = [ dev = ["pre-commit", "tox"] testing = ["pytest", "pytest-benchmark"] +[[package]] +name = "pycodestyle" +version = "2.12.1" +description = "Python style guide checker" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pycodestyle-2.12.1-py2.py3-none-any.whl", hash = "sha256:46f0fb92069a7c28ab7bb558f05bfc0110dac69a0cd23c61ea0040283a9d78b3"}, + {file = "pycodestyle-2.12.1.tar.gz", hash = "sha256:6838eae08bbce4f6accd5d5572075c63626a15ee3e6f842df996bf62f6d73521"}, +] + +[[package]] +name = "pydocstyle" +version = "6.3.0" +description = "Python docstring style checker" +optional = false +python-versions = ">=3.6" +files = [ + {file = "pydocstyle-6.3.0-py3-none-any.whl", hash = "sha256:118762d452a49d6b05e194ef344a55822987a462831ade91ec5c06fd2169d019"}, + {file = "pydocstyle-6.3.0.tar.gz", hash = "sha256:7ce43f0c0ac87b07494eb9c0b462c0b73e6ff276807f204d6b53edc72b7e44e1"}, +] + +[package.dependencies] +snowballstemmer = ">=2.2.0" + +[package.extras] +toml = ["tomli (>=1.2.3)"] + +[[package]] +name = "pyflakes" +version = "3.2.0" +description = "passive checker of Python programs" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pyflakes-3.2.0-py2.py3-none-any.whl", hash = "sha256:84b5be138a2dfbb40689ca07e2152deb896a65c3a3e24c251c5c62489568074a"}, + {file = "pyflakes-3.2.0.tar.gz", hash = "sha256:1c61603ff154621fb2a9172037d84dca3500def8c8b630657d1701f026f8af3f"}, +] + +[[package]] +name = "pylama" +version = "8.4.1" +description = "Code audit tool for python" +optional = false +python-versions = ">=3.7" +files = [ + {file = "pylama-8.4.1-py3-none-any.whl", hash = "sha256:5bbdbf5b620aba7206d688ed9fc917ecd3d73e15ec1a89647037a09fa3a86e60"}, + {file = "pylama-8.4.1.tar.gz", hash = "sha256:2d4f7aecfb5b7466216d48610c7d6bad1c3990c29cdd392ad08259b161e486f6"}, +] + +[package.dependencies] +mccabe = ">=0.7.0" +pycodestyle = ">=2.9.1" +pydocstyle = ">=6.1.1" +pyflakes = ">=2.5.0" + +[package.extras] +all = ["eradicate", "mypy", "pylint", "radon", "vulture"] +eradicate = ["eradicate"] +mypy = ["mypy"] +pylint = ["pylint"] +radon = ["radon"] +tests = ["eradicate (>=2.0.0)", "mypy", "pylama-quotes", "pylint (>=2.11.1)", "pytest (>=7.1.2)", "pytest-mypy", "radon (>=5.1.0)", "toml", "types-setuptools", "types-toml", "vulture"] +toml = ["toml (>=0.10.2)"] +vulture = ["vulture"] + [[package]] name = "pytest" version = "8.2.0" @@ -484,6 +619,37 @@ urllib3 = ">=1.21.1,<3" socks = ["PySocks (>=1.5.6,!=1.5.7)"] use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] +[[package]] +name = "setuptools" +version = "75.1.0" +description = "Easily download, build, install, upgrade, and uninstall Python packages" +optional = false +python-versions = ">=3.8" +files = [ + {file = "setuptools-75.1.0-py3-none-any.whl", hash = "sha256:35ab7fd3bcd95e6b7fd704e4a1539513edad446c097797f2985e0e4b960772f2"}, + {file = "setuptools-75.1.0.tar.gz", hash = "sha256:d59a21b17a275fb872a9c3dae73963160ae079f1049ed956880cd7c09b120538"}, +] + +[package.extras] +check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)", "ruff (>=0.5.2)"] +core = ["importlib-metadata (>=6)", "importlib-resources (>=5.10.2)", "jaraco.collections", "jaraco.functools", "jaraco.text (>=3.7)", "more-itertools", "more-itertools (>=8.8)", "packaging", "packaging (>=24)", "platformdirs (>=2.6.2)", "tomli (>=2.0.1)", "wheel (>=0.43.0)"] +cover = ["pytest-cov"] +doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "pyproject-hooks (!=1.1)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier", "towncrier (<24.7)"] +enabler = ["pytest-enabler (>=2.2)"] +test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "jaraco.test", "packaging (>=23.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-home (>=0.5)", "pytest-perf", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel (>=0.44.0)"] +type = ["importlib-metadata (>=7.0.2)", "jaraco.develop (>=7.21)", "mypy (==1.11.*)", "pytest-mypy"] + +[[package]] +name = "snowballstemmer" +version = "2.2.0" +description = "This package provides 29 stemmers for 28 languages generated from Snowball algorithms." +optional = false +python-versions = "*" +files = [ + {file = "snowballstemmer-2.2.0-py2.py3-none-any.whl", hash = "sha256:c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a"}, + {file = "snowballstemmer-2.2.0.tar.gz", hash = "sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1"}, +] + [[package]] name = "tomli" version = "2.0.2" @@ -526,4 +692,4 @@ zstd = ["zstandard (>=0.18.0)"] [metadata] lock-version = "2.0" python-versions = ">=3.8,<4" -content-hash = "e5efdf7c742b61a7695d59138c4a0c143304841128ac63acb63380b0226e8268" +content-hash = "8692848e7f098b229f3385598f21a1f128085587fb650d242c96e39a08b884c2" diff --git a/pyproject.toml b/pyproject.toml index 3c37376..7998504 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -45,6 +45,9 @@ pytest = ">=8.2.0,<8.3.0" aiomisc-pytest = "^1.2.1" pytest-cov = "^5.0.0" coveralls = "<4" +pylama = "^8.4.1" +setuptools = "^75.1.0" +mypy = "^1.11.2" [build-system] requires = ["poetry-core"] @@ -64,12 +67,22 @@ strict_optional = true warn_redundant_casts = true warn_unused_configs = true warn_unused_ignores = true +files = [ + "aiofile", + "tests", +] -[tool.mypy.tests] -ignore_errors = true +[[tool.mypy.overrides]] +module = ["tests.*"] +check_untyped_defs = true +disallow_incomplete_defs = false +disallow_untyped_calls = false +disallow_untyped_decorators = false +disallow_untyped_defs = false +warn_unused_ignores = false [tool.pylama] -skip = ["env*", ".tox*", "*build*"] +skip = ["*env*", ".*", "*build*"] [tool.pylama.pycodestyle] max_line_length = 80 diff --git a/tests/conftest.py b/tests/conftest.py index 6dd80d7..4d9d04d 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,4 +1,6 @@ from functools import partial +from types import ModuleType +from typing import List, Union import pytest from caio import python_aio_asyncio @@ -9,35 +11,37 @@ try: from caio import thread_aio_asyncio except ImportError: - thread_aio_asyncio = None + thread_aio_asyncio = None # type: ignore try: from caio import linux_aio_asyncio except ImportError: - linux_aio_asyncio = None + linux_aio_asyncio = None # type: ignore -class DefaultContext: - __name__ = "default" - - -IMPLEMENTATIONS = list( +IMPLEMENTATIONS: List[Union[ModuleType, None]] = list( filter( None, [ linux_aio_asyncio, thread_aio_asyncio, python_aio_asyncio, - DefaultContext(), ], ), ) -IMPLEMENTATION_NAMES = map(lambda x: x.__name__, IMPLEMENTATIONS) +IMPLEMENTATIONS.insert(0, None) + +IMPLEMENTATION_NAMES: List[str] = list( + map( + lambda x: x.__name__ if x is not None else "default", + IMPLEMENTATIONS + ) +) @pytest.fixture(params=IMPLEMENTATIONS, ids=IMPLEMENTATION_NAMES) async def aio_context(request, event_loop): - if isinstance(request.param, DefaultContext): + if request.param is None: yield None return diff --git a/tests/test_aio.py b/tests/test_aio.py index cc34562..6600aff 100644 --- a/tests/test_aio.py +++ b/tests/test_aio.py @@ -9,8 +9,8 @@ from unittest.mock import Mock, call from uuid import uuid4 -import caio -import pytest +import caio # type: ignore +import pytest # type: ignore from aiofile import AIOFile from aiofile.utils import ( @@ -236,6 +236,8 @@ async def test_line_reader(aio_file_maker, temp_file, uuid): chunk = b64encode(os.urandom(max_length)).decode() lines = [chunk[:i] for i in range(max_length)] + line: str | bytes + for line in lines: await writer(line) await writer("\n") diff --git a/tox.ini b/tox.ini deleted file mode 100644 index 497a974..0000000 --- a/tox.ini +++ /dev/null @@ -1,36 +0,0 @@ -[tox] -envlist = lint,py3{8-13},readme - -[testenv] -passenv = COVERALLS_*, GITHUB_* - -extras = - develop - -commands= - - -[testenv:lint] -deps = - pyflakes~=2.4.0 - pylama - -commands= - pylama -o pylama.ini . - -[testenv:checkdoc] -deps = - collective.checkdocs - pygments - -commands = - python setup.py checkdocs - -[testenv:mypy] -usedevelop = true - -deps = - mypy - -commands = - mypy aiofile