Attachment 'subscriber_cache.py'
Download 1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3
4 """
5 This is not a real plugin, but a hack to patch up MoinMoin's page subscriber
6 list to be cached.
7
8 This is based on http://moinmo.in/MoinMoinBugs/GetSubscribersSlow
9 """
10
11
12 import re
13
14 from MoinMoin import caching, user, Page
15
16
17 def getSubscribersCached(self, request, **kw):
18 """Get all subscribers of this page. Cached version.
19
20 @param request: the request object
21 @keyword include_self: if 1, include current user (default: 0)
22 @keyword return_users: if 1, return user instances (default: 0)
23 @rtype: dict
24 @return: lists of subscribed email addresses in a dict by language key
25 """
26 include_self = kw.get('include_self', self.include_self)
27 return_users = kw.get('return_users', 0)
28
29 request.clock.start('getSubscribersCached')
30 # extract categories of this page
31 pageList = self.getCategories(request)
32
33 # add current page name for list matching
34 pageList.append(self.page_name)
35
36 arena = 'user'
37 key = 'page_sub'
38
39 # get or create cache file
40 page_sub = {}
41 cache = caching.CacheEntry(request, arena, key, scope='wiki',
42 use_pickle=True)
43 if cache.exists():
44 page_sub = cache.content()
45 else:
46 #build a cache if it doesn't exist
47 cache = caching.CacheEntry(request, arena, key, scope='wiki',
48 use_pickle=True, do_locking=False)
49 # lock to stop anybody else interfering with the data while we're
50 # working
51 cache.lock('w')
52 userlist = user.getUserList(request)
53 for uid in userlist:
54 subscriber = user.User(request, uid)
55 # we don't care about storing entries for users without any page
56 # subscriptions
57 if subscriber.subscribed_pages:
58 page_sub[subscriber.id] = {
59 'name': subscriber.name,
60 'email': subscriber.email,
61 'subscribed_pages': subscriber.subscribed_pages
62 }
63 cache.update(page_sub)
64 cache.unlock()
65 # to go back to the same mode as if it had existed all along
66 cache.lock('r')
67
68 if self.cfg.SecurityPolicy:
69 UserPerms = self.cfg.SecurityPolicy
70 else:
71 from MoinMoin.security import Default as UserPerms
72
73 # get email addresses of the all wiki user which have a profile stored;
74 # add the address only if the user has subscribed to the page and
75 # the user is not the current editor
76 userlist = page_sub
77 subscriber_list = {}
78
79 pages = pageList[:]
80 if request.cfg.interwikiname:
81 pages += ["%s:%s" % (request.cfg.interwikiname, pagename) for pagename in pageList]
82 # Create text for regular expression search
83 text = '\n'.join(pages)
84
85 for uid in userlist.keys():
86 if uid == request.user.id and not include_self:
87 continue # no self notification
88
89 isSubscribed = False
90
91 # This is a bit wrong if return_users=1 (which implies that the caller
92 # will process
93 # user attributes and may, for example choose to send an SMS)
94 # So it _should_ be "not (subscriber.email and return_users)" but that
95 # breaks at the moment.
96 if not userlist[uid]['email']:
97 continue # skip empty email addresses
98
99 # now check patters for actual match
100 for pattern in userlist[uid]['subscribed_pages']:
101 if pattern in pages:
102 isSubscribed = True
103 try:
104 pattern = re.compile(r'^%s$' % pattern, re.M)
105 except re.error:
106 continue
107 if pattern.search(text):
108 isSubscribed = True
109
110 # only if subscribed, then read user info from file
111 if isSubscribed:
112 subscriber = user.User(request, uid)
113
114 if not UserPerms(subscriber).read(self.page_name):
115 continue
116
117 lang = subscriber.language or request.cfg.language_default
118 if not lang in subscriber_list:
119 subscriber_list[lang] = []
120 if return_users:
121 subscriber_list[lang].append(subscriber)
122 else:
123 subscriber_list[lang].append(subscriber.email)
124
125 request.clock.stop('getSubscribersCached')
126 return subscriber_list
127
128
129 def updatePageSubCache(self):
130 """
131 When a user changes his preferences, we update the page subscriber's cache
132 """
133
134 arena = 'user'
135 key = 'page_sub'
136
137 page_sub = {}
138 cache = caching.CacheEntry(self._request, arena, key, scope='wiki',
139 use_pickle=True, do_locking=False)
140 if not cache.exists():
141 return # if no cache file, just don't do anything
142
143 cache.lock('w')
144 page_sub = cache.content()
145
146 # we don't care about storing entries for users without any page
147 # subscriptions
148 if self.subscribed_pages:
149 page_sub[self.id] = {
150 'name': self.name,
151 'email': self.email,
152 'subscribed_pages': self.subscribed_pages
153 }
154 elif page_sub.get(self.id):
155 del page_sub[self.id]
156
157 cache.update(page_sub)
158 cache.unlock()
159
160
161 def do_patch():
162 """Install our uncanny patches."""
163
164 if getattr(user.User, 'updatePageSubCache', None) is not None:
165 # The patch is applied already, do nothing
166 return
167
168 Page.Page.getSubscribers = getSubscribersCached
169 oldUserSave = user.User.save
170 def userSave(self, *args, **kwargs):
171 ret = oldUserSave(self, *args, **kwargs)
172 self.updatePageSubCache()
173 return ret
174 user.User.updatePageSubCache = updatePageSubCache
175 user.User.save = userSave
Attached Files
To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.You are not allowed to attach a file to this page.