Skip to content

Commit 0b10287

Browse files
TheMatt2pre-commit-ci[bot]gaborbernat
authored
Properly pickle of Timeout objects + test cases (#203)
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Bernát Gábor <[email protected]>
1 parent 66b2d49 commit 0b10287

File tree

4 files changed

+54
-6
lines changed

4 files changed

+54
-6
lines changed

docs/changelog.rst

+7-3
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,20 @@
11
Changelog
22
=========
3+
v3.10.1 (2023-03-22)
4+
--------------------
5+
- Handle pickle for :class:`filelock.Timeout` :pr:`203` - by :user:`TheMatt2`.
6+
37
v3.10.0 (2023-03-15)
4-
-------------------
5-
- Add support for explicit file modes for lockfiles :pr:`192 - by :user:`jahrules`.
8+
--------------------
9+
- Add support for explicit file modes for lockfiles :pr:`192` - by :user:`jahrules`.
610

711
v3.9.1 (2023-03-14)
812
-------------------
913
- Use ``time.perf_counter`` instead of ``time.monotonic`` for calculating timeouts.
1014

1115
v3.9.0 (2022-12-28)
1216
-------------------
13-
- Move build backend to ``hatchling`` :pr:`185 - by :user:`gaborbernat`.
17+
- Move build backend to ``hatchling`` :pr:`185` - by :user:`gaborbernat`.
1418

1519
v3.8.1 (2022-12-04)
1620
-------------------

pyproject.toml

+1
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ line-length = 120
7171
[tool.isort]
7272
profile = "black"
7373
known_first_party = ["filelock"]
74+
add_imports = ["from __future__ import annotations"]
7475

7576
[tool.mypy]
7677
python_version = "3.11"

src/filelock/_error.py

+16-3
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,28 @@
11
from __future__ import annotations
22

3+
from typing import Any
4+
35

46
class Timeout(TimeoutError):
57
"""Raised when the lock could not be acquired in *timeout* seconds."""
68

79
def __init__(self, lock_file: str) -> None:
8-
#: The path of the file lock.
9-
self.lock_file = lock_file
10+
super().__init__()
11+
self._lock_file = lock_file
12+
13+
def __reduce__(self) -> str | tuple[Any, ...]:
14+
return self.__class__, (self._lock_file,) # Properly pickle the exception
1015

1116
def __str__(self) -> str:
12-
return f"The file lock '{self.lock_file}' could not be acquired."
17+
return f"The file lock '{self._lock_file}' could not be acquired."
18+
19+
def __repr__(self) -> str:
20+
return f"{self.__class__.__name__}({self.lock_file!r})"
21+
22+
@property
23+
def lock_file(self) -> str:
24+
""":return: The path of the file lock."""
25+
return self._lock_file
1326

1427

1528
__all__ = [

tests/test_error.py

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
from __future__ import annotations
2+
3+
import pickle
4+
5+
from filelock import Timeout
6+
7+
8+
def test_timeout_str() -> None:
9+
timeout = Timeout("/path/to/lock")
10+
assert str(timeout) == "The file lock '/path/to/lock' could not be acquired."
11+
12+
13+
def test_timeout_repr() -> None:
14+
timeout = Timeout("/path/to/lock")
15+
assert repr(timeout) == "Timeout('/path/to/lock')"
16+
17+
18+
def test_timeout_lock_file() -> None:
19+
timeout = Timeout("/path/to/lock")
20+
assert timeout.lock_file == "/path/to/lock"
21+
22+
23+
def test_timeout_pickle() -> None:
24+
timeout = Timeout("/path/to/lock")
25+
timeout_loaded = pickle.loads(pickle.dumps(timeout))
26+
27+
assert timeout.__class__ == timeout_loaded.__class__
28+
assert str(timeout) == str(timeout_loaded)
29+
assert repr(timeout) == repr(timeout_loaded)
30+
assert timeout.lock_file == timeout_loaded.lock_file

0 commit comments

Comments
 (0)