~abompard/mailman/bug-1312884

« back to all changes in this revision

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

  • Committer: Barry Warsaw
  • Date: 2014-11-01 16:49:15 UTC
  • mfrom: (7251.1.38 abhilash)
  • Revision ID: barry@list.org-20141101164915-06wqfmya6wf47n6n
Database
--------
 * The ORM layer, previously implemented with Storm, has been replaced by
   SQLAlchemy, thanks to the fantastic work by Abhilash Raj and Aurélien
   Bompard.  Alembic is now used for all database schema migrations.
 * The new logger `mailman.database` logs any errors at the database layer.

API
---
 * Several changes to the internal API:
   - `IListManager.mailing_lists` is guaranteed to be sorted in List-ID order.
   - `IDomains.mailing_lists` is guaranteed to be sorted in List-ID order.
   - Iteration over domains via the `IDomainManager` is guaranteed to be sorted
     by `IDomain.mail_host` order.
   - `ITemporaryDatabase` interface and all implementations are removed.

Show diffs side-by-side

added added

removed removed

Lines of Context:
26
26
 
27
27
from cPickle import dumps, loads
28
28
from datetime import timedelta
29
 
from storm.locals import AutoReload, Int, RawStr, Reference, Unicode
 
29
from sqlalchemy import Column, ForeignKey, Integer, LargeBinary, Unicode
 
30
from sqlalchemy.orm import relationship
30
31
from zope.component import getUtility
31
32
from zope.interface import implementer
32
33
 
68
69
    @property
69
70
    @dbconnection
70
71
    def count(self, store):
71
 
        return store.find(_Request, mailing_list=self.mailing_list).count()
 
72
        return store.query(_Request).filter_by(
 
73
            mailing_list=self.mailing_list).count()
72
74
 
73
75
    @dbconnection
74
76
    def count_of(self, store, request_type):
75
 
        return store.find(
76
 
            _Request,
 
77
        return store.query(_Request).filter_by(
77
78
            mailing_list=self.mailing_list, request_type=request_type).count()
78
79
 
79
80
    @property
80
81
    @dbconnection
81
82
    def held_requests(self, store):
82
 
        results = store.find(_Request, mailing_list=self.mailing_list)
 
83
        results = store.query(_Request).filter_by(
 
84
            mailing_list=self.mailing_list)
83
85
        for request in results:
84
86
            yield request
85
87
 
86
88
    @dbconnection
87
89
    def of_type(self, store, request_type):
88
 
        results = store.find(
89
 
            _Request,
 
90
        results = store.query(_Request).filter_by(
90
91
            mailing_list=self.mailing_list, request_type=request_type)
91
92
        for request in results:
92
93
            yield request
104
105
            data_hash = token
105
106
        request = _Request(key, request_type, self.mailing_list, data_hash)
106
107
        store.add(request)
 
108
        # XXX The caller needs a valid id immediately, so flush the changes
 
109
        # now to the SA transaction context.  Otherwise .id would not be
 
110
        # valid.  Hopefully this has no unintended side-effects.
 
111
        store.flush()
107
112
        return request.id
108
113
 
109
114
    @dbconnection
110
115
    def get_request(self, store, request_id, request_type=None):
111
 
        result = store.get(_Request, request_id)
 
116
        result = store.query(_Request).get(request_id)
112
117
        if result is None:
113
118
            return None
114
119
        if request_type is not None and result.request_type != request_type:
117
122
            return result.key, None
118
123
        pendable = getUtility(IPendings).confirm(
119
124
            result.data_hash, expunge=False)
 
125
        if pendable is None:
 
126
            return None
120
127
        data = dict()
121
128
        # Unpickle any non-Unicode values.
122
129
        for key, value in pendable.items():
130
137
 
131
138
    @dbconnection
132
139
    def delete_request(self, store, request_id):
133
 
        request = store.get(_Request, request_id)
 
140
        request = store.query(_Request).get(request_id)
134
141
        if request is None:
135
142
            raise KeyError(request_id)
136
143
        # Throw away the pended data.
137
144
        getUtility(IPendings).confirm(request.data_hash)
138
 
        store.remove(request)
 
145
        store.delete(request)
139
146
 
140
147
 
141
148
 
142
149
class _Request(Model):
143
150
    """Table for mailing list hold requests."""
144
151
 
145
 
    id = Int(primary=True, default=AutoReload)
146
 
    key = Unicode()
147
 
    request_type = Enum(RequestType)
148
 
    data_hash = RawStr()
149
 
 
150
 
    mailing_list_id = Int()
151
 
    mailing_list = Reference(mailing_list_id, 'MailingList.id')
 
152
    __tablename__ = '_request'
 
153
 
 
154
    id = Column(Integer, primary_key=True)
 
155
    key = Column(Unicode)
 
156
    request_type = Column(Enum(RequestType))
 
157
    data_hash = Column(LargeBinary)
 
158
 
 
159
    mailing_list_id = Column(Integer, ForeignKey('mailinglist.id'), index=True)
 
160
    mailing_list = relationship('MailingList')
152
161
 
153
162
    def __init__(self, key, request_type, mailing_list, data_hash):
154
163
        super(_Request, self).__init__()