diff --git a/IPython/lib/pretty.py b/IPython/lib/pretty.py index 8cb51aa..ec0bc25 100644 --- a/IPython/lib/pretty.py +++ b/IPython/lib/pretty.py @@ -605,7 +605,8 @@ def _dict_pprinter_factory(start, end, basetype=None): if cycle: return p.text('{...}') - p.begin_group(1, start) + step = len(start) + p.begin_group(step, start) keys = obj.keys() # if dict isn't large enough to be truncated, sort keys before displaying if not (p.max_seq_length and len(obj) >= p.max_seq_length): @@ -621,7 +622,7 @@ def _dict_pprinter_factory(start, end, basetype=None): p.pretty(key) p.text(': ') p.pretty(obj[key]) - p.end_group(1, end) + p.end_group(step, end) return inner @@ -760,6 +761,8 @@ try: _type_pprinters[types.ClassType] = _type_pprint _type_pprinters[types.SliceType] = _repr_pprint except AttributeError: # Python 3 + _type_pprinters[types.MappingProxyType] = \ + _dict_pprinter_factory('mappingproxy({', '})') _type_pprinters[slice] = _repr_pprint try: diff --git a/IPython/lib/tests/test_pretty.py b/IPython/lib/tests/test_pretty.py index 6995495..4adb0ce 100644 --- a/IPython/lib/tests/test_pretty.py +++ b/IPython/lib/tests/test_pretty.py @@ -7,11 +7,12 @@ from __future__ import print_function from collections import Counter, defaultdict, deque, OrderedDict +import types, string import nose.tools as nt from IPython.lib import pretty -from IPython.testing.decorators import skip_without, py2_only +from IPython.testing.decorators import skip_without, py2_only, py3_only from IPython.utils.py3compat import PY3, unicode_to_str if PY3: @@ -436,3 +437,48 @@ def test_collections_counter(): ] for obj, expected in cases: nt.assert_equal(pretty.pretty(obj), expected) + +@py3_only +def test_mappingproxy(): + MP = types.MappingProxyType + underlying_dict = {} + mp_recursive = MP(underlying_dict) + underlying_dict[2] = mp_recursive + underlying_dict[3] = underlying_dict + + cases = [ + (MP({}), "mappingproxy({})"), + (MP({None: MP({})}), "mappingproxy({None: mappingproxy({})})"), + (MP({k: k.upper() for k in string.ascii_lowercase}), + "mappingproxy({'a': 'A',\n" + " 'b': 'B',\n" + " 'c': 'C',\n" + " 'd': 'D',\n" + " 'e': 'E',\n" + " 'f': 'F',\n" + " 'g': 'G',\n" + " 'h': 'H',\n" + " 'i': 'I',\n" + " 'j': 'J',\n" + " 'k': 'K',\n" + " 'l': 'L',\n" + " 'm': 'M',\n" + " 'n': 'N',\n" + " 'o': 'O',\n" + " 'p': 'P',\n" + " 'q': 'Q',\n" + " 'r': 'R',\n" + " 's': 'S',\n" + " 't': 'T',\n" + " 'u': 'U',\n" + " 'v': 'V',\n" + " 'w': 'W',\n" + " 'x': 'X',\n" + " 'y': 'Y',\n" + " 'z': 'Z'})"), + (mp_recursive, "mappingproxy({2: {...}, 3: {2: {...}, 3: {...}}})"), + (underlying_dict, + "{2: mappingproxy({2: {...}, 3: {...}}), 3: {...}}"), + ] + for obj, expected in cases: + nt.assert_equal(pretty.pretty(obj), expected)