14
14
and/or the lease has been lost.
15
15
16
16
"""
17
- from __future__ import annotations
18
-
19
17
import re
20
18
import time
21
- from typing import TYPE_CHECKING , cast , ContextManager
22
19
import uuid
23
20
24
21
from kazoo .exceptions import (
34
31
RetryFailedError ,
35
32
)
36
33
37
- if TYPE_CHECKING :
38
- from kazoo .client import KazooClient
39
- from kazoo .protocol .states import WatchedEvent
40
- from typing import (
41
- Any ,
42
- List ,
43
- Optional ,
44
- Sequence ,
45
- Type ,
46
- Union ,
47
- )
48
- from typing_extensions import Literal
49
-
50
34
51
35
class _Watch (object ):
52
- def __init__ (self , duration : Optional [ float ] = None ):
36
+ def __init__ (self , duration = None ):
53
37
self .duration = duration
54
- self .started_at : Optional [ float ] = None
38
+ self .started_at = None
55
39
56
- def start (self ) -> None :
40
+ def start (self ):
57
41
self .started_at = time .monotonic ()
58
42
59
- def leftover (self ) -> Optional [ float ] :
43
+ def leftover (self ):
60
44
if self .duration is None :
61
45
return None
62
46
else :
63
- elapsed = time .monotonic () - cast ( float , self .started_at )
47
+ elapsed = time .monotonic () - self .started_at
64
48
return max (0 , self .duration - elapsed )
65
49
66
50
67
- class Lock (ContextManager [ None ] ):
51
+ class Lock (object ):
68
52
"""Kazoo Lock
69
53
70
54
Example usage with a :class:`~kazoo.client.KazooClient` instance:
@@ -93,13 +77,7 @@ class Lock(ContextManager[None]):
93
77
# sequence number. Involved in read/write locks.
94
78
_EXCLUDE_NAMES = ["__lock__" ]
95
79
96
- def __init__ (
97
- self ,
98
- client : KazooClient ,
99
- path : str ,
100
- identifier : Optional [str ] = None ,
101
- extra_lock_patterns : Sequence [str ] = (),
102
- ):
80
+ def __init__ (self , client , path , identifier = None , extra_lock_patterns = ()):
103
81
"""Create a Kazoo lock.
104
82
105
83
:param client: A :class:`~kazoo.client.KazooClient` instance.
@@ -131,7 +109,7 @@ def __init__(
131
109
# some data is written to the node. this can be queried via
132
110
# contenders() to see who is contending for the lock
133
111
self .data = str (identifier or "" ).encode ("utf-8" )
134
- self .node : Optional [ str ] = None
112
+ self .node = None
135
113
136
114
self .wake_event = client .handler .event_object ()
137
115
@@ -147,25 +125,20 @@ def __init__(
147
125
self .assured_path = False
148
126
self .cancelled = False
149
127
self ._retry = KazooRetry (
150
- max_tries = - 1 , sleep_func = client .handler .sleep_func
128
+ max_tries = None , sleep_func = client .handler .sleep_func
151
129
)
152
130
self ._acquire_method_lock = client .handler .lock_object ()
153
131
154
- def _ensure_path (self ) -> None :
132
+ def _ensure_path (self ):
155
133
self .client .ensure_path (self .path )
156
134
self .assured_path = True
157
135
158
- def cancel (self ) -> None :
136
+ def cancel (self ):
159
137
"""Cancel a pending lock acquire."""
160
138
self .cancelled = True
161
139
self .wake_event .set ()
162
140
163
- def acquire (
164
- self ,
165
- blocking : bool = True ,
166
- timeout : Optional [float ] = None ,
167
- ephemeral : bool = True ,
168
- ) -> bool :
141
+ def acquire (self , blocking = True , timeout = None , ephemeral = True ):
169
142
"""
170
143
Acquire the lock. By defaults blocks and waits forever.
171
144
@@ -231,13 +204,11 @@ def acquire(
231
204
finally :
232
205
self ._acquire_method_lock .release ()
233
206
234
- def _watch_session (self , state : KazooState ) -> bool :
207
+ def _watch_session (self , state ) :
235
208
self .wake_event .set ()
236
209
return True
237
210
238
- def _inner_acquire (
239
- self , blocking : bool , timeout : Optional [float ], ephemeral : bool = True
240
- ) -> bool :
211
+ def _inner_acquire (self , blocking , timeout , ephemeral = True ):
241
212
242
213
# wait until it's our chance to get it..
243
214
if self .is_acquired :
@@ -295,10 +266,10 @@ def _inner_acquire(
295
266
finally :
296
267
self .client .remove_listener (self ._watch_session )
297
268
298
- def _watch_predecessor (self , event : WatchedEvent ) -> None :
269
+ def _watch_predecessor (self , event ) :
299
270
self .wake_event .set ()
300
271
301
- def _get_predecessor (self , node : str ) -> Optional [ str ] :
272
+ def _get_predecessor (self , node ) :
302
273
"""returns `node`'s predecessor or None
303
274
304
275
Note: This handle the case where the current lock is not a contender
@@ -307,7 +278,7 @@ def _get_predecessor(self, node: str) -> Optional[str]:
307
278
"""
308
279
node_sequence = node [len (self .prefix ) :]
309
280
children = self .client .get_children (self .path )
310
- found_self : Union [ Literal [ False ], re . Match [ bytes ]] = False
281
+ found_self = False
311
282
# Filter out the contenders using the computed regex
312
283
contender_matches = []
313
284
for child in children :
@@ -322,7 +293,7 @@ def _get_predecessor(self, node: str) -> Optional[str]:
322
293
if child == node :
323
294
# Remember the node's match object so we can short circuit
324
295
# below.
325
- found_self = cast ( re . Match [ bytes ], match )
296
+ found_self = match
326
297
327
298
if found_self is False : # pragma: nocover
328
299
# somehow we aren't in the childrens -- probably we are
@@ -338,42 +309,42 @@ def _get_predecessor(self, node: str) -> Optional[str]:
338
309
sorted_matches = sorted (contender_matches , key = lambda m : m .groups ())
339
310
return sorted_matches [- 1 ].string
340
311
341
- def _find_node (self ) -> Optional [ str ] :
312
+ def _find_node (self ):
342
313
children = self .client .get_children (self .path )
343
314
for child in children :
344
315
if child .startswith (self .prefix ):
345
316
return child
346
317
return None
347
318
348
- def _delete_node (self , node : str ) -> None :
319
+ def _delete_node (self , node ) :
349
320
self .client .delete (self .path + "/" + node )
350
321
351
- def _best_effort_cleanup (self ) -> None :
322
+ def _best_effort_cleanup (self ):
352
323
try :
353
324
node = self .node or self ._find_node ()
354
325
if node :
355
326
self ._delete_node (node )
356
327
except KazooException : # pragma: nocover
357
328
pass
358
329
359
- def release (self ) -> bool :
330
+ def release (self ):
360
331
"""Release the lock immediately."""
361
332
return self .client .retry (self ._inner_release )
362
333
363
- def _inner_release (self ) -> bool :
334
+ def _inner_release (self ):
364
335
if not self .is_acquired :
365
336
return False
366
337
367
338
try :
368
- self ._delete_node (cast ( str , self .node ) )
339
+ self ._delete_node (self .node )
369
340
except NoNodeError : # pragma: nocover
370
341
pass
371
342
372
343
self .is_acquired = False
373
344
self .node = None
374
345
return True
375
346
376
- def contenders (self ) -> List [ str ] :
347
+ def contenders (self ):
377
348
"""Return an ordered list of the current contenders for the
378
349
lock.
379
350
@@ -409,7 +380,7 @@ def contenders(self) -> List[str]:
409
380
for match in sorted (contender_matches , key = lambda m : m .groups ())
410
381
]
411
382
# Retrieve all the contender nodes data (preserving order).
412
- contenders : List [ str ] = []
383
+ contenders = []
413
384
for node in contender_nodes :
414
385
try :
415
386
data , stat = self .client .get (self .path + "/" + node )
@@ -420,15 +391,10 @@ def contenders(self) -> List[str]:
420
391
421
392
return contenders
422
393
423
- def __enter__ (self ) -> None :
394
+ def __enter__ (self ):
424
395
self .acquire ()
425
396
426
- def __exit__ (
427
- self ,
428
- exc_type : Optional [Type [BaseException ]],
429
- exc_value : Optional [BaseException ],
430
- traceback : Any ,
431
- ) -> None :
397
+ def __exit__ (self , exc_type , exc_value , traceback ):
432
398
self .release ()
433
399
434
400
@@ -492,7 +458,7 @@ class ReadLock(Lock):
492
458
_EXCLUDE_NAMES = ["__lock__" ]
493
459
494
460
495
- class Semaphore (ContextManager [ None ] ):
461
+ class Semaphore (object ):
496
462
"""A Zookeeper-based Semaphore
497
463
498
464
This synchronization primitive operates in the same manner as the
@@ -527,13 +493,7 @@ class Semaphore(ContextManager[None]):
527
493
528
494
"""
529
495
530
- def __init__ (
531
- self ,
532
- client : KazooClient ,
533
- path : str ,
534
- identifier : Optional [str ] = None ,
535
- max_leases : int = 1 ,
536
- ):
496
+ def __init__ (self , client , path , identifier = None , max_leases = 1 ):
537
497
"""Create a Kazoo Lock
538
498
539
499
:param client: A :class:`~kazoo.client.KazooClient` instance.
@@ -569,7 +529,7 @@ def __init__(
569
529
self .cancelled = False
570
530
self ._session_expired = False
571
531
572
- def _ensure_path (self ) -> None :
532
+ def _ensure_path (self ):
573
533
result = self .client .ensure_path (self .path )
574
534
self .assured_path = True
575
535
if result is True :
@@ -590,14 +550,12 @@ def _ensure_path(self) -> None:
590
550
else :
591
551
self .client .set (self .path , str (self .max_leases ).encode ("utf-8" ))
592
552
593
- def cancel (self ) -> None :
553
+ def cancel (self ):
594
554
"""Cancel a pending semaphore acquire."""
595
555
self .cancelled = True
596
556
self .wake_event .set ()
597
557
598
- def acquire (
599
- self , blocking : bool = True , timeout : Optional [float ] = None
600
- ) -> bool :
558
+ def acquire (self , blocking = True , timeout = None ):
601
559
"""Acquire the semaphore. By defaults blocks and waits forever.
602
560
603
561
:param blocking: Block until semaphore is obtained or
@@ -635,9 +593,7 @@ def acquire(
635
593
636
594
return self .is_acquired
637
595
638
- def _inner_acquire (
639
- self , blocking : bool , timeout : Optional [float ] = None
640
- ) -> bool :
596
+ def _inner_acquire (self , blocking , timeout = None ):
641
597
"""Inner loop that runs from the top anytime a command hits a
642
598
retryable Zookeeper exception."""
643
599
self ._session_expired = False
@@ -678,10 +634,10 @@ def _inner_acquire(
678
634
finally :
679
635
lock .release ()
680
636
681
- def _watch_lease_change (self , event : WatchedEvent ) -> None :
637
+ def _watch_lease_change (self , event ) :
682
638
self .wake_event .set ()
683
639
684
- def _get_lease (self ) -> bool :
640
+ def _get_lease (self , data = None ) :
685
641
# Make sure the session is still valid
686
642
if self ._session_expired :
687
643
raise ForceRetryError ("Retry on session loss at top" )
@@ -710,26 +666,25 @@ def _get_lease(self) -> bool:
710
666
# Return current state
711
667
return self .is_acquired
712
668
713
- def _watch_session (self , state : KazooState ) -> Optional [ Literal [ True ]] :
669
+ def _watch_session (self , state ) :
714
670
if state == KazooState .LOST :
715
671
self ._session_expired = True
716
672
self .wake_event .set ()
717
673
718
674
# Return true to de-register
719
675
return True
720
- return None
721
676
722
- def _best_effort_cleanup (self ) -> None :
677
+ def _best_effort_cleanup (self ):
723
678
try :
724
679
self .client .delete (self .create_path )
725
680
except KazooException : # pragma: nocover
726
681
pass
727
682
728
- def release (self ) -> bool :
683
+ def release (self ):
729
684
"""Release the lease immediately."""
730
685
return self .client .retry (self ._inner_release )
731
686
732
- def _inner_release (self ) -> bool :
687
+ def _inner_release (self ):
733
688
if not self .is_acquired :
734
689
return False
735
690
try :
@@ -739,7 +694,7 @@ def _inner_release(self) -> bool:
739
694
self .is_acquired = False
740
695
return True
741
696
742
- def lease_holders (self ) -> List [ str ] :
697
+ def lease_holders (self ):
743
698
"""Return an unordered list of the current lease holders.
744
699
745
700
.. note::
@@ -753,7 +708,7 @@ def lease_holders(self) -> List[str]:
753
708
754
709
children = self .client .get_children (self .path )
755
710
756
- lease_holders : List [ str ] = []
711
+ lease_holders = []
757
712
for child in children :
758
713
try :
759
714
data , stat = self .client .get (self .path + "/" + child )
@@ -762,13 +717,8 @@ def lease_holders(self) -> List[str]:
762
717
pass
763
718
return lease_holders
764
719
765
- def __enter__ (self ) -> None :
720
+ def __enter__ (self ):
766
721
self .acquire ()
767
722
768
- def __exit__ (
769
- self ,
770
- exc_type : Optional [Type [BaseException ]],
771
- exc_value : Optional [BaseException ],
772
- traceback : Any ,
773
- ) -> None :
723
+ def __exit__ (self , exc_type , exc_value , traceback ):
774
724
self .release ()
0 commit comments