(objects, idx)
| 689 | |
| 690 | |
| 691 | def _find_reference_cycle(objects, idx): |
| 692 | |
| 693 | def get_ignore_reason(obj, blacklist): |
| 694 | """Tests whether an object should be omitted from the dependency graph.""" |
| 695 | if len(blacklist) > 100: |
| 696 | return "<depth limit>" |
| 697 | if tf_inspect.isframe(obj): |
| 698 | if "test_util.py" in tf_inspect.getframeinfo(obj)[0]: |
| 699 | return "<test code>" |
| 700 | for b in blacklist: |
| 701 | if b is obj: |
| 702 | return "<test code>" |
| 703 | if obj is blacklist: |
| 704 | return "<test code>" |
| 705 | return None |
| 706 | |
| 707 | # Note: this function is meant to help with diagnostics. Its output is purely |
| 708 | # a human-readable representation, so you may freely modify it to suit your |
| 709 | # needs. |
| 710 | def describe(obj, blacklist, leaves_only=False): |
| 711 | """Returns a custom human-readable summary of obj. |
| 712 | |
| 713 | Args: |
| 714 | obj: the value to describe. |
| 715 | blacklist: same as blacklist in get_ignore_reason. |
| 716 | leaves_only: boolean flag used when calling describe recursively. Useful |
| 717 | for summarizing collections. |
| 718 | """ |
| 719 | if get_ignore_reason(obj, blacklist): |
| 720 | return "{}{}".format(get_ignore_reason(obj, blacklist), type(obj)) |
| 721 | if tf_inspect.isframe(obj): |
| 722 | return "frame: {}".format(tf_inspect.getframeinfo(obj)) |
| 723 | elif tf_inspect.ismodule(obj): |
| 724 | return "module: {}".format(obj.__name__) |
| 725 | else: |
| 726 | if leaves_only: |
| 727 | return "{}, {}".format(type(obj), id(obj)) |
| 728 | elif isinstance(obj, list): |
| 729 | return "list({}): {}".format( |
| 730 | id(obj), [describe(e, blacklist, leaves_only=True) for e in obj]) |
| 731 | elif isinstance(obj, tuple): |
| 732 | return "tuple({}): {}".format( |
| 733 | id(obj), [describe(e, blacklist, leaves_only=True) for e in obj]) |
| 734 | elif isinstance(obj, dict): |
| 735 | return "dict({}): {} keys".format(id(obj), len(obj.keys())) |
| 736 | elif tf_inspect.isfunction(obj): |
| 737 | return "function({}) {}; globals ID: {}".format( |
| 738 | id(obj), obj.__name__, id(obj.__globals__)) |
| 739 | else: |
| 740 | return "{}, {}".format(type(obj), id(obj)) |
| 741 | |
| 742 | def build_ref_graph(obj, graph, reprs, blacklist): |
| 743 | """Builds a reference graph as <referrer> -> <list of refferents>. |
| 744 | |
| 745 | Args: |
| 746 | obj: The object to start from. The graph will be built by recursively |
| 747 | adding its referrers. |
| 748 | graph: Dict holding the graph to be built. To avoid creating extra |
no test coverage detected