@@ -533,6 +533,35 @@ recursion depth automatically).
533533 Ends a :c:func:`Py_EnterRecursiveCall`. Must be called once for each
534534 *successful* invocation of :c:func:`Py_EnterRecursiveCall`.
535535
536+ Properly implementing :attr:`tp_repr` for container types requires
537+ special recursion handling. In addition to protecting the stack,
538+ :attr:`tp_repr` also needs to track objects to prevent cycles. The
539+ following two functions facilitate this functionality. Effectively,
540+ these are the C equivalent to :func:`reprlib.recursive_repr`.
541+
542+ .. c:function:: int Py_ReprEntr(PyObject *object)
543+
544+ Called at the beginning of the :attr: `tp_repr ` implementation to
545+ detect cycles.
546+
547+ If the object has already been processed, the function returns a
548+ positive integer. In that case the :attr: `tp_repr ` implementation
549+ should return a string object indicating a cycle. As examples,
550+ :class: `dict ` objects return ``{...} `` and :class: `list ` objects
551+ return ``[...] ``.
552+
553+ The function will return a negative integer if the recursion limit
554+ is reached. In that case the :attr: `tp_repr ` implementation should
555+ typically return ``NULL ``.
556+
557+ Otherwise, the function returns zero and the :attr: `tp_repr `
558+ implementation can continue normally.
559+
560+ .. c :function :: void Py_ReprLeave (PyObject *object)
561+
562+ Ends a :c:func: `Py_ReprEntr `. Must be called once for each
563+ invocation of :c:func: `Py_ReprEntr ` that returns zero.
564+
536565
537566.. _standardexceptions :
538567
0 commit comments