Write object *obj* to file object *p*. The only supported flag for *flags* is
:c:macro:`Py_PRINT_RAW`; if given, the :func:`str` of the object is written
- instead of the :func:`repr`. Return ``0`` on success or ``-1`` on failure; the
- appropriate exception will be set.
+ instead of the :func:`repr`.
+
+ If *obj* is ``NULL``, write the string ``"<NULL>"``.
+ Return ``0`` on success or ``-1`` on failure; the
+ appropriate exception will be set.
.. c:function:: int PyFile_WriteString(const char *s, PyObject *p)
representation on success, ``NULL`` on failure. This is the equivalent of the
Python expression ``repr(o)``. Called by the :func:`repr` built-in function.
+ If argument is ``NULL``, return the string ``'<NULL>'``.
+
.. versionchanged:: 3.4
This function now includes a debug assertion to help ensure that it
does not silently discard an active exception.
a string similar to that returned by :c:func:`PyObject_Repr` in Python 2.
Called by the :func:`ascii` built-in function.
+ If argument is ``NULL``, return the string ``'<NULL>'``.
+
.. index:: string; PyObject_Str (C function)
Python expression ``str(o)``. Called by the :func:`str` built-in function
and, therefore, by the :func:`print` function.
+ If argument is ``NULL``, return the string ``'<NULL>'``.
+
.. versionchanged:: 3.4
This function now includes a debug assertion to help ensure that it
does not silently discard an active exception.
a TypeError is raised when *o* is an integer instead of a zero-initialized
bytes object.
+ If argument is ``NULL``, return the :class:`bytes` object ``b'<NULL>'``.
+
.. c:function:: int PyObject_IsSubclass(PyObject *derived, PyObject *cls)
Call :c:func:`PyObject_Repr` on *obj* and write the output into *writer*.
+ If *obj* is ``NULL``, write the string ``"<NULL>"`` into *writer*.
+
On success, return ``0``.
On error, set an exception, leave the writer unchanged, and return ``-1``.
# CRASHES list_extend(NULL, [])
# CRASHES list_extend([], NULL)
+ def test_uninitialized_list_repr(self):
+ lst = _testlimitedcapi.list_new(3)
+ self.assertEqual(repr(lst), '[<NULL>, <NULL>, <NULL>]')
+
if __name__ == "__main__":
unittest.main()
self.assertRaises(SystemError, tuple_new, PY_SSIZE_T_MIN)
self.assertRaises(MemoryError, tuple_new, PY_SSIZE_T_MAX)
+
def test_tuple_fromarray(self):
# Test PyTuple_FromArray()
tuple_fromarray = _testcapi.tuple_fromarray
self.assertEqual(tuple(my_iter()), (TAG, *range(10)))
self.assertEqual(tuples, [])
+ def test_uninitialized_tuple_repr(self):
+ tup = _testlimitedcapi.tuple_new(3)
+ self.assertEqual(repr(tup), '(<NULL>, <NULL>, <NULL>)')
+
if __name__ == "__main__":
unittest.main()
self.assertEqual(writer.finish(),
"var=long value 'repr'")
+ def test_repr_null(self):
+ writer = self.create_writer(0)
+ writer.write_utf8(b'var=', -1)
+ writer.write_repr(NULL)
+ self.assertEqual(writer.finish(),
+ "var=<NULL>")
+
def test_utf8(self):
writer = self.create_writer(0)
writer.write_utf8(b"ascii", -1)
--- /dev/null
+:c:func:`PyUnicodeWriter_WriteRepr` now supports ``NULL`` argument.
--- /dev/null
+Fix :meth:`!list.__repr__` for lists containing ``NULL``\ s.
if (!PyArg_ParseTuple(args, "O", &obj)) {
return NULL;
}
+ NULLABLE(obj);
if (PyUnicodeWriter_WriteRepr(self->writer, obj) < 0) {
return NULL;
so must refetch the list size on each iteration. */
for (Py_ssize_t i = 0; i < Py_SIZE(v); ++i) {
/* Hold a strong reference since repr(item) can mutate the list */
- item = Py_NewRef(v->ob_item[i]);
+ item = Py_XNewRef(v->ob_item[i]);
if (i > 0) {
if (PyUnicodeWriter_WriteChar(writer, ',') < 0) {
int
PyUnicodeWriter_WriteRepr(PyUnicodeWriter *writer, PyObject *obj)
{
+ if (obj == NULL) {
+ return _PyUnicodeWriter_WriteASCIIString((_PyUnicodeWriter*)writer, "<NULL>", 6);
+ }
+
if (Py_TYPE(obj) == &PyLong_Type) {
return _PyLong_FormatWriter((_PyUnicodeWriter*)writer, obj, 10, 0);
}