]> granicus.if.org Git - python/commitdiff
bpo-37376: pprint support for SimpleNamespace (GH-14318)
authorCarl Bordum Hansen <carl@bordum.dk>
Wed, 26 Jun 2019 23:13:18 +0000 (01:13 +0200)
committerMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>
Wed, 26 Jun 2019 23:13:18 +0000 (16:13 -0700)
https://bugs.python.org/issue37376

Doc/library/pprint.rst
Doc/whatsnew/3.9.rst
Lib/pprint.py
Lib/test/test_pprint.py
Misc/ACKS
Misc/NEWS.d/next/Library/2019-06-24-11-26-34.bpo-37376.SwSUQ4.rst [new file with mode: 0644]

index 9abf2865ef6143c0c1ea6d7df3244a4d916aae8f..207c3f8bca928b22d06fe2a66033c9c10e844b0d 100644 (file)
@@ -25,6 +25,9 @@ width constraint.
 
 Dictionaries are sorted by key before the display is computed.
 
+.. versionchanged:: 3.9
+   Added support for pretty-printing :class:`types.SimpleNamespace`.
+
 The :mod:`pprint` module defines one class:
 
 .. First the implementation class:
index 780c0a94d65c1fc423470b02437b53519216f33f..379a097ada152d1ef63932f1cd095a50545ccd22 100644 (file)
@@ -111,6 +111,12 @@ threads were never supported in subinterpreters. Previously, the subinterpreter
 finalization crashed with a Pyton fatal error if a daemon thread was still
 running.
 
+pprint
+------
+
+:mod:`pprint` can now pretty-print :class:`types.SimpleNamespace`.
+(Contributed by Carl Bordum Hansen in :issue:`37376`.)
+
 
 Optimizations
 =============
index 4bfcc31b25ea8e830f4675ae5aef43ad641f2bfa..7c1118a484b268fee26760fc0ca1ec76a533f52a 100644 (file)
@@ -342,6 +342,33 @@ class PrettyPrinter:
 
     _dispatch[_types.MappingProxyType.__repr__] = _pprint_mappingproxy
 
+    def _pprint_simplenamespace(self, object, stream, indent, allowance, context, level):
+        if type(object) is _types.SimpleNamespace:
+            # The SimpleNamespace repr is "namespace" instead of the class
+            # name, so we do the same here. For subclasses; use the class name.
+            cls_name = 'namespace'
+        else:
+            cls_name = object.__class__.__name__
+        indent += len(cls_name) + 1
+        delimnl = ',\n' + ' ' * indent
+        items = object.__dict__.items()
+        last_index = len(items) - 1
+
+        stream.write(cls_name + '(')
+        for i, (key, ent) in enumerate(items):
+            stream.write(key)
+            stream.write('=')
+
+            last = i == last_index
+            self._format(ent, stream, indent + len(key) + 1,
+                         allowance if last else 1,
+                         context, level)
+            if not last:
+                stream.write(delimnl)
+        stream.write(')')
+
+    _dispatch[_types.SimpleNamespace.__repr__] = _pprint_simplenamespace
+
     def _format_dict_items(self, items, stream, indent, allowance, context,
                            level):
         write = stream.write
index 269ac0624eeb8b377064789ef5d51cf3601e7f2d..b3b8715a5f75620203713a318cb4f88e6c64d0b1 100644 (file)
@@ -346,6 +346,65 @@ mappingproxy(OrderedDict([('the', 0),
                           ('lazy', 7),
                           ('dog', 8)]))""")
 
+    def test_empty_simple_namespace(self):
+        ns = types.SimpleNamespace()
+        formatted = pprint.pformat(ns)
+        self.assertEqual(formatted, "namespace()")
+
+    def test_small_simple_namespace(self):
+        ns = types.SimpleNamespace(a=1, b=2)
+        formatted = pprint.pformat(ns)
+        self.assertEqual(formatted, "namespace(a=1, b=2)")
+
+    def test_simple_namespace(self):
+        ns = types.SimpleNamespace(
+            the=0,
+            quick=1,
+            brown=2,
+            fox=3,
+            jumped=4,
+            over=5,
+            a=6,
+            lazy=7,
+            dog=8,
+        )
+        formatted = pprint.pformat(ns, width=60)
+        self.assertEqual(formatted, """\
+namespace(the=0,
+          quick=1,
+          brown=2,
+          fox=3,
+          jumped=4,
+          over=5,
+          a=6,
+          lazy=7,
+          dog=8)""")
+
+    def test_simple_namespace_subclass(self):
+        class AdvancedNamespace(types.SimpleNamespace): pass
+        ns = AdvancedNamespace(
+            the=0,
+            quick=1,
+            brown=2,
+            fox=3,
+            jumped=4,
+            over=5,
+            a=6,
+            lazy=7,
+            dog=8,
+        )
+        formatted = pprint.pformat(ns, width=60)
+        self.assertEqual(formatted, """\
+AdvancedNamespace(the=0,
+                  quick=1,
+                  brown=2,
+                  fox=3,
+                  jumped=4,
+                  over=5,
+                  a=6,
+                  lazy=7,
+                  dog=8)""")
+
     def test_subclassing(self):
         o = {'names with spaces': 'should be presented using repr()',
              'others.should.not.be': 'like.this'}
index 05a3e61f6941498371bb2723994c7e30da84f1dd..df0810fff46cc62cfe0d2884238552fe47e65923 100644 (file)
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -628,6 +628,7 @@ Mark Hammond
 Harald Hanche-Olsen
 Manus Hand
 Milton L. Hankins
+Carl Bordum Hansen
 Stephen Hansen
 Barry Hantman
 Lynda Hardman
diff --git a/Misc/NEWS.d/next/Library/2019-06-24-11-26-34.bpo-37376.SwSUQ4.rst b/Misc/NEWS.d/next/Library/2019-06-24-11-26-34.bpo-37376.SwSUQ4.rst
new file mode 100644 (file)
index 0000000..f47d813
--- /dev/null
@@ -0,0 +1,2 @@
+:mod:`pprint` now has support for :class:`types.SimpleNamespace`. Patch by Carl
+Bordum Hansen.