[Testbot] Plone 5.0 - Python 2.7 - Build # 2837 - Still failing! - 0 failure(s)

jenkins at plone.org jenkins at plone.org
Tue Jul 22 05:48:30 UTC 2014


-------------------------------------------------------------------------------
Plone 5.0 - Python 2.7 - Build # 2837 - Still Failing!
-------------------------------------------------------------------------------

http://jenkins.plone.org/job/plone-5.0-python-2.7/2837/


-------------------------------------------------------------------------------
CHANGES
-------------------------------------------------------------------------------

Repository: Products.CMFPlone
Branch: refs/heads/master
Date: 2014-07-21T15:19:16+02:00
Author: Timo Stollenwerk (tisto) <tisto at plone.org>
Commit: https://github.com/plone/Products.CMFPlone/commit/1e655fd5355e016f35a5928a2c55f8914755421d

Move maintenance control panel from plone.app.controlpanel to Products.CMFPlone.

Files changed:
A Products/CMFPlone/controlpanel/bbb/maintenance.py
A Products/CMFPlone/controlpanel/browser/maintenance.pt
A Products/CMFPlone/controlpanel/browser/maintenance.py
A Products/CMFPlone/controlpanel/tests/test_controlpanel_bbb_maintenance_adapter.py
A Products/CMFPlone/controlpanel/tests/test_controlpanel_browser_maintenance.py
M Products/CMFPlone/controlpanel/README.rst
M Products/CMFPlone/controlpanel/bbb/configure.zcml
M Products/CMFPlone/controlpanel/browser/configure.zcml
M Products/CMFPlone/interfaces/__init__.py
M Products/CMFPlone/interfaces/controlpanel.py
M Products/CMFPlone/profiles/dependencies/registry.xml

diff --git a/Products/CMFPlone/controlpanel/README.rst b/Products/CMFPlone/controlpanel/README.rst
index 68305b4..2e79a5b 100644
--- a/Products/CMFPlone/controlpanel/README.rst
+++ b/Products/CMFPlone/controlpanel/README.rst
@@ -19,6 +19,15 @@ If you want to change the settings, just change the attribute::
   >>> search_settings.enable_livesearch = False
 
 
+Maintenance Control Panel
+-------------------------
+
+  >>> from Products.CMFPlone.interfaces import IMaintenanceSchema
+  >>> maintenance_settings = registry.forInterface(IMaintenanceSchema, prefix='plone')
+
+  >>> maintenance_settings.days = 7
+
+
 Navigation Control Panel
 ------------------------
 
diff --git a/Products/CMFPlone/controlpanel/bbb/configure.zcml b/Products/CMFPlone/controlpanel/bbb/configure.zcml
index 97f01a4..6a48182 100644
--- a/Products/CMFPlone/controlpanel/bbb/configure.zcml
+++ b/Products/CMFPlone/controlpanel/bbb/configure.zcml
@@ -3,6 +3,7 @@
     xmlns:five="http://namespaces.zope.org/five"
     xmlns:browser="http://namespaces.zope.org/browser">
 
+  <adapter factory=".maintenance.MaintenanceControlPanelAdapter" />
   <adapter factory=".navigation.NavigationControlPanelAdapter" />
   <adapter factory=".search.SearchControlPanelAdapter" />
   <adapter factory=".site.SiteControlPanelAdapter" />
diff --git a/Products/CMFPlone/controlpanel/bbb/maintenance.py b/Products/CMFPlone/controlpanel/bbb/maintenance.py
new file mode 100644
index 0000000..3b8423d
--- /dev/null
+++ b/Products/CMFPlone/controlpanel/bbb/maintenance.py
@@ -0,0 +1,27 @@
+from Products.CMFPlone.interfaces import IMaintenanceSchema
+from Products.CMFCore.utils import getToolByName
+from zope.component import adapts
+from zope.component import getUtility
+from zope.interface import implements
+from plone.registry.interfaces import IRegistry
+from Products.CMFPlone.interfaces import IPloneSiteRoot
+
+
+class MaintenanceControlPanelAdapter(object):
+
+    adapts(IPloneSiteRoot)
+    implements(IMaintenanceSchema)
+
+    def __init__(self, context):
+        self.context = context
+        registry = getUtility(IRegistry)
+        self.maintenance_settings = registry.forInterface(
+            IMaintenanceSchema, prefix="plone")
+
+    def get_days(self):
+        return self.maintenance_settings.days
+
+    def set_days(self, value):
+        self.maintenance_settings.days = value
+
+    days = property(get_days, set_days)
diff --git a/Products/CMFPlone/controlpanel/browser/configure.zcml b/Products/CMFPlone/controlpanel/browser/configure.zcml
index a14bbca..cf67166 100644
--- a/Products/CMFPlone/controlpanel/browser/configure.zcml
+++ b/Products/CMFPlone/controlpanel/browser/configure.zcml
@@ -3,6 +3,14 @@
     xmlns:five="http://namespaces.zope.org/five"
     xmlns:browser="http://namespaces.zope.org/browser">
 
+  <!-- Maintenance Control Panel -->
+  <browser:page
+    name="maintenance-controlpanel"
+    for="Products.CMFPlone.interfaces.IPloneSiteRoot"
+    class=".maintenance.MaintenanceControlPanel"
+    permission="cmf.ManagePortal"
+    />
+
   <!-- Navigation Control Panel -->
   <browser:page
     name="navigation-controlpanel"
diff --git a/Products/CMFPlone/controlpanel/browser/maintenance.pt b/Products/CMFPlone/controlpanel/browser/maintenance.pt
new file mode 100644
index 0000000..152e16b
--- /dev/null
+++ b/Products/CMFPlone/controlpanel/browser/maintenance.pt
@@ -0,0 +1,178 @@
+<html xmlns="http://www.w3.org/1999/xhtml"
+      xmlns:metal="http://xml.zope.org/namespaces/metal"
+      xmlns:tal="http://xml.zope.org/namespaces/tal"
+      xmlns:i18n="http://xml.zope.org/namespaces/i18n"
+      xml:lang="en" lang="en"
+      metal:use-macro="context/prefs_main_template/macros/master"
+      i18n:domain="plone">
+
+<body>
+
+<metal:main fill-slot="prefs_configlet_main">
+
+    <metal:form define-macro="form" tal:condition="view/available">
+
+         <metal:block define-macro="header">
+
+             <dl tal:define="status view/status"
+                  tal:condition="status"
+                  class="portalMessage info">
+                 <dt i18n:translate="">
+                     Info
+                 </dt>
+                 <dd tal:content="view/status" />
+             </dl>
+
+         </metal:block>
+
+         <a href=""
+            id="setup-link"
+            tal:attributes="href string:$portal_url/plone_control_panel"
+            i18n:translate="">
+             Site Setup
+         </a>
+
+         <h1 class="documentFirstHeading"
+             i18n:translate=""
+             tal:condition="view/label"
+             tal:content="view/label"
+             metal:define-slot="heading">
+             Do something
+         </h1>
+
+         <div class="documentDescription" i18n:translate=""
+            tal:condition="view/description"
+            tal:content="view/description">
+             Description
+         </div>
+
+        <div id="content-core">
+
+            <form action="."
+                  tal:attributes="action request/URL"
+                  method="post"
+                  class="edit-form"
+                  enctype="multipart/form-data">
+
+                <fieldset>
+                    <legend i18n:translate="heading_zope_server">
+                        Zope Server
+                    </legend>
+
+                    <p i18n:translate="text_zope_server_uptime">
+                        Zope Server uptime: <span i18n:name="time" tal:replace="view/processTime" />
+                    </p>
+
+                    <div id="actionsView" class="formControls">
+                        <span class="actionButtons">
+                            <input type="submit"
+                                   id="form.buttons.shutdown"
+                                   name="form.buttons.shutdown"
+                                   value="Shut down"
+                                   i18n:attributes="value"
+                                   class="standalone" />
+
+                            <input tal:condition="view/isRestartable"
+                                   type="submit"
+                                   id="form.buttons.restart"
+                                   name="form.buttons.restart"
+                                   value="Restart"
+                                   i18n:attributes="value"
+                                   class="standalone" />
+
+                        </span>
+                    </div>
+
+                </fieldset>
+
+                <input tal:replace="structure context/@@authenticator/authenticator" />
+
+            </form>
+
+            <form action="."
+                  metal:define-macro="master"
+                  tal:attributes="action request/URL"
+                  method="post"
+                  class="edit-form"
+                  enctype="multipart/form-data"
+                  id="zc.page.browser_form">
+
+                <div metal:define-slot="extra_info" tal:replace="nothing">
+                </div>
+
+                <fieldset>
+                    <legend tal:define="form_name view/form_name|nothing"
+                            tal:condition="form_name"
+                            tal:content="form_name">Form name</legend>
+
+                    <p i18n:translate="text_zope_database_size">
+                        <strong>Current database size:</strong> <span i18n:name="size" tal:replace="view/dbSize" />
+                    </p>
+
+                    <metal:define define-macro="widget_rendering">
+                        <tal:widgets repeat="widget view/widgets/values">
+                            <metal:field-slot define-slot="field">
+                                <metal:field define-macro="field">
+                                    <tal:widget tal:replace="structure widget/@@ploneform-render-widget"/>
+                                </metal:field>
+                            </metal:field-slot>
+                        </tal:widgets>
+                    </metal:define>
+
+                    <metal:block define-slot="above_buttons" />
+
+                    <div class="visualClear"><!-- --></div>
+
+                    <div id="actionsView" class="formControls">
+                        <span class="actionButtons">
+                            <input type="submit"
+                                   id="form.buttons.pack"
+                                   name="form.buttons.pack"
+                                   value="Pack"
+                                   i18n:attributes="value"
+                                   class="standalone" />
+                        </span>
+                    </div>
+
+                </fieldset>
+
+                <input tal:replace="structure context/@@authenticator/authenticator" />
+
+            </form>
+
+            <script type="text/javascript"
+                tal:define="extra_script view/extra_script | nothing"
+                tal:condition="extra_script"
+                tal:content="structure extra_script">
+            </script>
+        </div>
+
+    </metal:form>
+
+    <metal:block tal:condition="not: view/available">
+         <h1 class="documentFirstHeading"
+             i18n:translate=""
+             tal:condition="view/label"
+             tal:content="view/label">
+             Do something
+         </h1>
+
+         <div class="documentDescription" i18n:translate="text_not_allowed_manage_server"
+            tal:condition="view/description">
+             You are not allowed to manage the Zope server.
+         </div>
+
+         <div id="content-core">
+             <a href=""
+                class="link-parent"
+                tal:attributes="href string:$portal_url/plone_control_panel"
+                i18n:translate="label_up_to_plone_setup">
+                 Up to Site Setup
+             </a>
+         </div>
+    </metal:block>
+
+
+</metal:main>
+</body>
+</html>
diff --git a/Products/CMFPlone/controlpanel/browser/maintenance.py b/Products/CMFPlone/controlpanel/browser/maintenance.py
new file mode 100644
index 0000000..223f610
--- /dev/null
+++ b/Products/CMFPlone/controlpanel/browser/maintenance.py
@@ -0,0 +1,123 @@
+from z3c.form import button
+import os
+from cgi import escape
+
+from plone.app.form.validators import null_validator
+from z3c.form import form
+
+from AccessControl import getSecurityManager
+from AccessControl.Permissions import view_management_screens
+from Acquisition import aq_inner
+from Products.CMFCore.utils import getToolByName
+from Products.CMFPlone import PloneMessageFactory as _
+from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
+
+from plone.protect import CheckAuthenticator
+
+from plone.autoform.form import AutoExtensibleForm
+
+from Products.CMFPlone.interfaces import IMaintenanceSchema
+
+
+class MaintenanceControlPanel(AutoExtensibleForm, form.EditForm):
+    """A simple form to pack the databases."""
+
+    schema = IMaintenanceSchema
+    id = "maintenance-control-panel"
+    label = _(u'Maintenance')
+    description = _(u"Zope server and site maintenance options.")
+    form_name = _(u'Zope Database Packing')
+    control_panel_view = "maintenance-controlpanel"
+    template = ViewPageTemplateFile('maintenance.pt')
+
+    @button.buttonAndHandler(_(u'Pack database now'), name='pack')
+    def handle_edit_action(self, action):
+        data, errors = self.extractData()
+        if errors:
+            self.status = self.formErrorsMessage
+            return
+        CheckAuthenticator(self.request)
+        if not self.available():
+            self.status = _(
+                u'text_not_allowed_manage_server',
+                default=u'You are not allowed to manage the Zope server.'
+            )
+            return
+
+        value = data.get('days', None)
+        # skip the actual pack method in tests
+        if value is not None and isinstance(value, int) and value >= 0:
+            context = aq_inner(self.context)
+            cpanel = context.unrestrictedTraverse('/Control_Panel')
+            cpanel.manage_pack(days=value, REQUEST=None)
+        self.status = _(u'Packed the database.')
+
+    #@form.action(_(u'Shut down'), validator=null_validator, name=u'shutdown')
+
+    @button.buttonAndHandler(_(u'Shut down'), name='shutdown')
+    def handle_shutdown_action(self, action):
+        CheckAuthenticator(self.request)
+        if not self.available():
+            self.status = _(
+                u'text_not_allowed_manage_server',
+                default=u'You are not allowed to manage the Zope server.'
+            )
+            return
+        context = aq_inner(self.context)
+        cpanel = context.unrestrictedTraverse('/Control_Panel')
+        result = cpanel.manage_shutdown()
+        return result
+
+    #@form.action(_(u'Restart'), validator=null_validator)
+
+    @button.buttonAndHandler(_(u'Restart'), name='restart')
+    def handle_restart_action(self, action):
+        CheckAuthenticator(self.request)
+        if not self.available():
+            self.status = _(
+                u'text_not_allowed_manage_server',
+                default=u'You are not allowed to manage the Zope server.'
+            )
+            return
+        context = aq_inner(self.context)
+        cpanel = context.unrestrictedTraverse('/Control_Panel')
+        url = self.request.get('URL')
+        cpanel.manage_restart(url)
+        return """<html>
+        <head><meta HTTP-EQUIV=REFRESH CONTENT="30; URL=%s">
+        </head>
+        <body>
+            Zope is restarting. This page will refresh in 30 seconds...
+        </body>
+        </html>
+        """ % escape(url, 1)
+
+    def available(self):
+        root = aq_inner(self.context).getPhysicalRoot()
+        sm = getSecurityManager()
+        return sm.checkPermission(view_management_screens, root)
+
+    def isRestartable(self):
+        if 'ZMANAGED' in os.environ:
+            return True
+        return False
+
+    def isDevelopmentMode(self):
+        qi = getToolByName(self.context, 'portal_quickinstaller')
+        return qi.isDevelopmentMode()
+
+    def coreVersions(self):
+        mt = getToolByName(self.context, 'portal_migration')
+        versions = mt.coreVersions()
+        versions['Instance'] = versions['Plone Instance']
+        return versions
+
+    def processTime(self):
+        context = aq_inner(self.context)
+        cpanel = context.unrestrictedTraverse('/Control_Panel')
+        return cpanel.process_time()
+
+    def dbSize(self):
+        context = aq_inner(self.context)
+        cpanel = context.unrestrictedTraverse('/Control_Panel')
+        return cpanel.db_size()
diff --git a/Products/CMFPlone/controlpanel/tests/test_controlpanel_bbb_maintenance_adapter.py b/Products/CMFPlone/controlpanel/tests/test_controlpanel_bbb_maintenance_adapter.py
new file mode 100644
index 0000000..1cb7089
--- /dev/null
+++ b/Products/CMFPlone/controlpanel/tests/test_controlpanel_bbb_maintenance_adapter.py
@@ -0,0 +1,51 @@
+import unittest
+from plone.app.testing import setRoles
+from Products.CMFPlone.interfaces import IMaintenanceSchema
+from zope.component import getAdapter
+from plone.app.testing import TEST_USER_ID
+from Products.CMFCore.utils import getToolByName
+from plone.registry.interfaces import IRegistry
+from zope.component import getUtility
+
+from Products.CMFPlone.testing import \
+    PRODUCTS_CMFPLONE_INTEGRATION_TESTING
+
+
+class MaintenanceControlPanelAdapterTest(unittest.TestCase):
+
+    layer = PRODUCTS_CMFPLONE_INTEGRATION_TESTING
+
+    def setUp(self):
+        self.portal = self.layer['portal']
+        self.request = self.layer['request']
+        setRoles(self.portal, TEST_USER_ID, ['Manager'])
+        registry = getUtility(IRegistry)
+        self.maintenance_settings = registry.forInterface(
+            IMaintenanceSchema, prefix="plone")
+
+    def test_adapter_lookup(self):
+        self.assertTrue(
+            getAdapter(self.portal, IMaintenanceSchema)
+        )
+
+    def test_get_days(self):
+        self.assertEqual(
+            getAdapter(self.portal, IMaintenanceSchema).days,
+            7
+        )
+        self.maintenance_settings.days = 4
+        self.assertEquals(
+            getAdapter(self.portal, IMaintenanceSchema).days,
+            4
+        )
+
+    def test_set_days(self):
+        self.assertEquals(
+            self.maintenance_settings.days,
+            7
+        )
+        getAdapter(self.portal, IMaintenanceSchema).days = 4
+        self.assertEquals(
+            self.maintenance_settings.days,
+            4
+        )
diff --git a/Products/CMFPlone/controlpanel/tests/test_controlpanel_browser_maintenance.py b/Products/CMFPlone/controlpanel/tests/test_controlpanel_browser_maintenance.py
new file mode 100644
index 0000000..da6f99b
--- /dev/null
+++ b/Products/CMFPlone/controlpanel/tests/test_controlpanel_browser_maintenance.py
@@ -0,0 +1,81 @@
+# -*- coding: utf-8 -*-
+from zope.component import getUtility
+from plone.registry.interfaces import IRegistry
+from plone.app.testing import TEST_USER_PASSWORD
+from plone.app.testing import TEST_USER_NAME
+from plone.app.testing import SITE_OWNER_PASSWORD
+from plone.app.testing import SITE_OWNER_NAME
+from plone.testing.z2 import Browser
+from plone.registry import Registry
+
+import unittest2 as unittest
+
+from zope.component import getMultiAdapter
+
+from Products.CMFCore.utils import getToolByName
+
+from plone.app.testing import TEST_USER_ID, setRoles
+
+from Products.CMFPlone.testing import \
+    PRODUCTS_CMFPLONE_FUNCTIONAL_TESTING
+
+
+class MaintenanceControlPanelFunctionalTest(unittest.TestCase):
+    """Test that changes in the maintenance control panel are actually
+    stored in the registry.
+    """
+
+    layer = PRODUCTS_CMFPLONE_FUNCTIONAL_TESTING
+
+    def setUp(self):
+        self.app = self.layer['app']
+        self.request = self.layer['request']
+        self.portal = self.layer['portal']
+        self.portal_url = self.portal.absolute_url()
+        self.browser = Browser(self.app)
+        self.browser.handleErrors = False
+        self.browser.addHeader('Authorization',
+                'Basic %s:%s' % (SITE_OWNER_NAME, SITE_OWNER_PASSWORD,)
+            )
+        self.site_administrator_browser = Browser(self.app)
+        self.site_administrator_browser.handleErrors = False
+        self.site_administrator_browser.addHeader('Authorization',
+                'Basic %s:%s' % (TEST_USER_NAME, TEST_USER_PASSWORD,)
+            )
+
+    def test_maintenance_control_panel_link(self):
+        self.browser.open(
+            "%s/plone_control_panel" % self.portal_url)
+        self.browser.getLink('Editing').click()
+
+    def test_maintenance_control_panel_backlink(self):
+        self.browser.open(
+            "%s/@@maintenance-controlpanel" % self.portal_url)
+        self.assertTrue("Plone Configuration" in self.browser.contents)
+
+    def test_maintenance_control_panel_sidebar(self):
+        self.browser.open(
+            "%s/@@maintenance-controlpanel" % self.portal_url)
+        self.browser.getLink('Site Setup').click()
+        self.assertEqual(
+            self.browser.url,
+            'http://nohost/plone/@@overview-controlpanel')
+
+    def test_maintenance_control_panel_raises_unauthorized(self):
+        self.site_administrator_browser.open(
+            self.portal_url + '/@@maintenance-controlpanel')
+        self.assertTrue(
+            'You are not allowed to manage the Zope server.'
+            in self.site_administrator_browser.contents)
+
+    @unittest.skip('Not working yet.')
+    def test_maintenance_pack_database(self):
+        """While we cannot test the actual packaging during tests, we can skip
+           the actual manage_pack method by providing a negative value for
+           days.
+        """
+        self.browser.open(self.portal_url + '/@@maintenance-controlpanel')
+        self.browser.getControl(name='form.widgets.days').value = '-1'
+        self.browser.getControl(name="form.buttons.pack").click()
+        self.assertTrue(self.browser.url.endswith('maintenance-controlpanel'))
+        self.assertTrue('Packed the database.' in self.browser.contents)
diff --git a/Products/CMFPlone/interfaces/__init__.py b/Products/CMFPlone/interfaces/__init__.py
index c699328..3837f1b 100644
--- a/Products/CMFPlone/interfaces/__init__.py
+++ b/Products/CMFPlone/interfaces/__init__.py
@@ -5,6 +5,7 @@
 from basetool import IPloneCatalogTool
 from controlpanel import IControlPanel
 from controlpanel import IDateAndTimeSchema
+from controlpanel import IMaintenanceSchema
 from controlpanel import INavigationSchema
 from controlpanel import ISearchSchema
 from controlpanel import ISiteSchema
diff --git a/Products/CMFPlone/interfaces/controlpanel.py b/Products/CMFPlone/interfaces/controlpanel.py
index 5f8c475..1785003 100644
--- a/Products/CMFPlone/interfaces/controlpanel.py
+++ b/Products/CMFPlone/interfaces/controlpanel.py
@@ -30,6 +30,22 @@ def enumConfiglets(group=None):
             calling .getAction() on each of them """
 
 
+class IMaintenanceSchema(Interface):
+
+    days = schema.Int(
+        title=_(u"Days of object history to keep after packing"),
+        description=_(
+            u"You should pack your database regularly. This number "
+            u"indicates how many days of undo history you want to "
+            u"keep. It is unrelated to versioning, so even if you "
+            u"pack the database, the history of the content changes "
+            u"will be kept. Recommended value is 7 days."
+        ),
+        default=7,
+        required=True
+    )
+
+
 class INavigationSchema(Interface):
 
     generate_tabs = schema.Bool(
diff --git a/Products/CMFPlone/profiles/dependencies/registry.xml b/Products/CMFPlone/profiles/dependencies/registry.xml
index bea2abe..ae1df50 100644
--- a/Products/CMFPlone/profiles/dependencies/registry.xml
+++ b/Products/CMFPlone/profiles/dependencies/registry.xml
@@ -1,5 +1,7 @@
 <?xml version="1.0"?>
 <registry>
+  <records interface="Products.CMFPlone.interfaces.IMaintenanceSchema"
+           prefix="plone" />
   <records interface="Products.CMFPlone.interfaces.INavigationSchema"
            prefix="plone" />
   <records interface="Products.CMFPlone.interfaces.ISearchSchema"




-------------------------------------------------------------------------------
-------------- next part --------------
A non-text attachment was scrubbed...
Name: CHANGES.log
Type: application/octet-stream
Size: 23278 bytes
Desc: not available
URL: <http://lists.plone.org/pipermail/plone-testbot/attachments/20140722/a77a6e37/attachment-0002.obj>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: build.log
Type: application/octet-stream
Size: 115416 bytes
Desc: not available
URL: <http://lists.plone.org/pipermail/plone-testbot/attachments/20140722/a77a6e37/attachment-0003.obj>


More information about the Testbot mailing list