code: def prune_duplicates(self) -> None:
      seen: Set[Tuple[str, int]] = set()
      self.seen_in_dispatchers(seen)
  
      # Breadth-first search so that we prefer objects with shorter names.
      todo = Deque([self])
      while todo:
          module = todo.popleft()
  
          new_classes = []
          for c in module.classes:
              # Account for objects to have aliases, hence include the object name in the key.
              # We want to generate documentation for both the alias and the original object.
              key = (c.name[c.name.rfind(".") + 1 :], id(c.obj))
              if key not in seen:
                  seen.add(key)
                  new_classes.append(c)
          module.classes = new_classes
  
          new_functions = []
          for f in module.functions:
              # See comment above (for classes) about aliases.
              key = (f.name[f.name.rfind(".") + 1 :], id(f.obj))
              if key not in seen:
                  seen.add(key)
                  new_functions.append(f)
          module.functions = new_functions
  
          todo.extend(module.modules)
  
imports: import inspect
  from dataclasses import dataclass
  from pathlib import Path
  from types import ModuleType
  from typing import Any, Callable, Deque, Dict, List, Mapping, Set, TextIO, Tuple, Type, Union
  from gpflow.utilities import Dispatcher
label_desc: Use image node_id 3 for calling the DocumentableModule obj's underlying member method code with example usage: obj.prune_duplicates() without return types