python-2.5.2/win32/Lib/pprint.py
changeset 0 ae805ac0140d
equal deleted inserted replaced
-1:000000000000 0:ae805ac0140d
       
     1 #  Author:      Fred L. Drake, Jr.
       
     2 #               fdrake@acm.org
       
     3 #
       
     4 #  This is a simple little module I wrote to make life easier.  I didn't
       
     5 #  see anything quite like it in the library, though I may have overlooked
       
     6 #  something.  I wrote this when I was trying to read some heavily nested
       
     7 #  tuples with fairly non-descriptive content.  This is modeled very much
       
     8 #  after Lisp/Scheme - style pretty-printing of lists.  If you find it
       
     9 #  useful, thank small children who sleep at night.
       
    10 
       
    11 """Support to pretty-print lists, tuples, & dictionaries recursively.
       
    12 
       
    13 Very simple, but useful, especially in debugging data structures.
       
    14 
       
    15 Classes
       
    16 -------
       
    17 
       
    18 PrettyPrinter()
       
    19     Handle pretty-printing operations onto a stream using a configured
       
    20     set of formatting parameters.
       
    21 
       
    22 Functions
       
    23 ---------
       
    24 
       
    25 pformat()
       
    26     Format a Python object into a pretty-printed representation.
       
    27 
       
    28 pprint()
       
    29     Pretty-print a Python object to a stream [default is sys.stdout].
       
    30 
       
    31 saferepr()
       
    32     Generate a 'standard' repr()-like value, but protect against recursive
       
    33     data structures.
       
    34 
       
    35 """
       
    36 
       
    37 import sys as _sys
       
    38 
       
    39 from cStringIO import StringIO as _StringIO
       
    40 
       
    41 __all__ = ["pprint","pformat","isreadable","isrecursive","saferepr",
       
    42            "PrettyPrinter"]
       
    43 
       
    44 # cache these for faster access:
       
    45 _commajoin = ", ".join
       
    46 _id = id
       
    47 _len = len
       
    48 _type = type
       
    49 
       
    50 
       
    51 def pprint(object, stream=None, indent=1, width=80, depth=None):
       
    52     """Pretty-print a Python object to a stream [default is sys.stdout]."""
       
    53     printer = PrettyPrinter(
       
    54         stream=stream, indent=indent, width=width, depth=depth)
       
    55     printer.pprint(object)
       
    56 
       
    57 def pformat(object, indent=1, width=80, depth=None):
       
    58     """Format a Python object into a pretty-printed representation."""
       
    59     return PrettyPrinter(indent=indent, width=width, depth=depth).pformat(object)
       
    60 
       
    61 def saferepr(object):
       
    62     """Version of repr() which can handle recursive data structures."""
       
    63     return _safe_repr(object, {}, None, 0)[0]
       
    64 
       
    65 def isreadable(object):
       
    66     """Determine if saferepr(object) is readable by eval()."""
       
    67     return _safe_repr(object, {}, None, 0)[1]
       
    68 
       
    69 def isrecursive(object):
       
    70     """Determine if object requires a recursive representation."""
       
    71     return _safe_repr(object, {}, None, 0)[2]
       
    72 
       
    73 class PrettyPrinter:
       
    74     def __init__(self, indent=1, width=80, depth=None, stream=None):
       
    75         """Handle pretty printing operations onto a stream using a set of
       
    76         configured parameters.
       
    77 
       
    78         indent
       
    79             Number of spaces to indent for each level of nesting.
       
    80 
       
    81         width
       
    82             Attempted maximum number of columns in the output.
       
    83 
       
    84         depth
       
    85             The maximum depth to print out nested structures.
       
    86 
       
    87         stream
       
    88             The desired output stream.  If omitted (or false), the standard
       
    89             output stream available at construction will be used.
       
    90 
       
    91         """
       
    92         indent = int(indent)
       
    93         width = int(width)
       
    94         assert indent >= 0, "indent must be >= 0"
       
    95         assert depth is None or depth > 0, "depth must be > 0"
       
    96         assert width, "width must be != 0"
       
    97         self._depth = depth
       
    98         self._indent_per_level = indent
       
    99         self._width = width
       
   100         if stream is not None:
       
   101             self._stream = stream
       
   102         else:
       
   103             self._stream = _sys.stdout
       
   104 
       
   105     def pprint(self, object):
       
   106         self._format(object, self._stream, 0, 0, {}, 0)
       
   107         self._stream.write("\n")
       
   108 
       
   109     def pformat(self, object):
       
   110         sio = _StringIO()
       
   111         self._format(object, sio, 0, 0, {}, 0)
       
   112         return sio.getvalue()
       
   113 
       
   114     def isrecursive(self, object):
       
   115         return self.format(object, {}, 0, 0)[2]
       
   116 
       
   117     def isreadable(self, object):
       
   118         s, readable, recursive = self.format(object, {}, 0, 0)
       
   119         return readable and not recursive
       
   120 
       
   121     def _format(self, object, stream, indent, allowance, context, level):
       
   122         level = level + 1
       
   123         objid = _id(object)
       
   124         if objid in context:
       
   125             stream.write(_recursion(object))
       
   126             self._recursive = True
       
   127             self._readable = False
       
   128             return
       
   129         rep = self._repr(object, context, level - 1)
       
   130         typ = _type(object)
       
   131         sepLines = _len(rep) > (self._width - 1 - indent - allowance)
       
   132         write = stream.write
       
   133 
       
   134         if sepLines:
       
   135             r = getattr(typ, "__repr__", None)
       
   136             if issubclass(typ, dict) and r is dict.__repr__:
       
   137                 write('{')
       
   138                 if self._indent_per_level > 1:
       
   139                     write((self._indent_per_level - 1) * ' ')
       
   140                 length = _len(object)
       
   141                 if length:
       
   142                     context[objid] = 1
       
   143                     indent = indent + self._indent_per_level
       
   144                     items  = object.items()
       
   145                     items.sort()
       
   146                     key, ent = items[0]
       
   147                     rep = self._repr(key, context, level)
       
   148                     write(rep)
       
   149                     write(': ')
       
   150                     self._format(ent, stream, indent + _len(rep) + 2,
       
   151                                   allowance + 1, context, level)
       
   152                     if length > 1:
       
   153                         for key, ent in items[1:]:
       
   154                             rep = self._repr(key, context, level)
       
   155                             write(',\n%s%s: ' % (' '*indent, rep))
       
   156                             self._format(ent, stream, indent + _len(rep) + 2,
       
   157                                           allowance + 1, context, level)
       
   158                     indent = indent - self._indent_per_level
       
   159                     del context[objid]
       
   160                 write('}')
       
   161                 return
       
   162 
       
   163             if (issubclass(typ, list) and r is list.__repr__) or \
       
   164                (issubclass(typ, tuple) and r is tuple.__repr__):
       
   165                 if issubclass(typ, list):
       
   166                     write('[')
       
   167                     endchar = ']'
       
   168                 else:
       
   169                     write('(')
       
   170                     endchar = ')'
       
   171                 if self._indent_per_level > 1:
       
   172                     write((self._indent_per_level - 1) * ' ')
       
   173                 length = _len(object)
       
   174                 if length:
       
   175                     context[objid] = 1
       
   176                     indent = indent + self._indent_per_level
       
   177                     self._format(object[0], stream, indent, allowance + 1,
       
   178                                  context, level)
       
   179                     if length > 1:
       
   180                         for ent in object[1:]:
       
   181                             write(',\n' + ' '*indent)
       
   182                             self._format(ent, stream, indent,
       
   183                                           allowance + 1, context, level)
       
   184                     indent = indent - self._indent_per_level
       
   185                     del context[objid]
       
   186                 if issubclass(typ, tuple) and length == 1:
       
   187                     write(',')
       
   188                 write(endchar)
       
   189                 return
       
   190 
       
   191         write(rep)
       
   192 
       
   193     def _repr(self, object, context, level):
       
   194         repr, readable, recursive = self.format(object, context.copy(),
       
   195                                                 self._depth, level)
       
   196         if not readable:
       
   197             self._readable = False
       
   198         if recursive:
       
   199             self._recursive = True
       
   200         return repr
       
   201 
       
   202     def format(self, object, context, maxlevels, level):
       
   203         """Format object for a specific context, returning a string
       
   204         and flags indicating whether the representation is 'readable'
       
   205         and whether the object represents a recursive construct.
       
   206         """
       
   207         return _safe_repr(object, context, maxlevels, level)
       
   208 
       
   209 
       
   210 # Return triple (repr_string, isreadable, isrecursive).
       
   211 
       
   212 def _safe_repr(object, context, maxlevels, level):
       
   213     typ = _type(object)
       
   214     if typ is str:
       
   215         if 'locale' not in _sys.modules:
       
   216             return repr(object), True, False
       
   217         if "'" in object and '"' not in object:
       
   218             closure = '"'
       
   219             quotes = {'"': '\\"'}
       
   220         else:
       
   221             closure = "'"
       
   222             quotes = {"'": "\\'"}
       
   223         qget = quotes.get
       
   224         sio = _StringIO()
       
   225         write = sio.write
       
   226         for char in object:
       
   227             if char.isalpha():
       
   228                 write(char)
       
   229             else:
       
   230                 write(qget(char, repr(char)[1:-1]))
       
   231         return ("%s%s%s" % (closure, sio.getvalue(), closure)), True, False
       
   232 
       
   233     r = getattr(typ, "__repr__", None)
       
   234     if issubclass(typ, dict) and r is dict.__repr__:
       
   235         if not object:
       
   236             return "{}", True, False
       
   237         objid = _id(object)
       
   238         if maxlevels and level > maxlevels:
       
   239             return "{...}", False, objid in context
       
   240         if objid in context:
       
   241             return _recursion(object), False, True
       
   242         context[objid] = 1
       
   243         readable = True
       
   244         recursive = False
       
   245         components = []
       
   246         append = components.append
       
   247         level += 1
       
   248         saferepr = _safe_repr
       
   249         for k, v in sorted(object.items()):
       
   250             krepr, kreadable, krecur = saferepr(k, context, maxlevels, level)
       
   251             vrepr, vreadable, vrecur = saferepr(v, context, maxlevels, level)
       
   252             append("%s: %s" % (krepr, vrepr))
       
   253             readable = readable and kreadable and vreadable
       
   254             if krecur or vrecur:
       
   255                 recursive = True
       
   256         del context[objid]
       
   257         return "{%s}" % _commajoin(components), readable, recursive
       
   258 
       
   259     if (issubclass(typ, list) and r is list.__repr__) or \
       
   260        (issubclass(typ, tuple) and r is tuple.__repr__):
       
   261         if issubclass(typ, list):
       
   262             if not object:
       
   263                 return "[]", True, False
       
   264             format = "[%s]"
       
   265         elif _len(object) == 1:
       
   266             format = "(%s,)"
       
   267         else:
       
   268             if not object:
       
   269                 return "()", True, False
       
   270             format = "(%s)"
       
   271         objid = _id(object)
       
   272         if maxlevels and level > maxlevels:
       
   273             return format % "...", False, objid in context
       
   274         if objid in context:
       
   275             return _recursion(object), False, True
       
   276         context[objid] = 1
       
   277         readable = True
       
   278         recursive = False
       
   279         components = []
       
   280         append = components.append
       
   281         level += 1
       
   282         for o in object:
       
   283             orepr, oreadable, orecur = _safe_repr(o, context, maxlevels, level)
       
   284             append(orepr)
       
   285             if not oreadable:
       
   286                 readable = False
       
   287             if orecur:
       
   288                 recursive = True
       
   289         del context[objid]
       
   290         return format % _commajoin(components), readable, recursive
       
   291 
       
   292     rep = repr(object)
       
   293     return rep, (rep and not rep.startswith('<')), False
       
   294 
       
   295 
       
   296 def _recursion(object):
       
   297     return ("<Recursion on %s with id=%s>"
       
   298             % (_type(object).__name__, _id(object)))
       
   299 
       
   300 
       
   301 def _perfcheck(object=None):
       
   302     import time
       
   303     if object is None:
       
   304         object = [("string", (1, 2), [3, 4], {5: 6, 7: 8})] * 100000
       
   305     p = PrettyPrinter()
       
   306     t1 = time.time()
       
   307     _safe_repr(object, {}, None, 0)
       
   308     t2 = time.time()
       
   309     p.pformat(object)
       
   310     t3 = time.time()
       
   311     print "_safe_repr:", t2 - t1
       
   312     print "pformat:", t3 - t2
       
   313 
       
   314 if __name__ == "__main__":
       
   315     _perfcheck()