1717from __future__ import annotations
1818
1919import itertools
20- import math
2120import threading
2221import time
2322from collections import Counter
2827import pywikibot
2928from pywikibot import config
3029from pywikibot .backports import Counter as CounterType
31- from pywikibot .tools import deprecated
30+ from pywikibot .tools import deprecate_positionals , deprecated , deprecated_args
3231
3332
3433FORMAT_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