changeset 4812:a1018d829c3e

Groups2009: It is possible to import backends as 'from Moin.groups import WikiGroups, ConfigGroups, CompositeGroups'. Compose backend was renamed to Composite.
author Dmitrijs Milajevs <dimazest@gmail.com>
date Sun, 14 Jun 2009 17:23:58 +0200
parents 89497de6165d
children 8ce584105581
files MoinMoin/_tests/wikiconfig_groups.py MoinMoin/events/wikidictsrescan.py MoinMoin/groups/__init__.py MoinMoin/groups/backends/_tests/test_compose_group.py MoinMoin/groups/backends/_tests/test_composite_groups.py MoinMoin/groups/backends/_tests/test_config_group.py MoinMoin/groups/backends/_tests/test_config_groups.py MoinMoin/groups/backends/_tests/test_wiki_group.py MoinMoin/groups/backends/_tests/test_wiki_groups.py MoinMoin/groups/backends/compose_group.py MoinMoin/groups/backends/composite_groups.py MoinMoin/groups/backends/config_group.py MoinMoin/groups/backends/config_groups.py MoinMoin/groups/backends/wiki_group.py MoinMoin/groups/backends/wiki_groups.py
diffstat 15 files changed, 545 insertions(+), 544 deletions(-) [+]
line wrap: on
line diff
--- a/MoinMoin/_tests/wikiconfig_groups.py	Sun Jun 14 17:18:29 2009 +0200
+++ b/MoinMoin/_tests/wikiconfig_groups.py	Sun Jun 14 17:23:58 2009 +0200
@@ -7,8 +7,8 @@
 """
 
 from wikiconfig import LocalConfig
-from MoinMoin.groups.backends import wiki_group
+from MoinMoin.groups import WikiGroups
 
 class Config(LocalConfig):
-    group_manager_init = lambda self, request: wiki_group.Backend(request)
+    group_manager_init = lambda self, request: WikiGroups(request)
 
--- a/MoinMoin/events/wikidictsrescan.py	Sun Jun 14 17:18:29 2009 +0200
+++ b/MoinMoin/events/wikidictsrescan.py	Sun Jun 14 17:23:58 2009 +0200
@@ -12,7 +12,6 @@
 logging = log.getLogger(__name__)
 
 from MoinMoin import events as ev
-from MoinMoin.groups.backends import wiki_group
 from MoinMoin import wikidicts
 
 def handle(event):
--- a/MoinMoin/groups/__init__.py	Sun Jun 14 17:18:29 2009 +0200
+++ b/MoinMoin/groups/__init__.py	Sun Jun 14 17:23:58 2009 +0200
@@ -6,3 +6,7 @@
 @license: GPL, see COPYING for details
 """
 
+from MoinMoin.groups.backends.wiki_groups import WikiGroups
+from MoinMoin.groups.backends.config_groups import ConfigGroups
+from MoinMoin.groups.backends.composite_groups import CompositeGroups
+
--- a/MoinMoin/groups/backends/_tests/test_compose_group.py	Sun Jun 14 17:18:29 2009 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,91 +0,0 @@
-# -*- coding: iso-8859-1 -*-
-
-"""
-MoinMoin.groups.GroupManager test
-
-@copyright: 2009 MoinMoin:DmitrijsMilajevs
-            2008 MoinMoin: MelitaMihaljevic
-@license: GPL, see COPYING for details
-"""
-
-from py.test import raises
-
-from  MoinMoin.groups.backends._tests import BackendTest
-from MoinMoin.groups.backends import config_group, compose_group
-from MoinMoin._tests import wikiconfig
-from MoinMoin import security
-
-
-class TestConfigBackend(BackendTest):
-
-    class Config(wikiconfig.Config):
-
-        def group_manager_init(self, request):
-            groups = BackendTest.test_groups
-            return compose_group.Backend(request, config_group.Backend(request, groups))
-
-
-class TestConfigGroup(object):
-
-    class Config(wikiconfig.Config):
-
-        admin_group = frozenset([u'Admin', u'JohnDoe'])
-        editor_group = frozenset([u'MainEditor', u'JohnDoe'])
-        fruit_group = frozenset([u'Apple', u'Banana', u'Cherry'])
-
-        first_backend_groups = {u'AdminGroup': admin_group,
-                                u'EditorGroup': editor_group,
-                                u'FruitGroup': fruit_group}
-
-        user_group = frozenset([u'JohnDoe', u'Bob', u'Joe'])
-        city_group = frozenset([u'Bolzano', u'Riga', u'London'])
-
-        # Suppose, someone hacked second backend and added himself to AdminGroup
-        second_admin_group = frozenset([u'TheHacker'])
-
-        second_backend_groups = {u'UserGroup': user_group,
-                                 u'CityGroup': city_group,
-                                 # Here group name clash occurs.
-                                 # AdminGroup is defined in both
-                                 # first_backend and second_backend.
-                                 u'AdminGroup': second_admin_group}
-
-        def group_manager_init(self, request):
-            return compose_group.Backend(request,
-                                         config_group.Backend(request,
-                                                              self.first_backend_groups),
-                                         config_group.Backend(request,
-                                                              self.second_backend_groups))
-
-    def setup_method(self, method):
-        self.groups = self.request.groups
-
-    def test_getitem(self):
-        raises(KeyError, lambda: self.groups[u'NotExistingGroup'])
-
-    def test_clashed_getitem(self):
-        """
-        Check the case when groups of the same name are defined in multiple
-        backends. __getitem__ should return the first match (backends are
-        considered in the order they are given in the backends list).
-        """
-        admin_group = self.groups[u'AdminGroup']
-
-        # TheHacker added himself to the second backend, but that must not be
-        # taken into consideration, because AdminGroup is defined in first
-        # backend and we only use the first match.
-        assert u'TheHacker' not in admin_group
-
-    def test_iter(self):
-        all_group_names = [group_name for group_name in self.groups]
-
-        assert 5 == len(all_group_names)
-        # There are no duplicates
-        assert len(set(all_group_names)) == len(all_group_names)
-
-    def test_contains(self):
-        assert u'UserGroup' in self.groups
-        assert u'not existing group' not in self.groups
-
-
-# coverage_modules = ['MoinMoin.groups.backend.compose_group']
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MoinMoin/groups/backends/_tests/test_composite_groups.py	Sun Jun 14 17:23:58 2009 +0200
@@ -0,0 +1,89 @@
+# -*- coding: iso-8859-1 -*-
+
+"""
+MoinMoin.groups.GroupManager test
+
+@copyright: 2009 MoinMoin:DmitrijsMilajevs
+            2008 MoinMoin: MelitaMihaljevic
+@license: GPL, see COPYING for details
+"""
+
+from py.test import raises
+
+from  MoinMoin.groups.backends._tests import BackendTest
+from MoinMoin.groups import ConfigGroups, CompositeGroups
+from MoinMoin._tests import wikiconfig
+from MoinMoin import security
+
+
+class TestConfigBackend(BackendTest):
+
+    class Config(wikiconfig.Config):
+
+        def group_manager_init(self, request):
+            groups = BackendTest.test_groups
+            return CompositeGroups(request, ConfigGroups(request, groups))
+
+
+class TestConfigGroup(object):
+
+    class Config(wikiconfig.Config):
+
+        admin_group = frozenset([u'Admin', u'JohnDoe'])
+        editor_group = frozenset([u'MainEditor', u'JohnDoe'])
+        fruit_group = frozenset([u'Apple', u'Banana', u'Cherry'])
+
+        first_backend_groups = {u'AdminGroup': admin_group,
+                                u'EditorGroup': editor_group,
+                                u'FruitGroup': fruit_group}
+
+        user_group = frozenset([u'JohnDoe', u'Bob', u'Joe'])
+        city_group = frozenset([u'Bolzano', u'Riga', u'London'])
+
+        # Suppose, someone hacked second backend and added himself to AdminGroup
+        second_admin_group = frozenset([u'TheHacker'])
+
+        second_backend_groups = {u'UserGroup': user_group,
+                                 u'CityGroup': city_group,
+                                 # Here group name clash occurs.
+                                 # AdminGroup is defined in both
+                                 # first_backend and second_backend.
+                                 u'AdminGroup': second_admin_group}
+
+        def group_manager_init(self, request):
+            return CompositeGroups(request,
+                                   ConfigGroups(request, self.first_backend_groups),
+                                   ConfigGroups(request, self.second_backend_groups))
+
+    def setup_method(self, method):
+        self.groups = self.request.groups
+
+    def test_getitem(self):
+        raises(KeyError, lambda: self.groups[u'NotExistingGroup'])
+
+    def test_clashed_getitem(self):
+        """
+        Check the case when groups of the same name are defined in multiple
+        backends. __getitem__ should return the first match (backends are
+        considered in the order they are given in the backends list).
+        """
+        admin_group = self.groups[u'AdminGroup']
+
+        # TheHacker added himself to the second backend, but that must not be
+        # taken into consideration, because AdminGroup is defined in first
+        # backend and we only use the first match.
+        assert u'TheHacker' not in admin_group
+
+    def test_iter(self):
+        all_group_names = [group_name for group_name in self.groups]
+
+        assert 5 == len(all_group_names)
+        # There are no duplicates
+        assert len(set(all_group_names)) == len(all_group_names)
+
+    def test_contains(self):
+        assert u'UserGroup' in self.groups
+        assert u'not existing group' not in self.groups
+
+
+coverage_modules = ['MoinMoin.groups.backends.composite_groups']
--- a/MoinMoin/groups/backends/_tests/test_config_group.py	Sun Jun 14 17:18:29 2009 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,28 +0,0 @@
-# -*- coding: iso-8859-1 -*-
-"""
-    MoinMoin - MoinMoin.groups.backends.wiki_group tests
-
-    @copyright: 2003-2004 by Juergen Hermann <jh@web.de>,
-                2007 by MoinMoin:ThomasWaldmann
-                2008 by MoinMoin:MelitaMihaljevic
-                2009 by MoinMoin:DmitrijsMilajevs
-    @license: GNU GPL, see COPYING for details.
-
-"""
-
-from  MoinMoin.groups.backends._tests import BackendTest
-from MoinMoin.groups.backends import config_group
-from MoinMoin._tests import wikiconfig
-
-
-class TestConfigBackend(BackendTest):
-
-    class Config(wikiconfig.Config):
-
-        def group_manager_init(self, request):
-            groups = BackendTest.test_groups
-            return config_group.Backend(request, groups)
-
-
-coverage_modules = ['MoinMoin.groups.backends.config_group']
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MoinMoin/groups/backends/_tests/test_config_groups.py	Sun Jun 14 17:23:58 2009 +0200
@@ -0,0 +1,28 @@
+# -*- coding: iso-8859-1 -*-
+"""
+    MoinMoin - MoinMoin.groups.backends.wiki_group tests
+
+    @copyright: 2003-2004 by Juergen Hermann <jh@web.de>,
+                2007 by MoinMoin:ThomasWaldmann
+                2008 by MoinMoin:MelitaMihaljevic
+                2009 by MoinMoin:DmitrijsMilajevs
+    @license: GNU GPL, see COPYING for details.
+
+"""
+
+from  MoinMoin.groups.backends._tests import BackendTest
+from MoinMoin.groups import ConfigGroups
+from MoinMoin._tests import wikiconfig
+
+
+class TestConfigBackend(BackendTest):
+
+    class Config(wikiconfig.Config):
+
+        def group_manager_init(self, request):
+            groups = BackendTest.test_groups
+            return ConfigGroups(request, groups)
+
+
+coverage_modules = ['MoinMoin.groups.backends.config_groups']
+
--- a/MoinMoin/groups/backends/_tests/test_wiki_group.py	Sun Jun 14 17:18:29 2009 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,249 +0,0 @@
-# -*- coding: iso-8859-1 -*-
-"""
-    MoinMoin - MoinMoin.groups.backends.wiki_group tests
-
-    @copyright: 2003-2004 by Juergen Hermann <jh@web.de>,
-                2007 by MoinMoin:ThomasWaldmann
-                2008 by MoinMoin:MelitaMihaljevic
-                2009 by MoinMoin:DmitrijsMilajevs
-    @license: GNU GPL, see COPYING for details.
-
-"""
-
-from py.test import raises
-import re, shutil
-
-from  MoinMoin.groups.backends._tests import BackendTest
-from MoinMoin.groups.backends import wiki_group
-from MoinMoin import Page, security
-from MoinMoin.PageEditor import PageEditor
-from MoinMoin.user import User
-from MoinMoin._tests import append_page, become_trusted, create_page, create_random_string_list, nuke_page, nuke_user, wikiconfig
-
-
-class TestWikiGroupPageParser(object):
-    """
-    Test what backend extracts from a group page and what is ignored.
-    """
-
-    class Config(wikiconfig.Config):
-
-        def group_manager_init(self, request):
-            return wiki_group.Backend(request)
-
-    def test_CamelCase(self):
-        text = """
- * CamelCase
-"""
-        assert u'CamelCase' in self.get_group(text)
-
-    def test_extended_name(self):
-        text = """
- * extended name
-"""
-        assert u'extended name' in self.get_group(text)
-
-    def test_extended_link(self):
-        text = """
- * [[extended link]]
-"""
-        assert u'extended link' in self.get_group(text)
-
-    def test_ignore_second_level_list(self):
-        text = """
-  * second level
-   * third level
-    * forth level
-     * and then some...
-"""
-        assert len([x for x in self.get_group(text)]) == 0
-
-    def test_ignore_other(self):
-        text = """
-= ignore this =
- * take this
-
-Ignore previous line and this text.
-"""
-        assert u'take this' in self.get_group(text)
-
-    def test_strip_whitespace(self):
-        text = """
- *   take this
-"""
-        assert u'take this' in self.get_group(text)
-
-    def get_group(self, text):
-        request = self.request
-        become_trusted(request)
-        create_page(request, u'SomeTestGroup', text)
-        group = request.groups[u'SomeTestGroup']
-        nuke_page(request, u'SomeTestGroup')
-        return group
-
-
-class TestWikiGroupBackend(BackendTest):
-
-    class Config(wikiconfig.Config):
-
-        def group_manager_init(self, request):
-            return wiki_group.Backend(request)
-
-    def setup_class(self):
-        become_trusted(self.request)
-
-        for (group, members) in self.test_groups.iteritems():
-            page_text = ' * %s' % '\n * '.join(members)
-            create_page(self.request, group, page_text)
-
-    def teardown_class(self):
-        become_trusted(self.request)
-
-        for group in self.test_groups:
-            nuke_page(self.request, group)
-
-    def test_rename_group_page(self):
-        """
-        Tests if the groups cache is refreshed after renaming a Group page.
-        """
-        request = self.request
-        become_trusted(request)
-
-        page = create_page(request, u'SomeGroup', u" * ExampleUser")
-        page.renamePage('AnotherGroup')
-
-        result = u'ExampleUser' in request.groups[u'AnotherGroup']
-        nuke_page(request, u'AnotherGroup')
-
-        assert result is True
-
-    def test_copy_group_page(self):
-        """
-        Tests if the groups cache is refreshed after copying a Group page.
-        """
-        request = self.request
-        become_trusted(request)
-
-        page = create_page(request, u'SomeGroup', u" * ExampleUser")
-        page.copyPage(u'SomeOtherGroup')
-
-        result = u'ExampleUser' in request.groups[u'SomeOtherGroup']
-
-        nuke_page(request, u'OtherGroup')
-        nuke_page(request, u'SomeGroup')
-
-        assert result is True
-
-    def test_appending_group_page(self):
-        """
-        Test scalability by appending a name to a large list of group members.
-        """
-        request = self.request
-        become_trusted(request)
-
-        # long list of users
-        page_content = [u" * %s" % member for member in create_random_string_list(length=15, count=30000)]
-        test_user = create_random_string_list(length=15, count=1)[0]
-        create_page(request, u'UserGroup', "\n".join(page_content))
-        append_page(request, u'UserGroup', u' * %s' % test_user)
-        result = test_user in request.groups['UserGroup']
-        nuke_page(request, u'UserGroup')
-
-        assert result
-
-    def test_user_addition_to_group_page(self):
-        """
-        Test addition of a username to a large list of group members.
-        """
-        request = self.request
-        become_trusted(request)
-
-        # long list of users
-        page_content = [u" * %s" % member for member in create_random_string_list()]
-        create_page(request, u'UserGroup', "\n".join(page_content))
-
-        new_user = create_random_string_list(length=15, count=1)[0]
-        append_page(request, u'UserGroup', u' * %s' % new_user)
-        user = User(request, name=new_user)
-        if not user.exists():
-            User(request, name=new_user, password=new_user).save()
-
-        result = new_user in request.groups[u'UserGroup']
-        nuke_page(request, u'UserGroup')
-        nuke_user(request, new_user)
-
-        assert result
-
-    def test_member_removed_from_group_page(self):
-        """
-        Tests appending a member to a large list of group members and
-        recreating the page without the member.
-        """
-        request = self.request
-        become_trusted(request)
-
-        # long list of users
-        page_content = [u" * %s" % member for member in create_random_string_list()]
-        page_content = "\n".join(page_content)
-        create_page(request, u'UserGroup', page_content)
-
-        test_user = create_random_string_list(length=15, count=1)[0]
-        page = append_page(request, u'UserGroup', u' * %s' % test_user)
-
-        # saves the text without test_user
-        page.saveText(page_content, 0)
-        result = test_user in request.groups[u'UserGroup']
-        nuke_page(request, u'UserGroup')
-
-        assert not result
-
-    def test_group_page_user_addition_trivial_change(self):
-        """
-        Test addition of a user to a group page by trivial change.
-        """
-        request = self.request
-        become_trusted(request)
-
-        test_user = create_random_string_list(length=15, count=1)[0]
-        member = u" * %s\n" % test_user
-        page = create_page(request, u'UserGroup', member)
-
-        # next member saved  as trivial change
-        test_user = create_random_string_list(length=15, count=1)[0]
-        member = u" * %s\n" % test_user
-        page.saveText(member, 0, trivial=1)
-
-        result = test_user in request.groups[u'UserGroup']
-
-        nuke_page(request, u'UserGroup')
-
-        assert result
-
-    def test_wiki_backend_page_acl_append_page(self):
-        """
-        Test if the wiki group backend works with acl code.
-        First check acl rights of a user that is not a member of group
-        then add user member to a page group and check acl rights
-        """
-        request = self.request
-        become_trusted(request)
-
-        create_page(request, u'NewGroup', u" * ExampleUser")
-
-        acl_rights = ["NewGroup:read,write"]
-        acl = security.AccessControlList(request.cfg, acl_rights)
-
-        has_rights_before = acl.may(request, u"AnotherUser", "read")
-
-        # update page - add AnotherUser to a page group NewGroup
-        append_page(request, u'NewGroup', u" * AnotherUser")
-
-        has_rights_after = acl.may(request, u"AnotherUser", "read")
-
-        nuke_page(request, u'NewGroup')
-
-        assert not has_rights_before, 'AnotherUser has no read rights because in the beginning he is not a member of a group page NewGroup'
-        assert has_rights_after, 'AnotherUser must have read rights because after appendage he is member of NewGroup'
-
-coverage_modules = ['MoinMoin.groups.backends.wiki_group']
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MoinMoin/groups/backends/_tests/test_wiki_groups.py	Sun Jun 14 17:23:58 2009 +0200
@@ -0,0 +1,249 @@
+# -*- coding: iso-8859-1 -*-
+"""
+    MoinMoin - MoinMoin.groups.backends.wiki_group tests
+
+    @copyright: 2003-2004 by Juergen Hermann <jh@web.de>,
+                2007 by MoinMoin:ThomasWaldmann
+                2008 by MoinMoin:MelitaMihaljevic
+                2009 by MoinMoin:DmitrijsMilajevs
+    @license: GNU GPL, see COPYING for details.
+
+"""
+
+from py.test import raises
+import re, shutil
+
+from  MoinMoin.groups.backends._tests import BackendTest
+from MoinMoin.groups import WikiGroups
+from MoinMoin import Page, security
+from MoinMoin.PageEditor import PageEditor
+from MoinMoin.user import User
+from MoinMoin._tests import append_page, become_trusted, create_page, create_random_string_list, nuke_page, nuke_user, wikiconfig
+
+
+class TestWikiGroupPageParser(object):
+    """
+    Test what backend extracts from a group page and what is ignored.
+    """
+
+    class Config(wikiconfig.Config):
+
+        def group_manager_init(self, request):
+            return WikiGroups(request)
+
+    def test_CamelCase(self):
+        text = """
+ * CamelCase
+"""
+        assert u'CamelCase' in self.get_group(text)
+
+    def test_extended_name(self):
+        text = """
+ * extended name
+"""
+        assert u'extended name' in self.get_group(text)
+
+    def test_extended_link(self):
+        text = """
+ * [[extended link]]
+"""
+        assert u'extended link' in self.get_group(text)
+
+    def test_ignore_second_level_list(self):
+        text = """
+  * second level
+   * third level
+    * forth level
+     * and then some...
+"""
+        assert len([x for x in self.get_group(text)]) == 0
+
+    def test_ignore_other(self):
+        text = """
+= ignore this =
+ * take this
+
+Ignore previous line and this text.
+"""
+        assert u'take this' in self.get_group(text)
+
+    def test_strip_whitespace(self):
+        text = """
+ *   take this
+"""
+        assert u'take this' in self.get_group(text)
+
+    def get_group(self, text):
+        request = self.request
+        become_trusted(request)
+        create_page(request, u'SomeTestGroup', text)
+        group = request.groups[u'SomeTestGroup']
+        nuke_page(request, u'SomeTestGroup')
+        return group
+
+
+class TestWikiGroupBackend(BackendTest):
+
+    class Config(wikiconfig.Config):
+
+        def group_manager_init(self, request):
+            return WikiGroups(request)
+
+    def setup_class(self):
+        become_trusted(self.request)
+
+        for (group, members) in self.test_groups.iteritems():
+            page_text = ' * %s' % '\n * '.join(members)
+            create_page(self.request, group, page_text)
+
+    def teardown_class(self):
+        become_trusted(self.request)
+
+        for group in self.test_groups:
+            nuke_page(self.request, group)
+
+    def test_rename_group_page(self):
+        """
+        Tests if the groups cache is refreshed after renaming a Group page.
+        """
+        request = self.request
+        become_trusted(request)
+
+        page = create_page(request, u'SomeGroup', u" * ExampleUser")
+        page.renamePage('AnotherGroup')
+
+        result = u'ExampleUser' in request.groups[u'AnotherGroup']
+        nuke_page(request, u'AnotherGroup')
+
+        assert result is True
+
+    def test_copy_group_page(self):
+        """
+        Tests if the groups cache is refreshed after copying a Group page.
+        """
+        request = self.request
+        become_trusted(request)
+
+        page = create_page(request, u'SomeGroup', u" * ExampleUser")
+        page.copyPage(u'SomeOtherGroup')
+
+        result = u'ExampleUser' in request.groups[u'SomeOtherGroup']
+
+        nuke_page(request, u'OtherGroup')
+        nuke_page(request, u'SomeGroup')
+
+        assert result is True
+
+    def test_appending_group_page(self):
+        """
+        Test scalability by appending a name to a large list of group members.
+        """
+        request = self.request
+        become_trusted(request)
+
+        # long list of users
+        page_content = [u" * %s" % member for member in create_random_string_list(length=15, count=30000)]
+        test_user = create_random_string_list(length=15, count=1)[0]
+        create_page(request, u'UserGroup', "\n".join(page_content))
+        append_page(request, u'UserGroup', u' * %s' % test_user)
+        result = test_user in request.groups['UserGroup']
+        nuke_page(request, u'UserGroup')
+
+        assert result
+
+    def test_user_addition_to_group_page(self):
+        """
+        Test addition of a username to a large list of group members.
+        """
+        request = self.request
+        become_trusted(request)
+
+        # long list of users
+        page_content = [u" * %s" % member for member in create_random_string_list()]
+        create_page(request, u'UserGroup', "\n".join(page_content))
+
+        new_user = create_random_string_list(length=15, count=1)[0]
+        append_page(request, u'UserGroup', u' * %s' % new_user)
+        user = User(request, name=new_user)
+        if not user.exists():
+            User(request, name=new_user, password=new_user).save()
+
+        result = new_user in request.groups[u'UserGroup']
+        nuke_page(request, u'UserGroup')
+        nuke_user(request, new_user)
+
+        assert result
+
+    def test_member_removed_from_group_page(self):
+        """
+        Tests appending a member to a large list of group members and
+        recreating the page without the member.
+        """
+        request = self.request
+        become_trusted(request)
+
+        # long list of users
+        page_content = [u" * %s" % member for member in create_random_string_list()]
+        page_content = "\n".join(page_content)
+        create_page(request, u'UserGroup', page_content)
+
+        test_user = create_random_string_list(length=15, count=1)[0]
+        page = append_page(request, u'UserGroup', u' * %s' % test_user)
+
+        # saves the text without test_user
+        page.saveText(page_content, 0)
+        result = test_user in request.groups[u'UserGroup']
+        nuke_page(request, u'UserGroup')
+
+        assert not result
+
+    def test_group_page_user_addition_trivial_change(self):
+        """
+        Test addition of a user to a group page by trivial change.
+        """
+        request = self.request
+        become_trusted(request)
+
+        test_user = create_random_string_list(length=15, count=1)[0]
+        member = u" * %s\n" % test_user
+        page = create_page(request, u'UserGroup', member)
+
+        # next member saved  as trivial change
+        test_user = create_random_string_list(length=15, count=1)[0]
+        member = u" * %s\n" % test_user
+        page.saveText(member, 0, trivial=1)
+
+        result = test_user in request.groups[u'UserGroup']
+
+        nuke_page(request, u'UserGroup')
+
+        assert result
+
+    def test_wiki_backend_page_acl_append_page(self):
+        """
+        Test if the wiki group backend works with acl code.
+        First check acl rights of a user that is not a member of group
+        then add user member to a page group and check acl rights
+        """
+        request = self.request
+        become_trusted(request)
+
+        create_page(request, u'NewGroup', u" * ExampleUser")
+
+        acl_rights = ["NewGroup:read,write"]
+        acl = security.AccessControlList(request.cfg, acl_rights)
+
+        has_rights_before = acl.may(request, u"AnotherUser", "read")
+
+        # update page - add AnotherUser to a page group NewGroup
+        append_page(request, u'NewGroup', u" * AnotherUser")
+
+        has_rights_after = acl.may(request, u"AnotherUser", "read")
+
+        nuke_page(request, u'NewGroup')
+
+        assert not has_rights_before, 'AnotherUser has no read rights because in the beginning he is not a member of a group page NewGroup'
+        assert has_rights_after, 'AnotherUser must have read rights because after appendage he is member of NewGroup'
+
+coverage_modules = ['MoinMoin.groups.backends.wiki_groups']
+
--- a/MoinMoin/groups/backends/compose_group.py	Sun Jun 14 17:18:29 2009 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,61 +0,0 @@
-# -*- coding: iso-8859-1 -*-
-"""
-MoinMoin - group access via various backends.
-
-@copyright: 2009 DmitrijsMilajevs
-@license: GPL, see COPYING for details
-"""
-
-from MoinMoin.groups.backends import BaseBackend
-
-
-class Backend(BaseBackend):
-    """
-    Manage several group backends.
-    """
-
-    def __init__(self, request, *backends):
-        """
-        @param backends: list of group backends which are used to get
-                         access to the group definitions.
-        """
-        super(Backend, self).__init__(request)
-        self._backends = backends
-
-    def __getitem__(self, group_name):
-        """
-        Get a group by its name. First match counts.
-
-        @param group_name: name of the group [unicode]
-        """
-        for backend in self._backends:
-            if group_name in backend:
-                return backend[group_name]
-        raise KeyError("There is no such group %s" % group_name)
-
-    def __iter__(self):
-        """
-        Iterate over group names in all backends (filtering duplicates).
-        """
-        yielded_groups = set()
-
-        for backend in self._backends:
-            for group_name in backend:
-                if group_name not in yielded_groups:
-                    yield group_name
-                    yielded_groups.add(group_name)
-
-    def __contains__(self, group_name):
-        """
-        Check if a group called group_name is available in any of the backends.
-
-        @param group_name: name of the group [unicode]
-        """
-        for backend in self._backends:
-            if group_name in backend:
-                return True
-        return False
-
-    def __repr__(self):
-        return "<%s backends=%s>" % (self.__class__, self._backends)
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MoinMoin/groups/backends/composite_groups.py	Sun Jun 14 17:23:58 2009 +0200
@@ -0,0 +1,61 @@
+# -*- coding: iso-8859-1 -*-
+"""
+MoinMoin - group access via various backends.
+
+@copyright: 2009 DmitrijsMilajevs
+@license: GPL, see COPYING for details
+"""
+
+from MoinMoin.groups.backends import BaseBackend
+
+
+class CompositeGroups(BaseBackend):
+    """
+    Manage several group backends.
+    """
+
+    def __init__(self, request, *backends):
+        """
+        @param backends: list of group backends which are used to get
+                         access to the group definitions.
+        """
+        super(CompositeGroups, self).__init__(request)
+        self._backends = backends
+
+    def __getitem__(self, group_name):
+        """
+        Get a group by its name. First match counts.
+
+        @param group_name: name of the group [unicode]
+        """
+        for backend in self._backends:
+            if group_name in backend:
+                return backend[group_name]
+        raise KeyError("There is no such group %s" % group_name)
+
+    def __iter__(self):
+        """
+        Iterate over group names in all backends (filtering duplicates).
+        """
+        yielded_groups = set()
+
+        for backend in self._backends:
+            for group_name in backend:
+                if group_name not in yielded_groups:
+                    yield group_name
+                    yielded_groups.add(group_name)
+
+    def __contains__(self, group_name):
+        """
+        Check if a group called group_name is available in any of the backends.
+
+        @param group_name: name of the group [unicode]
+        """
+        for backend in self._backends:
+            if group_name in backend:
+                return True
+        return False
+
+    def __repr__(self):
+        return "<%s backends=%s>" % (self.__class__, self._backends)
+
--- a/MoinMoin/groups/backends/config_group.py	Sun Jun 14 17:18:29 2009 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-# -*- coding: iso-8859-1 -*-
-"""
-MoinMoin - config group backend
-
-The config group backend enables you to define groups in a configuration file.
-
-@copyright: 2009 MoinMoin:DmitrijsMilajevs
-@license: GPL, see COPYING for details
-"""
-
-from MoinMoin.groups.backends import BaseGroup, BaseBackend
-
-
-class Group(BaseGroup):
-    pass
-
-
-class Backend(BaseBackend):
-
-    def __init__(self, request, groups):
-        """
-        @param groups: Dictionary of groups where key is group name,
-        and value is list of members of that group.
-        """
-        super(Backend, self).__init__(request)
-
-        self._groups = groups
-
-    def __contains__(self, group_name):
-        return self.page_group_regex.match(group_name) and group_name in self._groups
-
-    def __iter__(self):
-        return self._groups.iterkeys()
-
-    def __getitem__(self, group_name):
-        return Group(request=self.request, name=group_name, backend=self)
-
-    def _retrieve_members(self, group_name):
-        return self._groups[group_name]
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MoinMoin/groups/backends/config_groups.py	Sun Jun 14 17:23:58 2009 +0200
@@ -0,0 +1,40 @@
+# -*- coding: iso-8859-1 -*-
+"""
+MoinMoin - config group backend
+
+The config group backend enables you to define groups in a configuration file.
+
+@copyright: 2009 MoinMoin:DmitrijsMilajevs
+@license: GPL, see COPYING for details
+"""
+
+from MoinMoin.groups.backends import BaseGroup, BaseBackend
+
+
+class Group(BaseGroup):
+    pass
+
+
+class ConfigGroups(BaseBackend):
+
+    def __init__(self, request, groups):
+        """
+        @param groups: Dictionary of groups where key is group name,
+        and value is list of members of that group.
+        """
+        super(ConfigGroups, self).__init__(request)
+
+        self._groups = groups
+
+    def __contains__(self, group_name):
+        return self.page_group_regex.match(group_name) and group_name in self._groups
+
+    def __iter__(self):
+        return self._groups.iterkeys()
+
+    def __getitem__(self, group_name):
+        return Group(request=self.request, name=group_name, backend=self)
+
+    def _retrieve_members(self, group_name):
+        return self._groups[group_name]
+
--- a/MoinMoin/groups/backends/wiki_group.py	Sun Jun 14 17:18:29 2009 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,72 +0,0 @@
-# -*- coding: iso-8859-1 -*-
-"""
-MoinMoin - wiki group backend
-
-The wiki group backend enables you to define groups on wiki pages.  To
-find group pages, request.cfg.cache.page_group_regexact pattern is
-used.  To find group members, it parses these pages and extracts the
-first level list (wiki markup).
-
-@copyright: 2008 MoinMoin:ThomasWaldmann,
-            2008 MoinMoin:MelitaMihaljevic,
-            2009 MoinMoin:DmitrijsMilajevs
-@license: GPL, see COPYING for details
-"""
-
-import re
-
-from MoinMoin import caching, wikiutil
-from MoinMoin.Page import Page
-from MoinMoin.groups.backends import BaseGroup, BaseBackend
-
-
-class Group(BaseGroup):
-
-    def _load_group(self):
-        request = self.request
-        group_name = self.name
-
-        page = Page(request, group_name)
-        if page.exists():
-            arena = 'pagegroups'
-            key = wikiutil.quoteWikinameFS(group_name)
-            cache = caching.CacheEntry(request, arena, key, scope='wiki', use_pickle=True)
-            try:
-                cache_mtime = cache.mtime()
-                page_mtime = wikiutil.version2timestamp(page.mtime_usecs())
-                # TODO: fix up-to-date check mtime granularity problems
-                if cache_mtime > page_mtime:
-                    # cache is uptodate
-                    return cache.content()
-                else:
-                    raise caching.CacheError
-            except caching.CacheError:
-                # either cache does not exist, is erroneous or not uptodate: recreate it
-                members, member_groups = super(Group, self)._load_group()
-                cache.update((members, member_groups))
-                return members, member_groups
-        else:
-            raise KeyError("There is no such group page %s" % group_name)
-
-
-class Backend(BaseBackend):
-
-    def __contains__(self, group_name):
-        return self.is_group(group_name) and Page(self.request, group_name).exists()
-
-    def __iter__(self):
-        return iter(self.request.rootpage.getPageList(user='', filter=self.page_group_regex.search))
-
-    def __getitem__(self, group_name):
-        return Group(request=self.request, name=group_name, backend=self)
-
-    # * Member - ignore all but first level list items, strip
-    # whitespace, strip free links markup. This is used for parsing
-    # pages in order to find group page members.
-    _group_page_parse_regex = re.compile(ur'^ \* +(?:\[\[)?(?P<member>.+?)(?:\]\])? *$', re.MULTILINE | re.UNICODE)
-
-    def _retrieve_members(self, group_name):
-        page = Page(self.request, group_name)
-        text = page.get_raw_body()
-        return [match.group('member') for match in self._group_page_parse_regex.finditer(text)]
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MoinMoin/groups/backends/wiki_groups.py	Sun Jun 14 17:23:58 2009 +0200
@@ -0,0 +1,72 @@
+# -*- coding: iso-8859-1 -*-
+"""
+MoinMoin - wiki group backend
+
+The wiki group backend enables you to define groups on wiki pages.  To
+find group pages, request.cfg.cache.page_group_regexact pattern is
+used.  To find group members, it parses these pages and extracts the
+first level list (wiki markup).
+
+@copyright: 2008 MoinMoin:ThomasWaldmann,
+            2008 MoinMoin:MelitaMihaljevic,
+            2009 MoinMoin:DmitrijsMilajevs
+@license: GPL, see COPYING for details
+"""
+
+import re
+
+from MoinMoin import caching, wikiutil
+from MoinMoin.Page import Page
+from MoinMoin.groups.backends import BaseGroup, BaseBackend
+
+
+class Group(BaseGroup):
+
+    def _load_group(self):
+        request = self.request
+        group_name = self.name
+
+        page = Page(request, group_name)
+        if page.exists():
+            arena = 'pagegroups'
+            key = wikiutil.quoteWikinameFS(group_name)
+            cache = caching.CacheEntry(request, arena, key, scope='wiki', use_pickle=True)
+            try:
+                cache_mtime = cache.mtime()
+                page_mtime = wikiutil.version2timestamp(page.mtime_usecs())
+                # TODO: fix up-to-date check mtime granularity problems
+                if cache_mtime > page_mtime:
+                    # cache is uptodate
+                    return cache.content()
+                else:
+                    raise caching.CacheError
+            except caching.CacheError:
+                # either cache does not exist, is erroneous or not uptodate: recreate it
+                members, member_groups = super(Group, self)._load_group()
+                cache.update((members, member_groups))
+                return members, member_groups
+        else:
+            raise KeyError("There is no such group page %s" % group_name)
+
+
+class WikiGroups(BaseBackend):
+
+    def __contains__(self, group_name):
+        return self.is_group(group_name) and Page(self.request, group_name).exists()
+
+    def __iter__(self):
+        return iter(self.request.rootpage.getPageList(user='', filter=self.page_group_regex.search))
+
+    def __getitem__(self, group_name):
+        return Group(request=self.request, name=group_name, backend=self)
+
+    # * Member - ignore all but first level list items, strip
+    # whitespace, strip free links markup. This is used for parsing
+    # pages in order to find group page members.
+    _group_page_parse_regex = re.compile(ur'^ \* +(?:\[\[)?(?P<member>.+?)(?:\]\])? *$', re.MULTILINE | re.UNICODE)
+
+    def _retrieve_members(self, group_name):
+        page = Page(self.request, group_name)
+        text = page.get_raw_body()
+        return [match.group('member') for match in self._group_page_parse_regex.finditer(text)]
+