565) -> Node:
566 """Traverse object and generate a tree.
567
568 Args:
569 _object (Any): Object to be traversed.
570 max_length (int, optional): Maximum length of containers before abbreviating, or None for no abbreviation.
571 Defaults to None.
572 max_string (int, optional): Maximum length of string before truncating, or None to disable truncating.
573 Defaults to None.
574 max_depth (int, optional): Maximum depth of data structures, or None for no maximum.
575 Defaults to None.
576
577 Returns:
578 Node: The root of a tree structure which can be used to render a pretty repr.
579 """
580
582 """Get repr string for an object, but catch errors."""
583 if (
584 max_string is not None
585 and _safe_isinstance(obj, (bytes, str))
586 and len(obj) > max_string
587 ):
588 truncated =
len(obj) - max_string
589 obj_repr = f"{obj[:max_string]!r}+{truncated}"
590 else:
591 try:
592 obj_repr = repr(obj)
593 except Exception as error:
594 obj_repr = f"<repr-error {str(error)!r}>"
595 return obj_repr
596
597 visited_ids: Set[int] = set()
600
601 def _traverse(obj: Any, root: bool =
False, depth: int = 0) -> Node:
602 """Walk the object depth first."""
603
604 obj_id = id(obj)
605 if obj_id in visited_ids:
606
607 return Node(value_repr="...")
608
609 obj_type = type(obj)
610 children: List[Node]
611 reached_max_depth = max_depth is not None and depth >= max_depth
612
613 def iter_rich_args(rich_args: Any) -> Iterable[Union[Any, Tuple[str, Any]]]:
614 for arg in rich_args:
615 if _safe_isinstance(arg, tuple):
617 key, child, default = arg
618 if default == child:
619 continue
620 yield key, child
622 key, child = arg
623 yield key, child
625 yield arg[0]
626 else:
627 yield arg
628
629 try:
631 obj, "awehoi234_wdfjwljet234_234wdfoijsdfmmnxpi492"
632 )
633 except Exception:
634 fake_attributes = False
635
636 rich_repr_result: Optional[RichReprResult] = None
637 if not fake_attributes:
638 try:
639 if hasattr(obj,
"__rich_repr__")
and not isclass(obj):
641 except Exception:
642 pass
643
644 if rich_repr_result is not None:
649
650 if args:
651 children = []
653
654 if reached_max_depth:
655 if angular:
656 node = Node(value_repr=f"<{class_name}...>")
657 else:
658 node = Node(value_repr=f"{class_name}(...)")
659 else:
660 if angular:
661 node = Node(
662 open_brace=f"<{class_name} ",
663 close_brace=">",
664 children=children,
665 last=root,
666 separator=" ",
667 )
668 else:
669 node = Node(
670 open_brace=f"{class_name}(",
671 close_brace=")",
672 children=children,
673 last=root,
674 )
675 for last, arg in loop_last(args):
676 if _safe_isinstance(arg, tuple):
677 key, child = arg
678 child_node =
_traverse(child, depth=depth + 1)
682 append(child_node)
683 else:
684 child_node =
_traverse(arg, depth=depth + 1)
686 append(child_node)
687 else:
688 node = Node(
689 value_repr=f"<{class_name}>" if angular else f"{class_name}()",
690 children=[],
691 last=root,
692 )
694 elif _is_attr_object(obj) and not fake_attributes:
696 children = []
698
699 attr_fields = _get_attr_fields(obj)
700 if attr_fields:
701 if reached_max_depth:
702 node = Node(value_repr=f"{obj.__class__.__name__}(...)")
703 else:
704 node = Node(
705 open_brace=f"{obj.__class__.__name__}(",
706 close_brace=")",
707 children=children,
708 last=root,
709 )
710
712 Tuple[str, Any, Optional[Callable[[Any], str]]]
713 ]:
714 """Iterate over attr fields and values."""
715 for attr in attr_fields:
717 try:
719 except Exception as error:
720
722 else:
723 yield (
725 value,
727 )
728
729 for last, (name, value, repr_callable)
in loop_last(
iter_attrs()):
730 if repr_callable:
732 else:
733 child_node =
_traverse(value, depth=depth + 1)
737 append(child_node)
738 else:
739 node = Node(
740 value_repr=f"{obj.__class__.__name__}()", children=[], last=root
741 )
743 elif (
744 is_dataclass(obj)
745 and not _safe_isinstance(obj, type)
746 and not fake_attributes
747 and _is_dataclass_repr(obj)
748 ):
750 children = []
752 if reached_max_depth:
753 node = Node(value_repr=f"{obj.__class__.__name__}(...)")
754 else:
755 node = Node(
756 open_brace=f"{obj.__class__.__name__}(",
757 close_brace=")",
758 children=children,
759 last=root,
760 empty=f"{obj.__class__.__name__}()",
761 )
762
763 for last, field in loop_last(
765 ):
770 append(child_node)
771
773 elif _is_namedtuple(obj) and _has_default_namedtuple_repr(obj):
776 if reached_max_depth:
777
778 node = Node(
779 value_repr=f"{class_name}(...)",
780 )
781 else:
782 children = []
784 node = Node(
785 open_brace=f"{class_name}(",
786 close_brace=")",
787 children=children,
788 empty=f"{class_name}()",
789 )
790 for last, (key, value)
in loop_last(
obj._asdict().items()):
791 child_node =
_traverse(value, depth=depth + 1)
795 append(child_node)
797 elif _safe_isinstance(obj, _CONTAINERS):
798 for container_type in _CONTAINERS:
799 if _safe_isinstance(obj, container_type):
800 obj_type = container_type
801 break
802
804
805 open_brace, close_brace, empty = _BRACES[obj_type](obj)
806
807 if reached_max_depth:
808 node = Node(value_repr=f"{open_brace}...{close_brace}")
810 node = Node(value_repr=
to_repr(obj), last=root)
811 elif obj:
812 children = []
813 node = Node(
814 open_brace=open_brace,
815 close_brace=close_brace,
816 children=children,
817 last=root,
818 )
821 last_item_index = num_items - 1
822
823 if _safe_isinstance(obj, _MAPPING_CONTAINERS):
825 if max_length is not None:
826 iter_items = islice(iter_items, max_length)
827 for index, (key, child)
in enumerate(iter_items):
828 child_node =
_traverse(child, depth=depth + 1)
831 append(child_node)
832 else:
833 iter_values = iter(obj)
834 if max_length is not None:
835 iter_values = islice(iter_values, max_length)
836 for index, child
in enumerate(iter_values):
837 child_node =
_traverse(child, depth=depth + 1)
839 append(child_node)
840 if max_length is not None and num_items > max_length:
841 append(Node(value_repr=f"... +{num_items - max_length}", last=True))
842 else:
843 node = Node(empty=empty, children=[], last=root)
844
846 else:
847 node = Node(value_repr=
to_repr(obj), last=root)
850 return node
851
853 return node
854
855