projects/guix·blob python-team · refs

249 lines · 9.2 KiB

1From 25e374e1986147af10c66dc8c95de3c41dab2141 Mon Sep 17 00:00:00 2001
2Message-ID: <25e374e1986147af10c66dc8c95de3c41dab2141.1766619707.git.ngraves@ngraves.fr>
3From: l98peyro <[email protected]>
4Date: Sat, 22 Apr 2023 07:48:50 +0000
5Subject: [PATCH] Changed deprecated lockfile by filelock
6Edited 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
16diff --git a/ChangeLog b/ChangeLog
17index 51b1abb..7a967df 100644
18--- a/ChangeLog
19+++ b/ChangeLog
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 =============
33diff --git a/doc/examples/service-runner.txt b/doc/examples/service-runner.txt
34index 9b2d5c7..7091077 100644
35--- a/doc/examples/service-runner.txt
36+++ b/doc/examples/service-runner.txt
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
55diff --git a/pyproject.toml b/pyproject.toml
56index 63693d0..467d184 100644
57--- a/pyproject.toml
58+++ b/pyproject.toml
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.
72diff --git a/src/daemon/pidfile.py b/src/daemon/pidfile.py
73index 63d625f..8c36bb5 100644
74--- a/src/daemon/pidfile.py
75+++ b/src/daemon/pidfile.py
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.
105diff --git a/test/test_pidfile.py b/test/test_pidfile.py
106index b2b8d9a..41c787a 100644
107--- a/test/test_pidfile.py
108+++ b/test/test_pidfile.py
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--
2482.52.0
249