diff options
| author | Aurélien Bompard <aurelien@bompard.org> | 2013-09-10 15:46:19 +0200 |
|---|---|---|
| committer | Aurélien Bompard <aurelien@bompard.org> | 2013-09-10 15:46:19 +0200 |
| commit | 5dfb231d3e7e509d480c376ebffe2cc439209a57 (patch) | |
| tree | c40753df02a29ab284a388cfea3103e131ff6804 | |
| parent | 10cdfecde4879cff8f531e451c669a8cd90dc5a0 (diff) | |
| download | kittystore-5dfb231d3e7e509d480c376ebffe2cc439209a57.tar.gz kittystore-5dfb231d3e7e509d480c376ebffe2cc439209a57.tar.xz kittystore-5dfb231d3e7e509d480c376ebffe2cc439209a57.zip | |
Keep the reply graph acyclic
| -rw-r--r-- | kittystore/analysis.py | 5 | ||||
| -rw-r--r-- | kittystore/test/test_analysis.py | 31 |
2 files changed, 35 insertions, 1 deletions
diff --git a/kittystore/analysis.py b/kittystore/analysis.py index 0f49b78..9e3471a 100644 --- a/kittystore/analysis.py +++ b/kittystore/analysis.py @@ -37,11 +37,14 @@ def compute_thread_order_and_depth(thread): thread_pos["d"] += 1 thread_pos["o"] += 1 for succ in sorted(graph.successors(msgid), - key=lambda m: graph.node[m]["num"]): + 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) diff --git a/kittystore/test/test_analysis.py b/kittystore/test/test_analysis.py index 16d0d01..bcaf3bc 100644 --- a/kittystore/test/test_analysis.py +++ b/kittystore/test/test_analysis.py @@ -127,3 +127,34 @@ class TestThreadOrderDepth(unittest.TestCase): self.assertEqual(msg3.thread_depth, 1) self.assertEqual(msg4.thread_order, 2) self.assertEqual(msg4.thread_depth, 2) + + def test_reply_to_oneself(self): + # A message replying to itself (yes, it's been spotted in the wild) + thread = Thread("example-list", "<msg1>") + self.store.db.add(thread) + msg1 = make_fake_email(1) + msg1.in_reply_to = u"<msg1>" + msg1.thread_order = msg1.thread_depth = 42 + self.store.db.add(msg1) + self.store.flush() + compute_thread_order_and_depth(thread) + # Don't traceback with a "maximum recursion depth exceeded" error + self.assertEqual(msg1.thread_order, 0) + self.assertEqual(msg1.thread_depth, 0) + + def test_reply_loops(self): + """Loops in message replies""" + # This implies that someone replies to a message not yet sent, but you + # never know, Dr Who can be on your mailing-list. + thread = Thread("example-list", "<msg1>") + self.store.db.add(thread) + msg1 = make_fake_email(1) + msg1.in_reply_to = u"<msg2>" + self.store.db.add(msg1) + msg2 = make_fake_email(2) + msg2.thread_id = u"<msg1>" + msg2.in_reply_to = u"<msg1>" + self.store.db.add(msg2) + self.store.flush() + compute_thread_order_and_depth(thread) + # Don't traceback with a "maximum recursion depth exceeded" error |
