##// END OF EJS Templates
formatting
Randolf Scholz -
Show More
@@ -1,546 +1,546 b''
1 """Tests for the Formatters."""
1 """Tests for the Formatters."""
2
2
3 from math import pi
3 from math import pi
4
4
5 try:
5 try:
6 import numpy
6 import numpy
7 except:
7 except:
8 numpy = None
8 numpy = None
9 import pytest
9 import pytest
10
10
11 from IPython import get_ipython
11 from IPython import get_ipython
12 from traitlets.config import Config
12 from traitlets.config import Config
13 from IPython.core.formatters import (
13 from IPython.core.formatters import (
14 PlainTextFormatter, HTMLFormatter, PDFFormatter, _mod_name_key,
14 PlainTextFormatter, HTMLFormatter, PDFFormatter, _mod_name_key,
15 DisplayFormatter, JSONFormatter,
15 DisplayFormatter, JSONFormatter,
16 )
16 )
17 from IPython.utils.io import capture_output
17 from IPython.utils.io import capture_output
18
18
19 class A(object):
19 class A(object):
20 def __repr__(self):
20 def __repr__(self):
21 return 'A()'
21 return 'A()'
22
22
23 class B(A):
23 class B(A):
24 def __repr__(self):
24 def __repr__(self):
25 return 'B()'
25 return 'B()'
26
26
27 class C:
27 class C:
28 pass
28 pass
29
29
30 class BadRepr(object):
30 class BadRepr(object):
31 def __repr__(self):
31 def __repr__(self):
32 raise ValueError("bad repr")
32 raise ValueError("bad repr")
33
33
34 class BadPretty(object):
34 class BadPretty(object):
35 _repr_pretty_ = None
35 _repr_pretty_ = None
36
36
37 class GoodPretty(object):
37 class GoodPretty(object):
38 def _repr_pretty_(self, pp, cycle):
38 def _repr_pretty_(self, pp, cycle):
39 pp.text('foo')
39 pp.text('foo')
40
40
41 def __repr__(self):
41 def __repr__(self):
42 return 'GoodPretty()'
42 return 'GoodPretty()'
43
43
44 def foo_printer(obj, pp, cycle):
44 def foo_printer(obj, pp, cycle):
45 pp.text('foo')
45 pp.text('foo')
46
46
47 def test_pretty():
47 def test_pretty():
48 f = PlainTextFormatter()
48 f = PlainTextFormatter()
49 f.for_type(A, foo_printer)
49 f.for_type(A, foo_printer)
50 assert f(A()) == "foo"
50 assert f(A()) == "foo"
51 assert f(B()) == "B()"
51 assert f(B()) == "B()"
52 assert f(GoodPretty()) == "foo"
52 assert f(GoodPretty()) == "foo"
53 # Just don't raise an exception for the following:
53 # Just don't raise an exception for the following:
54 f(BadPretty())
54 f(BadPretty())
55
55
56 f.pprint = False
56 f.pprint = False
57 assert f(A()) == "A()"
57 assert f(A()) == "A()"
58 assert f(B()) == "B()"
58 assert f(B()) == "B()"
59 assert f(GoodPretty()) == "GoodPretty()"
59 assert f(GoodPretty()) == "GoodPretty()"
60
60
61
61
62 def test_deferred():
62 def test_deferred():
63 f = PlainTextFormatter()
63 f = PlainTextFormatter()
64
64
65 def test_precision():
65 def test_precision():
66 """test various values for float_precision."""
66 """test various values for float_precision."""
67 f = PlainTextFormatter()
67 f = PlainTextFormatter()
68 assert f(pi) == repr(pi)
68 assert f(pi) == repr(pi)
69 f.float_precision = 0
69 f.float_precision = 0
70 if numpy:
70 if numpy:
71 po = numpy.get_printoptions()
71 po = numpy.get_printoptions()
72 assert po["precision"] == 0
72 assert po["precision"] == 0
73 assert f(pi) == "3"
73 assert f(pi) == "3"
74 f.float_precision = 2
74 f.float_precision = 2
75 if numpy:
75 if numpy:
76 po = numpy.get_printoptions()
76 po = numpy.get_printoptions()
77 assert po["precision"] == 2
77 assert po["precision"] == 2
78 assert f(pi) == "3.14"
78 assert f(pi) == "3.14"
79 f.float_precision = "%g"
79 f.float_precision = "%g"
80 if numpy:
80 if numpy:
81 po = numpy.get_printoptions()
81 po = numpy.get_printoptions()
82 assert po["precision"] == 2
82 assert po["precision"] == 2
83 assert f(pi) == "3.14159"
83 assert f(pi) == "3.14159"
84 f.float_precision = "%e"
84 f.float_precision = "%e"
85 assert f(pi) == "3.141593e+00"
85 assert f(pi) == "3.141593e+00"
86 f.float_precision = ""
86 f.float_precision = ""
87 if numpy:
87 if numpy:
88 po = numpy.get_printoptions()
88 po = numpy.get_printoptions()
89 assert po["precision"] == 8
89 assert po["precision"] == 8
90 assert f(pi) == repr(pi)
90 assert f(pi) == repr(pi)
91
91
92
92
93 def test_bad_precision():
93 def test_bad_precision():
94 """test various invalid values for float_precision."""
94 """test various invalid values for float_precision."""
95 f = PlainTextFormatter()
95 f = PlainTextFormatter()
96 def set_fp(p):
96 def set_fp(p):
97 f.float_precision = p
97 f.float_precision = p
98
98
99 pytest.raises(ValueError, set_fp, "%")
99 pytest.raises(ValueError, set_fp, "%")
100 pytest.raises(ValueError, set_fp, "%.3f%i")
100 pytest.raises(ValueError, set_fp, "%.3f%i")
101 pytest.raises(ValueError, set_fp, "foo")
101 pytest.raises(ValueError, set_fp, "foo")
102 pytest.raises(ValueError, set_fp, -1)
102 pytest.raises(ValueError, set_fp, -1)
103
103
104 def test_for_type():
104 def test_for_type():
105 f = PlainTextFormatter()
105 f = PlainTextFormatter()
106
106
107 # initial return, None
107 # initial return, None
108 assert f.for_type(C, foo_printer) is None
108 assert f.for_type(C, foo_printer) is None
109 # no func queries
109 # no func queries
110 assert f.for_type(C) is foo_printer
110 assert f.for_type(C) is foo_printer
111 # shouldn't change anything
111 # shouldn't change anything
112 assert f.for_type(C) is foo_printer
112 assert f.for_type(C) is foo_printer
113 # None should do the same
113 # None should do the same
114 assert f.for_type(C, None) is foo_printer
114 assert f.for_type(C, None) is foo_printer
115 assert f.for_type(C, None) is foo_printer
115 assert f.for_type(C, None) is foo_printer
116
116
117 def test_for_type_string():
117 def test_for_type_string():
118 f = PlainTextFormatter()
118 f = PlainTextFormatter()
119
119
120 type_str = '%s.%s' % (C.__module__, 'C')
120 type_str = '%s.%s' % (C.__module__, 'C')
121
121
122 # initial return, None
122 # initial return, None
123 assert f.for_type(type_str, foo_printer) is None
123 assert f.for_type(type_str, foo_printer) is None
124 # no func queries
124 # no func queries
125 assert f.for_type(type_str) is foo_printer
125 assert f.for_type(type_str) is foo_printer
126 assert _mod_name_key(C) in f.deferred_printers
126 assert _mod_name_key(C) in f.deferred_printers
127 assert f.for_type(C) is foo_printer
127 assert f.for_type(C) is foo_printer
128 assert _mod_name_key(C) not in f.deferred_printers
128 assert _mod_name_key(C) not in f.deferred_printers
129 assert C in f.type_printers
129 assert C in f.type_printers
130
130
131 def test_for_type_by_name():
131 def test_for_type_by_name():
132 f = PlainTextFormatter()
132 f = PlainTextFormatter()
133
133
134 mod = C.__module__
134 mod = C.__module__
135
135
136 # initial return, None
136 # initial return, None
137 assert f.for_type_by_name(mod, "C", foo_printer) is None
137 assert f.for_type_by_name(mod, "C", foo_printer) is None
138 # no func queries
138 # no func queries
139 assert f.for_type_by_name(mod, "C") is foo_printer
139 assert f.for_type_by_name(mod, "C") is foo_printer
140 # shouldn't change anything
140 # shouldn't change anything
141 assert f.for_type_by_name(mod, "C") is foo_printer
141 assert f.for_type_by_name(mod, "C") is foo_printer
142 # None should do the same
142 # None should do the same
143 assert f.for_type_by_name(mod, "C", None) is foo_printer
143 assert f.for_type_by_name(mod, "C", None) is foo_printer
144 assert f.for_type_by_name(mod, "C", None) is foo_printer
144 assert f.for_type_by_name(mod, "C", None) is foo_printer
145
145
146
146
147 def test_lookup():
147 def test_lookup():
148 f = PlainTextFormatter()
148 f = PlainTextFormatter()
149
149
150 f.for_type(C, foo_printer)
150 f.for_type(C, foo_printer)
151 assert f.lookup(C()) is foo_printer
151 assert f.lookup(C()) is foo_printer
152 with pytest.raises(KeyError):
152 with pytest.raises(KeyError):
153 f.lookup(A())
153 f.lookup(A())
154
154
155 def test_lookup_string():
155 def test_lookup_string():
156 f = PlainTextFormatter()
156 f = PlainTextFormatter()
157 type_str = '%s.%s' % (C.__module__, 'C')
157 type_str = '%s.%s' % (C.__module__, 'C')
158
158
159 f.for_type(type_str, foo_printer)
159 f.for_type(type_str, foo_printer)
160 assert f.lookup(C()) is foo_printer
160 assert f.lookup(C()) is foo_printer
161 # should move from deferred to imported dict
161 # should move from deferred to imported dict
162 assert _mod_name_key(C) not in f.deferred_printers
162 assert _mod_name_key(C) not in f.deferred_printers
163 assert C in f.type_printers
163 assert C in f.type_printers
164
164
165 def test_lookup_by_type():
165 def test_lookup_by_type():
166 f = PlainTextFormatter()
166 f = PlainTextFormatter()
167 f.for_type(C, foo_printer)
167 f.for_type(C, foo_printer)
168 assert f.lookup_by_type(C) is foo_printer
168 assert f.lookup_by_type(C) is foo_printer
169 with pytest.raises(KeyError):
169 with pytest.raises(KeyError):
170 f.lookup_by_type(A)
170 f.lookup_by_type(A)
171
171
172 def test_lookup_by_type_string():
172 def test_lookup_by_type_string():
173 f = PlainTextFormatter()
173 f = PlainTextFormatter()
174 type_str = '%s.%s' % (C.__module__, 'C')
174 type_str = '%s.%s' % (C.__module__, 'C')
175 f.for_type(type_str, foo_printer)
175 f.for_type(type_str, foo_printer)
176
176
177 # verify insertion
177 # verify insertion
178 assert _mod_name_key(C) in f.deferred_printers
178 assert _mod_name_key(C) in f.deferred_printers
179 assert C not in f.type_printers
179 assert C not in f.type_printers
180
180
181 assert f.lookup_by_type(type_str) is foo_printer
181 assert f.lookup_by_type(type_str) is foo_printer
182 # lookup by string doesn't cause import
182 # lookup by string doesn't cause import
183 assert _mod_name_key(C) in f.deferred_printers
183 assert _mod_name_key(C) in f.deferred_printers
184 assert C not in f.type_printers
184 assert C not in f.type_printers
185
185
186 assert f.lookup_by_type(C) is foo_printer
186 assert f.lookup_by_type(C) is foo_printer
187 # should move from deferred to imported dict
187 # should move from deferred to imported dict
188 assert _mod_name_key(C) not in f.deferred_printers
188 assert _mod_name_key(C) not in f.deferred_printers
189 assert C in f.type_printers
189 assert C in f.type_printers
190
190
191 def test_in_formatter():
191 def test_in_formatter():
192 f = PlainTextFormatter()
192 f = PlainTextFormatter()
193 f.for_type(C, foo_printer)
193 f.for_type(C, foo_printer)
194 type_str = '%s.%s' % (C.__module__, 'C')
194 type_str = '%s.%s' % (C.__module__, 'C')
195 assert C in f
195 assert C in f
196 assert type_str in f
196 assert type_str in f
197
197
198 def test_string_in_formatter():
198 def test_string_in_formatter():
199 f = PlainTextFormatter()
199 f = PlainTextFormatter()
200 type_str = '%s.%s' % (C.__module__, 'C')
200 type_str = '%s.%s' % (C.__module__, 'C')
201 f.for_type(type_str, foo_printer)
201 f.for_type(type_str, foo_printer)
202 assert type_str in f
202 assert type_str in f
203 assert C in f
203 assert C in f
204
204
205 def test_pop():
205 def test_pop():
206 f = PlainTextFormatter()
206 f = PlainTextFormatter()
207 f.for_type(C, foo_printer)
207 f.for_type(C, foo_printer)
208 assert f.lookup_by_type(C) is foo_printer
208 assert f.lookup_by_type(C) is foo_printer
209 assert f.pop(C, None) is foo_printer
209 assert f.pop(C, None) is foo_printer
210 f.for_type(C, foo_printer)
210 f.for_type(C, foo_printer)
211 assert f.pop(C) is foo_printer
211 assert f.pop(C) is foo_printer
212 with pytest.raises(KeyError):
212 with pytest.raises(KeyError):
213 f.lookup_by_type(C)
213 f.lookup_by_type(C)
214 with pytest.raises(KeyError):
214 with pytest.raises(KeyError):
215 f.pop(C)
215 f.pop(C)
216 with pytest.raises(KeyError):
216 with pytest.raises(KeyError):
217 f.pop(A)
217 f.pop(A)
218 assert f.pop(A, None) is None
218 assert f.pop(A, None) is None
219
219
220 def test_pop_string():
220 def test_pop_string():
221 f = PlainTextFormatter()
221 f = PlainTextFormatter()
222 type_str = '%s.%s' % (C.__module__, 'C')
222 type_str = '%s.%s' % (C.__module__, 'C')
223
223
224 with pytest.raises(KeyError):
224 with pytest.raises(KeyError):
225 f.pop(type_str)
225 f.pop(type_str)
226
226
227 f.for_type(type_str, foo_printer)
227 f.for_type(type_str, foo_printer)
228 f.pop(type_str)
228 f.pop(type_str)
229 with pytest.raises(KeyError):
229 with pytest.raises(KeyError):
230 f.lookup_by_type(C)
230 f.lookup_by_type(C)
231 with pytest.raises(KeyError):
231 with pytest.raises(KeyError):
232 f.pop(type_str)
232 f.pop(type_str)
233
233
234 f.for_type(C, foo_printer)
234 f.for_type(C, foo_printer)
235 assert f.pop(type_str, None) is foo_printer
235 assert f.pop(type_str, None) is foo_printer
236 with pytest.raises(KeyError):
236 with pytest.raises(KeyError):
237 f.lookup_by_type(C)
237 f.lookup_by_type(C)
238 with pytest.raises(KeyError):
238 with pytest.raises(KeyError):
239 f.pop(type_str)
239 f.pop(type_str)
240 assert f.pop(type_str, None) is None
240 assert f.pop(type_str, None) is None
241
241
242
242
243 def test_error_method():
243 def test_error_method():
244 f = HTMLFormatter()
244 f = HTMLFormatter()
245 class BadHTML(object):
245 class BadHTML(object):
246 def _repr_html_(self):
246 def _repr_html_(self):
247 raise ValueError("Bad HTML")
247 raise ValueError("Bad HTML")
248 bad = BadHTML()
248 bad = BadHTML()
249 with capture_output() as captured:
249 with capture_output() as captured:
250 result = f(bad)
250 result = f(bad)
251 assert result is None
251 assert result is None
252 assert "Traceback" in captured.stdout
252 assert "Traceback" in captured.stdout
253 assert "Bad HTML" in captured.stdout
253 assert "Bad HTML" in captured.stdout
254 assert "_repr_html_" in captured.stdout
254 assert "_repr_html_" in captured.stdout
255
255
256 def test_nowarn_notimplemented():
256 def test_nowarn_notimplemented():
257 f = HTMLFormatter()
257 f = HTMLFormatter()
258 class HTMLNotImplemented(object):
258 class HTMLNotImplemented(object):
259 def _repr_html_(self):
259 def _repr_html_(self):
260 raise NotImplementedError
260 raise NotImplementedError
261 h = HTMLNotImplemented()
261 h = HTMLNotImplemented()
262 with capture_output() as captured:
262 with capture_output() as captured:
263 result = f(h)
263 result = f(h)
264 assert result is None
264 assert result is None
265 assert "" == captured.stderr
265 assert "" == captured.stderr
266 assert "" == captured.stdout
266 assert "" == captured.stdout
267
267
268
268
269 def test_warn_error_for_type():
269 def test_warn_error_for_type():
270 f = HTMLFormatter()
270 f = HTMLFormatter()
271 f.for_type(int, lambda i: name_error)
271 f.for_type(int, lambda i: name_error)
272 with capture_output() as captured:
272 with capture_output() as captured:
273 result = f(5)
273 result = f(5)
274 assert result is None
274 assert result is None
275 assert "Traceback" in captured.stdout
275 assert "Traceback" in captured.stdout
276 assert "NameError" in captured.stdout
276 assert "NameError" in captured.stdout
277 assert "name_error" in captured.stdout
277 assert "name_error" in captured.stdout
278
278
279 def test_error_pretty_method():
279 def test_error_pretty_method():
280 f = PlainTextFormatter()
280 f = PlainTextFormatter()
281 class BadPretty(object):
281 class BadPretty(object):
282 def _repr_pretty_(self):
282 def _repr_pretty_(self):
283 return "hello"
283 return "hello"
284 bad = BadPretty()
284 bad = BadPretty()
285 with capture_output() as captured:
285 with capture_output() as captured:
286 result = f(bad)
286 result = f(bad)
287 assert result is None
287 assert result is None
288 assert "Traceback" in captured.stdout
288 assert "Traceback" in captured.stdout
289 assert "_repr_pretty_" in captured.stdout
289 assert "_repr_pretty_" in captured.stdout
290 assert "given" in captured.stdout
290 assert "given" in captured.stdout
291 assert "argument" in captured.stdout
291 assert "argument" in captured.stdout
292
292
293
293
294 def test_bad_repr_traceback():
294 def test_bad_repr_traceback():
295 f = PlainTextFormatter()
295 f = PlainTextFormatter()
296 bad = BadRepr()
296 bad = BadRepr()
297 with capture_output() as captured:
297 with capture_output() as captured:
298 result = f(bad)
298 result = f(bad)
299 # catches error, returns None
299 # catches error, returns None
300 assert result is None
300 assert result is None
301 assert "Traceback" in captured.stdout
301 assert "Traceback" in captured.stdout
302 assert "__repr__" in captured.stdout
302 assert "__repr__" in captured.stdout
303 assert "ValueError" in captured.stdout
303 assert "ValueError" in captured.stdout
304
304
305
305
306 class MakePDF(object):
306 class MakePDF(object):
307 def _repr_pdf_(self):
307 def _repr_pdf_(self):
308 return 'PDF'
308 return 'PDF'
309
309
310 def test_pdf_formatter():
310 def test_pdf_formatter():
311 pdf = MakePDF()
311 pdf = MakePDF()
312 f = PDFFormatter()
312 f = PDFFormatter()
313 assert f(pdf) == "PDF"
313 assert f(pdf) == "PDF"
314
314
315
315
316 def test_print_method_bound():
316 def test_print_method_bound():
317 f = HTMLFormatter()
317 f = HTMLFormatter()
318 class MyHTML(object):
318 class MyHTML(object):
319 def _repr_html_(self):
319 def _repr_html_(self):
320 return "hello"
320 return "hello"
321 with capture_output() as captured:
321 with capture_output() as captured:
322 result = f(MyHTML)
322 result = f(MyHTML)
323 assert result is None
323 assert result is None
324 assert "FormatterWarning" not in captured.stderr
324 assert "FormatterWarning" not in captured.stderr
325
325
326 with capture_output() as captured:
326 with capture_output() as captured:
327 result = f(MyHTML())
327 result = f(MyHTML())
328 assert result == "hello"
328 assert result == "hello"
329 assert captured.stderr == ""
329 assert captured.stderr == ""
330
330
331
331
332 def test_print_method_weird():
332 def test_print_method_weird():
333
333
334 class TextMagicHat(object):
334 class TextMagicHat(object):
335 def __getattr__(self, key):
335 def __getattr__(self, key):
336 return key
336 return key
337
337
338 f = HTMLFormatter()
338 f = HTMLFormatter()
339
339
340 text_hat = TextMagicHat()
340 text_hat = TextMagicHat()
341 assert text_hat._repr_html_ == "_repr_html_"
341 assert text_hat._repr_html_ == "_repr_html_"
342 with capture_output() as captured:
342 with capture_output() as captured:
343 result = f(text_hat)
343 result = f(text_hat)
344
344
345 assert result is None
345 assert result is None
346 assert "FormatterWarning" not in captured.stderr
346 assert "FormatterWarning" not in captured.stderr
347
347
348 class CallableMagicHat(object):
348 class CallableMagicHat(object):
349 def __getattr__(self, key):
349 def __getattr__(self, key):
350 return lambda : key
350 return lambda : key
351
351
352 call_hat = CallableMagicHat()
352 call_hat = CallableMagicHat()
353 with capture_output() as captured:
353 with capture_output() as captured:
354 result = f(call_hat)
354 result = f(call_hat)
355
355
356 assert result is None
356 assert result is None
357
357
358 class BadReprArgs(object):
358 class BadReprArgs(object):
359 def _repr_html_(self, extra, args):
359 def _repr_html_(self, extra, args):
360 return "html"
360 return "html"
361
361
362 bad = BadReprArgs()
362 bad = BadReprArgs()
363 with capture_output() as captured:
363 with capture_output() as captured:
364 result = f(bad)
364 result = f(bad)
365
365
366 assert result is None
366 assert result is None
367 assert "FormatterWarning" not in captured.stderr
367 assert "FormatterWarning" not in captured.stderr
368
368
369
369
370 def test_format_config():
370 def test_format_config():
371 """config objects don't pretend to support fancy reprs with lazy attrs"""
371 """config objects don't pretend to support fancy reprs with lazy attrs"""
372 f = HTMLFormatter()
372 f = HTMLFormatter()
373 cfg = Config()
373 cfg = Config()
374 with capture_output() as captured:
374 with capture_output() as captured:
375 result = f(cfg)
375 result = f(cfg)
376 assert result is None
376 assert result is None
377 assert captured.stderr == ""
377 assert captured.stderr == ""
378
378
379 with capture_output() as captured:
379 with capture_output() as captured:
380 result = f(Config)
380 result = f(Config)
381 assert result is None
381 assert result is None
382 assert captured.stderr == ""
382 assert captured.stderr == ""
383
383
384
384
385 def test_pretty_max_seq_length():
385 def test_pretty_max_seq_length():
386 f = PlainTextFormatter(max_seq_length=1)
386 f = PlainTextFormatter(max_seq_length=1)
387 lis = list(range(3))
387 lis = list(range(3))
388 text = f(lis)
388 text = f(lis)
389 assert text == "[0, ...]"
389 assert text == "[0, ...]"
390 f.max_seq_length = 0
390 f.max_seq_length = 0
391 text = f(lis)
391 text = f(lis)
392 assert text == "[0, 1, 2]"
392 assert text == "[0, 1, 2]"
393 text = f(list(range(1024)))
393 text = f(list(range(1024)))
394 lines = text.splitlines()
394 lines = text.splitlines()
395 assert len(lines) == 1024
395 assert len(lines) == 1024
396
396
397
397
398 def test_ipython_display_formatter():
398 def test_ipython_display_formatter():
399 """Objects with _ipython_display_ defined bypass other formatters"""
399 """Objects with _ipython_display_ defined bypass other formatters"""
400 f = get_ipython().display_formatter
400 f = get_ipython().display_formatter
401 catcher = []
401 catcher = []
402 class SelfDisplaying(object):
402 class SelfDisplaying(object):
403 def _ipython_display_(self):
403 def _ipython_display_(self):
404 catcher.append(self)
404 catcher.append(self)
405
405
406 class NotSelfDisplaying(object):
406 class NotSelfDisplaying(object):
407 def __repr__(self):
407 def __repr__(self):
408 return "NotSelfDisplaying"
408 return "NotSelfDisplaying"
409
409
410 def _ipython_display_(self):
410 def _ipython_display_(self):
411 raise NotImplementedError
411 raise NotImplementedError
412
412
413 save_enabled = f.ipython_display_formatter.enabled
413 save_enabled = f.ipython_display_formatter.enabled
414 f.ipython_display_formatter.enabled = True
414 f.ipython_display_formatter.enabled = True
415
415
416 yes = SelfDisplaying()
416 yes = SelfDisplaying()
417 no = NotSelfDisplaying()
417 no = NotSelfDisplaying()
418
418
419 d, md = f.format(no)
419 d, md = f.format(no)
420 assert d == {"text/plain": repr(no)}
420 assert d == {"text/plain": repr(no)}
421 assert md == {}
421 assert md == {}
422 assert catcher == []
422 assert catcher == []
423
423
424 d, md = f.format(yes)
424 d, md = f.format(yes)
425 assert d == {}
425 assert d == {}
426 assert md == {}
426 assert md == {}
427 assert catcher == [yes]
427 assert catcher == [yes]
428
428
429 f.ipython_display_formatter.enabled = save_enabled
429 f.ipython_display_formatter.enabled = save_enabled
430
430
431
431
432 def test_repr_mime():
432 def test_repr_mime():
433 class HasReprMime(object):
433 class HasReprMime(object):
434 def _repr_mimebundle_(self, include=None, exclude=None):
434 def _repr_mimebundle_(self, include=None, exclude=None):
435 return {
435 return {
436 'application/json+test.v2': {
436 'application/json+test.v2': {
437 'x': 'y'
437 'x': 'y'
438 },
438 },
439 'plain/text' : '<HasReprMime>',
439 'plain/text' : '<HasReprMime>',
440 'image/png' : 'i-overwrite'
440 'image/png' : 'i-overwrite'
441 }
441 }
442
442
443 def _repr_png_(self):
443 def _repr_png_(self):
444 return 'should-be-overwritten'
444 return 'should-be-overwritten'
445 def _repr_html_(self):
445 def _repr_html_(self):
446 return '<b>hi!</b>'
446 return '<b>hi!</b>'
447
447
448 f = get_ipython().display_formatter
448 f = get_ipython().display_formatter
449 html_f = f.formatters['text/html']
449 html_f = f.formatters['text/html']
450 save_enabled = html_f.enabled
450 save_enabled = html_f.enabled
451 html_f.enabled = True
451 html_f.enabled = True
452 obj = HasReprMime()
452 obj = HasReprMime()
453 d, md = f.format(obj)
453 d, md = f.format(obj)
454 html_f.enabled = save_enabled
454 html_f.enabled = save_enabled
455
455
456 assert sorted(d) == [
456 assert sorted(d) == [
457 "application/json+test.v2",
457 "application/json+test.v2",
458 "image/png",
458 "image/png",
459 "plain/text",
459 "plain/text",
460 "text/html",
460 "text/html",
461 "text/plain",
461 "text/plain",
462 ]
462 ]
463 assert md == {}
463 assert md == {}
464
464
465 d, md = f.format(obj, include={"image/png"})
465 d, md = f.format(obj, include={"image/png"})
466 assert list(d.keys()) == [
466 assert list(d.keys()) == [
467 "image/png"
467 "image/png"
468 ], "Include should filter out even things from repr_mimebundle"
468 ], "Include should filter out even things from repr_mimebundle"
469
469
470 assert d["image/png"] == "i-overwrite", "_repr_mimebundle_ take precedence"
470 assert d["image/png"] == "i-overwrite", "_repr_mimebundle_ take precedence"
471
471
472
472
473 def test_pass_correct_include_exclude():
473 def test_pass_correct_include_exclude():
474 class Tester(object):
474 class Tester(object):
475
475
476 def __init__(self, include=None, exclude=None):
476 def __init__(self, include=None, exclude=None):
477 self.include = include
477 self.include = include
478 self.exclude = exclude
478 self.exclude = exclude
479
479
480 def _repr_mimebundle_(self, include, exclude, **kwargs):
480 def _repr_mimebundle_(self, include, exclude, **kwargs):
481 if include and (include != self.include):
481 if include and (include != self.include):
482 raise ValueError('include got modified: display() may be broken.')
482 raise ValueError('include got modified: display() may be broken.')
483 if exclude and (exclude != self.exclude):
483 if exclude and (exclude != self.exclude):
484 raise ValueError('exclude got modified: display() may be broken.')
484 raise ValueError('exclude got modified: display() may be broken.')
485
485
486 return None
486 return None
487
487
488 include = {'a', 'b', 'c'}
488 include = {'a', 'b', 'c'}
489 exclude = {'c', 'e' , 'f'}
489 exclude = {'c', 'e' , 'f'}
490
490
491 f = get_ipython().display_formatter
491 f = get_ipython().display_formatter
492 f.format(Tester(include=include, exclude=exclude), include=include, exclude=exclude)
492 f.format(Tester(include=include, exclude=exclude), include=include, exclude=exclude)
493 f.format(Tester(exclude=exclude), exclude=exclude)
493 f.format(Tester(exclude=exclude), exclude=exclude)
494 f.format(Tester(include=include), include=include)
494 f.format(Tester(include=include), include=include)
495
495
496
496
497 def test_repr_mime_meta():
497 def test_repr_mime_meta():
498 class HasReprMimeMeta(object):
498 class HasReprMimeMeta(object):
499 def _repr_mimebundle_(self, include=None, exclude=None):
499 def _repr_mimebundle_(self, include=None, exclude=None):
500 data = {
500 data = {
501 'image/png': 'base64-image-data',
501 'image/png': 'base64-image-data',
502 }
502 }
503 metadata = {
503 metadata = {
504 'image/png': {
504 'image/png': {
505 'width': 5,
505 'width': 5,
506 'height': 10,
506 'height': 10,
507 }
507 }
508 }
508 }
509 return (data, metadata)
509 return (data, metadata)
510
510
511 f = get_ipython().display_formatter
511 f = get_ipython().display_formatter
512 obj = HasReprMimeMeta()
512 obj = HasReprMimeMeta()
513 d, md = f.format(obj)
513 d, md = f.format(obj)
514 assert sorted(d) == ["image/png", "text/plain"]
514 assert sorted(d) == ["image/png", "text/plain"]
515 assert md == {
515 assert md == {
516 "image/png": {
516 "image/png": {
517 "width": 5,
517 "width": 5,
518 "height": 10,
518 "height": 10,
519 }
519 }
520 }
520 }
521
521
522
522
523 def test_repr_mime_failure():
523 def test_repr_mime_failure():
524 class BadReprMime(object):
524 class BadReprMime(object):
525 def _repr_mimebundle_(self, include=None, exclude=None):
525 def _repr_mimebundle_(self, include=None, exclude=None):
526 raise RuntimeError
526 raise RuntimeError
527
527
528 f = get_ipython().display_formatter
528 f = get_ipython().display_formatter
529 obj = BadReprMime()
529 obj = BadReprMime()
530 d, md = f.format(obj)
530 d, md = f.format(obj)
531 assert "text/plain" in d
531 assert "text/plain" in d
532
532
533
533
534 def test_custom_repr_namedtuple_partialmethod():
534 def test_custom_repr_namedtuple_partialmethod():
535 from functools import partialmethod
535 from functools import partialmethod
536 from typing import NamedTuple
536 from typing import NamedTuple
537
537
538 class Foo(NamedTuple):
538 class Foo(NamedTuple):
539 ...
539 ...
540
540
541 Foo.__repr__ = partialmethod(lambda obj: "Hello World")
541 Foo.__repr__ = partialmethod(lambda obj: "Hello World")
542 foo = Foo()
542 foo = Foo()
543
543
544 f = PlainTextFormatter()
544 f = PlainTextFormatter()
545 assert f.pprint
545 assert f.pprint
546 assert f(foo) == "Hello World"
546 assert f(foo) == "Hello World"
@@ -1,954 +1,954 b''
1 """
1 """
2 Python advanced pretty printer. This pretty printer is intended to
2 Python advanced pretty printer. This pretty printer is intended to
3 replace the old `pprint` python module which does not allow developers
3 replace the old `pprint` python module which does not allow developers
4 to provide their own pretty print callbacks.
4 to provide their own pretty print callbacks.
5
5
6 This module is based on ruby's `prettyprint.rb` library by `Tanaka Akira`.
6 This module is based on ruby's `prettyprint.rb` library by `Tanaka Akira`.
7
7
8
8
9 Example Usage
9 Example Usage
10 -------------
10 -------------
11
11
12 To directly print the representation of an object use `pprint`::
12 To directly print the representation of an object use `pprint`::
13
13
14 from pretty import pprint
14 from pretty import pprint
15 pprint(complex_object)
15 pprint(complex_object)
16
16
17 To get a string of the output use `pretty`::
17 To get a string of the output use `pretty`::
18
18
19 from pretty import pretty
19 from pretty import pretty
20 string = pretty(complex_object)
20 string = pretty(complex_object)
21
21
22
22
23 Extending
23 Extending
24 ---------
24 ---------
25
25
26 The pretty library allows developers to add pretty printing rules for their
26 The pretty library allows developers to add pretty printing rules for their
27 own objects. This process is straightforward. All you have to do is to
27 own objects. This process is straightforward. All you have to do is to
28 add a `_repr_pretty_` method to your object and call the methods on the
28 add a `_repr_pretty_` method to your object and call the methods on the
29 pretty printer passed::
29 pretty printer passed::
30
30
31 class MyObject(object):
31 class MyObject(object):
32
32
33 def _repr_pretty_(self, p, cycle):
33 def _repr_pretty_(self, p, cycle):
34 ...
34 ...
35
35
36 Here's an example for a class with a simple constructor::
36 Here's an example for a class with a simple constructor::
37
37
38 class MySimpleObject:
38 class MySimpleObject:
39
39
40 def __init__(self, a, b, *, c=None):
40 def __init__(self, a, b, *, c=None):
41 self.a = a
41 self.a = a
42 self.b = b
42 self.b = b
43 self.c = c
43 self.c = c
44
44
45 def _repr_pretty_(self, p, cycle):
45 def _repr_pretty_(self, p, cycle):
46 ctor = CallExpression.factory(self.__class__.__name__)
46 ctor = CallExpression.factory(self.__class__.__name__)
47 if self.c is None:
47 if self.c is None:
48 p.pretty(ctor(a, b))
48 p.pretty(ctor(a, b))
49 else:
49 else:
50 p.pretty(ctor(a, b, c=c))
50 p.pretty(ctor(a, b, c=c))
51
51
52 Here is an example implementation of a `_repr_pretty_` method for a list
52 Here is an example implementation of a `_repr_pretty_` method for a list
53 subclass::
53 subclass::
54
54
55 class MyList(list):
55 class MyList(list):
56
56
57 def _repr_pretty_(self, p, cycle):
57 def _repr_pretty_(self, p, cycle):
58 if cycle:
58 if cycle:
59 p.text('MyList(...)')
59 p.text('MyList(...)')
60 else:
60 else:
61 with p.group(8, 'MyList([', '])'):
61 with p.group(8, 'MyList([', '])'):
62 for idx, item in enumerate(self):
62 for idx, item in enumerate(self):
63 if idx:
63 if idx:
64 p.text(',')
64 p.text(',')
65 p.breakable()
65 p.breakable()
66 p.pretty(item)
66 p.pretty(item)
67
67
68 The `cycle` parameter is `True` if pretty detected a cycle. You *have* to
68 The `cycle` parameter is `True` if pretty detected a cycle. You *have* to
69 react to that or the result is an infinite loop. `p.text()` just adds
69 react to that or the result is an infinite loop. `p.text()` just adds
70 non breaking text to the output, `p.breakable()` either adds a whitespace
70 non breaking text to the output, `p.breakable()` either adds a whitespace
71 or breaks here. If you pass it an argument it's used instead of the
71 or breaks here. If you pass it an argument it's used instead of the
72 default space. `p.pretty` prettyprints another object using the pretty print
72 default space. `p.pretty` prettyprints another object using the pretty print
73 method.
73 method.
74
74
75 The first parameter to the `group` function specifies the extra indentation
75 The first parameter to the `group` function specifies the extra indentation
76 of the next line. In this example the next item will either be on the same
76 of the next line. In this example the next item will either be on the same
77 line (if the items are short enough) or aligned with the right edge of the
77 line (if the items are short enough) or aligned with the right edge of the
78 opening bracket of `MyList`.
78 opening bracket of `MyList`.
79
79
80 If you just want to indent something you can use the group function
80 If you just want to indent something you can use the group function
81 without open / close parameters. You can also use this code::
81 without open / close parameters. You can also use this code::
82
82
83 with p.indent(2):
83 with p.indent(2):
84 ...
84 ...
85
85
86 Inheritance diagram:
86 Inheritance diagram:
87
87
88 .. inheritance-diagram:: IPython.lib.pretty
88 .. inheritance-diagram:: IPython.lib.pretty
89 :parts: 3
89 :parts: 3
90
90
91 :copyright: 2007 by Armin Ronacher.
91 :copyright: 2007 by Armin Ronacher.
92 Portions (c) 2009 by Robert Kern.
92 Portions (c) 2009 by Robert Kern.
93 :license: BSD License.
93 :license: BSD License.
94 """
94 """
95
95
96 from contextlib import contextmanager
96 from contextlib import contextmanager
97 import datetime
97 import datetime
98 import os
98 import os
99 import re
99 import re
100 import sys
100 import sys
101 import types
101 import types
102 from collections import deque
102 from collections import deque
103 from inspect import signature
103 from inspect import signature
104 from io import StringIO
104 from io import StringIO
105 from warnings import warn
105 from warnings import warn
106
106
107 from IPython.utils.decorators import undoc
107 from IPython.utils.decorators import undoc
108 from IPython.utils.py3compat import PYPY
108 from IPython.utils.py3compat import PYPY
109
109
110 from typing import Dict
110 from typing import Dict
111
111
112 __all__ = ['pretty', 'pprint', 'PrettyPrinter', 'RepresentationPrinter',
112 __all__ = ['pretty', 'pprint', 'PrettyPrinter', 'RepresentationPrinter',
113 'for_type', 'for_type_by_name', 'RawText', 'RawStringLiteral', 'CallExpression']
113 'for_type', 'for_type_by_name', 'RawText', 'RawStringLiteral', 'CallExpression']
114
114
115
115
116 MAX_SEQ_LENGTH = 1000
116 MAX_SEQ_LENGTH = 1000
117 _re_pattern_type = type(re.compile(''))
117 _re_pattern_type = type(re.compile(''))
118
118
119 def _safe_getattr(obj, attr, default=None):
119 def _safe_getattr(obj, attr, default=None):
120 """Safe version of getattr.
120 """Safe version of getattr.
121
121
122 Same as getattr, but will return ``default`` on any Exception,
122 Same as getattr, but will return ``default`` on any Exception,
123 rather than raising.
123 rather than raising.
124 """
124 """
125 try:
125 try:
126 return getattr(obj, attr, default)
126 return getattr(obj, attr, default)
127 except Exception:
127 except Exception:
128 return default
128 return default
129
129
130 @undoc
130 @undoc
131 class CUnicodeIO(StringIO):
131 class CUnicodeIO(StringIO):
132 def __init__(self, *args, **kwargs):
132 def __init__(self, *args, **kwargs):
133 super().__init__(*args, **kwargs)
133 super().__init__(*args, **kwargs)
134 warn(("CUnicodeIO is deprecated since IPython 6.0. "
134 warn(("CUnicodeIO is deprecated since IPython 6.0. "
135 "Please use io.StringIO instead."),
135 "Please use io.StringIO instead."),
136 DeprecationWarning, stacklevel=2)
136 DeprecationWarning, stacklevel=2)
137
137
138 def _sorted_for_pprint(items):
138 def _sorted_for_pprint(items):
139 """
139 """
140 Sort the given items for pretty printing. Since some predictable
140 Sort the given items for pretty printing. Since some predictable
141 sorting is better than no sorting at all, we sort on the string
141 sorting is better than no sorting at all, we sort on the string
142 representation if normal sorting fails.
142 representation if normal sorting fails.
143 """
143 """
144 items = list(items)
144 items = list(items)
145 try:
145 try:
146 return sorted(items)
146 return sorted(items)
147 except Exception:
147 except Exception:
148 try:
148 try:
149 return sorted(items, key=str)
149 return sorted(items, key=str)
150 except Exception:
150 except Exception:
151 return items
151 return items
152
152
153 def pretty(obj, verbose=False, max_width=79, newline='\n', max_seq_length=MAX_SEQ_LENGTH):
153 def pretty(obj, verbose=False, max_width=79, newline='\n', max_seq_length=MAX_SEQ_LENGTH):
154 """
154 """
155 Pretty print the object's representation.
155 Pretty print the object's representation.
156 """
156 """
157 stream = StringIO()
157 stream = StringIO()
158 printer = RepresentationPrinter(stream, verbose, max_width, newline, max_seq_length=max_seq_length)
158 printer = RepresentationPrinter(stream, verbose, max_width, newline, max_seq_length=max_seq_length)
159 printer.pretty(obj)
159 printer.pretty(obj)
160 printer.flush()
160 printer.flush()
161 return stream.getvalue()
161 return stream.getvalue()
162
162
163
163
164 def pprint(obj, verbose=False, max_width=79, newline='\n', max_seq_length=MAX_SEQ_LENGTH):
164 def pprint(obj, verbose=False, max_width=79, newline='\n', max_seq_length=MAX_SEQ_LENGTH):
165 """
165 """
166 Like `pretty` but print to stdout.
166 Like `pretty` but print to stdout.
167 """
167 """
168 printer = RepresentationPrinter(sys.stdout, verbose, max_width, newline, max_seq_length=max_seq_length)
168 printer = RepresentationPrinter(sys.stdout, verbose, max_width, newline, max_seq_length=max_seq_length)
169 printer.pretty(obj)
169 printer.pretty(obj)
170 printer.flush()
170 printer.flush()
171 sys.stdout.write(newline)
171 sys.stdout.write(newline)
172 sys.stdout.flush()
172 sys.stdout.flush()
173
173
174 class _PrettyPrinterBase(object):
174 class _PrettyPrinterBase(object):
175
175
176 @contextmanager
176 @contextmanager
177 def indent(self, indent):
177 def indent(self, indent):
178 """with statement support for indenting/dedenting."""
178 """with statement support for indenting/dedenting."""
179 self.indentation += indent
179 self.indentation += indent
180 try:
180 try:
181 yield
181 yield
182 finally:
182 finally:
183 self.indentation -= indent
183 self.indentation -= indent
184
184
185 @contextmanager
185 @contextmanager
186 def group(self, indent=0, open='', close=''):
186 def group(self, indent=0, open='', close=''):
187 """like begin_group / end_group but for the with statement."""
187 """like begin_group / end_group but for the with statement."""
188 self.begin_group(indent, open)
188 self.begin_group(indent, open)
189 try:
189 try:
190 yield
190 yield
191 finally:
191 finally:
192 self.end_group(indent, close)
192 self.end_group(indent, close)
193
193
194 class PrettyPrinter(_PrettyPrinterBase):
194 class PrettyPrinter(_PrettyPrinterBase):
195 """
195 """
196 Baseclass for the `RepresentationPrinter` prettyprinter that is used to
196 Baseclass for the `RepresentationPrinter` prettyprinter that is used to
197 generate pretty reprs of objects. Contrary to the `RepresentationPrinter`
197 generate pretty reprs of objects. Contrary to the `RepresentationPrinter`
198 this printer knows nothing about the default pprinters or the `_repr_pretty_`
198 this printer knows nothing about the default pprinters or the `_repr_pretty_`
199 callback method.
199 callback method.
200 """
200 """
201
201
202 def __init__(self, output, max_width=79, newline='\n', max_seq_length=MAX_SEQ_LENGTH):
202 def __init__(self, output, max_width=79, newline='\n', max_seq_length=MAX_SEQ_LENGTH):
203 self.output = output
203 self.output = output
204 self.max_width = max_width
204 self.max_width = max_width
205 self.newline = newline
205 self.newline = newline
206 self.max_seq_length = max_seq_length
206 self.max_seq_length = max_seq_length
207 self.output_width = 0
207 self.output_width = 0
208 self.buffer_width = 0
208 self.buffer_width = 0
209 self.buffer = deque()
209 self.buffer = deque()
210
210
211 root_group = Group(0)
211 root_group = Group(0)
212 self.group_stack = [root_group]
212 self.group_stack = [root_group]
213 self.group_queue = GroupQueue(root_group)
213 self.group_queue = GroupQueue(root_group)
214 self.indentation = 0
214 self.indentation = 0
215
215
216 def _break_one_group(self, group):
216 def _break_one_group(self, group):
217 while group.breakables:
217 while group.breakables:
218 x = self.buffer.popleft()
218 x = self.buffer.popleft()
219 self.output_width = x.output(self.output, self.output_width)
219 self.output_width = x.output(self.output, self.output_width)
220 self.buffer_width -= x.width
220 self.buffer_width -= x.width
221 while self.buffer and isinstance(self.buffer[0], Text):
221 while self.buffer and isinstance(self.buffer[0], Text):
222 x = self.buffer.popleft()
222 x = self.buffer.popleft()
223 self.output_width = x.output(self.output, self.output_width)
223 self.output_width = x.output(self.output, self.output_width)
224 self.buffer_width -= x.width
224 self.buffer_width -= x.width
225
225
226 def _break_outer_groups(self):
226 def _break_outer_groups(self):
227 while self.max_width < self.output_width + self.buffer_width:
227 while self.max_width < self.output_width + self.buffer_width:
228 group = self.group_queue.deq()
228 group = self.group_queue.deq()
229 if not group:
229 if not group:
230 return
230 return
231 self._break_one_group(group)
231 self._break_one_group(group)
232
232
233 def text(self, obj):
233 def text(self, obj):
234 """Add literal text to the output."""
234 """Add literal text to the output."""
235 width = len(obj)
235 width = len(obj)
236 if self.buffer:
236 if self.buffer:
237 text = self.buffer[-1]
237 text = self.buffer[-1]
238 if not isinstance(text, Text):
238 if not isinstance(text, Text):
239 text = Text()
239 text = Text()
240 self.buffer.append(text)
240 self.buffer.append(text)
241 text.add(obj, width)
241 text.add(obj, width)
242 self.buffer_width += width
242 self.buffer_width += width
243 self._break_outer_groups()
243 self._break_outer_groups()
244 else:
244 else:
245 self.output.write(obj)
245 self.output.write(obj)
246 self.output_width += width
246 self.output_width += width
247
247
248 def breakable(self, sep=' '):
248 def breakable(self, sep=' '):
249 """
249 """
250 Add a breakable separator to the output. This does not mean that it
250 Add a breakable separator to the output. This does not mean that it
251 will automatically break here. If no breaking on this position takes
251 will automatically break here. If no breaking on this position takes
252 place the `sep` is inserted which default to one space.
252 place the `sep` is inserted which default to one space.
253 """
253 """
254 width = len(sep)
254 width = len(sep)
255 group = self.group_stack[-1]
255 group = self.group_stack[-1]
256 if group.want_break:
256 if group.want_break:
257 self.flush()
257 self.flush()
258 self.output.write(self.newline)
258 self.output.write(self.newline)
259 self.output.write(' ' * self.indentation)
259 self.output.write(' ' * self.indentation)
260 self.output_width = self.indentation
260 self.output_width = self.indentation
261 self.buffer_width = 0
261 self.buffer_width = 0
262 else:
262 else:
263 self.buffer.append(Breakable(sep, width, self))
263 self.buffer.append(Breakable(sep, width, self))
264 self.buffer_width += width
264 self.buffer_width += width
265 self._break_outer_groups()
265 self._break_outer_groups()
266
266
267 def break_(self):
267 def break_(self):
268 """
268 """
269 Explicitly insert a newline into the output, maintaining correct indentation.
269 Explicitly insert a newline into the output, maintaining correct indentation.
270 """
270 """
271 group = self.group_queue.deq()
271 group = self.group_queue.deq()
272 if group:
272 if group:
273 self._break_one_group(group)
273 self._break_one_group(group)
274 self.flush()
274 self.flush()
275 self.output.write(self.newline)
275 self.output.write(self.newline)
276 self.output.write(' ' * self.indentation)
276 self.output.write(' ' * self.indentation)
277 self.output_width = self.indentation
277 self.output_width = self.indentation
278 self.buffer_width = 0
278 self.buffer_width = 0
279
279
280
280
281 def begin_group(self, indent=0, open=''):
281 def begin_group(self, indent=0, open=''):
282 """
282 """
283 Begin a group.
283 Begin a group.
284 The first parameter specifies the indentation for the next line (usually
284 The first parameter specifies the indentation for the next line (usually
285 the width of the opening text), the second the opening text. All
285 the width of the opening text), the second the opening text. All
286 parameters are optional.
286 parameters are optional.
287 """
287 """
288 if open:
288 if open:
289 self.text(open)
289 self.text(open)
290 group = Group(self.group_stack[-1].depth + 1)
290 group = Group(self.group_stack[-1].depth + 1)
291 self.group_stack.append(group)
291 self.group_stack.append(group)
292 self.group_queue.enq(group)
292 self.group_queue.enq(group)
293 self.indentation += indent
293 self.indentation += indent
294
294
295 def _enumerate(self, seq):
295 def _enumerate(self, seq):
296 """like enumerate, but with an upper limit on the number of items"""
296 """like enumerate, but with an upper limit on the number of items"""
297 for idx, x in enumerate(seq):
297 for idx, x in enumerate(seq):
298 if self.max_seq_length and idx >= self.max_seq_length:
298 if self.max_seq_length and idx >= self.max_seq_length:
299 self.text(',')
299 self.text(',')
300 self.breakable()
300 self.breakable()
301 self.text('...')
301 self.text('...')
302 return
302 return
303 yield idx, x
303 yield idx, x
304
304
305 def end_group(self, dedent=0, close=''):
305 def end_group(self, dedent=0, close=''):
306 """End a group. See `begin_group` for more details."""
306 """End a group. See `begin_group` for more details."""
307 self.indentation -= dedent
307 self.indentation -= dedent
308 group = self.group_stack.pop()
308 group = self.group_stack.pop()
309 if not group.breakables:
309 if not group.breakables:
310 self.group_queue.remove(group)
310 self.group_queue.remove(group)
311 if close:
311 if close:
312 self.text(close)
312 self.text(close)
313
313
314 def flush(self):
314 def flush(self):
315 """Flush data that is left in the buffer."""
315 """Flush data that is left in the buffer."""
316 for data in self.buffer:
316 for data in self.buffer:
317 self.output_width += data.output(self.output, self.output_width)
317 self.output_width += data.output(self.output, self.output_width)
318 self.buffer.clear()
318 self.buffer.clear()
319 self.buffer_width = 0
319 self.buffer_width = 0
320
320
321
321
322 def _get_mro(obj_class):
322 def _get_mro(obj_class):
323 """ Get a reasonable method resolution order of a class and its superclasses
323 """ Get a reasonable method resolution order of a class and its superclasses
324 for both old-style and new-style classes.
324 for both old-style and new-style classes.
325 """
325 """
326 if not hasattr(obj_class, '__mro__'):
326 if not hasattr(obj_class, '__mro__'):
327 # Old-style class. Mix in object to make a fake new-style class.
327 # Old-style class. Mix in object to make a fake new-style class.
328 try:
328 try:
329 obj_class = type(obj_class.__name__, (obj_class, object), {})
329 obj_class = type(obj_class.__name__, (obj_class, object), {})
330 except TypeError:
330 except TypeError:
331 # Old-style extension type that does not descend from object.
331 # Old-style extension type that does not descend from object.
332 # FIXME: try to construct a more thorough MRO.
332 # FIXME: try to construct a more thorough MRO.
333 mro = [obj_class]
333 mro = [obj_class]
334 else:
334 else:
335 mro = obj_class.__mro__[1:-1]
335 mro = obj_class.__mro__[1:-1]
336 else:
336 else:
337 mro = obj_class.__mro__
337 mro = obj_class.__mro__
338 return mro
338 return mro
339
339
340
340
341 class RepresentationPrinter(PrettyPrinter):
341 class RepresentationPrinter(PrettyPrinter):
342 """
342 """
343 Special pretty printer that has a `pretty` method that calls the pretty
343 Special pretty printer that has a `pretty` method that calls the pretty
344 printer for a python object.
344 printer for a python object.
345
345
346 This class stores processing data on `self` so you must *never* use
346 This class stores processing data on `self` so you must *never* use
347 this class in a threaded environment. Always lock it or reinstanciate
347 this class in a threaded environment. Always lock it or reinstanciate
348 it.
348 it.
349
349
350 Instances also have a verbose flag callbacks can access to control their
350 Instances also have a verbose flag callbacks can access to control their
351 output. For example the default instance repr prints all attributes and
351 output. For example the default instance repr prints all attributes and
352 methods that are not prefixed by an underscore if the printer is in
352 methods that are not prefixed by an underscore if the printer is in
353 verbose mode.
353 verbose mode.
354 """
354 """
355
355
356 def __init__(self, output, verbose=False, max_width=79, newline='\n',
356 def __init__(self, output, verbose=False, max_width=79, newline='\n',
357 singleton_pprinters=None, type_pprinters=None, deferred_pprinters=None,
357 singleton_pprinters=None, type_pprinters=None, deferred_pprinters=None,
358 max_seq_length=MAX_SEQ_LENGTH):
358 max_seq_length=MAX_SEQ_LENGTH):
359
359
360 PrettyPrinter.__init__(self, output, max_width, newline, max_seq_length=max_seq_length)
360 PrettyPrinter.__init__(self, output, max_width, newline, max_seq_length=max_seq_length)
361 self.verbose = verbose
361 self.verbose = verbose
362 self.stack = []
362 self.stack = []
363 if singleton_pprinters is None:
363 if singleton_pprinters is None:
364 singleton_pprinters = _singleton_pprinters.copy()
364 singleton_pprinters = _singleton_pprinters.copy()
365 self.singleton_pprinters = singleton_pprinters
365 self.singleton_pprinters = singleton_pprinters
366 if type_pprinters is None:
366 if type_pprinters is None:
367 type_pprinters = _type_pprinters.copy()
367 type_pprinters = _type_pprinters.copy()
368 self.type_pprinters = type_pprinters
368 self.type_pprinters = type_pprinters
369 if deferred_pprinters is None:
369 if deferred_pprinters is None:
370 deferred_pprinters = _deferred_type_pprinters.copy()
370 deferred_pprinters = _deferred_type_pprinters.copy()
371 self.deferred_pprinters = deferred_pprinters
371 self.deferred_pprinters = deferred_pprinters
372
372
373 def pretty(self, obj):
373 def pretty(self, obj):
374 """Pretty print the given object."""
374 """Pretty print the given object."""
375 obj_id = id(obj)
375 obj_id = id(obj)
376 cycle = obj_id in self.stack
376 cycle = obj_id in self.stack
377 self.stack.append(obj_id)
377 self.stack.append(obj_id)
378 self.begin_group()
378 self.begin_group()
379 try:
379 try:
380 obj_class = _safe_getattr(obj, '__class__', None) or type(obj)
380 obj_class = _safe_getattr(obj, '__class__', None) or type(obj)
381 # First try to find registered singleton printers for the type.
381 # First try to find registered singleton printers for the type.
382 try:
382 try:
383 printer = self.singleton_pprinters[obj_id]
383 printer = self.singleton_pprinters[obj_id]
384 except (TypeError, KeyError):
384 except (TypeError, KeyError):
385 pass
385 pass
386 else:
386 else:
387 return printer(obj, self, cycle)
387 return printer(obj, self, cycle)
388 # Next walk the mro and check for either:
388 # Next walk the mro and check for either:
389 # 1) a registered printer
389 # 1) a registered printer
390 # 2) a _repr_pretty_ method
390 # 2) a _repr_pretty_ method
391 for cls in _get_mro(obj_class):
391 for cls in _get_mro(obj_class):
392 if cls in self.type_pprinters:
392 if cls in self.type_pprinters:
393 # printer registered in self.type_pprinters
393 # printer registered in self.type_pprinters
394 return self.type_pprinters[cls](obj, self, cycle)
394 return self.type_pprinters[cls](obj, self, cycle)
395 else:
395 else:
396 # deferred printer
396 # deferred printer
397 printer = self._in_deferred_types(cls)
397 printer = self._in_deferred_types(cls)
398 if printer is not None:
398 if printer is not None:
399 return printer(obj, self, cycle)
399 return printer(obj, self, cycle)
400 else:
400 else:
401 # Finally look for special method names.
401 # Finally look for special method names.
402 # Some objects automatically create any requested
402 # Some objects automatically create any requested
403 # attribute. Try to ignore most of them by checking for
403 # attribute. Try to ignore most of them by checking for
404 # callability.
404 # callability.
405 if '_repr_pretty_' in cls.__dict__:
405 if '_repr_pretty_' in cls.__dict__:
406 meth = cls._repr_pretty_
406 meth = cls._repr_pretty_
407 if callable(meth):
407 if callable(meth):
408 return meth(obj, self, cycle)
408 return meth(obj, self, cycle)
409 if (
409 if (
410 cls is not object
410 cls is not object
411 # check if cls defines __repr__
411 # check if cls defines __repr__
412 and "__repr__" in cls.__dict__
412 and "__repr__" in cls.__dict__
413 # check if __repr__ is callable.
413 # check if __repr__ is callable.
414 # Note: we need to test getattr(cls, '__repr__')
414 # Note: we need to test getattr(cls, '__repr__')
415 # instead of cls.__dict__['__repr__']
415 # instead of cls.__dict__['__repr__']
416 # in order to work with descriptors like partialmethod,
416 # in order to work with descriptors like partialmethod,
417 and callable(getattr(cls, '__repr__', None))
417 and callable(getattr(cls, "__repr__", None))
418 ):
418 ):
419 return _repr_pprint(obj, self, cycle)
419 return _repr_pprint(obj, self, cycle)
420
420
421 return _default_pprint(obj, self, cycle)
421 return _default_pprint(obj, self, cycle)
422 finally:
422 finally:
423 self.end_group()
423 self.end_group()
424 self.stack.pop()
424 self.stack.pop()
425
425
426 def _in_deferred_types(self, cls):
426 def _in_deferred_types(self, cls):
427 """
427 """
428 Check if the given class is specified in the deferred type registry.
428 Check if the given class is specified in the deferred type registry.
429
429
430 Returns the printer from the registry if it exists, and None if the
430 Returns the printer from the registry if it exists, and None if the
431 class is not in the registry. Successful matches will be moved to the
431 class is not in the registry. Successful matches will be moved to the
432 regular type registry for future use.
432 regular type registry for future use.
433 """
433 """
434 mod = _safe_getattr(cls, '__module__', None)
434 mod = _safe_getattr(cls, '__module__', None)
435 name = _safe_getattr(cls, '__name__', None)
435 name = _safe_getattr(cls, '__name__', None)
436 key = (mod, name)
436 key = (mod, name)
437 printer = None
437 printer = None
438 if key in self.deferred_pprinters:
438 if key in self.deferred_pprinters:
439 # Move the printer over to the regular registry.
439 # Move the printer over to the regular registry.
440 printer = self.deferred_pprinters.pop(key)
440 printer = self.deferred_pprinters.pop(key)
441 self.type_pprinters[cls] = printer
441 self.type_pprinters[cls] = printer
442 return printer
442 return printer
443
443
444
444
445 class Printable(object):
445 class Printable(object):
446
446
447 def output(self, stream, output_width):
447 def output(self, stream, output_width):
448 return output_width
448 return output_width
449
449
450
450
451 class Text(Printable):
451 class Text(Printable):
452
452
453 def __init__(self):
453 def __init__(self):
454 self.objs = []
454 self.objs = []
455 self.width = 0
455 self.width = 0
456
456
457 def output(self, stream, output_width):
457 def output(self, stream, output_width):
458 for obj in self.objs:
458 for obj in self.objs:
459 stream.write(obj)
459 stream.write(obj)
460 return output_width + self.width
460 return output_width + self.width
461
461
462 def add(self, obj, width):
462 def add(self, obj, width):
463 self.objs.append(obj)
463 self.objs.append(obj)
464 self.width += width
464 self.width += width
465
465
466
466
467 class Breakable(Printable):
467 class Breakable(Printable):
468
468
469 def __init__(self, seq, width, pretty):
469 def __init__(self, seq, width, pretty):
470 self.obj = seq
470 self.obj = seq
471 self.width = width
471 self.width = width
472 self.pretty = pretty
472 self.pretty = pretty
473 self.indentation = pretty.indentation
473 self.indentation = pretty.indentation
474 self.group = pretty.group_stack[-1]
474 self.group = pretty.group_stack[-1]
475 self.group.breakables.append(self)
475 self.group.breakables.append(self)
476
476
477 def output(self, stream, output_width):
477 def output(self, stream, output_width):
478 self.group.breakables.popleft()
478 self.group.breakables.popleft()
479 if self.group.want_break:
479 if self.group.want_break:
480 stream.write(self.pretty.newline)
480 stream.write(self.pretty.newline)
481 stream.write(' ' * self.indentation)
481 stream.write(' ' * self.indentation)
482 return self.indentation
482 return self.indentation
483 if not self.group.breakables:
483 if not self.group.breakables:
484 self.pretty.group_queue.remove(self.group)
484 self.pretty.group_queue.remove(self.group)
485 stream.write(self.obj)
485 stream.write(self.obj)
486 return output_width + self.width
486 return output_width + self.width
487
487
488
488
489 class Group(Printable):
489 class Group(Printable):
490
490
491 def __init__(self, depth):
491 def __init__(self, depth):
492 self.depth = depth
492 self.depth = depth
493 self.breakables = deque()
493 self.breakables = deque()
494 self.want_break = False
494 self.want_break = False
495
495
496
496
497 class GroupQueue(object):
497 class GroupQueue(object):
498
498
499 def __init__(self, *groups):
499 def __init__(self, *groups):
500 self.queue = []
500 self.queue = []
501 for group in groups:
501 for group in groups:
502 self.enq(group)
502 self.enq(group)
503
503
504 def enq(self, group):
504 def enq(self, group):
505 depth = group.depth
505 depth = group.depth
506 while depth > len(self.queue) - 1:
506 while depth > len(self.queue) - 1:
507 self.queue.append([])
507 self.queue.append([])
508 self.queue[depth].append(group)
508 self.queue[depth].append(group)
509
509
510 def deq(self):
510 def deq(self):
511 for stack in self.queue:
511 for stack in self.queue:
512 for idx, group in enumerate(reversed(stack)):
512 for idx, group in enumerate(reversed(stack)):
513 if group.breakables:
513 if group.breakables:
514 del stack[idx]
514 del stack[idx]
515 group.want_break = True
515 group.want_break = True
516 return group
516 return group
517 for group in stack:
517 for group in stack:
518 group.want_break = True
518 group.want_break = True
519 del stack[:]
519 del stack[:]
520
520
521 def remove(self, group):
521 def remove(self, group):
522 try:
522 try:
523 self.queue[group.depth].remove(group)
523 self.queue[group.depth].remove(group)
524 except ValueError:
524 except ValueError:
525 pass
525 pass
526
526
527
527
528 class RawText:
528 class RawText:
529 """ Object such that ``p.pretty(RawText(value))`` is the same as ``p.text(value)``.
529 """ Object such that ``p.pretty(RawText(value))`` is the same as ``p.text(value)``.
530
530
531 An example usage of this would be to show a list as binary numbers, using
531 An example usage of this would be to show a list as binary numbers, using
532 ``p.pretty([RawText(bin(i)) for i in integers])``.
532 ``p.pretty([RawText(bin(i)) for i in integers])``.
533 """
533 """
534 def __init__(self, value):
534 def __init__(self, value):
535 self.value = value
535 self.value = value
536
536
537 def _repr_pretty_(self, p, cycle):
537 def _repr_pretty_(self, p, cycle):
538 p.text(self.value)
538 p.text(self.value)
539
539
540
540
541 class CallExpression:
541 class CallExpression:
542 """ Object which emits a line-wrapped call expression in the form `__name(*args, **kwargs)` """
542 """ Object which emits a line-wrapped call expression in the form `__name(*args, **kwargs)` """
543 def __init__(__self, __name, *args, **kwargs):
543 def __init__(__self, __name, *args, **kwargs):
544 # dunders are to avoid clashes with kwargs, as python's name manging
544 # dunders are to avoid clashes with kwargs, as python's name manging
545 # will kick in.
545 # will kick in.
546 self = __self
546 self = __self
547 self.name = __name
547 self.name = __name
548 self.args = args
548 self.args = args
549 self.kwargs = kwargs
549 self.kwargs = kwargs
550
550
551 @classmethod
551 @classmethod
552 def factory(cls, name):
552 def factory(cls, name):
553 def inner(*args, **kwargs):
553 def inner(*args, **kwargs):
554 return cls(name, *args, **kwargs)
554 return cls(name, *args, **kwargs)
555 return inner
555 return inner
556
556
557 def _repr_pretty_(self, p, cycle):
557 def _repr_pretty_(self, p, cycle):
558 # dunders are to avoid clashes with kwargs, as python's name manging
558 # dunders are to avoid clashes with kwargs, as python's name manging
559 # will kick in.
559 # will kick in.
560
560
561 started = False
561 started = False
562 def new_item():
562 def new_item():
563 nonlocal started
563 nonlocal started
564 if started:
564 if started:
565 p.text(",")
565 p.text(",")
566 p.breakable()
566 p.breakable()
567 started = True
567 started = True
568
568
569 prefix = self.name + "("
569 prefix = self.name + "("
570 with p.group(len(prefix), prefix, ")"):
570 with p.group(len(prefix), prefix, ")"):
571 for arg in self.args:
571 for arg in self.args:
572 new_item()
572 new_item()
573 p.pretty(arg)
573 p.pretty(arg)
574 for arg_name, arg in self.kwargs.items():
574 for arg_name, arg in self.kwargs.items():
575 new_item()
575 new_item()
576 arg_prefix = arg_name + "="
576 arg_prefix = arg_name + "="
577 with p.group(len(arg_prefix), arg_prefix):
577 with p.group(len(arg_prefix), arg_prefix):
578 p.pretty(arg)
578 p.pretty(arg)
579
579
580
580
581 class RawStringLiteral:
581 class RawStringLiteral:
582 """ Wrapper that shows a string with a `r` prefix """
582 """ Wrapper that shows a string with a `r` prefix """
583 def __init__(self, value):
583 def __init__(self, value):
584 self.value = value
584 self.value = value
585
585
586 def _repr_pretty_(self, p, cycle):
586 def _repr_pretty_(self, p, cycle):
587 base_repr = repr(self.value)
587 base_repr = repr(self.value)
588 if base_repr[:1] in 'uU':
588 if base_repr[:1] in 'uU':
589 base_repr = base_repr[1:]
589 base_repr = base_repr[1:]
590 prefix = 'ur'
590 prefix = 'ur'
591 else:
591 else:
592 prefix = 'r'
592 prefix = 'r'
593 base_repr = prefix + base_repr.replace('\\\\', '\\')
593 base_repr = prefix + base_repr.replace('\\\\', '\\')
594 p.text(base_repr)
594 p.text(base_repr)
595
595
596
596
597 def _default_pprint(obj, p, cycle):
597 def _default_pprint(obj, p, cycle):
598 """
598 """
599 The default print function. Used if an object does not provide one and
599 The default print function. Used if an object does not provide one and
600 it's none of the builtin objects.
600 it's none of the builtin objects.
601 """
601 """
602 klass = _safe_getattr(obj, '__class__', None) or type(obj)
602 klass = _safe_getattr(obj, '__class__', None) or type(obj)
603 if _safe_getattr(klass, '__repr__', None) is not object.__repr__:
603 if _safe_getattr(klass, '__repr__', None) is not object.__repr__:
604 # A user-provided repr. Find newlines and replace them with p.break_()
604 # A user-provided repr. Find newlines and replace them with p.break_()
605 _repr_pprint(obj, p, cycle)
605 _repr_pprint(obj, p, cycle)
606 return
606 return
607 p.begin_group(1, '<')
607 p.begin_group(1, '<')
608 p.pretty(klass)
608 p.pretty(klass)
609 p.text(' at 0x%x' % id(obj))
609 p.text(' at 0x%x' % id(obj))
610 if cycle:
610 if cycle:
611 p.text(' ...')
611 p.text(' ...')
612 elif p.verbose:
612 elif p.verbose:
613 first = True
613 first = True
614 for key in dir(obj):
614 for key in dir(obj):
615 if not key.startswith('_'):
615 if not key.startswith('_'):
616 try:
616 try:
617 value = getattr(obj, key)
617 value = getattr(obj, key)
618 except AttributeError:
618 except AttributeError:
619 continue
619 continue
620 if isinstance(value, types.MethodType):
620 if isinstance(value, types.MethodType):
621 continue
621 continue
622 if not first:
622 if not first:
623 p.text(',')
623 p.text(',')
624 p.breakable()
624 p.breakable()
625 p.text(key)
625 p.text(key)
626 p.text('=')
626 p.text('=')
627 step = len(key) + 1
627 step = len(key) + 1
628 p.indentation += step
628 p.indentation += step
629 p.pretty(value)
629 p.pretty(value)
630 p.indentation -= step
630 p.indentation -= step
631 first = False
631 first = False
632 p.end_group(1, '>')
632 p.end_group(1, '>')
633
633
634
634
635 def _seq_pprinter_factory(start, end):
635 def _seq_pprinter_factory(start, end):
636 """
636 """
637 Factory that returns a pprint function useful for sequences. Used by
637 Factory that returns a pprint function useful for sequences. Used by
638 the default pprint for tuples and lists.
638 the default pprint for tuples and lists.
639 """
639 """
640 def inner(obj, p, cycle):
640 def inner(obj, p, cycle):
641 if cycle:
641 if cycle:
642 return p.text(start + '...' + end)
642 return p.text(start + '...' + end)
643 step = len(start)
643 step = len(start)
644 p.begin_group(step, start)
644 p.begin_group(step, start)
645 for idx, x in p._enumerate(obj):
645 for idx, x in p._enumerate(obj):
646 if idx:
646 if idx:
647 p.text(',')
647 p.text(',')
648 p.breakable()
648 p.breakable()
649 p.pretty(x)
649 p.pretty(x)
650 if len(obj) == 1 and isinstance(obj, tuple):
650 if len(obj) == 1 and isinstance(obj, tuple):
651 # Special case for 1-item tuples.
651 # Special case for 1-item tuples.
652 p.text(',')
652 p.text(',')
653 p.end_group(step, end)
653 p.end_group(step, end)
654 return inner
654 return inner
655
655
656
656
657 def _set_pprinter_factory(start, end):
657 def _set_pprinter_factory(start, end):
658 """
658 """
659 Factory that returns a pprint function useful for sets and frozensets.
659 Factory that returns a pprint function useful for sets and frozensets.
660 """
660 """
661 def inner(obj, p, cycle):
661 def inner(obj, p, cycle):
662 if cycle:
662 if cycle:
663 return p.text(start + '...' + end)
663 return p.text(start + '...' + end)
664 if len(obj) == 0:
664 if len(obj) == 0:
665 # Special case.
665 # Special case.
666 p.text(type(obj).__name__ + '()')
666 p.text(type(obj).__name__ + '()')
667 else:
667 else:
668 step = len(start)
668 step = len(start)
669 p.begin_group(step, start)
669 p.begin_group(step, start)
670 # Like dictionary keys, we will try to sort the items if there aren't too many
670 # Like dictionary keys, we will try to sort the items if there aren't too many
671 if not (p.max_seq_length and len(obj) >= p.max_seq_length):
671 if not (p.max_seq_length and len(obj) >= p.max_seq_length):
672 items = _sorted_for_pprint(obj)
672 items = _sorted_for_pprint(obj)
673 else:
673 else:
674 items = obj
674 items = obj
675 for idx, x in p._enumerate(items):
675 for idx, x in p._enumerate(items):
676 if idx:
676 if idx:
677 p.text(',')
677 p.text(',')
678 p.breakable()
678 p.breakable()
679 p.pretty(x)
679 p.pretty(x)
680 p.end_group(step, end)
680 p.end_group(step, end)
681 return inner
681 return inner
682
682
683
683
684 def _dict_pprinter_factory(start, end):
684 def _dict_pprinter_factory(start, end):
685 """
685 """
686 Factory that returns a pprint function used by the default pprint of
686 Factory that returns a pprint function used by the default pprint of
687 dicts and dict proxies.
687 dicts and dict proxies.
688 """
688 """
689 def inner(obj, p, cycle):
689 def inner(obj, p, cycle):
690 if cycle:
690 if cycle:
691 return p.text('{...}')
691 return p.text('{...}')
692 step = len(start)
692 step = len(start)
693 p.begin_group(step, start)
693 p.begin_group(step, start)
694 keys = obj.keys()
694 keys = obj.keys()
695 for idx, key in p._enumerate(keys):
695 for idx, key in p._enumerate(keys):
696 if idx:
696 if idx:
697 p.text(',')
697 p.text(',')
698 p.breakable()
698 p.breakable()
699 p.pretty(key)
699 p.pretty(key)
700 p.text(': ')
700 p.text(': ')
701 p.pretty(obj[key])
701 p.pretty(obj[key])
702 p.end_group(step, end)
702 p.end_group(step, end)
703 return inner
703 return inner
704
704
705
705
706 def _super_pprint(obj, p, cycle):
706 def _super_pprint(obj, p, cycle):
707 """The pprint for the super type."""
707 """The pprint for the super type."""
708 p.begin_group(8, '<super: ')
708 p.begin_group(8, '<super: ')
709 p.pretty(obj.__thisclass__)
709 p.pretty(obj.__thisclass__)
710 p.text(',')
710 p.text(',')
711 p.breakable()
711 p.breakable()
712 if PYPY: # In PyPy, super() objects don't have __self__ attributes
712 if PYPY: # In PyPy, super() objects don't have __self__ attributes
713 dself = obj.__repr__.__self__
713 dself = obj.__repr__.__self__
714 p.pretty(None if dself is obj else dself)
714 p.pretty(None if dself is obj else dself)
715 else:
715 else:
716 p.pretty(obj.__self__)
716 p.pretty(obj.__self__)
717 p.end_group(8, '>')
717 p.end_group(8, '>')
718
718
719
719
720
720
721 class _ReFlags:
721 class _ReFlags:
722 def __init__(self, value):
722 def __init__(self, value):
723 self.value = value
723 self.value = value
724
724
725 def _repr_pretty_(self, p, cycle):
725 def _repr_pretty_(self, p, cycle):
726 done_one = False
726 done_one = False
727 for flag in ('TEMPLATE', 'IGNORECASE', 'LOCALE', 'MULTILINE', 'DOTALL',
727 for flag in ('TEMPLATE', 'IGNORECASE', 'LOCALE', 'MULTILINE', 'DOTALL',
728 'UNICODE', 'VERBOSE', 'DEBUG'):
728 'UNICODE', 'VERBOSE', 'DEBUG'):
729 if self.value & getattr(re, flag):
729 if self.value & getattr(re, flag):
730 if done_one:
730 if done_one:
731 p.text('|')
731 p.text('|')
732 p.text('re.' + flag)
732 p.text('re.' + flag)
733 done_one = True
733 done_one = True
734
734
735
735
736 def _re_pattern_pprint(obj, p, cycle):
736 def _re_pattern_pprint(obj, p, cycle):
737 """The pprint function for regular expression patterns."""
737 """The pprint function for regular expression patterns."""
738 re_compile = CallExpression.factory('re.compile')
738 re_compile = CallExpression.factory('re.compile')
739 if obj.flags:
739 if obj.flags:
740 p.pretty(re_compile(RawStringLiteral(obj.pattern), _ReFlags(obj.flags)))
740 p.pretty(re_compile(RawStringLiteral(obj.pattern), _ReFlags(obj.flags)))
741 else:
741 else:
742 p.pretty(re_compile(RawStringLiteral(obj.pattern)))
742 p.pretty(re_compile(RawStringLiteral(obj.pattern)))
743
743
744
744
745 def _types_simplenamespace_pprint(obj, p, cycle):
745 def _types_simplenamespace_pprint(obj, p, cycle):
746 """The pprint function for types.SimpleNamespace."""
746 """The pprint function for types.SimpleNamespace."""
747 namespace = CallExpression.factory('namespace')
747 namespace = CallExpression.factory('namespace')
748 if cycle:
748 if cycle:
749 p.pretty(namespace(RawText("...")))
749 p.pretty(namespace(RawText("...")))
750 else:
750 else:
751 p.pretty(namespace(**obj.__dict__))
751 p.pretty(namespace(**obj.__dict__))
752
752
753
753
754 def _type_pprint(obj, p, cycle):
754 def _type_pprint(obj, p, cycle):
755 """The pprint for classes and types."""
755 """The pprint for classes and types."""
756 # Heap allocated types might not have the module attribute,
756 # Heap allocated types might not have the module attribute,
757 # and others may set it to None.
757 # and others may set it to None.
758
758
759 # Checks for a __repr__ override in the metaclass. Can't compare the
759 # Checks for a __repr__ override in the metaclass. Can't compare the
760 # type(obj).__repr__ directly because in PyPy the representation function
760 # type(obj).__repr__ directly because in PyPy the representation function
761 # inherited from type isn't the same type.__repr__
761 # inherited from type isn't the same type.__repr__
762 if [m for m in _get_mro(type(obj)) if "__repr__" in vars(m)][:1] != [type]:
762 if [m for m in _get_mro(type(obj)) if "__repr__" in vars(m)][:1] != [type]:
763 _repr_pprint(obj, p, cycle)
763 _repr_pprint(obj, p, cycle)
764 return
764 return
765
765
766 mod = _safe_getattr(obj, '__module__', None)
766 mod = _safe_getattr(obj, '__module__', None)
767 try:
767 try:
768 name = obj.__qualname__
768 name = obj.__qualname__
769 if not isinstance(name, str):
769 if not isinstance(name, str):
770 # This can happen if the type implements __qualname__ as a property
770 # This can happen if the type implements __qualname__ as a property
771 # or other descriptor in Python 2.
771 # or other descriptor in Python 2.
772 raise Exception("Try __name__")
772 raise Exception("Try __name__")
773 except Exception:
773 except Exception:
774 name = obj.__name__
774 name = obj.__name__
775 if not isinstance(name, str):
775 if not isinstance(name, str):
776 name = '<unknown type>'
776 name = '<unknown type>'
777
777
778 if mod in (None, '__builtin__', 'builtins', 'exceptions'):
778 if mod in (None, '__builtin__', 'builtins', 'exceptions'):
779 p.text(name)
779 p.text(name)
780 else:
780 else:
781 p.text(mod + '.' + name)
781 p.text(mod + '.' + name)
782
782
783
783
784 def _repr_pprint(obj, p, cycle):
784 def _repr_pprint(obj, p, cycle):
785 """A pprint that just redirects to the normal repr function."""
785 """A pprint that just redirects to the normal repr function."""
786 # Find newlines and replace them with p.break_()
786 # Find newlines and replace them with p.break_()
787 output = repr(obj)
787 output = repr(obj)
788 lines = output.splitlines()
788 lines = output.splitlines()
789 with p.group():
789 with p.group():
790 for idx, output_line in enumerate(lines):
790 for idx, output_line in enumerate(lines):
791 if idx:
791 if idx:
792 p.break_()
792 p.break_()
793 p.text(output_line)
793 p.text(output_line)
794
794
795
795
796 def _function_pprint(obj, p, cycle):
796 def _function_pprint(obj, p, cycle):
797 """Base pprint for all functions and builtin functions."""
797 """Base pprint for all functions and builtin functions."""
798 name = _safe_getattr(obj, '__qualname__', obj.__name__)
798 name = _safe_getattr(obj, '__qualname__', obj.__name__)
799 mod = obj.__module__
799 mod = obj.__module__
800 if mod and mod not in ('__builtin__', 'builtins', 'exceptions'):
800 if mod and mod not in ('__builtin__', 'builtins', 'exceptions'):
801 name = mod + '.' + name
801 name = mod + '.' + name
802 try:
802 try:
803 func_def = name + str(signature(obj))
803 func_def = name + str(signature(obj))
804 except ValueError:
804 except ValueError:
805 func_def = name
805 func_def = name
806 p.text('<function %s>' % func_def)
806 p.text('<function %s>' % func_def)
807
807
808
808
809 def _exception_pprint(obj, p, cycle):
809 def _exception_pprint(obj, p, cycle):
810 """Base pprint for all exceptions."""
810 """Base pprint for all exceptions."""
811 name = getattr(obj.__class__, '__qualname__', obj.__class__.__name__)
811 name = getattr(obj.__class__, '__qualname__', obj.__class__.__name__)
812 if obj.__class__.__module__ not in ('exceptions', 'builtins'):
812 if obj.__class__.__module__ not in ('exceptions', 'builtins'):
813 name = '%s.%s' % (obj.__class__.__module__, name)
813 name = '%s.%s' % (obj.__class__.__module__, name)
814
814
815 p.pretty(CallExpression(name, *getattr(obj, 'args', ())))
815 p.pretty(CallExpression(name, *getattr(obj, 'args', ())))
816
816
817
817
818 #: the exception base
818 #: the exception base
819 _exception_base: type
819 _exception_base: type
820 try:
820 try:
821 _exception_base = BaseException
821 _exception_base = BaseException
822 except NameError:
822 except NameError:
823 _exception_base = Exception
823 _exception_base = Exception
824
824
825
825
826 #: printers for builtin types
826 #: printers for builtin types
827 _type_pprinters = {
827 _type_pprinters = {
828 int: _repr_pprint,
828 int: _repr_pprint,
829 float: _repr_pprint,
829 float: _repr_pprint,
830 str: _repr_pprint,
830 str: _repr_pprint,
831 tuple: _seq_pprinter_factory('(', ')'),
831 tuple: _seq_pprinter_factory('(', ')'),
832 list: _seq_pprinter_factory('[', ']'),
832 list: _seq_pprinter_factory('[', ']'),
833 dict: _dict_pprinter_factory('{', '}'),
833 dict: _dict_pprinter_factory('{', '}'),
834 set: _set_pprinter_factory('{', '}'),
834 set: _set_pprinter_factory('{', '}'),
835 frozenset: _set_pprinter_factory('frozenset({', '})'),
835 frozenset: _set_pprinter_factory('frozenset({', '})'),
836 super: _super_pprint,
836 super: _super_pprint,
837 _re_pattern_type: _re_pattern_pprint,
837 _re_pattern_type: _re_pattern_pprint,
838 type: _type_pprint,
838 type: _type_pprint,
839 types.FunctionType: _function_pprint,
839 types.FunctionType: _function_pprint,
840 types.BuiltinFunctionType: _function_pprint,
840 types.BuiltinFunctionType: _function_pprint,
841 types.MethodType: _repr_pprint,
841 types.MethodType: _repr_pprint,
842 types.SimpleNamespace: _types_simplenamespace_pprint,
842 types.SimpleNamespace: _types_simplenamespace_pprint,
843 datetime.datetime: _repr_pprint,
843 datetime.datetime: _repr_pprint,
844 datetime.timedelta: _repr_pprint,
844 datetime.timedelta: _repr_pprint,
845 _exception_base: _exception_pprint
845 _exception_base: _exception_pprint
846 }
846 }
847
847
848 # render os.environ like a dict
848 # render os.environ like a dict
849 _env_type = type(os.environ)
849 _env_type = type(os.environ)
850 # future-proof in case os.environ becomes a plain dict?
850 # future-proof in case os.environ becomes a plain dict?
851 if _env_type is not dict:
851 if _env_type is not dict:
852 _type_pprinters[_env_type] = _dict_pprinter_factory('environ{', '}')
852 _type_pprinters[_env_type] = _dict_pprinter_factory('environ{', '}')
853
853
854 _type_pprinters[types.MappingProxyType] = _dict_pprinter_factory("mappingproxy({", "})")
854 _type_pprinters[types.MappingProxyType] = _dict_pprinter_factory("mappingproxy({", "})")
855 _type_pprinters[slice] = _repr_pprint
855 _type_pprinters[slice] = _repr_pprint
856
856
857 _type_pprinters[range] = _repr_pprint
857 _type_pprinters[range] = _repr_pprint
858 _type_pprinters[bytes] = _repr_pprint
858 _type_pprinters[bytes] = _repr_pprint
859
859
860 #: printers for types specified by name
860 #: printers for types specified by name
861 _deferred_type_pprinters: Dict = {}
861 _deferred_type_pprinters: Dict = {}
862
862
863
863
864 def for_type(typ, func):
864 def for_type(typ, func):
865 """
865 """
866 Add a pretty printer for a given type.
866 Add a pretty printer for a given type.
867 """
867 """
868 oldfunc = _type_pprinters.get(typ, None)
868 oldfunc = _type_pprinters.get(typ, None)
869 if func is not None:
869 if func is not None:
870 # To support easy restoration of old pprinters, we need to ignore Nones.
870 # To support easy restoration of old pprinters, we need to ignore Nones.
871 _type_pprinters[typ] = func
871 _type_pprinters[typ] = func
872 return oldfunc
872 return oldfunc
873
873
874 def for_type_by_name(type_module, type_name, func):
874 def for_type_by_name(type_module, type_name, func):
875 """
875 """
876 Add a pretty printer for a type specified by the module and name of a type
876 Add a pretty printer for a type specified by the module and name of a type
877 rather than the type object itself.
877 rather than the type object itself.
878 """
878 """
879 key = (type_module, type_name)
879 key = (type_module, type_name)
880 oldfunc = _deferred_type_pprinters.get(key, None)
880 oldfunc = _deferred_type_pprinters.get(key, None)
881 if func is not None:
881 if func is not None:
882 # To support easy restoration of old pprinters, we need to ignore Nones.
882 # To support easy restoration of old pprinters, we need to ignore Nones.
883 _deferred_type_pprinters[key] = func
883 _deferred_type_pprinters[key] = func
884 return oldfunc
884 return oldfunc
885
885
886
886
887 #: printers for the default singletons
887 #: printers for the default singletons
888 _singleton_pprinters = dict.fromkeys(map(id, [None, True, False, Ellipsis,
888 _singleton_pprinters = dict.fromkeys(map(id, [None, True, False, Ellipsis,
889 NotImplemented]), _repr_pprint)
889 NotImplemented]), _repr_pprint)
890
890
891
891
892 def _defaultdict_pprint(obj, p, cycle):
892 def _defaultdict_pprint(obj, p, cycle):
893 cls_ctor = CallExpression.factory(obj.__class__.__name__)
893 cls_ctor = CallExpression.factory(obj.__class__.__name__)
894 if cycle:
894 if cycle:
895 p.pretty(cls_ctor(RawText("...")))
895 p.pretty(cls_ctor(RawText("...")))
896 else:
896 else:
897 p.pretty(cls_ctor(obj.default_factory, dict(obj)))
897 p.pretty(cls_ctor(obj.default_factory, dict(obj)))
898
898
899 def _ordereddict_pprint(obj, p, cycle):
899 def _ordereddict_pprint(obj, p, cycle):
900 cls_ctor = CallExpression.factory(obj.__class__.__name__)
900 cls_ctor = CallExpression.factory(obj.__class__.__name__)
901 if cycle:
901 if cycle:
902 p.pretty(cls_ctor(RawText("...")))
902 p.pretty(cls_ctor(RawText("...")))
903 elif len(obj):
903 elif len(obj):
904 p.pretty(cls_ctor(list(obj.items())))
904 p.pretty(cls_ctor(list(obj.items())))
905 else:
905 else:
906 p.pretty(cls_ctor())
906 p.pretty(cls_ctor())
907
907
908 def _deque_pprint(obj, p, cycle):
908 def _deque_pprint(obj, p, cycle):
909 cls_ctor = CallExpression.factory(obj.__class__.__name__)
909 cls_ctor = CallExpression.factory(obj.__class__.__name__)
910 if cycle:
910 if cycle:
911 p.pretty(cls_ctor(RawText("...")))
911 p.pretty(cls_ctor(RawText("...")))
912 elif obj.maxlen is not None:
912 elif obj.maxlen is not None:
913 p.pretty(cls_ctor(list(obj), maxlen=obj.maxlen))
913 p.pretty(cls_ctor(list(obj), maxlen=obj.maxlen))
914 else:
914 else:
915 p.pretty(cls_ctor(list(obj)))
915 p.pretty(cls_ctor(list(obj)))
916
916
917 def _counter_pprint(obj, p, cycle):
917 def _counter_pprint(obj, p, cycle):
918 cls_ctor = CallExpression.factory(obj.__class__.__name__)
918 cls_ctor = CallExpression.factory(obj.__class__.__name__)
919 if cycle:
919 if cycle:
920 p.pretty(cls_ctor(RawText("...")))
920 p.pretty(cls_ctor(RawText("...")))
921 elif len(obj):
921 elif len(obj):
922 p.pretty(cls_ctor(dict(obj.most_common())))
922 p.pretty(cls_ctor(dict(obj.most_common())))
923 else:
923 else:
924 p.pretty(cls_ctor())
924 p.pretty(cls_ctor())
925
925
926
926
927 def _userlist_pprint(obj, p, cycle):
927 def _userlist_pprint(obj, p, cycle):
928 cls_ctor = CallExpression.factory(obj.__class__.__name__)
928 cls_ctor = CallExpression.factory(obj.__class__.__name__)
929 if cycle:
929 if cycle:
930 p.pretty(cls_ctor(RawText("...")))
930 p.pretty(cls_ctor(RawText("...")))
931 else:
931 else:
932 p.pretty(cls_ctor(obj.data))
932 p.pretty(cls_ctor(obj.data))
933
933
934
934
935 for_type_by_name('collections', 'defaultdict', _defaultdict_pprint)
935 for_type_by_name('collections', 'defaultdict', _defaultdict_pprint)
936 for_type_by_name('collections', 'OrderedDict', _ordereddict_pprint)
936 for_type_by_name('collections', 'OrderedDict', _ordereddict_pprint)
937 for_type_by_name('collections', 'deque', _deque_pprint)
937 for_type_by_name('collections', 'deque', _deque_pprint)
938 for_type_by_name('collections', 'Counter', _counter_pprint)
938 for_type_by_name('collections', 'Counter', _counter_pprint)
939 for_type_by_name("collections", "UserList", _userlist_pprint)
939 for_type_by_name("collections", "UserList", _userlist_pprint)
940
940
941 if __name__ == '__main__':
941 if __name__ == '__main__':
942 from random import randrange
942 from random import randrange
943 class Foo(object):
943 class Foo(object):
944 def __init__(self):
944 def __init__(self):
945 self.foo = 1
945 self.foo = 1
946 self.bar = re.compile(r'\s+')
946 self.bar = re.compile(r'\s+')
947 self.blub = dict.fromkeys(range(30), randrange(1, 40))
947 self.blub = dict.fromkeys(range(30), randrange(1, 40))
948 self.hehe = 23424.234234
948 self.hehe = 23424.234234
949 self.list = ["blub", "blah", self]
949 self.list = ["blub", "blah", self]
950
950
951 def get_foo(self):
951 def get_foo(self):
952 print("foo")
952 print("foo")
953
953
954 pprint(Foo(), verbose=True)
954 pprint(Foo(), verbose=True)
General Comments 0
You need to be logged in to leave comments. Login now