diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 4b19a74..f681e6c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -11,18 +11,15 @@ jobs: strategy: matrix: python: - - "3.7" - - "3.8" - "3.9" - "3.10" - "3.11" - - "pypy-3.7" - - "pypy-3.8" - - "pypy-3.9" + - "pypy-3.10" + - "pypy-3.11" steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v5 - name: Setup Python ${{ matrix.python }} - uses: actions/setup-python@v4 + uses: actions/setup-python@v6 with: python-version: ${{ matrix.python }} - name: Install dependencies @@ -36,9 +33,9 @@ jobs: matrix: env: [generate-integration-files, type, lint, format] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v5 - name: Setup Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v6 with: python-version: "3.11" - name: Install dependencies @@ -50,18 +47,18 @@ jobs: needs: [tests-py, tests-misc] runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v5 with: # fetch all commits for setuptools_scm fetch-depth: 0 - name: Setup Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v6 with: python-version: "3.11" - name: Build run: python setup.py sdist bdist_wheel - name: Save build artifacts - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: dist path: dist @@ -72,7 +69,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Restore build artifacts - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v5 with: name: dist path: dist diff --git a/CHANGELOG.md b/CHANGELOG.md index 3667d9b..7e11e22 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,21 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/), and this project adheres to [Semantic Versioning](https://semver.org/). +## [Unreleased] + +[unreleased]: https://github.com/rogdham/python-xz/compare/v0.5.0...HEAD + +### :boom: Breaking changes + +- End of Python 3.7 and 3.8 support + +### :house: Internal + +- Fix test xz files generation for xz-utils 5.5.1+ +- Freeze dev dependencies versions +- Update GitHub actions dependencies +- Add tests for PyPy 3.10 and 3.11 + ## [0.5.0] - 2023-02-27 [0.5.0]: https://github.com/rogdham/python-xz/releases/tag/v0.5.0 @@ -19,7 +34,7 @@ adheres to [Semantic Versioning](https://semver.org/). - Refactor a descriptor following PEP 487 - Add tests for CPython 3.11 and PyPy 3.9 - Use CPython 3.11 for misc. tests -- Update Github actions dependencies +- Update GitHub actions dependencies - Import typing modules impacted by PEP 585 based on Python version ## [0.4.0] - 2022-01-09 diff --git a/dev-requirements.txt b/dev-requirements.txt index 6fc9ef6..4aa65b3 100644 --- a/dev-requirements.txt +++ b/dev-requirements.txt @@ -2,20 +2,19 @@ -e . # typing -mypy +mypy==1.0.1 # tests -coverage -pytest -pytest-cov +pytest==7.2.1 +pytest-cov==4.0.0 # lint -pylint +pylint==2.16.2 # format -black -isort +black==23.1.0 +isort==5.12.0 # publish -setuptools_scm -wheel +setuptools_scm==7.1.0 +wheel==0.38.4 diff --git a/pytest.ini b/pytest.ini index 96798ad..89e354b 100644 --- a/pytest.ini +++ b/pytest.ini @@ -4,8 +4,6 @@ addopts = --strict-markers filterwarnings = error - # issue in standard lib for PyPy < 3.9 - ignore:Using or importing the ABCs from 'collections':DeprecationWarning:_lzma markers = generate_integration_files integration diff --git a/setup.cfg b/setup.cfg index fa04bdb..a1cdc01 100644 --- a/setup.cfg +++ b/setup.cfg @@ -19,8 +19,6 @@ classifiers = Programming Language :: Python Programming Language :: Python :: 3 Programming Language :: Python :: 3 :: Only - 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 @@ -32,9 +30,7 @@ classifiers = include_package_data = True package_dir = =src packages = xz -python_requires = >=3.7 +python_requires = >=3.9 setup_requires = setuptools_scm wheel -install_requires = - typing-extensions>=4.5.0;python_version<"3.8" diff --git a/src/xz/typing.py b/src/xz/typing.py index 7e8fefc..b2e2072 100644 --- a/src/xz/typing.py +++ b/src/xz/typing.py @@ -1,21 +1,8 @@ +from collections.abc import Mapping, Sequence from os import PathLike -import sys -from typing import TYPE_CHECKING, Any, BinaryIO, Optional, Union +from typing import TYPE_CHECKING, Any, BinaryIO, Literal, Optional, Protocol, Union -if sys.version_info >= (3, 9): # pragma: no cover - from collections.abc import Mapping, Sequence - - _LZMAFilenameType = Union[str, bytes, PathLike[str], PathLike[bytes], BinaryIO] -else: # pragma: no cover - from typing import Mapping, Sequence - - _LZMAFilenameType = Union[str, bytes, PathLike, BinaryIO] - - -if sys.version_info >= (3, 8): # pragma: no cover - from typing import Literal, Protocol -else: # pragma: no cover - from typing_extensions import Literal, Protocol +_LZMAFilenameType = Union[str, bytes, PathLike[str], PathLike[bytes], BinaryIO] if TYPE_CHECKING: # pragma: no cover diff --git a/src/xz/utils.py b/src/xz/utils.py index 63e3739..20220c0 100644 --- a/src/xz/utils.py +++ b/src/xz/utils.py @@ -1,13 +1,7 @@ from bisect import bisect_right, insort_right -import sys +from collections.abc import Iterator, MutableMapping from typing import Any, Dict, Generic, List, Tuple, TypeVar, cast -if sys.version_info >= (3, 9): # pragma: no cover - from collections.abc import Iterator, MutableMapping -else: # pragma: no cover - from typing import Iterator, MutableMapping - - T = TypeVar("T") diff --git a/tests/conftest.py b/tests/conftest.py index 475dadb..5586dae 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,15 +1,10 @@ +from collections.abc import Callable, Iterator from itertools import chain, product from pathlib import Path -import sys from typing import List, Tuple import pytest -if sys.version_info >= (3, 9): # pragma: no cover - from collections.abc import Callable, Iterator -else: # pragma: no cover - from typing import Callable, Iterator - def pytest_addoption(parser: pytest.Parser) -> None: parser.addoption( diff --git a/tests/integration/files/check-crc32.json b/tests/integration/files/check-crc32.json index 7723ab9..bbf3c1d 100644 --- a/tests/integration/files/check-crc32.json +++ b/tests/integration/files/check-crc32.json @@ -1,7 +1,7 @@ { "generate": [ { - "cmd": "xz -C crc32", + "cmd": "xz -T1 -C crc32", "length": 20280 } ], diff --git a/tests/integration/files/check-crc64.json b/tests/integration/files/check-crc64.json index c1a925a..9ad1522 100644 --- a/tests/integration/files/check-crc64.json +++ b/tests/integration/files/check-crc64.json @@ -1,7 +1,7 @@ { "generate": [ { - "cmd": "xz -C crc64", + "cmd": "xz -T1 -C crc64", "length": 20280 } ], diff --git a/tests/integration/files/check-none.json b/tests/integration/files/check-none.json index 63f0f19..d9b0bf8 100644 --- a/tests/integration/files/check-none.json +++ b/tests/integration/files/check-none.json @@ -1,7 +1,7 @@ { "generate": [ { - "cmd": "xz -C none", + "cmd": "xz -T1 -C none", "length": 20280 } ], diff --git a/tests/integration/files/check-sha256.json b/tests/integration/files/check-sha256.json index c0178ce..8a58c83 100644 --- a/tests/integration/files/check-sha256.json +++ b/tests/integration/files/check-sha256.json @@ -1,7 +1,7 @@ { "generate": [ { - "cmd": "xz -C sha256", + "cmd": "xz -T1 -C sha256", "length": 20280 } ], diff --git a/tests/integration/files/few-blocks.json b/tests/integration/files/few-blocks.json index bb0e00e..71c2450 100644 --- a/tests/integration/files/few-blocks.json +++ b/tests/integration/files/few-blocks.json @@ -1,7 +1,7 @@ { "generate": [ { - "cmd": "xz --block-size 10000", + "cmd": "xz -T1 --block-size 10000", "length": 20280 } ], diff --git a/tests/integration/files/many-blocks.json b/tests/integration/files/many-blocks.json index 0812bc4..4eb16a8 100644 --- a/tests/integration/files/many-blocks.json +++ b/tests/integration/files/many-blocks.json @@ -1,7 +1,7 @@ { "generate": [ { - "cmd": "xz --block-size 100", + "cmd": "xz -T1 --block-size 100", "length": 20280 } ], diff --git a/tests/integration/files/one-stream-with-padding.json b/tests/integration/files/one-stream-with-padding.json index 599f92c..7aee581 100644 --- a/tests/integration/files/one-stream-with-padding.json +++ b/tests/integration/files/one-stream-with-padding.json @@ -1,7 +1,7 @@ { "generate": [ { - "cmd": "xz --block-size 15000", + "cmd": "xz -T1 --block-size 15000", "length": 20280 }, { diff --git a/tests/integration/files/several-filters.json b/tests/integration/files/several-filters.json index 103de9c..4d1b818 100644 --- a/tests/integration/files/several-filters.json +++ b/tests/integration/files/several-filters.json @@ -1,7 +1,7 @@ { "generate": [ { - "cmd": "xz --x86=start=42 --delta=dist=3 --powerpc --lzma2", + "cmd": "xz -T1 --x86=start=42 --delta=dist=3 --powerpc --lzma2", "length": 20280 } ], diff --git a/tests/integration/files/several-streams-with-padding.json b/tests/integration/files/several-streams-with-padding.json index ddd0610..0b363a0 100644 --- a/tests/integration/files/several-streams-with-padding.json +++ b/tests/integration/files/several-streams-with-padding.json @@ -1,21 +1,21 @@ { "generate": [ { - "cmd": "xz --block-size 1000", + "cmd": "xz -T1 --block-size 1000", "length": 1500 }, { "cmd": "head -c 100 /dev/zero" }, { - "cmd": "xz", + "cmd": "xz -T1", "length": 2000 }, { "cmd": "head -c 200 /dev/zero" }, { - "cmd": "xz --block-size 4000", + "cmd": "xz -T1 --block-size 4000", "length": 16780 }, { diff --git a/tests/integration/files/several-streams.json b/tests/integration/files/several-streams.json index 1c37ca9..068072c 100644 --- a/tests/integration/files/several-streams.json +++ b/tests/integration/files/several-streams.json @@ -1,15 +1,15 @@ { "generate": [ { - "cmd": "xz --block-size 5000", + "cmd": "xz -T1 --block-size 5000", "length": 17000 }, { - "cmd": "xz --block-size 1000", + "cmd": "xz -T1 --block-size 1000", "length": 2100 }, { - "cmd": "xz", + "cmd": "xz -T1", "length": 1180 } ], diff --git a/tests/integration/files/various-block-sizes.json b/tests/integration/files/various-block-sizes.json index 834a8db..c95aec2 100644 --- a/tests/integration/files/various-block-sizes.json +++ b/tests/integration/files/various-block-sizes.json @@ -1,7 +1,7 @@ { "generate": [ { - "cmd": "xz --block-list 1234,567,8901,234,5678,90,0", + "cmd": "xz -T1 --block-list 1234,567,8901,234,5678,90,0", "length": 20280 } ], diff --git a/tests/integration/files/various-stream-checks-stream-padding-and-block-sizes.json b/tests/integration/files/various-stream-checks-stream-padding-and-block-sizes.json index 46dc530..504668b 100644 --- a/tests/integration/files/various-stream-checks-stream-padding-and-block-sizes.json +++ b/tests/integration/files/various-stream-checks-stream-padding-and-block-sizes.json @@ -1,25 +1,25 @@ { "generate": [ { - "cmd": "xz -C none --block-list 100,1000,200,2000,0", + "cmd": "xz -T1 -C none --block-list 100,1000,200,2000,0", "length": 3600 }, { "cmd": "head -c 100 /dev/zero" }, { - "cmd": "xz -C crc32", + "cmd": "xz -T1 -C crc32", "length": 10000 }, { "cmd": "head -c 800 /dev/zero" }, { - "cmd": "xz -C crc64 --block-list 3000,300,0", + "cmd": "xz -T1 -C crc64 --block-list 3000,300,0", "length": 3333 }, { - "cmd": "xz -C sha256 --block-size 600", + "cmd": "xz -T1 -C sha256 --block-size 600", "length": 3347 }, { diff --git a/tests/integration/files/various-stream-checks.json b/tests/integration/files/various-stream-checks.json index c58fe47..fad73a6 100644 --- a/tests/integration/files/various-stream-checks.json +++ b/tests/integration/files/various-stream-checks.json @@ -1,19 +1,19 @@ { "generate": [ { - "cmd": "xz -C none", + "cmd": "xz -T1 -C none", "length": 5070 }, { - "cmd": "xz -C crc32", + "cmd": "xz -T1 -C crc32", "length": 5070 }, { - "cmd": "xz -C crc64", + "cmd": "xz -T1 -C crc64", "length": 5070 }, { - "cmd": "xz -C sha256", + "cmd": "xz -T1 -C sha256", "length": 5070 } ], diff --git a/tests/integration/test_ram_usage.py b/tests/integration/test_ram_usage.py index 35806f1..8a17cbb 100644 --- a/tests/integration/test_ram_usage.py +++ b/tests/integration/test_ram_usage.py @@ -1,8 +1,8 @@ +from collections.abc import Callable, Iterator from io import DEFAULT_BUFFER_SIZE from lzma import compress from pathlib import Path -from random import seed -import sys +from random import randbytes, seed from typing import BinaryIO, Optional, cast import pytest @@ -11,16 +11,6 @@ from xz.common import create_xz_index_footer, parse_xz_footer, parse_xz_index from xz.io import IOCombiner, IOStatic -if sys.version_info >= (3, 9): - from collections.abc import Callable, Iterator - from random import randbytes -else: - from random import getrandbits - from typing import Callable, Iterator - - def randbytes(length: int) -> bytes: - return getrandbits(length * 8).to_bytes(length, "little") - @pytest.fixture def ram_usage() -> Iterator[Callable[[], int]]: diff --git a/tests/integration/test_readme.py b/tests/integration/test_readme.py index 50ae003..c3e5aa9 100644 --- a/tests/integration/test_readme.py +++ b/tests/integration/test_readme.py @@ -1,19 +1,14 @@ +from collections.abc import Iterator import doctest import os from pathlib import Path import shutil -import sys from typing import List, Optional, Tuple import pytest import xz -if sys.version_info >= (3, 9): # pragma: no cover - from collections.abc import Iterator -else: # pragma: no cover - from typing import Iterator - @pytest.fixture(autouse=True) def change_dir(tmp_path: Path) -> Iterator[None]: diff --git a/tests/unit/test_block.py b/tests/unit/test_block.py index 7367fe0..3a4acfb 100644 --- a/tests/unit/test_block.py +++ b/tests/unit/test_block.py @@ -1,5 +1,5 @@ +from collections.abc import Callable, Iterator from io import SEEK_SET, BytesIO, UnsupportedOperation -import sys from typing import Tuple, cast from unittest.mock import Mock, call @@ -10,12 +10,6 @@ from xz.common import XZError, create_xz_header, create_xz_index_footer from xz.io import IOAbstract, IOStatic -if sys.version_info >= (3, 9): # pragma: no cover - from collections.abc import Callable, Iterator -else: # pragma: no cover - from typing import Callable, Iterator - - BLOCK_BYTES = bytes.fromhex( "0200210116000000742fe5a3e0006300415d00209842100431d01ab285328305" "7ddb5924a128599cc9911a7fcff8d59c1f6f887bcee97b1f83f1808f005de273" diff --git a/tests/unit/test_file.py b/tests/unit/test_file.py index 4ec939d..869d0b7 100644 --- a/tests/unit/test_file.py +++ b/tests/unit/test_file.py @@ -1,7 +1,7 @@ +from collections.abc import Callable from io import SEEK_END, SEEK_SET, BytesIO, UnsupportedOperation import os from pathlib import Path -import sys from typing import Optional, Tuple, Union, cast from unittest.mock import Mock, call @@ -11,12 +11,6 @@ from xz.file import XZFile from xz.strategy import RollingBlockReadStrategy -if sys.version_info >= (3, 9): # pragma: no cover - from collections.abc import Callable -else: # pragma: no cover - from typing import Callable - - FILE_BYTES = bytes.fromhex( # stream 1: two blocks (lengths: 100, 90) "fd377a585a0000016922de360200210116000000742fe5a3e0006300415d0020" diff --git a/tests/unit/test_parse_mode.py b/tests/unit/test_parse_mode.py index 6ccc13f..cda1d73 100644 --- a/tests/unit/test_parse_mode.py +++ b/tests/unit/test_parse_mode.py @@ -1,5 +1,4 @@ from itertools import permutations, product -import sys from typing import Tuple try: @@ -26,20 +25,12 @@ } -@pytest.mark.skipif( - sys.version_info < (3, 9), - reason="Literal or get_args not supported", -) def test_known_valid_modes_binary() -> None: assert sorted( "".join(sorted(mode)) for mode in get_args(_XZModesBinaryType) ) == sorted(VALID_MODES) -@pytest.mark.skipif( - sys.version_info < (3, 9), - reason="Literal or get_args not supported", -) def test_known_valid_modes_text() -> None: assert sorted( "".join(sorted(mode.replace("t", ""))) for mode in get_args(_XZModesTextType) diff --git a/tests/unit/test_stream.py b/tests/unit/test_stream.py index bb4cd6d..865f3ef 100644 --- a/tests/unit/test_stream.py +++ b/tests/unit/test_stream.py @@ -1,5 +1,5 @@ +from collections.abc import Callable from io import SEEK_CUR, SEEK_END, BytesIO -import sys from typing import Tuple, cast from unittest.mock import Mock, call @@ -9,12 +9,6 @@ from xz.io import IOProxy from xz.stream import XZStream -if sys.version_info >= (3, 9): # pragma: no cover - from collections.abc import Callable -else: # pragma: no cover - from typing import Callable - - # a stream with two blocks (lengths: 100, 90) STREAM_BYTES = bytes.fromhex( "fd377a585a0000016922de360200210116000000742fe5a3e0006300415d0020" diff --git a/tox.ini b/tox.ini index 569160d..3997ce6 100644 --- a/tox.ini +++ b/tox.ini @@ -1,12 +1,12 @@ [tox] envlist = - py, py37, py38, py39, py310, py311, pypy3 + py, py39, py310, py311, pypy3 generate-integration-files, type, lint, format [testenv] deps = - pytest - pytest-cov + pytest==7.2.1 + pytest-cov==4.0.0 passenv = PY_COLORS setenv = COVERAGE_FILE = {toxworkdir}/{envname}/.coverage @@ -16,9 +16,10 @@ commands = py: -coverage html [testenv:generate-integration-files] +basepython = python3.11 deps = - pytest - pytest-cov + pytest==7.2.1 + pytest-cov==4.0.0 passenv = PY_COLORS setenv = PYTEST_ADDOPTS = --no-cov @@ -26,26 +27,29 @@ setenv = commands = pytest -vv -m generate_integration_files --generate-integration-files [testenv:type] +basepython = python3.11 deps = - mypy - pytest # for typing + mypy==1.0.1 + pytest==7.2.1 # for typing commands = mypy mypy --namespace-packages --explicit-package-bases tests [testenv:lint] +basepython = python3.11 deps = - pylint - pytest # to avoid import errors + pylint==2.16.2 + pytest==7.2.1 # to avoid import errors commands = pylint src pylint -d duplicate-code,too-many-statements,use-implicit-booleaness-not-comparison tests [testenv:format] +basepython = python3.11 skip_install = true deps = - black - isort + black==23.1.0 + isort==5.12.0 commands = black {posargs:--check --diff} src tests isort {posargs:--check --diff} src tests