code: def get_leaves(self, item_ids=None, language=None, forbidden_item_ids=None):
          
          forbidden_item_ids = set() if forbidden_item_ids is None else set(forbidden_item_ids)
          children = self.get_children_graph(item_ids, language=language, forbidden_item_ids=forbidden_item_ids)
          counts = self.get_children_counts(active=None)
          if item_ids is None:
              # not leaves
              item_ids = set(children.keys())
  
          def _get_leaves(item_id):
              leaves = set()
  
              def __search(item_ids):
                  result = set(flatten([children.get(item_id, []) for item_id in item_ids]))
                  new_leaves = {item_id for item_id in result if item_id not in children.keys()}
                  leaves.update(new_leaves)
                  return result - new_leaves
  
              fixed_point(
                  is_zero=lambda to_visit: len(to_visit) == 0,
                  minus=lambda to_visit, visited: to_visit - visited,
                  plus=lambda visited_x, visited_y: visited_x | visited_y,
                  f=__search,
                  x={item_id}
              )
              leaves = {leaf for leaf in leaves if counts[leaf] == 0}
              if len(leaves) > 0:
                  return leaves
              if counts[item_id] == 0 and item_id not in forbidden_item_ids:
                  return {item_id}
              return set()
  
          return {item_id: _get_leaves(item_id) for item_id in item_ids}
docs: Get mapping of items to their reachable leaves. Leaves having
          inactive relations to other items are omitted.
  
          Args:
              item_ids (list): items which are taken as roots for the reachability
              language (str): if specified, filter out items which are not
                  available in the given language
  
          Returns:
              dict: item id -> list of items (reachable leaves)