diff --git a/CHANGES.rst b/CHANGES.rst index 3e3653f6..f7f37333 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -12,11 +12,26 @@ Breaking changes: New features: -- Make imports work with python 3. Fix startup. +- Make it work in Python 3: + Make imports work. + Fix startup. + Fix setting the auth-cookie. + Fix assignment of MemberData-functions during startup. + User properties are text. + Fix scaling user profile. + Migrate all tests away from PloneTestCasei. + Fix other tests. [pbauer] Bug fixes: +- InitializeClass was moved to AccessControl.class_init + [jensens] + +- setDefaultRoles is deprecated. + addPermission from AccessControl.Permission is used. + [jensens] + - Removed ``Extensions/Install.py`` which had only backwards compatibility imports. [maurits] diff --git a/setup.py b/setup.py index 009c32f6..5114586f 100644 --- a/setup.py +++ b/setup.py @@ -20,7 +20,7 @@ 'setuptools', 'six', 'zope.deprecation', - 'Zope2 >=2.13.22', + 'Zope', ] setup( @@ -35,6 +35,8 @@ "License :: OSI Approved :: Zope Public License", "Programming Language :: Python", "Programming Language :: Python :: 2.7", + "Programming Language :: Python :: 3.6", + "Programming Language :: Python :: 3.7", ], keywords='Zope CMF Plone PAS authentication', author='Kapil Thangavelu, Wichert Akkerman', diff --git a/src/Products/PlonePAS/permissions.py b/src/Products/PlonePAS/permissions.py index 126932a3..0ab494d1 100644 --- a/src/Products/PlonePAS/permissions.py +++ b/src/Products/PlonePAS/permissions.py @@ -1,17 +1,17 @@ # -*- coding: utf-8 -*- -from Products.CMFCore.permissions import setDefaultRoles +from AccessControl.Permission import addPermission AddGroups = 'Add Groups' -setDefaultRoles(AddGroups, ('Manager',)) +addPermission(AddGroups, default_roles=('Manager',)) ManageGroups = 'Manage Groups' -setDefaultRoles(ManageGroups, ('Manager',)) +addPermission(ManageGroups, default_roles=('Manager',)) ViewGroups = 'View Groups' -setDefaultRoles(ViewGroups, ('Manager', 'Owner', 'Member')) +addPermission(ViewGroups, default_roles=('Manager', 'Owner', 'Member')) DeleteGroups = 'Delete Groups' -setDefaultRoles(DeleteGroups, ('Manager', )) +addPermission(DeleteGroups, default_roles=('Manager', )) SetGroupOwnership = 'Set Group Ownership' -setDefaultRoles(SetGroupOwnership, ('Manager', 'Owner')) +addPermission(SetGroupOwnership, default_roles=('Manager', 'Owner')) diff --git a/src/Products/PlonePAS/plugins/autogroup.py b/src/Products/PlonePAS/plugins/autogroup.py index 8ec0ee3f..5783ef63 100644 --- a/src/Products/PlonePAS/plugins/autogroup.py +++ b/src/Products/PlonePAS/plugins/autogroup.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -from App.class_init import InitializeClass +from AccessControl.class_init import InitializeClass from Products.PageTemplates.PageTemplateFile import PageTemplateFile from Products.PlonePAS.interfaces.group import IGroupIntrospection from Products.PluggableAuthService.PropertiedUser import PropertiedUser diff --git a/src/Products/PlonePAS/plugins/cookie_handler.py b/src/Products/PlonePAS/plugins/cookie_handler.py index a301a1ed..e3103c31 100644 --- a/src/Products/PlonePAS/plugins/cookie_handler.py +++ b/src/Products/PlonePAS/plugins/cookie_handler.py @@ -10,7 +10,7 @@ from AccessControl.SecurityManagement import getSecurityManager from Acquisition import aq_base from Acquisition import aq_parent -from App.class_init import InitializeClass +from AccessControl.class_init import InitializeClass from App.special_dtml import DTMLFile from base64 import encodestring from Products.PluggableAuthService.interfaces.authservice import \ @@ -70,7 +70,11 @@ def updateCredentials(self, request, response, login, new_password): setAuthCookie = getattr(self, 'setAuthCookie', None) if setAuthCookie: - cookie_val = encodestring('%s:%s' % (login, new_password)) + cookie_str = b':'.join([ + login.encode('utf-8'), + new_password.encode('utf-8'), + ]) + cookie_val = encodestring(cookie_str) cookie_val = cookie_val.rstrip() setAuthCookie(response, self.cookie_name, quote(cookie_val)) else: diff --git a/src/Products/PlonePAS/plugins/crumbler.py b/src/Products/PlonePAS/plugins/crumbler.py index 0061e1a3..1c940fc9 100644 --- a/src/Products/PlonePAS/plugins/crumbler.py +++ b/src/Products/PlonePAS/plugins/crumbler.py @@ -7,7 +7,7 @@ """ from AccessControl.SecurityInfo import ClassSecurityInfo from Acquisition import aq_base -from App.class_init import InitializeClass +from AccessControl.class_init import InitializeClass from App.special_dtml import DTMLFile from OFS.Folder import Folder from Products.CMFCore.CookieCrumbler import manage_addCC diff --git a/src/Products/PlonePAS/plugins/group.py b/src/Products/PlonePAS/plugins/group.py index 2bc36bf6..bbbd21ed 100644 --- a/src/Products/PlonePAS/plugins/group.py +++ b/src/Products/PlonePAS/plugins/group.py @@ -5,7 +5,7 @@ """ from AccessControl import ClassSecurityInfo -from App.class_init import InitializeClass +from AccessControl.class_init import InitializeClass from App.special_dtml import DTMLFile from BTrees.OOBTree import OOBTree from BTrees.OOBTree import OOSet diff --git a/src/Products/PlonePAS/plugins/local_role.py b/src/Products/PlonePAS/plugins/local_role.py index f09ef382..93e76b5d 100644 --- a/src/Products/PlonePAS/plugins/local_role.py +++ b/src/Products/PlonePAS/plugins/local_role.py @@ -9,7 +9,7 @@ from AccessControl import ClassSecurityInfo from Acquisition import aq_inner from Acquisition import aq_parent -from App.class_init import InitializeClass +from AccessControl.class_init import InitializeClass from App.special_dtml import DTMLFile from Products.PlonePAS.interfaces.plugins import ILocalRolesPlugin from Products.PluggableAuthService.plugins.LocalRolePlugin \ diff --git a/src/Products/PlonePAS/plugins/passwordpolicy.py b/src/Products/PlonePAS/plugins/passwordpolicy.py index 0b3c29a8..f0e36f89 100644 --- a/src/Products/PlonePAS/plugins/passwordpolicy.py +++ b/src/Products/PlonePAS/plugins/passwordpolicy.py @@ -4,7 +4,7 @@ Mutable Property Provider """ from AccessControl import ClassSecurityInfo -from App.class_init import InitializeClass +from AccessControl.class_init import InitializeClass from Products.PageTemplates.PageTemplateFile import PageTemplateFile from Products.PluggableAuthService.interfaces.plugins import IValidationPlugin from Products.PluggableAuthService.plugins.BasePlugin import BasePlugin diff --git a/src/Products/PlonePAS/plugins/property.py b/src/Products/PlonePAS/plugins/property.py index 799bd379..430a9dfa 100644 --- a/src/Products/PlonePAS/plugins/property.py +++ b/src/Products/PlonePAS/plugins/property.py @@ -3,7 +3,7 @@ Mutable Property Provider """ from AccessControl import ClassSecurityInfo -from App.class_init import InitializeClass +from AccessControl.class_init import InitializeClass from App.special_dtml import DTMLFile from BTrees.OOBTree import OOBTree from Products.CMFCore.utils import getToolByName diff --git a/src/Products/PlonePAS/plugins/role.py b/src/Products/PlonePAS/plugins/role.py index 8a0b4442..9c836ae0 100644 --- a/src/Products/PlonePAS/plugins/role.py +++ b/src/Products/PlonePAS/plugins/role.py @@ -10,7 +10,7 @@ from Acquisition import aq_get from Acquisition import aq_inner from Acquisition import aq_parent -from App.class_init import InitializeClass +from AccessControl.class_init import InitializeClass from App.special_dtml import DTMLFile from Products.PlonePAS.interfaces.capabilities import IAssignRoleCapability from Products.PlonePAS.utils import getGroupsForPrincipal diff --git a/src/Products/PlonePAS/plugins/ufactory.py b/src/Products/PlonePAS/plugins/ufactory.py index 6663650b..9be8b467 100644 --- a/src/Products/PlonePAS/plugins/ufactory.py +++ b/src/Products/PlonePAS/plugins/ufactory.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- from AccessControl import ClassSecurityInfo from AccessControl.PermissionRole import _what_not_even_god_should_do -from App.class_init import InitializeClass +from AccessControl.class_init import InitializeClass from App.special_dtml import DTMLFile from Products.PlonePAS.interfaces.plugins import ILocalRolesPlugin from Products.PlonePAS.interfaces.propertysheets import IMutablePropertySheet @@ -215,7 +215,7 @@ def setProperties(self, properties=None, **kw): continue update = {} - for (key, value) in properties.items(): + for (key, value) in list(properties.items()): if sheet.hasProperty(key): update[key] = value del properties[key] @@ -227,7 +227,7 @@ def getProperty(self, id, default=_marker): for sheet in self.getOrderedPropertySheets(): if sheet.hasProperty(id): value = sheet.getProperty(id) - if isinstance(value, six.text_type): + if six.PY2 and isinstance(value, six.text_type): # XXX Temporarily work around the fact that # property sheets blindly store and return # unicode. This is sub-optimal and should be diff --git a/src/Products/PlonePAS/plugins/user.py b/src/Products/PlonePAS/plugins/user.py index 79ee8f0f..5a4d8ace 100644 --- a/src/Products/PlonePAS/plugins/user.py +++ b/src/Products/PlonePAS/plugins/user.py @@ -5,7 +5,7 @@ from AccessControl import AuthEncoding from AccessControl import ClassSecurityInfo from AccessControl.Permissions import manage_users as ManageUsers -from App.class_init import InitializeClass +from AccessControl.class_init import InitializeClass from App.special_dtml import DTMLFile from Products.PlonePAS.interfaces.capabilities import IDeleteCapability from Products.PlonePAS.interfaces.capabilities import IPasswordSetCapability diff --git a/src/Products/PlonePAS/testing.py b/src/Products/PlonePAS/testing.py new file mode 100644 index 00000000..39bcf180 --- /dev/null +++ b/src/Products/PlonePAS/testing.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- +from plone.app.contenttypes.testing import PLONE_APP_CONTENTTYPES_FIXTURE +from plone.app.testing import setRoles +from plone.app.testing import TEST_USER_ID +from plone.app.testing import applyProfile +from plone.app.testing import FunctionalTesting +from plone.app.testing import IntegrationTesting +from plone.app.testing import PloneSandboxLayer +from plone.testing import z2 + +import Products.PlonePAS + + +class ProductsPlonepasLayer(PloneSandboxLayer): + + defaultBases = (PLONE_APP_CONTENTTYPES_FIXTURE,) + + def setUpZope(self, app, configurationContext): + # Load any other ZCML that is required for your tests. + # The z3c.autoinclude feature is disabled in the Plone fixture base + # layer. + self.loadZCML(package=Products.PlonePAS) + z2.installProduct(app, 'Products.PlonePAS') + + def setUpPloneSite(self, portal): + applyProfile(portal, 'Products.PlonePAS:PlonePAS') + # setRoles(portal, TEST_USER_ID, ['Manager']) + from Products.CMFPlone.utils import _createObjectByType + _createObjectByType('Folder', portal, id='Members') + mtool = portal.portal_membership + if not mtool.getMemberareaCreationFlag(): + mtool.setMemberareaCreationFlag() + mtool.createMemberArea(TEST_USER_ID) + if mtool.getMemberareaCreationFlag(): + mtool.setMemberareaCreationFlag() + + _createObjectByType('Folder', portal, id='folder') + + +PRODUCTS_PLONEPAS_FIXTURE = ProductsPlonepasLayer() + + +PRODUCTS_PLONEPAS_INTEGRATION_TESTING = IntegrationTesting( + bases=(PRODUCTS_PLONEPAS_FIXTURE,), + name='ProductsPlonepasLayer:IntegrationTesting', +) + + +PRODUCTS_PLONEPAS_FUNCTIONAL_TESTING = FunctionalTesting( + bases=(PRODUCTS_PLONEPAS_FIXTURE,), + name='ProductsPlonepasLayer:FunctionalTesting', +) diff --git a/src/Products/PlonePAS/tests/base.py b/src/Products/PlonePAS/tests/base.py deleted file mode 100644 index 20038455..00000000 --- a/src/Products/PlonePAS/tests/base.py +++ /dev/null @@ -1,3 +0,0 @@ -# -*- coding: utf-8 -*- -from plone.app.testing.bbb import PloneTestCase as TestCase # noqa -from plone.app.testing.bbb import PloneTestCase as FunctionalTestCase # noqa diff --git a/src/Products/PlonePAS/tests/cookie_auth.rst b/src/Products/PlonePAS/tests/cookie_auth.rst index e5b0e795..7405a560 100644 --- a/src/Products/PlonePAS/tests/cookie_auth.rst +++ b/src/Products/PlonePAS/tests/cookie_auth.rst @@ -11,13 +11,13 @@ User in Plone Site Plone Site has PAS installed >>> portal = layer['portal'] - >>> print portal.acl_users.meta_type + >>> print(portal.acl_users.meta_type) Pluggable Auth Service User exists in the user folder inside the Plone Site. >>> uf = portal.acl_users - >>> print uf.meta_type + >>> print(uf.meta_type) Pluggable Auth Service >>> user_name, user_password, user_role = ('foo', 'bar', 'Manager') @@ -32,7 +32,7 @@ Login to Plone Site using Basic Auth works. >>> browser = Browser(layer['app']) >>> browser.addHeader('Authorization', 'Basic %s:%s' % (TEST_USER_NAME, TEST_USER_PASSWORD,)) >>> browser.open('%s/manage' % portal.absolute_url()) - >>> print browser.headers + >>> print(browser.headers) Status: 200 ... Make sure cookie plugin is installed and activated. @@ -53,13 +53,13 @@ Make sure cookie plugin is installed and activated. ... pass >>> for active, iface in actives: - ... print iface, + ... print(iface) ... for id, plugin in active: ... if id == 'credentials_cookie_auth': - ... print True - <...IExtraction...> True - <...IChallenge...> True - <...ICredentialsUpdate...> <...ICredentialsReset...> + ... print(True) + <...IExtraction...>...True + <...IChallenge...>...True + <...ICredentialsUpdate...>...<...ICredentialsReset...> User in parent folder --------------------- @@ -68,7 +68,7 @@ User Exists on the folder containing the Plone Site, which should be a Pluggable Auth Service too. >>> uf = layer['app'].acl_users - >>> print uf.meta_type + >>> print(uf.meta_type) Pluggable Auth Service >>> user_name, user_password, user_role = ('baz', 'bar', 'Manager') @@ -85,7 +85,7 @@ Login directly to containing folder using Basic Auth works. >>> browser = Browser(layer['app']) >>> browser.addHeader('Authorization', 'Basic %s:%s' % (user_name, user_password,)) >>> browser.open('%s/manage' % layer['app'].absolute_url()) - >>> print browser.headers + >>> print(browser.headers) Status: 200 ... Login to Plone Site using Basic Auth works. @@ -93,6 +93,6 @@ Login to Plone Site using Basic Auth works. >>> browser = Browser(layer['app']) >>> browser.addHeader('Authorization', 'Basic %s:%s' % (user_name, user_password,)) >>> browser.open('%s/manage' % portal.absolute_url()) - >>> print browser.headers + >>> print(browser.headers) Status: 200 ... diff --git a/src/Products/PlonePAS/tests/dummy.py b/src/Products/PlonePAS/tests/dummy.py index 5c7a8c36..3dfede87 100644 --- a/src/Products/PlonePAS/tests/dummy.py +++ b/src/Products/PlonePAS/tests/dummy.py @@ -1,9 +1,9 @@ # -*- coding: utf-8 -*- from OFS.SimpleItem import SimpleItem -from six import StringIO +from six import BytesIO from ZPublisher.HTTPRequest import FileUpload -TEXT = 'file data' +TEXT = b'file data' class FieldStorage(object): @@ -33,7 +33,7 @@ def __init__(self, filename=None, data=None, headers=None): self.data = data if headers is not None: self.headers = headers - self.file = StringIO(self.data) + self.file = BytesIO(self.data) def seek(self, *args): pass diff --git a/src/Products/PlonePAS/tests/test_basic_ops.py b/src/Products/PlonePAS/tests/test_basic_ops.py index 55188058..220d8960 100644 --- a/src/Products/PlonePAS/tests/test_basic_ops.py +++ b/src/Products/PlonePAS/tests/test_basic_ops.py @@ -1,20 +1,24 @@ # -*- coding: utf-8 -*- -from Products.PlonePAS.tests import base -from Products.PluggableAuthService.PluggableAuthService import \ - _SWALLOWABLE_PLUGIN_EXCEPTIONS -from Products.PluggableAuthService.interfaces.authservice import \ - IPluggableAuthService -from Products.PluggableAuthService.interfaces.events import \ - IPrincipalDeletedEvent +from plone.app.testing import setRoles +from plone.app.testing import TEST_USER_ID +from Products.PlonePAS.testing import PRODUCTS_PLONEPAS_INTEGRATION_TESTING +from Products.PluggableAuthService.interfaces.authservice import IPluggableAuthService +from Products.PluggableAuthService.interfaces.events import IPrincipalDeletedEvent from Products.PluggableAuthService.interfaces.plugins import IRolesPlugin +from Products.PluggableAuthService.PluggableAuthService import _SWALLOWABLE_PLUGIN_EXCEPTIONS from zope.component import adapter from zope.component import getGlobalSiteManager +import unittest -class BasicOpsTestCase(base.TestCase): - def afterSetUp(self): - self.loginAsPortalOwner() +class BasicOpsTestCase(unittest.TestCase): + + layer = PRODUCTS_PLONEPAS_INTEGRATION_TESTING + + def setUp(self): + self.portal = self.layer['portal'] + setRoles(self.portal, TEST_USER_ID, ['Manager']) self.acl_users = self.portal.acl_users def compareRoles(self, target, user, roles): @@ -32,11 +36,9 @@ def compareRoles(self, target, user, roles): user_roles = list(u.getRoles()) else: user_roles = list(u.getRolesInContext(target)) - actual_roles = filter(lambda x: x not in non_roles, user_roles) - actual_roles.sort() + actual_roles = list(filter(lambda x: x not in non_roles, user_roles)) wished_roles = list(roles) - wished_roles.sort() - if actual_roles == wished_roles: + if sorted(actual_roles) == sorted(wished_roles): return 1 raise RuntimeError("User %s: Whished roles: %s BUT current " "roles: %s" % (user, wished_roles, actual_roles)) diff --git a/src/Products/PlonePAS/tests/test_doctests.py b/src/Products/PlonePAS/tests/test_doctests.py index 9e2c509c..73647bfd 100644 --- a/src/Products/PlonePAS/tests/test_doctests.py +++ b/src/Products/PlonePAS/tests/test_doctests.py @@ -1,10 +1,20 @@ # -*- coding: utf-8 -*- -from plone.app.testing.bbb import PTC_FUNCTIONAL_TESTING +from Products.PlonePAS.testing import PRODUCTS_PLONEPAS_FUNCTIONAL_TESTING from plone.testing import layered + import doctest +import re +import six import unittest +class Py23DocChecker(doctest.OutputChecker): + def check_output(self, want, got, optionflags): + if six.PY2: + got = re.sub("IOError", "OSError", got) + return doctest.OutputChecker.check_output(self, want, got, optionflags) + + def test_suite(): suite = unittest.TestSuite() suite.addTest( @@ -12,15 +22,17 @@ def test_suite(): doctest.DocFileSuite( 'cookie_auth.rst', package='Products.PlonePAS.tests', - optionflags=doctest.ELLIPSIS + optionflags=doctest.ELLIPSIS, + checker=Py23DocChecker(), ), - layer=PTC_FUNCTIONAL_TESTING + layer=PRODUCTS_PLONEPAS_FUNCTIONAL_TESTING ) ) suite.addTest( doctest.DocTestSuite( 'Products.PlonePAS.utils', - optionflags=doctest.ELLIPSIS + optionflags=doctest.ELLIPSIS, + checker=Py23DocChecker(), ) ) return suite diff --git a/src/Products/PlonePAS/tests/test_groupdatatool.py b/src/Products/PlonePAS/tests/test_groupdatatool.py index 343c6e7a..d69da2d9 100644 --- a/src/Products/PlonePAS/tests/test_groupdatatool.py +++ b/src/Products/PlonePAS/tests/test_groupdatatool.py @@ -2,9 +2,12 @@ from AccessControl import Permissions from AccessControl import Unauthorized from Acquisition import aq_parent -from Products.PlonePAS.tests import base from plone.app.testing import TEST_USER_ID from plone.app.testing import TEST_USER_NAME +from plone.app.testing import logout +from Products.PlonePAS.testing import PRODUCTS_PLONEPAS_INTEGRATION_TESTING + +import unittest def sortTuple(t): @@ -13,9 +16,12 @@ def sortTuple(t): return tuple(l) -class TestGroupDataTool(base.TestCase): +class TestGroupDataTool(unittest.TestCase): + + layer = PRODUCTS_PLONEPAS_INTEGRATION_TESTING - def afterSetUp(self): + def setUp(self): + self.portal = self.layer['portal'] self.acl_users = self.portal.acl_users self.groups = self.portal.portal_groups self.groupdata = self.portal.portal_groupdata @@ -35,9 +41,12 @@ def testWrapGroup(self): 'GroupManager') -class TestGroupData(base.TestCase): +class TestGroupData(unittest.TestCase): - def afterSetUp(self): + layer = PRODUCTS_PLONEPAS_INTEGRATION_TESTING + + def setUp(self): + self.portal = self.layer['portal'] self.membership = self.portal.portal_membership self.memberdata = self.portal.portal_memberdata self.acl_users = self.portal.acl_users @@ -73,13 +82,13 @@ def testGroupMembersAreWrapped(self): self.assertEqual(aq_parent(ms[0]).__class__.__name__, 'PluggableAuthService') def testAddMember(self): - self.setPermissions([Permissions.manage_users]) + self.portal.manage_role('Member', [Permissions.manage_users]) g = self.groups.getGroupById('foo') g.addMember(TEST_USER_ID) self.assertEqual(g.getGroupMembers()[0].getId(), TEST_USER_ID) def testRemoveMember(self): - self.setPermissions([Permissions.manage_users]) + self.portal.manage_role('Member', [Permissions.manage_users]) g = self.groups.getGroupById('foo') g.addMember(TEST_USER_ID) g.removeMember(TEST_USER_ID) @@ -121,6 +130,7 @@ def testGetRoles(self): ('Authenticated', 'Member')) def testGetRolesInContext(self): + self.folder = self.portal['folder'] g = self.groups.getGroupById('foo') self.acl_users.userSetGroups(TEST_USER_ID, groupnames=['foo']) user = self.acl_users.getUser(TEST_USER_NAME) @@ -145,19 +155,22 @@ def testHasRole(self): self.assertTrue(g.has_role('Member')) -class TestMethodProtection(base.TestCase): +class TestMethodProtection(unittest.TestCase): + + layer = PRODUCTS_PLONEPAS_INTEGRATION_TESTING - def afterSetUp(self): + def setUp(self): + self.portal = self.layer['portal'] self.groups = self.portal.portal_groups self.groups.addGroup('foo') self.groupdata = self.groups.getGroupById('foo') def testAnonAddMember(self): - self.logout() + logout() self.assertRaises(Unauthorized, self.groupdata.addMember, TEST_USER_ID) def testAnonRemoveMember(self): - self.logout() + logout() self.assertRaises(Unauthorized, self.groupdata.removeMember, TEST_USER_ID) @@ -169,10 +182,10 @@ def testMemberRemoveMember(self): TEST_USER_ID) def testManagerAddMember(self): - self.setPermissions([Permissions.manage_users]) + self.portal.manage_role('Member', [Permissions.manage_users]) self.groupdata.addMember(TEST_USER_ID) def testManagerRemoveMember(self): - self.setPermissions([Permissions.manage_users]) + self.portal.manage_role('Member', [Permissions.manage_users]) self.groupdata.addMember(TEST_USER_ID) self.groupdata.removeMember(TEST_USER_ID) diff --git a/src/Products/PlonePAS/tests/test_groupstool.py b/src/Products/PlonePAS/tests/test_groupstool.py index fce58aa7..da81fd0a 100644 --- a/src/Products/PlonePAS/tests/test_groupstool.py +++ b/src/Products/PlonePAS/tests/test_groupstool.py @@ -3,16 +3,20 @@ from AccessControl import Unauthorized from Acquisition import aq_base from Acquisition import aq_parent +from plone.app.testing import setRoles +from plone.app.testing import logout +from plone.app.testing import TEST_USER_ID +from plone.app.testing import TEST_USER_ID from Products.CMFCore.utils import getToolByName from Products.PlonePAS.plugins.group import PloneGroup -from Products.PlonePAS.tests import base +from Products.PlonePAS.testing import PRODUCTS_PLONEPAS_INTEGRATION_TESTING from Products.PlonePAS.tools.groupdata import GroupData -from Products.PluggableAuthService.interfaces.events import \ - IGroupDeletedEvent -from plone.app.testing import TEST_USER_ID +from Products.PluggableAuthService.interfaces.events import IGroupDeletedEvent from zope.component import adapter from zope.component import getGlobalSiteManager +import unittest + def sortTuple(t): l = list(t) @@ -20,15 +24,18 @@ def sortTuple(t): return tuple(l) -class GroupsToolTest(base.TestCase): +class TestGroupsTool(unittest.TestCase): - def afterSetUp(self): + layer = PRODUCTS_PLONEPAS_INTEGRATION_TESTING + + def setUp(self): + self.portal = self.layer['portal'] self.gt = getToolByName(self.portal, 'portal_groups') self.gd = getToolByName(self.portal, 'portal_groupdata') self.group_id = 'group1' # Create a new Group - self.loginAsPortalOwner() + setRoles(self.portal, TEST_USER_ID, ['Manager']) self.gt.addGroup( self.group_id, ['Reviewer'], @@ -89,20 +96,23 @@ def test_edit_group(self): self.assertTrue('Reviewers' in group.getGroups()) -class TestMethodProtection(base.TestCase): +class TestMethodProtection(unittest.TestCase): # GroupData has wrong security declarations - def afterSetUp(self): + layer = PRODUCTS_PLONEPAS_INTEGRATION_TESTING + + def setUp(self): + self.portal = self.layer['portal'] self.groups = self.portal.portal_groups self.groups.addGroup('foo') self.groupdata = self.groups.getGroupById('foo') def testAnonAddMember(self): - self.logout() + logout() self.assertRaises(Unauthorized, self.groupdata.addMember, TEST_USER_ID) def testAnonRemoveMember(self): - self.logout() + logout() self.assertRaises(Unauthorized, self.groupdata.removeMember, TEST_USER_ID) @@ -114,21 +124,25 @@ def testMemberRemoveMember(self): TEST_USER_ID) def testManagerAddMember(self): - self.setPermissions([Permissions.manage_users]) + self.portal.manage_role('Member', [Permissions.manage_users]) self.groupdata.addMember(TEST_USER_ID) def testManagerRemoveMember(self): - self.setPermissions([Permissions.manage_users]) + self.portal.manage_role('Member', [Permissions.manage_users]) self.groupdata.addMember(TEST_USER_ID) self.groupdata.removeMember(TEST_USER_ID) -class TestGroupsTool(base.TestCase): +class TestGroupsTool(unittest.TestCase): + + layer = PRODUCTS_PLONEPAS_INTEGRATION_TESTING - def afterSetUp(self): + def setUp(self): + self.portal = self.layer['portal'] self.membership = self.portal.portal_membership self.acl_users = self.portal.acl_users self.groups = self.portal.portal_groups + self.folder = self.portal['folder'] if 'auto_group' in self.acl_users: self.acl_users.manage_delObjects(['auto_group']) @@ -262,7 +276,7 @@ def testGetGroupInfo(self): def testGetGroupInfoAsAnonymous(self): self.groups.addGroup('foo', title='Foo', description='Bar') - self.logout() + logout() info = self.groups.restrictedTraverse('getGroupInfo')('foo') self.assertEqual(info.get('title'), 'Foo') self.assertEqual(info.get('description'), 'Bar') diff --git a/src/Products/PlonePAS/tests/test_memberdatatool.py b/src/Products/PlonePAS/tests/test_memberdatatool.py index 440322aa..c4321242 100644 --- a/src/Products/PlonePAS/tests/test_memberdatatool.py +++ b/src/Products/PlonePAS/tests/test_memberdatatool.py @@ -2,13 +2,18 @@ from DateTime import DateTime from OFS.Image import Image from plone.app.testing import TEST_USER_ID as default_user -from Products.PlonePAS.tests import base from Products.PlonePAS.tests import dummy +from Products.PlonePAS.testing import PRODUCTS_PLONEPAS_INTEGRATION_TESTING +import unittest -class TestMemberDataTool(base.TestCase): - def afterSetUp(self): +class TestMemberDataTool(unittest.TestCase): + + layer = PRODUCTS_PLONEPAS_INTEGRATION_TESTING + + def setUp(self): + self.portal = self.layer['portal'] self.memberdata = self.portal.portal_memberdata self.membership = self.portal.portal_membership self.membership.memberareaCreationFlag = 0 diff --git a/src/Products/PlonePAS/tests/test_membershiptool.py b/src/Products/PlonePAS/tests/test_membershiptool.py index 5f1ab79f..42d989c8 100644 --- a/src/Products/PlonePAS/tests/test_membershiptool.py +++ b/src/Products/PlonePAS/tests/test_membershiptool.py @@ -11,25 +11,34 @@ from plone.app.testing import TEST_USER_ID from plone.app.testing import TEST_USER_NAME from plone.app.testing import TEST_USER_PASSWORD +from plone.app.testing import login +from plone.app.testing import logout +from plone.app.testing import setRoles from Products.CMFCore.utils import getToolByName from Products.PlonePAS.browser.member import PASMemberView from Products.PlonePAS.interfaces.membership import IMembershipTool from Products.PlonePAS.plugins.ufactory import PloneUser -from Products.PlonePAS.tests import base +from Products.PlonePAS.testing import PRODUCTS_PLONEPAS_INTEGRATION_TESTING from Products.PlonePAS.tests import dummy from Products.PlonePAS.tools.memberdata import MemberData from Products.PlonePAS.tools.membership import MembershipTool from Products.PlonePAS.utils import getGroupsForPrincipal -import six -from six import StringIO +from six import BytesIO from zExceptions import BadRequest +from plone.app.testing import TEST_USER_ID + import os +import six +import unittest -class MembershipToolTest(base.TestCase): +class MembershipToolTest(unittest.TestCase): - def afterSetUp(self): + layer = PRODUCTS_PLONEPAS_INTEGRATION_TESTING + + def setUp(self): + self.portal = self.layer['portal'] self.mt = getToolByName(self.portal, 'portal_membership') self.md = getToolByName(self.portal, 'portal_memberdata') @@ -120,12 +129,16 @@ def test_id_clean(self): cleaned = cleanId(u'abc') self.assertEqual(cleaned, 'abc') self.assertTrue(isinstance(cleaned, str)) - self.assertFalse(isinstance(cleaned, six.text_type)) + if six.PY2: + self.assertFalse(isinstance(cleaned, six.text_type)) + +class MemberAreaTest(unittest.TestCase): -class MemberAreaTest(base.TestCase): + layer = PRODUCTS_PLONEPAS_INTEGRATION_TESTING - def afterSetUp(self): + def setUp(self): + self.portal = self.layer['portal'] self.mt = getToolByName(self.portal, 'portal_membership') self.md = getToolByName(self.portal, 'portal_memberdata') # Enable member-area creation @@ -133,7 +146,7 @@ def afterSetUp(self): # Those are all valid chars in Zope. self.mid = "Member #1 - Houston, TX. ($100)" self.pas = self.portal.acl_users - self.loginAsPortalOwner() + setRoles(self.portal, TEST_USER_ID, ['Manager']) def test_funky_member_ids_1(self): mid = self.mid @@ -167,11 +180,15 @@ def test_memberareaCreationFlag_respected(self): self.assertFalse('bar' in self.portal.Members) -class TestMembershipTool(base.TestCase): +class TestMembershipTool(unittest.TestCase): + + layer = PRODUCTS_PLONEPAS_INTEGRATION_TESTING - def afterSetUp(self): + def setUp(self): + self.portal = self.layer['portal'] self.membership = self.portal.portal_membership self.groups = self.portal.portal_groups + self.folder = self.portal['folder'] def test_interface(self): from zope.interface.verify import verifyClass @@ -232,7 +249,7 @@ def testChangeOwnMemberPortraitWithEmailUsers(self): {'email': 'member2@host.com', 'title': 'Member #2'} ) - self.login(member_id) + login(self.portal, member_id) image = self.makeRealImage() safe_member_id = self.membership._getSafeMemberId(member_id) @@ -247,6 +264,7 @@ def testChangeOwnMemberPortraitWithEmailUsers(self): def testCannotChangeOtherMemberPortrait(self): # A normal member should not be able to change the portrait of # another member. + setRoles(self.portal, TEST_USER_ID, ['Member']) image = self.makeRealImage() self.membership.addMember('joe', 'secret', ['Member'], []) self.assertRaises(Unauthorized, self.membership.changeMemberPortrait, @@ -257,7 +275,7 @@ def testChangeMemberPortraitAsManager(self): # member. image = self.makeRealImage() self.membership.addMember('joe', 'secret', ['Member'], []) - self.setRoles(['Manager']) + setRoles(self.portal, TEST_USER_ID, ['Manager']) # This should not raise Unauthorized: self.membership.changeMemberPortrait(image, 'joe') self.assertEqual(self.membership.getPersonalPortrait('joe').getId(), @@ -282,9 +300,9 @@ def testCannotDeleteOtherPersonalPortrait(self): # another member. image = self.makeRealImage() self.membership.addMember('joe', 'secret', ['Member'], []) - self.setRoles(['Manager']) + setRoles(self.portal, TEST_USER_ID, ['Manager']) self.membership.changeMemberPortrait(image, 'joe') - self.setRoles(['Member']) + setRoles(self.portal, TEST_USER_ID, ['Member']) self.assertRaises(Unauthorized, self.membership.deletePersonalPortrait, 'joe') @@ -293,7 +311,7 @@ def testDeleteOtherPersonalPortraitAsManager(self): # member. image = self.makeRealImage() self.membership.addMember('joe', 'secret', ['Member'], []) - self.setRoles(['Manager']) + setRoles(self.portal, TEST_USER_ID, ['Manager']) self.membership.changeMemberPortrait(image, 'joe') self.membership.deletePersonalPortrait('joe') self.assertEqual( @@ -318,7 +336,7 @@ def testPortraitForNonStandardUserId(self): safe_id = self.membership._getSafeMemberId(user_id) self.assertEqual(safe_id, 'bob--jones-2Btest-40example.org') self.membership.addMember(user_id, 'secret', ['Member'], []) - self.login(user_id) + login(self.portal, user_id) # Should return the default portrait self.assertEqual( @@ -333,7 +351,7 @@ def testPortraitForNonStandardUserId(self): 'Image') # Other users should be able to see your portrait. - self.login(TEST_USER_NAME) + login(self.portal, TEST_USER_NAME) self.assertEqual( self.membership.getPersonalPortrait(user_id).getId(), safe_id) @@ -342,7 +360,7 @@ def testPortraitForNonStandardUserId(self): 'Image') # You can delete your own portrait. - self.login(user_id) + login(self.portal, user_id) self.membership.deletePersonalPortrait(user_id) self.assertEqual( self.membership.getPersonalPortrait(user_id).getId(), @@ -351,7 +369,7 @@ def testPortraitForNonStandardUserId(self): # Managers should be able to change the portrait of another # member and delete it. manager_image = self.makeRealImage() - self.loginAsPortalOwner() + setRoles(self.portal, TEST_USER_ID, ['Manager']) # This should not raise Unauthorized: self.membership.changeMemberPortrait(manager_image, user_id) self.assertEqual(self.membership.getPersonalPortrait(user_id).getId(), @@ -406,7 +424,7 @@ def testSetPassword(self): def testSetPasswordIfAnonymous(self): # Anonymous should not be able to change password - self.logout() + logout() try: self.membership.setPassword('geheim') except BadRequest: @@ -424,9 +442,9 @@ def testSetPasswordAndKeepGroups(self): groups = self.groups groups.addGroup(group2, None, [], []) group = groups.getGroupById(group2) - self.loginAsPortalOwner() + setRoles(self.portal, TEST_USER_ID, ['Manager']) group.addMember(TEST_USER_ID) - self.login(TEST_USER_NAME) # Back to normal + login(self.portal, TEST_USER_NAME) # Back to normal ugroups = self.portal.acl_users.getUserById(TEST_USER_ID).getGroups() self.membership.setPassword('geheim') t_groups = self.portal.acl_users.getUserById(TEST_USER_ID).getGroups() @@ -460,20 +478,20 @@ def testGetAuthenticatedMemberIsWrapped(self): 'PluggableAuthService') def testGetAuthenticatedMemberIfAnonymous(self): - self.logout() + logout() member = self.membership.getAuthenticatedMember() self.assertEqual(member.getUserName(), 'Anonymous User') def testAnonymousMemberIsNotWrapped(self): # Also see http://dev.plone.org/plone/ticket/1851 - self.logout() + logout() member = self.membership.getAuthenticatedMember() self.assertNotEqual(member.__class__.__name__, 'MemberData') self.assertEqual(member.__class__.__name__, 'SpecialUser') def testIsAnonymousUser(self): self.assertFalse(self.membership.isAnonymousUser()) - self.logout() + logout() self.assertTrue(self.membership.isAnonymousUser()) def testWrapUserWrapsBareUser(self): @@ -513,14 +531,14 @@ def testWrapUserWrapsAnonymous(self): def testGetCandidateLocalRoles(self): self.assertEqual(self.membership.getCandidateLocalRoles(self.folder), ('Owner',)) - self.setRoles(['Member', 'Reviewer']) + setRoles(self.portal, TEST_USER_ID, ['Member', 'Reviewer']) self.assertEqual(self.membership.getCandidateLocalRoles(self.folder), ('Owner', 'Reviewer')) def testSetLocalRoles(self): self.assertTrue( 'Owner' in self.folder.get_local_roles_for_userid(TEST_USER_ID)) - self.setRoles(['Member', 'Reviewer']) + setRoles(self.portal, TEST_USER_ID, ['Member', 'Reviewer']) self.membership.setLocalRoles(self.folder, [TEST_USER_ID, 'user2'], 'Reviewer') self.assertEqual(self.folder.get_local_roles_for_userid(TEST_USER_ID), @@ -529,7 +547,7 @@ def testSetLocalRoles(self): ('Reviewer',)) def testDeleteLocalRoles(self): - self.setRoles(['Member', 'Reviewer']) + setRoles(self.portal, TEST_USER_ID, ['Member', 'Reviewer']) self.membership.setLocalRoles(self.folder, ['user2'], 'Reviewer') self.assertEqual(self.folder.get_local_roles_for_userid('user2'), ('Reviewer',)) @@ -630,7 +648,7 @@ def testGetCandidateLocalRolesForAssigned(self): def test_bug4333_delete_user_remove_memberdata(self): # delete user should delete portal_memberdata memberdata = self.portal.portal_memberdata - self.setRoles(['Manager']) + setRoles(self.portal, TEST_USER_ID, ['Manager']) self.addMember('barney', 'Barney Rubble', 'barney@bedrock.com', ['Member'], '2002-01-01') barney = self.membership.getMemberById('barney') @@ -655,7 +673,7 @@ def test_bug4333_delete_user_remove_memberdata(self): def testBogusMemberPortrait(self): # Should change the portrait image - bad_file = dummy.File(data='
This is a lie!!!
', + bad_file = dummy.File(data=b'
This is a lie!!!
', headers={'content_type': 'image/jpeg'}) self.assertRaises(IOError, self.membership.changeMemberPortrait, bad_file, TEST_USER_ID) @@ -668,13 +686,13 @@ def testGetBadMembers(self): bad_file = Image( id=TEST_USER_ID, title='', - file=StringIO('
This is a lie!!!
') + file=BytesIO(b'
This is a lie!!!
') ) # Manually set a bad image using private methods self.portal.portal_memberdata._setPortrait(bad_file, TEST_USER_ID) self.assertEqual(self.membership.getBadMembers(), [TEST_USER_ID]) # Try an empty image - empty_file = Image(id=TEST_USER_ID, title='', file=StringIO('')) + empty_file = Image(id=TEST_USER_ID, title='', file=BytesIO(b'')) self.portal.portal_memberdata._setPortrait(empty_file, TEST_USER_ID) self.assertEqual(self.membership.getBadMembers(), []) # And a good image @@ -683,9 +701,12 @@ def testGetBadMembers(self): self.assertEqual(self.membership.getBadMembers(), []) -class TestCreateMemberarea(base.TestCase): +class TestCreateMemberarea(unittest.TestCase): - def afterSetUp(self): + layer = PRODUCTS_PLONEPAS_INTEGRATION_TESTING + + def setUp(self): + self.portal = self.layer['portal'] self.membership = self.portal.portal_membership self.membership.addMember('user2', 'secret', ['Member'], []) @@ -702,7 +723,7 @@ def testCreateMemberarea(self): def testCreatMemberareaUsesCurrentUser(self): if self.membership.memberareaCreationFlag is True: # Should create a memberarea for user2 - self.login('user2') + login(self.portal, 'user2') self.membership.createMemberarea() memberfolder = self.membership.getHomeFolder('user2') self.assertTrue( @@ -765,9 +786,12 @@ def testCreateMemberareaWhenDisabled(self): ) -class TestMemberareaSetup(base.TestCase): +class TestMemberareaSetup(unittest.TestCase): + + layer = PRODUCTS_PLONEPAS_INTEGRATION_TESTING - def afterSetUp(self): + def setUp(self): + self.portal = self.layer['portal'] self.membership = self.portal.portal_membership self.membership.addMember('user2', 'secret', ['Member'], []) self.membership.createMemberarea('user2') @@ -806,9 +830,12 @@ def testHomePageNotExists(self): self.assertFalse('index_html' in self.home) -class TestSearchForMembers(base.TestCase): +class TestSearchForMembers(unittest.TestCase): + + layer = PRODUCTS_PLONEPAS_INTEGRATION_TESTING - def afterSetUp(self): + def setUp(self): + self.portal = self.layer['portal'] self.memberdata = self.portal.portal_memberdata self.membership = self.portal.portal_membership # Don't let default_user disturb results @@ -885,10 +912,13 @@ def testSearchByRequestObj(self): len(search(REQUEST=dict(name='jürgen'))), 1) -class TestDefaultUserAndPasswordNotChanged(base.TestCase): +class TestDefaultUserAndPasswordNotChanged(unittest.TestCase): # A test for a silly transaction/persistency bug in PlonePAS - def afterSetUp(self): + layer = PRODUCTS_PLONEPAS_INTEGRATION_TESTING + + def setUp(self): + self.portal = self.layer['portal'] self.membership = self.portal.portal_membership def testDefaultUserAndPasswordUnchanged(self): @@ -900,10 +930,12 @@ def testDefaultUserAndPasswordUnchanged(self): self.assertFalse(self.membership.testCurrentPassword('geheim')) -class TestMethodProtection(base.TestCase): +class TestMethodProtection(unittest.TestCase): # MembershipTool is missing security declarations # http://dev.plone.org/plone/ticket/5432 + layer = PRODUCTS_PLONEPAS_INTEGRATION_TESTING + _unprotected = ( 'changeMemberPortrait', 'deletePersonalPortrait', @@ -911,29 +943,33 @@ class TestMethodProtection(base.TestCase): 'searchForMembers', ) - def afterSetUp(self): + def setUp(self): + self.portal = self.layer['portal'] self.membership = self.portal.portal_membership def assertUnprotected(self, object, method): - self.logout() + logout() object.restrictedTraverse(method) def assertProtected(self, object, method): - self.logout() + logout() self.assertRaises(Unauthorized, object.restrictedTraverse, method) for method in _unprotected: - exec "def testUnprotected_%s(self):" \ + exec ("def testUnprotected_%s(self):" \ " self.assertProtected(self.membership, '%s')" \ - % (method, method) + % (method, method)) + + exec ("def testMemberAccessible_%s(self):" \ + " self.membership.restrictedTraverse('%s')" % (method, method)) - exec "def testMemberAccessible_%s(self):" \ - " self.membership.restrictedTraverse('%s')" % (method, method) +class TestMemberInfoView(unittest.TestCase): -class TestMemberInfoView(base.TestCase): + layer = PRODUCTS_PLONEPAS_INTEGRATION_TESTING - def afterSetUp(self): + def setUp(self): + self.portal = self.layer['portal'] self.membership = self.portal.portal_membership self.view = PASMemberView(self.portal, self.portal.REQUEST) @@ -967,7 +1003,7 @@ def testGetMemberInfoViewForNonMember(self): self.assertEqual(info['name_or_id'], 'charon') def testGetMemberInfoViewForAnonymous(self): - self.logout() + logout() self.assertTrue(self.membership.isAnonymousUser()) info = self.view.info() self.assertEqual(info['username'], 'Anonymous User') @@ -991,18 +1027,17 @@ def testGetMemberInfoViewHomePageBad(self): def testSetGroupsWithUserNameIdDifference(self): pas = self.portal['acl_users'] self.portal.portal_groups.addGroup('Editors', [], []) - self.setGroups(['Editors'], name=TEST_USER_ID) - self.login(TEST_USER_NAME) + self.portal.acl_users.userSetGroups(TEST_USER_ID, groupnames=['Editors']) + login(self.portal, TEST_USER_NAME) user = getSecurityManager().getUser() self.assertTrue( 'Editors' in getGroupsForPrincipal(user, pas['plugins']) ) - self.login() def testSetGroupsWithSameUserNameAndId(self): pas = self.portal['acl_users'] self.portal.portal_groups.addGroup('Editors', [], []) - self.setGroups(['Editors']) + self.portal.acl_users.userSetGroups(TEST_USER_ID, groupnames=['Editors']) user = getSecurityManager().getUser() self.assertTrue( 'Editors' in getGroupsForPrincipal(user, pas['plugins']) diff --git a/src/Products/PlonePAS/tests/test_properties.py b/src/Products/PlonePAS/tests/test_properties.py index 3dab964c..f6d5763c 100644 --- a/src/Products/PlonePAS/tests/test_properties.py +++ b/src/Products/PlonePAS/tests/test_properties.py @@ -1,12 +1,22 @@ # -*- coding: utf-8 -*- +from plone.app.testing import setRoles +from plone.app.testing import TEST_USER_ID +from plone.app.testing import login from Products.CMFCore.utils import getToolByName from Products.PlonePAS.plugins.property import ZODBMutablePropertyProvider -from Products.PlonePAS.tests import base from Products.PluggableAuthService.interfaces.plugins import \ IUserEnumerationPlugin +from Products.PlonePAS.testing import PRODUCTS_PLONEPAS_INTEGRATION_TESTING +import unittest -class PropertiesTest(base.TestCase): + +class PropertiesTest(unittest.TestCase): + + layer = PRODUCTS_PLONEPAS_INTEGRATION_TESTING + + def setUp(self): + self.portal = self.layer['portal'] def test_user_properties(self): mt = getToolByName(self.portal, 'portal_membership') @@ -37,7 +47,7 @@ def test_user_properties(self): member = mt.getMemberById('user1') # Set some member properties. Needs to be logged in as the user. - self.login('user1') + login(self.portal, 'user1') member.setMemberProperties({'age': 30, 'fullname': 'User #1 Is Cool', 'email': 'user1@anotherhost.qa'}) @@ -81,7 +91,7 @@ def test_group_properties(self): gt = getToolByName(self.portal, 'portal_groups') gd = getToolByName(self.portal, 'portal_groupdata') - self.loginAsPortalOwner() + setRoles(self.portal, TEST_USER_ID, ['Manager']) # Create a new Group gt.addGroup( @@ -185,9 +195,12 @@ def test_schema_for_mutable_property_provider(self): self.assertEqual(sheet.getProperty('addresses'), ('Here', 'There')) -class PropertySearchTest(base.TestCase): +class PropertySearchTest(unittest.TestCase): + + layer = PRODUCTS_PLONEPAS_INTEGRATION_TESTING - def afterSetUp(self): + def setUp(self): + self.portal = self.layer['portal'] self.mt = getToolByName(self.portal, 'portal_membership') self.md = getToolByName(self.portal, 'portal_memberdata') self.gt = getToolByName(self.portal, 'portal_groups') diff --git a/src/Products/PlonePAS/tests/test_role_plugin.py b/src/Products/PlonePAS/tests/test_role_plugin.py index 00ec703d..67710330 100644 --- a/src/Products/PlonePAS/tests/test_role_plugin.py +++ b/src/Products/PlonePAS/tests/test_role_plugin.py @@ -2,7 +2,6 @@ # $Id$ """Tests for Products.PlonePAS.plugins.role.GroupAwareRoleManager""" -from Products.PlonePAS.tests import base from Products.PluggableAuthService.PluggableAuthService import \ _PLUGIN_TYPE_INFO from Products.PluggableAuthService.interfaces.plugins import IGroupsPlugin @@ -13,6 +12,9 @@ makeRequestAndResponse from Products.PluginRegistry.PluginRegistry import PluginRegistry from zope.interface import implementer +from Products.PlonePAS.testing import PRODUCTS_PLONEPAS_INTEGRATION_TESTING + +import unittest @implementer(IGroupsPlugin) @@ -22,9 +24,11 @@ def getGroupsForPrincipal(self, principal, request=None): return principal._groups -class GroupAwareRoleManagerTests(base.TestCase): +class GroupAwareRoleManagerTests(unittest.TestCase): """Roles manager that takes care of goup of principal""" + layer = PRODUCTS_PLONEPAS_INTEGRATION_TESTING + def _getTargetClass(self): from Products.PlonePAS.plugins.role import GroupAwareRoleManager diff --git a/src/Products/PlonePAS/tests/test_views.py b/src/Products/PlonePAS/tests/test_views.py index d0a7f60c..e4c62ca2 100644 --- a/src/Products/PlonePAS/tests/test_views.py +++ b/src/Products/PlonePAS/tests/test_views.py @@ -1,10 +1,15 @@ # -*- encoding: utf-8 -*- -from Products.PlonePAS.tests import base +from Products.PlonePAS.testing import PRODUCTS_PLONEPAS_INTEGRATION_TESTING +import unittest -class TestPASSearchView(base.TestCase): + +class TestPASSearchView(unittest.TestCase): + + layer = PRODUCTS_PLONEPAS_INTEGRATION_TESTING def test_sort(self): + self.portal = self.layer['portal'] pas_search = self.portal.restrictedTraverse('@@pas_search') values = [{'title': u'Sociologie'}, {'title': u'Économie'}, {'title': u'anthropologie'}] diff --git a/src/Products/PlonePAS/tools/groupdata.py b/src/Products/PlonePAS/tools/groupdata.py index 24b9d82c..4da00f87 100644 --- a/src/Products/PlonePAS/tools/groupdata.py +++ b/src/Products/PlonePAS/tools/groupdata.py @@ -7,7 +7,7 @@ from Acquisition import aq_base from Acquisition import aq_inner from Acquisition import aq_parent -from App.class_init import InitializeClass +from AccessControl.class_init import InitializeClass from BTrees.OOBTree import OOBTree from OFS.PropertyManager import PropertyManager from OFS.SimpleItem import SimpleItem @@ -30,6 +30,7 @@ from zope.interface import implementer import logging +import six logger = logging.getLogger('PlonePAS') _marker = object() @@ -514,9 +515,15 @@ def canWriteProperty(self, prop_name): break # shadowed by read-only return 0 - canAddToGroup = MemberData.canAddToGroup.__func__ - canRemoveFromGroup = MemberData.canRemoveFromGroup.__func__ - canAssignRole = MemberData.canAssignRole.__func__ + if six.PY3: + canAddToGroup = MemberData.canAddToGroup + canRemoveFromGroup = MemberData.canRemoveFromGroup + canAssignRole = MemberData.canAssignRole + else: + # in PY2 this is a unbound method + canAddToGroup = MemberData.canAddToGroup.__func__ + canRemoveFromGroup = MemberData.canRemoveFromGroup.__func__ + canAssignRole = MemberData.canAssignRole.__func__ # plugin getters diff --git a/src/Products/PlonePAS/tools/groups.py b/src/Products/PlonePAS/tools/groups.py index 2e320c6c..837805af 100644 --- a/src/Products/PlonePAS/tools/groups.py +++ b/src/Products/PlonePAS/tools/groups.py @@ -5,7 +5,7 @@ from Acquisition import aq_base from Acquisition import aq_inner from Acquisition import aq_parent -from App.class_init import InitializeClass +from AccessControl.class_init import InitializeClass from OFS.SimpleItem import SimpleItem from Products.CMFCore.utils import UniqueObject from Products.CMFCore.utils import getToolByName diff --git a/src/Products/PlonePAS/tools/memberdata.py b/src/Products/PlonePAS/tools/memberdata.py index 29d2386a..68cfbb14 100644 --- a/src/Products/PlonePAS/tools/memberdata.py +++ b/src/Products/PlonePAS/tools/memberdata.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- from AccessControl import ClassSecurityInfo from AccessControl.requestmethod import postonly -from App.class_init import InitializeClass +from AccessControl.class_init import InitializeClass from Products.BTreeFolder2.BTreeFolder2 import BTreeFolder2 from Products.CMFCore.interfaces import IMember from Products.CMFCore.MemberDataTool import _marker @@ -304,7 +304,7 @@ def getProperty(self, id, default=_marker): if sheet.hasProperty(id): # Return the first one that has the property. value = sheet.getProperty(id) - if isinstance(value, six.text_type): + if six.PY2 and isinstance(value, six.text_type): # XXX Temporarily work around the fact that # property sheets blindly store and return # unicode. This is sub-optimal and should be diff --git a/src/Products/PlonePAS/tools/membership.py b/src/Products/PlonePAS/tools/membership.py index 58cd8266..4f5c2b09 100644 --- a/src/Products/PlonePAS/tools/membership.py +++ b/src/Products/PlonePAS/tools/membership.py @@ -7,7 +7,7 @@ from Acquisition import aq_get from Acquisition import aq_inner from Acquisition import aq_parent -from App.class_init import InitializeClass +from AccessControl.class_init import InitializeClass from App.special_dtml import DTMLFile from DateTime import DateTime from OFS.Image import Image @@ -32,7 +32,7 @@ from ZODB.POSException import ConflictError from plone.protect.interfaces import IDisableCSRFProtection import six -from six import StringIO +from six import BytesIO from zExceptions import BadRequest from zope import event from zope.component import getUtility @@ -762,8 +762,10 @@ def getBadMembers(self): counter = 1 for member_id in tuple(portraits.keys()): portrait = portraits[member_id] - portrait_data = str(portrait.data) - if portrait_data == '': + portrait_data = portrait.data + if six.PY2: + portrait_data = str(portrait.data) + if not portrait_data: continue if not HAS_PIL: raise RuntimeError( @@ -772,7 +774,7 @@ def getBadMembers(self): ) try: import PIL - PIL.Image.open(StringIO(portrait_data)) + PIL.Image.open(BytesIO(portrait_data)) except ConflictError: pass except: diff --git a/src/Products/PlonePAS/utils.py b/src/Products/PlonePAS/utils.py index 61af69c8..8544c0e6 100644 --- a/src/Products/PlonePAS/utils.py +++ b/src/Products/PlonePAS/utils.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- from Products.PlonePAS.config import IMAGE_SCALE_PARAMS from Products.PluggableAuthService.interfaces.plugins import IGroupsPlugin -from six import StringIO +from six import BytesIO from six.moves import urllib import six @@ -69,11 +69,11 @@ def scale_image(image_file, max_size=None, default_format=None): >>> scale_image(invalid, (50, 50)) Traceback (most recent call last): ... - IOError: cannot identify image file... + OSError: cannot identify image file... >>> scale_image(sneaky, (50, 50)) Traceback (most recent call last): ... - IOError: cannot identify image file... + OSError: cannot identify image file... Now that that's out of the way we check on our real images to make sure the format and mode are preserved, that they are scaled, and that they @@ -112,13 +112,13 @@ def scale_image(image_file, max_size=None, default_format=None): width only unless told not to (we need to reset out files before trying again though:: - >>> orig_jpg.seek(0) + >>> _ = orig_jpg.seek(0) >>> new_jpg, mimetype = scale_image(orig_jpg, (70, 100)) >>> img = Image.open(new_jpg) >>> img.size (70, 70) - >>> orig_jpg.seek(0) + >>> _ = orig_jpg.seek(0) >>> new_jpg, mimetype = scale_image(orig_jpg, (70, 50)) >>> img = Image.open(new_jpg) >>> img.size @@ -159,7 +159,7 @@ def scale_image(image_file, max_size=None, default_format=None): if original_mode == 'P' and format in ('GIF', 'PNG'): image = image.convert('P') # Save - new_file = StringIO() + new_file = BytesIO() image.save(new_file, format, quality=IMAGE_SCALE_PARAMS['quality']) new_file.seek(0) # Return the file data and the new mimetype