Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/hypothesis/vendor/pretty.py: 40%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

459 statements  

1# This file is part of Hypothesis, which may be found at 

2# https://github.com/HypothesisWorks/hypothesis/ 

3# 

4# Copyright the Hypothesis Authors. 

5# Individual contributors are listed in AUTHORS.rst and the git log. 

6# 

7# This Source Code Form is subject to the terms of the Mozilla Public License, 

8# v. 2.0. If a copy of the MPL was not distributed with this file, You can 

9# obtain one at https://mozilla.org/MPL/2.0/. 

10 

11""" 

12Python advanced pretty printer. This pretty printer is intended to 

13replace the old `pprint` python module which does not allow developers 

14to provide their own pretty print callbacks. 

15This module is based on ruby's `prettyprint.rb` library by `Tanaka Akira`. 

16Example Usage 

17------------- 

18To get a string of the output use `pretty`:: 

19 from pretty import pretty 

20 string = pretty(complex_object) 

21Extending 

22--------- 

23The pretty library allows developers to add pretty printing rules for their 

24own objects. This process is straightforward. All you have to do is to 

25add a `_repr_pretty_` method to your object and call the methods on the 

26pretty printer passed:: 

27 class MyObject(object): 

28 def _repr_pretty_(self, p, cycle): 

29 ... 

30Here is an example implementation of a `_repr_pretty_` method for a list 

31subclass:: 

32 class MyList(list): 

33 def _repr_pretty_(self, p, cycle): 

34 if cycle: 

35 p.text('MyList(...)') 

36 else: 

37 with p.group(8, 'MyList([', '])'): 

38 for idx, item in enumerate(self): 

39 if idx: 

40 p.text(',') 

41 p.breakable() 

42 p.pretty(item) 

43The `cycle` parameter is `True` if pretty detected a cycle. You *have* to 

44react to that or the result is an infinite loop. `p.text()` just adds 

45non breaking text to the output, `p.breakable()` either adds a whitespace 

46or breaks here. If you pass it an argument it's used instead of the 

47default space. `p.pretty` prettyprints another object using the pretty print 

48method. 

49The first parameter to the `group` function specifies the extra indentation 

50of the next line. In this example the next item will either be on the same 

51line (if the items are short enough) or aligned with the right edge of the 

52opening bracket of `MyList`. 

53If you just want to indent something you can use the group function 

54without open / close parameters. You can also use this code:: 

55 with p.indent(2): 

56 ... 

57Inheritance diagram: 

58.. inheritance-diagram:: IPython.lib.pretty 

59 :parts: 3 

60:copyright: 2007 by Armin Ronacher. 

61 Portions (c) 2009 by Robert Kern. 

62:license: BSD License. 

63""" 

64 

65import datetime 

66import re 

67import struct 

68import sys 

69import types 

70import warnings 

71from collections import defaultdict, deque 

72from contextlib import contextmanager 

73from enum import Flag 

74from io import StringIO 

75from math import copysign, isnan 

76 

77__all__ = [ 

78 "pretty", 

79 "IDKey", 

80 "RepresentationPrinter", 

81] 

82 

83 

84def _safe_getattr(obj, attr, default=None): 

85 """Safe version of getattr. 

86 

87 Same as getattr, but will return ``default`` on any Exception, 

88 rather than raising. 

89 

90 """ 

91 try: 

92 return getattr(obj, attr, default) 

93 except Exception: 

94 return default 

95 

96 

97def pretty(obj): 

98 """Pretty print the object's representation.""" 

99 printer = RepresentationPrinter() 

100 printer.pretty(obj) 

101 return printer.getvalue() 

102 

103 

104class IDKey: 

105 def __init__(self, value): 

106 self.value = value 

107 

108 def __hash__(self) -> int: 

109 return hash((type(self), id(self.value))) 

110 

111 def __eq__(self, __o: object) -> bool: 

112 return isinstance(__o, type(self)) and id(self.value) == id(__o.value) 

113 

114 

115class RepresentationPrinter: 

116 """Special pretty printer that has a `pretty` method that calls the pretty 

117 printer for a python object. 

118 

119 This class stores processing data on `self` so you must *never* use 

120 this class in a threaded environment. Always lock it or 

121 reinstantiate it. 

122 

123 """ 

124 

125 def __init__(self, output=None, *, context=None): 

126 """Pass the output stream, and optionally the current build context. 

127 

128 We use the context to represent objects constructed by strategies by showing 

129 *how* they were constructed, and add annotations showing which parts of the 

130 minimal failing example can vary without changing the test result. 

131 """ 

132 self.broken = False 

133 self.output = StringIO() if output is None else output 

134 self.max_width = 79 

135 self.max_seq_length = 1000 

136 self.output_width = 0 

137 self.buffer_width = 0 

138 self.buffer = deque() 

139 

140 root_group = Group(0) 

141 self.group_stack = [root_group] 

142 self.group_queue = GroupQueue(root_group) 

143 self.indentation = 0 

144 

145 self.snans = 0 

146 

147 self.stack = [] 

148 self.singleton_pprinters = {} 

149 self.type_pprinters = {} 

150 self.deferred_pprinters = {} 

151 # If IPython has been imported, load up their pretty-printer registry 

152 if "IPython.lib.pretty" in sys.modules: 

153 ipp = sys.modules["IPython.lib.pretty"] 

154 self.singleton_pprinters.update(ipp._singleton_pprinters) 

155 self.type_pprinters.update(ipp._type_pprinters) 

156 self.deferred_pprinters.update(ipp._deferred_type_pprinters) 

157 # If there's overlap between our pprinters and IPython's, we'll use ours. 

158 self.singleton_pprinters.update(_singleton_pprinters) 

159 self.type_pprinters.update(_type_pprinters) 

160 self.deferred_pprinters.update(_deferred_type_pprinters) 

161 

162 # for which-parts-matter, we track a mapping from the (start_idx, end_idx) 

163 # of slices into the minimal failing example; this is per-interesting_origin 

164 # but we report each separately so that's someone else's problem here. 

165 # Invocations of self.repr_call() can report the slice for each argument, 

166 # which will then be used to look up the relevant comment if any. 

167 if context is None: 

168 self.known_object_printers = defaultdict(list) 

169 self.slice_comments = {} 

170 else: 

171 self.known_object_printers = context.known_object_printers 

172 self.slice_comments = context.data.slice_comments 

173 assert all(isinstance(k, IDKey) for k in self.known_object_printers) 

174 

175 def pretty(self, obj): 

176 """Pretty print the given object.""" 

177 obj_id = id(obj) 

178 cycle = obj_id in self.stack 

179 self.stack.append(obj_id) 

180 try: 

181 with self.group(): 

182 obj_class = _safe_getattr(obj, "__class__", None) or type(obj) 

183 # First try to find registered singleton printers for the type. 

184 try: 

185 printer = self.singleton_pprinters[obj_id] 

186 except (TypeError, KeyError): 

187 pass 

188 else: 

189 return printer(obj, self, cycle) 

190 # Next walk the mro and check for either: 

191 # 1) a registered printer 

192 # 2) a _repr_pretty_ method 

193 for cls in obj_class.__mro__: 

194 if cls in self.type_pprinters: 

195 # printer registered in self.type_pprinters 

196 return self.type_pprinters[cls](obj, self, cycle) 

197 else: 

198 # Check if the given class is specified in the deferred type 

199 # registry; move it to the regular type registry if so. 

200 key = ( 

201 _safe_getattr(cls, "__module__", None), 

202 _safe_getattr(cls, "__name__", None), 

203 ) 

204 if key in self.deferred_pprinters: 

205 # Move the printer over to the regular registry. 

206 printer = self.deferred_pprinters.pop(key) 

207 self.type_pprinters[cls] = printer 

208 return printer(obj, self, cycle) 

209 else: 

210 # Finally look for special method names. 

211 # Some objects automatically create any requested 

212 # attribute. Try to ignore most of them by checking for 

213 # callability. 

214 if "_repr_pretty_" in cls.__dict__: 

215 meth = cls._repr_pretty_ 

216 if callable(meth): 

217 return meth(obj, self, cycle) 

218 # Now check for object-specific printers which show how this 

219 # object was constructed (a Hypothesis special feature). 

220 printers = self.known_object_printers[IDKey(obj)] 

221 if len(printers) == 1: 

222 return printers[0](obj, self, cycle) 

223 elif printers: 

224 # We've ended up with multiple registered functions for the same 

225 # object, which must have been returned from multiple calls due to 

226 # e.g. memoization. If they all return the same string, we'll use 

227 # the first; otherwise we'll pretend that *none* were registered. 

228 # 

229 # It's annoying, but still seems to be the best option for which- 

230 # parts-matter too, as unreportable results aren't very useful. 

231 strs = set() 

232 for f in printers: 

233 p = RepresentationPrinter() 

234 f(obj, p, cycle) 

235 strs.add(p.getvalue()) 

236 if len(strs) == 1: 

237 return printers[0](obj, self, cycle) 

238 

239 # A user-provided repr. Find newlines and replace them with p.break_() 

240 return _repr_pprint(obj, self, cycle) 

241 finally: 

242 self.stack.pop() 

243 

244 def _break_outer_groups(self): 

245 while self.max_width < self.output_width + self.buffer_width: 

246 group = self.group_queue.deq() 

247 if not group: 

248 return 

249 while group.breakables: 

250 x = self.buffer.popleft() 

251 self.output_width = x.output(self.output, self.output_width) 

252 self.buffer_width -= x.width 

253 while self.buffer and isinstance(self.buffer[0], Text): 

254 x = self.buffer.popleft() 

255 self.output_width = x.output(self.output, self.output_width) 

256 self.buffer_width -= x.width 

257 

258 def text(self, obj): 

259 """Add literal text to the output.""" 

260 width = len(obj) 

261 if self.buffer: 

262 text = self.buffer[-1] 

263 if not isinstance(text, Text): 

264 text = Text() 

265 self.buffer.append(text) 

266 text.add(obj, width) 

267 self.buffer_width += width 

268 self._break_outer_groups() 

269 else: 

270 self.output.write(obj) 

271 self.output_width += width 

272 

273 def breakable(self, sep=" "): 

274 """Add a breakable separator to the output. 

275 

276 This does not mean that it will automatically break here. If no 

277 breaking on this position takes place the `sep` is inserted 

278 which default to one space. 

279 

280 """ 

281 width = len(sep) 

282 group = self.group_stack[-1] 

283 if group.want_break: 

284 self.flush() 

285 self.output.write("\n" + " " * self.indentation) 

286 self.output_width = self.indentation 

287 self.buffer_width = 0 

288 else: 

289 self.buffer.append(Breakable(sep, width, self)) 

290 self.buffer_width += width 

291 self._break_outer_groups() 

292 

293 def break_(self): 

294 """Explicitly insert a newline into the output, maintaining correct 

295 indentation.""" 

296 self.flush() 

297 self.output.write("\n" + " " * self.indentation) 

298 self.output_width = self.indentation 

299 self.buffer_width = 0 

300 

301 @contextmanager 

302 def indent(self, indent): 

303 """`with`-statement support for indenting/dedenting.""" 

304 self.indentation += indent 

305 try: 

306 yield 

307 finally: 

308 self.indentation -= indent 

309 

310 @contextmanager 

311 def group(self, indent=0, open="", close=""): 

312 """Context manager for an indented group. 

313 

314 with p.group(1, '{', '}'): 

315 

316 The first parameter specifies the indentation for the next line 

317 (usually the width of the opening text), the second and third the 

318 opening and closing delimiters. 

319 """ 

320 self.begin_group(indent=indent, open=open) 

321 try: 

322 yield 

323 finally: 

324 self.end_group(dedent=indent, close=close) 

325 

326 def begin_group(self, indent=0, open=""): 

327 """Use the `with group(...) context manager instead. 

328 

329 The begin_group() and end_group() methods are for IPython compatibility only; 

330 see https://github.com/HypothesisWorks/hypothesis/issues/3721 for details. 

331 """ 

332 if open: 

333 self.text(open) 

334 group = Group(self.group_stack[-1].depth + 1) 

335 self.group_stack.append(group) 

336 self.group_queue.enq(group) 

337 self.indentation += indent 

338 

339 def end_group(self, dedent=0, close=""): 

340 """See begin_group().""" 

341 self.indentation -= dedent 

342 group = self.group_stack.pop() 

343 if not group.breakables: 

344 self.group_queue.remove(group) 

345 if close: 

346 self.text(close) 

347 

348 def _enumerate(self, seq): 

349 """Like enumerate, but with an upper limit on the number of items.""" 

350 for idx, x in enumerate(seq): 

351 if self.max_seq_length and idx >= self.max_seq_length: 

352 self.text(",") 

353 self.breakable() 

354 self.text("...") 

355 return 

356 yield idx, x 

357 

358 def flush(self): 

359 """Flush data that is left in the buffer.""" 

360 if self.snans: 

361 # Reset self.snans *before* calling breakable(), which might flush() 

362 snans = self.snans 

363 self.snans = 0 

364 self.breakable(" ") 

365 self.text(f"# Saw {snans} signaling NaN" + "s" * (snans > 1)) 

366 for data in self.buffer: 

367 self.output_width += data.output(self.output, self.output_width) 

368 self.buffer.clear() 

369 self.buffer_width = 0 

370 

371 def getvalue(self): 

372 assert isinstance(self.output, StringIO) 

373 self.flush() 

374 return self.output.getvalue() 

375 

376 def repr_call( 

377 self, 

378 func_name, 

379 args, 

380 kwargs, 

381 *, 

382 force_split=None, 

383 arg_slices=None, 

384 leading_comment=None, 

385 ): 

386 """Helper function to represent a function call. 

387 

388 - func_name, args, and kwargs should all be pretty obvious. 

389 - If split_lines, we'll force one-argument-per-line; otherwise we'll place 

390 calls that fit on a single line (and split otherwise). 

391 - arg_slices is a mapping from pos-idx or keyword to (start_idx, end_idx) 

392 of the Conjecture buffer, by which we can look up comments to add. 

393 """ 

394 assert isinstance(func_name, str) 

395 if func_name.startswith(("lambda:", "lambda ")): 

396 func_name = f"({func_name})" 

397 self.text(func_name) 

398 all_args = [(None, v) for v in args] + list(kwargs.items()) 

399 comments = { 

400 k: self.slice_comments[v] 

401 for k, v in (arg_slices or {}).items() 

402 if v in self.slice_comments 

403 } 

404 

405 if leading_comment or any(k in comments for k, _ in all_args): 

406 # We have to split one arg per line in order to leave comments on them. 

407 force_split = True 

408 if force_split is None: 

409 # We're OK with printing this call on a single line, but will it fit? 

410 # If not, we'd rather fall back to one-argument-per-line instead. 

411 p = RepresentationPrinter() 

412 p.stack = self.stack.copy() 

413 p.known_object_printers = self.known_object_printers 

414 p.repr_call("_" * self.output_width, args, kwargs, force_split=False) 

415 s = p.getvalue() 

416 force_split = "\n" in s 

417 

418 with self.group(indent=4, open="(", close=""): 

419 for i, (k, v) in enumerate(all_args): 

420 if force_split: 

421 if i == 0 and leading_comment: 

422 self.break_() 

423 self.text(leading_comment) 

424 self.break_() 

425 else: 

426 self.breakable(" " if i else "") 

427 if k: 

428 self.text(f"{k}=") 

429 self.pretty(v) 

430 if force_split or i + 1 < len(all_args): 

431 self.text(",") 

432 # Optional comments are used to annotate which-parts-matter 

433 comment = comments.get(i) or comments.get(k) 

434 if comment: 

435 self.text(f" # {comment}") 

436 if all_args and force_split: 

437 self.break_() 

438 self.text(")") # after dedent 

439 

440 

441class Printable: 

442 def output(self, stream, output_width): # pragma: no cover 

443 raise NotImplementedError 

444 

445 

446class Text(Printable): 

447 def __init__(self): 

448 self.objs = [] 

449 self.width = 0 

450 

451 def output(self, stream, output_width): 

452 for obj in self.objs: 

453 stream.write(obj) 

454 return output_width + self.width 

455 

456 def add(self, obj, width): 

457 self.objs.append(obj) 

458 self.width += width 

459 

460 

461class Breakable(Printable): 

462 def __init__(self, seq, width, pretty): 

463 self.obj = seq 

464 self.width = width 

465 self.pretty = pretty 

466 self.indentation = pretty.indentation 

467 self.group = pretty.group_stack[-1] 

468 self.group.breakables.append(self) 

469 

470 def output(self, stream, output_width): 

471 self.group.breakables.popleft() 

472 if self.group.want_break: 

473 stream.write("\n" + " " * self.indentation) 

474 return self.indentation 

475 if not self.group.breakables: 

476 self.pretty.group_queue.remove(self.group) 

477 stream.write(self.obj) 

478 return output_width + self.width 

479 

480 

481class Group(Printable): 

482 def __init__(self, depth): 

483 self.depth = depth 

484 self.breakables = deque() 

485 self.want_break = False 

486 

487 

488class GroupQueue: 

489 def __init__(self, *groups): 

490 self.queue = [] 

491 for group in groups: 

492 self.enq(group) 

493 

494 def enq(self, group): 

495 depth = group.depth 

496 while depth > len(self.queue) - 1: 

497 self.queue.append([]) 

498 self.queue[depth].append(group) 

499 

500 def deq(self): 

501 for stack in self.queue: 

502 for idx, group in enumerate(reversed(stack)): 

503 if group.breakables: 

504 del stack[idx] 

505 group.want_break = True 

506 return group 

507 for group in stack: 

508 group.want_break = True 

509 del stack[:] 

510 

511 def remove(self, group): 

512 try: 

513 self.queue[group.depth].remove(group) 

514 except ValueError: 

515 pass 

516 

517 

518def _seq_pprinter_factory(start, end, basetype): 

519 """Factory that returns a pprint function useful for sequences. 

520 

521 Used by the default pprint for tuples, dicts, and lists. 

522 """ 

523 

524 def inner(obj, p, cycle): 

525 typ = type(obj) 

526 if ( 

527 basetype is not None 

528 and typ is not basetype 

529 and typ.__repr__ != basetype.__repr__ 

530 ): 

531 # If the subclass provides its own repr, use it instead. 

532 return p.text(typ.__repr__(obj)) 

533 

534 if cycle: 

535 return p.text(start + "..." + end) 

536 step = len(start) 

537 with p.group(step, start, end): 

538 for idx, x in p._enumerate(obj): 

539 if idx: 

540 p.text(",") 

541 p.breakable() 

542 p.pretty(x) 

543 if len(obj) == 1 and type(obj) is tuple: 

544 # Special case for 1-item tuples. 

545 p.text(",") 

546 

547 return inner 

548 

549 

550def _set_pprinter_factory(start, end, basetype): 

551 """Factory that returns a pprint function useful for sets and 

552 frozensets.""" 

553 

554 def inner(obj, p, cycle): 

555 typ = type(obj) 

556 if ( 

557 basetype is not None 

558 and typ is not basetype 

559 and typ.__repr__ != basetype.__repr__ 

560 ): 

561 # If the subclass provides its own repr, use it instead. 

562 return p.text(typ.__repr__(obj)) 

563 

564 if cycle: 

565 return p.text(start + "..." + end) 

566 if not obj: 

567 # Special case. 

568 p.text(basetype.__name__ + "()") 

569 else: 

570 step = len(start) 

571 with p.group(step, start, end): 

572 # Like dictionary keys, try to sort the items if there aren't too many 

573 items = obj 

574 if not (p.max_seq_length and len(obj) >= p.max_seq_length): 

575 try: 

576 items = sorted(obj) 

577 except Exception: 

578 # Sometimes the items don't sort. 

579 pass 

580 for idx, x in p._enumerate(items): 

581 if idx: 

582 p.text(",") 

583 p.breakable() 

584 p.pretty(x) 

585 

586 return inner 

587 

588 

589def _dict_pprinter_factory(start, end, basetype=None): 

590 """Factory that returns a pprint function used by the default pprint of 

591 dicts and dict proxies.""" 

592 

593 def inner(obj, p, cycle): 

594 typ = type(obj) 

595 if ( 

596 basetype is not None 

597 and typ is not basetype 

598 and typ.__repr__ != basetype.__repr__ 

599 ): 

600 # If the subclass provides its own repr, use it instead. 

601 return p.text(typ.__repr__(obj)) 

602 

603 if cycle: 

604 return p.text("{...}") 

605 with p.group(1, start, end): 

606 # If the dict contains both "" and b"" (empty string and empty bytes), we 

607 # ignore the BytesWarning raised by `python -bb` mode. We can't use 

608 # `.items()` because it might be a non-`dict` type of mapping. 

609 with warnings.catch_warnings(): 

610 warnings.simplefilter("ignore", BytesWarning) 

611 for idx, key in p._enumerate(obj): 

612 if idx: 

613 p.text(",") 

614 p.breakable() 

615 p.pretty(key) 

616 p.text(": ") 

617 p.pretty(obj[key]) 

618 

619 inner.__name__ = f"_dict_pprinter_factory({start!r}, {end!r}, {basetype!r})" 

620 return inner 

621 

622 

623def _super_pprint(obj, p, cycle): 

624 """The pprint for the super type.""" 

625 with p.group(8, "<super: ", ">"): 

626 p.pretty(obj.__thisclass__) 

627 p.text(",") 

628 p.breakable() 

629 p.pretty(obj.__self__) 

630 

631 

632def _re_pattern_pprint(obj, p, cycle): 

633 """The pprint function for regular expression patterns.""" 

634 p.text("re.compile(") 

635 pattern = repr(obj.pattern) 

636 if pattern[:1] in "uU": # pragma: no cover 

637 pattern = pattern[1:] 

638 prefix = "ur" 

639 else: 

640 prefix = "r" 

641 pattern = prefix + pattern.replace("\\\\", "\\") 

642 p.text(pattern) 

643 if obj.flags: 

644 p.text(",") 

645 p.breakable() 

646 done_one = False 

647 for flag in ( 

648 "TEMPLATE", 

649 "IGNORECASE", 

650 "LOCALE", 

651 "MULTILINE", 

652 "DOTALL", 

653 "UNICODE", 

654 "VERBOSE", 

655 "DEBUG", 

656 ): 

657 if obj.flags & getattr(re, flag, 0): 

658 if done_one: 

659 p.text("|") 

660 p.text("re." + flag) 

661 done_one = True 

662 p.text(")") 

663 

664 

665def _type_pprint(obj, p, cycle): 

666 """The pprint for classes and types.""" 

667 # Heap allocated types might not have the module attribute, 

668 # and others may set it to None. 

669 

670 # Checks for a __repr__ override in the metaclass 

671 # != rather than is not because pypy compatibility 

672 if type(obj).__repr__ != type.__repr__: 

673 _repr_pprint(obj, p, cycle) 

674 return 

675 

676 mod = _safe_getattr(obj, "__module__", None) 

677 try: 

678 name = obj.__qualname__ 

679 if not isinstance(name, str): # pragma: no cover 

680 # This can happen if the type implements __qualname__ as a property 

681 # or other descriptor in Python 2. 

682 raise Exception("Try __name__") 

683 except Exception: # pragma: no cover 

684 name = obj.__name__ 

685 if not isinstance(name, str): 

686 name = "<unknown type>" 

687 

688 if mod in (None, "__builtin__", "builtins", "exceptions"): 

689 p.text(name) 

690 else: 

691 p.text(mod + "." + name) 

692 

693 

694def _repr_pprint(obj, p, cycle): 

695 """A pprint that just redirects to the normal repr function.""" 

696 # Find newlines and replace them with p.break_() 

697 output = repr(obj) 

698 for idx, output_line in enumerate(output.splitlines()): 

699 if idx: 

700 p.break_() 

701 p.text(output_line) 

702 

703 

704def _function_pprint(obj, p, cycle): 

705 """Base pprint for all functions and builtin functions.""" 

706 from hypothesis.internal.reflection import get_pretty_function_description 

707 

708 p.text(get_pretty_function_description(obj)) 

709 

710 

711def _exception_pprint(obj, p, cycle): 

712 """Base pprint for all exceptions.""" 

713 name = getattr(obj.__class__, "__qualname__", obj.__class__.__name__) 

714 if obj.__class__.__module__ not in ("exceptions", "builtins"): 

715 name = f"{obj.__class__.__module__}.{name}" 

716 step = len(name) + 1 

717 with p.group(step, name + "(", ")"): 

718 for idx, arg in enumerate(getattr(obj, "args", ())): 

719 if idx: 

720 p.text(",") 

721 p.breakable() 

722 p.pretty(arg) 

723 

724 

725def _repr_float_counting_nans(obj, p, cycle): 

726 if isnan(obj) and hasattr(p, "snans"): 

727 if struct.pack("!d", abs(obj)) != struct.pack("!d", float("nan")): 

728 p.snans += 1 

729 if copysign(1.0, obj) == -1.0: 

730 p.text("-nan") 

731 return 

732 p.text(repr(obj)) 

733 

734 

735#: printers for builtin types 

736_type_pprinters = { 

737 int: _repr_pprint, 

738 float: _repr_float_counting_nans, 

739 str: _repr_pprint, 

740 tuple: _seq_pprinter_factory("(", ")", tuple), 

741 list: _seq_pprinter_factory("[", "]", list), 

742 dict: _dict_pprinter_factory("{", "}", dict), 

743 set: _set_pprinter_factory("{", "}", set), 

744 frozenset: _set_pprinter_factory("frozenset({", "})", frozenset), 

745 super: _super_pprint, 

746 re.Pattern: _re_pattern_pprint, 

747 type: _type_pprint, 

748 types.FunctionType: _function_pprint, 

749 types.BuiltinFunctionType: _function_pprint, 

750 types.MethodType: _function_pprint, 

751 datetime.datetime: _repr_pprint, 

752 datetime.timedelta: _repr_pprint, 

753 BaseException: _exception_pprint, 

754 slice: _repr_pprint, 

755 range: _repr_pprint, 

756 bytes: _repr_pprint, 

757} 

758 

759#: printers for types specified by name 

760_deferred_type_pprinters = {} # type: ignore 

761 

762 

763def for_type_by_name(type_module, type_name, func): 

764 """Add a pretty printer for a type specified by the module and name of a 

765 type rather than the type object itself.""" 

766 key = (type_module, type_name) 

767 oldfunc = _deferred_type_pprinters.get(key) 

768 _deferred_type_pprinters[key] = func 

769 return oldfunc 

770 

771 

772#: printers for the default singletons 

773_singleton_pprinters = dict.fromkeys( 

774 map(id, [None, True, False, Ellipsis, NotImplemented]), _repr_pprint 

775) 

776 

777 

778def _defaultdict_pprint(obj, p, cycle): 

779 name = obj.__class__.__name__ 

780 with p.group(len(name) + 1, name + "(", ")"): 

781 if cycle: 

782 p.text("...") 

783 else: 

784 p.pretty(obj.default_factory) 

785 p.text(",") 

786 p.breakable() 

787 p.pretty(dict(obj)) 

788 

789 

790def _ordereddict_pprint(obj, p, cycle): 

791 name = obj.__class__.__name__ 

792 with p.group(len(name) + 1, name + "(", ")"): 

793 if cycle: 

794 p.text("...") 

795 elif obj: 

796 p.pretty(list(obj.items())) 

797 

798 

799def _deque_pprint(obj, p, cycle): 

800 name = obj.__class__.__name__ 

801 with p.group(len(name) + 1, name + "(", ")"): 

802 if cycle: 

803 p.text("...") 

804 else: 

805 p.pretty(list(obj)) 

806 

807 

808def _counter_pprint(obj, p, cycle): 

809 name = obj.__class__.__name__ 

810 with p.group(len(name) + 1, name + "(", ")"): 

811 if cycle: 

812 p.text("...") 

813 elif obj: 

814 p.pretty(dict(obj)) 

815 

816 

817def _repr_dataframe(obj, p, cycle): # pragma: no cover 

818 with p.indent(4): 

819 p.break_() 

820 _repr_pprint(obj, p, cycle) 

821 p.break_() 

822 

823 

824def _repr_enum(obj, p, cycle): 

825 tname = type(obj).__name__ 

826 if isinstance(obj, Flag): 

827 p.text( 

828 " | ".join(f"{tname}.{x.name}" for x in type(obj) if x & obj == x) 

829 or f"{tname}({obj.value!r})" # if no matching members 

830 ) 

831 else: 

832 p.text(f"{tname}.{obj.name}") 

833 

834 

835class _ReprDots: 

836 def __repr__(self) -> str: 

837 return "..." 

838 

839 

840def _repr_partial(obj, p, cycle): 

841 args, kw = obj.args, obj.keywords 

842 if cycle: 

843 args, kw = (_ReprDots(),), {} 

844 p.repr_call(pretty(type(obj)), (obj.func, *args), kw) 

845 

846 

847for_type_by_name("collections", "defaultdict", _defaultdict_pprint) 

848for_type_by_name("collections", "OrderedDict", _ordereddict_pprint) 

849for_type_by_name("ordereddict", "OrderedDict", _ordereddict_pprint) 

850for_type_by_name("collections", "deque", _deque_pprint) 

851for_type_by_name("collections", "Counter", _counter_pprint) 

852for_type_by_name("pandas.core.frame", "DataFrame", _repr_dataframe) 

853for_type_by_name("enum", "Enum", _repr_enum) 

854for_type_by_name("functools", "partial", _repr_partial)