https://github.com/python/cpython/commit/8f5be78bce95deb338e2e1cf13a0a579b3b42dd2
commit: 8f5be78bce95deb338e2e1cf13a0a579b3b42dd2
branch: main
author: Furkan Onder <[email protected]>
committer: serhiy-storchaka <[email protected]>
date: 2024-02-25T22:55:19+02:00
summary:

gh-72249: Include the module name in the repr of partial object (GH-101910)

Co-authored-by: Anilyka Barry <[email protected]>

files:
A Misc/NEWS.d/next/Library/2023-02-14-17-19-59.gh-issue-72249.fv35wU.rst
M Lib/functools.py
M Lib/test/test_functools.py
M Modules/_functoolsmodule.c

diff --git a/Lib/functools.py b/Lib/functools.py
index 7045be551c8c49..601cb8e7c0b74b 100644
--- a/Lib/functools.py
+++ b/Lib/functools.py
@@ -303,13 +303,13 @@ def __call__(self, /, *args, **keywords):
 
     @recursive_repr()
     def __repr__(self):
-        qualname = type(self).__qualname__
+        cls = type(self)
+        qualname = cls.__qualname__
+        module = cls.__module__
         args = [repr(self.func)]
         args.extend(repr(x) for x in self.args)
         args.extend(f"{k}={v!r}" for (k, v) in self.keywords.items())
-        if type(self).__module__ == "functools":
-            return f"functools.{qualname}({', '.join(args)})"
-        return f"{qualname}({', '.join(args)})"
+        return f"{module}.{qualname}({', '.join(args)})"
 
     def __reduce__(self):
         return type(self), (self.func,), (self.func, self.args,
diff --git a/Lib/test/test_functools.py b/Lib/test/test_functools.py
index 2c814d5e888840..4eb322644fc541 100644
--- a/Lib/test/test_functools.py
+++ b/Lib/test/test_functools.py
@@ -31,10 +31,6 @@
 
 decimal = import_helper.import_fresh_module('decimal', fresh=['_decimal'])
 
-_partial_types = [py_functools.partial]
-if c_functools:
-    _partial_types.append(c_functools.partial)
-
 
 @contextlib.contextmanager
 def replaced_module(name, replacement):
@@ -207,10 +203,7 @@ def test_repr(self):
         kwargs = {'a': object(), 'b': object()}
         kwargs_reprs = ['a={a!r}, b={b!r}'.format_map(kwargs),
                         'b={b!r}, a={a!r}'.format_map(kwargs)]
-        if self.partial in _partial_types:
-            name = 'functools.partial'
-        else:
-            name = self.partial.__name__
+        name = f"{self.partial.__module__}.{self.partial.__qualname__}"
 
         f = self.partial(capture)
         self.assertEqual(f'{name}({capture!r})', repr(f))
@@ -229,10 +222,7 @@ def test_repr(self):
                        for kwargs_repr in kwargs_reprs])
 
     def test_recursive_repr(self):
-        if self.partial in _partial_types:
-            name = 'functools.partial'
-        else:
-            name = self.partial.__name__
+        name = f"{self.partial.__module__}.{self.partial.__qualname__}"
 
         f = self.partial(capture)
         f.__setstate__((f, (), {}, {}))
diff --git 
a/Misc/NEWS.d/next/Library/2023-02-14-17-19-59.gh-issue-72249.fv35wU.rst 
b/Misc/NEWS.d/next/Library/2023-02-14-17-19-59.gh-issue-72249.fv35wU.rst
new file mode 100644
index 00000000000000..10cc5a4e7528dd
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2023-02-14-17-19-59.gh-issue-72249.fv35wU.rst
@@ -0,0 +1,2 @@
+:func:`functools.partial`s of :func:`repr` has been improved to include the
+:term:`module` name. Patched by Furkan Onder and Anilyka Barry.
diff --git a/Modules/_functoolsmodule.c b/Modules/_functoolsmodule.c
index 9ab847165dc097..d2212d40550a3c 100644
--- a/Modules/_functoolsmodule.c
+++ b/Modules/_functoolsmodule.c
@@ -365,6 +365,8 @@ partial_repr(partialobject *pto)
 {
     PyObject *result = NULL;
     PyObject *arglist;
+    PyObject *mod;
+    PyObject *name;
     Py_ssize_t i, n;
     PyObject *key, *value;
     int status;
@@ -399,13 +401,28 @@ partial_repr(partialobject *pto)
         if (arglist == NULL)
             goto done;
     }
-    result = PyUnicode_FromFormat("%s(%R%U)", Py_TYPE(pto)->tp_name,
-                                  pto->fn, arglist);
+
+    mod = _PyType_GetModuleName(Py_TYPE(pto));
+    if (mod == NULL) {
+        goto error;
+    }
+    name = PyType_GetQualName(Py_TYPE(pto));
+    if (name == NULL) {
+        Py_DECREF(mod);
+        goto error;
+    }
+    result = PyUnicode_FromFormat("%S.%S(%R%U)", mod, name, pto->fn, arglist);
+    Py_DECREF(mod);
+    Py_DECREF(name);
     Py_DECREF(arglist);
 
  done:
     Py_ReprLeave((PyObject *)pto);
     return result;
+ error:
+    Py_DECREF(arglist);
+    Py_ReprLeave((PyObject *)pto);
+    return NULL;
 }
 
 /* Pickle strategy:

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: [email protected]

Reply via email to