Skip to content

Commit eed32df

Browse files
bpo-24391: Better reprs for threading objects. (GH-20534)
Add reprs for Semaphore, BoundedSemaphore, Event, and Barrier.
1 parent b6fe857 commit eed32df

File tree

3 files changed

+61
-0
lines changed

3 files changed

+61
-0
lines changed

Lib/test/lock_tests.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -455,6 +455,12 @@ def test_at_fork_reinit(self):
455455
with evt._cond:
456456
self.assertFalse(evt._cond.acquire(False))
457457

458+
def test_repr(self):
459+
evt = self.eventtype()
460+
self.assertRegex(repr(evt), r"<\w+\.Event at .*: unset>")
461+
evt.set()
462+
self.assertRegex(repr(evt), r"<\w+\.Event at .*: set>")
463+
458464

459465
class ConditionTests(BaseTestCase):
460466
"""
@@ -802,6 +808,15 @@ def test_release_unacquired(self):
802808
sem.acquire()
803809
sem.release()
804810

811+
def test_repr(self):
812+
sem = self.semtype(3)
813+
self.assertRegex(repr(sem), r"<\w+\.Semaphore at .*: value=3>")
814+
sem.acquire()
815+
self.assertRegex(repr(sem), r"<\w+\.Semaphore at .*: value=2>")
816+
sem.release()
817+
sem.release()
818+
self.assertRegex(repr(sem), r"<\w+\.Semaphore at .*: value=4>")
819+
805820

806821
class BoundedSemaphoreTests(BaseSemaphoreTests):
807822
"""
@@ -816,6 +831,12 @@ def test_release_unacquired(self):
816831
sem.release()
817832
self.assertRaises(ValueError, sem.release)
818833

834+
def test_repr(self):
835+
sem = self.semtype(3)
836+
self.assertRegex(repr(sem), r"<\w+\.BoundedSemaphore at .*: value=3/3>")
837+
sem.acquire()
838+
self.assertRegex(repr(sem), r"<\w+\.BoundedSemaphore at .*: value=2/3>")
839+
819840

820841
class BarrierTests(BaseTestCase):
821842
"""
@@ -1008,3 +1029,18 @@ def test_single_thread(self):
10081029
b = self.barriertype(1)
10091030
b.wait()
10101031
b.wait()
1032+
1033+
def test_repr(self):
1034+
b = self.barriertype(3)
1035+
self.assertRegex(repr(b), r"<\w+\.Barrier at .*: waiters=0/3>")
1036+
def f():
1037+
b.wait(3)
1038+
bunch = Bunch(f, 2)
1039+
bunch.wait_for_started()
1040+
time.sleep(0.2)
1041+
self.assertRegex(repr(b), r"<\w+\.Barrier at .*: waiters=2/3>")
1042+
b.wait(3)
1043+
bunch.wait_for_finished()
1044+
self.assertRegex(repr(b), r"<\w+\.Barrier at .*: waiters=0/3>")
1045+
b.abort()
1046+
self.assertRegex(repr(b), r"<\w+\.Barrier at .*: broken>")

Lib/threading.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -418,6 +418,11 @@ def __init__(self, value=1):
418418
self._cond = Condition(Lock())
419419
self._value = value
420420

421+
def __repr__(self):
422+
cls = self.__class__
423+
return (f"<{cls.__module__}.{cls.__qualname__} at {id(self):#x}:"
424+
f" value={self._value}>")
425+
421426
def acquire(self, blocking=True, timeout=None):
422427
"""Acquire a semaphore, decrementing the internal counter by one.
423428
@@ -504,6 +509,11 @@ def __init__(self, value=1):
504509
Semaphore.__init__(self, value)
505510
self._initial_value = value
506511

512+
def __repr__(self):
513+
cls = self.__class__
514+
return (f"<{cls.__module__}.{cls.__qualname__} at {id(self):#x}:"
515+
f" value={self._value}/{self._initial_value}>")
516+
507517
def release(self, n=1):
508518
"""Release a semaphore, incrementing the internal counter by one or more.
509519
@@ -539,6 +549,11 @@ def __init__(self):
539549
self._cond = Condition(Lock())
540550
self._flag = False
541551

552+
def __repr__(self):
553+
cls = self.__class__
554+
status = 'set' if self._flag else 'unset'
555+
return f"<{cls.__module__}.{cls.__qualname__} at {id(self):#x}: {status}>"
556+
542557
def _at_fork_reinit(self):
543558
# Private method called by Thread._reset_internal_locks()
544559
self._cond._at_fork_reinit()
@@ -637,6 +652,13 @@ def __init__(self, parties, action=None, timeout=None):
637652
self._state = 0 #0 filling, 1, draining, -1 resetting, -2 broken
638653
self._count = 0
639654

655+
def __repr__(self):
656+
cls = self.__class__
657+
if self.broken:
658+
return f"<{cls.__module__}.{cls.__qualname__} at {id(self):#x}: broken>"
659+
return (f"<{cls.__module__}.{cls.__qualname__} at {id(self):#x}:"
660+
f" waiters={self.n_waiting}/{self.parties}>")
661+
640662
def wait(self, timeout=None):
641663
"""Wait for the barrier.
642664
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Improved reprs of :mod:`threading` synchronization objects:
2+
:class:`~threading.Semaphore`, :class:`~threading.BoundedSemaphore`,
3+
:class:`~threading.Event` and :class:`~threading.Barrier`.

0 commit comments

Comments
 (0)