##// END OF EJS Templates
only sort small dicts and sets in lib.pretty...
MinRK -
Show More
@@ -1,820 +1,823
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 Python advanced pretty printer. This pretty printer is intended to
3 Python advanced pretty printer. This pretty printer is intended to
4 replace the old `pprint` python module which does not allow developers
4 replace the old `pprint` python module which does not allow developers
5 to provide their own pretty print callbacks.
5 to provide their own pretty print callbacks.
6
6
7 This module is based on ruby's `prettyprint.rb` library by `Tanaka Akira`.
7 This module is based on ruby's `prettyprint.rb` library by `Tanaka Akira`.
8
8
9
9
10 Example Usage
10 Example Usage
11 -------------
11 -------------
12
12
13 To directly print the representation of an object use `pprint`::
13 To directly print the representation of an object use `pprint`::
14
14
15 from pretty import pprint
15 from pretty import pprint
16 pprint(complex_object)
16 pprint(complex_object)
17
17
18 To get a string of the output use `pretty`::
18 To get a string of the output use `pretty`::
19
19
20 from pretty import pretty
20 from pretty import pretty
21 string = pretty(complex_object)
21 string = pretty(complex_object)
22
22
23
23
24 Extending
24 Extending
25 ---------
25 ---------
26
26
27 The pretty library allows developers to add pretty printing rules for their
27 The pretty library allows developers to add pretty printing rules for their
28 own objects. This process is straightforward. All you have to do is to
28 own objects. This process is straightforward. All you have to do is to
29 add a `_repr_pretty_` method to your object and call the methods on the
29 add a `_repr_pretty_` method to your object and call the methods on the
30 pretty printer passed::
30 pretty printer passed::
31
31
32 class MyObject(object):
32 class MyObject(object):
33
33
34 def _repr_pretty_(self, p, cycle):
34 def _repr_pretty_(self, p, cycle):
35 ...
35 ...
36
36
37 Depending on the python version you want to support you have two
37 Depending on the python version you want to support you have two
38 possibilities. The following list shows the python 2.5 version and the
38 possibilities. The following list shows the python 2.5 version and the
39 compatibility one.
39 compatibility one.
40
40
41
41
42 Here the example implementation of a `_repr_pretty_` method for a list
42 Here the example implementation of a `_repr_pretty_` method for a list
43 subclass for python 2.5 and higher (python 2.5 requires the with statement
43 subclass for python 2.5 and higher (python 2.5 requires the with statement
44 __future__ import)::
44 __future__ import)::
45
45
46 class MyList(list):
46 class MyList(list):
47
47
48 def _repr_pretty_(self, p, cycle):
48 def _repr_pretty_(self, p, cycle):
49 if cycle:
49 if cycle:
50 p.text('MyList(...)')
50 p.text('MyList(...)')
51 else:
51 else:
52 with p.group(8, 'MyList([', '])'):
52 with p.group(8, 'MyList([', '])'):
53 for idx, item in enumerate(self):
53 for idx, item in enumerate(self):
54 if idx:
54 if idx:
55 p.text(',')
55 p.text(',')
56 p.breakable()
56 p.breakable()
57 p.pretty(item)
57 p.pretty(item)
58
58
59 The `cycle` parameter is `True` if pretty detected a cycle. You *have* to
59 The `cycle` parameter is `True` if pretty detected a cycle. You *have* to
60 react to that or the result is an infinite loop. `p.text()` just adds
60 react to that or the result is an infinite loop. `p.text()` just adds
61 non breaking text to the output, `p.breakable()` either adds a whitespace
61 non breaking text to the output, `p.breakable()` either adds a whitespace
62 or breaks here. If you pass it an argument it's used instead of the
62 or breaks here. If you pass it an argument it's used instead of the
63 default space. `p.pretty` prettyprints another object using the pretty print
63 default space. `p.pretty` prettyprints another object using the pretty print
64 method.
64 method.
65
65
66 The first parameter to the `group` function specifies the extra indentation
66 The first parameter to the `group` function specifies the extra indentation
67 of the next line. In this example the next item will either be not
67 of the next line. In this example the next item will either be not
68 breaked (if the items are short enough) or aligned with the right edge of
68 breaked (if the items are short enough) or aligned with the right edge of
69 the opening bracked of `MyList`.
69 the opening bracked of `MyList`.
70
70
71 If you want to support python 2.4 and lower you can use this code::
71 If you want to support python 2.4 and lower you can use this code::
72
72
73 class MyList(list):
73 class MyList(list):
74
74
75 def _repr_pretty_(self, p, cycle):
75 def _repr_pretty_(self, p, cycle):
76 if cycle:
76 if cycle:
77 p.text('MyList(...)')
77 p.text('MyList(...)')
78 else:
78 else:
79 p.begin_group(8, 'MyList([')
79 p.begin_group(8, 'MyList([')
80 for idx, item in enumerate(self):
80 for idx, item in enumerate(self):
81 if idx:
81 if idx:
82 p.text(',')
82 p.text(',')
83 p.breakable()
83 p.breakable()
84 p.pretty(item)
84 p.pretty(item)
85 p.end_group(8, '])')
85 p.end_group(8, '])')
86
86
87 If you just want to indent something you can use the group function
87 If you just want to indent something you can use the group function
88 without open / close parameters. Under python 2.5 you can also use this
88 without open / close parameters. Under python 2.5 you can also use this
89 code::
89 code::
90
90
91 with p.indent(2):
91 with p.indent(2):
92 ...
92 ...
93
93
94 Or under python2.4 you might want to modify ``p.indentation`` by hand but
94 Or under python2.4 you might want to modify ``p.indentation`` by hand but
95 this is rather ugly.
95 this is rather ugly.
96
96
97 Inheritance diagram:
97 Inheritance diagram:
98
98
99 .. inheritance-diagram:: IPython.lib.pretty
99 .. inheritance-diagram:: IPython.lib.pretty
100 :parts: 3
100 :parts: 3
101
101
102 :copyright: 2007 by Armin Ronacher.
102 :copyright: 2007 by Armin Ronacher.
103 Portions (c) 2009 by Robert Kern.
103 Portions (c) 2009 by Robert Kern.
104 :license: BSD License.
104 :license: BSD License.
105 """
105 """
106 from __future__ import print_function
106 from __future__ import print_function
107 from contextlib import contextmanager
107 from contextlib import contextmanager
108 import sys
108 import sys
109 import types
109 import types
110 import re
110 import re
111 import datetime
111 import datetime
112 from collections import deque
112 from collections import deque
113
113
114 from IPython.utils.py3compat import PY3
114 from IPython.utils.py3compat import PY3
115
115
116 if PY3:
116 if PY3:
117 from io import StringIO
117 from io import StringIO
118 else:
118 else:
119 from StringIO import StringIO
119 from StringIO import StringIO
120
120
121
121
122 __all__ = ['pretty', 'pprint', 'PrettyPrinter', 'RepresentationPrinter',
122 __all__ = ['pretty', 'pprint', 'PrettyPrinter', 'RepresentationPrinter',
123 'for_type', 'for_type_by_name']
123 'for_type', 'for_type_by_name']
124
124
125
125
126 _re_pattern_type = type(re.compile(''))
126 _re_pattern_type = type(re.compile(''))
127
127
128
128
129 def _safe_getattr(obj, attr, default=None):
129 def _safe_getattr(obj, attr, default=None):
130 """Safe version of getattr.
130 """Safe version of getattr.
131
131
132 Same as getattr, but will return ``default`` on any Exception,
132 Same as getattr, but will return ``default`` on any Exception,
133 rather than raising.
133 rather than raising.
134 """
134 """
135 try:
135 try:
136 return getattr(obj, attr, default)
136 return getattr(obj, attr, default)
137 except Exception:
137 except Exception:
138 return default
138 return default
139
139
140 def pretty(obj, verbose=False, max_width=79, newline='\n'):
140 def pretty(obj, verbose=False, max_width=79, newline='\n'):
141 """
141 """
142 Pretty print the object's representation.
142 Pretty print the object's representation.
143 """
143 """
144 stream = StringIO()
144 stream = StringIO()
145 printer = RepresentationPrinter(stream, verbose, max_width, newline)
145 printer = RepresentationPrinter(stream, verbose, max_width, newline)
146 printer.pretty(obj)
146 printer.pretty(obj)
147 printer.flush()
147 printer.flush()
148 return stream.getvalue()
148 return stream.getvalue()
149
149
150
150
151 def pprint(obj, verbose=False, max_width=79, newline='\n'):
151 def pprint(obj, verbose=False, max_width=79, newline='\n'):
152 """
152 """
153 Like `pretty` but print to stdout.
153 Like `pretty` but print to stdout.
154 """
154 """
155 printer = RepresentationPrinter(sys.stdout, verbose, max_width, newline)
155 printer = RepresentationPrinter(sys.stdout, verbose, max_width, newline)
156 printer.pretty(obj)
156 printer.pretty(obj)
157 printer.flush()
157 printer.flush()
158 sys.stdout.write(newline)
158 sys.stdout.write(newline)
159 sys.stdout.flush()
159 sys.stdout.flush()
160
160
161 class _PrettyPrinterBase(object):
161 class _PrettyPrinterBase(object):
162
162
163 @contextmanager
163 @contextmanager
164 def indent(self, indent):
164 def indent(self, indent):
165 """with statement support for indenting/dedenting."""
165 """with statement support for indenting/dedenting."""
166 self.indentation += indent
166 self.indentation += indent
167 try:
167 try:
168 yield
168 yield
169 finally:
169 finally:
170 self.indentation -= indent
170 self.indentation -= indent
171
171
172 @contextmanager
172 @contextmanager
173 def group(self, indent=0, open='', close=''):
173 def group(self, indent=0, open='', close=''):
174 """like begin_group / end_group but for the with statement."""
174 """like begin_group / end_group but for the with statement."""
175 self.begin_group(indent, open)
175 self.begin_group(indent, open)
176 try:
176 try:
177 yield
177 yield
178 finally:
178 finally:
179 self.end_group(indent, close)
179 self.end_group(indent, close)
180
180
181 class PrettyPrinter(_PrettyPrinterBase):
181 class PrettyPrinter(_PrettyPrinterBase):
182 """
182 """
183 Baseclass for the `RepresentationPrinter` prettyprinter that is used to
183 Baseclass for the `RepresentationPrinter` prettyprinter that is used to
184 generate pretty reprs of objects. Contrary to the `RepresentationPrinter`
184 generate pretty reprs of objects. Contrary to the `RepresentationPrinter`
185 this printer knows nothing about the default pprinters or the `_repr_pretty_`
185 this printer knows nothing about the default pprinters or the `_repr_pretty_`
186 callback method.
186 callback method.
187 """
187 """
188
188
189 def __init__(self, output, max_width=79, newline='\n', max_seq_length=1000):
189 def __init__(self, output, max_width=79, newline='\n', max_seq_length=1000):
190 self.output = output
190 self.output = output
191 self.max_width = max_width
191 self.max_width = max_width
192 self.newline = newline
192 self.newline = newline
193 self.max_seq_length = max_seq_length
193 self.max_seq_length = max_seq_length
194 self.output_width = 0
194 self.output_width = 0
195 self.buffer_width = 0
195 self.buffer_width = 0
196 self.buffer = deque()
196 self.buffer = deque()
197
197
198 root_group = Group(0)
198 root_group = Group(0)
199 self.group_stack = [root_group]
199 self.group_stack = [root_group]
200 self.group_queue = GroupQueue(root_group)
200 self.group_queue = GroupQueue(root_group)
201 self.indentation = 0
201 self.indentation = 0
202
202
203 def _break_outer_groups(self):
203 def _break_outer_groups(self):
204 while self.max_width < self.output_width + self.buffer_width:
204 while self.max_width < self.output_width + self.buffer_width:
205 group = self.group_queue.deq()
205 group = self.group_queue.deq()
206 if not group:
206 if not group:
207 return
207 return
208 while group.breakables:
208 while group.breakables:
209 x = self.buffer.popleft()
209 x = self.buffer.popleft()
210 self.output_width = x.output(self.output, self.output_width)
210 self.output_width = x.output(self.output, self.output_width)
211 self.buffer_width -= x.width
211 self.buffer_width -= x.width
212 while self.buffer and isinstance(self.buffer[0], Text):
212 while self.buffer and isinstance(self.buffer[0], Text):
213 x = self.buffer.popleft()
213 x = self.buffer.popleft()
214 self.output_width = x.output(self.output, self.output_width)
214 self.output_width = x.output(self.output, self.output_width)
215 self.buffer_width -= x.width
215 self.buffer_width -= x.width
216
216
217 def text(self, obj):
217 def text(self, obj):
218 """Add literal text to the output."""
218 """Add literal text to the output."""
219 width = len(obj)
219 width = len(obj)
220 if self.buffer:
220 if self.buffer:
221 text = self.buffer[-1]
221 text = self.buffer[-1]
222 if not isinstance(text, Text):
222 if not isinstance(text, Text):
223 text = Text()
223 text = Text()
224 self.buffer.append(text)
224 self.buffer.append(text)
225 text.add(obj, width)
225 text.add(obj, width)
226 self.buffer_width += width
226 self.buffer_width += width
227 self._break_outer_groups()
227 self._break_outer_groups()
228 else:
228 else:
229 self.output.write(obj)
229 self.output.write(obj)
230 self.output_width += width
230 self.output_width += width
231
231
232 def breakable(self, sep=' '):
232 def breakable(self, sep=' '):
233 """
233 """
234 Add a breakable separator to the output. This does not mean that it
234 Add a breakable separator to the output. This does not mean that it
235 will automatically break here. If no breaking on this position takes
235 will automatically break here. If no breaking on this position takes
236 place the `sep` is inserted which default to one space.
236 place the `sep` is inserted which default to one space.
237 """
237 """
238 width = len(sep)
238 width = len(sep)
239 group = self.group_stack[-1]
239 group = self.group_stack[-1]
240 if group.want_break:
240 if group.want_break:
241 self.flush()
241 self.flush()
242 self.output.write(self.newline)
242 self.output.write(self.newline)
243 self.output.write(' ' * self.indentation)
243 self.output.write(' ' * self.indentation)
244 self.output_width = self.indentation
244 self.output_width = self.indentation
245 self.buffer_width = 0
245 self.buffer_width = 0
246 else:
246 else:
247 self.buffer.append(Breakable(sep, width, self))
247 self.buffer.append(Breakable(sep, width, self))
248 self.buffer_width += width
248 self.buffer_width += width
249 self._break_outer_groups()
249 self._break_outer_groups()
250
250
251 def break_(self):
251 def break_(self):
252 """
252 """
253 Explicitly insert a newline into the output, maintaining correct indentation.
253 Explicitly insert a newline into the output, maintaining correct indentation.
254 """
254 """
255 self.flush()
255 self.flush()
256 self.output.write(self.newline)
256 self.output.write(self.newline)
257 self.output.write(' ' * self.indentation)
257 self.output.write(' ' * self.indentation)
258 self.output_width = self.indentation
258 self.output_width = self.indentation
259 self.buffer_width = 0
259 self.buffer_width = 0
260
260
261
261
262 def begin_group(self, indent=0, open=''):
262 def begin_group(self, indent=0, open=''):
263 """
263 """
264 Begin a group. If you want support for python < 2.5 which doesn't has
264 Begin a group. If you want support for python < 2.5 which doesn't has
265 the with statement this is the preferred way:
265 the with statement this is the preferred way:
266
266
267 p.begin_group(1, '{')
267 p.begin_group(1, '{')
268 ...
268 ...
269 p.end_group(1, '}')
269 p.end_group(1, '}')
270
270
271 The python 2.5 expression would be this:
271 The python 2.5 expression would be this:
272
272
273 with p.group(1, '{', '}'):
273 with p.group(1, '{', '}'):
274 ...
274 ...
275
275
276 The first parameter specifies the indentation for the next line (usually
276 The first parameter specifies the indentation for the next line (usually
277 the width of the opening text), the second the opening text. All
277 the width of the opening text), the second the opening text. All
278 parameters are optional.
278 parameters are optional.
279 """
279 """
280 if open:
280 if open:
281 self.text(open)
281 self.text(open)
282 group = Group(self.group_stack[-1].depth + 1)
282 group = Group(self.group_stack[-1].depth + 1)
283 self.group_stack.append(group)
283 self.group_stack.append(group)
284 self.group_queue.enq(group)
284 self.group_queue.enq(group)
285 self.indentation += indent
285 self.indentation += indent
286
286
287 def _enumerate(self, seq):
287 def _enumerate(self, seq):
288 """like enumerate, but with an upper limit on the number of items"""
288 """like enumerate, but with an upper limit on the number of items"""
289 for idx, x in enumerate(seq):
289 for idx, x in enumerate(seq):
290 if self.max_seq_length and idx >= self.max_seq_length:
290 if self.max_seq_length and idx >= self.max_seq_length:
291 self.text(',')
291 self.text(',')
292 self.breakable()
292 self.breakable()
293 self.text('...')
293 self.text('...')
294 raise StopIteration
294 raise StopIteration
295 yield idx, x
295 yield idx, x
296
296
297 def end_group(self, dedent=0, close=''):
297 def end_group(self, dedent=0, close=''):
298 """End a group. See `begin_group` for more details."""
298 """End a group. See `begin_group` for more details."""
299 self.indentation -= dedent
299 self.indentation -= dedent
300 group = self.group_stack.pop()
300 group = self.group_stack.pop()
301 if not group.breakables:
301 if not group.breakables:
302 self.group_queue.remove(group)
302 self.group_queue.remove(group)
303 if close:
303 if close:
304 self.text(close)
304 self.text(close)
305
305
306 def flush(self):
306 def flush(self):
307 """Flush data that is left in the buffer."""
307 """Flush data that is left in the buffer."""
308 for data in self.buffer:
308 for data in self.buffer:
309 self.output_width += data.output(self.output, self.output_width)
309 self.output_width += data.output(self.output, self.output_width)
310 self.buffer.clear()
310 self.buffer.clear()
311 self.buffer_width = 0
311 self.buffer_width = 0
312
312
313
313
314 def _get_mro(obj_class):
314 def _get_mro(obj_class):
315 """ Get a reasonable method resolution order of a class and its superclasses
315 """ Get a reasonable method resolution order of a class and its superclasses
316 for both old-style and new-style classes.
316 for both old-style and new-style classes.
317 """
317 """
318 if not hasattr(obj_class, '__mro__'):
318 if not hasattr(obj_class, '__mro__'):
319 # Old-style class. Mix in object to make a fake new-style class.
319 # Old-style class. Mix in object to make a fake new-style class.
320 try:
320 try:
321 obj_class = type(obj_class.__name__, (obj_class, object), {})
321 obj_class = type(obj_class.__name__, (obj_class, object), {})
322 except TypeError:
322 except TypeError:
323 # Old-style extension type that does not descend from object.
323 # Old-style extension type that does not descend from object.
324 # FIXME: try to construct a more thorough MRO.
324 # FIXME: try to construct a more thorough MRO.
325 mro = [obj_class]
325 mro = [obj_class]
326 else:
326 else:
327 mro = obj_class.__mro__[1:-1]
327 mro = obj_class.__mro__[1:-1]
328 else:
328 else:
329 mro = obj_class.__mro__
329 mro = obj_class.__mro__
330 return mro
330 return mro
331
331
332
332
333 class RepresentationPrinter(PrettyPrinter):
333 class RepresentationPrinter(PrettyPrinter):
334 """
334 """
335 Special pretty printer that has a `pretty` method that calls the pretty
335 Special pretty printer that has a `pretty` method that calls the pretty
336 printer for a python object.
336 printer for a python object.
337
337
338 This class stores processing data on `self` so you must *never* use
338 This class stores processing data on `self` so you must *never* use
339 this class in a threaded environment. Always lock it or reinstanciate
339 this class in a threaded environment. Always lock it or reinstanciate
340 it.
340 it.
341
341
342 Instances also have a verbose flag callbacks can access to control their
342 Instances also have a verbose flag callbacks can access to control their
343 output. For example the default instance repr prints all attributes and
343 output. For example the default instance repr prints all attributes and
344 methods that are not prefixed by an underscore if the printer is in
344 methods that are not prefixed by an underscore if the printer is in
345 verbose mode.
345 verbose mode.
346 """
346 """
347
347
348 def __init__(self, output, verbose=False, max_width=79, newline='\n',
348 def __init__(self, output, verbose=False, max_width=79, newline='\n',
349 singleton_pprinters=None, type_pprinters=None, deferred_pprinters=None):
349 singleton_pprinters=None, type_pprinters=None, deferred_pprinters=None):
350
350
351 PrettyPrinter.__init__(self, output, max_width, newline)
351 PrettyPrinter.__init__(self, output, max_width, newline)
352 self.verbose = verbose
352 self.verbose = verbose
353 self.stack = []
353 self.stack = []
354 if singleton_pprinters is None:
354 if singleton_pprinters is None:
355 singleton_pprinters = _singleton_pprinters.copy()
355 singleton_pprinters = _singleton_pprinters.copy()
356 self.singleton_pprinters = singleton_pprinters
356 self.singleton_pprinters = singleton_pprinters
357 if type_pprinters is None:
357 if type_pprinters is None:
358 type_pprinters = _type_pprinters.copy()
358 type_pprinters = _type_pprinters.copy()
359 self.type_pprinters = type_pprinters
359 self.type_pprinters = type_pprinters
360 if deferred_pprinters is None:
360 if deferred_pprinters is None:
361 deferred_pprinters = _deferred_type_pprinters.copy()
361 deferred_pprinters = _deferred_type_pprinters.copy()
362 self.deferred_pprinters = deferred_pprinters
362 self.deferred_pprinters = deferred_pprinters
363
363
364 def pretty(self, obj):
364 def pretty(self, obj):
365 """Pretty print the given object."""
365 """Pretty print the given object."""
366 obj_id = id(obj)
366 obj_id = id(obj)
367 cycle = obj_id in self.stack
367 cycle = obj_id in self.stack
368 self.stack.append(obj_id)
368 self.stack.append(obj_id)
369 self.begin_group()
369 self.begin_group()
370 try:
370 try:
371 obj_class = _safe_getattr(obj, '__class__', None) or type(obj)
371 obj_class = _safe_getattr(obj, '__class__', None) or type(obj)
372 # First try to find registered singleton printers for the type.
372 # First try to find registered singleton printers for the type.
373 try:
373 try:
374 printer = self.singleton_pprinters[obj_id]
374 printer = self.singleton_pprinters[obj_id]
375 except (TypeError, KeyError):
375 except (TypeError, KeyError):
376 pass
376 pass
377 else:
377 else:
378 return printer(obj, self, cycle)
378 return printer(obj, self, cycle)
379 # Next walk the mro and check for either:
379 # Next walk the mro and check for either:
380 # 1) a registered printer
380 # 1) a registered printer
381 # 2) a _repr_pretty_ method
381 # 2) a _repr_pretty_ method
382 for cls in _get_mro(obj_class):
382 for cls in _get_mro(obj_class):
383 if cls in self.type_pprinters:
383 if cls in self.type_pprinters:
384 # printer registered in self.type_pprinters
384 # printer registered in self.type_pprinters
385 return self.type_pprinters[cls](obj, self, cycle)
385 return self.type_pprinters[cls](obj, self, cycle)
386 else:
386 else:
387 # deferred printer
387 # deferred printer
388 printer = self._in_deferred_types(cls)
388 printer = self._in_deferred_types(cls)
389 if printer is not None:
389 if printer is not None:
390 return printer(obj, self, cycle)
390 return printer(obj, self, cycle)
391 else:
391 else:
392 # Finally look for special method names.
392 # Finally look for special method names.
393 # Some objects automatically create any requested
393 # Some objects automatically create any requested
394 # attribute. Try to ignore most of them by checking for
394 # attribute. Try to ignore most of them by checking for
395 # callability.
395 # callability.
396 if '_repr_pretty_' in cls.__dict__:
396 if '_repr_pretty_' in cls.__dict__:
397 meth = cls._repr_pretty_
397 meth = cls._repr_pretty_
398 if callable(meth):
398 if callable(meth):
399 return meth(obj, self, cycle)
399 return meth(obj, self, cycle)
400 return _default_pprint(obj, self, cycle)
400 return _default_pprint(obj, self, cycle)
401 finally:
401 finally:
402 self.end_group()
402 self.end_group()
403 self.stack.pop()
403 self.stack.pop()
404
404
405 def _in_deferred_types(self, cls):
405 def _in_deferred_types(self, cls):
406 """
406 """
407 Check if the given class is specified in the deferred type registry.
407 Check if the given class is specified in the deferred type registry.
408
408
409 Returns the printer from the registry if it exists, and None if the
409 Returns the printer from the registry if it exists, and None if the
410 class is not in the registry. Successful matches will be moved to the
410 class is not in the registry. Successful matches will be moved to the
411 regular type registry for future use.
411 regular type registry for future use.
412 """
412 """
413 mod = _safe_getattr(cls, '__module__', None)
413 mod = _safe_getattr(cls, '__module__', None)
414 name = _safe_getattr(cls, '__name__', None)
414 name = _safe_getattr(cls, '__name__', None)
415 key = (mod, name)
415 key = (mod, name)
416 printer = None
416 printer = None
417 if key in self.deferred_pprinters:
417 if key in self.deferred_pprinters:
418 # Move the printer over to the regular registry.
418 # Move the printer over to the regular registry.
419 printer = self.deferred_pprinters.pop(key)
419 printer = self.deferred_pprinters.pop(key)
420 self.type_pprinters[cls] = printer
420 self.type_pprinters[cls] = printer
421 return printer
421 return printer
422
422
423
423
424 class Printable(object):
424 class Printable(object):
425
425
426 def output(self, stream, output_width):
426 def output(self, stream, output_width):
427 return output_width
427 return output_width
428
428
429
429
430 class Text(Printable):
430 class Text(Printable):
431
431
432 def __init__(self):
432 def __init__(self):
433 self.objs = []
433 self.objs = []
434 self.width = 0
434 self.width = 0
435
435
436 def output(self, stream, output_width):
436 def output(self, stream, output_width):
437 for obj in self.objs:
437 for obj in self.objs:
438 stream.write(obj)
438 stream.write(obj)
439 return output_width + self.width
439 return output_width + self.width
440
440
441 def add(self, obj, width):
441 def add(self, obj, width):
442 self.objs.append(obj)
442 self.objs.append(obj)
443 self.width += width
443 self.width += width
444
444
445
445
446 class Breakable(Printable):
446 class Breakable(Printable):
447
447
448 def __init__(self, seq, width, pretty):
448 def __init__(self, seq, width, pretty):
449 self.obj = seq
449 self.obj = seq
450 self.width = width
450 self.width = width
451 self.pretty = pretty
451 self.pretty = pretty
452 self.indentation = pretty.indentation
452 self.indentation = pretty.indentation
453 self.group = pretty.group_stack[-1]
453 self.group = pretty.group_stack[-1]
454 self.group.breakables.append(self)
454 self.group.breakables.append(self)
455
455
456 def output(self, stream, output_width):
456 def output(self, stream, output_width):
457 self.group.breakables.popleft()
457 self.group.breakables.popleft()
458 if self.group.want_break:
458 if self.group.want_break:
459 stream.write(self.pretty.newline)
459 stream.write(self.pretty.newline)
460 stream.write(' ' * self.indentation)
460 stream.write(' ' * self.indentation)
461 return self.indentation
461 return self.indentation
462 if not self.group.breakables:
462 if not self.group.breakables:
463 self.pretty.group_queue.remove(self.group)
463 self.pretty.group_queue.remove(self.group)
464 stream.write(self.obj)
464 stream.write(self.obj)
465 return output_width + self.width
465 return output_width + self.width
466
466
467
467
468 class Group(Printable):
468 class Group(Printable):
469
469
470 def __init__(self, depth):
470 def __init__(self, depth):
471 self.depth = depth
471 self.depth = depth
472 self.breakables = deque()
472 self.breakables = deque()
473 self.want_break = False
473 self.want_break = False
474
474
475
475
476 class GroupQueue(object):
476 class GroupQueue(object):
477
477
478 def __init__(self, *groups):
478 def __init__(self, *groups):
479 self.queue = []
479 self.queue = []
480 for group in groups:
480 for group in groups:
481 self.enq(group)
481 self.enq(group)
482
482
483 def enq(self, group):
483 def enq(self, group):
484 depth = group.depth
484 depth = group.depth
485 while depth > len(self.queue) - 1:
485 while depth > len(self.queue) - 1:
486 self.queue.append([])
486 self.queue.append([])
487 self.queue[depth].append(group)
487 self.queue[depth].append(group)
488
488
489 def deq(self):
489 def deq(self):
490 for stack in self.queue:
490 for stack in self.queue:
491 for idx, group in enumerate(reversed(stack)):
491 for idx, group in enumerate(reversed(stack)):
492 if group.breakables:
492 if group.breakables:
493 del stack[idx]
493 del stack[idx]
494 group.want_break = True
494 group.want_break = True
495 return group
495 return group
496 for group in stack:
496 for group in stack:
497 group.want_break = True
497 group.want_break = True
498 del stack[:]
498 del stack[:]
499
499
500 def remove(self, group):
500 def remove(self, group):
501 try:
501 try:
502 self.queue[group.depth].remove(group)
502 self.queue[group.depth].remove(group)
503 except ValueError:
503 except ValueError:
504 pass
504 pass
505
505
506 try:
506 try:
507 _baseclass_reprs = (object.__repr__, types.InstanceType.__repr__)
507 _baseclass_reprs = (object.__repr__, types.InstanceType.__repr__)
508 except AttributeError: # Python 3
508 except AttributeError: # Python 3
509 _baseclass_reprs = (object.__repr__,)
509 _baseclass_reprs = (object.__repr__,)
510
510
511
511
512 def _default_pprint(obj, p, cycle):
512 def _default_pprint(obj, p, cycle):
513 """
513 """
514 The default print function. Used if an object does not provide one and
514 The default print function. Used if an object does not provide one and
515 it's none of the builtin objects.
515 it's none of the builtin objects.
516 """
516 """
517 klass = _safe_getattr(obj, '__class__', None) or type(obj)
517 klass = _safe_getattr(obj, '__class__', None) or type(obj)
518 if _safe_getattr(klass, '__repr__', None) not in _baseclass_reprs:
518 if _safe_getattr(klass, '__repr__', None) not in _baseclass_reprs:
519 # A user-provided repr. Find newlines and replace them with p.break_()
519 # A user-provided repr. Find newlines and replace them with p.break_()
520 _repr_pprint(obj, p, cycle)
520 _repr_pprint(obj, p, cycle)
521 return
521 return
522 p.begin_group(1, '<')
522 p.begin_group(1, '<')
523 p.pretty(klass)
523 p.pretty(klass)
524 p.text(' at 0x%x' % id(obj))
524 p.text(' at 0x%x' % id(obj))
525 if cycle:
525 if cycle:
526 p.text(' ...')
526 p.text(' ...')
527 elif p.verbose:
527 elif p.verbose:
528 first = True
528 first = True
529 for key in dir(obj):
529 for key in dir(obj):
530 if not key.startswith('_'):
530 if not key.startswith('_'):
531 try:
531 try:
532 value = getattr(obj, key)
532 value = getattr(obj, key)
533 except AttributeError:
533 except AttributeError:
534 continue
534 continue
535 if isinstance(value, types.MethodType):
535 if isinstance(value, types.MethodType):
536 continue
536 continue
537 if not first:
537 if not first:
538 p.text(',')
538 p.text(',')
539 p.breakable()
539 p.breakable()
540 p.text(key)
540 p.text(key)
541 p.text('=')
541 p.text('=')
542 step = len(key) + 1
542 step = len(key) + 1
543 p.indentation += step
543 p.indentation += step
544 p.pretty(value)
544 p.pretty(value)
545 p.indentation -= step
545 p.indentation -= step
546 first = False
546 first = False
547 p.end_group(1, '>')
547 p.end_group(1, '>')
548
548
549
549
550 def _seq_pprinter_factory(start, end, basetype):
550 def _seq_pprinter_factory(start, end, basetype):
551 """
551 """
552 Factory that returns a pprint function useful for sequences. Used by
552 Factory that returns a pprint function useful for sequences. Used by
553 the default pprint for tuples, dicts, and lists.
553 the default pprint for tuples, dicts, and lists.
554 """
554 """
555 def inner(obj, p, cycle):
555 def inner(obj, p, cycle):
556 typ = type(obj)
556 typ = type(obj)
557 if basetype is not None and typ is not basetype and typ.__repr__ != basetype.__repr__:
557 if basetype is not None and typ is not basetype and typ.__repr__ != basetype.__repr__:
558 # If the subclass provides its own repr, use it instead.
558 # If the subclass provides its own repr, use it instead.
559 return p.text(typ.__repr__(obj))
559 return p.text(typ.__repr__(obj))
560
560
561 if cycle:
561 if cycle:
562 return p.text(start + '...' + end)
562 return p.text(start + '...' + end)
563 step = len(start)
563 step = len(start)
564 p.begin_group(step, start)
564 p.begin_group(step, start)
565 for idx, x in p._enumerate(obj):
565 for idx, x in p._enumerate(obj):
566 if idx:
566 if idx:
567 p.text(',')
567 p.text(',')
568 p.breakable()
568 p.breakable()
569 p.pretty(x)
569 p.pretty(x)
570 if len(obj) == 1 and type(obj) is tuple:
570 if len(obj) == 1 and type(obj) is tuple:
571 # Special case for 1-item tuples.
571 # Special case for 1-item tuples.
572 p.text(',')
572 p.text(',')
573 p.end_group(step, end)
573 p.end_group(step, end)
574 return inner
574 return inner
575
575
576
576
577 def _set_pprinter_factory(start, end, basetype):
577 def _set_pprinter_factory(start, end, basetype):
578 """
578 """
579 Factory that returns a pprint function useful for sets and frozensets.
579 Factory that returns a pprint function useful for sets and frozensets.
580 """
580 """
581 def inner(obj, p, cycle):
581 def inner(obj, p, cycle):
582 typ = type(obj)
582 typ = type(obj)
583 if basetype is not None and typ is not basetype and typ.__repr__ != basetype.__repr__:
583 if basetype is not None and typ is not basetype and typ.__repr__ != basetype.__repr__:
584 # If the subclass provides its own repr, use it instead.
584 # If the subclass provides its own repr, use it instead.
585 return p.text(typ.__repr__(obj))
585 return p.text(typ.__repr__(obj))
586
586
587 if cycle:
587 if cycle:
588 return p.text(start + '...' + end)
588 return p.text(start + '...' + end)
589 if len(obj) == 0:
589 if len(obj) == 0:
590 # Special case.
590 # Special case.
591 p.text(basetype.__name__ + '()')
591 p.text(basetype.__name__ + '()')
592 else:
592 else:
593 step = len(start)
593 step = len(start)
594 p.begin_group(step, start)
594 p.begin_group(step, start)
595 # Like dictionary keys, we will try to sort the items.
595 # Like dictionary keys, we will try to sort the items if there aren't too many
596 items = list(obj)
596 items = obj
597 if not (p.max_seq_length and len(obj) >= p.max_seq_length):
597 try:
598 try:
598 items.sort()
599 items = sorted(obj)
599 except Exception:
600 except Exception:
600 # Sometimes the items don't sort.
601 # Sometimes the items don't sort.
601 pass
602 pass
602 for idx, x in p._enumerate(items):
603 for idx, x in p._enumerate(items):
603 if idx:
604 if idx:
604 p.text(',')
605 p.text(',')
605 p.breakable()
606 p.breakable()
606 p.pretty(x)
607 p.pretty(x)
607 p.end_group(step, end)
608 p.end_group(step, end)
608 return inner
609 return inner
609
610
610
611
611 def _dict_pprinter_factory(start, end, basetype=None):
612 def _dict_pprinter_factory(start, end, basetype=None):
612 """
613 """
613 Factory that returns a pprint function used by the default pprint of
614 Factory that returns a pprint function used by the default pprint of
614 dicts and dict proxies.
615 dicts and dict proxies.
615 """
616 """
616 def inner(obj, p, cycle):
617 def inner(obj, p, cycle):
617 typ = type(obj)
618 typ = type(obj)
618 if basetype is not None and typ is not basetype and typ.__repr__ != basetype.__repr__:
619 if basetype is not None and typ is not basetype and typ.__repr__ != basetype.__repr__:
619 # If the subclass provides its own repr, use it instead.
620 # If the subclass provides its own repr, use it instead.
620 return p.text(typ.__repr__(obj))
621 return p.text(typ.__repr__(obj))
621
622
622 if cycle:
623 if cycle:
623 return p.text('{...}')
624 return p.text('{...}')
624 p.begin_group(1, start)
625 p.begin_group(1, start)
625 keys = obj.keys()
626 keys = obj.keys()
627 # if dict isn't large enough to be truncated, sort keys before displaying
628 if not (p.max_seq_length and len(obj) >= p.max_seq_length):
626 try:
629 try:
627 keys.sort()
630 keys = sorted(keys)
628 except Exception as e:
631 except Exception:
629 # Sometimes the keys don't sort.
632 # Sometimes the keys don't sort.
630 pass
633 pass
631 for idx, key in p._enumerate(keys):
634 for idx, key in p._enumerate(keys):
632 if idx:
635 if idx:
633 p.text(',')
636 p.text(',')
634 p.breakable()
637 p.breakable()
635 p.pretty(key)
638 p.pretty(key)
636 p.text(': ')
639 p.text(': ')
637 p.pretty(obj[key])
640 p.pretty(obj[key])
638 p.end_group(1, end)
641 p.end_group(1, end)
639 return inner
642 return inner
640
643
641
644
642 def _super_pprint(obj, p, cycle):
645 def _super_pprint(obj, p, cycle):
643 """The pprint for the super type."""
646 """The pprint for the super type."""
644 p.begin_group(8, '<super: ')
647 p.begin_group(8, '<super: ')
645 p.pretty(obj.__thisclass__)
648 p.pretty(obj.__thisclass__)
646 p.text(',')
649 p.text(',')
647 p.breakable()
650 p.breakable()
648 p.pretty(obj.__self__)
651 p.pretty(obj.__self__)
649 p.end_group(8, '>')
652 p.end_group(8, '>')
650
653
651
654
652 def _re_pattern_pprint(obj, p, cycle):
655 def _re_pattern_pprint(obj, p, cycle):
653 """The pprint function for regular expression patterns."""
656 """The pprint function for regular expression patterns."""
654 p.text('re.compile(')
657 p.text('re.compile(')
655 pattern = repr(obj.pattern)
658 pattern = repr(obj.pattern)
656 if pattern[:1] in 'uU':
659 if pattern[:1] in 'uU':
657 pattern = pattern[1:]
660 pattern = pattern[1:]
658 prefix = 'ur'
661 prefix = 'ur'
659 else:
662 else:
660 prefix = 'r'
663 prefix = 'r'
661 pattern = prefix + pattern.replace('\\\\', '\\')
664 pattern = prefix + pattern.replace('\\\\', '\\')
662 p.text(pattern)
665 p.text(pattern)
663 if obj.flags:
666 if obj.flags:
664 p.text(',')
667 p.text(',')
665 p.breakable()
668 p.breakable()
666 done_one = False
669 done_one = False
667 for flag in ('TEMPLATE', 'IGNORECASE', 'LOCALE', 'MULTILINE', 'DOTALL',
670 for flag in ('TEMPLATE', 'IGNORECASE', 'LOCALE', 'MULTILINE', 'DOTALL',
668 'UNICODE', 'VERBOSE', 'DEBUG'):
671 'UNICODE', 'VERBOSE', 'DEBUG'):
669 if obj.flags & getattr(re, flag):
672 if obj.flags & getattr(re, flag):
670 if done_one:
673 if done_one:
671 p.text('|')
674 p.text('|')
672 p.text('re.' + flag)
675 p.text('re.' + flag)
673 done_one = True
676 done_one = True
674 p.text(')')
677 p.text(')')
675
678
676
679
677 def _type_pprint(obj, p, cycle):
680 def _type_pprint(obj, p, cycle):
678 """The pprint for classes and types."""
681 """The pprint for classes and types."""
679 # Heap allocated types might not have the module attribute,
682 # Heap allocated types might not have the module attribute,
680 # and others may set it to None.
683 # and others may set it to None.
681
684
682 # Checks for a __repr__ override in the metaclass
685 # Checks for a __repr__ override in the metaclass
683 if type(obj).__repr__ is not type.__repr__:
686 if type(obj).__repr__ is not type.__repr__:
684 _repr_pprint(obj, p, cycle)
687 _repr_pprint(obj, p, cycle)
685 return
688 return
686
689
687 mod = _safe_getattr(obj, '__module__', None)
690 mod = _safe_getattr(obj, '__module__', None)
688 name = _safe_getattr(obj, '__qualname__', obj.__name__)
691 name = _safe_getattr(obj, '__qualname__', obj.__name__)
689
692
690 if mod in (None, '__builtin__', 'builtins', 'exceptions'):
693 if mod in (None, '__builtin__', 'builtins', 'exceptions'):
691 p.text(name)
694 p.text(name)
692 else:
695 else:
693 p.text(mod + '.' + name)
696 p.text(mod + '.' + name)
694
697
695
698
696 def _repr_pprint(obj, p, cycle):
699 def _repr_pprint(obj, p, cycle):
697 """A pprint that just redirects to the normal repr function."""
700 """A pprint that just redirects to the normal repr function."""
698 # Find newlines and replace them with p.break_()
701 # Find newlines and replace them with p.break_()
699 output = repr(obj)
702 output = repr(obj)
700 for idx,output_line in enumerate(output.splitlines()):
703 for idx,output_line in enumerate(output.splitlines()):
701 if idx:
704 if idx:
702 p.break_()
705 p.break_()
703 p.text(output_line)
706 p.text(output_line)
704
707
705
708
706 def _function_pprint(obj, p, cycle):
709 def _function_pprint(obj, p, cycle):
707 """Base pprint for all functions and builtin functions."""
710 """Base pprint for all functions and builtin functions."""
708 name = _safe_getattr(obj, '__qualname__', obj.__name__)
711 name = _safe_getattr(obj, '__qualname__', obj.__name__)
709 mod = obj.__module__
712 mod = obj.__module__
710 if mod and mod not in ('__builtin__', 'builtins', 'exceptions'):
713 if mod and mod not in ('__builtin__', 'builtins', 'exceptions'):
711 name = mod + '.' + name
714 name = mod + '.' + name
712 p.text('<function %s>' % name)
715 p.text('<function %s>' % name)
713
716
714
717
715 def _exception_pprint(obj, p, cycle):
718 def _exception_pprint(obj, p, cycle):
716 """Base pprint for all exceptions."""
719 """Base pprint for all exceptions."""
717 name = getattr(obj.__class__, '__qualname__', obj.__class__.__name__)
720 name = getattr(obj.__class__, '__qualname__', obj.__class__.__name__)
718 if obj.__class__.__module__ not in ('exceptions', 'builtins'):
721 if obj.__class__.__module__ not in ('exceptions', 'builtins'):
719 name = '%s.%s' % (obj.__class__.__module__, name)
722 name = '%s.%s' % (obj.__class__.__module__, name)
720 step = len(name) + 1
723 step = len(name) + 1
721 p.begin_group(step, name + '(')
724 p.begin_group(step, name + '(')
722 for idx, arg in enumerate(getattr(obj, 'args', ())):
725 for idx, arg in enumerate(getattr(obj, 'args', ())):
723 if idx:
726 if idx:
724 p.text(',')
727 p.text(',')
725 p.breakable()
728 p.breakable()
726 p.pretty(arg)
729 p.pretty(arg)
727 p.end_group(step, ')')
730 p.end_group(step, ')')
728
731
729
732
730 #: the exception base
733 #: the exception base
731 try:
734 try:
732 _exception_base = BaseException
735 _exception_base = BaseException
733 except NameError:
736 except NameError:
734 _exception_base = Exception
737 _exception_base = Exception
735
738
736
739
737 #: printers for builtin types
740 #: printers for builtin types
738 _type_pprinters = {
741 _type_pprinters = {
739 int: _repr_pprint,
742 int: _repr_pprint,
740 float: _repr_pprint,
743 float: _repr_pprint,
741 str: _repr_pprint,
744 str: _repr_pprint,
742 tuple: _seq_pprinter_factory('(', ')', tuple),
745 tuple: _seq_pprinter_factory('(', ')', tuple),
743 list: _seq_pprinter_factory('[', ']', list),
746 list: _seq_pprinter_factory('[', ']', list),
744 dict: _dict_pprinter_factory('{', '}', dict),
747 dict: _dict_pprinter_factory('{', '}', dict),
745
748
746 set: _set_pprinter_factory('{', '}', set),
749 set: _set_pprinter_factory('{', '}', set),
747 frozenset: _set_pprinter_factory('frozenset({', '})', frozenset),
750 frozenset: _set_pprinter_factory('frozenset({', '})', frozenset),
748 super: _super_pprint,
751 super: _super_pprint,
749 _re_pattern_type: _re_pattern_pprint,
752 _re_pattern_type: _re_pattern_pprint,
750 type: _type_pprint,
753 type: _type_pprint,
751 types.FunctionType: _function_pprint,
754 types.FunctionType: _function_pprint,
752 types.BuiltinFunctionType: _function_pprint,
755 types.BuiltinFunctionType: _function_pprint,
753 types.MethodType: _repr_pprint,
756 types.MethodType: _repr_pprint,
754
757
755 datetime.datetime: _repr_pprint,
758 datetime.datetime: _repr_pprint,
756 datetime.timedelta: _repr_pprint,
759 datetime.timedelta: _repr_pprint,
757 _exception_base: _exception_pprint
760 _exception_base: _exception_pprint
758 }
761 }
759
762
760 try:
763 try:
761 _type_pprinters[types.DictProxyType] = _dict_pprinter_factory('<dictproxy {', '}>')
764 _type_pprinters[types.DictProxyType] = _dict_pprinter_factory('<dictproxy {', '}>')
762 _type_pprinters[types.ClassType] = _type_pprint
765 _type_pprinters[types.ClassType] = _type_pprint
763 _type_pprinters[types.SliceType] = _repr_pprint
766 _type_pprinters[types.SliceType] = _repr_pprint
764 except AttributeError: # Python 3
767 except AttributeError: # Python 3
765 _type_pprinters[slice] = _repr_pprint
768 _type_pprinters[slice] = _repr_pprint
766
769
767 try:
770 try:
768 _type_pprinters[xrange] = _repr_pprint
771 _type_pprinters[xrange] = _repr_pprint
769 _type_pprinters[long] = _repr_pprint
772 _type_pprinters[long] = _repr_pprint
770 _type_pprinters[unicode] = _repr_pprint
773 _type_pprinters[unicode] = _repr_pprint
771 except NameError:
774 except NameError:
772 _type_pprinters[range] = _repr_pprint
775 _type_pprinters[range] = _repr_pprint
773 _type_pprinters[bytes] = _repr_pprint
776 _type_pprinters[bytes] = _repr_pprint
774
777
775 #: printers for types specified by name
778 #: printers for types specified by name
776 _deferred_type_pprinters = {
779 _deferred_type_pprinters = {
777 }
780 }
778
781
779 def for_type(typ, func):
782 def for_type(typ, func):
780 """
783 """
781 Add a pretty printer for a given type.
784 Add a pretty printer for a given type.
782 """
785 """
783 oldfunc = _type_pprinters.get(typ, None)
786 oldfunc = _type_pprinters.get(typ, None)
784 if func is not None:
787 if func is not None:
785 # To support easy restoration of old pprinters, we need to ignore Nones.
788 # To support easy restoration of old pprinters, we need to ignore Nones.
786 _type_pprinters[typ] = func
789 _type_pprinters[typ] = func
787 return oldfunc
790 return oldfunc
788
791
789 def for_type_by_name(type_module, type_name, func):
792 def for_type_by_name(type_module, type_name, func):
790 """
793 """
791 Add a pretty printer for a type specified by the module and name of a type
794 Add a pretty printer for a type specified by the module and name of a type
792 rather than the type object itself.
795 rather than the type object itself.
793 """
796 """
794 key = (type_module, type_name)
797 key = (type_module, type_name)
795 oldfunc = _deferred_type_pprinters.get(key, None)
798 oldfunc = _deferred_type_pprinters.get(key, None)
796 if func is not None:
799 if func is not None:
797 # To support easy restoration of old pprinters, we need to ignore Nones.
800 # To support easy restoration of old pprinters, we need to ignore Nones.
798 _deferred_type_pprinters[key] = func
801 _deferred_type_pprinters[key] = func
799 return oldfunc
802 return oldfunc
800
803
801
804
802 #: printers for the default singletons
805 #: printers for the default singletons
803 _singleton_pprinters = dict.fromkeys(map(id, [None, True, False, Ellipsis,
806 _singleton_pprinters = dict.fromkeys(map(id, [None, True, False, Ellipsis,
804 NotImplemented]), _repr_pprint)
807 NotImplemented]), _repr_pprint)
805
808
806
809
807 if __name__ == '__main__':
810 if __name__ == '__main__':
808 from random import randrange
811 from random import randrange
809 class Foo(object):
812 class Foo(object):
810 def __init__(self):
813 def __init__(self):
811 self.foo = 1
814 self.foo = 1
812 self.bar = re.compile(r'\s+')
815 self.bar = re.compile(r'\s+')
813 self.blub = dict.fromkeys(range(30), randrange(1, 40))
816 self.blub = dict.fromkeys(range(30), randrange(1, 40))
814 self.hehe = 23424.234234
817 self.hehe = 23424.234234
815 self.list = ["blub", "blah", self]
818 self.list = ["blub", "blah", self]
816
819
817 def get_foo(self):
820 def get_foo(self):
818 print("foo")
821 print("foo")
819
822
820 pprint(Foo(), verbose=True)
823 pprint(Foo(), verbose=True)
General Comments 0
You need to be logged in to leave comments. Login now