Skip to content

Commit 62a1c04

Browse files
committed
Flesh out PyObject_Pretty()
* Document it in the C-API docs. * Express the refcounting semantics in refcounts.dat. * Describe PyObject_Pretty in the stable_abi.dat and stable_abi.toml files. * Add tests to test_capi/test_abstract.py
1 parent 556a20d commit 62a1c04

File tree

7 files changed

+52
-0
lines changed

7 files changed

+52
-0
lines changed

Doc/c-api/object.rst

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,15 @@ Object Protocol
380380
.. index:: string; PyObject_Str (C function)
381381
382382
383+
.. c:function:: PyObject* PyObject_Pretty(PyObject *o)
384+
385+
Return the "pretty" representation of an object *o*, which must not be
386+
``NULL``. This is used by the ``!p`` specifier for both f-strings and
387+
:func:`str.format`. This function is not directly exposed in Python.
388+
389+
.. versionadded:: 3.15
390+
391+
383392
.. c:function:: PyObject* PyObject_Str(PyObject *o)
384393
385394
Compute a string representation of object *o*. Returns the string

Doc/data/refcounts.dat

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1690,6 +1690,9 @@ PyOS_FSPath:PyObject*:path:0:
16901690
PyObject_ASCII:PyObject*::+1:
16911691
PyObject_ASCII:PyObject*:o:0:
16921692

1693+
PyObject_Pretty:PyObject*::+1:
1694+
PyObject_Pretty:PyObject*:o:0:
1695+
16931696
PyObject_Bytes:PyObject*::+1:
16941697
PyObject_Bytes:PyObject*:o:0:
16951698

Doc/data/stable_abi.dat

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Lib/test/test_capi/test_abstract.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,35 @@ def test_object_ascii(self):
112112
self.assertTypedEqual(object_ascii(WithRepr(StrSubclass('<\U0001f40d>'))), r'<\U0001f40d>')
113113
self.assertTypedEqual(object_ascii(NULL), '<NULL>')
114114

115+
def test_object_pretty(self):
116+
# Test PyObject_Pretty()
117+
import pprint
118+
object_pretty = _testlimitedcapi.object_pretty
119+
120+
# Simple objects: pretty == repr for short values
121+
self.assertTypedEqual(object_pretty('abc'), "'abc'")
122+
self.assertTypedEqual(object_pretty(42), '42')
123+
self.assertTypedEqual(object_pretty([1, 2, 3]), '[1, 2, 3]')
124+
self.assertTypedEqual(object_pretty({'a': 1}), "{'a': 1}")
125+
self.assertTypedEqual(object_pretty(()), '()')
126+
self.assertTypedEqual(object_pretty(True), 'True')
127+
self.assertTypedEqual(object_pretty(None), 'None')
128+
129+
# Nested/long structures that pformat formats differently from repr
130+
long_list = list(range(20))
131+
self.assertEqual(object_pretty(long_list), pprint.pformat(long_list))
132+
133+
nested = {'key1': list(range(10)), 'key2': {'inner': list(range(10))}}
134+
self.assertEqual(object_pretty(nested), pprint.pformat(nested))
135+
136+
# OrderedDict
137+
od = OrderedDict([('b', 2), ('a', 1), ('c', 3)])
138+
self.assertEqual(object_pretty(od), pprint.pformat(od))
139+
140+
# Return type is always str
141+
self.assertIsInstance(object_pretty([1, 2, 3]), str)
142+
self.assertIsInstance(object_pretty(nested), str)
143+
115144
def test_object_bytes(self):
116145
# Test PyObject_Bytes()
117146
object_bytes = _testlimitedcapi.object_bytes

Lib/test/test_stable_abi_ctypes.py

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Misc/stable_abi.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1138,6 +1138,8 @@
11381138
added = '3.2'
11391139
[function.PyObject_ASCII]
11401140
added = '3.2'
1141+
[function.PyObject_Pretty]
1142+
added = '3.15'
11411143
[function.PyObject_AsFileDescriptor]
11421144
added = '3.2'
11431145
[function.PyObject_Bytes]

Modules/_testlimitedcapi/abstract.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,12 @@ object_str(PyObject *self, PyObject *arg)
2323
return PyObject_Str(arg);
2424
}
2525

26+
static PyObject *
27+
object_pretty(PyObject *self, PyObject *arg)
28+
{
29+
return PyObject_Pretty(arg);
30+
}
31+
2632
static PyObject *
2733
object_bytes(PyObject *self, PyObject *arg)
2834
{
@@ -533,6 +539,7 @@ static PyMethodDef test_methods[] = {
533539
{"object_repr", object_repr, METH_O},
534540
{"object_ascii", object_ascii, METH_O},
535541
{"object_str", object_str, METH_O},
542+
{"object_pretty", object_pretty, METH_O},
536543
{"object_bytes", object_bytes, METH_O},
537544

538545
{"object_getattr", object_getattr, METH_VARARGS},

0 commit comments

Comments
 (0)