Skip to content

Commit 777740f

Browse files
committed
BUG: pretty print all Mappings, not just dicts
This was discovered in ibis-project/ibis#8693
1 parent aa3e949 commit 777740f

File tree

3 files changed

+24
-5
lines changed

3 files changed

+24
-5
lines changed

doc/source/whatsnew/v3.0.0.rst

+1
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,7 @@ MultiIndex
357357
I/O
358358
^^^
359359
- Bug in :meth:`DataFrame.to_excel` when writing empty :class:`DataFrame` with :class:`MultiIndex` on both axes (:issue:`57696`)
360+
- Now all ``Mapping`` s are pretty printed correctly. Before only literal ``dict`` s were. (:issue:`57915`)
360361
-
361362
-
362363

pandas/io/formats/printing.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -187,8 +187,8 @@ def pprint_thing(
187187
_nest_lvl : internal use only. pprint_thing() is mutually-recursive
188188
with pprint_sequence, this argument is used to keep track of the
189189
current nesting level, and limit it.
190-
escape_chars : list or dict, optional
191-
Characters to escape. If a dict is passed the values are the
190+
escape_chars : list[str] or Mapping[str, str], optional
191+
Characters to escape. If a Mapping is passed the values are the
192192
replacements
193193
default_escapes : bool, default False
194194
Whether the input escape characters replaces or adds to the defaults
@@ -204,11 +204,11 @@ def as_escaped_string(
204204
thing: Any, escape_chars: EscapeChars | None = escape_chars
205205
) -> str:
206206
translate = {"\t": r"\t", "\n": r"\n", "\r": r"\r"}
207-
if isinstance(escape_chars, dict):
207+
if isinstance(escape_chars, Mapping):
208208
if default_escapes:
209209
translate.update(escape_chars)
210210
else:
211-
translate = escape_chars
211+
translate = escape_chars # type: ignore[assignment]
212212
escape_chars = list(escape_chars.keys())
213213
else:
214214
escape_chars = escape_chars or ()
@@ -220,7 +220,7 @@ def as_escaped_string(
220220

221221
if hasattr(thing, "__next__"):
222222
return str(thing)
223-
elif isinstance(thing, dict) and _nest_lvl < get_option(
223+
elif isinstance(thing, Mapping) and _nest_lvl < get_option(
224224
"display.pprint_nest_depth"
225225
):
226226
result = _pprint_dict(

pandas/tests/io/formats/test_printing.py

+18
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# Note! This file is aimed specifically at pandas.io.formats.printing utility
22
# functions, not the general printing of pandas objects.
3+
from collections.abc import Mapping
34
import string
45

56
import pandas._config.config as cf
@@ -16,6 +17,17 @@ def test_adjoin():
1617
assert adjoined == expected
1718

1819

20+
class MyMapping(Mapping):
21+
def __getitem__(self, key):
22+
return 4
23+
24+
def __iter__(self):
25+
return iter(["a", "b"])
26+
27+
def __len__(self):
28+
return 2
29+
30+
1931
class TestPPrintThing:
2032
def test_repr_binary_type(self):
2133
letters = string.ascii_letters
@@ -42,6 +54,12 @@ def test_repr_obeys_max_seq_limit(self):
4254
def test_repr_set(self):
4355
assert printing.pprint_thing({1}) == "{1}"
4456

57+
def test_repr_dict(self):
58+
assert printing.pprint_thing({"a": 4, "b": 4}) == "{'a': 4, 'b': 4}"
59+
60+
def test_repr_mapping(self):
61+
assert printing.pprint_thing(MyMapping()) == "{'a': 4, 'b': 4}"
62+
4563

4664
class TestFormatBase:
4765
def test_adjoin(self):

0 commit comments

Comments
 (0)