mirror of
https://github.com/python/cpython.git
synced 2025-07-29 06:05:00 +00:00
pprint functions used to sort a dict (by key) if and only if
the output required more than one line. "Small" dicts got displayed in seemingly random order (the hash-induced order produced by dict.__repr__). None of this was documented. Now pprint functions always sort dicts by key, and the docs promise it. This was proposed and agreed to during the PyCon 2006 core sprint -- I just didn't have time for it before now.
This commit is contained in:
parent
7f7386cfd2
commit
d609b1a20e
4 changed files with 42 additions and 5 deletions
|
@ -20,6 +20,10 @@ and breaks them onto multiple lines if they don't fit within the
|
||||||
allowed width. Construct \class{PrettyPrinter} objects explicitly if
|
allowed width. Construct \class{PrettyPrinter} objects explicitly if
|
||||||
you need to adjust the width constraint.
|
you need to adjust the width constraint.
|
||||||
|
|
||||||
|
\versionchanged[Dictionaries are sorted by key before the display is
|
||||||
|
computed; before 2.5, a dictionary was sorted only if its display
|
||||||
|
required more than one line, although that wasn't documented]{2.5}
|
||||||
|
|
||||||
The \module{pprint} module defines one class:
|
The \module{pprint} module defines one class:
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -246,7 +246,7 @@ def _safe_repr(object, context, maxlevels, level):
|
||||||
append = components.append
|
append = components.append
|
||||||
level += 1
|
level += 1
|
||||||
saferepr = _safe_repr
|
saferepr = _safe_repr
|
||||||
for k, v in object.iteritems():
|
for k, v in sorted(object.items()):
|
||||||
krepr, kreadable, krecur = saferepr(k, context, maxlevels, level)
|
krepr, kreadable, krecur = saferepr(k, context, maxlevels, level)
|
||||||
vrepr, vreadable, vrecur = saferepr(v, context, maxlevels, level)
|
vrepr, vreadable, vrecur = saferepr(v, context, maxlevels, level)
|
||||||
append("%s: %s" % (krepr, vrepr))
|
append("%s: %s" % (krepr, vrepr))
|
||||||
|
|
|
@ -11,16 +11,21 @@ except NameError:
|
||||||
# list, tuple and dict subclasses that do or don't overwrite __repr__
|
# list, tuple and dict subclasses that do or don't overwrite __repr__
|
||||||
class list2(list):
|
class list2(list):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
class list3(list):
|
class list3(list):
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return list.__repr__(self)
|
return list.__repr__(self)
|
||||||
|
|
||||||
class tuple2(tuple):
|
class tuple2(tuple):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
class tuple3(tuple):
|
class tuple3(tuple):
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return tuple.__repr__(self)
|
return tuple.__repr__(self)
|
||||||
|
|
||||||
class dict2(dict):
|
class dict2(dict):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
class dict3(dict):
|
class dict3(dict):
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return dict.__repr__(self)
|
return dict.__repr__(self)
|
||||||
|
@ -101,7 +106,13 @@ class QueryTestCase(unittest.TestCase):
|
||||||
|
|
||||||
def test_same_as_repr(self):
|
def test_same_as_repr(self):
|
||||||
# Simple objects, small containers and classes that overwrite __repr__
|
# Simple objects, small containers and classes that overwrite __repr__
|
||||||
# For those the result should be the same as repr()
|
# For those the result should be the same as repr().
|
||||||
|
# Ahem. The docs don't say anything about that -- this appears to
|
||||||
|
# be testing an implementation quirk. Starting in Python 2.5, it's
|
||||||
|
# not true for dicts: pprint always sorts dicts by key now; before,
|
||||||
|
# it sorted a dict display if and only if the display required
|
||||||
|
# multiple lines. For that reason, dicts with more than one element
|
||||||
|
# aren't tested here.
|
||||||
verify = self.assert_
|
verify = self.assert_
|
||||||
for simple in (0, 0L, 0+0j, 0.0, "", uni(""),
|
for simple in (0, 0L, 0+0j, 0.0, "", uni(""),
|
||||||
(), tuple2(), tuple3(),
|
(), tuple2(), tuple3(),
|
||||||
|
@ -112,9 +123,7 @@ class QueryTestCase(unittest.TestCase):
|
||||||
(1,2), [3,4], {5: 6, 7: 8},
|
(1,2), [3,4], {5: 6, 7: 8},
|
||||||
tuple2((1,2)), tuple3((1,2)), tuple3(range(100)),
|
tuple2((1,2)), tuple3((1,2)), tuple3(range(100)),
|
||||||
[3,4], list2([3,4]), list3([3,4]), list3(range(100)),
|
[3,4], list2([3,4]), list3([3,4]), list3(range(100)),
|
||||||
{5: 6, 7: 8}, dict2({5: 6, 7: 8}), dict3({5: 6, 7: 8}),
|
{5: 6, 7: 8}, dict2({5: 6}), dict3({5: 6}),
|
||||||
dict3([(x,x) for x in range(100)]),
|
|
||||||
{"xy\tab\n": (3,), 5: [[]], (): {}},
|
|
||||||
range(10, -11, -1)
|
range(10, -11, -1)
|
||||||
):
|
):
|
||||||
native = repr(simple)
|
native = repr(simple)
|
||||||
|
@ -160,6 +169,24 @@ class QueryTestCase(unittest.TestCase):
|
||||||
for type in [list, list2]:
|
for type in [list, list2]:
|
||||||
self.assertEqual(pprint.pformat(type(o), indent=4), exp)
|
self.assertEqual(pprint.pformat(type(o), indent=4), exp)
|
||||||
|
|
||||||
|
def test_sorted_dict(self):
|
||||||
|
# Starting in Python 2.5, pprint sorts dict displays by key regardless
|
||||||
|
# of how small the dictionary may be.
|
||||||
|
# Before the change, on 32-bit Windows pformat() gave order
|
||||||
|
# 'a', 'c', 'b' here, so this test failed.
|
||||||
|
d = {'a': 1, 'b': 1, 'c': 1}
|
||||||
|
self.assertEqual(pprint.pformat(d), "{'a': 1, 'b': 1, 'c': 1}")
|
||||||
|
self.assertEqual(pprint.pformat([d, d]),
|
||||||
|
"[{'a': 1, 'b': 1, 'c': 1}, {'a': 1, 'b': 1, 'c': 1}]")
|
||||||
|
|
||||||
|
# The next one is kind of goofy. The sorted order depends on the
|
||||||
|
# alphabetic order of type names: "int" < "str" < "tuple". Before
|
||||||
|
# Python 2.5, this was in the test_same_as_repr() test. It's worth
|
||||||
|
# keeping around for now because it's one of few tests of pprint
|
||||||
|
# against a crazy mix of types.
|
||||||
|
self.assertEqual(pprint.pformat({"xy\tab\n": (3,), 5: [[]], (): {}}),
|
||||||
|
r"{5: [[]], 'xy\tab\n': (3,), (): {}}")
|
||||||
|
|
||||||
def test_subclassing(self):
|
def test_subclassing(self):
|
||||||
o = {'names with spaces': 'should be presented using repr()',
|
o = {'names with spaces': 'should be presented using repr()',
|
||||||
'others.should.not.be': 'like.this'}
|
'others.should.not.be': 'like.this'}
|
||||||
|
|
|
@ -101,6 +101,12 @@ Extension Modules
|
||||||
Library
|
Library
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
- The functions in the ``pprint`` module now sort dictionaries by key
|
||||||
|
before computing the display. Before 2.5, ``pprint`` sorted a dictionary
|
||||||
|
if and only if its display required more than one line, although that
|
||||||
|
wasn't documented. The new behavior increases predictability; e.g.,
|
||||||
|
using ``pprint.pprint(a_dict)`` in a doctest is now reliable.
|
||||||
|
|
||||||
- Patch #1497027: try HTTP digest auth before basic auth in urllib2
|
- Patch #1497027: try HTTP digest auth before basic auth in urllib2
|
||||||
(thanks for J. J. Lee).
|
(thanks for J. J. Lee).
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue