diff --git a/docs/changelog.rst b/docs/changelog.rst index 62e717e4..6ac0f1b5 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -1,8 +1,12 @@ Changelog ========= +v3.10.1 (2023-03-22) +-------------------- +- Handle pickle for :class:`filelock.Timeout` :pr:`203` - by :user:`TheMatt2`. + v3.10.0 (2023-03-15) -------------------- -- Add support for explicit file modes for lockfiles :pr:`192 - by :user:`jahrules`. +-------------------- +- Add support for explicit file modes for lockfiles :pr:`192` - by :user:`jahrules`. v3.9.1 (2023-03-14) ------------------- @@ -10,7 +14,7 @@ v3.9.1 (2023-03-14) v3.9.0 (2022-12-28) ------------------- -- Move build backend to ``hatchling`` :pr:`185 - by :user:`gaborbernat`. +- Move build backend to ``hatchling`` :pr:`185` - by :user:`gaborbernat`. v3.8.1 (2022-12-04) ------------------- diff --git a/pyproject.toml b/pyproject.toml index c1b2de1c..da688b7b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -71,6 +71,7 @@ line-length = 120 [tool.isort] profile = "black" known_first_party = ["filelock"] +add_imports = ["from __future__ import annotations"] [tool.mypy] python_version = "3.11" diff --git a/src/filelock/_error.py b/src/filelock/_error.py index b3885214..e2bd6530 100644 --- a/src/filelock/_error.py +++ b/src/filelock/_error.py @@ -1,15 +1,28 @@ from __future__ import annotations +from typing import Any + class Timeout(TimeoutError): """Raised when the lock could not be acquired in *timeout* seconds.""" def __init__(self, lock_file: str) -> None: - #: The path of the file lock. - self.lock_file = lock_file + super().__init__() + self._lock_file = lock_file + + def __reduce__(self) -> str | tuple[Any, ...]: + return self.__class__, (self._lock_file,) # Properly pickle the exception def __str__(self) -> str: - return f"The file lock '{self.lock_file}' could not be acquired." + return f"The file lock '{self._lock_file}' could not be acquired." + + def __repr__(self) -> str: + return f"{self.__class__.__name__}({self.lock_file!r})" + + @property + def lock_file(self) -> str: + """:return: The path of the file lock.""" + return self._lock_file __all__ = [ diff --git a/tests/test_error.py b/tests/test_error.py new file mode 100644 index 00000000..45e940e4 --- /dev/null +++ b/tests/test_error.py @@ -0,0 +1,30 @@ +from __future__ import annotations + +import pickle + +from filelock import Timeout + + +def test_timeout_str() -> None: + timeout = Timeout("/path/to/lock") + assert str(timeout) == "The file lock '/path/to/lock' could not be acquired." + + +def test_timeout_repr() -> None: + timeout = Timeout("/path/to/lock") + assert repr(timeout) == "Timeout('/path/to/lock')" + + +def test_timeout_lock_file() -> None: + timeout = Timeout("/path/to/lock") + assert timeout.lock_file == "/path/to/lock" + + +def test_timeout_pickle() -> None: + timeout = Timeout("/path/to/lock") + timeout_loaded = pickle.loads(pickle.dumps(timeout)) + + assert timeout.__class__ == timeout_loaded.__class__ + assert str(timeout) == str(timeout_loaded) + assert repr(timeout) == repr(timeout_loaded) + assert timeout.lock_file == timeout_loaded.lock_file