~barry/mailman/events-and-web

« back to all changes in this revision

Viewing changes to src/mailman/model/messagestore.py

  • Committer: Barry Warsaw
  • Date: 2012-04-22 21:33:33 UTC
  • mfrom: (7150.1.11 transactions)
  • Revision ID: barry@list.org-20120422213333-3skjqsjktooesgsl
Several non-functional improvements to the code base.

Reduce the explicit use of the config.db global by introducing two new
helpers:
 - A new transaction() context manager which will commit the transaction on
   successful exit, otherwise it will abort the transaction
 - A new dbconnection decorator which calls the decorated method with the
   Storm store object as the first argument (after self).  This can be used
   instead of config.db.store.

By reducing the explicit use of this global, we have a better chance of
refactoring it away in the future.  Still TODO: runner.py and lmtp.py.

Be explicit about the `store` attribute on the IDatabase interface.

More consistent use of __future__ imports.

Remove an obsolete command line script.

Show diffs side-by-side

added added

removed removed

Lines of Context:
17
17
 
18
18
"""Model for message stores."""
19
19
 
20
 
 
21
 
from __future__ import absolute_import, unicode_literals
 
20
from __future__ import absolute_import, print_function, unicode_literals
22
21
 
23
22
__metaclass__ = type
24
23
__all__ = [
34
33
from zope.interface import implements
35
34
 
36
35
from mailman.config import config
 
36
from mailman.database.transaction import dbconnection
37
37
from mailman.interfaces.messages import IMessageStore
38
38
from mailman.model.message import Message
39
39
from mailman.utilities.filesystem import makedirs
49
49
class MessageStore:
50
50
    implements(IMessageStore)
51
51
 
52
 
    def add(self, message):
 
52
    @dbconnection
 
53
    def add(self, store, message):
53
54
        # Ensure that the message has the requisite headers.
54
55
        message_ids = message.get_all('message-id', [])
55
56
        if len(message_ids) <> 1:
57
58
        # Calculate and insert the X-Message-ID-Hash.
58
59
        message_id = message_ids[0]
59
60
        # Complain if the Message-ID already exists in the storage.
60
 
        existing = config.db.store.find(Message,
61
 
                                        Message.message_id == message_id).one()
 
61
        existing = store.find(Message, Message.message_id == message_id).one()
62
62
        if existing is not None:
63
63
            raise ValueError(
64
64
                'Message ID already exists in message store: {0}'.format(
104
104
        with open(path) as fp:
105
105
            return pickle.load(fp)
106
106
 
107
 
    def get_message_by_id(self, message_id):
108
 
        row = config.db.store.find(Message, message_id=message_id).one()
 
107
    @dbconnection
 
108
    def get_message_by_id(self, store, message_id):
 
109
        row = store.find(Message, message_id=message_id).one()
109
110
        if row is None:
110
111
            return None
111
112
        return self._get_message(row)
112
113
 
113
 
    def get_message_by_hash(self, message_id_hash):
 
114
    @dbconnection
 
115
    def get_message_by_hash(self, store, message_id_hash):
114
116
        # It's possible the hash came from a message header, in which case it
115
117
        # will be a Unicode.  However when coming from source code, it may be
116
118
        # an 8-string.  Coerce to the latter if necessary; it must be
117
119
        # US-ASCII.
118
120
        if isinstance(message_id_hash, unicode):
119
121
            message_id_hash = message_id_hash.encode('ascii')
120
 
        row = config.db.store.find(Message,
121
 
                                   message_id_hash=message_id_hash).one()
 
122
        row = store.find(Message, message_id_hash=message_id_hash).one()
122
123
        if row is None:
123
124
            return None
124
125
        return self._get_message(row)
125
126
 
126
127
    @property
127
 
    def messages(self):
128
 
        for row in config.db.store.find(Message):
 
128
    @dbconnection
 
129
    def messages(self, store):
 
130
        for row in store.find(Message):
129
131
            yield self._get_message(row)
130
132
 
131
 
    def delete_message(self, message_id):
132
 
        row = config.db.store.find(Message, message_id=message_id).one()
 
133
    @dbconnection
 
134
    def delete_message(self, store, message_id):
 
135
        row = store.find(Message, message_id=message_id).one()
133
136
        if row is None:
134
137
            raise LookupError(message_id)
135
138
        path = os.path.join(config.MESSAGES_DIR, row.path)
136
139
        os.remove(path)
137
 
        config.db.store.remove(row)
 
140
        store.remove(row)