<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def donate_leadership(self, opt_count, skip_brokers, used_edges):
 """Over-loaded brokers tries to donate their leadership to one of their followers recursively until they become balanced. :key_terms: used_edges: Represent list of tuple/edges (partition, prev-leader, new-leader), which have already been used for donating leadership from prev-leader to new-leader in same partition before. skip_brokers: This is to avoid using same broker recursively for balancing to prevent loops. :Algorithm: * Over-loaded leader tries to donate its leadership to one of its followers * Follower will try to be balanced recursively if it becomes over-balanced * If it is successful, over-loaded leader moves to next partition if required, return otherwise. * If it is unsuccessful, it tries for next-follower or next-partition whatever or returns if none available. """

        owned_partitions = list(filter(
            lambda p: self is p.leader and len(p.replicas) > 1,
            self.partitions,
        ))
        for partition in owned_partitions:
            # Skip using same partition with broker if already used before
            potential_new_leaders = list(filter(
                lambda f: f not in skip_brokers,
                partition.followers,
            ))
            for follower in potential_new_leaders:
                # Don't swap the broker-pair if already swapped before
                # in same partition
                if (partition, self, follower) in used_edges:
                    continue
                partition.swap_leader(follower)
                used_edges.append((partition, follower, self))
                # new-leader didn't unbalance
                if follower.count_preferred_replica() <= opt_count + 1:
                    # over-broker balanced
                    # If over-broker is the one which needs to be revoked from leadership
                    # it's considered balanced only if its preferred replica count is 0
                    if (self.count_preferred_replica() <= opt_count + 1 and not self.revoked_leadership) or \
                            (self.count_preferred_replica() == 0 and self.revoked_leadership):
                        return
                    else:
                        # Try next-partition, not another follower
                        break
                else:  # new-leader (broker) became over-balanced
                    skip_brokers.append(follower)
                    follower.donate_leadership(opt_count, skip_brokers, used_edges)
                    # new-leader couldn't be balanced, revert
                    if follower.count_preferred_replica() > opt_count + 1:
                        used_edges.append((partition, follower, self))
                        partition.swap_leader(self)
                        # Try next leader or partition
                        continue
                    else:
                        # New-leader was successfully balanced
                        used_edges.append((partition, follower, self))
                        # New-leader can be reused
                        skip_brokers.remove(follower)
                        # If broker is the one which needs to be revoked from leadership
                        # it's considered balanced only if its preferred replica count is 0
                        if (self.count_preferred_replica() <= opt_count + 1 and not self.revoked_leadership) or \
                                (self.count_preferred_replica() == 0 and self.revoked_leadership):
                            # Now broker is balanced
                            return
                        else:
                            # Try next-partition, not another follower
                            break