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

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

510 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 ast 

66import datetime 

67import re 

68import struct 

69import sys 

70import types 

71import warnings 

72from collections import Counter, OrderedDict, defaultdict, deque 

73from collections.abc import Generator, Iterable, Sequence 

74from contextlib import contextmanager, suppress 

75from enum import Enum, Flag 

76from functools import partial 

77from io import StringIO, TextIOBase 

78from math import copysign, isnan 

79from typing import TYPE_CHECKING, Any, Callable, Optional, TypeVar, Union 

80 

81if TYPE_CHECKING: 

82 from typing import TypeAlias 

83 

84 from hypothesis.control import BuildContext 

85 

86# ruff: noqa: FBT001 

87 

88T = TypeVar("T") 

89PrettyPrintFunction: "TypeAlias" = Callable[[Any, "RepresentationPrinter", bool], None] 

90 

91__all__ = [ 

92 "IDKey", 

93 "RepresentationPrinter", 

94 "pretty", 

95] 

96 

97 

98def _safe_getattr(obj: object, attr: str, default: Optional[Any] = None) -> Any: 

99 """Safe version of getattr. 

100 

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

102 rather than raising. 

103 

104 """ 

105 try: 

106 return getattr(obj, attr, default) 

107 except Exception: 

108 return default 

109 

110 

111def pretty(obj: object) -> str: 

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

113 printer = RepresentationPrinter() 

114 printer.pretty(obj) 

115 return printer.getvalue() 

116 

117 

118class IDKey: 

119 def __init__(self, value: object): 

120 self.value = value 

121 

122 def __hash__(self) -> int: 

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

124 

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

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

127 

128 

129class RepresentationPrinter: 

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

131 printer for a python object. 

132 

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

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

135 reinstantiate it. 

136 

137 """ 

138 

139 def __init__( 

140 self, 

141 output: Optional[TextIOBase] = None, 

142 *, 

143 context: Optional["BuildContext"] = None, 

144 ) -> None: 

145 """Optionally pass the output stream and the current build context. 

146 

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

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

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

150 """ 

151 self.broken: bool = False 

152 self.output: TextIOBase = StringIO() if output is None else output 

153 self.max_width: int = 79 

154 self.max_seq_length: int = 1000 

155 self.output_width: int = 0 

156 self.buffer_width: int = 0 

157 self.buffer: deque[Union[Breakable, Text]] = deque() 

158 

159 root_group = Group(0) 

160 self.group_stack = [root_group] 

161 self.group_queue = GroupQueue(root_group) 

162 self.indentation: int = 0 

163 

164 self.stack: list[int] = [] 

165 self.singleton_pprinters: dict[int, PrettyPrintFunction] = {} 

166 self.type_pprinters: dict[type, PrettyPrintFunction] = {} 

167 self.deferred_pprinters: dict[tuple[str, str], PrettyPrintFunction] = {} 

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

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

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

171 self.singleton_pprinters.update(ipp._singleton_pprinters) 

172 self.type_pprinters.update(ipp._type_pprinters) 

173 self.deferred_pprinters.update(ipp._deferred_type_pprinters) 

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

175 self.singleton_pprinters.update(_singleton_pprinters) 

176 self.type_pprinters.update(_type_pprinters) 

177 self.deferred_pprinters.update(_deferred_type_pprinters) 

178 

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

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

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

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

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

184 self.known_object_printers: dict[IDKey, list[PrettyPrintFunction]] 

185 self.slice_comments: dict[tuple[int, int], str] 

186 if context is None: 

187 self.known_object_printers = defaultdict(list) 

188 self.slice_comments = {} 

189 else: 

190 self.known_object_printers = context.known_object_printers 

191 self.slice_comments = context.data.slice_comments 

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

193 

194 def pretty(self, obj: object) -> None: 

195 """Pretty print the given object.""" 

196 obj_id = id(obj) 

197 cycle = obj_id in self.stack 

198 self.stack.append(obj_id) 

199 try: 

200 with self.group(): 

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

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

203 try: 

204 printer = self.singleton_pprinters[obj_id] 

205 except (TypeError, KeyError): 

206 pass 

207 else: 

208 return printer(obj, self, cycle) 

209 

210 # Look for the _repr_pretty_ method which allows users 

211 # to define custom pretty printing. 

212 # Some objects automatically create any requested 

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

214 # callability. 

215 pretty_method = _safe_getattr(obj, "_repr_pretty_", None) 

216 if callable(pretty_method): 

217 return pretty_method(self, cycle) 

218 

219 # Next walk the mro and check for either: 

220 # 1) a registered printer 

221 # 2) a _repr_pretty_ method 

222 for cls in obj_class.__mro__: 

223 if cls in self.type_pprinters: 

224 # printer registered in self.type_pprinters 

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

226 else: 

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

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

229 key = ( 

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

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

232 ) 

233 if key in self.deferred_pprinters: 

234 # Move the printer over to the regular registry. 

235 printer = self.deferred_pprinters.pop(key) 

236 self.type_pprinters[cls] = printer 

237 return printer(obj, self, cycle) 

238 else: 

239 if hasattr(cls, "__attrs_attrs__"): 

240 return pprint_fields( 

241 obj, 

242 self, 

243 cycle, 

244 [at.name for at in cls.__attrs_attrs__ if at.init], 

245 ) 

246 if hasattr(cls, "__dataclass_fields__"): 

247 return pprint_fields( 

248 obj, 

249 self, 

250 cycle, 

251 [ 

252 k 

253 for k, v in cls.__dataclass_fields__.items() 

254 if v.init 

255 ], 

256 ) 

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

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

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

260 if len(printers) == 1: 

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

262 elif printers: 

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

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

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

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

267 # 

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

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

270 strs = set() 

271 for f in printers: 

272 p = RepresentationPrinter() 

273 f(obj, p, cycle) 

274 strs.add(p.getvalue()) 

275 if len(strs) == 1: 

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

277 

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

279 return _repr_pprint(obj, self, cycle) 

280 finally: 

281 self.stack.pop() 

282 

283 def _break_outer_groups(self) -> None: 

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

285 group = self.group_queue.deq() 

286 if not group: 

287 return 

288 while group.breakables: 

289 x = self.buffer.popleft() 

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

291 self.buffer_width -= x.width 

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

293 x = self.buffer.popleft() 

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

295 self.buffer_width -= x.width 

296 

297 def text(self, obj: str) -> None: 

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

299 width = len(obj) 

300 if self.buffer: 

301 text = self.buffer[-1] 

302 if not isinstance(text, Text): 

303 text = Text() 

304 self.buffer.append(text) 

305 text.add(obj, width) 

306 self.buffer_width += width 

307 self._break_outer_groups() 

308 else: 

309 self.output.write(obj) 

310 self.output_width += width 

311 

312 def breakable(self, sep: str = " ") -> None: 

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

314 

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

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

317 which default to one space. 

318 

319 """ 

320 width = len(sep) 

321 group = self.group_stack[-1] 

322 if group.want_break: 

323 self.flush() 

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

325 self.output_width = self.indentation 

326 self.buffer_width = 0 

327 else: 

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

329 self.buffer_width += width 

330 self._break_outer_groups() 

331 

332 def break_(self) -> None: 

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

334 indentation.""" 

335 self.flush() 

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

337 self.output_width = self.indentation 

338 self.buffer_width = 0 

339 

340 @contextmanager 

341 def indent(self, indent: int) -> Generator[None, None, None]: 

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

343 self.indentation += indent 

344 try: 

345 yield 

346 finally: 

347 self.indentation -= indent 

348 

349 @contextmanager 

350 def group( 

351 self, indent: int = 0, open: str = "", close: str = "" 

352 ) -> Generator[None, None, None]: 

353 """Context manager for an indented group. 

354 

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

356 

357 The first parameter specifies the indentation for the next line 

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

359 opening and closing delimiters. 

360 """ 

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

362 try: 

363 yield 

364 finally: 

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

366 

367 def begin_group(self, indent: int = 0, open: str = "") -> None: 

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

369 

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

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

372 """ 

373 if open: 

374 self.text(open) 

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

376 self.group_stack.append(group) 

377 self.group_queue.enq(group) 

378 self.indentation += indent 

379 

380 def end_group(self, dedent: int = 0, close: str = "") -> None: 

381 """See begin_group().""" 

382 self.indentation -= dedent 

383 group = self.group_stack.pop() 

384 if not group.breakables: 

385 self.group_queue.remove(group) 

386 if close: 

387 self.text(close) 

388 

389 def _enumerate(self, seq: Iterable[T]) -> Generator[tuple[int, T], None, None]: 

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

391 for idx, x in enumerate(seq): 

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

393 self.text(",") 

394 self.breakable() 

395 self.text("...") 

396 return 

397 yield idx, x 

398 

399 def flush(self) -> None: 

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

401 for data in self.buffer: 

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

403 self.buffer.clear() 

404 self.buffer_width = 0 

405 

406 def getvalue(self) -> str: 

407 assert isinstance(self.output, StringIO) 

408 self.flush() 

409 return self.output.getvalue() 

410 

411 def maybe_repr_known_object_as_call( 

412 self, 

413 obj: object, 

414 cycle: bool, 

415 name: str, 

416 args: Sequence[object], 

417 kwargs: dict[str, object], 

418 ) -> None: 

419 # pprint this object as a call, _unless_ the call would be invalid syntax 

420 # and the repr would be valid and there are not comments on arguments. 

421 if cycle: 

422 return self.text("<...>") 

423 # Since we don't yet track comments for sub-argument parts, we omit the 

424 # "if no comments" condition here for now. Add it when we revive 

425 # https://github.com/HypothesisWorks/hypothesis/pull/3624/ 

426 with suppress(Exception): 

427 # Check whether the repr is valid syntax: 

428 ast.parse(repr(obj)) 

429 # Given that the repr is valid syntax, check the call: 

430 p = RepresentationPrinter() 

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

432 p.known_object_printers = self.known_object_printers 

433 p.repr_call(name, args, kwargs) 

434 # If the call is not valid syntax, use the repr 

435 try: 

436 ast.parse(p.getvalue()) 

437 except Exception: 

438 return _repr_pprint(obj, self, cycle) 

439 return self.repr_call(name, args, kwargs) 

440 

441 def repr_call( 

442 self, 

443 func_name: str, 

444 args: Sequence[object], 

445 kwargs: dict[str, object], 

446 *, 

447 force_split: Optional[bool] = None, 

448 arg_slices: Optional[dict[str, tuple[int, int]]] = None, 

449 leading_comment: Optional[str] = None, 

450 avoid_realization: bool = False, 

451 ) -> None: 

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

453 

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

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

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

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

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

459 """ 

460 assert isinstance(func_name, str) 

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

462 func_name = f"({func_name})" 

463 self.text(func_name) 

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

465 # int indicates the position of a positional argument, rather than a keyword 

466 # argument. Currently no callers use this; see #3624. 

467 comments: dict[Union[int, str], object] = { 

468 k: self.slice_comments[v] 

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

470 if v in self.slice_comments 

471 } 

472 

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

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

475 force_split = True 

476 if force_split is None: 

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

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

479 p = RepresentationPrinter() 

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

481 p.known_object_printers = self.known_object_printers 

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

483 s = p.getvalue() 

484 force_split = "\n" in s 

485 

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

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

488 if force_split: 

489 if i == 0 and leading_comment: 

490 self.break_() 

491 self.text(leading_comment) 

492 self.break_() 

493 else: 

494 assert leading_comment is None # only passed by top-level report 

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

496 if k: 

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

498 if avoid_realization: 

499 self.text("<symbolic>") 

500 else: 

501 self.pretty(v) 

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

503 self.text(",") 

504 comment = None 

505 if k is not None: 

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

507 if comment: 

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

509 if all_args and force_split: 

510 self.break_() 

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

512 

513 

514class Printable: 

515 def output(self, stream: TextIOBase, output_width: int) -> int: # pragma: no cover 

516 raise NotImplementedError 

517 

518 

519class Text(Printable): 

520 def __init__(self) -> None: 

521 self.objs: list[str] = [] 

522 self.width: int = 0 

523 

524 def output(self, stream: TextIOBase, output_width: int) -> int: 

525 for obj in self.objs: 

526 stream.write(obj) 

527 return output_width + self.width 

528 

529 def add(self, obj: str, width: int) -> None: 

530 self.objs.append(obj) 

531 self.width += width 

532 

533 

534class Breakable(Printable): 

535 def __init__(self, seq: str, width: int, pretty: RepresentationPrinter) -> None: 

536 self.obj = seq 

537 self.width = width 

538 self.pretty = pretty 

539 self.indentation = pretty.indentation 

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

541 self.group.breakables.append(self) 

542 

543 def output(self, stream: TextIOBase, output_width: int) -> int: 

544 self.group.breakables.popleft() 

545 if self.group.want_break: 

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

547 return self.indentation 

548 if not self.group.breakables: 

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

550 stream.write(self.obj) 

551 return output_width + self.width 

552 

553 

554class Group(Printable): 

555 def __init__(self, depth: int) -> None: 

556 self.depth = depth 

557 self.breakables: deque[Breakable] = deque() 

558 self.want_break: bool = False 

559 

560 

561class GroupQueue: 

562 def __init__(self, *groups: Group) -> None: 

563 self.queue: list[list[Group]] = [] 

564 for group in groups: 

565 self.enq(group) 

566 

567 def enq(self, group: Group) -> None: 

568 depth = group.depth 

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

570 self.queue.append([]) 

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

572 

573 def deq(self) -> Optional[Group]: 

574 for stack in self.queue: 

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

576 if group.breakables: 

577 del stack[idx] 

578 group.want_break = True 

579 return group 

580 for group in stack: 

581 group.want_break = True 

582 del stack[:] 

583 return None 

584 

585 def remove(self, group: Group) -> None: 

586 try: 

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

588 except ValueError: 

589 pass 

590 

591 

592def _seq_pprinter_factory(start: str, end: str, basetype: type) -> PrettyPrintFunction: 

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

594 

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

596 """ 

597 

598 def inner( 

599 obj: Union[tuple[object], list[object]], p: RepresentationPrinter, cycle: bool 

600 ) -> None: 

601 typ = type(obj) 

602 if ( 

603 basetype is not None 

604 and typ is not basetype 

605 and typ.__repr__ != basetype.__repr__ # type: ignore[comparison-overlap] 

606 ): 

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

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

609 

610 if cycle: 

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

612 step = len(start) 

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

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

615 if idx: 

616 p.text(",") 

617 p.breakable() 

618 p.pretty(x) 

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

620 # Special case for 1-item tuples. 

621 p.text(",") 

622 

623 return inner 

624 

625 

626def get_class_name(cls: type[object]) -> str: 

627 class_name = _safe_getattr(cls, "__qualname__", cls.__name__) 

628 assert isinstance(class_name, str) 

629 return class_name 

630 

631 

632def _set_pprinter_factory( 

633 start: str, end: str, basetype: type[object] 

634) -> PrettyPrintFunction: 

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

636 frozensets.""" 

637 

638 def inner( 

639 obj: Union[set[Any], frozenset[Any]], 

640 p: RepresentationPrinter, 

641 cycle: bool, 

642 ) -> None: 

643 typ = type(obj) 

644 if ( 

645 basetype is not None 

646 and typ is not basetype 

647 and typ.__repr__ != basetype.__repr__ 

648 ): 

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

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

651 

652 if cycle: 

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

654 if not obj: 

655 # Special case. 

656 p.text(get_class_name(basetype) + "()") 

657 else: 

658 step = len(start) 

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

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

661 items: Iterable[object] = obj 

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

663 try: 

664 items = sorted(obj) 

665 except Exception: 

666 # Sometimes the items don't sort. 

667 pass 

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

669 if idx: 

670 p.text(",") 

671 p.breakable() 

672 p.pretty(x) 

673 

674 return inner 

675 

676 

677def _dict_pprinter_factory( 

678 start: str, end: str, basetype: Optional[type[object]] = None 

679) -> PrettyPrintFunction: 

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

681 dicts and dict proxies.""" 

682 

683 def inner(obj: dict[object, object], p: RepresentationPrinter, cycle: bool) -> None: 

684 typ = type(obj) 

685 if ( 

686 basetype is not None 

687 and typ is not basetype 

688 and typ.__repr__ != basetype.__repr__ 

689 ): 

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

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

692 

693 if cycle: 

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

695 # NOTE: For compatibility with Python 3.9's LL(1) 

696 # parser, this is written as a nested with-statement, 

697 # instead of a compound one. 

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

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

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

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

702 with warnings.catch_warnings(): 

703 warnings.simplefilter("ignore", BytesWarning) 

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

705 if idx: 

706 p.text(",") 

707 p.breakable() 

708 p.pretty(key) 

709 p.text(": ") 

710 p.pretty(obj[key]) 

711 

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

713 return inner 

714 

715 

716def _super_pprint(obj: Any, p: RepresentationPrinter, cycle: bool) -> None: 

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

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

719 p.pretty(obj.__thisclass__) 

720 p.text(",") 

721 p.breakable() 

722 p.pretty(obj.__self__) 

723 

724 

725def _re_pattern_pprint(obj: re.Pattern, p: RepresentationPrinter, cycle: bool) -> None: 

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

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

728 pattern = repr(obj.pattern) 

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

730 pattern = pattern[1:] 

731 prefix = "ur" 

732 else: 

733 prefix = "r" 

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

735 p.text(pattern) 

736 if obj.flags: 

737 p.text(",") 

738 p.breakable() 

739 done_one = False 

740 for flag in ( 

741 "TEMPLATE", 

742 "IGNORECASE", 

743 "LOCALE", 

744 "MULTILINE", 

745 "DOTALL", 

746 "UNICODE", 

747 "VERBOSE", 

748 "DEBUG", 

749 ): 

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

751 if done_one: 

752 p.text("|") 

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

754 done_one = True 

755 p.text(")") 

756 

757 

758def _type_pprint(obj: type[object], p: RepresentationPrinter, cycle: bool) -> None: 

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

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

761 # and others may set it to None. 

762 

763 # Checks for a __repr__ override in the metaclass 

764 # != rather than is not because pypy compatibility 

765 if type(obj).__repr__ != type.__repr__: # type: ignore[comparison-overlap] 

766 _repr_pprint(obj, p, cycle) 

767 return 

768 

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

770 try: 

771 name = obj.__qualname__ 

772 except Exception: # pragma: no cover 

773 name = obj.__name__ 

774 if not isinstance(name, str): 

775 name = "<unknown type>" 

776 

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

778 p.text(name) 

779 else: 

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

781 

782 

783def _repr_pprint(obj: object, p: RepresentationPrinter, cycle: bool) -> None: 

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

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

786 output = repr(obj) 

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

788 if idx: 

789 p.break_() 

790 p.text(output_line) 

791 

792 

793def pprint_fields( 

794 obj: object, p: RepresentationPrinter, cycle: bool, fields: Iterable[str] 

795) -> None: 

796 name = get_class_name(obj.__class__) 

797 if cycle: 

798 return p.text(f"{name}(...)") 

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

800 for idx, field in enumerate(fields): 

801 if idx: 

802 p.text(",") 

803 p.breakable() 

804 p.text(field) 

805 p.text("=") 

806 p.pretty(getattr(obj, field)) 

807 

808 

809def _function_pprint( 

810 obj: Union[types.FunctionType, types.BuiltinFunctionType, types.MethodType], 

811 p: RepresentationPrinter, 

812 cycle: bool, 

813) -> None: 

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

815 from hypothesis.internal.reflection import get_pretty_function_description 

816 

817 p.text(get_pretty_function_description(obj)) 

818 

819 

820def _exception_pprint( 

821 obj: BaseException, p: RepresentationPrinter, cycle: bool 

822) -> None: 

823 """Base pprint for all exceptions.""" 

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

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

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

827 step = len(name) + 1 

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

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

830 if idx: 

831 p.text(",") 

832 p.breakable() 

833 p.pretty(arg) 

834 

835 

836def _repr_integer(obj: int, p: RepresentationPrinter, cycle: bool) -> None: 

837 if abs(obj) < 1_000_000_000: 

838 p.text(repr(obj)) 

839 elif abs(obj) < 10**640: 

840 # add underscores for integers over ten decimal digits 

841 p.text(f"{obj:#_d}") 

842 else: 

843 # for very very large integers, use hex because power-of-two bases are cheaper 

844 # https://docs.python.org/3/library/stdtypes.html#integer-string-conversion-length-limitation 

845 p.text(f"{obj:#_x}") 

846 

847 

848def _repr_float_counting_nans( 

849 obj: float, p: RepresentationPrinter, cycle: bool 

850) -> None: 

851 if isnan(obj): 

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

853 show = hex(*struct.unpack("Q", struct.pack("d", obj))) 

854 return p.text(f"struct.unpack('d', struct.pack('Q', {show}))[0]") 

855 elif copysign(1.0, obj) == -1.0: 

856 return p.text("-nan") 

857 p.text(repr(obj)) 

858 

859 

860#: printers for builtin types 

861_type_pprinters: dict[type, PrettyPrintFunction] = { 

862 int: _repr_integer, 

863 float: _repr_float_counting_nans, 

864 str: _repr_pprint, 

865 tuple: _seq_pprinter_factory("(", ")", tuple), 

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

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

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

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

870 super: _super_pprint, 

871 re.Pattern: _re_pattern_pprint, 

872 type: _type_pprint, 

873 types.FunctionType: _function_pprint, 

874 types.BuiltinFunctionType: _function_pprint, 

875 types.MethodType: _function_pprint, 

876 datetime.datetime: _repr_pprint, 

877 datetime.timedelta: _repr_pprint, 

878 BaseException: _exception_pprint, 

879 slice: _repr_pprint, 

880 range: _repr_pprint, 

881 bytes: _repr_pprint, 

882} 

883 

884#: printers for types specified by name 

885_deferred_type_pprinters: dict[tuple[str, str], PrettyPrintFunction] = {} 

886 

887 

888def for_type_by_name( 

889 type_module: str, type_name: str, func: PrettyPrintFunction 

890) -> Optional[PrettyPrintFunction]: 

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

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

893 key = (type_module, type_name) 

894 oldfunc = _deferred_type_pprinters.get(key) 

895 _deferred_type_pprinters[key] = func 

896 return oldfunc 

897 

898 

899#: printers for the default singletons 

900_singleton_pprinters: dict[int, PrettyPrintFunction] = dict.fromkeys( 

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

902) 

903 

904 

905def _defaultdict_pprint( 

906 obj: defaultdict[object, object], p: RepresentationPrinter, cycle: bool 

907) -> None: 

908 name = obj.__class__.__name__ 

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

910 if cycle: 

911 p.text("...") 

912 else: 

913 p.pretty(obj.default_factory) 

914 p.text(",") 

915 p.breakable() 

916 p.pretty(dict(obj)) 

917 

918 

919def _ordereddict_pprint( 

920 obj: OrderedDict[object, object], p: RepresentationPrinter, cycle: bool 

921) -> None: 

922 name = obj.__class__.__name__ 

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

924 if cycle: 

925 p.text("...") 

926 elif obj: 

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

928 

929 

930def _deque_pprint(obj: deque[object], p: RepresentationPrinter, cycle: bool) -> None: 

931 name = obj.__class__.__name__ 

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

933 if cycle: 

934 p.text("...") 

935 else: 

936 p.pretty(list(obj)) 

937 

938 

939def _counter_pprint( 

940 obj: Counter[object], p: RepresentationPrinter, cycle: bool 

941) -> None: 

942 name = obj.__class__.__name__ 

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

944 if cycle: 

945 p.text("...") 

946 elif obj: 

947 p.pretty(dict(obj)) 

948 

949 

950def _repr_dataframe( 

951 obj: object, p: RepresentationPrinter, cycle: bool 

952) -> None: # pragma: no cover 

953 with p.indent(4): 

954 p.break_() 

955 _repr_pprint(obj, p, cycle) 

956 p.break_() 

957 

958 

959def _repr_enum(obj: Enum, p: RepresentationPrinter, cycle: bool) -> None: 

960 tname = get_class_name(type(obj)) 

961 if isinstance(obj, Flag): 

962 p.text( 

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

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

965 ) 

966 else: 

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

968 

969 

970class _ReprDots: 

971 def __repr__(self) -> str: 

972 return "..." 

973 

974 

975def _repr_partial(obj: partial[Any], p: RepresentationPrinter, cycle: bool) -> None: 

976 args, kw = obj.args, obj.keywords 

977 if cycle: 

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

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

980 

981 

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

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

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

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

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

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

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

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