Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
small changes
  • Loading branch information
brijkapadia committed Feb 28, 2026
commit 7b4955f495962b318dc3e603a495f88a864e0034
2 changes: 1 addition & 1 deletion Lib/test/test_functools.py
Original file line number Diff line number Diff line change
Expand Up @@ -514,7 +514,7 @@ def test_partial_genericalias(self):
self.assertEqual(alias.__args__, (int,))
self.assertEqual(alias.__parameters__, ())

# Issue 144475
# GH-144475: Tests that the partial object does not change until repr finishes
def test_repr_saftey_against_reentrant_mutation(self):
Comment thread
brijkapadia marked this conversation as resolved.
Outdated
g_partial = None

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
Fixed a bug in :func:`functools.partial` when calling :func:`repr` on a partial
object that could occur when the ``fn``, ``args``, or ``kw`` arguments are modified
during a call to :func:`repr`. Now, calls to :func:`repr` will use the original
arguments when generating the string representation of the partial object.
Subsequent calls will use the updated arguments instead.

Calling :func:`repr` on :func:`functools.partial` will no longer
use a mutated version of the arguments ``fn``, ``args``, or ``kw``
when generating the string representation of the partial object.
26 changes: 12 additions & 14 deletions Modules/_functoolsmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -689,9 +689,9 @@ partial_repr(PyObject *self)
partialobject *pto = partialobject_CAST(self);
PyObject *result = NULL;
PyObject *fn, *args, *kw;
PyObject *arglist;
PyObject *mod;
PyObject *name;
PyObject *arglist = NULL;
PyObject *mod = NULL;
PyObject *name = NULL;
Py_ssize_t i, n;
PyObject *key, *value;
int status;
Expand All @@ -712,15 +712,15 @@ partial_repr(PyObject *self)

arglist = Py_GetConstant(Py_CONSTANT_EMPTY_STR);
if (arglist == NULL) {
goto arglist_error;
goto done;
}
/* Pack positional arguments */
n = PyTuple_GET_SIZE(args);
for (i = 0; i < n; i++) {
Py_SETREF(arglist, PyUnicode_FromFormat("%U, %R", arglist,
PyTuple_GET_ITEM(args, i)));
if (arglist == NULL) {
goto arglist_error;
goto done;
}
}
/* Pack keyword arguments */
Expand All @@ -731,27 +731,25 @@ partial_repr(PyObject *self)
key, value));
Py_DECREF(value);
if (arglist == NULL) {
goto arglist_error;
goto done;
}
}

mod = PyType_GetModuleName(Py_TYPE(pto));
if (mod == NULL) {
goto mod_error;
goto done;
}

name = PyType_GetQualName(Py_TYPE(pto));
if (name == NULL) {
goto name_error;
goto done;
}

result = PyUnicode_FromFormat("%S.%S(%R%U)", mod, name, fn, arglist);
Py_DECREF(name);
name_error:
Py_DECREF(mod);
mod_error:
Py_DECREF(arglist);
arglist_error:
done:
Py_XDECREF(name);
Py_XDECREF(mod);
Py_XDECREF(arglist);
Py_DECREF(fn);
Py_DECREF(args);
Py_DECREF(kw);
Expand Down
Loading