Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Drop 3.8 #388

Merged
merged 2 commits into from
Jan 21, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion .github/workflows/check.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ jobs:
- "3.11"
- "3.10"
- "3.9"
- "3.8"
os:
- ubuntu-latest
- windows-latest
Expand All @@ -52,17 +51,21 @@ jobs:
run: uv python install --python-preference only-managed ${{ matrix.py }}
- name: Setup test suite
run: tox run -vv --notest --skip-missing-interpreters false -e ${{ matrix.py }}
env:
UV_PYTHON_PREFERENCE: only-managed
- name: Run test suite
if: ${{ !startsWith(matrix.py, 'pypy')}}
run: tox run --skip-pkg-install -e ${{ matrix.py }}
env:
PYTEST_ADDOPTS: "-vv --durations=20"
DIFF_AGAINST: HEAD
UV_PYTHON_PREFERENCE: only-managed
- name: Run test suite without coverage
if: ${{ startsWith(matrix.py, 'pypy')}}
run: tox run --skip-pkg-install -e ${{ matrix.py }} --
env:
PYTEST_ADDOPTS: "-vv --durations=20"
UV_PYTHON_PREFERENCE: only-managed
- name: Rename coverage report file
if: ${{ !startsWith(matrix.py, 'pypy')}}
run: |
Expand Down Expand Up @@ -102,6 +105,8 @@ jobs:
run: uv build --python 3.13 --python-preference only-managed --wheel . --out-dir dist
- name: Setup coverage tool
run: tox -e coverage --notest
env:
UV_PYTHON_PREFERENCE: only-managed
- name: Download coverage data
uses: actions/download-artifact@v4
with:
Expand All @@ -110,6 +115,8 @@ jobs:
merge-multiple: true
- name: Combine and report coverage
run: tox -e coverage --skip-pkg-install
env:
UV_PYTHON_PREFERENCE: only-managed
- name: Upload HTML report
uses: actions/upload-artifact@v4
with:
Expand Down Expand Up @@ -150,5 +157,9 @@ jobs:
run: uv tool install --python-preference only-managed --python 3.13 tox --with tox-uv
- name: Setup test suite
run: tox run -vv --notest --skip-missing-interpreters false -e ${{ matrix.tox_env }}
env:
UV_PYTHON_PREFERENCE: only-managed
- name: Run test suite
run: tox run --skip-pkg-install -e ${{ matrix.tox_env }}
env:
UV_PYTHON_PREFERENCE: only-managed
10 changes: 5 additions & 5 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,17 @@ repos:
- id: end-of-file-fixer
- id: trailing-whitespace
- repo: https://github.com/python-jsonschema/check-jsonschema
rev: 0.30.0
rev: 0.31.0
hooks:
- id: check-github-workflows
args: ["--verbose"]
- repo: https://github.com/codespell-project/codespell
rev: v2.3.0
hooks:
- id: codespell
additional_dependencies: ["tomli>=2.0.1"]
additional_dependencies: ["tomli>=2.2.1"]
- repo: https://github.com/tox-dev/tox-ini-fmt
rev: "1.4.1"
rev: "1.5.0"
hooks:
- id: tox-ini-fmt
args: ["-p", "fix"]
Expand All @@ -24,7 +24,7 @@ repos:
hooks:
- id: pyproject-fmt
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: "v0.8.3"
rev: "v0.9.2"
hooks:
- id: ruff-format
- id: ruff
Expand All @@ -34,7 +34,7 @@ repos:
hooks:
- id: prettier
additional_dependencies:
- prettier@3.3.3
- prettier@3.4.2
- "@prettier/[email protected]"
- repo: meta
hooks:
Expand Down
23 changes: 10 additions & 13 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
build-backend = "hatchling.build"
requires = [
"hatch-vcs>=0.4",
"hatchling>=1.25",
"hatchling>=1.27",
]

[project]
Expand All @@ -20,15 +20,14 @@ license = "Unlicense"
maintainers = [
{ name = "Bernát Gábor", email = "[email protected]" },
]
requires-python = ">=3.8"
requires-python = ">=3.9"
classifiers = [
"Development Status :: 5 - Production/Stable",
"Intended Audience :: Developers",
"License :: OSI Approved :: The Unlicense (Unlicense)",
"Operating System :: OS Independent",
"Programming Language :: Python",
"Programming Language :: Python :: 3 :: Only",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
Expand All @@ -43,19 +42,19 @@ dynamic = [
]
optional-dependencies.docs = [
"furo>=2024.8.6",
"sphinx>=8.0.2",
"sphinx-autodoc-typehints>=2.4.1",
"sphinx>=8.1.3",
"sphinx-autodoc-typehints>=3",
]
optional-dependencies.testing = [
"covdefaults>=2.3",
"coverage>=7.6.1",
"diff-cover>=9.2",
"pytest>=8.3.3",
"pytest-asyncio>=0.24",
"pytest-cov>=5",
"coverage>=7.6.10",
"diff-cover>=9.2.1",
"pytest>=8.3.4",
"pytest-asyncio>=0.25.2",
"pytest-cov>=6",
"pytest-mock>=3.14",
"pytest-timeout>=2.3.1",
"virtualenv>=20.26.4",
"virtualenv>=20.28.1",
]
optional-dependencies.typing = [
"typing-extensions>=4.12.2; python_version<'3.11'",
Expand All @@ -75,7 +74,6 @@ build.targets.sdist.include = [
version.source = "vcs"

[tool.ruff]
target-version = "py38"
line-length = 120
format.preview = true
format.docstring-code-line-length = 100
Expand All @@ -84,7 +82,6 @@ lint.select = [
"ALL",
]
lint.ignore = [
"ANN101", # Missing type annotation for `self` in method
"COM812", # Conflict with formatter
"CPY", # No copyright statements
"D203", # `one-blank-line-before-class` (D203) and `no-blank-line-before-class` (D211) are incompatible
Expand Down
14 changes: 7 additions & 7 deletions tests/test_async_filelock.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,46 +91,46 @@ async def test_non_blocking(lock_type: type[BaseAsyncFileLock], tmp_path: Path)
assert not lock_5.is_locked

# try to acquire lock 2
with pytest.raises(Timeout, match="The file lock '.*' could not be acquired."):
with pytest.raises(Timeout, match=r"The file lock '.*' could not be acquired."):
await lock_2.acquire(blocking=False)
assert not lock_2.is_locked
assert lock_1.is_locked

# try to acquire pre-parametrized `blocking=False` lock 3 with `acquire`
with pytest.raises(Timeout, match="The file lock '.*' could not be acquired."):
with pytest.raises(Timeout, match=r"The file lock '.*' could not be acquired."):
await lock_3.acquire()
assert not lock_3.is_locked
assert lock_1.is_locked

# try to acquire pre-parametrized `blocking=False` lock 3 with context manager
with pytest.raises(Timeout, match="The file lock '.*' could not be acquired."):
with pytest.raises(Timeout, match=r"The file lock '.*' could not be acquired."):
async with lock_3:
pass
assert not lock_3.is_locked
assert lock_1.is_locked

# try to acquire pre-parametrized `timeout=0` lock 4 with `acquire`
with pytest.raises(Timeout, match="The file lock '.*' could not be acquired."):
with pytest.raises(Timeout, match=r"The file lock '.*' could not be acquired."):
await lock_4.acquire()
assert not lock_4.is_locked
assert lock_1.is_locked

# try to acquire pre-parametrized `timeout=0` lock 4 with context manager
with pytest.raises(Timeout, match="The file lock '.*' could not be acquired."):
with pytest.raises(Timeout, match=r"The file lock '.*' could not be acquired."):
async with lock_4:
pass
assert not lock_4.is_locked
assert lock_1.is_locked

# blocking precedence over timeout
# try to acquire pre-parametrized `timeout=-1,blocking=False` lock 5 with `acquire`
with pytest.raises(Timeout, match="The file lock '.*' could not be acquired."):
with pytest.raises(Timeout, match=r"The file lock '.*' could not be acquired."):
await lock_5.acquire()
assert not lock_5.is_locked
assert lock_1.is_locked

# try to acquire pre-parametrized `timeout=-1,blocking=False` lock 5 with context manager
with pytest.raises(Timeout, match="The file lock '.*' could not be acquired."):
with pytest.raises(Timeout, match=r"The file lock '.*' could not be acquired."):
async with lock_5:
pass
assert not lock_5.is_locked
Expand Down
28 changes: 15 additions & 13 deletions tests/test_filelock.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from pathlib import Path, PurePath
from stat import S_IWGRP, S_IWOTH, S_IWUSR, filemode
from types import TracebackType
from typing import TYPE_CHECKING, Any, Callable, Iterator, Tuple, Type, Union
from typing import TYPE_CHECKING, Any, Callable, Union
from uuid import uuid4
from weakref import WeakValueDictionary

Expand All @@ -21,6 +21,8 @@
from filelock import BaseFileLock, FileLock, SoftFileLock, Timeout, UnixFileLock, WindowsFileLock

if TYPE_CHECKING:
from collections.abc import Iterator

from pytest_mock import MockerFixture


Expand Down Expand Up @@ -218,7 +220,7 @@ def test_nested_contruct(lock_type: type[BaseFileLock], tmp_path: Path) -> None:
assert not lock_1.is_locked


_ExcInfoType = Union[Tuple[Type[BaseException], BaseException, TracebackType], Tuple[None, None, None]]
_ExcInfoType = Union[tuple[type[BaseException], BaseException, TracebackType], tuple[None, None, None]]


class ExThread(threading.Thread):
Expand Down Expand Up @@ -304,7 +306,7 @@ def test_timeout(lock_type: type[BaseFileLock], tmp_path: Path) -> None:
assert not lock_2.is_locked

# try to acquire lock 2
with pytest.raises(Timeout, match="The file lock '.*' could not be acquired."):
with pytest.raises(Timeout, match=r"The file lock '.*' could not be acquired."):
lock_2.acquire(timeout=0.1)
assert not lock_2.is_locked
assert lock_1.is_locked
Expand Down Expand Up @@ -333,44 +335,44 @@ def test_non_blocking(lock_type: type[BaseFileLock], tmp_path: Path) -> None:
assert not lock_5.is_locked

# try to acquire lock 2
with pytest.raises(Timeout, match="The file lock '.*' could not be acquired."):
with pytest.raises(Timeout, match=r"The file lock '.*' could not be acquired."):
lock_2.acquire(blocking=False)
assert not lock_2.is_locked
assert lock_1.is_locked

# try to acquire pre-parametrized `blocking=False` lock 3 with `acquire`
with pytest.raises(Timeout, match="The file lock '.*' could not be acquired."):
with pytest.raises(Timeout, match=r"The file lock '.*' could not be acquired."):
lock_3.acquire()
assert not lock_3.is_locked
assert lock_1.is_locked

# try to acquire pre-parametrized `blocking=False` lock 3 with context manager
with pytest.raises(Timeout, match="The file lock '.*' could not be acquired."), lock_3:
with pytest.raises(Timeout, match=r"The file lock '.*' could not be acquired."), lock_3:
pass
assert not lock_3.is_locked
assert lock_1.is_locked

# try to acquire pre-parametrized `timeout=0` lock 4 with `acquire`
with pytest.raises(Timeout, match="The file lock '.*' could not be acquired."):
with pytest.raises(Timeout, match=r"The file lock '.*' could not be acquired."):
lock_4.acquire()
assert not lock_4.is_locked
assert lock_1.is_locked

# try to acquire pre-parametrized `timeout=0` lock 4 with context manager
with pytest.raises(Timeout, match="The file lock '.*' could not be acquired."), lock_4:
with pytest.raises(Timeout, match=r"The file lock '.*' could not be acquired."), lock_4:
pass
assert not lock_4.is_locked
assert lock_1.is_locked

# blocking precedence over timeout
# try to acquire pre-parametrized `timeout=-1,blocking=False` lock 5 with `acquire`
with pytest.raises(Timeout, match="The file lock '.*' could not be acquired."):
with pytest.raises(Timeout, match=r"The file lock '.*' could not be acquired."):
lock_5.acquire()
assert not lock_5.is_locked
assert lock_1.is_locked

# try to acquire pre-parametrized `timeout=-1,blocking=False` lock 5 with context manager
with pytest.raises(Timeout, match="The file lock '.*' could not be acquired."), lock_5:
with pytest.raises(Timeout, match=r"The file lock '.*' could not be acquired."), lock_5:
pass
assert not lock_5.is_locked
assert lock_1.is_locked
Expand All @@ -397,15 +399,15 @@ def test_default_timeout(lock_type: type[BaseFileLock], tmp_path: Path) -> None:
assert not lock_2.is_locked

# try to acquire lock 2
with pytest.raises(Timeout, match="The file lock '.*' could not be acquired."):
with pytest.raises(Timeout, match=r"The file lock '.*' could not be acquired."):
lock_2.acquire()
assert not lock_2.is_locked
assert lock_1.is_locked

lock_2.timeout = 0
assert lock_2.timeout == 0

with pytest.raises(Timeout, match="The file lock '.*' could not be acquired."):
with pytest.raises(Timeout, match=r"The file lock '.*' could not be acquired."):
lock_2.acquire()
assert not lock_2.is_locked
assert lock_1.is_locked
Expand Down Expand Up @@ -459,7 +461,7 @@ def test_del(lock_type: type[BaseFileLock], tmp_path: Path) -> None:
assert not lock_2.is_locked

# try to acquire lock 2
with pytest.raises(Timeout, match="The file lock '.*' could not be acquired."):
with pytest.raises(Timeout, match=r"The file lock '.*' could not be acquired."):
lock_2.acquire(timeout=0.1)

# delete lock 1 and try to acquire lock 2 again
Expand Down
19 changes: 9 additions & 10 deletions tox.ini
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
[tox]
requires =
tox>=4.2
tox-uv>=1.11.3
tox>=4.23.2
tox-uv>=1.17
env_list =
fix
3.13
3.12
3.11
3.10
3.9
3.8
type
coverage
docs
Expand Down Expand Up @@ -39,15 +38,15 @@ description = format the code base to adhere to our styles, and complain about w
base_python = python3.10
skip_install = true
deps =
pre-commit>=3.8
pre-commit>=4.0.1
commands =
pre-commit run --all-files --show-diff-on-failure
python -c 'import pathlib; print("hint: run \{\} install to add checks as pre-commit hook".format(pathlib.Path(r"{envdir}") / "bin" / "pre-commit"))'

[testenv:type]
description = run type check on code base
deps =
mypy==1.11.2
mypy==1.14.1
set_env =
{tty:MYPY_FORCE_COLOR = 1}
commands =
Expand All @@ -59,8 +58,8 @@ description = combine coverage files and generate diff (against DIFF_AGAINST def
skip_install = true
deps =
covdefaults>=2.3
coverage[toml]>=7.6.1
diff-cover>=9.2
coverage[toml]>=7.6.10
diff-cover>=9.2.1
extras =
parallel_show_output = true
pass_env =
Expand Down Expand Up @@ -93,9 +92,9 @@ commands =
description = check that the long description is valid
skip_install = true
deps =
check-wheel-contents>=0.6
twine>=5.1.1
uv>=0.4.10
check-wheel-contents>=0.6.1
twine>=6.0.1
uv>=0.5.18
commands =
uv build --sdist --wheel --out-dir {envtmpdir} .
twine check {envtmpdir}{/}*
Expand Down
Loading