Improved some error messages for command line processing.
[python/dscho.git] / Lib / pprint.py
blobfcf09046c8a75c60eb04b82f11952bc4786f0395
1 # Author: Fred L. Drake, Jr.
2 # fdrake@cnri.reston.va.us, fdrake@acm.org
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 modelled very much
8 # after Lisp/Scheme - style pretty-printing of lists. If you find it
9 # useful, thank small children who sleep at night.
11 """Support to pretty-print lists, tuples, & dictionaries recursively.
13 Very simple, but useful, especially in debugging data structures.
15 Classes
16 -------
18 PrettyPrinter()
19 Handle pretty-printing operations onto a stream using a configured
20 set of formatting parameters.
22 Functions
23 ---------
25 pformat()
26 Format a Python object into a pretty-printed representation.
28 pprint()
29 Pretty-print a Python object to a stream [default is sys.sydout].
31 saferepr()
32 Generate a 'standard' repr()-like value, but protect against recursive
33 data structures.
35 """
37 from types import DictType, ListType, TupleType
39 try:
40 from cStringIO import StringIO
41 except ImportError:
42 from StringIO import StringIO
45 def pprint(object, stream=None):
46 """Pretty-print a Python object to a stream [default is sys.sydout]."""
47 printer = PrettyPrinter(stream=stream)
48 printer.pprint(object)
51 def pformat(object):
52 """Format a Python object into a pretty-printed representation."""
53 return PrettyPrinter().pformat(object)
56 def isreadable(object):
57 """Determine if saferepr(object) is readable by eval()."""
58 return PrettyPrinter().isreadable(object)
61 def isrecursive(object):
62 """Determine if object requires a recursive representation."""
63 return PrettyPrinter().isrecursive(object)
66 def saferepr(object):
67 """Version of repr() which can handle recursive data structures."""
68 return _safe_repr(object, {})[0]
71 class PrettyPrinter:
72 def __init__(self, indent=1, width=80, depth=None, stream=None):
73 """Handle pretty printing operations onto a stream using a set of
74 configured parameters.
76 indent
77 Number of spaces to indent for each level of nesting.
79 width
80 Attempted maximum number of columns in the output.
82 depth
83 The maximum depth to print out nested structures.
85 stream
86 The desired output stream. If omitted (or false), the standard
87 output stream available at construction will be used.
89 """
90 indent = int(indent)
91 width = int(width)
92 assert indent >= 0
93 assert (not depth) or depth > 0, "depth may not be negative"
94 assert width
95 self.__depth = depth
96 self.__indent_per_level = indent
97 self.__width = width
98 if stream:
99 self.__stream = stream
100 else:
101 import sys
102 self.__stream = sys.stdout
104 def pprint(self, object):
105 self.__stream.write(self.pformat(object) + "\n")
107 def pformat(self, object):
108 sio = StringIO()
109 self.__format(object, sio, 0, 0, {}, 0)
110 return sio.getvalue()
112 def isrecursive(self, object):
113 self.__recursive = 0
114 self.pformat(object)
115 return self.__recursive
117 def isreadable(self, object):
118 self.__recursive = 0
119 self.__readable = 1
120 self.pformat(object)
121 return self.__readable and not self.__recursive
123 def __format(self, object, stream, indent, allowance, context, level):
124 level = level + 1
125 if context.has_key(id(object)):
126 object = _Recursion(object)
127 self.__recursive = 1
128 rep = self.__repr(object, context, level - 1)
129 objid = id(object)
130 context[objid] = 1
131 typ = type(object)
132 sepLines = len(rep) > (self.__width - 1 - indent - allowance)
134 if sepLines and typ in (ListType, TupleType):
135 # Pretty-print the sequence.
136 stream.write((typ is ListType) and '[' or '(')
137 if self.__indent_per_level > 1:
138 stream.write((self.__indent_per_level - 1) * ' ')
139 length = len(object)
140 if length:
141 indent = indent + self.__indent_per_level
142 self.__format(object[0], stream, indent, allowance + 1,
143 context, level)
144 if len(object) > 1:
145 for ent in object[1:]:
146 stream.write(',\n' + ' '*indent)
147 self.__format(ent, stream, indent,
148 allowance + 1, context, level)
149 indent = indent - self.__indent_per_level
150 if typ is TupleType and length == 1:
151 stream.write(',')
152 stream.write(((typ is ListType) and ']') or ')')
154 elif sepLines and typ is DictType:
155 stream.write('{')
156 if self.__indent_per_level > 1:
157 stream.write((self.__indent_per_level - 1) * ' ')
158 length = len(object)
159 if length:
160 indent = indent + self.__indent_per_level
161 items = object.items()
162 items.sort()
163 key, ent = items[0]
164 rep = self.__repr(key, context, level) + ': '
165 stream.write(rep)
166 self.__format(ent, stream, indent + len(rep),
167 allowance + 1, context, level)
168 if len(items) > 1:
169 for key, ent in items[1:]:
170 rep = self.__repr(key, context, level) + ': '
171 stream.write(',\n' + ' '*indent + rep)
172 self.__format(ent, stream, indent + len(rep),
173 allowance + 1, context, level)
174 indent = indent - self.__indent_per_level
175 stream.write('}')
177 else:
178 stream.write(rep)
179 del context[objid]
181 def __repr(self, object, context, level):
182 repr, readable = _safe_repr(object, context, self.__depth, level)
183 if not readable:
184 self.__readable = 0
185 return repr
188 def _safe_repr(object, context, maxlevels=None, level=0):
189 level = level + 1
190 readable = 1
191 typ = type(object)
192 if not (typ in (DictType, ListType, TupleType) and object):
193 rep = `object`
194 if rep:
195 if rep[0] == '<':
196 readable = 0
197 else:
198 readable = 0
199 return `object`, readable
200 if context.has_key(id(object)):
201 return `_Recursion(object)`, 0
202 objid = id(object)
203 context[objid] = 1
204 if typ is DictType:
205 if maxlevels and level >= maxlevels:
206 s = "{...}"
207 readable = 0
208 else:
209 items = object.items()
210 k, v = items[0]
211 krepr, kreadable = _safe_repr(k, context, maxlevels, level)
212 vrepr, vreadable = _safe_repr(v, context, maxlevels, level)
213 readable = readable and kreadable and vreadable
214 s = "{%s: %s" % (krepr, vrepr)
215 for k, v in items[1:]:
216 krepr, kreadable = _safe_repr(k, context, maxlevels, level)
217 vrepr, vreadable = _safe_repr(v, context, maxlevels, level)
218 readable = readable and kreadable and vreadable
219 s = "%s, %s: %s" % (s, krepr, vrepr)
220 s = s + "}"
221 else:
222 s, term = (typ is ListType) and ('[', ']') or ('(', ')')
223 if maxlevels and level >= maxlevels:
224 s = s + "..."
225 readable = 0
226 else:
227 subrepr, subreadable = _safe_repr(
228 object[0], context, maxlevels, level)
229 readable = readable and subreadable
230 s = s + subrepr
231 tail = object[1:]
232 if not tail:
233 if typ is TupleType:
234 s = s + ','
235 for ent in tail:
236 subrepr, subreadable = _safe_repr(
237 ent, context, maxlevels, level)
238 readable = readable and subreadable
239 s = "%s, %s" % (s, subrepr)
240 s = s + term
241 del context[objid]
242 return s, readable
245 class _Recursion:
246 # represent a recursive relationship; really only used for the __repr__()
247 # method...
248 def __init__(self, object):
249 self.__repr = "<Recursion on %s with id=%s>" \
250 % (type(object).__name__, id(object))
252 def __repr__(self):
253 return self.__repr