##// END OF EJS Templates
Added sorting on counter and passed all tests
Jono Tassia -
Show More
@@ -1,953 +1,953 b''
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's an example for a class with a simple constructor::
38 38
39 39 class MySimpleObject:
40 40
41 41 def __init__(self, a, b, *, c=None):
42 42 self.a = a
43 43 self.b = b
44 44 self.c = c
45 45
46 46 def _repr_pretty_(self, p, cycle):
47 47 ctor = CallExpression.factory(self.__class__.__name__)
48 48 if self.c is None:
49 49 p.pretty(ctor(a, b))
50 50 else:
51 51 p.pretty(ctor(a, b, c=c))
52 52
53 53 Here is an example implementation of a `_repr_pretty_` method for a list
54 54 subclass::
55 55
56 56 class MyList(list):
57 57
58 58 def _repr_pretty_(self, p, cycle):
59 59 if cycle:
60 60 p.text('MyList(...)')
61 61 else:
62 62 with p.group(8, 'MyList([', '])'):
63 63 for idx, item in enumerate(self):
64 64 if idx:
65 65 p.text(',')
66 66 p.breakable()
67 67 p.pretty(item)
68 68
69 69 The `cycle` parameter is `True` if pretty detected a cycle. You *have* to
70 70 react to that or the result is an infinite loop. `p.text()` just adds
71 71 non breaking text to the output, `p.breakable()` either adds a whitespace
72 72 or breaks here. If you pass it an argument it's used instead of the
73 73 default space. `p.pretty` prettyprints another object using the pretty print
74 74 method.
75 75
76 76 The first parameter to the `group` function specifies the extra indentation
77 77 of the next line. In this example the next item will either be on the same
78 78 line (if the items are short enough) or aligned with the right edge of the
79 79 opening bracket of `MyList`.
80 80
81 81 If you just want to indent something you can use the group function
82 82 without open / close parameters. You can also use this code::
83 83
84 84 with p.indent(2):
85 85 ...
86 86
87 87 Inheritance diagram:
88 88
89 89 .. inheritance-diagram:: IPython.lib.pretty
90 90 :parts: 3
91 91
92 92 :copyright: 2007 by Armin Ronacher.
93 93 Portions (c) 2009 by Robert Kern.
94 94 :license: BSD License.
95 95 """
96 96
97 97 from contextlib import contextmanager
98 98 import datetime
99 99 import os
100 100 import re
101 101 import sys
102 102 import types
103 103 from collections import deque
104 104 from inspect import signature
105 105 from io import StringIO
106 106 from warnings import warn
107 107
108 108 from IPython.utils.decorators import undoc
109 109 from IPython.utils.py3compat import PYPY
110 110
111 111 __all__ = ['pretty', 'pprint', 'PrettyPrinter', 'RepresentationPrinter',
112 112 'for_type', 'for_type_by_name', 'RawText', 'RawStringLiteral', 'CallExpression']
113 113
114 114
115 115 MAX_SEQ_LENGTH = 1000
116 116 _re_pattern_type = type(re.compile(''))
117 117
118 118 def _safe_getattr(obj, attr, default=None):
119 119 """Safe version of getattr.
120 120
121 121 Same as getattr, but will return ``default`` on any Exception,
122 122 rather than raising.
123 123 """
124 124 try:
125 125 return getattr(obj, attr, default)
126 126 except Exception:
127 127 return default
128 128
129 129 @undoc
130 130 class CUnicodeIO(StringIO):
131 131 def __init__(self, *args, **kwargs):
132 132 super().__init__(*args, **kwargs)
133 133 warn(("CUnicodeIO is deprecated since IPython 6.0. "
134 134 "Please use io.StringIO instead."),
135 135 DeprecationWarning, stacklevel=2)
136 136
137 137 def _sorted_for_pprint(items):
138 138 """
139 139 Sort the given items for pretty printing. Since some predictable
140 140 sorting is better than no sorting at all, we sort on the string
141 141 representation if normal sorting fails.
142 142 """
143 143 items = list(items)
144 144 try:
145 145 return sorted(items)
146 146 except Exception:
147 147 try:
148 148 return sorted(items, key=str)
149 149 except Exception:
150 150 return items
151 151
152 152 def pretty(obj, verbose=False, max_width=79, newline='\n', max_seq_length=MAX_SEQ_LENGTH):
153 153 """
154 154 Pretty print the object's representation.
155 155 """
156 156 stream = StringIO()
157 157 printer = RepresentationPrinter(stream, verbose, max_width, newline, max_seq_length=max_seq_length)
158 158 printer.pretty(obj)
159 159 printer.flush()
160 160 return stream.getvalue()
161 161
162 162
163 163 def pprint(obj, verbose=False, max_width=79, newline='\n', max_seq_length=MAX_SEQ_LENGTH):
164 164 """
165 165 Like `pretty` but print to stdout.
166 166 """
167 167 printer = RepresentationPrinter(sys.stdout, verbose, max_width, newline, max_seq_length=max_seq_length)
168 168 printer.pretty(obj)
169 169 printer.flush()
170 170 sys.stdout.write(newline)
171 171 sys.stdout.flush()
172 172
173 173 class _PrettyPrinterBase(object):
174 174
175 175 @contextmanager
176 176 def indent(self, indent):
177 177 """with statement support for indenting/dedenting."""
178 178 self.indentation += indent
179 179 try:
180 180 yield
181 181 finally:
182 182 self.indentation -= indent
183 183
184 184 @contextmanager
185 185 def group(self, indent=0, open='', close=''):
186 186 """like begin_group / end_group but for the with statement."""
187 187 self.begin_group(indent, open)
188 188 try:
189 189 yield
190 190 finally:
191 191 self.end_group(indent, close)
192 192
193 193 class PrettyPrinter(_PrettyPrinterBase):
194 194 """
195 195 Baseclass for the `RepresentationPrinter` prettyprinter that is used to
196 196 generate pretty reprs of objects. Contrary to the `RepresentationPrinter`
197 197 this printer knows nothing about the default pprinters or the `_repr_pretty_`
198 198 callback method.
199 199 """
200 200
201 201 def __init__(self, output, max_width=79, newline='\n', max_seq_length=MAX_SEQ_LENGTH):
202 202 self.output = output
203 203 self.max_width = max_width
204 204 self.newline = newline
205 205 self.max_seq_length = max_seq_length
206 206 self.output_width = 0
207 207 self.buffer_width = 0
208 208 self.buffer = deque()
209 209
210 210 root_group = Group(0)
211 211 self.group_stack = [root_group]
212 212 self.group_queue = GroupQueue(root_group)
213 213 self.indentation = 0
214 214
215 215 def _break_one_group(self, group):
216 216 while group.breakables:
217 217 x = self.buffer.popleft()
218 218 self.output_width = x.output(self.output, self.output_width)
219 219 self.buffer_width -= x.width
220 220 while self.buffer and isinstance(self.buffer[0], Text):
221 221 x = self.buffer.popleft()
222 222 self.output_width = x.output(self.output, self.output_width)
223 223 self.buffer_width -= x.width
224 224
225 225 def _break_outer_groups(self):
226 226 while self.max_width < self.output_width + self.buffer_width:
227 227 group = self.group_queue.deq()
228 228 if not group:
229 229 return
230 230 self._break_one_group(group)
231 231
232 232 def text(self, obj):
233 233 """Add literal text to the output."""
234 234 width = len(obj)
235 235 if self.buffer:
236 236 text = self.buffer[-1]
237 237 if not isinstance(text, Text):
238 238 text = Text()
239 239 self.buffer.append(text)
240 240 text.add(obj, width)
241 241 self.buffer_width += width
242 242 self._break_outer_groups()
243 243 else:
244 244 self.output.write(obj)
245 245 self.output_width += width
246 246
247 247 def breakable(self, sep=' '):
248 248 """
249 249 Add a breakable separator to the output. This does not mean that it
250 250 will automatically break here. If no breaking on this position takes
251 251 place the `sep` is inserted which default to one space.
252 252 """
253 253 width = len(sep)
254 254 group = self.group_stack[-1]
255 255 if group.want_break:
256 256 self.flush()
257 257 self.output.write(self.newline)
258 258 self.output.write(' ' * self.indentation)
259 259 self.output_width = self.indentation
260 260 self.buffer_width = 0
261 261 else:
262 262 self.buffer.append(Breakable(sep, width, self))
263 263 self.buffer_width += width
264 264 self._break_outer_groups()
265 265
266 266 def break_(self):
267 267 """
268 268 Explicitly insert a newline into the output, maintaining correct indentation.
269 269 """
270 270 group = self.group_queue.deq()
271 271 if group:
272 272 self._break_one_group(group)
273 273 self.flush()
274 274 self.output.write(self.newline)
275 275 self.output.write(' ' * self.indentation)
276 276 self.output_width = self.indentation
277 277 self.buffer_width = 0
278 278
279 279
280 280 def begin_group(self, indent=0, open=''):
281 281 """
282 282 Begin a group.
283 283 The first parameter specifies the indentation for the next line (usually
284 284 the width of the opening text), the second the opening text. All
285 285 parameters are optional.
286 286 """
287 287 if open:
288 288 self.text(open)
289 289 group = Group(self.group_stack[-1].depth + 1)
290 290 self.group_stack.append(group)
291 291 self.group_queue.enq(group)
292 292 self.indentation += indent
293 293
294 294 def _enumerate(self, seq):
295 295 """like enumerate, but with an upper limit on the number of items"""
296 296 for idx, x in enumerate(seq):
297 297 if self.max_seq_length and idx >= self.max_seq_length:
298 298 self.text(',')
299 299 self.breakable()
300 300 self.text('...')
301 301 return
302 302 yield idx, x
303 303
304 304 def end_group(self, dedent=0, close=''):
305 305 """End a group. See `begin_group` for more details."""
306 306 self.indentation -= dedent
307 307 group = self.group_stack.pop()
308 308 if not group.breakables:
309 309 self.group_queue.remove(group)
310 310 if close:
311 311 self.text(close)
312 312
313 313 def flush(self):
314 314 """Flush data that is left in the buffer."""
315 315 for data in self.buffer:
316 316 self.output_width += data.output(self.output, self.output_width)
317 317 self.buffer.clear()
318 318 self.buffer_width = 0
319 319
320 320
321 321 def _get_mro(obj_class):
322 322 """ Get a reasonable method resolution order of a class and its superclasses
323 323 for both old-style and new-style classes.
324 324 """
325 325 if not hasattr(obj_class, '__mro__'):
326 326 # Old-style class. Mix in object to make a fake new-style class.
327 327 try:
328 328 obj_class = type(obj_class.__name__, (obj_class, object), {})
329 329 except TypeError:
330 330 # Old-style extension type that does not descend from object.
331 331 # FIXME: try to construct a more thorough MRO.
332 332 mro = [obj_class]
333 333 else:
334 334 mro = obj_class.__mro__[1:-1]
335 335 else:
336 336 mro = obj_class.__mro__
337 337 return mro
338 338
339 339
340 340 class RepresentationPrinter(PrettyPrinter):
341 341 """
342 342 Special pretty printer that has a `pretty` method that calls the pretty
343 343 printer for a python object.
344 344
345 345 This class stores processing data on `self` so you must *never* use
346 346 this class in a threaded environment. Always lock it or reinstanciate
347 347 it.
348 348
349 349 Instances also have a verbose flag callbacks can access to control their
350 350 output. For example the default instance repr prints all attributes and
351 351 methods that are not prefixed by an underscore if the printer is in
352 352 verbose mode.
353 353 """
354 354
355 355 def __init__(self, output, verbose=False, max_width=79, newline='\n',
356 356 singleton_pprinters=None, type_pprinters=None, deferred_pprinters=None,
357 357 max_seq_length=MAX_SEQ_LENGTH):
358 358
359 359 PrettyPrinter.__init__(self, output, max_width, newline, max_seq_length=max_seq_length)
360 360 self.verbose = verbose
361 361 self.stack = []
362 362 if singleton_pprinters is None:
363 363 singleton_pprinters = _singleton_pprinters.copy()
364 364 self.singleton_pprinters = singleton_pprinters
365 365 if type_pprinters is None:
366 366 type_pprinters = _type_pprinters.copy()
367 367 self.type_pprinters = type_pprinters
368 368 if deferred_pprinters is None:
369 369 deferred_pprinters = _deferred_type_pprinters.copy()
370 370 self.deferred_pprinters = deferred_pprinters
371 371
372 372 def pretty(self, obj):
373 373 """Pretty print the given object."""
374 374 obj_id = id(obj)
375 375 cycle = obj_id in self.stack
376 376 self.stack.append(obj_id)
377 377 self.begin_group()
378 378 try:
379 379 obj_class = _safe_getattr(obj, '__class__', None) or type(obj)
380 380 # First try to find registered singleton printers for the type.
381 381 try:
382 382 printer = self.singleton_pprinters[obj_id]
383 383 except (TypeError, KeyError):
384 384 pass
385 385 else:
386 386 return printer(obj, self, cycle)
387 387 # Next walk the mro and check for either:
388 388 # 1) a registered printer
389 389 # 2) a _repr_pretty_ method
390 390 for cls in _get_mro(obj_class):
391 391 if cls in self.type_pprinters:
392 392 # printer registered in self.type_pprinters
393 393 return self.type_pprinters[cls](obj, self, cycle)
394 394 else:
395 395 # deferred printer
396 396 printer = self._in_deferred_types(cls)
397 397 if printer is not None:
398 398 return printer(obj, self, cycle)
399 399 else:
400 400 # Finally look for special method names.
401 401 # Some objects automatically create any requested
402 402 # attribute. Try to ignore most of them by checking for
403 403 # callability.
404 404 if '_repr_pretty_' in cls.__dict__:
405 405 meth = cls._repr_pretty_
406 406 if callable(meth):
407 407 return meth(obj, self, cycle)
408 408 if cls is not object \
409 409 and callable(cls.__dict__.get('__repr__')):
410 410 return _repr_pprint(obj, self, cycle)
411 411
412 412 return _default_pprint(obj, self, cycle)
413 413 finally:
414 414 self.end_group()
415 415 self.stack.pop()
416 416
417 417 def _in_deferred_types(self, cls):
418 418 """
419 419 Check if the given class is specified in the deferred type registry.
420 420
421 421 Returns the printer from the registry if it exists, and None if the
422 422 class is not in the registry. Successful matches will be moved to the
423 423 regular type registry for future use.
424 424 """
425 425 mod = _safe_getattr(cls, '__module__', None)
426 426 name = _safe_getattr(cls, '__name__', None)
427 427 key = (mod, name)
428 428 printer = None
429 429 if key in self.deferred_pprinters:
430 430 # Move the printer over to the regular registry.
431 431 printer = self.deferred_pprinters.pop(key)
432 432 self.type_pprinters[cls] = printer
433 433 return printer
434 434
435 435
436 436 class Printable(object):
437 437
438 438 def output(self, stream, output_width):
439 439 return output_width
440 440
441 441
442 442 class Text(Printable):
443 443
444 444 def __init__(self):
445 445 self.objs = []
446 446 self.width = 0
447 447
448 448 def output(self, stream, output_width):
449 449 for obj in self.objs:
450 450 stream.write(obj)
451 451 return output_width + self.width
452 452
453 453 def add(self, obj, width):
454 454 self.objs.append(obj)
455 455 self.width += width
456 456
457 457
458 458 class Breakable(Printable):
459 459
460 460 def __init__(self, seq, width, pretty):
461 461 self.obj = seq
462 462 self.width = width
463 463 self.pretty = pretty
464 464 self.indentation = pretty.indentation
465 465 self.group = pretty.group_stack[-1]
466 466 self.group.breakables.append(self)
467 467
468 468 def output(self, stream, output_width):
469 469 self.group.breakables.popleft()
470 470 if self.group.want_break:
471 471 stream.write(self.pretty.newline)
472 472 stream.write(' ' * self.indentation)
473 473 return self.indentation
474 474 if not self.group.breakables:
475 475 self.pretty.group_queue.remove(self.group)
476 476 stream.write(self.obj)
477 477 return output_width + self.width
478 478
479 479
480 480 class Group(Printable):
481 481
482 482 def __init__(self, depth):
483 483 self.depth = depth
484 484 self.breakables = deque()
485 485 self.want_break = False
486 486
487 487
488 488 class GroupQueue(object):
489 489
490 490 def __init__(self, *groups):
491 491 self.queue = []
492 492 for group in groups:
493 493 self.enq(group)
494 494
495 495 def enq(self, group):
496 496 depth = group.depth
497 497 while depth > len(self.queue) - 1:
498 498 self.queue.append([])
499 499 self.queue[depth].append(group)
500 500
501 501 def deq(self):
502 502 for stack in self.queue:
503 503 for idx, group in enumerate(reversed(stack)):
504 504 if group.breakables:
505 505 del stack[idx]
506 506 group.want_break = True
507 507 return group
508 508 for group in stack:
509 509 group.want_break = True
510 510 del stack[:]
511 511
512 512 def remove(self, group):
513 513 try:
514 514 self.queue[group.depth].remove(group)
515 515 except ValueError:
516 516 pass
517 517
518 518
519 519 class RawText:
520 520 """ Object such that ``p.pretty(RawText(value))`` is the same as ``p.text(value)``.
521 521
522 522 An example usage of this would be to show a list as binary numbers, using
523 523 ``p.pretty([RawText(bin(i)) for i in integers])``.
524 524 """
525 525 def __init__(self, value):
526 526 self.value = value
527 527
528 528 def _repr_pretty_(self, p, cycle):
529 529 p.text(self.value)
530 530
531 531
532 532 class CallExpression:
533 533 """ Object which emits a line-wrapped call expression in the form `__name(*args, **kwargs)` """
534 534 def __init__(__self, __name, *args, **kwargs):
535 535 # dunders are to avoid clashes with kwargs, as python's name manging
536 536 # will kick in.
537 537 self = __self
538 538 self.name = __name
539 539 self.args = args
540 540 self.kwargs = kwargs
541 541
542 542 @classmethod
543 543 def factory(cls, name):
544 544 def inner(*args, **kwargs):
545 545 return cls(name, *args, **kwargs)
546 546 return inner
547 547
548 548 def _repr_pretty_(self, p, cycle):
549 549 # dunders are to avoid clashes with kwargs, as python's name manging
550 550 # will kick in.
551 551
552 552 started = False
553 553 def new_item():
554 554 nonlocal started
555 555 if started:
556 556 p.text(",")
557 557 p.breakable()
558 558 started = True
559 559
560 560 prefix = self.name + "("
561 561 with p.group(len(prefix), prefix, ")"):
562 562 for arg in self.args:
563 563 new_item()
564 564 p.pretty(arg)
565 565 for arg_name, arg in self.kwargs.items():
566 566 new_item()
567 567 arg_prefix = arg_name + "="
568 568 with p.group(len(arg_prefix), arg_prefix):
569 569 p.pretty(arg)
570 570
571 571
572 572 class RawStringLiteral:
573 573 """ Wrapper that shows a string with a `r` prefix """
574 574 def __init__(self, value):
575 575 self.value = value
576 576
577 577 def _repr_pretty_(self, p, cycle):
578 578 base_repr = repr(self.value)
579 579 if base_repr[:1] in 'uU':
580 580 base_repr = base_repr[1:]
581 581 prefix = 'ur'
582 582 else:
583 583 prefix = 'r'
584 584 base_repr = prefix + base_repr.replace('\\\\', '\\')
585 585 p.text(base_repr)
586 586
587 587
588 588 def _default_pprint(obj, p, cycle):
589 589 """
590 590 The default print function. Used if an object does not provide one and
591 591 it's none of the builtin objects.
592 592 """
593 593 klass = _safe_getattr(obj, '__class__', None) or type(obj)
594 594 if _safe_getattr(klass, '__repr__', None) is not object.__repr__:
595 595 # A user-provided repr. Find newlines and replace them with p.break_()
596 596 _repr_pprint(obj, p, cycle)
597 597 return
598 598 p.begin_group(1, '<')
599 599 p.pretty(klass)
600 600 p.text(' at 0x%x' % id(obj))
601 601 if cycle:
602 602 p.text(' ...')
603 603 elif p.verbose:
604 604 first = True
605 605 for key in dir(obj):
606 606 if not key.startswith('_'):
607 607 try:
608 608 value = getattr(obj, key)
609 609 except AttributeError:
610 610 continue
611 611 if isinstance(value, types.MethodType):
612 612 continue
613 613 if not first:
614 614 p.text(',')
615 615 p.breakable()
616 616 p.text(key)
617 617 p.text('=')
618 618 step = len(key) + 1
619 619 p.indentation += step
620 620 p.pretty(value)
621 621 p.indentation -= step
622 622 first = False
623 623 p.end_group(1, '>')
624 624
625 625
626 626 def _seq_pprinter_factory(start, end):
627 627 """
628 628 Factory that returns a pprint function useful for sequences. Used by
629 629 the default pprint for tuples and lists.
630 630 """
631 631 def inner(obj, p, cycle):
632 632 if cycle:
633 633 return p.text(start + '...' + end)
634 634 step = len(start)
635 635 p.begin_group(step, start)
636 636 for idx, x in p._enumerate(obj):
637 637 if idx:
638 638 p.text(',')
639 639 p.breakable()
640 640 p.pretty(x)
641 641 if len(obj) == 1 and isinstance(obj, tuple):
642 642 # Special case for 1-item tuples.
643 643 p.text(',')
644 644 p.end_group(step, end)
645 645 return inner
646 646
647 647
648 648 def _set_pprinter_factory(start, end):
649 649 """
650 650 Factory that returns a pprint function useful for sets and frozensets.
651 651 """
652 652 def inner(obj, p, cycle):
653 653 if cycle:
654 654 return p.text(start + '...' + end)
655 655 if len(obj) == 0:
656 656 # Special case.
657 657 p.text(type(obj).__name__ + '()')
658 658 else:
659 659 step = len(start)
660 660 p.begin_group(step, start)
661 661 # Like dictionary keys, we will try to sort the items if there aren't too many
662 662 if not (p.max_seq_length and len(obj) >= p.max_seq_length):
663 663 items = _sorted_for_pprint(obj)
664 664 else:
665 665 items = obj
666 666 for idx, x in p._enumerate(items):
667 667 if idx:
668 668 p.text(',')
669 669 p.breakable()
670 670 p.pretty(x)
671 671 p.end_group(step, end)
672 672 return inner
673 673
674 674
675 675 def _dict_pprinter_factory(start, end):
676 676 """
677 677 Factory that returns a pprint function used by the default pprint of
678 678 dicts and dict proxies.
679 679 """
680 680 def inner(obj, p, cycle):
681 681 if cycle:
682 682 return p.text('{...}')
683 683 step = len(start)
684 684 p.begin_group(step, start)
685 685 keys = obj.keys()
686 686 for idx, key in p._enumerate(keys):
687 687 if idx:
688 688 p.text(',')
689 689 p.breakable()
690 690 p.pretty(key)
691 691 p.text(': ')
692 692 p.pretty(obj[key])
693 693 p.end_group(step, end)
694 694 return inner
695 695
696 696
697 697 def _super_pprint(obj, p, cycle):
698 698 """The pprint for the super type."""
699 699 p.begin_group(8, '<super: ')
700 700 p.pretty(obj.__thisclass__)
701 701 p.text(',')
702 702 p.breakable()
703 703 if PYPY: # In PyPy, super() objects don't have __self__ attributes
704 704 dself = obj.__repr__.__self__
705 705 p.pretty(None if dself is obj else dself)
706 706 else:
707 707 p.pretty(obj.__self__)
708 708 p.end_group(8, '>')
709 709
710 710
711 711
712 712 class _ReFlags:
713 713 def __init__(self, value):
714 714 self.value = value
715 715
716 716 def _repr_pretty_(self, p, cycle):
717 717 done_one = False
718 718 for flag in ('TEMPLATE', 'IGNORECASE', 'LOCALE', 'MULTILINE', 'DOTALL',
719 719 'UNICODE', 'VERBOSE', 'DEBUG'):
720 720 if self.value & getattr(re, flag):
721 721 if done_one:
722 722 p.text('|')
723 723 p.text('re.' + flag)
724 724 done_one = True
725 725
726 726
727 727 def _re_pattern_pprint(obj, p, cycle):
728 728 """The pprint function for regular expression patterns."""
729 729 re_compile = CallExpression.factory('re.compile')
730 730 if obj.flags:
731 731 p.pretty(re_compile(RawStringLiteral(obj.pattern), _ReFlags(obj.flags)))
732 732 else:
733 733 p.pretty(re_compile(RawStringLiteral(obj.pattern)))
734 734
735 735
736 736 def _types_simplenamespace_pprint(obj, p, cycle):
737 737 """The pprint function for types.SimpleNamespace."""
738 738 namespace = CallExpression.factory('namespace')
739 739 if cycle:
740 740 p.pretty(namespace(RawText("...")))
741 741 else:
742 742 p.pretty(namespace(**obj.__dict__))
743 743
744 744
745 745 def _type_pprint(obj, p, cycle):
746 746 """The pprint for classes and types."""
747 747 # Heap allocated types might not have the module attribute,
748 748 # and others may set it to None.
749 749
750 750 # Checks for a __repr__ override in the metaclass. Can't compare the
751 751 # type(obj).__repr__ directly because in PyPy the representation function
752 752 # inherited from type isn't the same type.__repr__
753 753 if [m for m in _get_mro(type(obj)) if "__repr__" in vars(m)][:1] != [type]:
754 754 _repr_pprint(obj, p, cycle)
755 755 return
756 756
757 757 mod = _safe_getattr(obj, '__module__', None)
758 758 try:
759 759 name = obj.__qualname__
760 760 if not isinstance(name, str):
761 761 # This can happen if the type implements __qualname__ as a property
762 762 # or other descriptor in Python 2.
763 763 raise Exception("Try __name__")
764 764 except Exception:
765 765 name = obj.__name__
766 766 if not isinstance(name, str):
767 767 name = '<unknown type>'
768 768
769 769 if mod in (None, '__builtin__', 'builtins', 'exceptions'):
770 770 p.text(name)
771 771 else:
772 772 p.text(mod + '.' + name)
773 773
774 774
775 775 def _repr_pprint(obj, p, cycle):
776 776 """A pprint that just redirects to the normal repr function."""
777 777 # Find newlines and replace them with p.break_()
778 778 output = repr(obj)
779 779 lines = output.splitlines()
780 780 with p.group():
781 781 for idx, output_line in enumerate(lines):
782 782 if idx:
783 783 p.break_()
784 784 p.text(output_line)
785 785
786 786
787 787 def _function_pprint(obj, p, cycle):
788 788 """Base pprint for all functions and builtin functions."""
789 789 name = _safe_getattr(obj, '__qualname__', obj.__name__)
790 790 mod = obj.__module__
791 791 if mod and mod not in ('__builtin__', 'builtins', 'exceptions'):
792 792 name = mod + '.' + name
793 793 try:
794 794 func_def = name + str(signature(obj))
795 795 except ValueError:
796 796 func_def = name
797 797 p.text('<function %s>' % func_def)
798 798
799 799
800 800 def _exception_pprint(obj, p, cycle):
801 801 """Base pprint for all exceptions."""
802 802 name = getattr(obj.__class__, '__qualname__', obj.__class__.__name__)
803 803 if obj.__class__.__module__ not in ('exceptions', 'builtins'):
804 804 name = '%s.%s' % (obj.__class__.__module__, name)
805 805
806 806 p.pretty(CallExpression(name, *getattr(obj, 'args', ())))
807 807
808 808
809 809 #: the exception base
810 810 try:
811 811 _exception_base = BaseException
812 812 except NameError:
813 813 _exception_base = Exception
814 814
815 815
816 816 #: printers for builtin types
817 817 _type_pprinters = {
818 818 int: _repr_pprint,
819 819 float: _repr_pprint,
820 820 str: _repr_pprint,
821 821 tuple: _seq_pprinter_factory('(', ')'),
822 822 list: _seq_pprinter_factory('[', ']'),
823 823 dict: _dict_pprinter_factory('{', '}'),
824 824 set: _set_pprinter_factory('{', '}'),
825 825 frozenset: _set_pprinter_factory('frozenset({', '})'),
826 826 super: _super_pprint,
827 827 _re_pattern_type: _re_pattern_pprint,
828 828 type: _type_pprint,
829 829 types.FunctionType: _function_pprint,
830 830 types.BuiltinFunctionType: _function_pprint,
831 831 types.MethodType: _repr_pprint,
832 832 types.SimpleNamespace: _types_simplenamespace_pprint,
833 833 datetime.datetime: _repr_pprint,
834 834 datetime.timedelta: _repr_pprint,
835 835 _exception_base: _exception_pprint
836 836 }
837 837
838 838 # render os.environ like a dict
839 839 _env_type = type(os.environ)
840 840 # future-proof in case os.environ becomes a plain dict?
841 841 if _env_type is not dict:
842 842 _type_pprinters[_env_type] = _dict_pprinter_factory('environ{', '}')
843 843
844 844 try:
845 845 # In PyPy, types.DictProxyType is dict, setting the dictproxy printer
846 846 # using dict.setdefault avoids overwriting the dict printer
847 847 _type_pprinters.setdefault(types.DictProxyType,
848 848 _dict_pprinter_factory('dict_proxy({', '})'))
849 849 _type_pprinters[types.ClassType] = _type_pprint
850 850 _type_pprinters[types.SliceType] = _repr_pprint
851 851 except AttributeError: # Python 3
852 852 _type_pprinters[types.MappingProxyType] = \
853 853 _dict_pprinter_factory('mappingproxy({', '})')
854 854 _type_pprinters[slice] = _repr_pprint
855 855
856 856 _type_pprinters[range] = _repr_pprint
857 857 _type_pprinters[bytes] = _repr_pprint
858 858
859 859 #: printers for types specified by name
860 860 _deferred_type_pprinters = {
861 861 }
862 862
863 863 def for_type(typ, func):
864 864 """
865 865 Add a pretty printer for a given type.
866 866 """
867 867 oldfunc = _type_pprinters.get(typ, None)
868 868 if func is not None:
869 869 # To support easy restoration of old pprinters, we need to ignore Nones.
870 870 _type_pprinters[typ] = func
871 871 return oldfunc
872 872
873 873 def for_type_by_name(type_module, type_name, func):
874 874 """
875 875 Add a pretty printer for a type specified by the module and name of a type
876 876 rather than the type object itself.
877 877 """
878 878 key = (type_module, type_name)
879 879 oldfunc = _deferred_type_pprinters.get(key, None)
880 880 if func is not None:
881 881 # To support easy restoration of old pprinters, we need to ignore Nones.
882 882 _deferred_type_pprinters[key] = func
883 883 return oldfunc
884 884
885 885
886 886 #: printers for the default singletons
887 887 _singleton_pprinters = dict.fromkeys(map(id, [None, True, False, Ellipsis,
888 888 NotImplemented]), _repr_pprint)
889 889
890 890
891 891 def _defaultdict_pprint(obj, p, cycle):
892 892 cls_ctor = CallExpression.factory(obj.__class__.__name__)
893 893 if cycle:
894 894 p.pretty(cls_ctor(RawText("...")))
895 895 else:
896 896 p.pretty(cls_ctor(obj.default_factory, dict(obj)))
897 897
898 898 def _ordereddict_pprint(obj, p, cycle):
899 899 cls_ctor = CallExpression.factory(obj.__class__.__name__)
900 900 if cycle:
901 901 p.pretty(cls_ctor(RawText("...")))
902 902 elif len(obj):
903 903 p.pretty(cls_ctor(list(obj.items())))
904 904 else:
905 905 p.pretty(cls_ctor())
906 906
907 907 def _deque_pprint(obj, p, cycle):
908 908 cls_ctor = CallExpression.factory(obj.__class__.__name__)
909 909 if cycle:
910 910 p.pretty(cls_ctor(RawText("...")))
911 911 elif obj.maxlen is not None:
912 912 p.pretty(cls_ctor(list(obj), maxlen=obj.maxlen))
913 913 else:
914 914 p.pretty(cls_ctor(list(obj)))
915 915
916 916 def _counter_pprint(obj, p, cycle):
917 917 cls_ctor = CallExpression.factory(obj.__class__.__name__)
918 918 if cycle:
919 919 p.pretty(cls_ctor(RawText("...")))
920 920 elif len(obj):
921 p.pretty(cls_ctor(dict(obj)))
921 p.pretty(cls_ctor(dict(sorted(obj.items(), key=lambda x: x[1], reverse=True))))
922 922 else:
923 923 p.pretty(cls_ctor())
924 924
925 925
926 926 def _userlist_pprint(obj, p, cycle):
927 927 cls_ctor = CallExpression.factory(obj.__class__.__name__)
928 928 if cycle:
929 929 p.pretty(cls_ctor(RawText("...")))
930 930 else:
931 931 p.pretty(cls_ctor(obj.data))
932 932
933 933
934 934 for_type_by_name('collections', 'defaultdict', _defaultdict_pprint)
935 935 for_type_by_name('collections', 'OrderedDict', _ordereddict_pprint)
936 936 for_type_by_name('collections', 'deque', _deque_pprint)
937 937 for_type_by_name('collections', 'Counter', _counter_pprint)
938 938 for_type_by_name("collections", "UserList", _userlist_pprint)
939 939
940 940 if __name__ == '__main__':
941 941 from random import randrange
942 942 class Foo(object):
943 943 def __init__(self):
944 944 self.foo = 1
945 945 self.bar = re.compile(r'\s+')
946 946 self.blub = dict.fromkeys(range(30), randrange(1, 40))
947 947 self.hehe = 23424.234234
948 948 self.list = ["blub", "blah", self]
949 949
950 950 def get_foo(self):
951 951 print("foo")
952 952
953 953 pprint(Foo(), verbose=True)
@@ -1,539 +1,540 b''
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, UserList
9 9 import os
10 10 import pytest
11 11 import types
12 12 import string
13 13 import sys
14 14 import unittest
15 15
16 16 import pytest
17 17
18 18 from IPython.lib import pretty
19 19
20 20 from io import StringIO
21 21
22 22
23 23 class MyList(object):
24 24 def __init__(self, content):
25 25 self.content = content
26 26 def _repr_pretty_(self, p, cycle):
27 27 if cycle:
28 28 p.text("MyList(...)")
29 29 else:
30 30 with p.group(3, "MyList(", ")"):
31 31 for (i, child) in enumerate(self.content):
32 32 if i:
33 33 p.text(",")
34 34 p.breakable()
35 35 else:
36 36 p.breakable("")
37 37 p.pretty(child)
38 38
39 39
40 40 class MyDict(dict):
41 41 def _repr_pretty_(self, p, cycle):
42 42 p.text("MyDict(...)")
43 43
44 44 class MyObj(object):
45 45 def somemethod(self):
46 46 pass
47 47
48 48
49 49 class Dummy1(object):
50 50 def _repr_pretty_(self, p, cycle):
51 51 p.text("Dummy1(...)")
52 52
53 53 class Dummy2(Dummy1):
54 54 _repr_pretty_ = None
55 55
56 56 class NoModule(object):
57 57 pass
58 58
59 59 NoModule.__module__ = None
60 60
61 61 class Breaking(object):
62 62 def _repr_pretty_(self, p, cycle):
63 63 with p.group(4,"TG: ",":"):
64 64 p.text("Breaking(")
65 65 p.break_()
66 66 p.text(")")
67 67
68 68 class BreakingRepr(object):
69 69 def __repr__(self):
70 70 return "Breaking(\n)"
71 71
72 72 class BadRepr(object):
73 73 def __repr__(self):
74 74 return 1/0
75 75
76 76
77 77 def test_indentation():
78 78 """Test correct indentation in groups"""
79 79 count = 40
80 80 gotoutput = pretty.pretty(MyList(range(count)))
81 81 expectedoutput = "MyList(\n" + ",\n".join(" %d" % i for i in range(count)) + ")"
82 82
83 83 assert gotoutput == expectedoutput
84 84
85 85
86 86 def test_dispatch():
87 87 """
88 88 Test correct dispatching: The _repr_pretty_ method for MyDict
89 89 must be found before the registered printer for dict.
90 90 """
91 91 gotoutput = pretty.pretty(MyDict())
92 92 expectedoutput = "MyDict(...)"
93 93
94 94 assert gotoutput == expectedoutput
95 95
96 96
97 97 def test_callability_checking():
98 98 """
99 99 Test that the _repr_pretty_ method is tested for callability and skipped if
100 100 not.
101 101 """
102 102 gotoutput = pretty.pretty(Dummy2())
103 103 expectedoutput = "Dummy1(...)"
104 104
105 105 assert gotoutput == expectedoutput
106 106
107 107
108 108 @pytest.mark.parametrize(
109 109 "obj,expected_output",
110 110 zip(
111 111 [
112 112 set(),
113 113 frozenset(),
114 114 set([1]),
115 115 frozenset([1]),
116 116 set([1, 2]),
117 117 frozenset([1, 2]),
118 118 set([-1, -2, -3]),
119 119 ],
120 120 [
121 121 "set()",
122 122 "frozenset()",
123 123 "{1}",
124 124 "frozenset({1})",
125 125 "{1, 2}",
126 126 "frozenset({1, 2})",
127 127 "{-3, -2, -1}",
128 128 ],
129 129 ),
130 130 )
131 131 def test_sets(obj, expected_output):
132 132 """
133 133 Test that set and frozenset use Python 3 formatting.
134 134 """
135 135 got_output = pretty.pretty(obj)
136 136 assert got_output == expected_output
137 137
138 138
139 139 def test_pprint_heap_allocated_type():
140 140 """
141 141 Test that pprint works for heap allocated types.
142 142 """
143 143 module_name = "xxlimited" if sys.version_info < (3, 10) else "xxlimited_35"
144 144 expected_output = (
145 145 "xxlimited.Null" if sys.version_info < (3, 10, 6) else "xxlimited_35.Null"
146 146 )
147 147 xxlimited = pytest.importorskip(module_name)
148 148 output = pretty.pretty(xxlimited.Null)
149 149 assert output == expected_output
150 150
151 151
152 152 def test_pprint_nomod():
153 153 """
154 154 Test that pprint works for classes with no __module__.
155 155 """
156 156 output = pretty.pretty(NoModule)
157 157 assert output == "NoModule"
158 158
159 159
160 160 def test_pprint_break():
161 161 """
162 162 Test that p.break_ produces expected output
163 163 """
164 164 output = pretty.pretty(Breaking())
165 165 expected = "TG: Breaking(\n ):"
166 166 assert output == expected
167 167
168 168 def test_pprint_break_repr():
169 169 """
170 170 Test that p.break_ is used in repr
171 171 """
172 172 output = pretty.pretty([[BreakingRepr()]])
173 173 expected = "[[Breaking(\n )]]"
174 174 assert output == expected
175 175
176 176 output = pretty.pretty([[BreakingRepr()]*2])
177 177 expected = "[[Breaking(\n ),\n Breaking(\n )]]"
178 178 assert output == expected
179 179
180 180 def test_bad_repr():
181 181 """Don't catch bad repr errors"""
182 182 with pytest.raises(ZeroDivisionError):
183 183 pretty.pretty(BadRepr())
184 184
185 185 class BadException(Exception):
186 186 def __str__(self):
187 187 return -1
188 188
189 189 class ReallyBadRepr(object):
190 190 __module__ = 1
191 191 @property
192 192 def __class__(self):
193 193 raise ValueError("I am horrible")
194 194
195 195 def __repr__(self):
196 196 raise BadException()
197 197
198 198 def test_really_bad_repr():
199 199 with pytest.raises(BadException):
200 200 pretty.pretty(ReallyBadRepr())
201 201
202 202
203 203 class SA(object):
204 204 pass
205 205
206 206 class SB(SA):
207 207 pass
208 208
209 209 class TestsPretty(unittest.TestCase):
210 210
211 211 def test_super_repr(self):
212 212 # "<super: module_name.SA, None>"
213 213 output = pretty.pretty(super(SA))
214 214 self.assertRegex(output, r"<super: \S+.SA, None>")
215 215
216 216 # "<super: module_name.SA, <module_name.SB at 0x...>>"
217 217 sb = SB()
218 218 output = pretty.pretty(super(SA, sb))
219 219 self.assertRegex(output, r"<super: \S+.SA,\s+<\S+.SB at 0x\S+>>")
220 220
221 221
222 222 def test_long_list(self):
223 223 lis = list(range(10000))
224 224 p = pretty.pretty(lis)
225 225 last2 = p.rsplit('\n', 2)[-2:]
226 226 self.assertEqual(last2, [' 999,', ' ...]'])
227 227
228 228 def test_long_set(self):
229 229 s = set(range(10000))
230 230 p = pretty.pretty(s)
231 231 last2 = p.rsplit('\n', 2)[-2:]
232 232 self.assertEqual(last2, [' 999,', ' ...}'])
233 233
234 234 def test_long_tuple(self):
235 235 tup = tuple(range(10000))
236 236 p = pretty.pretty(tup)
237 237 last2 = p.rsplit('\n', 2)[-2:]
238 238 self.assertEqual(last2, [' 999,', ' ...)'])
239 239
240 240 def test_long_dict(self):
241 241 d = { n:n for n in range(10000) }
242 242 p = pretty.pretty(d)
243 243 last2 = p.rsplit('\n', 2)[-2:]
244 244 self.assertEqual(last2, [' 999: 999,', ' ...}'])
245 245
246 246 def test_unbound_method(self):
247 247 output = pretty.pretty(MyObj.somemethod)
248 248 self.assertIn('MyObj.somemethod', output)
249 249
250 250
251 251 class MetaClass(type):
252 252 def __new__(cls, name):
253 253 return type.__new__(cls, name, (object,), {'name': name})
254 254
255 255 def __repr__(self):
256 256 return "[CUSTOM REPR FOR CLASS %s]" % self.name
257 257
258 258
259 259 ClassWithMeta = MetaClass('ClassWithMeta')
260 260
261 261
262 262 def test_metaclass_repr():
263 263 output = pretty.pretty(ClassWithMeta)
264 264 assert output == "[CUSTOM REPR FOR CLASS ClassWithMeta]"
265 265
266 266
267 267 def test_unicode_repr():
268 268 u = u"üniçodé"
269 269 ustr = u
270 270
271 271 class C(object):
272 272 def __repr__(self):
273 273 return ustr
274 274
275 275 c = C()
276 276 p = pretty.pretty(c)
277 277 assert p == u
278 278 p = pretty.pretty([c])
279 279 assert p == "[%s]" % u
280 280
281 281
282 282 def test_basic_class():
283 283 def type_pprint_wrapper(obj, p, cycle):
284 284 if obj is MyObj:
285 285 type_pprint_wrapper.called = True
286 286 return pretty._type_pprint(obj, p, cycle)
287 287 type_pprint_wrapper.called = False
288 288
289 289 stream = StringIO()
290 290 printer = pretty.RepresentationPrinter(stream)
291 291 printer.type_pprinters[type] = type_pprint_wrapper
292 292 printer.pretty(MyObj)
293 293 printer.flush()
294 294 output = stream.getvalue()
295 295
296 296 assert output == "%s.MyObj" % __name__
297 297 assert type_pprint_wrapper.called is True
298 298
299 299
300 300 def test_collections_userlist():
301 301 # Create userlist with cycle
302 302 a = UserList()
303 303 a.append(a)
304 304
305 305 cases = [
306 306 (UserList(), "UserList([])"),
307 307 (
308 308 UserList(i for i in range(1000, 1020)),
309 309 "UserList([1000,\n"
310 310 " 1001,\n"
311 311 " 1002,\n"
312 312 " 1003,\n"
313 313 " 1004,\n"
314 314 " 1005,\n"
315 315 " 1006,\n"
316 316 " 1007,\n"
317 317 " 1008,\n"
318 318 " 1009,\n"
319 319 " 1010,\n"
320 320 " 1011,\n"
321 321 " 1012,\n"
322 322 " 1013,\n"
323 323 " 1014,\n"
324 324 " 1015,\n"
325 325 " 1016,\n"
326 326 " 1017,\n"
327 327 " 1018,\n"
328 328 " 1019])",
329 329 ),
330 330 (a, "UserList([UserList(...)])"),
331 331 ]
332 332 for obj, expected in cases:
333 333 assert pretty.pretty(obj) == expected
334 334
335 335
336 336 # TODO : pytest.mark.parametrise once nose is gone.
337 337 def test_collections_defaultdict():
338 338 # Create defaultdicts with cycles
339 339 a = defaultdict()
340 340 a.default_factory = a
341 341 b = defaultdict(list)
342 342 b['key'] = b
343 343
344 344 # Dictionary order cannot be relied on, test against single keys.
345 345 cases = [
346 346 (defaultdict(list), 'defaultdict(list, {})'),
347 347 (defaultdict(list, {'key': '-' * 50}),
348 348 "defaultdict(list,\n"
349 349 " {'key': '--------------------------------------------------'})"),
350 350 (a, 'defaultdict(defaultdict(...), {})'),
351 351 (b, "defaultdict(list, {'key': defaultdict(...)})"),
352 352 ]
353 353 for obj, expected in cases:
354 354 assert pretty.pretty(obj) == expected
355 355
356 356
357 357 # TODO : pytest.mark.parametrise once nose is gone.
358 358 def test_collections_ordereddict():
359 359 # Create OrderedDict with cycle
360 360 a = OrderedDict()
361 361 a['key'] = a
362 362
363 363 cases = [
364 364 (OrderedDict(), 'OrderedDict()'),
365 365 (OrderedDict((i, i) for i in range(1000, 1010)),
366 366 'OrderedDict([(1000, 1000),\n'
367 367 ' (1001, 1001),\n'
368 368 ' (1002, 1002),\n'
369 369 ' (1003, 1003),\n'
370 370 ' (1004, 1004),\n'
371 371 ' (1005, 1005),\n'
372 372 ' (1006, 1006),\n'
373 373 ' (1007, 1007),\n'
374 374 ' (1008, 1008),\n'
375 375 ' (1009, 1009)])'),
376 376 (a, "OrderedDict([('key', OrderedDict(...))])"),
377 377 ]
378 378 for obj, expected in cases:
379 379 assert pretty.pretty(obj) == expected
380 380
381 381
382 382 # TODO : pytest.mark.parametrise once nose is gone.
383 383 def test_collections_deque():
384 384 # Create deque with cycle
385 385 a = deque()
386 386 a.append(a)
387 387
388 388 cases = [
389 389 (deque(), 'deque([])'),
390 390 (deque(i for i in range(1000, 1020)),
391 391 'deque([1000,\n'
392 392 ' 1001,\n'
393 393 ' 1002,\n'
394 394 ' 1003,\n'
395 395 ' 1004,\n'
396 396 ' 1005,\n'
397 397 ' 1006,\n'
398 398 ' 1007,\n'
399 399 ' 1008,\n'
400 400 ' 1009,\n'
401 401 ' 1010,\n'
402 402 ' 1011,\n'
403 403 ' 1012,\n'
404 404 ' 1013,\n'
405 405 ' 1014,\n'
406 406 ' 1015,\n'
407 407 ' 1016,\n'
408 408 ' 1017,\n'
409 409 ' 1018,\n'
410 410 ' 1019])'),
411 411 (a, 'deque([deque(...)])'),
412 412 ]
413 413 for obj, expected in cases:
414 414 assert pretty.pretty(obj) == expected
415 415
416 416
417 417 # TODO : pytest.mark.parametrise once nose is gone.
418 418 def test_collections_counter():
419 419 class MyCounter(Counter):
420 420 pass
421 421 cases = [
422 422 (Counter(), 'Counter()'),
423 423 (Counter(a=1), "Counter({'a': 1})"),
424 424 (MyCounter(a=1), "MyCounter({'a': 1})"),
425 (Counter(a=1, c=22), "Counter({'c': 22, 'a': 1})")
425 426 ]
426 427 for obj, expected in cases:
427 428 assert pretty.pretty(obj) == expected
428 429
429 430 # TODO : pytest.mark.parametrise once nose is gone.
430 431 def test_mappingproxy():
431 432 MP = types.MappingProxyType
432 433 underlying_dict = {}
433 434 mp_recursive = MP(underlying_dict)
434 435 underlying_dict[2] = mp_recursive
435 436 underlying_dict[3] = underlying_dict
436 437
437 438 cases = [
438 439 (MP({}), "mappingproxy({})"),
439 440 (MP({None: MP({})}), "mappingproxy({None: mappingproxy({})})"),
440 441 (MP({k: k.upper() for k in string.ascii_lowercase}),
441 442 "mappingproxy({'a': 'A',\n"
442 443 " 'b': 'B',\n"
443 444 " 'c': 'C',\n"
444 445 " 'd': 'D',\n"
445 446 " 'e': 'E',\n"
446 447 " 'f': 'F',\n"
447 448 " 'g': 'G',\n"
448 449 " 'h': 'H',\n"
449 450 " 'i': 'I',\n"
450 451 " 'j': 'J',\n"
451 452 " 'k': 'K',\n"
452 453 " 'l': 'L',\n"
453 454 " 'm': 'M',\n"
454 455 " 'n': 'N',\n"
455 456 " 'o': 'O',\n"
456 457 " 'p': 'P',\n"
457 458 " 'q': 'Q',\n"
458 459 " 'r': 'R',\n"
459 460 " 's': 'S',\n"
460 461 " 't': 'T',\n"
461 462 " 'u': 'U',\n"
462 463 " 'v': 'V',\n"
463 464 " 'w': 'W',\n"
464 465 " 'x': 'X',\n"
465 466 " 'y': 'Y',\n"
466 467 " 'z': 'Z'})"),
467 468 (mp_recursive, "mappingproxy({2: {...}, 3: {2: {...}, 3: {...}}})"),
468 469 (underlying_dict,
469 470 "{2: mappingproxy({2: {...}, 3: {...}}), 3: {...}}"),
470 471 ]
471 472 for obj, expected in cases:
472 473 assert pretty.pretty(obj) == expected
473 474
474 475
475 476 # TODO : pytest.mark.parametrise once nose is gone.
476 477 def test_simplenamespace():
477 478 SN = types.SimpleNamespace
478 479
479 480 sn_recursive = SN()
480 481 sn_recursive.first = sn_recursive
481 482 sn_recursive.second = sn_recursive
482 483 cases = [
483 484 (SN(), "namespace()"),
484 485 (SN(x=SN()), "namespace(x=namespace())"),
485 486 (SN(a_long_name=[SN(s=string.ascii_lowercase)]*3, a_short_name=None),
486 487 "namespace(a_long_name=[namespace(s='abcdefghijklmnopqrstuvwxyz'),\n"
487 488 " namespace(s='abcdefghijklmnopqrstuvwxyz'),\n"
488 489 " namespace(s='abcdefghijklmnopqrstuvwxyz')],\n"
489 490 " a_short_name=None)"),
490 491 (sn_recursive, "namespace(first=namespace(...), second=namespace(...))"),
491 492 ]
492 493 for obj, expected in cases:
493 494 assert pretty.pretty(obj) == expected
494 495
495 496
496 497 def test_pretty_environ():
497 498 dict_repr = pretty.pretty(dict(os.environ))
498 499 # reindent to align with 'environ' prefix
499 500 dict_indented = dict_repr.replace('\n', '\n' + (' ' * len('environ')))
500 501 env_repr = pretty.pretty(os.environ)
501 502 assert env_repr == "environ" + dict_indented
502 503
503 504
504 505 def test_function_pretty():
505 506 "Test pretty print of function"
506 507 # posixpath is a pure python module, its interface is consistent
507 508 # across Python distributions
508 509 import posixpath
509 510
510 511 assert pretty.pretty(posixpath.join) == "<function posixpath.join(a, *p)>"
511 512
512 513 # custom function
513 514 def meaning_of_life(question=None):
514 515 if question:
515 516 return 42
516 517 return "Don't panic"
517 518
518 519 assert "meaning_of_life(question=None)" in pretty.pretty(meaning_of_life)
519 520
520 521
521 522 class OrderedCounter(Counter, OrderedDict):
522 523 'Counter that remembers the order elements are first encountered'
523 524
524 525 def __repr__(self):
525 526 return '%s(%r)' % (self.__class__.__name__, OrderedDict(self))
526 527
527 528 def __reduce__(self):
528 529 return self.__class__, (OrderedDict(self),)
529 530
530 531 class MySet(set): # Override repr of a basic type
531 532 def __repr__(self):
532 533 return 'mine'
533 534
534 535 def test_custom_repr():
535 536 """A custom repr should override a pretty printer for a parent type"""
536 537 oc = OrderedCounter("abracadabra")
537 538 assert "OrderedCounter(OrderedDict" in pretty.pretty(oc)
538 539
539 540 assert pretty.pretty(MySet()) == "mine"
General Comments 0
You need to be logged in to leave comments. Login now