changeset 4853:be20907b4747

Groups2009: LazyGroup and LazyGroupsBackend classes were added. The config_lazy_groups backend was refactored.
author Dmitrijs Milajevs <dimazest@gmail.com>
date Fri, 17 Jul 2009 12:19:28 +0200
parents 65bef5bcec41
children 77837e7984ea
files MoinMoin/datastruct/backends/__init__.py MoinMoin/datastruct/backends/_tests/test_lazy_config_groups.py MoinMoin/datastruct/backends/config_lazy_groups.py
diffstat 3 files changed, 149 insertions(+), 166 deletions(-) [+]
line wrap: on
line diff
--- a/MoinMoin/datastruct/backends/__init__.py	Fri Jul 17 08:38:02 2009 +0200
+++ b/MoinMoin/datastruct/backends/__init__.py	Fri Jul 17 12:19:28 2009 +0200
@@ -40,92 +40,6 @@
             raise NotImplementedError()
 
 
-class GreedyGroup(BaseGroup):
-
-    def __init__(self, request, name, backend):
-        super(GreedyGroup, self).__init__(request, name, backend)
-        self.members, self.member_groups = self._load_group()
-
-    def _load_group(self):
-        """
-        Retrieve group data from the backend and filter it to members and group_members.
-        """
-        members_retrieved = set(self._backend._retrieve_members(self.name))
-
-        member_groups = set(member for member in members_retrieved if self._backend.is_group_name(member))
-        members = members_retrieved - member_groups
-
-        return members, member_groups
-
-    def __contains__(self, member, processed_groups=None):
-        """
-        First check if <member> is part of this group and then check
-        for every subgroup in this group.
-
-        <processed_groups> is needed to avoid infinite recursion, if
-        groups are defined recursively.
-
-        @param member: member name [unicode]
-        @param processed_groups: groups which were checked for containment before [set]
-        """
-
-        if not processed_groups:
-            processed_groups = set()
-
-        processed_groups.add(self.name)
-
-        if member in self.members or member in self.member_groups:
-            return True
-        else:
-            groups = self.request.groups
-            for group_name in self.member_groups:
-                if group_name not in processed_groups and group_name in groups and groups[group_name].__contains__(member, processed_groups):
-                    return True
-
-        return False
-
-    def __iter__(self, yielded_members=None, processed_groups=None):
-        """
-        Iterate first over members of this group, then over subgroups of this group.
-
-        <yielded_members> and <processed_groups> are needed to avoid infinite recursion.
-        This can happen if there are two groups like these:
-           OneGroup: Something, OtherGroup
-           OtherGroup: OneGroup, SomethingOther
-
-        @param yielded_members: members which have been already yielded before [set]
-        @param processed_groups: group names which have been iterated before [set]
-        """
-
-        if not processed_groups:
-            processed_groups = set()
-
-        if not yielded_members:
-            yielded_members = set()
-
-        processed_groups.add(self.name)
-
-        for member in self.members:
-            if member not in yielded_members:
-                yielded_members.add(member)
-                yield member
-
-        groups = self.request.groups
-        for group_name in self.member_groups:
-            if group_name not in processed_groups:
-                if group_name in groups:
-                    for member in groups[group_name].__iter__(yielded_members, processed_groups):
-                        yield member
-                else:
-                    yield group_name
-
-    def __repr__(self):
-        return "<%s name=%s members=%s member_groups=%s>" % (self.__class__,
-                                                             self.name,
-                                                             self.members,
-                                                             self.member_groups)
-
-
 class BaseGroupsBackend(object):
 
     def __init__(self, request):
@@ -176,10 +90,135 @@
                 pass
 
     def get(self, key, default=None):
-        if key in self:
+        try:
             return self[key]
+        except GroupDoesNotExistError:
+            return default
+
+
+class LazyGroup(BaseGroup):
+    """
+    A lazy group does not store members internally, but gets them from
+    a backend when needed.
+    """
+
+    def __init__(self, request, name, backend):
+        super(LazyGroup, self).__init__(request, name, backend)
+
+        if name not in backend:
+            raise GroupDoesNotExistError(name)
+
+    def __contains__(self, member, processed_groups=None):
+        # processed_groups are not used here but other group classes
+        # may expect this parameter.
+        return self._backend._group_has_member(self.name, member)
+
+    def __iter__(self, yielded_members=None, processed_groups=None):
+        # processed_groups are not used here but other group classes
+        # may expect this parameter.
+        if yielded_members is None:
+            yielded_members = set()
+
+        for member in self._backend._iter_group_members(self.name):
+            if member not in yielded_members:
+                yielded_members.add(member)
+                yield member
+
+
+class LazyGroupsBackend(BaseGroupsBackend):
+
+    def _iter_group_members(self, group_name):
+        raise NotImplementedError()
+
+    def _group_has_member(self, group_name, member):
+        raise NotImplementedError()
+
+
+class GreedyGroup(BaseGroup):
+
+    def __init__(self, request, name, backend):
+
+        super(GreedyGroup, self).__init__(request, name, backend)
+        self.members, self.member_groups = self._load_group()
+
+    def _load_group(self):
+        """
+        Retrieve group data from the backend and filter it to members and group_members.
+        """
+        members_retrieved = set(self._backend._retrieve_members(self.name))
+
+        member_groups = set(member for member in members_retrieved if self._backend.is_group_name(member))
+        members = members_retrieved - member_groups
+
+        return members, member_groups
+
+    def __contains__(self, member, processed_groups=None):
+        """
+        First check if <member> is part of this group and then check
+        for every subgroup in this group.
+
+        <processed_groups> is needed to avoid infinite recursion, if
+        groups are defined recursively.
+
+        @param member: member name [unicode]
+        @param processed_groups: groups which were checked for containment before [set]
+        """
+
+        if processed_groups is None:
+            processed_groups = set()
+
+        processed_groups.add(self.name)
+
+        if member in self.members or member in self.member_groups:
+            return True
         else:
-            return default
+            groups = self.request.groups
+            for group_name in self.member_groups:
+                if group_name not in processed_groups and group_name in groups and groups[group_name].__contains__(member, processed_groups):
+                    return True
+
+        return False
+
+    def __iter__(self, yielded_members=None, processed_groups=None):
+        """
+        Iterate first over members of this group, then over subgroups of this group.
+
+        <yielded_members> and <processed_groups> are needed to avoid infinite recursion.
+        This can happen if there are two groups like these:
+           OneGroup: Something, OtherGroup
+           OtherGroup: OneGroup, SomethingOther
+
+        @param yielded_members: members which have been already yielded before [set]
+        @param processed_groups: group names which have been iterated before [set]
+        """
+
+        if processed_groups is None:
+            processed_groups = set()
+
+        if yielded_members is None:
+            yielded_members = set()
+
+        processed_groups.add(self.name)
+
+        for member in self.members:
+            if member not in yielded_members:
+                yielded_members.add(member)
+                yield member
+
+        groups = self.request.groups
+        for group_name in self.member_groups:
+            if group_name not in processed_groups:
+                if group_name in groups:
+                    for member in groups[group_name].__iter__(yielded_members, processed_groups):
+                        yield member
+                else:
+                    yield group_name
+
+    def __repr__(self):
+        return "<%s name=%s members=%s member_groups=%s>" % (self.__class__,
+                                                             self.name,
+                                                             self.members,
+                                                             self.member_groups)
 
 
 class BaseDict(object):
--- a/MoinMoin/datastruct/backends/_tests/test_lazy_config_groups.py	Fri Jul 17 08:38:02 2009 +0200
+++ b/MoinMoin/datastruct/backends/_tests/test_lazy_config_groups.py	Fri Jul 17 12:19:28 2009 +0200
@@ -8,7 +8,7 @@
 
 from MoinMoin.datastruct.backends._tests.test_config_groups import TestConfigGroupsBackend
 from MoinMoin.datastruct.backends._tests import GroupsBackendTest
-from MoinMoin.datastruct.backends.config_lazy_groups import LazyConfigGroups
+from MoinMoin.datastruct.backends.config_lazy_groups import ConfigLazyGroups
 from MoinMoin.datastruct import ConfigGroups, CompositeGroups, GroupDoesNotExistError
 from MoinMoin._tests import wikiconfig
 
@@ -27,7 +27,7 @@
 
         def group_manager_init(self, request):
             groups = TestLazyConfigGroups.test_groups
-            return LazyConfigGroups(request, groups)
+            return ConfigLazyGroups(request, groups)
 
     def test_contains_group(self):
         pass
@@ -50,7 +50,7 @@
 
             return CompositeGroups(request,
                                    ConfigGroups(request, config_groups),
-                                   LazyConfigGroups(request, lazy_groups))
+                                   ConfigLazyGroups(request, lazy_groups))
 
 
 coverage_modules = ['MoinMoin.datastruct.backends.config_lazy_groups']
--- a/MoinMoin/datastruct/backends/config_lazy_groups.py	Fri Jul 17 08:38:02 2009 +0200
+++ b/MoinMoin/datastruct/backends/config_lazy_groups.py	Fri Jul 17 12:19:28 2009 +0200
@@ -2,37 +2,28 @@
 """
     MoinMoin - config group lazy backend.
 
-    The config group backend allows defining groups in a configuration
-    file. These backends do not store members internally, but get them
-    from backend when needed in a lazy way.
+    The config group backend allows one to define groups in a
+    configuration file.
 
-    NOTE, the backends are experimental and are implemented to find
-    out how different backends, for example, LDAP backend, should
-    work.
+    NOTE that this is proof-of-concept implementation. LDAP backend
+    should be based on this concept.
 
     @copyright: 2009 MoinMoin:DmitrijsMilajevs
     @license: GPL, see COPYING for details
 """
 
-import time
-
-from MoinMoin.datastruct.backends import BaseGroup, BaseGroupsBackend, GroupDoesNotExistError
+from MoinMoin.datastruct.backends import LazyGroup, LazyGroupsBackend
 
 
-class Proxy(object):
-    """
-    This class is done just to emulate that group definition is
-    something external.
+class ConfigLazyGroup(LazyGroup):
+    pass
 
-    For the LDAP backend this class not needed. __contains__ and
-    __iter__ may be defined in a Group class.
-    """
 
-    def __init__(self, groups):
-        """
-        Although, groups are passed, it doesn't look like
-        something lazy, it the best solution i can find now.
-        """
+class ConfigLazyGroups(LazyGroupsBackend):
+
+    def __init__(self, request, groups):
+        super(ConfigLazyGroups, self).__init__(request)
+
         self._groups = groups
 
     def __contains__(self, group_name):
@@ -41,59 +32,12 @@
     def __iter__(self):
         return self._groups.iterkeys()
 
-    def iter_group(self, group_name):
-        if group_name in self:
-            for member in self._groups[group_name]:
-                # Imitate slow connection
-                time.sleep(0.1)
-                yield member
-
-    def has_member(self, group_name, member):
-        # Imitate slow connection
-        time.sleep(0.1)
-        return group_name in self and member in self._groups[group_name]
-
-
-class LazyGroup(BaseGroup):
-
-    def __init__(self, request, name, backend):
-        super(LazyGroup, self).__init__(request, name, backend)
-
-        if name not in backend:
-            raise GroupDoesNotExistError(name)
-
-        self.proxy = backend._proxy
-
-    def __contains__(self, member, processed_groups=None):
-        return self.proxy.has_member(self.name, member)
+    def __getitem__(self, group_name):
+        return ConfigLazyGroup(self.request, group_name, self)
 
-    def __iter__(self, yielded_members=None, processed_groups=None):
-        if not yielded_members:
-            yielded_members = set()
-
-        for member in self.proxy.iter_group(self.name):
-            if member not in yielded_members:
-                yielded_members.add(member)
-                yield member
-
-
-class LazyConfigGroups(BaseGroupsBackend):
+    def _iter_group_members(self, group_name):
+        if group_name in self:
+            return self._groups[group_name].__iter__()
 
-    def __init__(self, request, groups):
-        """
-        @param groups: Dictionary of groups where key is a group name,
-        and value is a list of members of that group.
-        """
-        super(LazyConfigGroups, self).__init__(request)
-
-        self._proxy = Proxy(groups)
-
-    def __contains__(self, group_name):
-        return group_name in self._proxy
-
-    def __iter__(self):
-        return self._proxy.__iter__()
-
-    def __getitem__(self, group_name):
-        return LazyGroup(request=self.request, name=group_name, backend=self)
-
+    def _group_has_member(self, group_name, member):
+        return group_name in self and member in self._groups[group_name]