Skip to content

Commit

Permalink
Re-raise error if cannot create file for some reason for soft locks
Browse files Browse the repository at this point in the history
* updated nomenclature to allign with softlock, added test, added changelog

* moved fcntl import to the test def and added type hints

* another type attempt

* flake fixes

* flake fixes

* changes to resolve issue 147

* fix typo

* flake 8 fix

* test for OSError in SoftFileLock

* flake8 fix

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* PR Feedback

Signed-off-by: Bernát Gábor <bgabor8@bloomberg.net>

* PR Feedback

Signed-off-by: Bernát Gábor <bgabor8@bloomberg.net>

---------

Signed-off-by: Bernát Gábor <bgabor8@bloomberg.net>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Bernát Gábor <bgabor8@bloomberg.net>
  • Loading branch information
3 people authored Mar 26, 2023
1 parent 43472a5 commit dfb8cc7
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 22 deletions.
4 changes: 4 additions & 0 deletions docs/changelog.rst
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
Changelog
=========
v3.10.6 (2023-03-25)
--------------------
- Enhance the robustness of the try/catch block in _soft.py. by :user:`jahrules`.

v3.10.5 (2023-03-25)
--------------------
- Add explicit error check as certain UNIX filesystems do not support flock. by :user:`jahrules`.
Expand Down
18 changes: 8 additions & 10 deletions src/filelock/_soft.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import os
import sys
from errno import EACCES, EEXIST, ENOENT
from errno import EACCES, EEXIST

from ._api import BaseFileLock
from ._util import raise_on_exist_ro_file
Expand All @@ -21,17 +21,15 @@ def _acquire(self) -> None:
| os.O_TRUNC # truncate the file to zero byte
)
try:
fd = os.open(self._lock_file, flags, self._mode)
except OSError as exception:
if exception.errno == EEXIST: # expected if cannot lock
pass
elif exception.errno == ENOENT: # No such file or directory - parent directory is missing
file_handler = os.open(self._lock_file, flags, self._mode)
except OSError as exception: # re-raise unless expected exception
if not (
exception.errno == EEXIST # lock already exist
or (exception.errno == EACCES and sys.platform == "win32") # has no access to this lock
): # pragma: win32 no cover
raise
elif exception.errno == EACCES and sys.platform != "win32": # pragma: win32 no cover
# Permission denied - parent dir is R/O
raise # note windows does not allow you to make a folder r/o only files
else:
self._lock_file_fd = fd
self._lock_file_fd = file_handler

def _release(self) -> None:
os.close(self._lock_file_fd) # type: ignore # the lock file is definitely not None
Expand Down
27 changes: 16 additions & 11 deletions tests/test_filelock.py
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ def __init__(self, target: Callable[[], None], name: str) -> None:
def run(self) -> None:
try:
super().run()
except Exception: # pragma: no cover
except RuntimeError: # pragma: no cover
self.ex = sys.exc_info() # pragma: no cover

def join(self, timeout: float | None = None) -> None:
Expand Down Expand Up @@ -337,8 +337,8 @@ def test_context_release_on_exc(lock_type: type[BaseFileLock], tmp_path: Path) -
with lock as lock_1:
assert lock is lock_1
assert lock.is_locked
raise Exception
except Exception:
raise ValueError
except ValueError:
assert not lock.is_locked


Expand All @@ -352,8 +352,8 @@ def test_acquire_release_on_exc(lock_type: type[BaseFileLock], tmp_path: Path) -
with lock.acquire() as lock_1:
assert lock is lock_1
assert lock.is_locked
raise Exception
except Exception:
raise ValueError
except ValueError:
assert not lock.is_locked


Expand Down Expand Up @@ -385,9 +385,8 @@ def test_del(lock_type: type[BaseFileLock], tmp_path: Path) -> None:
def test_cleanup_soft_lock(tmp_path: Path) -> None:
# tests if the lock file is removed after use
lock_path = tmp_path / "a"
lock = SoftFileLock(str(lock_path))

with lock:
with SoftFileLock(lock_path):
assert lock_path.exists()
assert not lock_path.exists()

Expand All @@ -399,9 +398,9 @@ def test_poll_intervall_deprecated(lock_type: type[BaseFileLock], tmp_path: Path

with pytest.deprecated_call(match="use poll_interval instead of poll_intervall") as checker:
lock.acquire(poll_intervall=0.05) # the deprecation warning will be captured by the checker
frameinfo = getframeinfo(stack()[0][0]) # get frameinfo of current file and lineno (+1 than the above lineno)
frame_info = getframeinfo(stack()[0][0]) # get frame info of current file and lineno (+1 than the above lineno)
for warning in checker:
if warning.filename == frameinfo.filename and warning.lineno + 1 == frameinfo.lineno: # pragma: no cover
if warning.filename == frame_info.filename and warning.lineno + 1 == frame_info.lineno: # pragma: no cover
break
else: # pragma: no cover
pytest.fail("No warnings of stacklevel=2 matching.")
Expand Down Expand Up @@ -490,7 +489,7 @@ def test_wrong_platform(tmp_path: Path) -> None:
assert inspect.isabstract(BaseFileLock)

lock_type = UnixFileLock if sys.platform == "win32" else WindowsFileLock
lock = lock_type(str(tmp_path / "lockfile"))
lock = lock_type(tmp_path / "lockfile")

with pytest.raises(NotImplementedError):
lock.acquire()
Expand All @@ -502,5 +501,11 @@ def test_wrong_platform(tmp_path: Path) -> None:
def test_flock_not_implemented_unix(tmp_path: Path, mocker: MockerFixture) -> None:
mocker.patch("fcntl.flock", side_effect=OSError(ENOSYS, "mock error"))
with pytest.raises(NotImplementedError):
with FileLock(str(tmp_path / "a.lock")):
with FileLock(tmp_path / "a.lock"):
pass


def test_soft_errors(tmp_path: Path, mocker: MockerFixture) -> None:
mocker.patch("os.open", side_effect=OSError(ENOSYS, "mock error"))
with pytest.raises(OSError, match="mock error"):
SoftFileLock(tmp_path / "a.lock").acquire()
1 change: 0 additions & 1 deletion whitelist.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ enosys
extlinks
filelock
filemode
frameinfo
fspath
getframeinfo
intersphinx
Expand Down

0 comments on commit dfb8cc7

Please sign in to comment.