# Path: kittystore/analysis.py
# def compute_thread_order_and_depth(thread):
#     graph = nx.DiGraph()
#     thread_pos = {"d": 0, "o": 0} # depth, order
#     def walk_successors(msgid):
#         obj = graph.node[msgid]["obj"]
#         obj.thread_depth = thread_pos["d"]
#         obj.thread_order = thread_pos["o"]
#         thread_pos["d"] += 1
#         thread_pos["o"] += 1
#         for succ in sorted(graph.successors(msgid),
#                            key=lambda m: graph.node[m]["num"]):
#             walk_successors(succ)
#         thread_pos["d"] -= 1
#     for index, email in enumerate(thread.emails):
#         graph.add_node(email.message_id, num=index, obj=email)
#         if email.in_reply_to is not None:
#             graph.add_edge(email.in_reply_to, email.message_id)
#             if not nx.is_directed_acyclic_graph(graph):
#                 # I don't want reply loops in my graph, thank you very much
#                 graph.remove_edge(email.in_reply_to, email.message_id)
#     walk_successors(thread.starting_email.message_id)


from zope.interface import implements
from mailman.interfaces.messages import IMessageStore
from kittystore.analysis import compute_thread_order_and_depth
import logging
        """
        # Not sure this is useful: a message should always be in a list
        raise NotImplementedError

    def get_message_by_id_from_list(self, list_name, message_id):
        """Return the message with a matching Message-ID.

        :param list_name: The fully qualified list name to which the
            message should be added.
        :param message_id: The Message-ID header contents to search for.
        :returns: The message, or None if no matching message was found.
        """
        raise NotImplementedError

    @property
    def messages(self):
        """An iterator over all messages in this message store."""
        raise NotImplementedError

    # Other methods (not in IMessageStore)

    def attach_to_thread(self, email, thread):
        """Attach an email to an existing thread"""
        if email.date <= thread.starting_email.date:
            raise ValueError("Can't attach emails older than the first "
                             "email in a thread")
        email.thread_id = thread.thread_id
        email.in_reply_to = thread.starting_email.message_id
        if email.date > thread.date_active:
            thread.date_active = email.date

# Path: kittystore/analysis.py
# def compute_thread_order_and_depth(thread):
#     graph = nx.DiGraph()
#     thread_pos = {"d": 0, "o": 0} # depth, order
#     def walk_successors(msgid):
#         obj = graph.node[msgid]["obj"]
#         obj.thread_depth = thread_pos["d"]
#         obj.thread_order = thread_pos["o"]
#         thread_pos["d"] += 1
#         thread_pos["o"] += 1
#         for succ in sorted(graph.successors(msgid),
#                            key=lambda m: graph.node[m]["num"]):
#             walk_successors(succ)
#         thread_pos["d"] -= 1
#     for index, email in enumerate(thread.emails):
#         graph.add_node(email.message_id, num=index, obj=email)
#         if email.in_reply_to is not None:
#             graph.add_edge(email.in_reply_to, email.message_id)
#             if not nx.is_directed_acyclic_graph(graph):
#                 # I don't want reply loops in my graph, thank you very much
#                 graph.remove_edge(email.in_reply_to, email.message_id)
#     walk_successors(thread.starting_email.message_id)


# Path: kittystore/store.py
from zope.interface import implements
from mailman.interfaces.messages import IMessageStore
from kittystore.analysis import compute_thread_order_and_depth
import logging

        """
        # Not sure this is useful: a message should always be in a list
        raise NotImplementedError

    def get_message_by_id_from_list(self, list_name, message_id):
        """Return the message with a matching Message-ID.

        :param list_name: The fully qualified list name to which the
            message should be added.
        :param message_id: The Message-ID header contents to search for.
        :returns: The message, or None if no matching message was found.
        """
        raise NotImplementedError

    @property
    def messages(self):
        """An iterator over all messages in this message store."""
        raise NotImplementedError

    # Other methods (not in IMessageStore)

    def attach_to_thread(self, email, thread):
        """Attach an email to an existing thread"""
        if email.date <= thread.starting_email.date:
            raise ValueError("Can't attach emails older than the first "
                             "email in a thread")
        email.thread_id = thread.thread_id
        email.in_reply_to = thread.starting_email.message_id
        if email.date > thread.date_active:
            thread.date_active = email.date

        compute_thread_order_and_depth(thread)