summaryrefslogtreecommitdiffstats
path: root/kittystore/storm/store.py
diff options
context:
space:
mode:
authorAurélien Bompard <aurelien@bompard.org>2012-11-09 13:51:18 +0100
committerAurélien Bompard <aurelien@bompard.org>2012-11-09 13:51:18 +0100
commit6a1eaf953aedfb2de06ef43119741d612a6f779b (patch)
tree061ab301091bd7c7a3e856b392c703e21e473f80 /kittystore/storm/store.py
parentff7b371366aaf51302c5f021af5d5e2bda02565c (diff)
downloadkittystore-6a1eaf953aedfb2de06ef43119741d612a6f779b.tar.gz
kittystore-6a1eaf953aedfb2de06ef43119741d612a6f779b.tar.xz
kittystore-6a1eaf953aedfb2de06ef43119741d612a6f779b.zip
Add a thread object in the model
New object in the model: the Thread. It starts by having an active_date, corresponding to the date of the last email in the thread. Later on, it will also hold the category, tags, maybe ratings, etc. A schema migration is provided, upgrade should be automatic.
Diffstat (limited to 'kittystore/storm/store.py')
-rw-r--r--kittystore/storm/store.py114
1 files changed, 50 insertions, 64 deletions
diff --git a/kittystore/storm/store.py b/kittystore/storm/store.py
index b51e2c9..4e91346 100644
--- a/kittystore/storm/store.py
+++ b/kittystore/storm/store.py
@@ -28,7 +28,7 @@ from mailman.interfaces.messages import IMessageStore
from storm.locals import Desc
from storm.expr import And, Or
-from .model import List, Email, Attachment
+from .model import List, Email, Attachment, Thread
class StormStore(object):
@@ -99,8 +99,10 @@ class StormStore(object):
return email.message_id_hash
# Find thread id
+ new_thread = False
ref, thread_id = get_ref_and_thread_id(message, list_name, self)
if thread_id is None:
+ new_thread = True
# make up the thread_id if not found
thread_id = email.message_id_hash
email.thread_id = thread_id
@@ -108,8 +110,8 @@ class StormStore(object):
from_name, from_email = parseaddr(message['From'])
from_name = header_to_unicode(from_name)
- email.sender_name = from_name
- email.sender_email = unicode(from_email)
+ email.sender_name = from_name.strip()
+ email.sender_email = unicode(from_email).strip()
email.subject = header_to_unicode(message.get('Subject'))
email.full = message.as_string() # Before scrubbing
scrubber = Scrubber(list_name, message, self)
@@ -125,6 +127,16 @@ class StormStore(object):
# # i18n!
# category = 'Agenda'
+ if new_thread:
+ thread = Thread(list_name, thread_id, email.date)
+ else:
+ thread = self.db.find(Thread, And(
+ Thread.list_name == list_name,
+ Thread.thread_id == thread_id,
+ )).one()
+ thread.date_active = email.date
+ self.db.add(thread)
+
self.db.add(email)
self.flush()
return email.message_id_hash
@@ -152,6 +164,13 @@ class StormStore(object):
if msg is None:
raise MessageNotFound(list_name, message_id)
self.db.delete(msg)
+ # Remove the thread if necessary
+ thread = self.db.find(Thread, And(
+ Thread.list_name == msg.list_name,
+ Thread.thread_id == msg.thread_id,
+ )).one()
+ if len(thread.emails) == 0:
+ self.db.delete(thread)
self.flush()
def get_list_size(self, list_name):
@@ -297,9 +316,8 @@ class StormStore(object):
"""
return list(self.db.find(List.name).order_by(List.name))
- def get_messages(self, list_name, start, end, threads=False):
- """ Return all emails between two given dates, optionnaly selecting
- only the thread-starting ones.
+ def get_messages(self, list_name, start, end):
+ """ Return all emails between two given dates.
:param list_name: The name of the mailing list in which these emails
should be searched.
@@ -309,20 +327,29 @@ class StormStore(object):
the interval to query.
:returns: The list of messages.
"""
- conditions = [
- Email.list_name == unicode(list_name),
- Email.date >= start,
- Email.date < end,
- ]
- if threads:
- # Beginning of thread == No 'References' header
- conditions.append(Email.in_reply_to == None)
- emails = self.db.find(Email, And(*conditions)
- ).order_by(Desc(Email.date))
+ emails = self.db.find(Email, And(
+ Email.list_name == unicode(list_name),
+ Email.date >= start,
+ Email.date < end,
+ )).order_by(Desc(Email.date))
return list(emails)
+ def get_thread(self, list_name, thread_id):
+ """ Return the specified thread.
+
+ :param list_name: The name of the mailing list in which this email
+ should be searched.
+ :param thread_id: The thread_id as used in the web-pages. Used here to
+ uniquely identify the thread in the database.
+ :returns: The thread object.
+ """
+ return self.db.find(Thread, And(
+ Thread.list_name == unicode(list_name),
+ Thread.thread_id == unicode(thread_id)
+ )).one()
+
def get_threads(self, list_name, start, end):
- """ Return all the thread-starting emails between two given dates.
+ """ Return all the threads active between two given dates.
:param list_name: The name of the mailing list in which this email
should be searched.
@@ -332,7 +359,12 @@ class StormStore(object):
the interval to query.
:returns: The list of thread-starting messages.
"""
- return self.get_messages(list_name, start, end, threads=True)
+ threads = self.db.find(Thread, And(
+ Thread.list_name == unicode(list_name),
+ Thread.date_active >= start,
+ Thread.date_active < end,
+ )).order_by(Desc(Thread.date_active))
+ return list(threads)
def get_start_date(self, list_name):
""" Get the date of the first archived email in a list.
@@ -349,52 +381,6 @@ class StormStore(object):
else:
return None
- def get_messages_in_thread(self, list_name, thread_id):
- """ Return all the emails present in a thread. This thread
- is uniquely identified by its thread_id.
-
- :param list_name: The name of the mailing list in which this email
- should be searched.
- :param thread_id: The thread_id as used in the web-pages. Used here to
- uniquely identify the thread in the database.
- :returns: The list of messages in the thread.
- """
- emails = self.db.find(Email, And(
- Email.list_name == unicode(list_name),
- Email.thread_id == unicode(thread_id),
- )).order_by(Email.date)
- return list(emails)
-
- def get_thread_length(self, list_name, thread_id):
- """ Return the number of email present in a thread. This thread
- is uniquely identified by its thread_id.
-
- :param list_name: The name of the mailing list to query.
- :param thread_id: The unique identifier of the thread as specified in
- the database.
- :returns: The number of messages in the thread.
- :rtype: int
- """
- return self.db.find(Email, And(
- Email.list_name == unicode(list_name),
- Email.thread_id == unicode(thread_id),
- )).count()
-
- def get_thread_participants(self, list_name, thread_id):
- """ Return the list of participant in a thread. This thread
- is uniquely identified by its thread_id.
-
- :param list_name: The name of the mailing list to query.
- :param thread_id: The unique identifier of the thread as specified in
- the database.
- :return: The list of message sender names in the thread.
- """
- participants = self.db.find(Email.sender_name, And(
- Email.list_name == unicode(list_name),
- Email.thread_id == unicode(thread_id),
- )).config(distinct=True)
- return list(participants)
-
def get_thread_neighbors(self, list_name, thread_id):
""" Return the previous and the next threads of the specified thread,
in date order. The returned objects are the emails starting the