Skip to content

Commit 62f4dad

Browse files
committed
Issue 21137: Better repr for threading.Lock()
1 parent fa4ed0c commit 62f4dad

6 files changed

Lines changed: 41 additions & 6 deletions

File tree

Lib/_dummy_thread.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,14 @@ def release(self):
140140
def locked(self):
141141
return self.locked_status
142142

143+
def __repr__(self):
144+
return "<%s %s.%s object at %s>" % (
145+
"locked" if self.locked_status else "unlocked",
146+
self.__class__.__module__,
147+
self.__class__.__qualname__,
148+
hex(id(self))
149+
)
150+
143151
# Used to signal that interrupt_main was called in a "thread"
144152
_interrupt = False
145153
# True when not executing in a "thread"

Lib/test/lock_tests.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,13 @@ def test_constructor(self):
8282

8383
def test_repr(self):
8484
lock = self.locktype()
85-
repr(lock)
85+
self.assertRegex(repr(lock), "<unlocked .* object (.*)?at .*>")
86+
del lock
87+
88+
def test_locked_repr(self):
89+
lock = self.locktype()
90+
lock.acquire()
91+
self.assertRegex(repr(lock), "<locked .* object (.*)?at .*>")
8692
del lock
8793

8894
def test_acquire_destroy(self):

Lib/test/test_importlib/test_locks.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ class ModuleLockAsRLockTests:
3131
test_timeout = None
3232
# _release_save() unsupported
3333
test_release_save_unacquired = None
34+
# lock status in repr unsupported
35+
test_repr = None
36+
test_locked_repr = None
3437

3538
LOCK_TYPES = {kind: splitinit._bootstrap._ModuleLock
3639
for kind, splitinit in init.items()}

Lib/threading.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,8 +106,14 @@ def __repr__(self):
106106
owner = _active[owner].name
107107
except KeyError:
108108
pass
109-
return "<%s owner=%r count=%d>" % (
110-
self.__class__.__name__, owner, self._count)
109+
return "<%s %s.%s object owner=%r count=%d at %s>" % (
110+
"locked" if self._block.locked() else "unlocked",
111+
self.__class__.__module__,
112+
self.__class__.__qualname__,
113+
owner,
114+
self._count,
115+
hex(id(self))
116+
)
111117

112118
def acquire(self, blocking=True, timeout=-1):
113119
"""Acquire a lock, blocking or non-blocking.

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,9 @@ Library
9797
- Issue #21513: Speedup some properties of IP addresses (IPv4Address,
9898
IPv6Address) such as .is_private or .is_multicast.
9999

100+
- Issue #21137: Improve the repr for threading.Lock() and its variants
101+
by showing the "locked" or "unlocked" status. Patch by Berker Peksag.
102+
100103
- Issue #21538: The plistlib module now supports loading of binary plist files
101104
when reference or offset size is not a power of two.
102105

Modules/_threadmodule.c

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,13 @@ PyDoc_STRVAR(locked_doc,
192192
\n\
193193
Return whether the lock is in the locked state.");
194194

195+
static PyObject *
196+
lock_repr(lockobject *self)
197+
{
198+
return PyUnicode_FromFormat("<%s %s object at %p>",
199+
self->locked ? "locked" : "unlocked", Py_TYPE(self)->tp_name, self);
200+
}
201+
195202
static PyMethodDef lock_methods[] = {
196203
{"acquire_lock", (PyCFunction)lock_PyThread_acquire_lock,
197204
METH_VARARGS | METH_KEYWORDS, acquire_doc},
@@ -223,7 +230,7 @@ static PyTypeObject Locktype = {
223230
0, /*tp_getattr*/
224231
0, /*tp_setattr*/
225232
0, /*tp_reserved*/
226-
0, /*tp_repr*/
233+
(reprfunc)lock_repr, /*tp_repr*/
227234
0, /*tp_as_number*/
228235
0, /*tp_as_sequence*/
229236
0, /*tp_as_mapping*/
@@ -475,8 +482,10 @@ rlock_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
475482
static PyObject *
476483
rlock_repr(rlockobject *self)
477484
{
478-
return PyUnicode_FromFormat("<%s owner=%ld count=%lu>",
479-
Py_TYPE(self)->tp_name, self->rlock_owner, self->rlock_count);
485+
return PyUnicode_FromFormat("<%s %s object owner=%ld count=%lu at %p>",
486+
self->rlock_count ? "locked" : "unlocked",
487+
Py_TYPE(self)->tp_name, self->rlock_owner,
488+
self->rlock_count, self);
480489
}
481490

482491

0 commit comments

Comments
 (0)