Internal helper for traverse.
(root, visit, stack, path)
| 27 | |
| 28 | |
| 29 | def _traverse_internal(root, visit, stack, path): |
| 30 | """Internal helper for traverse.""" |
| 31 | |
| 32 | # Only traverse modules and classes |
| 33 | if not tf_inspect.isclass(root) and not tf_inspect.ismodule(root): |
| 34 | return |
| 35 | |
| 36 | try: |
| 37 | children = tf_inspect.getmembers(root) |
| 38 | |
| 39 | # Add labels for duplicate values in Enum. |
| 40 | if tf_inspect.isclass(root) and issubclass(root, enum.Enum): |
| 41 | for enum_member in root.__members__.items(): |
| 42 | if enum_member not in children: |
| 43 | children.append(enum_member) |
| 44 | children = sorted(children) |
| 45 | except ImportError: |
| 46 | # On some Python installations, some modules do not support enumerating |
| 47 | # members (six in particular), leading to import errors. |
| 48 | children = [] |
| 49 | |
| 50 | new_stack = stack + [root] |
| 51 | visit(path, root, children) |
| 52 | for name, child in children: |
| 53 | # Do not descend into built-in modules |
| 54 | if tf_inspect.ismodule( |
| 55 | child) and child.__name__ in sys.builtin_module_names: |
| 56 | continue |
| 57 | |
| 58 | # Break cycles |
| 59 | if any(child is item for item in new_stack): # `in`, but using `is` |
| 60 | continue |
| 61 | |
| 62 | child_path = path + '.' + name if path else name |
| 63 | _traverse_internal(child, visit, new_stack, child_path) |
| 64 | |
| 65 | |
| 66 | def traverse(root, visit): |