summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Doc/lib/libpprint.tex23
-rw-r--r--Lib/pprint.py22
-rw-r--r--Lib/test/test_pprint.py21
3 files changed, 57 insertions, 9 deletions
diff --git a/Doc/lib/libpprint.tex b/Doc/lib/libpprint.tex
index 3ecc7bc..22ffd7b 100644
--- a/Doc/lib/libpprint.tex
+++ b/Doc/lib/libpprint.tex
@@ -173,3 +173,26 @@ this returns false.
\begin{methoddesc}{isrecursive}{object}
Determine if the object requires a recursive representation.
\end{methoddesc}
+
+This method is provided as a hook to allow subclasses to modify the
+way objects are converted to strings. The default implementation uses
+the internals of the \function{saferepr()} implementation.
+
+\begin{methoddesc}{format}{object, context, maxlevels, level}
+Returns three values: the formatted version of \var{object} as a
+string, a flag indicating whether the result is readable, and a flag
+indicating whether recursion was detected. The first argument is the
+object to be presented. The second is a dictionary which contains the
+\function{id()} of objects that are part of the current presentation
+context (direct and indirect containers for \var{object} that are
+affecting the presentation) as the keys; if an object needs to be
+presented which is already represented in \var{context}, the third
+return value should be true. Recursive calls to the \method{format()}
+method should add additionaly entries for containers to this
+dictionary. The fourth argument, \var{maxlevels}, gives the requested
+limit to recursion; this will be \code{0} if there is no requested
+limit. This argument should be passed unmodified to recursive calls.
+The fourth argument, \var{level} gives the current level; recursive
+calls should be passed a value less than that of the current call.
+\versionadded{2.3}
+\end{methoddesc}
diff --git a/Lib/pprint.py b/Lib/pprint.py
index 5d178a2..82eeac6 100644
--- a/Lib/pprint.py
+++ b/Lib/pprint.py
@@ -115,15 +115,11 @@ class PrettyPrinter:
return sio.getvalue()
def isrecursive(self, object):
- self.__recursive = 0
- self.__repr(object, {}, 0)
- return self.__recursive
+ return self.format(object, {}, 0)[2]
def isreadable(self, object):
- self.__recursive = 0
- self.__readable = 1
- self.__repr(object, {}, 0)
- return self.__readable and not self.__recursive
+ s, readable, recursive = self.format(object, {}, 0)
+ return readable and not recursive
def __format(self, object, stream, indent, allowance, context, level):
level = level + 1
@@ -196,14 +192,22 @@ class PrettyPrinter:
write(rep)
def __repr(self, object, context, level):
- repr, readable, recursive = _safe_repr(object, context,
- self.__depth, level)
+ repr, readable, recursive = self.format(object, context.copy(),
+ self.__depth, level)
if not readable:
self.__readable = 0
if recursive:
self.__recursive = 1
return repr
+ def format(self, object, context, maxlevels, level):
+ """Format object for a specific context, returning a string
+ and flags indicating whether the representation is 'readable'
+ and whether the object represents a recursive construct.
+ """
+ return _safe_repr(object, context, maxlevels, level)
+
+
# Return triple (repr_string, isreadable, isrecursive).
def _safe_repr(object, context, maxlevels, level):
diff --git a/Lib/test/test_pprint.py b/Lib/test/test_pprint.py
index 14626fb..d5e10aa 100644
--- a/Lib/test/test_pprint.py
+++ b/Lib/test/test_pprint.py
@@ -96,6 +96,27 @@ class QueryTestCase(unittest.TestCase):
'write_io_runtime_us': 43690}"""
self.assertEqual(pprint.pformat(o), exp)
+ def test_subclassing(self):
+ o = {'names with spaces': 'should be presented using repr()',
+ 'others.should.not.be': 'like.this'}
+ exp = """\
+{'names with spaces': 'should be presented using repr()',
+ others.should.not.be: like.this}"""
+ self.assertEqual(DottedPrettyPrinter().pformat(o), exp)
+
+
+class DottedPrettyPrinter(pprint.PrettyPrinter):
+ def format(self, object, context, maxlevels, level):
+ if isinstance(object, str):
+ if ' ' in object:
+ return `object`, 1, 0
+ else:
+ return object, 0, 0
+ else:
+ return pprint.PrettyPrinter.format(
+ self, object, context, maxlevels, level)
+
+
def test_main():
test_support.run_unittest(QueryTestCase)