| 1 | From 25e374e1986147af10c66dc8c95de3c41dab2141 Mon Sep 17 00:00:00 2001
|
| 2 | Message-ID: <25e374e1986147af10c66dc8c95de3c41dab2141.1766619707.git.ngraves@ngraves.fr>
|
| 3 | From: l98peyro <[email protected]>
|
| 4 | Date: Sat, 22 Apr 2023 07:48:50 +0000
|
| 5 | Subject: [PATCH] Changed deprecated lockfile by filelock
|
| 6 | Edited by [email protected]
|
| 7 |
|
| 8 | ---
|
| 9 | ChangeLog | 6 ++++++
|
| 10 | doc/examples/service-runner.txt | 4 ++--
|
| 11 | pyproject.toml | 6 +-----
|
| 12 | src/daemon/pidfile.py | 12 ++++++++---
|
| 13 | test/test_pidfile.py | 38 ++++++++++++++++-----------------
|
| 14 | 5 files changed, 37 insertions(+), 29 deletions(-)
|
| 15 |
|
| 16 | diff --git a/ChangeLog b/ChangeLog
|
| 17 | index 51b1abb..7a967df 100644
|
| 18 | |
| 19 | |
| 20 | @@ -150,6 +150,12 @@ Changed:
|
| 21 |
|
| 22 | Closes: Pagure #87. Thanks to Attila Lendvai for the report.
|
| 23 |
|
| 24 | +* Changed deprecated lockfile dependency with filelock.
|
| 25 | +
|
| 26 | + The package lockfile used is no longer maintained. Filelock has been chosen
|
| 27 | + over pid due to it's more frequent updates.
|
| 28 | +
|
| 29 | + Closes: Pagure #42
|
| 30 |
|
| 31 | Version 3.0.1
|
| 32 | =============
|
| 33 | diff --git a/doc/examples/service-runner.txt b/doc/examples/service-runner.txt
|
| 34 | index 9b2d5c7..7091077 100644
|
| 35 | |
| 36 | |
| 37 | @@ -33,7 +33,7 @@ example: a `ServiceRunner` class.
|
| 38 |
|
| 39 | from daemon import pidfile
|
| 40 | from daemon.daemon import DaemonContext
|
| 41 | - import lockfile
|
| 42 | + from filelock import FileLock
|
| 43 |
|
| 44 |
|
| 45 | class ServiceRunnerError(Exception):
|
| 46 | @@ -93,7 +93,7 @@ example: a `ServiceRunner` class.
|
| 47 |
|
| 48 | self.pidfile = None
|
| 49 | if app.pidfile_path is not None:
|
| 50 | - self.pidfile = make_pidlockfile(
|
| 51 | + self.pidfile = Filelock(
|
| 52 | app.pidfile_path, app.pidfile_timeout)
|
| 53 | self.daemon_context.pidfile = self.pidfile
|
| 54 |
|
| 55 | diff --git a/pyproject.toml b/pyproject.toml
|
| 56 | index 63693d0..467d184 100644
|
| 57 | |
| 58 | |
| 59 | @@ -29,11 +29,7 @@ requires-python = ">= 3.7"
|
| 60 |
|
| 61 | # Core dependencies required for the package to operate.
|
| 62 | dependencies = [
|
| 63 | -
|
| 64 | - # Platform-independent file locking module.
|
| 65 | - # Documentation: <URL:http://docs.openstack.org/developer/pylockfile>.
|
| 66 | - "lockfile >= 0.10",
|
| 67 | -
|
| 68 | + "filelock >=3.9.0",
|
| 69 | ]
|
| 70 |
|
| 71 | # The license granted to recipients of this project.
|
| 72 | diff --git a/src/daemon/pidfile.py b/src/daemon/pidfile.py
|
| 73 | index 63d625f..8c36bb5 100644
|
| 74 | |
| 75 | |
| 76 | @@ -6,11 +6,15 @@
|
| 77 | # information, grant of license, and disclaimer of warranty.
|
| 78 |
|
| 79 | """ Lockfile behaviour implemented via Unix PID files. """
|
| 80 | +from __future__ import annotations
|
| 81 | +
|
| 82 | +from threading import Lock
|
| 83 | +
|
| 84 | +from filelock import FileLock
|
| 85 |
|
| 86 | -from lockfile.pidlockfile import PIDLockFile
|
| 87 |
|
| 88 |
|
| 89 | -class TimeoutPIDLockFile(PIDLockFile):
|
| 90 | +class TimeoutPIDLockFile(FileLock):
|
| 91 | """ Lockfile with default timeout, implemented as a Unix PID file.
|
| 92 |
|
| 93 | This uses the ``PIDLockFile`` implementation, with the
|
| 94 | @@ -30,7 +34,9 @@ class TimeoutPIDLockFile(PIDLockFile):
|
| 95 | :return: ``None``.
|
| 96 | """
|
| 97 | self.acquire_timeout = acquire_timeout
|
| 98 | - super().__init__(path, *args, **kwargs)
|
| 99 | + self._thread_lock: Lock = Lock()
|
| 100 | + self._lock_file_fd: int | None = None
|
| 101 | + super().__init__(lock_file=path, *args, **kwargs)
|
| 102 |
|
| 103 | def acquire(self, timeout=None, *args, **kwargs):
|
| 104 | """ Acquire the lock.
|
| 105 | diff --git a/test/test_pidfile.py b/test/test_pidfile.py
|
| 106 | index b2b8d9a..41c787a 100644
|
| 107 | |
| 108 | |
| 109 | @@ -16,7 +16,7 @@ import os
|
| 110 | import tempfile
|
| 111 | import unittest.mock
|
| 112 |
|
| 113 | -import lockfile
|
| 114 | +import filelock
|
| 115 |
|
| 116 | import daemon.pidfile
|
| 117 |
|
| 118 | @@ -43,7 +43,7 @@ class FakeFileDescriptorStringIO(io.StringIO):
|
| 119 |
|
| 120 |
|
| 121 | def make_pidlockfile_scenarios():
|
| 122 | - """ Make a collection of scenarios for testing `PIDLockFile` instances.
|
| 123 | + """ Make a collection of scenarios for testing `PIDFileLock` instances.
|
| 124 |
|
| 125 | :return: A collection of scenarios for tests involving
|
| 126 | `PIDLockfFile` instances.
|
| 127 | @@ -134,7 +134,7 @@ def setup_pidfile_fixtures(testcase):
|
| 128 | :param testcase: A `TestCase` instance to decorate.
|
| 129 |
|
| 130 | Decorate the `testcase` with attributes to be fixtures for tests
|
| 131 | - involving `PIDLockFile` instances.
|
| 132 | + involving `PIDFileLock` instances.
|
| 133 | """
|
| 134 | scenarios = make_pidlockfile_scenarios()
|
| 135 | testcase.pidlockfile_scenarios = scenarios
|
| 136 | @@ -266,7 +266,7 @@ def setup_pidfile_fixtures(testcase):
|
| 137 | def make_lockfile_method_fakes(scenario):
|
| 138 | """ Make common fake methods for lockfile class.
|
| 139 |
|
| 140 | - :param scenario: A scenario for testing with PIDLockFile.
|
| 141 | + :param scenario: A scenario for testing with PIDFileLock.
|
| 142 | :return: A mapping from normal function name to the corresponding
|
| 143 | fake function.
|
| 144 |
|
| 145 | @@ -285,14 +285,14 @@ def make_lockfile_method_fakes(scenario):
|
| 146 |
|
| 147 | def fake_func_acquire(timeout=None):
|
| 148 | if scenario['locking_pid'] is not None:
|
| 149 | - raise lockfile.AlreadyLocked()
|
| 150 | + raise Exception("Already locked")
|
| 151 | scenario['locking_pid'] = scenario['pid']
|
| 152 |
|
| 153 | def fake_func_release():
|
| 154 | if scenario['locking_pid'] is None:
|
| 155 | - raise lockfile.NotLocked()
|
| 156 | + raise Exception("Not locked")
|
| 157 | if scenario['locking_pid'] != scenario['pid']:
|
| 158 | - raise lockfile.NotMyLock()
|
| 159 | + raise Exception("Unlock error")
|
| 160 | scenario['locking_pid'] = None
|
| 161 |
|
| 162 | def fake_func_break_lock():
|
| 163 | @@ -313,7 +313,7 @@ def apply_lockfile_method_mocks(mock_lockfile, testcase, scenario):
|
| 164 | :param mock_lockfile: An object providing the `LockFile` interface.
|
| 165 | :param testcase: The `TestCase` instance providing the context for
|
| 166 | the patch.
|
| 167 | - :param scenario: The `PIDLockFile` test scenario to use.
|
| 168 | + :param scenario: The `PIDFileLock` test scenario to use.
|
| 169 |
|
| 170 | Mock the `LockFile` methods of `mock_lockfile`, by applying fake
|
| 171 | methods customised for `scenario`. The mock is does by a patch
|
| 172 | @@ -334,13 +334,13 @@ def apply_lockfile_method_mocks(mock_lockfile, testcase, scenario):
|
| 173 |
|
| 174 |
|
| 175 | def setup_pidlockfile_fixtures(testcase, scenario_name=None):
|
| 176 | - """ Set up common fixtures for PIDLockFile test cases.
|
| 177 | + """ Set up common fixtures for PIDFileLock test cases.
|
| 178 |
|
| 179 | :param testcase: The `TestCase` instance to decorate.
|
| 180 | - :param scenario_name: The name of the `PIDLockFile` scenario to use.
|
| 181 | + :param scenario_name: The name of the `PIDFileLock` scenario to use.
|
| 182 |
|
| 183 | Decorate the `testcase` with attributes that are fixtures for test
|
| 184 | - cases involving `PIDLockFile` instances.`
|
| 185 | + cases involving `PIDFileLock` instances.`
|
| 186 | """
|
| 187 |
|
| 188 | setup_pidfile_fixtures(testcase)
|
| 189 | @@ -350,7 +350,7 @@ def setup_pidlockfile_fixtures(testcase, scenario_name=None):
|
| 190 | 'remove_existing_pidfile',
|
| 191 | ]:
|
| 192 | func_patcher = unittest.mock.patch.object(
|
| 193 | - lockfile.pidlockfile, func_name)
|
| 194 | + filelock.FileLock, func_name)
|
| 195 | func_patcher.start()
|
| 196 | testcase.addCleanup(func_patcher.stop)
|
| 197 |
|
| 198 | @@ -371,16 +371,16 @@ class TimeoutPIDLockFile_TestCase(scaffold.TestCase):
|
| 199 | }
|
| 200 |
|
| 201 | self.test_kwargs = dict(
|
| 202 | - path=self.scenario['pidfile_path'],
|
| 203 | + lock_file=self.scenario['pidfile_path'],
|
| 204 | acquire_timeout=self.scenario['acquire_timeout'],
|
| 205 | )
|
| 206 | self.test_instance = daemon.pidfile.TimeoutPIDLockFile(
|
| 207 | **self.test_kwargs)
|
| 208 |
|
| 209 | def test_inherits_from_pidlockfile(self):
|
| 210 | - """ Should inherit from PIDLockFile. """
|
| 211 | + """ Should inherit from PIDFileLock. """
|
| 212 | instance = self.test_instance
|
| 213 | - self.assertIsInstance(instance, lockfile.pidlockfile.PIDLockFile)
|
| 214 | + self.assertIsInstance(instance, filelock.FileLock)
|
| 215 |
|
| 216 | def test_init_has_expected_signature(self):
|
| 217 | """ Should have expected signature for ‘__init__’. """
|
| 218 | @@ -397,16 +397,16 @@ class TimeoutPIDLockFile_TestCase(scaffold.TestCase):
|
| 219 | self.assertEqual(expected_timeout, instance.acquire_timeout)
|
| 220 |
|
| 221 | @unittest.mock.patch.object(
|
| 222 | - lockfile.pidlockfile.PIDLockFile, "__init__",
|
| 223 | + filelock.FileLock, "__init__",
|
| 224 | autospec=True)
|
| 225 | def test_calls_superclass_init(self, mock_init):
|
| 226 | """ Should call the superclass ‘__init__’. """
|
| 227 | - expected_path = self.test_kwargs['path']
|
| 228 | + expected_path = self.test_kwargs['lock_file']
|
| 229 | instance = daemon.pidfile.TimeoutPIDLockFile(**self.test_kwargs)
|
| 230 | mock_init.assert_called_with(instance, expected_path)
|
| 231 |
|
| 232 | @unittest.mock.patch.object(
|
| 233 | - lockfile.pidlockfile.PIDLockFile, "acquire",
|
| 234 | + filelock.FileLock, "acquire",
|
| 235 | autospec=True)
|
| 236 | def test_acquire_uses_specified_timeout(self, mock_func_acquire):
|
| 237 | """ Should call the superclass ‘acquire’ with specified timeout. """
|
| 238 | @@ -417,7 +417,7 @@ class TimeoutPIDLockFile_TestCase(scaffold.TestCase):
|
| 239 | mock_func_acquire.assert_called_with(instance, expected_timeout)
|
| 240 |
|
| 241 | @unittest.mock.patch.object(
|
| 242 | - lockfile.pidlockfile.PIDLockFile, "acquire",
|
| 243 | + filelock.FileLock, "acquire",
|
| 244 | autospec=True)
|
| 245 | def test_acquire_uses_stored_timeout_by_default(self, mock_func_acquire):
|
| 246 | """
|
| 247 | --
|
| 248 | 2.52.0
|
| 249 |
|