All the simple test fixes are now in, and while there are still some failing
[mailman.git] / Mailman / database / model / requests.py
blob0817388e39e07b4983ca01ebb01f0912171257a4
1 # Copyright (C) 2007 by the Free Software Foundation, Inc.
3 # This program is free software; you can redistribute it and/or
4 # modify it under the terms of the GNU General Public License
5 # as published by the Free Software Foundation; either version 2
6 # of the License, or (at your option) any later version.
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
13 # You should have received a copy of the GNU General Public License
14 # along with this program; if not, write to the Free Software
15 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
16 # USA.
18 """Implementations of the IRequests and IListRequests interfaces."""
20 from datetime import timedelta
21 from storm.locals import *
22 from zope.interface import implements
24 from Mailman.configuration import config
25 from Mailman.database import Model
26 from Mailman.database.types import Enum
27 from Mailman.interfaces import IListRequests, IPendable, IRequests, RequestType
30 __metaclass__ = type
31 __all__ = [
32 'Requests',
37 class DataPendable(dict):
38 implements(IPendable)
42 class ListRequests:
43 implements(IListRequests)
45 def __init__(self, mailing_list):
46 self.mailing_list = mailing_list
48 @property
49 def count(self):
50 return config.db.store.find(
51 _Request, mailing_list=self.mailing_list).count()
53 def count_of(self, request_type):
54 return config.db.store.find(
55 _Request,
56 mailing_list=self.mailing_list, request_type=request_type).count()
58 @property
59 def held_requests(self):
60 results = config.db.store.find(
61 _Request, mailing_list=self.mailing_list)
62 for request in results:
63 yield request
65 def of_type(self, request_type):
66 results = config.db.store.find(
67 _Request,
68 mailing_list=self.mailing_list, request_type=request_type)
69 for request in results:
70 yield request
72 def hold_request(self, request_type, key, data=None):
73 if request_type not in RequestType:
74 raise TypeError(request_type)
75 if data is None:
76 data_hash = None
77 else:
78 # We're abusing the pending database as a way of storing arbitrary
79 # key/value pairs, where both are strings. This isn't ideal but
80 # it lets us get auxiliary data almost for free. We may need to
81 # lock this down more later.
82 pendable = DataPendable()
83 pendable.update(data)
84 token = config.db.pendings.add(pendable, timedelta(days=5000))
85 data_hash = token
86 request = _Request(key, request_type, self.mailing_list, data_hash)
87 config.db.store.add(request)
88 return request.id
90 def get_request(self, request_id):
91 result = config.db.store.get(_Request, request_id)
92 if result is None:
93 return None
94 if result.data_hash is None:
95 return result.key, result.data_hash
96 pendable = config.db.pendings.confirm(result.data_hash, expunge=False)
97 data = dict()
98 data.update(pendable)
99 return result.key, data
101 def delete_request(self, request_id):
102 result = _Request.get(request_id)
103 if result is None:
104 raise KeyError(request_id)
105 # Throw away the pended data.
106 config.db.pendings.confirm(result.data_hash)
107 result.delete()
111 class Requests:
112 implements(IRequests)
114 def get_list_requests(self, mailing_list):
115 return ListRequests(mailing_list)
119 class _Request(Model):
120 """Table for mailing list hold requests."""
122 id = Int(primary=True, default=AutoReload)
123 key = Unicode()
124 request_type = Enum()
125 data_hash = RawStr()
127 mailing_list_id = Int()
128 mailing_list = Reference(mailing_list_id, 'MailingList.id')
130 def __init__(self, key, request_type, mailing_list, data_hash):
131 self.key = key
132 self.request_type = request_type
133 self.mailing_list = mailing_list
134 self.data_hash = data_hash