From adefc41e4e909f3647d4eadb9bbb0f53de0f9f8c Mon Sep 17 00:00:00 2001 From: Ethan Blackwood Date: Wed, 12 Jun 2024 14:41:08 -0400 Subject: [PATCH 01/12] Restore __init__ method and use different strategy to bypass initialization --- src/filelock/_api.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/filelock/_api.py b/src/filelock/_api.py index b074c6d2..1af3637a 100644 --- a/src/filelock/_api.py +++ b/src/filelock/_api.py @@ -117,6 +117,9 @@ def __init_subclass__(cls, **kwargs: dict[str, Any]) -> None: super().__init_subclass__(**kwargs) cls._instances = WeakValueDictionary() + def __init__(self, *args, **kwargs): + pass # for backwards compatibility (don't break super().__init__ calls) + def _initialize( # noqa: PLR0913 self, lock_file: str | os.PathLike[str], From 0d3d1cbd7830a436223d4e93712e7116237de86b Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 12 Jun 2024 18:43:26 +0000 Subject: [PATCH 02/12] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- src/filelock/_api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/filelock/_api.py b/src/filelock/_api.py index 1af3637a..73d60908 100644 --- a/src/filelock/_api.py +++ b/src/filelock/_api.py @@ -117,7 +117,7 @@ def __init_subclass__(cls, **kwargs: dict[str, Any]) -> None: super().__init_subclass__(**kwargs) cls._instances = WeakValueDictionary() - def __init__(self, *args, **kwargs): + def __init__(self, *args, **kwargs) -> None: pass # for backwards compatibility (don't break super().__init__ calls) def _initialize( # noqa: PLR0913 From fa8fb4e41124bd39e2c6e89d28f6b5bb86732c71 Mon Sep 17 00:00:00 2001 From: Ethan Blackwood Date: Wed, 12 Jun 2024 14:44:09 -0400 Subject: [PATCH 03/12] Fix previous commit --- src/filelock/_api.py | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/filelock/_api.py b/src/filelock/_api.py index 1af3637a..593d078d 100644 --- a/src/filelock/_api.py +++ b/src/filelock/_api.py @@ -95,14 +95,11 @@ def __new__( # noqa: PLR0913 ) -> Self: """Create a new lock object or if specified return the singleton instance for the lock file.""" if not is_singleton: - self = super().__new__(cls) - self._initialize(lock_file, timeout, mode, thread_local, blocking=blocking, is_singleton=is_singleton) - return self + return super().__new__(cls) instance = cls._instances.get(str(lock_file)) if not instance: self = super().__new__(cls) - self._initialize(lock_file, timeout, mode, thread_local, blocking=blocking, is_singleton=is_singleton) cls._instances[str(lock_file)] = self return self @@ -117,10 +114,7 @@ def __init_subclass__(cls, **kwargs: dict[str, Any]) -> None: super().__init_subclass__(**kwargs) cls._instances = WeakValueDictionary() - def __init__(self, *args, **kwargs): - pass # for backwards compatibility (don't break super().__init__ calls) - - def _initialize( # noqa: PLR0913 + def __init__( # noqa: PLR0913 self, lock_file: str | os.PathLike[str], timeout: float = -1, @@ -146,6 +140,9 @@ def _initialize( # noqa: PLR0913 to pass the same object around. """ + if hasattr(self, '_context'): + return # bypass initialization because object is already initialized + self._is_thread_local = thread_local self._is_singleton = is_singleton From 42ee73031e3490773bcad99a8d039665c02bdcbe Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 12 Jun 2024 18:45:14 +0000 Subject: [PATCH 04/12] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- src/filelock/_api.py | 54 ++++++++++++++++++++++---------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/src/filelock/_api.py b/src/filelock/_api.py index 3d0cb1e9..5ca73a7a 100644 --- a/src/filelock/_api.py +++ b/src/filelock/_api.py @@ -114,22 +114,22 @@ def __init_subclass__(cls, **kwargs: dict[str, Any]) -> None: super().__init_subclass__(**kwargs) cls._instances = WeakValueDictionary() -<<<<<<< HEAD + +<< << << < HEAD def __init__( # noqa: PLR0913 -======= - def __init__(self, *args, **kwargs) -> None: +== == ===def __init__(self, *args, **kwargs) -> None: pass # for backwards compatibility (don't break super().__init__ calls) def _initialize( # noqa: PLR0913 ->>>>>>> 0d3d1cbd7830a436223d4e93712e7116237de86b +>> >> >> > 0d3d1cbd7830a436223d4e93712e7116237de86b self, lock_file: str | os.PathLike[str], - timeout: float = -1, - mode: int = 0o644, - thread_local: bool = True, # noqa: FBT001, FBT002 + timeout: float=-1, + mode: int=0o644, + thread_local: bool=True, # noqa: FBT001, FBT002 *, - blocking: bool = True, - is_singleton: bool = False, + blocking: bool=True, + is_singleton: bool=False, ) -> None: """ Create a new lock object. @@ -167,17 +167,17 @@ def is_thread_local(self) -> bool: """:return: a flag indicating if this lock is thread local or not""" return self._is_thread_local - @property + @ property def is_singleton(self) -> bool: """:return: a flag indicating if this lock is singleton or not""" return self._is_singleton - @property + @ property def lock_file(self) -> str: """:return: path to the lock file""" return self._context.lock_file - @property + @ property def timeout(self) -> float: """ :return: the default timeout value, in seconds @@ -186,7 +186,7 @@ def timeout(self) -> float: """ return self._context.timeout - @timeout.setter + @ timeout.setter def timeout(self, value: float | str) -> None: """ Change the default timeout value. @@ -196,12 +196,12 @@ def timeout(self, value: float | str) -> None: """ self._context.timeout = float(value) - @property + @ property def blocking(self) -> bool: """:return: whether the locking is blocking or not""" return self._context.blocking - @blocking.setter + @ blocking.setter def blocking(self, value: bool) -> None: """ Change the default blocking value. @@ -211,22 +211,22 @@ def blocking(self, value: bool) -> None: """ self._context.blocking = value - @property + @ property def mode(self) -> int: """:return: the file permissions for the lockfile""" return self._context.mode - @abstractmethod + @ abstractmethod def _acquire(self) -> None: """If the file lock could be acquired, self._context.lock_file_fd holds the file descriptor of the lock file.""" raise NotImplementedError - @abstractmethod + @ abstractmethod def _release(self) -> None: """Releases the lock and sets self._context.lock_file_fd to None.""" raise NotImplementedError - @property + @ property def is_locked(self) -> bool: """ @@ -238,18 +238,18 @@ def is_locked(self) -> bool: """ return self._context.lock_file_fd is not None - @property + @ property def lock_counter(self) -> int: """:return: The number of times this lock has been acquired (but not yet released).""" return self._context.lock_counter def acquire( self, - timeout: float | None = None, - poll_interval: float = 0.05, + timeout: float | None=None, + poll_interval: float=0.05, *, - poll_intervall: float | None = None, - blocking: bool | None = None, + poll_intervall: float | None=None, + blocking: bool | None=None, ) -> AcquireReturnProxy: """ Try to acquire the file lock. @@ -322,7 +322,7 @@ def acquire( raise return AcquireReturnProxy(lock=self) - def release(self, force: bool = False) -> None: # noqa: FBT001, FBT002 + def release(self, force: bool=False) -> None: # noqa: FBT001, FBT002 """ Releases the file lock. Please note, that the lock is only completely released, if the lock counter is 0. Also note, that the lock file itself is not automatically deleted. @@ -334,11 +334,11 @@ def release(self, force: bool = False) -> None: # noqa: FBT001, FBT002 self._context.lock_counter -= 1 if self._context.lock_counter == 0 or force: - lock_id, lock_filename = id(self), self.lock_file + lock_id, lock_filename=id(self), self.lock_file _LOGGER.debug("Attempting to release lock %s on %s", lock_id, lock_filename) self._release() - self._context.lock_counter = 0 + self._context.lock_counter=0 _LOGGER.debug("Lock %s released on %s", lock_id, lock_filename) def __enter__(self) -> Self: From 6df00e7b07b6e47d3a152de2e9430d039506cccd Mon Sep 17 00:00:00 2001 From: Ethan Blackwood Date: Wed, 12 Jun 2024 14:45:40 -0400 Subject: [PATCH 05/12] Another fix --- src/filelock/_api.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/filelock/_api.py b/src/filelock/_api.py index 3d0cb1e9..593d078d 100644 --- a/src/filelock/_api.py +++ b/src/filelock/_api.py @@ -114,14 +114,7 @@ def __init_subclass__(cls, **kwargs: dict[str, Any]) -> None: super().__init_subclass__(**kwargs) cls._instances = WeakValueDictionary() -<<<<<<< HEAD def __init__( # noqa: PLR0913 -======= - def __init__(self, *args, **kwargs) -> None: - pass # for backwards compatibility (don't break super().__init__ calls) - - def _initialize( # noqa: PLR0913 ->>>>>>> 0d3d1cbd7830a436223d4e93712e7116237de86b self, lock_file: str | os.PathLike[str], timeout: float = -1, From 9c07da7186313540a087fa4f3c3445a2dc3f9a13 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 12 Jun 2024 18:46:31 +0000 Subject: [PATCH 06/12] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- src/filelock/_api.py | 48 ++++++++++++++++++++++---------------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/src/filelock/_api.py b/src/filelock/_api.py index d61bc555..3b2e9208 100644 --- a/src/filelock/_api.py +++ b/src/filelock/_api.py @@ -117,12 +117,12 @@ def __init_subclass__(cls, **kwargs: dict[str, Any]) -> None: def __init__( # noqa: PLR0913 self, lock_file: str | os.PathLike[str], - timeout: float=-1, - mode: int=0o644, - thread_local: bool=True, # noqa: FBT001, FBT002 + timeout: float = -1, + mode: int = 0o644, + thread_local: bool = True, # noqa: FBT001, FBT002 *, - blocking: bool=True, - is_singleton: bool=False, + blocking: bool = True, + is_singleton: bool = False, ) -> None: """ Create a new lock object. @@ -140,7 +140,7 @@ def __init__( # noqa: PLR0913 to pass the same object around. """ - if hasattr(self, '_context'): + if hasattr(self, "_context"): return # bypass initialization because object is already initialized self._is_thread_local = thread_local @@ -160,17 +160,17 @@ def is_thread_local(self) -> bool: """:return: a flag indicating if this lock is thread local or not""" return self._is_thread_local - @ property + @property def is_singleton(self) -> bool: """:return: a flag indicating if this lock is singleton or not""" return self._is_singleton - @ property + @property def lock_file(self) -> str: """:return: path to the lock file""" return self._context.lock_file - @ property + @property def timeout(self) -> float: """ :return: the default timeout value, in seconds @@ -179,7 +179,7 @@ def timeout(self) -> float: """ return self._context.timeout - @ timeout.setter + @timeout.setter def timeout(self, value: float | str) -> None: """ Change the default timeout value. @@ -189,12 +189,12 @@ def timeout(self, value: float | str) -> None: """ self._context.timeout = float(value) - @ property + @property def blocking(self) -> bool: """:return: whether the locking is blocking or not""" return self._context.blocking - @ blocking.setter + @blocking.setter def blocking(self, value: bool) -> None: """ Change the default blocking value. @@ -204,22 +204,22 @@ def blocking(self, value: bool) -> None: """ self._context.blocking = value - @ property + @property def mode(self) -> int: """:return: the file permissions for the lockfile""" return self._context.mode - @ abstractmethod + @abstractmethod def _acquire(self) -> None: """If the file lock could be acquired, self._context.lock_file_fd holds the file descriptor of the lock file.""" raise NotImplementedError - @ abstractmethod + @abstractmethod def _release(self) -> None: """Releases the lock and sets self._context.lock_file_fd to None.""" raise NotImplementedError - @ property + @property def is_locked(self) -> bool: """ @@ -231,18 +231,18 @@ def is_locked(self) -> bool: """ return self._context.lock_file_fd is not None - @ property + @property def lock_counter(self) -> int: """:return: The number of times this lock has been acquired (but not yet released).""" return self._context.lock_counter def acquire( self, - timeout: float | None=None, - poll_interval: float=0.05, + timeout: float | None = None, + poll_interval: float = 0.05, *, - poll_intervall: float | None=None, - blocking: bool | None=None, + poll_intervall: float | None = None, + blocking: bool | None = None, ) -> AcquireReturnProxy: """ Try to acquire the file lock. @@ -315,7 +315,7 @@ def acquire( raise return AcquireReturnProxy(lock=self) - def release(self, force: bool=False) -> None: # noqa: FBT001, FBT002 + def release(self, force: bool = False) -> None: # noqa: FBT001, FBT002 """ Releases the file lock. Please note, that the lock is only completely released, if the lock counter is 0. Also note, that the lock file itself is not automatically deleted. @@ -327,11 +327,11 @@ def release(self, force: bool=False) -> None: # noqa: FBT001, FBT002 self._context.lock_counter -= 1 if self._context.lock_counter == 0 or force: - lock_id, lock_filename=id(self), self.lock_file + lock_id, lock_filename = id(self), self.lock_file _LOGGER.debug("Attempting to release lock %s on %s", lock_id, lock_filename) self._release() - self._context.lock_counter=0 + self._context.lock_counter = 0 _LOGGER.debug("Lock %s released on %s", lock_id, lock_filename) def __enter__(self) -> Self: From 57c4a3114689c28b0f83b86322de5c130bf1d973 Mon Sep 17 00:00:00 2001 From: Ethan Blackwood Date: Wed, 12 Jun 2024 15:20:19 -0400 Subject: [PATCH 07/12] Improve subclass test; put singleton validation in __init__ --- src/filelock/_api.py | 24 +++++++++++++++--------- tests/test_filelock.py | 10 ++++++---- 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/src/filelock/_api.py b/src/filelock/_api.py index 3b2e9208..699bd78b 100644 --- a/src/filelock/_api.py +++ b/src/filelock/_api.py @@ -85,11 +85,11 @@ class BaseFileLock(ABC, contextlib.ContextDecorator): def __new__( # noqa: PLR0913 cls, lock_file: str | os.PathLike[str], - timeout: float = -1, - mode: int = 0o644, - thread_local: bool = True, # noqa: FBT001, FBT002 + timeout: float = -1, # noqa: ARG003 + mode: int = 0o644, # noqa: ARG003 + thread_local: bool = True, # noqa: FBT001, FBT002, ARG003 *, - blocking: bool = True, + blocking: bool = True, # noqa: ARG003 is_singleton: bool = False, **kwargs: Any, # capture remaining kwargs for subclasses # noqa: ARG003, ANN401 ) -> Self: @@ -103,10 +103,6 @@ def __new__( # noqa: PLR0913 cls._instances[str(lock_file)] = self return self - if timeout != instance.timeout or mode != instance.mode: - msg = "Singleton lock instances cannot be initialized with differing arguments" - raise ValueError(msg) - return instance # type: ignore[return-value] # https://github.com/python/mypy/issues/15322 def __init_subclass__(cls, **kwargs: dict[str, Any]) -> None: @@ -140,7 +136,17 @@ def __init__( # noqa: PLR0913 to pass the same object around. """ - if hasattr(self, "_context"): + if is_singleton and hasattr(self, "_context"): + # test whether other parameters match existing instance. + if ( + self.is_thread_local() != thread_local + or not self.is_singleton + or self._context.timeout != timeout + or self._context.mode != mode + or self._context.blocking != blocking + ): + msg = "Singleton lock instances cannot be initialized with differing arguments" + raise ValueError(msg) return # bypass initialization because object is already initialized self._is_thread_local = thread_local diff --git a/tests/test_filelock.py b/tests/test_filelock.py index 7d16ae7c..d6908a64 100644 --- a/tests/test_filelock.py +++ b/tests/test_filelock.py @@ -687,9 +687,10 @@ def __init__( # noqa: PLR0913 Too many arguments to function call (6 > 5) mode: int = 0o644, thread_local: bool = True, my_param: int = 0, - **kwargs: dict[str, Any], + **kwargs: dict[str, Any], # noqa: ARG002 ) -> None: - pass + super().__init__(lock_file, timeout, mode, thread_local, blocking=True, is_singleton=True) + self.my_param = my_param lock_path = tmp_path / "a" MyFileLock(str(lock_path), my_param=1) @@ -702,9 +703,10 @@ def __init__( # noqa: PLR0913 Too many arguments to function call (6 > 5) mode: int = 0o644, thread_local: bool = True, my_param: int = 0, - **kwargs: dict[str, Any], + **kwargs: dict[str, Any], # noqa: ARG002 ) -> None: - pass + super().__init__(lock_file, timeout, mode, thread_local, blocking=True, is_singleton=True) + self.my_param = my_param MySoftFileLock(str(lock_path), my_param=1) From cddd7ae39f4554035afba00bbe9db50a4c78b8e3 Mon Sep 17 00:00:00 2001 From: Ethan Blackwood Date: Wed, 12 Jun 2024 16:08:23 -0400 Subject: [PATCH 08/12] Better error message for non-matching arguments --- src/filelock/_api.py | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/src/filelock/_api.py b/src/filelock/_api.py index 699bd78b..317c049e 100644 --- a/src/filelock/_api.py +++ b/src/filelock/_api.py @@ -138,16 +138,26 @@ def __init__( # noqa: PLR0913 """ if is_singleton and hasattr(self, "_context"): # test whether other parameters match existing instance. - if ( - self.is_thread_local() != thread_local - or not self.is_singleton - or self._context.timeout != timeout - or self._context.mode != mode - or self._context.blocking != blocking - ): - msg = "Singleton lock instances cannot be initialized with differing arguments" - raise ValueError(msg) - return # bypass initialization because object is already initialized + if not self.is_singleton: + raise RuntimeError("__init__ should only be called on initialized object if it is a singleton") + + params_to_check = { + "is_thread_local": (thread_local, self.is_thread_local()), + "timeout": (timeout, self.timeout), + "mode": (mode, self.mode), + "blocking": (blocking, self.blocking), + } + + non_matching_params = {name: vals for name, vals in params_to_check.items() if vals[0] != vals[1]} + if len(non_matching_params) == 0: + return # bypass initialization because object is already initialized + + # parameters do not match; raise error + msg = "Singleton lock instances cannot be initialized with differing arguments" + msg += "\nNon-matching arguments: " + for param_name, (passed_param, set_param) in non_matching_params.items(): + msg += f"\n\t{param_name} (existing lock has {set_param} but {passed_param} was passed)" + raise ValueError(msg) self._is_thread_local = thread_local self._is_singleton = is_singleton From e667171225383ecbba81bf81300fe15f9d2e99df Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 12 Jun 2024 20:13:01 +0000 Subject: [PATCH 09/12] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- src/filelock/_api.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/filelock/_api.py b/src/filelock/_api.py index 317c049e..ca8fea91 100644 --- a/src/filelock/_api.py +++ b/src/filelock/_api.py @@ -139,7 +139,8 @@ def __init__( # noqa: PLR0913 if is_singleton and hasattr(self, "_context"): # test whether other parameters match existing instance. if not self.is_singleton: - raise RuntimeError("__init__ should only be called on initialized object if it is a singleton") + msg = "__init__ should only be called on initialized object if it is a singleton" + raise RuntimeError(msg) params_to_check = { "is_thread_local": (thread_local, self.is_thread_local()), From 18544de8c3120cb1efae4fe8f5867eb06bb83013 Mon Sep 17 00:00:00 2001 From: Ethan Blackwood Date: Wed, 12 Jun 2024 16:32:51 -0400 Subject: [PATCH 10/12] Add test for all arg differences for singleton locks --- src/filelock/_api.py | 2 +- tests/test_filelock.py | 19 +++++++++++++------ 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/filelock/_api.py b/src/filelock/_api.py index ca8fea91..8672d40c 100644 --- a/src/filelock/_api.py +++ b/src/filelock/_api.py @@ -143,7 +143,7 @@ def __init__( # noqa: PLR0913 raise RuntimeError(msg) params_to_check = { - "is_thread_local": (thread_local, self.is_thread_local()), + "thread_local": (thread_local, self.is_thread_local()), "timeout": (timeout, self.timeout), "mode": (mode, self.mode), "blocking": (blocking, self.blocking), diff --git a/tests/test_filelock.py b/tests/test_filelock.py index d6908a64..5c2ba094 100644 --- a/tests/test_filelock.py +++ b/tests/test_filelock.py @@ -744,12 +744,19 @@ def test_singleton_locks_are_distinct_per_lock_file(lock_type: type[BaseFileLock @pytest.mark.parametrize("lock_type", [FileLock, SoftFileLock]) def test_singleton_locks_must_be_initialized_with_the_same_args(lock_type: type[BaseFileLock], tmp_path: Path) -> None: lock_path = tmp_path / "a" - lock = lock_type(str(lock_path), is_singleton=True) # noqa: F841 - - with pytest.raises(ValueError, match="Singleton lock instances cannot be initialized with differing arguments"): - lock_type(str(lock_path), timeout=10, is_singleton=True) - with pytest.raises(ValueError, match="Singleton lock instances cannot be initialized with differing arguments"): - lock_type(str(lock_path), mode=0, is_singleton=True) + args: dict[str, Any] = {"timeout": -1, "mode": 0o644, "thread_local": True, "blocking": True} + alternate_args: dict[str, Any] = {"timeout": 10, "mode": 0, "thread_local": False, "blocking": False} + + lock = lock_type(str(lock_path), is_singleton=True, **args) + + for arg_name in args: + general_msg = "Singleton lock instances cannot be initialized with differing arguments" + altered_args = args.copy() + altered_args[arg_name] = alternate_args[arg_name] + with pytest.raises(ValueError, match=general_msg) as exc_info: + lock_type(str(lock_path), is_singleton=True, **altered_args) + exc_info.match(arg_name) # ensure specific non-matching argument is included in exception text + del lock @pytest.mark.skipif(hasattr(sys, "pypy_version_info"), reason="del() does not trigger GC in PyPy") From 8acba23b0f1abeaca970677c18f043024d07bac5 Mon Sep 17 00:00:00 2001 From: Ethan Blackwood Date: Wed, 12 Jun 2024 18:27:50 -0400 Subject: [PATCH 11/12] Make non_matching_params lines more idiomatic --- src/filelock/_api.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/filelock/_api.py b/src/filelock/_api.py index 8672d40c..2894e61b 100644 --- a/src/filelock/_api.py +++ b/src/filelock/_api.py @@ -149,8 +149,12 @@ def __init__( # noqa: PLR0913 "blocking": (blocking, self.blocking), } - non_matching_params = {name: vals for name, vals in params_to_check.items() if vals[0] != vals[1]} - if len(non_matching_params) == 0: + non_matching_params = { + name: (passed_param, set_param) + for name, (passed_param, set_param) in params_to_check.items() + if passed_param != set_param + } + if not non_matching_params: return # bypass initialization because object is already initialized # parameters do not match; raise error From 3775b03e6ced71835c49fc41d4db6c306ba56bec Mon Sep 17 00:00:00 2001 From: Ethan Blackwood Date: Wed, 12 Jun 2024 18:39:32 -0400 Subject: [PATCH 12/12] Fix test failure due to not deleting exc_info --- tests/test_filelock.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_filelock.py b/tests/test_filelock.py index 5c2ba094..8ecd743b 100644 --- a/tests/test_filelock.py +++ b/tests/test_filelock.py @@ -756,7 +756,7 @@ def test_singleton_locks_must_be_initialized_with_the_same_args(lock_type: type[ with pytest.raises(ValueError, match=general_msg) as exc_info: lock_type(str(lock_path), is_singleton=True, **altered_args) exc_info.match(arg_name) # ensure specific non-matching argument is included in exception text - del lock + del lock, exc_info @pytest.mark.skipif(hasattr(sys, "pypy_version_info"), reason="del() does not trigger GC in PyPy")