Skip to content

Commit 82f66d7

Browse files
lprnmnsgaborbernat
andauthored
🐛 fix(lease): reject a duration no marker can carry (#723)
Co-authored-by: BernĂĄt GĂĄbor <gaborjbernat@gmail.com>
1 parent 1d9e9e7 commit 82f66d7

3 files changed

Lines changed: 25 additions & 10 deletions

File tree

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
``SoftFileLease`` and ``AsyncSoftFileLease`` now reject a boolean or non-finite ``lease_duration``, which used to
2+
publish an owner record their own ``owner`` property reads back as malformed.

‎src/filelock/_lease.py‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import time
66
from contextlib import suppress
77
from dataclasses import dataclass
8+
from math import isfinite
89
from threading import Event, Thread, current_thread, local
910
from typing import TYPE_CHECKING, Literal
1011

@@ -131,8 +132,11 @@ def __init__(
131132
hide.
132133
133134
"""
134-
if lease_duration <= 0:
135-
msg = f"lease_duration must be positive, got {lease_duration!r}"
135+
if isinstance(lease_duration, bool) or not isinstance(lease_duration, (int, float)):
136+
msg = f"lease_duration must be a finite positive number, not {type(lease_duration).__name__}"
137+
raise TypeError(msg)
138+
if not isfinite(lease_duration) or lease_duration <= 0:
139+
msg = f"lease_duration must be positive and finite, got {lease_duration!r}"
136140
raise ValueError(msg)
137141
if heartbeat_interval is None:
138142
heartbeat_interval = lease_duration / 3

‎tests/test_soft_lease.py‎

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -406,19 +406,28 @@ def test_lease_does_not_expire_a_strict_holder(marker: Path) -> None: # pragma:
406406

407407

408408
@pytest.mark.parametrize(
409-
("lease_duration", "heartbeat_interval", "message"),
409+
("lease_duration", "heartbeat_interval", "error", "message"),
410410
[
411-
pytest.param(0, None, "lease_duration must be positive", id="zero-duration"),
412-
pytest.param(-1, None, "lease_duration must be positive", id="negative-duration"),
413-
pytest.param(_DURATION, 0, "heartbeat_interval must be positive", id="zero-heartbeat"),
414-
pytest.param(_DURATION, _DURATION, "below lease_duration", id="heartbeat-equals-duration"),
415-
pytest.param(_DURATION, _DURATION * 2, "below lease_duration", id="heartbeat-over-duration"),
411+
pytest.param(0, None, ValueError, "lease_duration must be positive", id="zero-duration"),
412+
pytest.param(-1, None, ValueError, "lease_duration must be positive", id="negative-duration"),
413+
pytest.param(float("nan"), _HEARTBEAT, ValueError, "positive and finite", id="nan-duration"),
414+
pytest.param(float("inf"), _HEARTBEAT, ValueError, "positive and finite", id="infinite-duration"),
415+
pytest.param(float("-inf"), _HEARTBEAT, ValueError, "positive and finite", id="negative-infinite-duration"),
416+
pytest.param(True, None, TypeError, "number, not bool", id="true-duration"),
417+
pytest.param(False, None, TypeError, "number, not bool", id="false-duration"),
418+
pytest.param(_DURATION, 0, ValueError, "heartbeat_interval must be positive", id="zero-heartbeat"),
419+
pytest.param(_DURATION, _DURATION, ValueError, "below lease_duration", id="heartbeat-equals-duration"),
420+
pytest.param(_DURATION, _DURATION * 2, ValueError, "below lease_duration", id="heartbeat-over-duration"),
416421
],
417422
)
418423
def test_lease_rejects_incoherent_settings(
419-
marker: Path, lease_duration: float, heartbeat_interval: float | None, message: str
424+
marker: Path,
425+
lease_duration: float,
426+
heartbeat_interval: float | None,
427+
error: type[Exception],
428+
message: str,
420429
) -> None:
421-
with pytest.raises(ValueError, match=message):
430+
with pytest.raises(error, match=message):
422431
SoftFileLease(str(marker), lease_duration=lease_duration, heartbeat_interval=heartbeat_interval)
423432

424433

0 commit comments

Comments
 (0)