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

Enable use as a context decorator #128

Merged
merged 6 commits into from Feb 14, 2022
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 4 additions & 0 deletions docs/changelog.rst
@@ -1,6 +1,10 @@
Changelog
=========

v3.5.0 (2022-01-03)
-------------------
- Enable use as context decorator

v3.4.2 (2021-12-16)
-------------------
- Drop support for python ``3.6``
Expand Down
8 changes: 8 additions & 0 deletions docs/index.rst
Expand Up @@ -67,6 +67,14 @@ locks:
finally:
lock.release()


@lock
def decorated():
print("You're a decorated Jedi!")


decorated()

The :meth:`acquire <filelock.BaseFileLock.acquire>` method accepts also a ``timeout`` parameter. If the lock cannot be
acquired within ``timeout`` seconds, a :class:`Timeout <filelock.Timeout>` exception is raised:

Expand Down
3 changes: 2 additions & 1 deletion src/filelock/_api.py
@@ -1,5 +1,6 @@
from __future__ import annotations

import contextlib
import logging
import os
import time
Expand Down Expand Up @@ -35,7 +36,7 @@ def __exit__(
self.lock.release()


class BaseFileLock(ABC):
class BaseFileLock(ABC, contextlib.ContextDecorator):
"""Abstract base class for a file lock object."""

def __init__(self, lock_file: str | os.PathLike[Any], timeout: float = -1) -> None:
Expand Down
14 changes: 14 additions & 0 deletions tests/test_filelock.py
Expand Up @@ -368,3 +368,17 @@ def test_poll_intervall_deprecated(lock_type: type[BaseFileLock], tmp_path: Path
break
else: # pragma: no cover
pytest.fail("No warnings of stacklevel=2 matching.")


@pytest.mark.parametrize("lock_type", [FileLock, SoftFileLock])
def test_context_decorator(lock_type: type[BaseFileLock], tmp_path: Path) -> None:
lock_path = tmp_path / "a"
lock = lock_type(str(lock_path))

@lock
def decorated_method() -> None:
assert lock.is_locked

assert not lock.is_locked
decorated_method()
assert not lock.is_locked