summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVictor Stinner <vstinner@python.org>2024-04-03 10:18:05 (GMT)
committerGitHub <noreply@github.com>2024-04-03 10:18:05 (GMT)
commit8ef98924d304b5c9430e23f8170e2c32ec3a9920 (patch)
treedc8cdd0dc2bed56c3c194cfeb11c2f4c83812542
parent8987a5c809343ae0dd2b8e607bf2c32a87773127 (diff)
downloadcpython-8ef98924d304b5c9430e23f8170e2c32ec3a9920.zip
cpython-8ef98924d304b5c9430e23f8170e2c32ec3a9920.tar.gz
cpython-8ef98924d304b5c9430e23f8170e2c32ec3a9920.tar.bz2
gh-117281: Change weakref repr() to fully qualified name (#117285)
Use the fully qualified type name in repr() of weakref.ref and weakref.proxy types. Fix a crash in proxy_repr() when the reference is dead. Add also test_ref_repr() and test_proxy_repr().
-rw-r--r--Lib/test/test_weakref.py41
-rw-r--r--Objects/weakrefobject.c24
2 files changed, 57 insertions, 8 deletions
diff --git a/Lib/test/test_weakref.py b/Lib/test/test_weakref.py
index 4cdd66d..d6470fb 100644
--- a/Lib/test/test_weakref.py
+++ b/Lib/test/test_weakref.py
@@ -116,6 +116,33 @@ class ReferencesTestCase(TestBase):
del o
repr(wr)
+ @support.cpython_only
+ def test_ref_repr(self):
+ obj = C()
+ ref = weakref.ref(obj)
+ self.assertRegex(repr(ref),
+ rf"<weakref at 0x[0-9a-fA-F]+; "
+ rf"to '{C.__module__}.{C.__qualname__}' "
+ rf"at 0x[0-9a-fA-F]+>")
+
+ obj = None
+ gc_collect()
+ self.assertRegex(repr(ref),
+ rf'<weakref at 0x[0-9a-fA-F]+; dead>')
+
+ # test type with __name__
+ class WithName:
+ @property
+ def __name__(self):
+ return "custom_name"
+
+ obj2 = WithName()
+ ref2 = weakref.ref(obj2)
+ self.assertRegex(repr(ref2),
+ rf"<weakref at 0x[0-9a-fA-F]+; "
+ rf"to '{WithName.__module__}.{WithName.__qualname__}' "
+ rf"at 0x[0-9a-fA-F]+ \(custom_name\)>")
+
def test_repr_failure_gh99184(self):
class MyConfig(dict):
def __getattr__(self, x):
@@ -195,6 +222,20 @@ class ReferencesTestCase(TestBase):
self.assertRaises(ReferenceError, bool, ref3)
self.assertEqual(self.cbcalled, 2)
+ @support.cpython_only
+ def test_proxy_repr(self):
+ obj = C()
+ ref = weakref.proxy(obj, self.callback)
+ self.assertRegex(repr(ref),
+ rf"<weakproxy at 0x[0-9a-fA-F]+; "
+ rf"to '{C.__module__}.{C.__qualname__}' "
+ rf"at 0x[0-9a-fA-F]+>")
+
+ obj = None
+ gc_collect()
+ self.assertRegex(repr(ref),
+ rf'<weakproxy at 0x[0-9a-fA-F]+; dead>')
+
def check_basic_ref(self, factory):
o = factory()
ref = weakref.ref(o)
diff --git a/Objects/weakrefobject.c b/Objects/weakrefobject.c
index b7b2906..d8dd6ae 100644
--- a/Objects/weakrefobject.c
+++ b/Objects/weakrefobject.c
@@ -177,13 +177,13 @@ weakref_repr(PyObject *self)
PyObject *repr;
if (name == NULL || !PyUnicode_Check(name)) {
repr = PyUnicode_FromFormat(
- "<weakref at %p; to '%s' at %p>",
- self, Py_TYPE(obj)->tp_name, obj);
+ "<weakref at %p; to '%T' at %p>",
+ self, obj, obj);
}
else {
repr = PyUnicode_FromFormat(
- "<weakref at %p; to '%s' at %p (%U)>",
- self, Py_TYPE(obj)->tp_name, obj, name);
+ "<weakref at %p; to '%T' at %p (%U)>",
+ self, obj, obj, name);
}
Py_DECREF(obj);
Py_XDECREF(name);
@@ -471,10 +471,18 @@ static PyObject *
proxy_repr(PyObject *proxy)
{
PyObject *obj = _PyWeakref_GET_REF(proxy);
- PyObject *repr = PyUnicode_FromFormat(
- "<weakproxy at %p to %s at %p>",
- proxy, Py_TYPE(obj)->tp_name, obj);
- Py_DECREF(obj);
+ PyObject *repr;
+ if (obj != NULL) {
+ repr = PyUnicode_FromFormat(
+ "<weakproxy at %p; to '%T' at %p>",
+ proxy, obj, obj);
+ Py_DECREF(obj);
+ }
+ else {
+ repr = PyUnicode_FromFormat(
+ "<weakproxy at %p; dead>",
+ proxy);
+ }
return repr;
}