1.1 --- a/MoinMessage.py Mon Oct 29 22:36:16 2012 +0100
1.2 +++ b/MoinMessage.py Fri Jan 18 00:36:13 2013 +0100
1.3 @@ -2,7 +2,7 @@
1.4 """
1.5 MoinMoin - MoinMessage library
1.6
1.7 - @copyright: 2012 by Paul Boddie <paul@boddie.org.uk>
1.8 + @copyright: 2012, 2013 by Paul Boddie <paul@boddie.org.uk>
1.9 @license: GNU GPL (v2 or later), see COPYING.txt for details.
1.10 """
1.11
1.12 @@ -14,6 +14,7 @@
1.13 from subprocess import Popen, PIPE
1.14 from tempfile import mkstemp
1.15 from urlparse import urlsplit
1.16 +from MoinMoin.util import lock
1.17 import httplib
1.18 import os
1.19
1.20 @@ -50,21 +51,34 @@
1.21 else:
1.22 self.updates.append(message)
1.23
1.24 - def add_update(self, alternatives):
1.25 + def add_updates(self, parts):
1.26
1.27 """
1.28 - Add an update fragment to a message, providing alternative forms of the
1.29 - update content in the given 'alternatives': a list of MIME message
1.30 - parts, each encoding the content according to different MIME types.
1.31 + Add the given 'parts' to a message.
1.32 """
1.33
1.34 - if len(alternatives) > 1:
1.35 - part = MIMEMultipart()
1.36 - for alternative in alternatives:
1.37 - part.attach(alternative)
1.38 - self.updates.append(part)
1.39 - else:
1.40 - self.updates.append(alternatives[0])
1.41 + for part in updates:
1.42 + self.add_update(part)
1.43 +
1.44 + def add_update(self, part):
1.45 +
1.46 + """
1.47 + Add an update 'part' to a message.
1.48 + """
1.49 +
1.50 + self.updates.append(part)
1.51 +
1.52 + def get_update(self, alternatives):
1.53 +
1.54 + """
1.55 + Return a suitable multipart object containing the supplied
1.56 + 'alternatives'.
1.57 + """
1.58 +
1.59 + part = MIMEMultipart()
1.60 + for alternative in alternatives:
1.61 + part.attach(alternative)
1.62 + return part
1.63
1.64 def get_payload(self):
1.65
1.66 @@ -117,6 +131,83 @@
1.67
1.68 return mailbox
1.69
1.70 +class MessageStore:
1.71 +
1.72 + "A page-specific message store."
1.73 +
1.74 + def __init__(self, page):
1.75 +
1.76 + "Initialise a message store for the given 'page'."
1.77 +
1.78 + self.path = page.getPagePath("messages")
1.79 + self.next_path = os.path.join(self.path, "next")
1.80 + lock_dir = page.getPagePath("message-locks")
1.81 + self.lock = lock.WriteLock(lock_dir)
1.82 +
1.83 + def get_next(self):
1.84 +
1.85 + "Return the next message number."
1.86 +
1.87 + next = self.read_next()
1.88 + if not next:
1.89 + next = self.deduce_next()
1.90 + self.write_next(next)
1.91 + return next
1.92 +
1.93 + def deduce_next(self):
1.94 +
1.95 + "Deduce the next message number from the existing message files."
1.96 +
1.97 + return max([int(filename) for filename in os.listdir(self.path) if filename.isdigit()] or [0]) + 1
1.98 +
1.99 + def read_next(self):
1.100 +
1.101 + "Read the next message number from a special file."
1.102 +
1.103 + if not os.path.exists(self.next_path):
1.104 + return 0
1.105 +
1.106 + f = open(self.next_path)
1.107 + try:
1.108 + try:
1.109 + return int(f.read())
1.110 + except ValueError:
1.111 + return 0
1.112 + finally:
1.113 + f.close()
1.114 +
1.115 + def write_next(self, next):
1.116 +
1.117 + "Write the 'next' message number to a special file."
1.118 +
1.119 + f = open(self.next_path, "w")
1.120 + try:
1.121 + f.write(str(next))
1.122 + finally:
1.123 + f.close()
1.124 +
1.125 + def write_message(self, message, next):
1.126 +
1.127 + "Write the given 'message' to a file with the given 'next' message number."
1.128 +
1.129 + f = open(os.path.join(self.path, str(next)), "w")
1.130 + try:
1.131 + f.write(message.as_string())
1.132 + finally:
1.133 + f.close()
1.134 +
1.135 + def append(self, message):
1.136 +
1.137 + "Append the given 'message' to the store."
1.138 +
1.139 + self.lock.acquire()
1.140 + try:
1.141 + next = self.get_next()
1.142 + self.write_message(message, next)
1.143 + self.write_next(next + 1)
1.144 + finally:
1.145 + self.lock.release()
1.146 +
1.147 class MoinMessageError(Exception):
1.148 pass
1.149