Skip to content

Commit 6485eff

Browse files
xqtjenkins-bot
authored andcommitted
cleanup throttle: deprecate requestsize and rename methods for clarity
- Deprecate unused `requestsize` parameter from `Throttle.__call__` - Deprecate `next_multiplicity` property - Rename `getDelay` → `get_delay` for PEP 8 compliance - Rename `setDelays` → `set_delays` accordingly - Simplify `__call__` and `get_delay` logic - Improve docstrings for clarity and consistency Bug: T399266 Change-Id: I69397a247f4adc97201e70b32e8d08989300c668
1 parent 870ae4a commit 6485eff

File tree

1 file changed

+85
-32
lines changed

1 file changed

+85
-32
lines changed

pywikibot/throttle.py

Lines changed: 85 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
from __future__ import annotations
1818

1919
import itertools
20-
import math
2120
import threading
2221
import time
2322
from collections import Counter
@@ -28,7 +27,7 @@
2827
import pywikibot
2928
from pywikibot import config
3029
from pywikibot.backports import Counter as CounterType
31-
from pywikibot.tools import deprecated
30+
from pywikibot.tools import deprecate_positionals, deprecated, deprecated_args
3231

3332

3433
FORMAT_LINE = '{module_id} {pid} {time} {site}\n'
@@ -89,7 +88,6 @@ def __init__(self, site: pywikibot.site.BaseSite | str, *,
8988
self.writedelay = writedelay or config.put_throttle
9089
self.last_read = 0.0
9190
self.last_write = 0.0
92-
self.next_multiplicity = 1.0
9391

9492
self.retry_after = 0 # set by http.request
9593
self.delay = 0
@@ -99,6 +97,25 @@ def __init__(self, site: pywikibot.site.BaseSite | str, *,
9997
self.checkMultiplicity()
10098
self.setDelays()
10199

100+
@property
101+
@deprecated(since='10.3.0')
102+
def next_multiplicity(self) -> float:
103+
"""Factor to scale delay time based on upcoming request size.
104+
105+
.. deprecated:: 10.3.0
106+
"""
107+
return 1.0
108+
109+
@next_multiplicity.setter
110+
@deprecated(since='10.3.0')
111+
def next_multiplicity(self, value: float) -> None:
112+
"""Setter for delay scaling factor for the next request.
113+
114+
.. deprecated:: 10.3.0
115+
This property has no effect and is retained for backward
116+
compatibility.
117+
"""
118+
102119
@property
103120
@deprecated('expiry', since='8.4.0')
104121
def dropdelay(self):
@@ -209,6 +226,7 @@ def checkMultiplicity(self) -> None:
209226
pywikibot.log(f'Found {count} {mysite} processes running,'
210227
' including this one.')
211228

229+
@deprecated('set_delays', since='10.3.0')
212230
def setDelays(
213231
self,
214232
delay=None,
@@ -217,7 +235,23 @@ def setDelays(
217235
) -> None:
218236
"""Set the nominal delays in seconds.
219237
238+
.. deprecated:: 10.3.0
239+
Use :meth:`set_delays` instead.
240+
"""
241+
self.set_delays(delay=delay, writedelay=writedelay, absolute=absolute)
242+
243+
def set_delays(
244+
self, *,
245+
delay=None,
246+
writedelay=None,
247+
absolute: bool = False
248+
) -> None:
249+
"""Set the nominal delays in seconds.
250+
220251
Defaults to config values.
252+
253+
.. versionadded:: 10.3.0
254+
Renamed from :meth:`setDelays`.
221255
"""
222256
with self.lock:
223257
delay = delay or self.mindelay
@@ -231,24 +265,38 @@ def setDelays(
231265
# Start the delay count now, not at the next check
232266
self.last_read = self.last_write = time.time()
233267

234-
def getDelay(self, write: bool = False):
235-
"""Return the actual delay, accounting for multiple processes.
268+
@deprecated('get_delay', since='10.3.0')
269+
def getDelay(self, write: bool = False) -> float:
270+
"""Return the current delay, adjusted for active processes.
236271
237-
This value is the maximum wait between reads/writes, not taking
238-
into account of how much time has elapsed since the last access.
272+
.. deprecated:: 10.3.0
273+
Use :meth:`get_delay` instead.
239274
"""
240-
thisdelay = self.writedelay if write else self.delay
275+
return self.get_delay(write=write)
276+
277+
def get_delay(self, *, write: bool = False) -> float:
278+
"""Return the current delay, adjusted for active processes.
241279
242-
# We're checking for multiple processes
280+
Compute the delay for a read or write operation, factoring in
281+
process concurrency. This method does not account for how much
282+
time has already passed since the last access — use
283+
:meth:`waittime` for that.
284+
285+
.. versionadded:: 10.3.0
286+
Renamed from :meth:`getDelay`.
287+
288+
:param write: Whether the operation is a write (uses writedelay).
289+
:return: The delay in seconds before the next operation should
290+
occur.
291+
"""
292+
current_delay = self.writedelay if write else self.delay
293+
294+
# Refresh process count if the check interval has elapsed
243295
if time.time() > self.checktime + self.checkdelay:
244296
self.checkMultiplicity()
245-
multiplied_delay = self.mindelay * self.next_multiplicity
246-
if thisdelay < multiplied_delay:
247-
thisdelay = multiplied_delay
248-
elif thisdelay > self.maxdelay:
249-
thisdelay = self.maxdelay
250-
thisdelay *= self.process_multiplicity
251-
return thisdelay
297+
298+
current_delay = max(self.mindelay, min(current_delay, self.maxdelay))
299+
return current_delay * self.process_multiplicity
252300

253301
def waittime(self, write: bool = False):
254302
"""Return waiting time in seconds.
@@ -257,7 +305,7 @@ def waittime(self, write: bool = False):
257305
"""
258306
# Take the previous requestsize in account calculating the desired
259307
# delay this time
260-
thisdelay = self.getDelay(write=write)
308+
thisdelay = self.get_delay(write=write)
261309
now = time.time()
262310
ago = now - (self.last_write if write else self.last_read)
263311
return max(0.0, thisdelay - ago)
@@ -294,31 +342,36 @@ def wait(seconds: int | float) -> None:
294342

295343
time.sleep(seconds)
296344

297-
def __call__(self, requestsize: int = 1, write: bool = False) -> None:
298-
"""Block the calling program if the throttle time has not expired.
345+
@deprecated_args(requestsize=None) # since: 10.3.0
346+
@deprecate_positionals(since='10.3.0')
347+
def __call__(self, *, requestsize: int = 1, write: bool = False) -> None:
348+
"""Apply throttling based on delay rules and request type.
349+
350+
This method blocks the calling thread if the minimum delay has
351+
not yet elapsed since the last read or write operation.
299352
300-
Parameter requestsize is the number of Pages to be read/written;
301-
multiply delay time by an appropriate factor.
353+
.. versionchanged:: 10.3.0
354+
The *write* parameter is now keyword-only.
302355
303-
Because this seizes the throttle lock, it will prevent any other
304-
thread from writing to the same site until the wait expires.
356+
.. deprecated:: 10.3.0
357+
The *requestsize* parameter has no effect and will be removed
358+
in a future release.
359+
360+
:param requestsize: Number of pages to be read or written.
361+
Deprecated since 10.3.0. No longer affects throttling.
362+
:param write: Whether the operation involves writing to the site.
363+
Write operations use a separate delay timer and lock.
305364
"""
306365
lock = self.lock_write if write else self.lock_read
307366
with lock:
308367
wait = self.waittime(write=write)
309-
# Calculate the multiplicity of the next delay based on how
310-
# big the request is that is being posted now.
311-
# We want to add "one delay" for each factor of two in the
312-
# size of the request. Getting 64 pages at once allows 6 times
313-
# the delay time for the server.
314-
self.next_multiplicity = math.log(1 + requestsize) / math.log(2.0)
315-
316368
self.wait(wait)
317369

370+
now = time.time()
318371
if write:
319-
self.last_write = time.time()
372+
self.last_write = now
320373
else:
321-
self.last_read = time.time()
374+
self.last_read = now
322375

323376
def lag(self, lagtime: float | None = None) -> None:
324377
"""Seize the throttle lock due to server lag.

0 commit comments

Comments
 (0)