1
# -*- coding: iso-8859-1 -*-
3
MoinMoin - base classes for datastructs.
5
@copyright: 2009 MoinMoin:DmitrijsMilajevs
6
@license: GPL, see COPYING for details
9
from UserDict import DictMixin
12
class GroupDoesNotExistError(Exception):
14
Raised when a group name is not found in the backend.
18
class DictDoesNotExistError(Exception):
20
Raised when a dict name is not found in the backend.
24
class BaseGroup(object):
26
Group is something which stores members. Groups are immutable. A
27
member is some arbitrary entity name (Unicode object).
30
def __init__(self, request, name, backend):
35
@param name: moin group name
36
@backend: backend object which created this object
38
self.request = request
40
self._backend = backend
42
def __contains__(self, member, processed_groups=None):
43
raise NotImplementedError()
45
def __iter__(self, yielded_members=None, processed_groups=None):
46
raise NotImplementedError()
49
class BaseGroupsBackend(object):
51
Backend provides access to the group definitions for the other
55
def __init__(self, request):
56
self.request = request
57
self.page_group_regex = request.cfg.cache.page_group_regexact
59
def is_group_name(self, member):
60
return self.page_group_regex.match(member)
62
def __contains__(self, group_name):
64
Check if a group called <group_name> is available in this backend.
66
raise NotImplementedError()
70
Iterate over moin group names of the groups defined in this backend.
72
@return: moin group names
74
raise NotImplementedError()
76
def __getitem__(self, group_name):
78
Get a group by its moin group name.
80
raise NotImplementedError()
83
return "<%s groups=%s>" % (self.__class__, list(self))
85
def _retrieve_members(self, group_name):
86
raise NotImplementedError()
88
def groups_with_member(self, member):
90
List all group names of groups containing <member>.
92
@param member: member name [unicode]
93
@return: list of group names [unicode]
95
for group_name in self:
97
if member in self[group_name]:
99
except GroupDoesNotExistError:
102
def get(self, key, default=None):
104
Return the group named <key> if key is in the backend, else
105
default. If default is not given, it defaults to None, so that
106
this method never raises a GroupDoesNotExistError.
110
except GroupDoesNotExistError:
114
class LazyGroup(BaseGroup):
116
A lazy group does not store members internally, but gets them from
117
a backend when needed.
119
Lazy group is made only of members. It can not consist of other groups.
121
For instance, this is a possible LazyGroup:
127
This is a group which cannot be LazyGroup:
135
def __init__(self, request, name, backend):
136
super(LazyGroup, self).__init__(request, name, backend)
138
if name not in backend:
139
raise GroupDoesNotExistError(name)
141
def __contains__(self, member, processed_groups=None):
142
# processed_groups are not used here but other group classes
143
# may expect this parameter.
144
return self._backend._group_has_member(self.name, member)
146
def __iter__(self, yielded_members=None, processed_groups=None):
147
# processed_groups are not used here but other group classes
148
# may expect this parameter.
149
if yielded_members is None:
150
yielded_members = set()
152
for member in self._backend._iter_group_members(self.name):
153
if member not in yielded_members:
154
yielded_members.add(member)
158
class LazyGroupsBackend(BaseGroupsBackend):
160
def _iter_group_members(self, group_name):
161
raise NotImplementedError()
163
def _group_has_member(self, group_name, member):
164
raise NotImplementedError()
167
class GreedyGroup(BaseGroup):
169
GreedyGroup gets all members during initialization and stores them internally.
171
Members of a group may be names of other groups.
174
def __init__(self, request, name, backend):
176
super(GreedyGroup, self).__init__(request, name, backend)
177
self.members, self.member_groups = self._load_group()
179
def _load_group(self):
181
Retrieve group data from the backend and filter it to members and group_members.
183
members_retrieved = set(self._backend._retrieve_members(self.name))
185
member_groups = set(member for member in members_retrieved if self._backend.is_group_name(member))
186
members = members_retrieved - member_groups
188
return members, member_groups
190
def __contains__(self, member, processed_groups=None):
192
First check if <member> is part of this group and then check
193
for every subgroup in this group.
195
<processed_groups> is needed to avoid infinite recursion, if
196
groups are defined recursively.
198
@param member: member name [unicode]
199
@param processed_groups: groups which were checked for containment before [set]
202
if processed_groups is None:
203
processed_groups = set()
205
processed_groups.add(self.name)
207
if member in self.members or member in self.member_groups:
210
groups = self.request.groups
211
for group_name in self.member_groups:
212
if group_name not in processed_groups and group_name in groups and groups[group_name].__contains__(member, processed_groups):
217
def __iter__(self, yielded_members=None, processed_groups=None):
219
Iterate first over members of this group, then over subgroups of this group.
221
<yielded_members> and <processed_groups> are needed to avoid infinite recursion.
222
This can happen if there are two groups like these:
223
OneGroup: Something, OtherGroup
224
OtherGroup: OneGroup, SomethingOther
226
@param yielded_members: members which have been already yielded before [set]
227
@param processed_groups: group names which have been iterated before [set]
230
if processed_groups is None:
231
processed_groups = set()
233
if yielded_members is None:
234
yielded_members = set()
236
processed_groups.add(self.name)
238
for member in self.members:
239
if member not in yielded_members:
240
yielded_members.add(member)
243
groups = self.request.groups
244
for group_name in self.member_groups:
245
if group_name not in processed_groups:
246
if group_name in groups:
247
for member in groups[group_name].__iter__(yielded_members, processed_groups):
253
return "<%s name=%s members=%s member_groups=%s>" % (self.__class__,
259
class BaseDict(object, DictMixin):
261
def __init__(self, request, name, backend):
263
Initialize a dict. Dicts are greedy, it stores all keys and
267
@param name: moin dict name
268
@backend: backend object which created this object
270
self.request = request
272
self._backend = backend
273
self._dict = self._load_dict()
276
return self._dict.__iter__()
282
return self._dict.__len__()
284
def __getitem__(self, key):
285
return self._dict[key]
287
def get(self, key, default=None):
289
Return the value if key is in the dictionary, else default. If
290
default is not given, it defaults to None, so that this method
291
never raises a KeyError.
293
return self._dict.get(key, default)
295
def _load_dict(self):
297
Retrieve dict data from the backend.
299
return self._backend._retrieve_items(self.name)
302
return "<%r name=%r items=%r>" % (self.__class__, self.name, self._dict.items())
305
class BaseDictsBackend(object):
307
def __init__(self, request):
308
self.request = request
309
self.page_dict_regex = request.cfg.cache.page_dict_regexact
311
def is_dict_name(self, name):
312
return self.page_dict_regex.match(name)
314
def __contains__(self, dict_name):
316
Check if a dict called <dict_name> is available in this backend.
318
raise NotImplementedError()
320
def __getitem__(self, dict_name):
322
Get a dict by its moin dict name.
324
raise NotImplementedError()
326
def _retrieve_items(self, dict_name):
327
raise NotImplementedError()
329
def get(self, key, default=None):
331
Return the dictionary named <key> if key is in the backend,
332
else default. If default is not given, it defaults to None, so
333
that this method never raises a DictDoesNotExistError.
337
except DictDoesNotExistError: