##// END OF EJS Templates
Merge pull request #10863 from Madhu94/add-function-signature-display...
Thomas Kluyver -
r24032:dc9d1c67 merge
parent child Browse files
Show More
@@ -1,432 +1,437
1 1 """Tests for the object inspection functionality.
2 2 """
3 3
4 4 # Copyright (c) IPython Development Team.
5 5 # Distributed under the terms of the Modified BSD License.
6 6
7 7
8 8 from inspect import Signature, Parameter
9 9 import os
10 10 import re
11 11 import sys
12 12
13 13 import nose.tools as nt
14 14
15 15 from .. import oinspect
16 16 from IPython.core.magic import (Magics, magics_class, line_magic,
17 17 cell_magic, line_cell_magic,
18 18 register_line_magic, register_cell_magic,
19 19 register_line_cell_magic)
20 20 from decorator import decorator
21 21 from IPython import get_ipython
22 22 from IPython.testing.tools import AssertPrints, AssertNotPrints
23 23 from IPython.utils.path import compress_user
24 24
25 25
26 26 #-----------------------------------------------------------------------------
27 27 # Globals and constants
28 28 #-----------------------------------------------------------------------------
29 29
30 30 inspector = oinspect.Inspector()
31 31 ip = get_ipython()
32 32
33 33 #-----------------------------------------------------------------------------
34 34 # Local utilities
35 35 #-----------------------------------------------------------------------------
36 36
37 37 # WARNING: since this test checks the line number where a function is
38 38 # defined, if any code is inserted above, the following line will need to be
39 39 # updated. Do NOT insert any whitespace between the next line and the function
40 40 # definition below.
41 41 THIS_LINE_NUMBER = 41 # Put here the actual number of this line
42 42
43 43 from unittest import TestCase
44 44
45 45 class Test(TestCase):
46 46
47 47 def test_find_source_lines(self):
48 48 self.assertEqual(oinspect.find_source_lines(Test.test_find_source_lines),
49 49 THIS_LINE_NUMBER+6)
50 50
51 51
52 52 # A couple of utilities to ensure these tests work the same from a source or a
53 53 # binary install
54 54 def pyfile(fname):
55 55 return os.path.normcase(re.sub('.py[co]$', '.py', fname))
56 56
57 57
58 58 def match_pyfiles(f1, f2):
59 59 nt.assert_equal(pyfile(f1), pyfile(f2))
60 60
61 61
62 62 def test_find_file():
63 63 match_pyfiles(oinspect.find_file(test_find_file), os.path.abspath(__file__))
64 64
65 65
66 66 def test_find_file_decorated1():
67 67
68 68 @decorator
69 69 def noop1(f):
70 70 def wrapper(*a, **kw):
71 71 return f(*a, **kw)
72 72 return wrapper
73 73
74 74 @noop1
75 75 def f(x):
76 76 "My docstring"
77 77
78 78 match_pyfiles(oinspect.find_file(f), os.path.abspath(__file__))
79 79 nt.assert_equal(f.__doc__, "My docstring")
80 80
81 81
82 82 def test_find_file_decorated2():
83 83
84 84 @decorator
85 85 def noop2(f, *a, **kw):
86 86 return f(*a, **kw)
87 87
88 88 @noop2
89 89 @noop2
90 90 @noop2
91 91 def f(x):
92 92 "My docstring 2"
93 93
94 94 match_pyfiles(oinspect.find_file(f), os.path.abspath(__file__))
95 95 nt.assert_equal(f.__doc__, "My docstring 2")
96 96
97 97
98 98 def test_find_file_magic():
99 99 run = ip.find_line_magic('run')
100 100 nt.assert_not_equal(oinspect.find_file(run), None)
101 101
102 102
103 103 # A few generic objects we can then inspect in the tests below
104 104
105 105 class Call(object):
106 106 """This is the class docstring."""
107 107
108 108 def __init__(self, x, y=1):
109 109 """This is the constructor docstring."""
110 110
111 111 def __call__(self, *a, **kw):
112 112 """This is the call docstring."""
113 113
114 114 def method(self, x, z=2):
115 115 """Some method's docstring"""
116 116
117 117 class HasSignature(object):
118 118 """This is the class docstring."""
119 119 __signature__ = Signature([Parameter('test', Parameter.POSITIONAL_OR_KEYWORD)])
120 120
121 121 def __init__(self, *args):
122 122 """This is the init docstring"""
123 123
124 124
125 125 class SimpleClass(object):
126 126 def method(self, x, z=2):
127 127 """Some method's docstring"""
128 128
129 129
130 130 class OldStyle:
131 131 """An old-style class for testing."""
132 132 pass
133 133
134 134
135 135 def f(x, y=2, *a, **kw):
136 136 """A simple function."""
137 137
138 138
139 139 def g(y, z=3, *a, **kw):
140 140 pass # no docstring
141 141
142 142
143 143 @register_line_magic
144 144 def lmagic(line):
145 145 "A line magic"
146 146
147 147
148 148 @register_cell_magic
149 149 def cmagic(line, cell):
150 150 "A cell magic"
151 151
152 152
153 153 @register_line_cell_magic
154 154 def lcmagic(line, cell=None):
155 155 "A line/cell magic"
156 156
157 157
158 158 @magics_class
159 159 class SimpleMagics(Magics):
160 160 @line_magic
161 161 def Clmagic(self, cline):
162 162 "A class-based line magic"
163 163
164 164 @cell_magic
165 165 def Ccmagic(self, cline, ccell):
166 166 "A class-based cell magic"
167 167
168 168 @line_cell_magic
169 169 def Clcmagic(self, cline, ccell=None):
170 170 "A class-based line/cell magic"
171 171
172 172
173 173 class Awkward(object):
174 174 def __getattr__(self, name):
175 175 raise Exception(name)
176 176
177 177 class NoBoolCall:
178 178 """
179 179 callable with `__bool__` raising should still be inspect-able.
180 180 """
181 181
182 182 def __call__(self):
183 183 """does nothing"""
184 184 pass
185 185
186 186 def __bool__(self):
187 187 """just raise NotImplemented"""
188 188 raise NotImplementedError('Must be implemented')
189 189
190 190
191 191 class SerialLiar(object):
192 192 """Attribute accesses always get another copy of the same class.
193 193
194 194 unittest.mock.call does something similar, but it's not ideal for testing
195 195 as the failure mode is to eat all your RAM. This gives up after 10k levels.
196 196 """
197 197 def __init__(self, max_fibbing_twig, lies_told=0):
198 198 if lies_told > 10000:
199 199 raise RuntimeError('Nose too long, honesty is the best policy')
200 200 self.max_fibbing_twig = max_fibbing_twig
201 201 self.lies_told = lies_told
202 202 max_fibbing_twig[0] = max(max_fibbing_twig[0], lies_told)
203 203
204 204 def __getattr__(self, item):
205 205 return SerialLiar(self.max_fibbing_twig, self.lies_told + 1)
206 206
207 207 #-----------------------------------------------------------------------------
208 208 # Tests
209 209 #-----------------------------------------------------------------------------
210 210
211 211 def test_info():
212 212 "Check that Inspector.info fills out various fields as expected."
213 213 i = inspector.info(Call, oname='Call')
214 214 nt.assert_equal(i['type_name'], 'type')
215 215 expted_class = str(type(type)) # <class 'type'> (Python 3) or <type 'type'>
216 216 nt.assert_equal(i['base_class'], expted_class)
217 217 nt.assert_regex(i['string_form'], "<class 'IPython.core.tests.test_oinspect.Call'( at 0x[0-9a-f]{1,9})?>")
218 218 fname = __file__
219 219 if fname.endswith(".pyc"):
220 220 fname = fname[:-1]
221 221 # case-insensitive comparison needed on some filesystems
222 222 # e.g. Windows:
223 223 nt.assert_equal(i['file'].lower(), compress_user(fname).lower())
224 224 nt.assert_equal(i['definition'], None)
225 225 nt.assert_equal(i['docstring'], Call.__doc__)
226 226 nt.assert_equal(i['source'], None)
227 227 nt.assert_true(i['isclass'])
228 228 nt.assert_equal(i['init_definition'], "Call(x, y=1)")
229 229 nt.assert_equal(i['init_docstring'], Call.__init__.__doc__)
230 230
231 231 i = inspector.info(Call, detail_level=1)
232 232 nt.assert_not_equal(i['source'], None)
233 233 nt.assert_equal(i['docstring'], None)
234 234
235 235 c = Call(1)
236 236 c.__doc__ = "Modified instance docstring"
237 237 i = inspector.info(c)
238 238 nt.assert_equal(i['type_name'], 'Call')
239 239 nt.assert_equal(i['docstring'], "Modified instance docstring")
240 240 nt.assert_equal(i['class_docstring'], Call.__doc__)
241 241 nt.assert_equal(i['init_docstring'], Call.__init__.__doc__)
242 242 nt.assert_equal(i['call_docstring'], Call.__call__.__doc__)
243 243
244 244 def test_class_signature():
245 245 info = inspector.info(HasSignature, 'HasSignature')
246 246 nt.assert_equal(info['init_definition'], "HasSignature(test)")
247 247 nt.assert_equal(info['init_docstring'], HasSignature.__init__.__doc__)
248 248
249 249 def test_info_awkward():
250 250 # Just test that this doesn't throw an error.
251 251 inspector.info(Awkward())
252 252
253 253 def test_bool_raise():
254 254 inspector.info(NoBoolCall())
255 255
256 256 def test_info_serialliar():
257 257 fib_tracker = [0]
258 258 inspector.info(SerialLiar(fib_tracker))
259 259
260 260 # Nested attribute access should be cut off at 100 levels deep to avoid
261 261 # infinite loops: https://github.com/ipython/ipython/issues/9122
262 262 nt.assert_less(fib_tracker[0], 9000)
263 263
264 264 def test_calldef_none():
265 265 # We should ignore __call__ for all of these.
266 266 for obj in [f, SimpleClass().method, any, str.upper]:
267 267 print(obj)
268 268 i = inspector.info(obj)
269 269 nt.assert_is(i['call_def'], None)
270 270
271 271 def f_kwarg(pos, *, kwonly):
272 272 pass
273 273
274 274 def test_definition_kwonlyargs():
275 275 i = inspector.info(f_kwarg, oname='f_kwarg') # analysis:ignore
276 276 nt.assert_equal(i['definition'], "f_kwarg(pos, *, kwonly)")
277 277
278 278 def test_getdoc():
279 279 class A(object):
280 280 """standard docstring"""
281 281 pass
282 282
283 283 class B(object):
284 284 """standard docstring"""
285 285 def getdoc(self):
286 286 return "custom docstring"
287 287
288 288 class C(object):
289 289 """standard docstring"""
290 290 def getdoc(self):
291 291 return None
292 292
293 293 a = A()
294 294 b = B()
295 295 c = C()
296 296
297 297 nt.assert_equal(oinspect.getdoc(a), "standard docstring")
298 298 nt.assert_equal(oinspect.getdoc(b), "custom docstring")
299 299 nt.assert_equal(oinspect.getdoc(c), "standard docstring")
300 300
301 301
302 302 def test_empty_property_has_no_source():
303 303 i = inspector.info(property(), detail_level=1)
304 304 nt.assert_is(i['source'], None)
305 305
306 306
307 307 def test_property_sources():
308 import zlib
309
308 import posixpath
309 # A simple adder whose source and signature stays
310 # the same across Python distributions
311 def simple_add(a, b):
312 "Adds two numbers"
313 return a + b
314
310 315 class A(object):
311 316 @property
312 317 def foo(self):
313 318 return 'bar'
314 319
315 320 foo = foo.setter(lambda self, v: setattr(self, 'bar', v))
316 321
317 id = property(id)
318 compress = property(zlib.compress)
322 dname = property(posixpath.dirname)
323 adder = property(simple_add)
319 324
320 325 i = inspector.info(A.foo, detail_level=1)
321 326 nt.assert_in('def foo(self):', i['source'])
322 327 nt.assert_in('lambda self, v:', i['source'])
323 328
324 i = inspector.info(A.id, detail_level=1)
325 nt.assert_in('fget = <function id>', i['source'])
326
327 i = inspector.info(A.compress, detail_level=1)
328 nt.assert_in('fget = <function zlib.compress>', i['source'])
329 i = inspector.info(A.dname, detail_level=1)
330 nt.assert_in('def dirname(p)', i['source'])
331
332 i = inspector.info(A.adder, detail_level=1)
333 nt.assert_in('def simple_add(a, b)', i['source'])
329 334
330 335
331 336 def test_property_docstring_is_in_info_for_detail_level_0():
332 337 class A(object):
333 338 @property
334 339 def foobar(self):
335 340 """This is `foobar` property."""
336 341 pass
337 342
338 343 ip.user_ns['a_obj'] = A()
339 344 nt.assert_equal(
340 345 'This is `foobar` property.',
341 346 ip.object_inspect('a_obj.foobar', detail_level=0)['docstring'])
342 347
343 348 ip.user_ns['a_cls'] = A
344 349 nt.assert_equal(
345 350 'This is `foobar` property.',
346 351 ip.object_inspect('a_cls.foobar', detail_level=0)['docstring'])
347 352
348 353
349 354 def test_pdef():
350 355 # See gh-1914
351 356 def foo(): pass
352 357 inspector.pdef(foo, 'foo')
353 358
354 359
355 360 def test_pinfo_nonascii():
356 361 # See gh-1177
357 362 from . import nonascii2
358 363 ip.user_ns['nonascii2'] = nonascii2
359 364 ip._inspect('pinfo', 'nonascii2', detail_level=1)
360 365
361 366
362 367 def test_pinfo_docstring_no_source():
363 368 """Docstring should be included with detail_level=1 if there is no source"""
364 369 with AssertPrints('Docstring:'):
365 370 ip._inspect('pinfo', 'str.format', detail_level=0)
366 371 with AssertPrints('Docstring:'):
367 372 ip._inspect('pinfo', 'str.format', detail_level=1)
368 373
369 374
370 375 def test_pinfo_no_docstring_if_source():
371 376 """Docstring should not be included with detail_level=1 if source is found"""
372 377 def foo():
373 378 """foo has a docstring"""
374 379
375 380 ip.user_ns['foo'] = foo
376 381
377 382 with AssertPrints('Docstring:'):
378 383 ip._inspect('pinfo', 'foo', detail_level=0)
379 384 with AssertPrints('Source:'):
380 385 ip._inspect('pinfo', 'foo', detail_level=1)
381 386 with AssertNotPrints('Docstring:'):
382 387 ip._inspect('pinfo', 'foo', detail_level=1)
383 388
384 389
385 390 def test_pinfo_docstring_if_detail_and_no_source():
386 391 """ Docstring should be displayed if source info not available """
387 392 obj_def = '''class Foo(object):
388 393 """ This is a docstring for Foo """
389 394 def bar(self):
390 395 """ This is a docstring for Foo.bar """
391 396 pass
392 397 '''
393 398
394 399 ip.run_cell(obj_def)
395 400 ip.run_cell('foo = Foo()')
396 401
397 402 with AssertNotPrints("Source:"):
398 403 with AssertPrints('Docstring:'):
399 404 ip._inspect('pinfo', 'foo', detail_level=0)
400 405 with AssertPrints('Docstring:'):
401 406 ip._inspect('pinfo', 'foo', detail_level=1)
402 407 with AssertPrints('Docstring:'):
403 408 ip._inspect('pinfo', 'foo.bar', detail_level=0)
404 409
405 410 with AssertNotPrints('Docstring:'):
406 411 with AssertPrints('Source:'):
407 412 ip._inspect('pinfo', 'foo.bar', detail_level=1)
408 413
409 414
410 415 def test_pinfo_magic():
411 416 with AssertPrints('Docstring:'):
412 417 ip._inspect('pinfo', 'lsmagic', detail_level=0)
413 418
414 419 with AssertPrints('Source:'):
415 420 ip._inspect('pinfo', 'lsmagic', detail_level=1)
416 421
417 422
418 423 def test_init_colors():
419 424 # ensure colors are not present in signature info
420 425 info = inspector.info(HasSignature)
421 426 init_def = info['init_definition']
422 427 nt.assert_not_in('[0m', init_def)
423 428
424 429
425 430 def test_builtin_init():
426 431 info = inspector.info(list)
427 432 init_def = info['init_definition']
428 433 # Python < 3.4 can't get init definition from builtins,
429 434 # but still exercise the inspection in case of error-raising bugs.
430 435 if sys.version_info >= (3,4):
431 436 nt.assert_is_not_none(init_def)
432 437
@@ -1,867 +1,871
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 Python advanced pretty printer. This pretty printer is intended to
4 4 replace the old `pprint` python module which does not allow developers
5 5 to provide their own pretty print callbacks.
6 6
7 7 This module is based on ruby's `prettyprint.rb` library by `Tanaka Akira`.
8 8
9 9
10 10 Example Usage
11 11 -------------
12 12
13 13 To directly print the representation of an object use `pprint`::
14 14
15 15 from pretty import pprint
16 16 pprint(complex_object)
17 17
18 18 To get a string of the output use `pretty`::
19 19
20 20 from pretty import pretty
21 21 string = pretty(complex_object)
22 22
23 23
24 24 Extending
25 25 ---------
26 26
27 27 The pretty library allows developers to add pretty printing rules for their
28 28 own objects. This process is straightforward. All you have to do is to
29 29 add a `_repr_pretty_` method to your object and call the methods on the
30 30 pretty printer passed::
31 31
32 32 class MyObject(object):
33 33
34 34 def _repr_pretty_(self, p, cycle):
35 35 ...
36 36
37 37 Here is an example implementation of a `_repr_pretty_` method for a list
38 38 subclass::
39 39
40 40 class MyList(list):
41 41
42 42 def _repr_pretty_(self, p, cycle):
43 43 if cycle:
44 44 p.text('MyList(...)')
45 45 else:
46 46 with p.group(8, 'MyList([', '])'):
47 47 for idx, item in enumerate(self):
48 48 if idx:
49 49 p.text(',')
50 50 p.breakable()
51 51 p.pretty(item)
52 52
53 53 The `cycle` parameter is `True` if pretty detected a cycle. You *have* to
54 54 react to that or the result is an infinite loop. `p.text()` just adds
55 55 non breaking text to the output, `p.breakable()` either adds a whitespace
56 56 or breaks here. If you pass it an argument it's used instead of the
57 57 default space. `p.pretty` prettyprints another object using the pretty print
58 58 method.
59 59
60 60 The first parameter to the `group` function specifies the extra indentation
61 61 of the next line. In this example the next item will either be on the same
62 62 line (if the items are short enough) or aligned with the right edge of the
63 63 opening bracket of `MyList`.
64 64
65 65 If you just want to indent something you can use the group function
66 66 without open / close parameters. You can also use this code::
67 67
68 68 with p.indent(2):
69 69 ...
70 70
71 71 Inheritance diagram:
72 72
73 73 .. inheritance-diagram:: IPython.lib.pretty
74 74 :parts: 3
75 75
76 76 :copyright: 2007 by Armin Ronacher.
77 77 Portions (c) 2009 by Robert Kern.
78 78 :license: BSD License.
79 79 """
80 80 from contextlib import contextmanager
81 81 import sys
82 82 import types
83 83 import re
84 84 import datetime
85 85 from collections import deque
86 86 from io import StringIO
87 87 from warnings import warn
88 88
89 89 from IPython.utils.decorators import undoc
90 90 from IPython.utils.py3compat import PYPY
91
91 from IPython.utils.signatures import signature
92 92
93 93 __all__ = ['pretty', 'pprint', 'PrettyPrinter', 'RepresentationPrinter',
94 94 'for_type', 'for_type_by_name']
95 95
96 96
97 97 MAX_SEQ_LENGTH = 1000
98 98 _re_pattern_type = type(re.compile(''))
99 99
100 100 def _safe_getattr(obj, attr, default=None):
101 101 """Safe version of getattr.
102 102
103 103 Same as getattr, but will return ``default`` on any Exception,
104 104 rather than raising.
105 105 """
106 106 try:
107 107 return getattr(obj, attr, default)
108 108 except Exception:
109 109 return default
110 110
111 111 @undoc
112 112 class CUnicodeIO(StringIO):
113 113 def __init__(self, *args, **kwargs):
114 114 super().__init__(*args, **kwargs)
115 115 warn(("CUnicodeIO is deprecated since IPython 6.0. "
116 116 "Please use io.StringIO instead."),
117 117 DeprecationWarning, stacklevel=2)
118 118
119 119 def _sorted_for_pprint(items):
120 120 """
121 121 Sort the given items for pretty printing. Since some predictable
122 122 sorting is better than no sorting at all, we sort on the string
123 123 representation if normal sorting fails.
124 124 """
125 125 items = list(items)
126 126 try:
127 127 return sorted(items)
128 128 except Exception:
129 129 try:
130 130 return sorted(items, key=str)
131 131 except Exception:
132 132 return items
133 133
134 134 def pretty(obj, verbose=False, max_width=79, newline='\n', max_seq_length=MAX_SEQ_LENGTH):
135 135 """
136 136 Pretty print the object's representation.
137 137 """
138 138 stream = StringIO()
139 139 printer = RepresentationPrinter(stream, verbose, max_width, newline, max_seq_length=max_seq_length)
140 140 printer.pretty(obj)
141 141 printer.flush()
142 142 return stream.getvalue()
143 143
144 144
145 145 def pprint(obj, verbose=False, max_width=79, newline='\n', max_seq_length=MAX_SEQ_LENGTH):
146 146 """
147 147 Like `pretty` but print to stdout.
148 148 """
149 149 printer = RepresentationPrinter(sys.stdout, verbose, max_width, newline, max_seq_length=max_seq_length)
150 150 printer.pretty(obj)
151 151 printer.flush()
152 152 sys.stdout.write(newline)
153 153 sys.stdout.flush()
154 154
155 155 class _PrettyPrinterBase(object):
156 156
157 157 @contextmanager
158 158 def indent(self, indent):
159 159 """with statement support for indenting/dedenting."""
160 160 self.indentation += indent
161 161 try:
162 162 yield
163 163 finally:
164 164 self.indentation -= indent
165 165
166 166 @contextmanager
167 167 def group(self, indent=0, open='', close=''):
168 168 """like begin_group / end_group but for the with statement."""
169 169 self.begin_group(indent, open)
170 170 try:
171 171 yield
172 172 finally:
173 173 self.end_group(indent, close)
174 174
175 175 class PrettyPrinter(_PrettyPrinterBase):
176 176 """
177 177 Baseclass for the `RepresentationPrinter` prettyprinter that is used to
178 178 generate pretty reprs of objects. Contrary to the `RepresentationPrinter`
179 179 this printer knows nothing about the default pprinters or the `_repr_pretty_`
180 180 callback method.
181 181 """
182 182
183 183 def __init__(self, output, max_width=79, newline='\n', max_seq_length=MAX_SEQ_LENGTH):
184 184 self.output = output
185 185 self.max_width = max_width
186 186 self.newline = newline
187 187 self.max_seq_length = max_seq_length
188 188 self.output_width = 0
189 189 self.buffer_width = 0
190 190 self.buffer = deque()
191 191
192 192 root_group = Group(0)
193 193 self.group_stack = [root_group]
194 194 self.group_queue = GroupQueue(root_group)
195 195 self.indentation = 0
196 196
197 197 def _break_outer_groups(self):
198 198 while self.max_width < self.output_width + self.buffer_width:
199 199 group = self.group_queue.deq()
200 200 if not group:
201 201 return
202 202 while group.breakables:
203 203 x = self.buffer.popleft()
204 204 self.output_width = x.output(self.output, self.output_width)
205 205 self.buffer_width -= x.width
206 206 while self.buffer and isinstance(self.buffer[0], Text):
207 207 x = self.buffer.popleft()
208 208 self.output_width = x.output(self.output, self.output_width)
209 209 self.buffer_width -= x.width
210 210
211 211 def text(self, obj):
212 212 """Add literal text to the output."""
213 213 width = len(obj)
214 214 if self.buffer:
215 215 text = self.buffer[-1]
216 216 if not isinstance(text, Text):
217 217 text = Text()
218 218 self.buffer.append(text)
219 219 text.add(obj, width)
220 220 self.buffer_width += width
221 221 self._break_outer_groups()
222 222 else:
223 223 self.output.write(obj)
224 224 self.output_width += width
225 225
226 226 def breakable(self, sep=' '):
227 227 """
228 228 Add a breakable separator to the output. This does not mean that it
229 229 will automatically break here. If no breaking on this position takes
230 230 place the `sep` is inserted which default to one space.
231 231 """
232 232 width = len(sep)
233 233 group = self.group_stack[-1]
234 234 if group.want_break:
235 235 self.flush()
236 236 self.output.write(self.newline)
237 237 self.output.write(' ' * self.indentation)
238 238 self.output_width = self.indentation
239 239 self.buffer_width = 0
240 240 else:
241 241 self.buffer.append(Breakable(sep, width, self))
242 242 self.buffer_width += width
243 243 self._break_outer_groups()
244 244
245 245 def break_(self):
246 246 """
247 247 Explicitly insert a newline into the output, maintaining correct indentation.
248 248 """
249 249 self.flush()
250 250 self.output.write(self.newline)
251 251 self.output.write(' ' * self.indentation)
252 252 self.output_width = self.indentation
253 253 self.buffer_width = 0
254 254
255 255
256 256 def begin_group(self, indent=0, open=''):
257 257 """
258 258 Begin a group. If you want support for python < 2.5 which doesn't has
259 259 the with statement this is the preferred way:
260 260
261 261 p.begin_group(1, '{')
262 262 ...
263 263 p.end_group(1, '}')
264 264
265 265 The python 2.5 expression would be this:
266 266
267 267 with p.group(1, '{', '}'):
268 268 ...
269 269
270 270 The first parameter specifies the indentation for the next line (usually
271 271 the width of the opening text), the second the opening text. All
272 272 parameters are optional.
273 273 """
274 274 if open:
275 275 self.text(open)
276 276 group = Group(self.group_stack[-1].depth + 1)
277 277 self.group_stack.append(group)
278 278 self.group_queue.enq(group)
279 279 self.indentation += indent
280 280
281 281 def _enumerate(self, seq):
282 282 """like enumerate, but with an upper limit on the number of items"""
283 283 for idx, x in enumerate(seq):
284 284 if self.max_seq_length and idx >= self.max_seq_length:
285 285 self.text(',')
286 286 self.breakable()
287 287 self.text('...')
288 288 return
289 289 yield idx, x
290 290
291 291 def end_group(self, dedent=0, close=''):
292 292 """End a group. See `begin_group` for more details."""
293 293 self.indentation -= dedent
294 294 group = self.group_stack.pop()
295 295 if not group.breakables:
296 296 self.group_queue.remove(group)
297 297 if close:
298 298 self.text(close)
299 299
300 300 def flush(self):
301 301 """Flush data that is left in the buffer."""
302 302 for data in self.buffer:
303 303 self.output_width += data.output(self.output, self.output_width)
304 304 self.buffer.clear()
305 305 self.buffer_width = 0
306 306
307 307
308 308 def _get_mro(obj_class):
309 309 """ Get a reasonable method resolution order of a class and its superclasses
310 310 for both old-style and new-style classes.
311 311 """
312 312 if not hasattr(obj_class, '__mro__'):
313 313 # Old-style class. Mix in object to make a fake new-style class.
314 314 try:
315 315 obj_class = type(obj_class.__name__, (obj_class, object), {})
316 316 except TypeError:
317 317 # Old-style extension type that does not descend from object.
318 318 # FIXME: try to construct a more thorough MRO.
319 319 mro = [obj_class]
320 320 else:
321 321 mro = obj_class.__mro__[1:-1]
322 322 else:
323 323 mro = obj_class.__mro__
324 324 return mro
325 325
326 326
327 327 class RepresentationPrinter(PrettyPrinter):
328 328 """
329 329 Special pretty printer that has a `pretty` method that calls the pretty
330 330 printer for a python object.
331 331
332 332 This class stores processing data on `self` so you must *never* use
333 333 this class in a threaded environment. Always lock it or reinstanciate
334 334 it.
335 335
336 336 Instances also have a verbose flag callbacks can access to control their
337 337 output. For example the default instance repr prints all attributes and
338 338 methods that are not prefixed by an underscore if the printer is in
339 339 verbose mode.
340 340 """
341 341
342 342 def __init__(self, output, verbose=False, max_width=79, newline='\n',
343 343 singleton_pprinters=None, type_pprinters=None, deferred_pprinters=None,
344 344 max_seq_length=MAX_SEQ_LENGTH):
345 345
346 346 PrettyPrinter.__init__(self, output, max_width, newline, max_seq_length=max_seq_length)
347 347 self.verbose = verbose
348 348 self.stack = []
349 349 if singleton_pprinters is None:
350 350 singleton_pprinters = _singleton_pprinters.copy()
351 351 self.singleton_pprinters = singleton_pprinters
352 352 if type_pprinters is None:
353 353 type_pprinters = _type_pprinters.copy()
354 354 self.type_pprinters = type_pprinters
355 355 if deferred_pprinters is None:
356 356 deferred_pprinters = _deferred_type_pprinters.copy()
357 357 self.deferred_pprinters = deferred_pprinters
358 358
359 359 def pretty(self, obj):
360 360 """Pretty print the given object."""
361 361 obj_id = id(obj)
362 362 cycle = obj_id in self.stack
363 363 self.stack.append(obj_id)
364 364 self.begin_group()
365 365 try:
366 366 obj_class = _safe_getattr(obj, '__class__', None) or type(obj)
367 367 # First try to find registered singleton printers for the type.
368 368 try:
369 369 printer = self.singleton_pprinters[obj_id]
370 370 except (TypeError, KeyError):
371 371 pass
372 372 else:
373 373 return printer(obj, self, cycle)
374 374 # Next walk the mro and check for either:
375 375 # 1) a registered printer
376 376 # 2) a _repr_pretty_ method
377 377 for cls in _get_mro(obj_class):
378 378 if cls in self.type_pprinters:
379 379 # printer registered in self.type_pprinters
380 380 return self.type_pprinters[cls](obj, self, cycle)
381 381 else:
382 382 # deferred printer
383 383 printer = self._in_deferred_types(cls)
384 384 if printer is not None:
385 385 return printer(obj, self, cycle)
386 386 else:
387 387 # Finally look for special method names.
388 388 # Some objects automatically create any requested
389 389 # attribute. Try to ignore most of them by checking for
390 390 # callability.
391 391 if '_repr_pretty_' in cls.__dict__:
392 392 meth = cls._repr_pretty_
393 393 if callable(meth):
394 394 return meth(obj, self, cycle)
395 395 return _default_pprint(obj, self, cycle)
396 396 finally:
397 397 self.end_group()
398 398 self.stack.pop()
399 399
400 400 def _in_deferred_types(self, cls):
401 401 """
402 402 Check if the given class is specified in the deferred type registry.
403 403
404 404 Returns the printer from the registry if it exists, and None if the
405 405 class is not in the registry. Successful matches will be moved to the
406 406 regular type registry for future use.
407 407 """
408 408 mod = _safe_getattr(cls, '__module__', None)
409 409 name = _safe_getattr(cls, '__name__', None)
410 410 key = (mod, name)
411 411 printer = None
412 412 if key in self.deferred_pprinters:
413 413 # Move the printer over to the regular registry.
414 414 printer = self.deferred_pprinters.pop(key)
415 415 self.type_pprinters[cls] = printer
416 416 return printer
417 417
418 418
419 419 class Printable(object):
420 420
421 421 def output(self, stream, output_width):
422 422 return output_width
423 423
424 424
425 425 class Text(Printable):
426 426
427 427 def __init__(self):
428 428 self.objs = []
429 429 self.width = 0
430 430
431 431 def output(self, stream, output_width):
432 432 for obj in self.objs:
433 433 stream.write(obj)
434 434 return output_width + self.width
435 435
436 436 def add(self, obj, width):
437 437 self.objs.append(obj)
438 438 self.width += width
439 439
440 440
441 441 class Breakable(Printable):
442 442
443 443 def __init__(self, seq, width, pretty):
444 444 self.obj = seq
445 445 self.width = width
446 446 self.pretty = pretty
447 447 self.indentation = pretty.indentation
448 448 self.group = pretty.group_stack[-1]
449 449 self.group.breakables.append(self)
450 450
451 451 def output(self, stream, output_width):
452 452 self.group.breakables.popleft()
453 453 if self.group.want_break:
454 454 stream.write(self.pretty.newline)
455 455 stream.write(' ' * self.indentation)
456 456 return self.indentation
457 457 if not self.group.breakables:
458 458 self.pretty.group_queue.remove(self.group)
459 459 stream.write(self.obj)
460 460 return output_width + self.width
461 461
462 462
463 463 class Group(Printable):
464 464
465 465 def __init__(self, depth):
466 466 self.depth = depth
467 467 self.breakables = deque()
468 468 self.want_break = False
469 469
470 470
471 471 class GroupQueue(object):
472 472
473 473 def __init__(self, *groups):
474 474 self.queue = []
475 475 for group in groups:
476 476 self.enq(group)
477 477
478 478 def enq(self, group):
479 479 depth = group.depth
480 480 while depth > len(self.queue) - 1:
481 481 self.queue.append([])
482 482 self.queue[depth].append(group)
483 483
484 484 def deq(self):
485 485 for stack in self.queue:
486 486 for idx, group in enumerate(reversed(stack)):
487 487 if group.breakables:
488 488 del stack[idx]
489 489 group.want_break = True
490 490 return group
491 491 for group in stack:
492 492 group.want_break = True
493 493 del stack[:]
494 494
495 495 def remove(self, group):
496 496 try:
497 497 self.queue[group.depth].remove(group)
498 498 except ValueError:
499 499 pass
500 500
501 501
502 502 def _default_pprint(obj, p, cycle):
503 503 """
504 504 The default print function. Used if an object does not provide one and
505 505 it's none of the builtin objects.
506 506 """
507 507 klass = _safe_getattr(obj, '__class__', None) or type(obj)
508 508 if _safe_getattr(klass, '__repr__', None) is not object.__repr__:
509 509 # A user-provided repr. Find newlines and replace them with p.break_()
510 510 _repr_pprint(obj, p, cycle)
511 511 return
512 512 p.begin_group(1, '<')
513 513 p.pretty(klass)
514 514 p.text(' at 0x%x' % id(obj))
515 515 if cycle:
516 516 p.text(' ...')
517 517 elif p.verbose:
518 518 first = True
519 519 for key in dir(obj):
520 520 if not key.startswith('_'):
521 521 try:
522 522 value = getattr(obj, key)
523 523 except AttributeError:
524 524 continue
525 525 if isinstance(value, types.MethodType):
526 526 continue
527 527 if not first:
528 528 p.text(',')
529 529 p.breakable()
530 530 p.text(key)
531 531 p.text('=')
532 532 step = len(key) + 1
533 533 p.indentation += step
534 534 p.pretty(value)
535 535 p.indentation -= step
536 536 first = False
537 537 p.end_group(1, '>')
538 538
539 539
540 540 def _seq_pprinter_factory(start, end, basetype):
541 541 """
542 542 Factory that returns a pprint function useful for sequences. Used by
543 543 the default pprint for tuples, dicts, and lists.
544 544 """
545 545 def inner(obj, p, cycle):
546 546 typ = type(obj)
547 547 if basetype is not None and typ is not basetype and typ.__repr__ != basetype.__repr__:
548 548 # If the subclass provides its own repr, use it instead.
549 549 return p.text(typ.__repr__(obj))
550 550
551 551 if cycle:
552 552 return p.text(start + '...' + end)
553 553 step = len(start)
554 554 p.begin_group(step, start)
555 555 for idx, x in p._enumerate(obj):
556 556 if idx:
557 557 p.text(',')
558 558 p.breakable()
559 559 p.pretty(x)
560 560 if len(obj) == 1 and type(obj) is tuple:
561 561 # Special case for 1-item tuples.
562 562 p.text(',')
563 563 p.end_group(step, end)
564 564 return inner
565 565
566 566
567 567 def _set_pprinter_factory(start, end, basetype):
568 568 """
569 569 Factory that returns a pprint function useful for sets and frozensets.
570 570 """
571 571 def inner(obj, p, cycle):
572 572 typ = type(obj)
573 573 if basetype is not None and typ is not basetype and typ.__repr__ != basetype.__repr__:
574 574 # If the subclass provides its own repr, use it instead.
575 575 return p.text(typ.__repr__(obj))
576 576
577 577 if cycle:
578 578 return p.text(start + '...' + end)
579 579 if len(obj) == 0:
580 580 # Special case.
581 581 p.text(basetype.__name__ + '()')
582 582 else:
583 583 step = len(start)
584 584 p.begin_group(step, start)
585 585 # Like dictionary keys, we will try to sort the items if there aren't too many
586 586 if not (p.max_seq_length and len(obj) >= p.max_seq_length):
587 587 items = _sorted_for_pprint(obj)
588 588 else:
589 589 items = obj
590 590 for idx, x in p._enumerate(items):
591 591 if idx:
592 592 p.text(',')
593 593 p.breakable()
594 594 p.pretty(x)
595 595 p.end_group(step, end)
596 596 return inner
597 597
598 598
599 599 def _dict_pprinter_factory(start, end, basetype=None):
600 600 """
601 601 Factory that returns a pprint function used by the default pprint of
602 602 dicts and dict proxies.
603 603 """
604 604 def inner(obj, p, cycle):
605 605 typ = type(obj)
606 606 if basetype is not None and typ is not basetype and typ.__repr__ != basetype.__repr__:
607 607 # If the subclass provides its own repr, use it instead.
608 608 return p.text(typ.__repr__(obj))
609 609
610 610 if cycle:
611 611 return p.text('{...}')
612 612 step = len(start)
613 613 p.begin_group(step, start)
614 614 keys = obj.keys()
615 615 # if dict isn't large enough to be truncated, sort keys before displaying
616 616 if not (p.max_seq_length and len(obj) >= p.max_seq_length):
617 617 keys = _sorted_for_pprint(keys)
618 618 for idx, key in p._enumerate(keys):
619 619 if idx:
620 620 p.text(',')
621 621 p.breakable()
622 622 p.pretty(key)
623 623 p.text(': ')
624 624 p.pretty(obj[key])
625 625 p.end_group(step, end)
626 626 return inner
627 627
628 628
629 629 def _super_pprint(obj, p, cycle):
630 630 """The pprint for the super type."""
631 631 p.begin_group(8, '<super: ')
632 632 p.pretty(obj.__thisclass__)
633 633 p.text(',')
634 634 p.breakable()
635 635 if PYPY: # In PyPy, super() objects don't have __self__ attributes
636 636 dself = obj.__repr__.__self__
637 637 p.pretty(None if dself is obj else dself)
638 638 else:
639 639 p.pretty(obj.__self__)
640 640 p.end_group(8, '>')
641 641
642 642
643 643 def _re_pattern_pprint(obj, p, cycle):
644 644 """The pprint function for regular expression patterns."""
645 645 p.text('re.compile(')
646 646 pattern = repr(obj.pattern)
647 647 if pattern[:1] in 'uU':
648 648 pattern = pattern[1:]
649 649 prefix = 'ur'
650 650 else:
651 651 prefix = 'r'
652 652 pattern = prefix + pattern.replace('\\\\', '\\')
653 653 p.text(pattern)
654 654 if obj.flags:
655 655 p.text(',')
656 656 p.breakable()
657 657 done_one = False
658 658 for flag in ('TEMPLATE', 'IGNORECASE', 'LOCALE', 'MULTILINE', 'DOTALL',
659 659 'UNICODE', 'VERBOSE', 'DEBUG'):
660 660 if obj.flags & getattr(re, flag):
661 661 if done_one:
662 662 p.text('|')
663 663 p.text('re.' + flag)
664 664 done_one = True
665 665 p.text(')')
666 666
667 667
668 668 def _type_pprint(obj, p, cycle):
669 669 """The pprint for classes and types."""
670 670 # Heap allocated types might not have the module attribute,
671 671 # and others may set it to None.
672 672
673 673 # Checks for a __repr__ override in the metaclass. Can't compare the
674 674 # type(obj).__repr__ directly because in PyPy the representation function
675 675 # inherited from type isn't the same type.__repr__
676 676 if [m for m in _get_mro(type(obj)) if "__repr__" in vars(m)][:1] != [type]:
677 677 _repr_pprint(obj, p, cycle)
678 678 return
679 679
680 680 mod = _safe_getattr(obj, '__module__', None)
681 681 try:
682 682 name = obj.__qualname__
683 683 if not isinstance(name, str):
684 684 # This can happen if the type implements __qualname__ as a property
685 685 # or other descriptor in Python 2.
686 686 raise Exception("Try __name__")
687 687 except Exception:
688 688 name = obj.__name__
689 689 if not isinstance(name, str):
690 690 name = '<unknown type>'
691 691
692 692 if mod in (None, '__builtin__', 'builtins', 'exceptions'):
693 693 p.text(name)
694 694 else:
695 695 p.text(mod + '.' + name)
696 696
697 697
698 698 def _repr_pprint(obj, p, cycle):
699 699 """A pprint that just redirects to the normal repr function."""
700 700 # Find newlines and replace them with p.break_()
701 701 output = repr(obj)
702 702 for idx,output_line in enumerate(output.splitlines()):
703 703 if idx:
704 704 p.break_()
705 705 p.text(output_line)
706 706
707 707
708 708 def _function_pprint(obj, p, cycle):
709 709 """Base pprint for all functions and builtin functions."""
710 710 name = _safe_getattr(obj, '__qualname__', obj.__name__)
711 711 mod = obj.__module__
712 712 if mod and mod not in ('__builtin__', 'builtins', 'exceptions'):
713 713 name = mod + '.' + name
714 p.text('<function %s>' % name)
714 try:
715 func_def = name + str(signature(obj))
716 except ValueError:
717 func_def = name
718 p.text('<function %s>' % func_def)
715 719
716 720
717 721 def _exception_pprint(obj, p, cycle):
718 722 """Base pprint for all exceptions."""
719 723 name = getattr(obj.__class__, '__qualname__', obj.__class__.__name__)
720 724 if obj.__class__.__module__ not in ('exceptions', 'builtins'):
721 725 name = '%s.%s' % (obj.__class__.__module__, name)
722 726 step = len(name) + 1
723 727 p.begin_group(step, name + '(')
724 728 for idx, arg in enumerate(getattr(obj, 'args', ())):
725 729 if idx:
726 730 p.text(',')
727 731 p.breakable()
728 732 p.pretty(arg)
729 733 p.end_group(step, ')')
730 734
731 735
732 736 #: the exception base
733 737 try:
734 738 _exception_base = BaseException
735 739 except NameError:
736 740 _exception_base = Exception
737 741
738 742
739 743 #: printers for builtin types
740 744 _type_pprinters = {
741 745 int: _repr_pprint,
742 746 float: _repr_pprint,
743 747 str: _repr_pprint,
744 748 tuple: _seq_pprinter_factory('(', ')', tuple),
745 749 list: _seq_pprinter_factory('[', ']', list),
746 750 dict: _dict_pprinter_factory('{', '}', dict),
747 751
748 752 set: _set_pprinter_factory('{', '}', set),
749 753 frozenset: _set_pprinter_factory('frozenset({', '})', frozenset),
750 754 super: _super_pprint,
751 755 _re_pattern_type: _re_pattern_pprint,
752 756 type: _type_pprint,
753 757 types.FunctionType: _function_pprint,
754 758 types.BuiltinFunctionType: _function_pprint,
755 759 types.MethodType: _repr_pprint,
756 760
757 761 datetime.datetime: _repr_pprint,
758 762 datetime.timedelta: _repr_pprint,
759 763 _exception_base: _exception_pprint
760 764 }
761 765
762 766 try:
763 767 # In PyPy, types.DictProxyType is dict, setting the dictproxy printer
764 768 # using dict.setdefault avoids overwritting the dict printer
765 769 _type_pprinters.setdefault(types.DictProxyType,
766 770 _dict_pprinter_factory('dict_proxy({', '})'))
767 771 _type_pprinters[types.ClassType] = _type_pprint
768 772 _type_pprinters[types.SliceType] = _repr_pprint
769 773 except AttributeError: # Python 3
770 774 _type_pprinters[types.MappingProxyType] = \
771 775 _dict_pprinter_factory('mappingproxy({', '})')
772 776 _type_pprinters[slice] = _repr_pprint
773 777
774 778 try:
775 779 _type_pprinters[long] = _repr_pprint
776 780 _type_pprinters[unicode] = _repr_pprint
777 781 except NameError:
778 782 _type_pprinters[range] = _repr_pprint
779 783 _type_pprinters[bytes] = _repr_pprint
780 784
781 785 #: printers for types specified by name
782 786 _deferred_type_pprinters = {
783 787 }
784 788
785 789 def for_type(typ, func):
786 790 """
787 791 Add a pretty printer for a given type.
788 792 """
789 793 oldfunc = _type_pprinters.get(typ, None)
790 794 if func is not None:
791 795 # To support easy restoration of old pprinters, we need to ignore Nones.
792 796 _type_pprinters[typ] = func
793 797 return oldfunc
794 798
795 799 def for_type_by_name(type_module, type_name, func):
796 800 """
797 801 Add a pretty printer for a type specified by the module and name of a type
798 802 rather than the type object itself.
799 803 """
800 804 key = (type_module, type_name)
801 805 oldfunc = _deferred_type_pprinters.get(key, None)
802 806 if func is not None:
803 807 # To support easy restoration of old pprinters, we need to ignore Nones.
804 808 _deferred_type_pprinters[key] = func
805 809 return oldfunc
806 810
807 811
808 812 #: printers for the default singletons
809 813 _singleton_pprinters = dict.fromkeys(map(id, [None, True, False, Ellipsis,
810 814 NotImplemented]), _repr_pprint)
811 815
812 816
813 817 def _defaultdict_pprint(obj, p, cycle):
814 818 name = obj.__class__.__name__
815 819 with p.group(len(name) + 1, name + '(', ')'):
816 820 if cycle:
817 821 p.text('...')
818 822 else:
819 823 p.pretty(obj.default_factory)
820 824 p.text(',')
821 825 p.breakable()
822 826 p.pretty(dict(obj))
823 827
824 828 def _ordereddict_pprint(obj, p, cycle):
825 829 name = obj.__class__.__name__
826 830 with p.group(len(name) + 1, name + '(', ')'):
827 831 if cycle:
828 832 p.text('...')
829 833 elif len(obj):
830 834 p.pretty(list(obj.items()))
831 835
832 836 def _deque_pprint(obj, p, cycle):
833 837 name = obj.__class__.__name__
834 838 with p.group(len(name) + 1, name + '(', ')'):
835 839 if cycle:
836 840 p.text('...')
837 841 else:
838 842 p.pretty(list(obj))
839 843
840 844
841 845 def _counter_pprint(obj, p, cycle):
842 846 name = obj.__class__.__name__
843 847 with p.group(len(name) + 1, name + '(', ')'):
844 848 if cycle:
845 849 p.text('...')
846 850 elif len(obj):
847 851 p.pretty(dict(obj))
848 852
849 853 for_type_by_name('collections', 'defaultdict', _defaultdict_pprint)
850 854 for_type_by_name('collections', 'OrderedDict', _ordereddict_pprint)
851 855 for_type_by_name('collections', 'deque', _deque_pprint)
852 856 for_type_by_name('collections', 'Counter', _counter_pprint)
853 857
854 858 if __name__ == '__main__':
855 859 from random import randrange
856 860 class Foo(object):
857 861 def __init__(self):
858 862 self.foo = 1
859 863 self.bar = re.compile(r'\s+')
860 864 self.blub = dict.fromkeys(range(30), randrange(1, 40))
861 865 self.hehe = 23424.234234
862 866 self.list = ["blub", "blah", self]
863 867
864 868 def get_foo(self):
865 869 print("foo")
866 870
867 871 pprint(Foo(), verbose=True)
@@ -1,407 +1,423
1 1 # coding: utf-8
2 2 """Tests for IPython.lib.pretty."""
3 3
4 4 # Copyright (c) IPython Development Team.
5 5 # Distributed under the terms of the Modified BSD License.
6 6
7 7
8 8 from collections import Counter, defaultdict, deque, OrderedDict
9 9 import types
10 10 import string
11 11 import unittest
12 12
13 13 import nose.tools as nt
14 14
15 15 from IPython.lib import pretty
16 16 from IPython.testing.decorators import skip_without
17 17
18 18 from io import StringIO
19 19
20 20
21 21 class MyList(object):
22 22 def __init__(self, content):
23 23 self.content = content
24 24 def _repr_pretty_(self, p, cycle):
25 25 if cycle:
26 26 p.text("MyList(...)")
27 27 else:
28 28 with p.group(3, "MyList(", ")"):
29 29 for (i, child) in enumerate(self.content):
30 30 if i:
31 31 p.text(",")
32 32 p.breakable()
33 33 else:
34 34 p.breakable("")
35 35 p.pretty(child)
36 36
37 37
38 38 class MyDict(dict):
39 39 def _repr_pretty_(self, p, cycle):
40 40 p.text("MyDict(...)")
41 41
42 42 class MyObj(object):
43 43 def somemethod(self):
44 44 pass
45 45
46 46
47 47 class Dummy1(object):
48 48 def _repr_pretty_(self, p, cycle):
49 49 p.text("Dummy1(...)")
50 50
51 51 class Dummy2(Dummy1):
52 52 _repr_pretty_ = None
53 53
54 54 class NoModule(object):
55 55 pass
56 56
57 57 NoModule.__module__ = None
58 58
59 59 class Breaking(object):
60 60 def _repr_pretty_(self, p, cycle):
61 61 with p.group(4,"TG: ",":"):
62 62 p.text("Breaking(")
63 63 p.break_()
64 64 p.text(")")
65 65
66 66 class BreakingRepr(object):
67 67 def __repr__(self):
68 68 return "Breaking(\n)"
69 69
70 70 class BreakingReprParent(object):
71 71 def _repr_pretty_(self, p, cycle):
72 72 with p.group(4,"TG: ",":"):
73 73 p.pretty(BreakingRepr())
74 74
75 75 class BadRepr(object):
76 76
77 77 def __repr__(self):
78 78 return 1/0
79 79
80 80
81 81 def test_indentation():
82 82 """Test correct indentation in groups"""
83 83 count = 40
84 84 gotoutput = pretty.pretty(MyList(range(count)))
85 85 expectedoutput = "MyList(\n" + ",\n".join(" %d" % i for i in range(count)) + ")"
86 86
87 87 nt.assert_equal(gotoutput, expectedoutput)
88 88
89 89
90 90 def test_dispatch():
91 91 """
92 92 Test correct dispatching: The _repr_pretty_ method for MyDict
93 93 must be found before the registered printer for dict.
94 94 """
95 95 gotoutput = pretty.pretty(MyDict())
96 96 expectedoutput = "MyDict(...)"
97 97
98 98 nt.assert_equal(gotoutput, expectedoutput)
99 99
100 100
101 101 def test_callability_checking():
102 102 """
103 103 Test that the _repr_pretty_ method is tested for callability and skipped if
104 104 not.
105 105 """
106 106 gotoutput = pretty.pretty(Dummy2())
107 107 expectedoutput = "Dummy1(...)"
108 108
109 109 nt.assert_equal(gotoutput, expectedoutput)
110 110
111 111
112 112 def test_sets():
113 113 """
114 114 Test that set and frozenset use Python 3 formatting.
115 115 """
116 116 objects = [set(), frozenset(), set([1]), frozenset([1]), set([1, 2]),
117 117 frozenset([1, 2]), set([-1, -2, -3])]
118 118 expected = ['set()', 'frozenset()', '{1}', 'frozenset({1})', '{1, 2}',
119 119 'frozenset({1, 2})', '{-3, -2, -1}']
120 120 for obj, expected_output in zip(objects, expected):
121 121 got_output = pretty.pretty(obj)
122 122 yield nt.assert_equal, got_output, expected_output
123 123
124 124
125 125 @skip_without('xxlimited')
126 126 def test_pprint_heap_allocated_type():
127 127 """
128 128 Test that pprint works for heap allocated types.
129 129 """
130 130 import xxlimited
131 131 output = pretty.pretty(xxlimited.Null)
132 132 nt.assert_equal(output, 'xxlimited.Null')
133 133
134 134 def test_pprint_nomod():
135 135 """
136 136 Test that pprint works for classes with no __module__.
137 137 """
138 138 output = pretty.pretty(NoModule)
139 139 nt.assert_equal(output, 'NoModule')
140 140
141 141 def test_pprint_break():
142 142 """
143 143 Test that p.break_ produces expected output
144 144 """
145 145 output = pretty.pretty(Breaking())
146 146 expected = "TG: Breaking(\n ):"
147 147 nt.assert_equal(output, expected)
148 148
149 149 def test_pprint_break_repr():
150 150 """
151 151 Test that p.break_ is used in repr
152 152 """
153 153 output = pretty.pretty(BreakingReprParent())
154 154 expected = "TG: Breaking(\n ):"
155 155 nt.assert_equal(output, expected)
156 156
157 157 def test_bad_repr():
158 158 """Don't catch bad repr errors"""
159 159 with nt.assert_raises(ZeroDivisionError):
160 160 pretty.pretty(BadRepr())
161 161
162 162 class BadException(Exception):
163 163 def __str__(self):
164 164 return -1
165 165
166 166 class ReallyBadRepr(object):
167 167 __module__ = 1
168 168 @property
169 169 def __class__(self):
170 170 raise ValueError("I am horrible")
171 171
172 172 def __repr__(self):
173 173 raise BadException()
174 174
175 175 def test_really_bad_repr():
176 176 with nt.assert_raises(BadException):
177 177 pretty.pretty(ReallyBadRepr())
178 178
179 179
180 180 class SA(object):
181 181 pass
182 182
183 183 class SB(SA):
184 184 pass
185 185
186 186 class TestsPretty(unittest.TestCase):
187 187
188 188 def test_super_repr(self):
189 189 # "<super: module_name.SA, None>"
190 190 output = pretty.pretty(super(SA))
191 191 self.assertRegex(output, r"<super: \S+.SA, None>")
192 192
193 193 # "<super: module_name.SA, <module_name.SB at 0x...>>"
194 194 sb = SB()
195 195 output = pretty.pretty(super(SA, sb))
196 196 self.assertRegex(output, r"<super: \S+.SA,\s+<\S+.SB at 0x\S+>>")
197 197
198 198
199 199 def test_long_list(self):
200 200 lis = list(range(10000))
201 201 p = pretty.pretty(lis)
202 202 last2 = p.rsplit('\n', 2)[-2:]
203 203 self.assertEqual(last2, [' 999,', ' ...]'])
204 204
205 205 def test_long_set(self):
206 206 s = set(range(10000))
207 207 p = pretty.pretty(s)
208 208 last2 = p.rsplit('\n', 2)[-2:]
209 209 self.assertEqual(last2, [' 999,', ' ...}'])
210 210
211 211 def test_long_tuple(self):
212 212 tup = tuple(range(10000))
213 213 p = pretty.pretty(tup)
214 214 last2 = p.rsplit('\n', 2)[-2:]
215 215 self.assertEqual(last2, [' 999,', ' ...)'])
216 216
217 217 def test_long_dict(self):
218 218 d = { n:n for n in range(10000) }
219 219 p = pretty.pretty(d)
220 220 last2 = p.rsplit('\n', 2)[-2:]
221 221 self.assertEqual(last2, [' 999: 999,', ' ...}'])
222 222
223 223 def test_unbound_method(self):
224 224 output = pretty.pretty(MyObj.somemethod)
225 225 self.assertIn('MyObj.somemethod', output)
226 226
227 227
228 228 class MetaClass(type):
229 229 def __new__(cls, name):
230 230 return type.__new__(cls, name, (object,), {'name': name})
231 231
232 232 def __repr__(self):
233 233 return "[CUSTOM REPR FOR CLASS %s]" % self.name
234 234
235 235
236 236 ClassWithMeta = MetaClass('ClassWithMeta')
237 237
238 238
239 239 def test_metaclass_repr():
240 240 output = pretty.pretty(ClassWithMeta)
241 241 nt.assert_equal(output, "[CUSTOM REPR FOR CLASS ClassWithMeta]")
242 242
243 243
244 244 def test_unicode_repr():
245 245 u = u"üniçodé"
246 246 ustr = u
247 247
248 248 class C(object):
249 249 def __repr__(self):
250 250 return ustr
251 251
252 252 c = C()
253 253 p = pretty.pretty(c)
254 254 nt.assert_equal(p, u)
255 255 p = pretty.pretty([c])
256 256 nt.assert_equal(p, u'[%s]' % u)
257 257
258 258
259 259 def test_basic_class():
260 260 def type_pprint_wrapper(obj, p, cycle):
261 261 if obj is MyObj:
262 262 type_pprint_wrapper.called = True
263 263 return pretty._type_pprint(obj, p, cycle)
264 264 type_pprint_wrapper.called = False
265 265
266 266 stream = StringIO()
267 267 printer = pretty.RepresentationPrinter(stream)
268 268 printer.type_pprinters[type] = type_pprint_wrapper
269 269 printer.pretty(MyObj)
270 270 printer.flush()
271 271 output = stream.getvalue()
272 272
273 273 nt.assert_equal(output, '%s.MyObj' % __name__)
274 274 nt.assert_true(type_pprint_wrapper.called)
275 275
276 276
277 277 def test_collections_defaultdict():
278 278 # Create defaultdicts with cycles
279 279 a = defaultdict()
280 280 a.default_factory = a
281 281 b = defaultdict(list)
282 282 b['key'] = b
283 283
284 284 # Dictionary order cannot be relied on, test against single keys.
285 285 cases = [
286 286 (defaultdict(list), 'defaultdict(list, {})'),
287 287 (defaultdict(list, {'key': '-' * 50}),
288 288 "defaultdict(list,\n"
289 289 " {'key': '--------------------------------------------------'})"),
290 290 (a, 'defaultdict(defaultdict(...), {})'),
291 291 (b, "defaultdict(list, {'key': defaultdict(...)})"),
292 292 ]
293 293 for obj, expected in cases:
294 294 nt.assert_equal(pretty.pretty(obj), expected)
295 295
296 296
297 297 def test_collections_ordereddict():
298 298 # Create OrderedDict with cycle
299 299 a = OrderedDict()
300 300 a['key'] = a
301 301
302 302 cases = [
303 303 (OrderedDict(), 'OrderedDict()'),
304 304 (OrderedDict((i, i) for i in range(1000, 1010)),
305 305 'OrderedDict([(1000, 1000),\n'
306 306 ' (1001, 1001),\n'
307 307 ' (1002, 1002),\n'
308 308 ' (1003, 1003),\n'
309 309 ' (1004, 1004),\n'
310 310 ' (1005, 1005),\n'
311 311 ' (1006, 1006),\n'
312 312 ' (1007, 1007),\n'
313 313 ' (1008, 1008),\n'
314 314 ' (1009, 1009)])'),
315 315 (a, "OrderedDict([('key', OrderedDict(...))])"),
316 316 ]
317 317 for obj, expected in cases:
318 318 nt.assert_equal(pretty.pretty(obj), expected)
319 319
320 320
321 321 def test_collections_deque():
322 322 # Create deque with cycle
323 323 a = deque()
324 324 a.append(a)
325 325
326 326 cases = [
327 327 (deque(), 'deque([])'),
328 328 (deque(i for i in range(1000, 1020)),
329 329 'deque([1000,\n'
330 330 ' 1001,\n'
331 331 ' 1002,\n'
332 332 ' 1003,\n'
333 333 ' 1004,\n'
334 334 ' 1005,\n'
335 335 ' 1006,\n'
336 336 ' 1007,\n'
337 337 ' 1008,\n'
338 338 ' 1009,\n'
339 339 ' 1010,\n'
340 340 ' 1011,\n'
341 341 ' 1012,\n'
342 342 ' 1013,\n'
343 343 ' 1014,\n'
344 344 ' 1015,\n'
345 345 ' 1016,\n'
346 346 ' 1017,\n'
347 347 ' 1018,\n'
348 348 ' 1019])'),
349 349 (a, 'deque([deque(...)])'),
350 350 ]
351 351 for obj, expected in cases:
352 352 nt.assert_equal(pretty.pretty(obj), expected)
353 353
354 354 def test_collections_counter():
355 355 class MyCounter(Counter):
356 356 pass
357 357 cases = [
358 358 (Counter(), 'Counter()'),
359 359 (Counter(a=1), "Counter({'a': 1})"),
360 360 (MyCounter(a=1), "MyCounter({'a': 1})"),
361 361 ]
362 362 for obj, expected in cases:
363 363 nt.assert_equal(pretty.pretty(obj), expected)
364 364
365 365 def test_mappingproxy():
366 366 MP = types.MappingProxyType
367 367 underlying_dict = {}
368 368 mp_recursive = MP(underlying_dict)
369 369 underlying_dict[2] = mp_recursive
370 370 underlying_dict[3] = underlying_dict
371 371
372 372 cases = [
373 373 (MP({}), "mappingproxy({})"),
374 374 (MP({None: MP({})}), "mappingproxy({None: mappingproxy({})})"),
375 375 (MP({k: k.upper() for k in string.ascii_lowercase}),
376 376 "mappingproxy({'a': 'A',\n"
377 377 " 'b': 'B',\n"
378 378 " 'c': 'C',\n"
379 379 " 'd': 'D',\n"
380 380 " 'e': 'E',\n"
381 381 " 'f': 'F',\n"
382 382 " 'g': 'G',\n"
383 383 " 'h': 'H',\n"
384 384 " 'i': 'I',\n"
385 385 " 'j': 'J',\n"
386 386 " 'k': 'K',\n"
387 387 " 'l': 'L',\n"
388 388 " 'm': 'M',\n"
389 389 " 'n': 'N',\n"
390 390 " 'o': 'O',\n"
391 391 " 'p': 'P',\n"
392 392 " 'q': 'Q',\n"
393 393 " 'r': 'R',\n"
394 394 " 's': 'S',\n"
395 395 " 't': 'T',\n"
396 396 " 'u': 'U',\n"
397 397 " 'v': 'V',\n"
398 398 " 'w': 'W',\n"
399 399 " 'x': 'X',\n"
400 400 " 'y': 'Y',\n"
401 401 " 'z': 'Z'})"),
402 402 (mp_recursive, "mappingproxy({2: {...}, 3: {2: {...}, 3: {...}}})"),
403 403 (underlying_dict,
404 404 "{2: mappingproxy({2: {...}, 3: {...}}), 3: {...}}"),
405 405 ]
406 406 for obj, expected in cases:
407 407 nt.assert_equal(pretty.pretty(obj), expected)
408
409 def test_function_pretty():
410 "Test pretty print of function"
411 # posixpath is a pure python module, its interface is consistent
412 # across Python distributions
413 import posixpath
414 nt.assert_equal(pretty.pretty(posixpath.join), '<function posixpath.join(a, *p)>')
415
416 # custom function
417 def meaning_of_life(question=None):
418 if question:
419 return 42
420 return "Don't panic"
421
422 nt.assert_in('meaning_of_life(question=None)', pretty.pretty(meaning_of_life))
423
General Comments 0
You need to be logged in to leave comments. Login now