~ubuntu-branches/ubuntu/natty/moin/natty-updates

« back to all changes in this revision

Viewing changes to MoinMoin/datastruct/backends/__init__.py

  • Committer: Bazaar Package Importer
  • Author(s): Jonas Smedegaard
  • Date: 2008-06-22 21:17:13 UTC
  • mto: This revision was merged to the branch mainline in revision 18.
  • Revision ID: james.westby@ubuntu.com-20080622211713-inlv5k4eifxckelr
ImportĀ upstreamĀ versionĀ 1.7.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# -*- coding: iso-8859-1 -*-
2
 
"""
3
 
MoinMoin - base classes for datastructs.
4
 
 
5
 
@copyright: 2009 MoinMoin:DmitrijsMilajevs
6
 
@license: GPL, see COPYING for details
7
 
"""
8
 
 
9
 
from UserDict import DictMixin
10
 
 
11
 
 
12
 
class GroupDoesNotExistError(Exception):
13
 
    """
14
 
    Raised when a group name is not found in the backend.
15
 
    """
16
 
 
17
 
 
18
 
class DictDoesNotExistError(Exception):
19
 
    """
20
 
    Raised when a dict name is not found in the backend.
21
 
    """
22
 
 
23
 
 
24
 
class BaseGroup(object):
25
 
    """
26
 
    Group is something which stores members. Groups are immutable. A
27
 
    member is some arbitrary entity name (Unicode object).
28
 
    """
29
 
 
30
 
    def __init__(self, request, name, backend):
31
 
        """
32
 
        Initialize a group.
33
 
 
34
 
        @param request
35
 
        @param name: moin group name
36
 
        @backend: backend object which created this object
37
 
        """
38
 
        self.request = request
39
 
        self.name = name
40
 
        self._backend = backend
41
 
 
42
 
    def __contains__(self, member, processed_groups=None):
43
 
        raise NotImplementedError()
44
 
 
45
 
    def __iter__(self, yielded_members=None, processed_groups=None):
46
 
        raise NotImplementedError()
47
 
 
48
 
 
49
 
class BaseGroupsBackend(object):
50
 
    """
51
 
    Backend provides access to the group definitions for the other
52
 
    MoinMoin code.
53
 
    """
54
 
 
55
 
    def __init__(self, request):
56
 
        self.request = request
57
 
        self.page_group_regex = request.cfg.cache.page_group_regexact
58
 
 
59
 
    def is_group_name(self, member):
60
 
        return self.page_group_regex.match(member)
61
 
 
62
 
    def __contains__(self, group_name):
63
 
        """
64
 
        Check if a group called <group_name> is available in this backend.
65
 
        """
66
 
        raise NotImplementedError()
67
 
 
68
 
    def __iter__(self):
69
 
        """
70
 
        Iterate over moin group names of the groups defined in this backend.
71
 
 
72
 
        @return: moin group names
73
 
        """
74
 
        raise NotImplementedError()
75
 
 
76
 
    def __getitem__(self, group_name):
77
 
        """
78
 
        Get a group by its moin group name.
79
 
        """
80
 
        raise NotImplementedError()
81
 
 
82
 
    def __repr__(self):
83
 
        return "<%s groups=%s>" % (self.__class__, list(self))
84
 
 
85
 
    def _retrieve_members(self, group_name):
86
 
        raise NotImplementedError()
87
 
 
88
 
    def groups_with_member(self, member):
89
 
        """
90
 
        List all group names of groups containing <member>.
91
 
 
92
 
        @param member: member name [unicode]
93
 
        @return: list of group names [unicode]
94
 
        """
95
 
        for group_name in self:
96
 
            try:
97
 
                if member in self[group_name]:
98
 
                    yield group_name
99
 
            except GroupDoesNotExistError:
100
 
                pass
101
 
 
102
 
    def get(self, key, default=None):
103
 
        """
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.
107
 
        """
108
 
        try:
109
 
            return self[key]
110
 
        except GroupDoesNotExistError:
111
 
            return default
112
 
 
113
 
 
114
 
class LazyGroup(BaseGroup):
115
 
    """
116
 
    A lazy group does not store members internally, but gets them from
117
 
    a backend when needed.
118
 
 
119
 
    Lazy group is made only of members. It can not consist of other groups.
120
 
 
121
 
    For instance, this is a possible LazyGroup:
122
 
 
123
 
     PossibleGroup
124
 
      * OneMember
125
 
      * OtherMember
126
 
 
127
 
    This is a group which cannot be LazyGroup:
128
 
 
129
 
     NotPossibleGroup
130
 
      * OneMember
131
 
      * OtherMember
132
 
      * OtherGroup
133
 
    """
134
 
 
135
 
    def __init__(self, request, name, backend):
136
 
        super(LazyGroup, self).__init__(request, name, backend)
137
 
 
138
 
        if name not in backend:
139
 
            raise GroupDoesNotExistError(name)
140
 
 
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)
145
 
 
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()
151
 
 
152
 
        for member in self._backend._iter_group_members(self.name):
153
 
            if member not in yielded_members:
154
 
                yielded_members.add(member)
155
 
                yield member
156
 
 
157
 
 
158
 
class LazyGroupsBackend(BaseGroupsBackend):
159
 
 
160
 
    def _iter_group_members(self, group_name):
161
 
        raise NotImplementedError()
162
 
 
163
 
    def _group_has_member(self, group_name, member):
164
 
        raise NotImplementedError()
165
 
 
166
 
 
167
 
class GreedyGroup(BaseGroup):
168
 
    """
169
 
    GreedyGroup gets all members during initialization and stores them internally.
170
 
 
171
 
    Members of a group may be names of other groups.
172
 
    """
173
 
 
174
 
    def __init__(self, request, name, backend):
175
 
 
176
 
        super(GreedyGroup, self).__init__(request, name, backend)
177
 
        self.members, self.member_groups = self._load_group()
178
 
 
179
 
    def _load_group(self):
180
 
        """
181
 
        Retrieve group data from the backend and filter it to members and group_members.
182
 
        """
183
 
        members_retrieved = set(self._backend._retrieve_members(self.name))
184
 
 
185
 
        member_groups = set(member for member in members_retrieved if self._backend.is_group_name(member))
186
 
        members = members_retrieved - member_groups
187
 
 
188
 
        return members, member_groups
189
 
 
190
 
    def __contains__(self, member, processed_groups=None):
191
 
        """
192
 
        First check if <member> is part of this group and then check
193
 
        for every subgroup in this group.
194
 
 
195
 
        <processed_groups> is needed to avoid infinite recursion, if
196
 
        groups are defined recursively.
197
 
 
198
 
        @param member: member name [unicode]
199
 
        @param processed_groups: groups which were checked for containment before [set]
200
 
        """
201
 
 
202
 
        if processed_groups is None:
203
 
            processed_groups = set()
204
 
 
205
 
        processed_groups.add(self.name)
206
 
 
207
 
        if member in self.members or member in self.member_groups:
208
 
            return True
209
 
        else:
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):
213
 
                    return True
214
 
 
215
 
        return False
216
 
 
217
 
    def __iter__(self, yielded_members=None, processed_groups=None):
218
 
        """
219
 
        Iterate first over members of this group, then over subgroups of this group.
220
 
 
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
225
 
 
226
 
        @param yielded_members: members which have been already yielded before [set]
227
 
        @param processed_groups: group names which have been iterated before [set]
228
 
        """
229
 
 
230
 
        if processed_groups is None:
231
 
            processed_groups = set()
232
 
 
233
 
        if yielded_members is None:
234
 
            yielded_members = set()
235
 
 
236
 
        processed_groups.add(self.name)
237
 
 
238
 
        for member in self.members:
239
 
            if member not in yielded_members:
240
 
                yielded_members.add(member)
241
 
                yield member
242
 
 
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):
248
 
                        yield member
249
 
                else:
250
 
                    yield group_name
251
 
 
252
 
    def __repr__(self):
253
 
        return "<%s name=%s members=%s member_groups=%s>" % (self.__class__,
254
 
                                                             self.name,
255
 
                                                             self.members,
256
 
                                                             self.member_groups)
257
 
 
258
 
 
259
 
class BaseDict(object, DictMixin):
260
 
 
261
 
    def __init__(self, request, name, backend):
262
 
        """
263
 
        Initialize a dict. Dicts are greedy, it stores all keys and
264
 
        items internally.
265
 
 
266
 
        @param request
267
 
        @param name: moin dict name
268
 
        @backend: backend object which created this object
269
 
        """
270
 
        self.request = request
271
 
        self.name = name
272
 
        self._backend = backend
273
 
        self._dict = self._load_dict()
274
 
 
275
 
    def __iter__(self):
276
 
        return self._dict.__iter__()
277
 
 
278
 
    def keys(self):
279
 
        return list(self)
280
 
 
281
 
    def __len__(self):
282
 
        return self._dict.__len__()
283
 
 
284
 
    def __getitem__(self, key):
285
 
        return self._dict[key]
286
 
 
287
 
    def get(self, key, default=None):
288
 
        """
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.
292
 
        """
293
 
        return self._dict.get(key, default)
294
 
 
295
 
    def _load_dict(self):
296
 
        """
297
 
        Retrieve dict data from the backend.
298
 
        """
299
 
        return self._backend._retrieve_items(self.name)
300
 
 
301
 
    def __repr__(self):
302
 
        return "<%r name=%r items=%r>" % (self.__class__, self.name, self._dict.items())
303
 
 
304
 
 
305
 
class BaseDictsBackend(object):
306
 
 
307
 
    def __init__(self, request):
308
 
        self.request = request
309
 
        self.page_dict_regex = request.cfg.cache.page_dict_regexact
310
 
 
311
 
    def is_dict_name(self, name):
312
 
        return self.page_dict_regex.match(name)
313
 
 
314
 
    def __contains__(self, dict_name):
315
 
        """
316
 
        Check if a dict called <dict_name> is available in this backend.
317
 
        """
318
 
        raise NotImplementedError()
319
 
 
320
 
    def __getitem__(self, dict_name):
321
 
        """
322
 
        Get a dict by its moin dict name.
323
 
        """
324
 
        raise NotImplementedError()
325
 
 
326
 
    def _retrieve_items(self, dict_name):
327
 
        raise NotImplementedError()
328
 
 
329
 
    def get(self, key, default=None):
330
 
        """
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.
334
 
        """
335
 
        try:
336
 
            return self[key]
337
 
        except DictDoesNotExistError:
338
 
            return default
339