summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Lib/functools.py8
-rw-r--r--Lib/test/test_functools.py14
-rw-r--r--Misc/NEWS.d/next/Library/2023-02-14-17-19-59.gh-issue-72249.fv35wU.rst2
-rw-r--r--Modules/_functoolsmodule.c21
4 files changed, 27 insertions, 18 deletions
diff --git a/Lib/functools.py b/Lib/functools.py
index 7045be5..601cb8e 100644
--- a/Lib/functools.py
+++ b/Lib/functools.py
@@ -303,13 +303,13 @@ class partial:
@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 2c814d5..4eb3226 100644
--- a/Lib/test/test_functools.py
+++ b/Lib/test/test_functools.py
@@ -31,10 +31,6 @@ c_functools = import_helper.import_fresh_module('functools',
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 @@ class TestPartial:
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 @@ class TestPartial:
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 0000000..10cc5a4
--- /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 9ab8471..d2212d4 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: