[Checkins] SVN: grokui.admin/trunk/ Merged trunk with branch fancy-layout
Souheil CHELFOUH
souheil at chelfouh.com
Fri Jan 29 10:59:55 EST 2010
Log message for revision 108639:
Merged trunk with branch fancy-layout
Changed:
_U grokui.admin/trunk/
U grokui.admin/trunk/CHANGES.txt
U grokui.admin/trunk/buildout.cfg
U grokui.admin/trunk/setup.py
U grokui.admin/trunk/src/grokui/admin/__init__.py
A grokui.admin/trunk/src/grokui/admin/applications.py
U grokui.admin/trunk/src/grokui/admin/configure.zcml
U grokui.admin/trunk/src/grokui/admin/ftesting.zcml
D grokui.admin/trunk/src/grokui/admin/messages.py
A grokui.admin/trunk/src/grokui/admin/providers.py
A grokui.admin/trunk/src/grokui/admin/representation.py
U grokui.admin/trunk/src/grokui/admin/security.py
A grokui.admin/trunk/src/grokui/admin/server.py
D grokui.admin/trunk/src/grokui/admin/static/
A grokui.admin/trunk/src/grokui/admin/templates/
U grokui.admin/trunk/src/grokui/admin/tests/apps.py
U grokui.admin/trunk/src/grokui/admin/tests/brokenobjs.py
U grokui.admin/trunk/src/grokui/admin/tests/events.py
U grokui.admin/trunk/src/grokui/admin/tests/infoviews.py
D grokui.admin/trunk/src/grokui/admin/tests/macros.py
U grokui.admin/trunk/src/grokui/admin/tests/packdatabase.py
U grokui.admin/trunk/src/grokui/admin/tests/security.py
U grokui.admin/trunk/src/grokui/admin/tests/server.py
U grokui.admin/trunk/src/grokui/admin/tests/test_grokadmin.py
U grokui.admin/trunk/src/grokui/admin/tests/test_grokadmin_functional.py
U grokui.admin/trunk/src/grokui/admin/utilities.py
U grokui.admin/trunk/src/grokui/admin/view.py
A grokui.admin/trunk/versions.cfg
-=-
Property changes on: grokui.admin/trunk
___________________________________________________________________
Deleted: svn:mergeinfo
-
Modified: grokui.admin/trunk/CHANGES.txt
===================================================================
--- grokui.admin/trunk/CHANGES.txt 2010-01-29 15:55:39 UTC (rev 108638)
+++ grokui.admin/trunk/CHANGES.txt 2010-01-29 15:59:54 UTC (rev 108639)
@@ -4,7 +4,9 @@
0.6 (unreleased)
================
+* Reflect the changes in grokcore.view 1.12 where View and CodeView become a single View again.
+
0.5 (2009-09-15)
================
Modified: grokui.admin/trunk/buildout.cfg
===================================================================
--- grokui.admin/trunk/buildout.cfg 2010-01-29 15:55:39 UTC (rev 108638)
+++ grokui.admin/trunk/buildout.cfg 2010-01-29 15:59:54 UTC (rev 108639)
@@ -1,23 +1,30 @@
[buildout]
develop = .
-parts = test data zopectl app
+parts = svn test data zopectl app
find-links = http://download.zope.org/distribution/
-extends = http://grok.zope.org/releaseinfo/grok-1.1a2.cfg
+extends = http://svn.zope.org/*checkout*/groktoolkit/trunk/grok.cfg
versions = versions
[data]
recipe = zc.recipe.filestorage
+[svn]
+recipe = infrae.subversion
+as_eggs = True
+urls = svn://svn.zope.org/repos/main/grokui.base/trunk grokui.base
+
[versions]
grokui.admin =
+grokui.base =
[app]
recipe = zc.zope3recipes>=0.5.3:application
eggs = grokui.admin
site.zcml =<configure xmlns='http://namespaces.zope.org/zope'
xmlns:meta="http://namespaces.zope.org/meta"
- i18n_domain="zope"
- >
+ i18n_domain="zope">
+
+ <include package="grokui.base" />
<include package="grokui.admin" />
<include package="zope.app.twisted" />
@@ -40,11 +47,13 @@
password="grok"
/>
+ <!-- Replace the following directive if you don't want
+ public access -->
<grant permission="zope.View"
- principal="zope.Anybody" />
+ principal="zope.Everybody" />
<grant permission="zope.app.dublincore.view"
- principal="zope.Anybody" />
+ principal="zope.Everybody" />
<role id="zope.Manager" title="Site Manager" />
<role id="zope.Member" title="Site Member" />
@@ -61,5 +70,5 @@
[test]
recipe = zc.recipe.testrunner
-eggs = grokui.admin [test,]
+eggs = grokui.admin [test]
defaults = ['--tests-pattern', '^f?tests$', '-v']
Modified: grokui.admin/trunk/setup.py
===================================================================
--- grokui.admin/trunk/setup.py 2010-01-29 15:55:39 UTC (rev 108638)
+++ grokui.admin/trunk/setup.py 2010-01-29 15:59:54 UTC (rev 108639)
@@ -2,10 +2,11 @@
from setuptools import setup, find_packages
tests_require = [
- 'z3c.testsetup',
+ 'zope.app.testing',
'zope.testbrowser',
'zope.testing',
- 'zope.app.testing',
+ 'zope.security',
+ 'zope.securitypolicy'
]
def read(*rnames):
@@ -19,7 +20,6 @@
'\n\n' +
read('CHANGES.txt')
),
- # Get strings from http://www.python.org/pypi?%3Aaction=list_classifiers
classifiers=[
'Development Status :: 3 - Alpha',
'Environment :: Web Environment',
@@ -39,21 +39,27 @@
packages=find_packages('src'),
include_package_data=True,
zip_safe=False,
- namespace_packages = ['grokui'],
- install_requires=['setuptools',
- 'ZODB3',
- 'grok',
- 'grokcore.view',
- 'martian',
- 'z3c.flashmessage',
- 'zope.app.applicationcontrol',
- 'zope.app.appsetup',
- 'zope.component',
- 'zope.exceptions',
- 'zope.interface',
- 'zope.schema',
- 'zope.security',
- ],
+ namespace_packages=['grokui'],
+ install_requires=[
+ 'ZODB3',
+ 'grok',
+ 'grokui.base',
+ 'setuptools',
+ 'z3c.flashmessage',
+ 'zope.applicationcontrol',
+ 'zope.component',
+ 'zope.configuration',
+ 'zope.contentprovider',
+ 'zope.exceptions',
+ 'zope.i18nmessageid',
+ 'zope.interface',
+ 'zope.location',
+ 'zope.login',
+ 'zope.schema',
+ 'zope.site',
+ 'zope.size',
+ 'zope.traversing',
+ ],
tests_require = tests_require,
extras_require = dict(test=tests_require),
entry_points="""
Modified: grokui.admin/trunk/src/grokui/admin/__init__.py
===================================================================
--- grokui.admin/trunk/src/grokui/admin/__init__.py 2010-01-29 15:55:39 UTC (rev 108638)
+++ grokui.admin/trunk/src/grokui/admin/__init__.py 2010-01-29 15:59:54 UTC (rev 108639)
@@ -12,4 +12,3 @@
#
##############################################################################
# a package
-
Copied: grokui.admin/trunk/src/grokui/admin/applications.py (from rev 108638, grokui.admin/branches/fancy-layout/src/grokui/admin/applications.py)
===================================================================
--- grokui.admin/trunk/src/grokui/admin/applications.py (rev 0)
+++ grokui.admin/trunk/src/grokui/admin/applications.py 2010-01-29 15:59:54 UTC (rev 108639)
@@ -0,0 +1,90 @@
+# -*- coding: utf-8 -*-
+
+import grok
+from ZODB.broken import Broken
+from grokui.admin import representation
+from zope.traversing.browser import absoluteURL
+from zope.contentprovider.interfaces import IContentProvider
+from zope.component import getMultiAdapter, getAllUtilitiesRegisteredFor
+from grokui.base.layout import GrokUIView
+from grokui.base.namespace import GrokUILayer
+
+grok.templatedir("templates")
+
+
+class InstalledApplication(object):
+ grok.implements(representation.IInstalledApplication)
+
+ def __init__(self, obj, request):
+ self.__name__ = obj.__name__
+ self.url = absoluteURL(obj, request)
+ self.description = obj.__doc__
+ self.__parent__ = obj.__parent__
+ self.classname = ".".join((obj.__class__.__module__,
+ obj.__class__.__name__))
+
+ def __cmp__(self, other):
+ return cmp(self.__name__, other.__name__)
+
+
+class BrokenApplication(object):
+ grok.implements(representation.IApplicationRepresentation)
+
+ def __init__(self, name, obj):
+ self.__name__ = name
+ self.classname = ".".join((obj.__class__.__module__,
+ obj.__class__.__name__))
+
+ def __cmp__(self, other):
+ return cmp(self.__name__, other.__name__)
+
+
+class InstallableApplication(object):
+ grok.implements(representation.IInstallableApplication)
+
+ def __init__(self, klass):
+ self.__name__ = klass.__name__
+ self.classname = ".".join((klass.__module__, klass.__name__))
+ self.description = unicode(klass.__doc__)
+
+
+class ApplicationInfo(grok.View):
+ grok.name('info')
+ grok.context(representation.IApplicationRepresentation)
+
+ def render(self):
+ info = getMultiAdapter(
+ (self.context, self.request, self),
+ IContentProvider,
+ name='grokui_admin_appinfo')
+ info.update()
+ return info.render()
+
+
+class Applications(GrokUIView):
+ """View for application management.
+ """
+ grok.layer(GrokUILayer)
+ grok.name('applications')
+ grok.title('Applications')
+ grok.require('grok.ManageApplications')
+
+ def update(self):
+ # Available apps...
+ apps = getAllUtilitiesRegisteredFor(grok.interfaces.IApplication)
+ self.installable = (InstallableApplication(x) for x in apps)
+
+ # Installed apps...
+ self.broken = []
+ self.installed = []
+
+ for name, app in self.context.root.items():
+ is_broken = isinstance(app, Broken)
+ if is_broken:
+ self.broken.append(BrokenApplication(name, app))
+ else:
+ self.installed.append(InstalledApplication(app, self.request))
+
+ self.broken.sort()
+ self.installed.sort()
+ self.has_apps = bool(len(self.installed) + len(self.broken))
Modified: grokui.admin/trunk/src/grokui/admin/configure.zcml
===================================================================
--- grokui.admin/trunk/src/grokui/admin/configure.zcml 2010-01-29 15:55:39 UTC (rev 108638)
+++ grokui.admin/trunk/src/grokui/admin/configure.zcml 2010-01-29 15:59:54 UTC (rev 108639)
@@ -1,5 +1,7 @@
<configure xmlns="http://namespaces.zope.org/zope"
xmlns:grok="http://namespaces.zope.org/grok">
<include package="grok" />
+ <include package="zope.applicationcontrol" />
+ <include package="zope.login" />
<grok:grok package="." />
</configure>
Modified: grokui.admin/trunk/src/grokui/admin/ftesting.zcml
===================================================================
--- grokui.admin/trunk/src/grokui/admin/ftesting.zcml 2010-01-29 15:55:39 UTC (rev 108638)
+++ grokui.admin/trunk/src/grokui/admin/ftesting.zcml 2010-01-29 15:59:54 UTC (rev 108639)
@@ -2,9 +2,9 @@
xmlns="http://namespaces.zope.org/zope"
xmlns:grok="http://namespaces.zope.org/grok"
i18n_domain="grok"
- package="grokui.admin"
- >
+ package="grokui.admin">
+ <include package="grokui.base" />
<include package="grokui.admin" />
<grok:grok package="grokui.admin.tests" />
Deleted: grokui.admin/trunk/src/grokui/admin/messages.py
===================================================================
--- grokui.admin/trunk/src/grokui/admin/messages.py 2010-01-29 15:55:39 UTC (rev 108638)
+++ grokui.admin/trunk/src/grokui/admin/messages.py 2010-01-29 15:59:54 UTC (rev 108639)
@@ -1,31 +0,0 @@
-# -*- coding: latin-1 -*-
-# Copyright (c) 2007 gocept gmbh & co. kg
-# See also LICENSE.txt
-# $Id$
-"""Support for flash-messages in the grok admin UI."""
-
-import zope.interface
-import zope.component
-
-import grok
-
-import z3c.flashmessage.interfaces
-import z3c.flashmessage.sources
-import z3c.flashmessage.receiver
-
-
-class Messages(grok.View):
-
- grok.context(zope.interface.Interface)
-
- @property
- def messages(self):
- receiver = zope.component.getUtility(
- z3c.flashmessage.interfaces.IMessageReceiver)
- return receiver.receive()
-
-
-
-grok.global_utility(z3c.flashmessage.sources.SessionMessageSource,
- name='session')
-grok.global_utility(z3c.flashmessage.receiver.GlobalMessageReceiver)
Copied: grokui.admin/trunk/src/grokui/admin/providers.py (from rev 108638, grokui.admin/branches/fancy-layout/src/grokui/admin/providers.py)
===================================================================
--- grokui.admin/trunk/src/grokui/admin/providers.py (rev 0)
+++ grokui.admin/trunk/src/grokui/admin/providers.py 2010-01-29 15:59:54 UTC (rev 108639)
@@ -0,0 +1,9 @@
+# -*- coding: utf-8 -*-
+
+import grok
+from grokui.admin import representation
+
+
+class ApplicationInformation(grok.ViewletManager):
+ grok.name('grokui_admin_appinfo')
+ grok.context(representation.IApplicationRepresentation)
Copied: grokui.admin/trunk/src/grokui/admin/representation.py (from rev 108638, grokui.admin/branches/fancy-layout/src/grokui/admin/representation.py)
===================================================================
--- grokui.admin/trunk/src/grokui/admin/representation.py (rev 0)
+++ grokui.admin/trunk/src/grokui/admin/representation.py 2010-01-29 15:59:54 UTC (rev 108639)
@@ -0,0 +1,42 @@
+# -*- coding: utf-8 -*-
+
+from zope import schema
+from zope.location import ILocation
+from zope.interface import Interface
+from zope.configuration.fields import PythonIdentifier
+from zope.contentprovider.interfaces import IContentProvider
+
+
+class IApplicationRepresentation(Interface):
+ """Defines an Grok application
+ """
+ __name__ = schema.TextLine(
+ title = u"Name",
+ required = True)
+
+ classname = PythonIdentifier(
+ title = u"Dotted name of the Application class",
+ required = True)
+
+ description = schema.Text(
+ title = u"Description of the Application",
+ default = u"",
+ required = False)
+
+
+class IInstallableApplication(IApplicationRepresentation):
+ """Defines an installable application.
+ """
+
+
+class IInstalledApplication(IApplicationRepresentation, ILocation):
+ """Defines an application that is installed in our system.
+ """
+ url = schema.URI(
+ title = u"Absolute URL of the application",
+ required = True)
+
+
+class IApplicationInformation(IContentProvider):
+ """Marker interface for the Application information content provider.
+ """
Modified: grokui.admin/trunk/src/grokui/admin/security.py
===================================================================
--- grokui.admin/trunk/src/grokui/admin/security.py 2010-01-29 15:55:39 UTC (rev 108638)
+++ grokui.admin/trunk/src/grokui/admin/security.py 2010-01-29 15:59:54 UTC (rev 108639)
@@ -10,23 +10,19 @@
from persistent import Persistent
from zope.component import adapter, provideHandler
-from zope.site.interfaces import IRootFolder
-from zope.app.appsetup.interfaces import IDatabaseOpenedWithRootEvent
from grokui.admin.interfaces import ISecurityNotifier
from grokui.admin.utilities import getVersion, TimeoutableHTTPHandler
+from grokui.base import Header, Messages, IGrokUIRealm
+MSG_DISABLED = u'Security notifications are disabled.'
-class SecurityScreen(grok.ViewletManager):
- """A viewlet manager that keeps security related notifications.
- """
- grok.name('grokadmin_security')
- grok.context(IRootFolder)
-
class SecurityNotificationViewlet(grok.Viewlet):
"""Viewlet displaying notifications from a local `SecurityNotifier`.
"""
- grok.context(IRootFolder)
+ grok.order(40)
+ grok.context(IGrokUIRealm)
+ grok.viewletmanager(Messages)
@property
def security_notifier(self):
@@ -40,7 +36,11 @@
return site_manager.queryUtility(ISecurityNotifier, default=None)
def render(self):
- return self.security_notifier.getNotification()
+ notifier = self.security_notifier
+ if notifier is None:
+ return u""
+ return '''<div class="grokui-security message">%s</div>''' % (
+ self.security_notifier.getNotification())
class SecurityNotifier(Persistent):
@@ -49,11 +49,9 @@
It can be placed in a site to store notification dates and other
data persistently.
"""
-
grok.implements(ISecurityNotifier)
VERSION = 1 # for possibly updates/downgrades
- MSG_DISABLED = u'Security notifications are disabled.'
DEFAULT_URL = 'http://grok.zope.org/releaseinfo/'
lookup_url = DEFAULT_URL
@@ -82,7 +80,7 @@
"""Get the current security notification.
"""
if self.enabled is False:
- return self.MSG_DISABLED
+ return MSG_DISABLED
self.updateMessage()
return self._message
@@ -127,7 +125,7 @@
except:
# An unexpected problem occured...
pass
- if self._message == self.MSG_DISABLED:
+ if self._message == MSG_DISABLED:
self._message = u''
self.last_lookup = time.time()
return
@@ -146,38 +144,3 @@
"""
self.last_display = time.time()
return
-
-
-def setupSecurityNotification(site):
- """Setup a SecurityNotifier as persistent utility.
-
- The utility is installed as a local and persistent utility. It is
- local to `site` and installed under the name
- ``grokadmin_security`` in the site manager of `site`.
-
- It can be retrieved with a call like::
-
- site.getSiteManager().getUtiliy(ISecurityNotifier)
-
- See also ``security.py`` in ``tests``.
- """
- site_manager = site.getSiteManager()
- if 'grokadmin_security' not in site_manager:
- site_manager['grokadmin_security'] = SecurityNotifier()
- utility = site_manager['grokadmin_security']
- site_manager.registerUtility(utility, ISecurityNotifier, name=u'')
- return
-
-
- at adapter(IDatabaseOpenedWithRootEvent)
-def securitySetupHandler(event):
- """Call security notification setup as soon as DB is ready.
- """
- from zope.app.appsetup.bootstrap import getInformationFromEvent
-
- db, connection, root, root_folder = getInformationFromEvent(event)
- setupSecurityNotification(root_folder)
-
-
-# ...then install the event handler:
-provideHandler(securitySetupHandler)
Copied: grokui.admin/trunk/src/grokui/admin/server.py (from rev 108638, grokui.admin/branches/fancy-layout/src/grokui/admin/server.py)
===================================================================
--- grokui.admin/trunk/src/grokui/admin/server.py (rev 0)
+++ grokui.admin/trunk/src/grokui/admin/server.py 2010-01-29 15:59:54 UTC (rev 108639)
@@ -0,0 +1,234 @@
+# -*- coding: utf-8 -*-
+
+import grok
+import z3c.flashmessage.interfaces
+
+from grokui.base.layout import GrokUIView
+from grokui.admin.interfaces import ISecurityNotifier
+from grokui.admin.utilities import getVersion
+from grokui.admin.security import SecurityNotifier
+
+from ZODB.interfaces import IDatabase
+from ZODB.FileStorage.FileStorage import FileStorageError
+
+from zope.size import byteDisplay
+from zope.applicationcontrol.interfaces import IServerControl, IRuntimeInfo
+from zope.applicationcontrol.applicationcontrol import applicationController
+from zope.component import getUtility, queryUtility, getUtilitiesFor
+from zope.i18nmessageid import MessageFactory
+
+_ = MessageFactory('grokui')
+grok.templatedir("templates")
+
+
+class Server(GrokUIView):
+ """Zope3 management screen.
+ """
+ grok.title('Server Control')
+ grok.require('grok.ManageApplications')
+
+ _fields = (
+ "ZopeVersion",
+ "PythonVersion",
+ "PythonPath",
+ "SystemPlatform",
+ "PreferredEncoding",
+ "FileSystemEncoding",
+ "CommandLine",
+ "ProcessId",
+ "DeveloperMode",
+ )
+
+ _unavailable = _("Unavailable")
+
+ @property
+ def grok_version(self):
+ return getVersion('grok')
+
+ @property
+ def grokuiadmin_version(self):
+ return getVersion('grokui.admin')
+
+ def root_url(self, name=None):
+ obj = self.context
+ result = ""
+ while obj is not None:
+ if IRootFolder.providedBy(obj):
+ return self.url(obj, name)
+ obj = obj.__parent__
+ raise ValueError("No application nor root element found.")
+
+ @property
+ def security_notifier_url(self):
+ """Get the URL to look up for security warnings.
+ """
+ return self.security_notifier.lookup_url
+
+ @property
+ def security_notifier(self):
+ """Get a local security notifier.
+
+ The security notifier is installed as a local utility by an
+ event handler in the security module.
+ """
+ site = grok.getSite()
+ site_manager = site.getSiteManager()
+ return site_manager.queryUtility(ISecurityNotifier, default=None)
+
+ @property
+ def secnotes_enabled(self):
+ if self.security_notifier is None:
+ return False
+ return self.security_notifier.enabled
+
+ @property
+ def secnotes_message(self):
+ if self.security_notifier is None:
+ return u'Security notifier is not installed.'
+ return self.security_notifier.getNotification()
+
+ @property
+ def server_control(self):
+ return queryUtility(IServerControl)
+
+ @property
+ def runtime_info(self):
+ try:
+ ri = IRuntimeInfo(applicationController)
+ except TypeError:
+ formatted = dict.fromkeys(self._fields, self._unavailable)
+ formatted["Uptime"] = self._unavailable
+ else:
+ formatted = self._getInfo(ri)
+
+ return formatted
+
+ def _getInfo(self, ri):
+ formatted = {}
+ for name in self._fields:
+ try:
+ value = getattr(ri, "get" + name)()
+ except ValueError:
+ value = self._unavailable
+ formatted[name] = value
+ formatted["Uptime"] = self._getUptime(ri)
+ return formatted
+
+ def _getUptime(self, ri):
+ # make a unix "uptime" uptime format
+ uptime = long(ri.getUptime())
+ minutes, seconds = divmod(uptime, 60)
+ hours, minutes = divmod(minutes, 60)
+ days, hours = divmod(hours, 24)
+
+ return _('${days} day(s) ${hours}:${minutes}:${seconds}',
+ mapping = {'days': '%d' % days,
+ 'hours': '%02d' % hours,
+ 'minutes': '%02d' % minutes,
+ 'seconds': '%02d' % seconds})
+
+
+ @property
+ def current_message(self):
+ source = getUtility(
+ z3c.flashmessage.interfaces.IMessageSource, name='admin')
+ messages = list(source.list())
+ if messages:
+ return messages[0]
+
+ def updateSecurityNotifier(self, setsecnotes=None, setsecnotesource=None,
+ secnotesource=None):
+ if self.security_notifier is None:
+ site = grok.getSite()
+ site_manager = site.getSiteManager()
+ if 'grokadmin_security' not in site_manager:
+ site_manager['grokadmin_security'] = SecurityNotifier()
+ utility = site_manager['grokadmin_security']
+ site_manager.registerUtility(
+ utility, ISecurityNotifier, name=u'')
+
+ if setsecnotesource is not None:
+ self.security_notifier.setLookupURL(secnotesource)
+ if setsecnotes is not None:
+ if self.security_notifier.enabled is True:
+ self.security_notifier.disable()
+ else:
+ self.security_notifier.enable()
+ if self.secnotes_enabled is False:
+ return
+ return
+
+ def update(self, time=None, restart=None, shutdown=None,
+ setsecnotes=None, secnotesource=None, setsecnotesource=None,
+ admin_message=None, submitted=False, dbName="", pack=None,
+ days=0):
+
+ # Packing control
+ if pack is not None:
+ return self.pack(dbName, days)
+
+ # Security notification control
+ self.updateSecurityNotifier(setsecnotes, setsecnotesource,
+ secnotesource)
+
+
+ if not submitted:
+ return
+
+ # Admin message control
+ source = getUtility(
+ z3c.flashmessage.interfaces.IMessageSource, name='admin')
+ if admin_message is not None:
+ source.send(admin_message)
+ elif getattr(source, 'current_message', False):
+ source.delete(source.current_message)
+
+ # Restart control
+ if time is not None:
+ try:
+ time = int(time)
+ except:
+ time = 0
+ else:
+ time = 0
+
+ if restart is not None:
+ self.server_control.restart(time)
+ elif shutdown is not None:
+ self.server_control.shutdown(time)
+
+ self.redirect(self.url())
+
+ @property
+ def databases(self):
+ res = []
+ for name, db in getUtilitiesFor(IDatabase):
+ d = dict(dbName = db.getName(),
+ utilName = str(name),
+ size = self._getSize(db),
+ )
+ res.append(d)
+ return res
+
+ def _getSize(self, db):
+ """Get the database size in a human readable format."""
+ size = db.getSize()
+ if not isinstance(size, (int, long, float)):
+ return str(size)
+ return byteDisplay(size)
+
+ def pack(self, dbName, days):
+ try:
+ days = int(days)
+ except ValueError:
+ flash('Error: Invalid Number')
+ return
+ db = getUtility(IDatabase, name=dbName)
+ print "DB: ", db, days
+ db.pack(days=days)
+ return
+ try:
+ db.pack(days=days)
+ flash('ZODB `%s` successfully packed.' % (dbName))
+ except FileStorageError, err:
+ flash('ERROR packing ZODB `%s`: %s' % (dbName, err))
Modified: grokui.admin/trunk/src/grokui/admin/tests/apps.py
===================================================================
--- grokui.admin/trunk/src/grokui/admin/tests/apps.py 2010-01-29 15:55:39 UTC (rev 108638)
+++ grokui.admin/trunk/src/grokui/admin/tests/apps.py 2010-01-29 15:59:54 UTC (rev 108639)
@@ -33,13 +33,13 @@
>>> print browser.contents
<html xmlns="http://www.w3.org/1999/xhtml">
...
- ... <p ...>Currently no working...applications are installed.</p>
+ ... Currently no working...applications are installed.
...
We are able to add a mammoth manager...
- >>> subform = browser.getForm(name='MammothManager')
- >>> subform.getControl('Name your new app:').value = 'my-mammoth-manager'
+ >>> subform = browser.getForm(name='grokui.admin.tests.apps.MammothManager')
+ >>> subform.getControl(name='name').value = 'my-mammoth-manager'
>>> subform.getControl('Create').click()
>>> print browser.contents
@@ -62,7 +62,7 @@
We can also rename applications. For this we choose the application we
installed and click `Rename`::
- >>> browser.open("http://localhost/applications")
+ >>> browser.open("http://localhost/++grokui++/applications")
>>> ctrl = browser.getControl(name='items')
>>> ctrl.getControl(value='my-mammoth-manager').selected = True
>>> browser.getControl('Rename').click()
@@ -91,7 +91,7 @@
We are able to delete installed mammoth-managers
- >>> browser.open("http://localhost/applications")
+ >>> browser.open("http://localhost/++grokui++/applications")
>>> print browser.contents
<html xmlns="http://www.w3.org/1999/xhtml">
...
@@ -103,7 +103,7 @@
>>> print browser.contents
<html xmlns="http://www.w3.org/1999/xhtml">
...
- ... <p ...>Currently no working applications...are installed.</p>
+ ... Currently no working applications are installed.
...
...<legend>Add application</legend>
...
@@ -114,13 +114,10 @@
class MammothManager(grok.Application, grok.Container):
- """A mammoth manager.
- """
+ """A mammoth manager"""
pass
class Index(grok.View):
- """A Mammoth manager view.
- """
def render(self):
return u"Let's manage some mammoths!"
Modified: grokui.admin/trunk/src/grokui/admin/tests/brokenobjs.py
===================================================================
--- grokui.admin/trunk/src/grokui/admin/tests/brokenobjs.py 2010-01-29 15:55:39 UTC (rev 108638)
+++ grokui.admin/trunk/src/grokui/admin/tests/brokenobjs.py 2010-01-29 15:59:54 UTC (rev 108639)
@@ -26,24 +26,25 @@
If no broken applications are in the root, everything should look as
usual:
- >>> browser.open('http://localhost/applications')
+ >>> browser.open('http://localhost/++grokui++/applications')
>>> 'Broken applications:' not in browser.contents
True
We have an application type available, which is intentionally broken
and defined below::
- >>> browser.open('http://localhost/applications')
+ >>> browser.open('http://localhost/++grokui++/applications')
>>> 'PseudoBroken' in browser.contents
True
We add an instance of that new type:
- >>> subform = browser.getForm(name='PseudoBroken')
+ >>> subform = browser.getForm(
+ ... name='grokui.admin.tests.brokenobjs.PseudoBroken')
>>> subform
<zope.testbrowser.browser.Form object at 0x...>
- >>> subform.getControl('Name your new app').value = 'mybrokenobj'
+ >>> subform.getControl(name='name').value = 'mybrokenobj'
>>> subform.getControl('Create').click()
and the broken object should show up in the applications list:
Modified: grokui.admin/trunk/src/grokui/admin/tests/events.py
===================================================================
--- grokui.admin/trunk/src/grokui/admin/tests/events.py 2010-01-29 15:55:39 UTC (rev 108638)
+++ grokui.admin/trunk/src/grokui/admin/tests/events.py 2010-01-29 15:59:54 UTC (rev 108639)
@@ -29,14 +29,13 @@
When we create a new instance of our app, the eventhandler defined
below will be called:
- >>> subform = browser.getForm(name='App')
- >>> subform.getControl('Name your new app:').value = 'my-app'
+ >>> subform = browser.getForm(name='grokui.admin.tests.events.App')
+ >>> subform.getControl(name='name').value = 'my-app'
>>> subform.getControl('Create').click()
ObjectCreated event happened.
"""
import grok
-from zope.component import interfaces
class App(grok.Application, grok.Container):
pass
Modified: grokui.admin/trunk/src/grokui/admin/tests/infoviews.py
===================================================================
--- grokui.admin/trunk/src/grokui/admin/tests/infoviews.py 2010-01-29 15:55:39 UTC (rev 108638)
+++ grokui.admin/trunk/src/grokui/admin/tests/infoviews.py 2010-01-29 15:59:54 UTC (rev 108639)
@@ -29,7 +29,7 @@
We must be authenticated to fetch those infos::
- >>> browser.open('http://localhost/@@grokadmin/@@version')
+ >>> browser.open('http://localhost/++grokui++/@@admin/@@version')
Traceback (most recent call last):
...
HTTPError: HTTP Error 401: Unauthorized
@@ -40,7 +40,7 @@
When we are authenticated, we can retrieve the grok version used::
>>> browser.addHeader('Authorization', 'Basic mgr:mgrpw')
- >>> browser.open('http://localhost/@@grokadmin/@@version')
+ >>> browser.open('http://localhost/++grokui++/@@admin/@@version')
>>> print browser.contents
grok ...
@@ -63,7 +63,7 @@
To determine the used version of `grokui.admin` we can call::
>>> import pkg_resources
- >>> browser.open('http://localhost/@@grokadmin/@@version?pkg=grokui.admin')
+ >>> browser.open('http://localhost/++grokui++/@@admin/@@version?pkg=grokui.admin')
>>> version = pkg_resources.get_distribution('grokui.admin').version
>>> browser.contents == ('grokui.admin ' + version)
True
@@ -74,7 +74,7 @@
We can get the current security notification::
- >>> browser.open('http://localhost/@@grokadmin/@@secnote')
+ >>> browser.open('http://localhost/++grokui++/@@admin/@@secnote')
>>> print browser.contents
Security notifications are disabled.
Deleted: grokui.admin/trunk/src/grokui/admin/tests/macros.py
===================================================================
--- grokui.admin/trunk/src/grokui/admin/tests/macros.py 2010-01-29 15:55:39 UTC (rev 108638)
+++ grokui.admin/trunk/src/grokui/admin/tests/macros.py 2010-01-29 15:59:54 UTC (rev 108639)
@@ -1,68 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2007 Zope Corporation and Contributors.
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the Zope Public License,
-# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
-# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
-# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
-# FOR A PARTICULAR PURPOSE.
-#
-##############################################################################
-"""
-Macros for the grok admin UI
-
- >>> from zope.testbrowser.testing import Browser
- >>> browser = Browser()
- >>> browser.addHeader('Authorization', 'Basic mgr:mgrpw')
- >>> browser.open('http://localhost/applications')
-
-Check, that the macros template renders correctly, even if not called
-with context of a GAIA object. This is important, because the macro
-view is bound to ``Interface`` and can therefore be called with nearly
-every object as context.
-
-We create a non-GAIA object, a mammoth called 'manfred'.
-
- >>> subform = browser.getForm(name='Mammoth')
- >>> subform.getControl('Name your new app:').value = 'manfred'
- >>> subform.getControl('Create').click()
-
-and call the macroview with it:
-
- >>> browser.open('http://localhost/manfred/@@externalview')
- >>> print browser.contents
- <html xmlns="http://www.w3.org/1999/xhtml">
- ...
- This template (grokadminmacros.pt in grok.admin) must be called
- from a view with defined root_url.
- ...
-
-So developers get informed, that they called the wrong macro view.
-
-Let's clean up.
-
- >>> browser.open('http://localhost/applications')
- >>> ctrl = browser.getControl(name='items')
- >>> ctrl.getControl(value='manfred').selected = True
- >>> browser.getControl('Delete Selected').click()
-
-
-"""
-import grok
-
-class Mammoth(grok.Application, grok.Container):
- pass
-
-class ExternalView(grok.View):
- """A view that calls grokadminmacros 'illegally'.
- """
- grok.context(Mammoth)
-
-externalview = grok.PageTemplate("""\
-<html metal:use-macro="context/@@grokadminmacros/macros/gaia-page">
-</html>
-""")
-
Modified: grokui.admin/trunk/src/grokui/admin/tests/packdatabase.py
===================================================================
--- grokui.admin/trunk/src/grokui/admin/tests/packdatabase.py 2010-01-29 15:55:39 UTC (rev 108638)
+++ grokui.admin/trunk/src/grokui/admin/tests/packdatabase.py 2010-01-29 15:59:54 UTC (rev 108639)
@@ -19,8 +19,9 @@
>>> browser.addHeader('Authorization', 'Basic mgr:mgrpw')
>>> browser.open("http://localhost/")
- >>> subform = browser.getForm(name='StuffedMammoth')
- >>> subform.getControl('Name your new app:').value = 'my-stuffed-mammoth'
+ >>> subform = browser.getForm(
+ ... name='grokui.admin.tests.packdatabase.StuffedMammoth')
+ >>> subform.getControl(name='name').value = 'my-stuffed-mammoth'
>>> subform.getControl('Create').click()
>>> mylink = browser.getLink('my-stuffed-mammoth').click()
@@ -36,29 +37,19 @@
Time to stuff a mammoth!
Check the size of the ZODB.
- >>> browser.open("http://localhost/server")
+ >>> browser.open("http://localhost/++grokui++/server")
>>> lines = [ l.strip() for l in browser.contents.split('\\n') ]
>>> zodb_size = lines[lines.index("Demo storage 'unnamed'")+ 1]
>>> num_zodb_size = int(zodb_size.split(' ')[0])
Now, pack the database.
-(XXX: This test is disabled, because we get an infinite loop trying to
- pack a demo storage.)
-
- >>> #ctrl = browser.getControl(name='pack').click()
>>> lines = [ l.strip() for l in browser.contents.split('\\n') ]
>>> zodb_size = lines[lines.index("Demo storage 'unnamed'")+ 1]
>>> new_num_zodb_size = int(zodb_size.split(' ')[0])
-# remove this test - it highlights a problem with the zodb api, but is
-# a problem as a regression test
-#Ensure that it is smaller now:
-# >>> new_num_zodb_size < num_zodb_size
-# True
-
And clean up after ourselves.
- >>> browser.open("http://localhost/applications")
+ >>> browser.open("http://localhost/++grokui++/applications")
>>> ctrl = browser.getControl(name='items')
>>> ctrl.getControl(value='my-stuffed-mammoth').selected = True
>>> browser.getControl('Delete Selected').click()
@@ -66,17 +57,15 @@
"""
import grok
-try:
- from grokcore.view import CodeView as View
-except ImportError:
- from grok import View
+
class StuffedMammoth(grok.Application, grok.Container):
"""A stuffed mammoth"""
stuffing = None
-class Index(View):#
+class Index(grok.View):#
+
def update(self, stuffing=None):
if stuffing is not None:
self.context.stuffing = stuffing*1000
Modified: grokui.admin/trunk/src/grokui/admin/tests/security.py
===================================================================
--- grokui.admin/trunk/src/grokui/admin/tests/security.py 2010-01-29 15:55:39 UTC (rev 108638)
+++ grokui.admin/trunk/src/grokui/admin/tests/security.py 2010-01-29 15:59:54 UTC (rev 108639)
@@ -149,47 +149,30 @@
Currently, as `grokui.admin` is merely a collection of views bound to
root folders, also the security notification utility is normally
-managed by the local site manager of the root folder::
+managed by the local site manager of the root folder.
- >>> root = getRootFolder()
- >>> sm = root.getSiteManager()
-
-Now we can lookup the utility::
-
- >>> from grokui.admin.interfaces import ISecurityNotifier
- >>> notifier = sm.getUtility(ISecurityNotifier)
- >>> notifier
- <grokui.admin.security.SecurityNotifier object at 0x...>
-
The utility is local, because different root folders might want
different settings for security notifications.
The utility is persistent, so that the settings are preserved when
shutting down.
-Immediately after startup, the notifier exists, but is disabled::
+Immediately after startup, the notifier doesn't exists::
- >>> notifier.enabled
- False
+ >>> from grokui.admin.interfaces import ISecurityNotifier
+
+ >>> root = getRootFolder()
+ >>> sm = root.getSiteManager()
+ >>> notifier = sm.queryUtility(ISecurityNotifier)
+ >>> notifier is None
+ True
-We can get notifications, of course::
+We log into the admin screen to set a new notifier URL::
- >>> notifier.getNotification()
- u'Security notifications are disabled.'
-
-We can check in a formal way, whether the current notification is a
-warning::
-
- >>> notifier.isWarning()
- False
-
-The notifier we got here is the same as when using the UI. We log into
-the admin screen to set a new notifier URL::
-
>>> from zope.testbrowser.testing import Browser
>>> browser = Browser()
>>> browser.addHeader('Authorization', 'Basic mgr:mgrpw')
- >>> browser.open('http://localhost/@@server')
+ >>> browser.open('http://localhost/++grokui++/@@server')
On the server administration page we can see the status of our
notifier (enabled or disabled)::
@@ -205,7 +188,7 @@
>>> print browser.contents
<html xmlns="http://www.w3.org/1999/xhtml">
- ...<div id="securitynotifications">Security notifications are disabled.</div>
+ ...<div id="grokui-messages"><div class="grokui-security message">Security notifications are disabled.</div>
...
But we are not bound to the default URL to do lookups. We can set
@@ -224,7 +207,7 @@
>>> print browser.contents
<html xmlns="http://www.w3.org/1999/xhtml">
- ...<div id="securitynotifications">You better smash ...</div>
+ ...<div id="grokui-messages"><div class="grokui-security message">You better smash ...</div>
...
We can of course disable security notifications at any time::
@@ -232,14 +215,13 @@
>>> browser.getControl('Disable').click()
>>> print browser.contents
<html xmlns="http://www.w3.org/1999/xhtml">
- ...<div id="securitynotifications">Security notifications are disabled.</div>
+ ...<div id="grokui-messages"><div class="grokui-security message">Security notifications are disabled.</div>
...
+
Clean up::
>>> import os
>>> os.unlink(fake_warning_file)
-
-
"""
Modified: grokui.admin/trunk/src/grokui/admin/tests/server.py
===================================================================
--- grokui.admin/trunk/src/grokui/admin/tests/server.py 2010-01-29 15:55:39 UTC (rev 108638)
+++ grokui.admin/trunk/src/grokui/admin/tests/server.py 2010-01-29 15:59:54 UTC (rev 108639)
@@ -35,7 +35,8 @@
>>> print browser.contents
<html xmlns="http://www.w3.org/1999/xhtml">
...
- ... <a href="http://localhost/server">Server Control</a>
+ <a href="http://localhost/++grokui++/server"
+ title="Server Control">Server Control</a>
...
Now we can click that link and should get the server administration
@@ -43,7 +44,7 @@
>>> browser.getLink('Server Control').click()
>>> browser.title
- 'grok administration interface'
+ 'Grok User Interface'
We can enter an admin message::
@@ -59,8 +60,10 @@
>>> msg_form.submit()
>>> print browser.contents
<html xmlns="http://www.w3.org/1999/xhtml">
- ... <li class="admin">Hi there!</li>
...
+ <dl class="messages-list">
+ <dd class="admin">Hi there!</dd>
+ ...
The message stays, even if we call another page::
@@ -68,9 +71,7 @@
>>> print browser.contents
<html xmlns="http://www.w3.org/1999/xhtml">
...
- ... <li class="admin">Hi there!</li>
- ...
- ...
+ ... <dd class="admin">Hi there!</dd>
... <legend>Add application</legend>
...
@@ -80,7 +81,7 @@
>>> print browser.contents
<html xmlns="http://www.w3.org/1999/xhtml">
...
- ... <li class="admin">Hi there!</li>
+ ... <dd class="admin">Hi there!</dd>
...
Modified: grokui.admin/trunk/src/grokui/admin/tests/test_grokadmin.py
===================================================================
--- grokui.admin/trunk/src/grokui/admin/tests/test_grokadmin.py 2010-01-29 15:55:39 UTC (rev 108638)
+++ grokui.admin/trunk/src/grokui/admin/tests/test_grokadmin.py 2010-01-29 15:59:54 UTC (rev 108639)
@@ -59,14 +59,14 @@
for name in []:
suite.addTest(suiteFromPackage(name))
for name in ['utilities.py']:
- suite.addTest(doctest.DocFileSuite(name,
- package='grokui.admin',
- globs=globs,
- setUp=setUpZope,
- tearDown=cleanUpZope,
- optionflags=doctest.ELLIPSIS+
- doctest.NORMALIZE_WHITESPACE)
- )
+ suite.addTest(doctest.DocFileSuite(
+ name,
+ package='grokui.admin',
+ globs=globs,
+ setUp=setUpZope,
+ tearDown=cleanUpZope,
+ optionflags=(doctest.ELLIPSIS|doctest.NORMALIZE_WHITESPACE),
+ ))
return suite
if __name__ == '__main__':
Modified: grokui.admin/trunk/src/grokui/admin/tests/test_grokadmin_functional.py
===================================================================
--- grokui.admin/trunk/src/grokui/admin/tests/test_grokadmin_functional.py 2010-01-29 15:55:39 UTC (rev 108638)
+++ grokui.admin/trunk/src/grokui/admin/tests/test_grokadmin_functional.py 2010-01-29 15:59:54 UTC (rev 108639)
@@ -16,10 +16,6 @@
def setUp(test):
FunctionalTestSetup().setUp()
- # In functional tests no IDatabaseOpenedWithRootEvent are fired. We
- # therefore have to setup security notifications manually
- from grokui.admin.security import setupSecurityNotification
- setupSecurityNotification(getRootFolder())
def tearDown(test):
FunctionalTestSetup().tearDown()
Modified: grokui.admin/trunk/src/grokui/admin/utilities.py
===================================================================
--- grokui.admin/trunk/src/grokui/admin/utilities.py 2010-01-29 15:55:39 UTC (rev 108638)
+++ grokui.admin/trunk/src/grokui/admin/utilities.py 2010-01-29 15:59:54 UTC (rev 108639)
@@ -1,11 +1,8 @@
import httplib
import pkg_resources
-import re
import socket
import urllib
import urllib2
-from zope.tal.taldefs import attrEscape
-from urlparse import urlparse, urlunparse
def getURLWithParams(url, data=None):
@@ -38,7 +35,6 @@
"""A customised HTTPConnection allowing a per-connection
timeout, specified at construction.
"""
-
def __init__(self, host, port=None, strict=None, timeout=None):
httplib.HTTPConnection.__init__(self, host, port,
strict)
@@ -71,7 +67,6 @@
"""A customised HTTPHandler which times out connection
after the duration specified at construction.
"""
-
def __init__(self, timeout=None):
urllib2.HTTPHandler.__init__(self)
self.timeout = timeout
@@ -84,4 +79,3 @@
timeout = self.timeout)
return self.do_open(makeConnection, req)
-
Modified: grokui.admin/trunk/src/grokui/admin/view.py
===================================================================
--- grokui.admin/trunk/src/grokui/admin/view.py 2010-01-29 15:55:39 UTC (rev 108638)
+++ grokui.admin/trunk/src/grokui/admin/view.py 2010-01-29 15:59:54 UTC (rev 108639)
@@ -1,50 +1,22 @@
-##############################################################################
-#
-# Copyright (c) 2007-2008 Zope Corporation and Contributors.
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the Zope Public License,
-# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
-# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
-# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
-# FOR A PARTICULAR PURPOSE.
-#
-##############################################################################
+# -*- coding: utf-8 -*-
"""Views for the grok admin UI"""
import grok
-import z3c.flashmessage.interfaces
+from BTrees.OOBTree import OOBTree
+from grokui.base import IGrokUIRealm, GrokUIView
from grokui.admin.interfaces import ISecurityNotifier
from grokui.admin.utilities import getVersion, getURLWithParams
+from grokui.admin.security import MSG_DISABLED
-from ZODB.broken import Broken
-from ZODB.interfaces import IDatabase
-from BTrees.OOBTree import OOBTree
-from ZODB.FileStorage.FileStorage import FileStorageError
-
-import zope.component
-from zope.interface import Interface
-from zope.exceptions import DuplicationError
from zope.site.interfaces import IRootFolder
-from zope.authentication.interfaces import IUnauthenticatedPrincipal
+from zope.exceptions import DuplicationError
+from zope.component import getUtility, queryUtility
-from zope.app.applicationcontrol.interfaces import IServerControl
-from zope.app.applicationcontrol.applicationcontrol import applicationController
-from zope.app.applicationcontrol.browser.runtimeinfo import RuntimeInfoView
-from zope.app.applicationcontrol.browser.zodbcontrol import ZODBControlView
+grok.context(IGrokUIRealm)
+grok.templatedir("templates")
-grok.context(IRootFolder)
-
-def flash(message, type='message'):
- src = zope.component.getUtility(
- z3c.flashmessage.interfaces.IMessageSource, name='session'
- )
- src.send(message, type)
-
-
class ManageApplications(grok.Permission):
grok.name('grok.ManageApplications')
@@ -52,70 +24,42 @@
class GrokAdminInfoView(grok.View):
"""A base to provide machinereadable views.
"""
- grok.name('grokadmin')
+ grok.name('admin')
grok.require('grok.ManageApplications')
def render(self):
return u'go to @@version or @@secnotes'
-class AdminViewBase(grok.View):
- """A grok.View with a special application_url.
- We have to compute the application_url different from common
- grok.Views, because we have no root application object in the
- adminUI. To avoid mismatch, we also call it 'root_url'.
- """
- grok.baseclass()
-
- @property
- def grok_version(self):
- return getVersion('grok')
-
- @property
- def grokuiadmin_version(self):
- return getVersion('grokui.admin')
-
- def is_authenticated(self):
- """Check, wether we are authenticated.
- """
- return not IUnauthenticatedPrincipal.providedBy(self.request.principal)
-
- def root_url(self, name=None):
- obj = self.context
- while obj is not None:
- if IRootFolder.providedBy(obj):
- return self.url(obj, name)
- obj = obj.__parent__
- raise ValueError("No application nor root element found.")
-
-
-
class GrokAdminVersion(grok.View):
"""Display version of a package.
- Call this view via http://localhost:8080/@@grokadmin/@@version to
+
+ Call this view via http://localhost:8080/@@admin/@@version to
get the used grok version. Call
- http://localhost:8080/@@grokadmin/@@version?pkg=<pkgname> to get
+ http://localhost:8080/@@admin/@@version?pkg=<pkgname> to get
the used version of package <pkgname>.
"""
grok.name('version')
grok.context(GrokAdminInfoView)
grok.require('grok.ManageApplications')
+
def render(self, pkg='grok'):
return u'%s %s' % (pkg, getVersion(pkg))
class GrokAdminSecurityNotes(grok.View):
"""Display current security notification.
- Call this view via http://localhost:8080/@@grokadmin/@@secnote
+
+ Call this view via http://localhost:8080/@@admin/@@secnote
"""
grok.name('secnote')
grok.context(GrokAdminInfoView)
grok.require('grok.ManageApplications')
+
def render(self):
- site = grok.getSite()
- site_manager = site.getSiteManager()
- notifier = site_manager.queryUtility(ISecurityNotifier, default=None)
- return notifier.getNotification()
+ notifier = queryUtility(ISecurityNotifier, default=None)
+ return (notifier is not None and notifier.getNotification()
+ or MSG_DISABLED)
class Add(grok.View):
@@ -131,28 +75,27 @@
def render(self, application, name, inspectapp=None):
if name is None or name == "":
- self.redirect(self.url(self.context))
+ self.redirect(self.url(self.context, 'applications'))
return
if name is None or name == "":
- self.redirect(self.url(self.context))
+ self.redirect(self.url(self.context, 'applications'))
return
- app = zope.component.getUtility(grok.interfaces.IApplication,
- name=application)
+ app = getUtility(grok.interfaces.IApplication, name=application)
try:
new_app = app()
grok.notify(grok.ObjectCreatedEvent(new_app))
- self.context[name] = new_app
- flash(u'Added %s `%s`.' % (application, name))
+ self.context.root[name] = new_app
+ self.flash(u'Added %s `%s`.' % (application, name))
except DuplicationError:
- flash(
- u'Name `%s` already in use. Please choose another name.' % (
- name,))
- self.redirect(self.url(self.context))
+ self.flash(u'Name `%s` already in use. '
+ u'Please choose another name.' % (name,))
+ self.redirect(self.url(self.context, 'applications'))
class ManageApps(grok.View):
"""Manage applications (delete, rename).
"""
+
grok.require('grok.ManageApplications')
def delete(self, items):
@@ -161,34 +104,35 @@
msg = u''
for name in items:
try:
- del self.context[name]
+ del self.context.root[name]
msg = (u'%sApplication `%s` was successfully '
u'deleted.\n' % (msg, name))
except AttributeError:
# Object is broken.. Try it the hard way...
# TODO: Try to repair before deleting.
- if not hasattr(self.context, 'data'):
+ obj = self.context.root[name]
+ if not hasattr(self.context.root, 'data'):
msg = (
u'%sCould not delete application `%s`: no '
u'`data` attribute found.\n' % (msg, name))
continue
- if not isinstance(self.context.data, OOBTree):
+ if not isinstance(self.context.root.data, OOBTree):
msg = (
u'%sCould not delete application `%s`: no '
u'`data` is not a BTree.\n' % (msg, name))
continue
- self.context.data.pop(name)
- self.context.data._p_changed = True
+ self.context.root.data.pop(name)
+ self.context.root.data._p_changed = True
msg = (u'%sBroken application `%s` was successfully '
u'deleted.\n' % (msg, name))
- flash(msg)
- self.redirect(self.url(self.context))
+ self.flash(msg)
+ self.redirect(self.url(self.context, 'applications'))
def render(self, rename=None, delete=None, items=None):
if items is None:
- return self.redirect(self.url(self.context))
+ return self.redirect(self.url(self.context, 'applications'))
if not isinstance(items, list):
items = [items]
@@ -199,10 +143,10 @@
return self.redirect(getURLWithParams(
self.url(self.context, '@@grokadmin_rename'),
data=dict(items=items)))
- self.redirect(self.url(self.context))
+ self.redirect(self.url(self.context, 'applications'))
-class Rename(AdminViewBase):
+class Rename(GrokUIView):
"""Rename Grok applications.
"""
grok.name('grokadmin_rename')
@@ -210,237 +154,49 @@
grok.require('grok.ManageApplications')
def update(self, cancel=None, items=None, new_names=None):
- """We proceed with the renaming, using the request parameters.
- """
- if cancel is not None:
- return self.redirect(self.url(self.context))
+ msg = u''
+ if cancel is not None or not items:
+ return self.redirect(self.url(self.context, 'applications'))
+
if not isinstance(items, list):
items = [items]
self.apps = items
if new_names is not None and len(new_names) != len(items):
- return self.redirect(self.url(self.context))
+ return self.redirect(self.url(self.context, 'applications'))
if new_names is None:
return
mapping = dict([(items[x], new_names[x]) for x in range(len(items))])
+ root = self.context.__parent__
+ existing = root.keys()
for oldname, newname in mapping.items():
if oldname == newname:
continue
- if oldname not in self.context.keys():
- flash('Could not rename %s: not found' % oldname)
+ if oldname not in existing:
+ self.flash('Could not rename %s: not found' % oldname)
continue
- if newname in self.context.keys():
- flash('`%s` already exists.' % newname)
+ if newname in existing:
+ self.flash('`%s` already exists.' % newname)
continue
- self.context[newname] = self.context[oldname]
- self.context[newname].__name__ = newname
- del self.context[oldname]
- flash('Renamed `%s` to `%s`.' % (oldname, newname))
- self.redirect(self.url(self.context))
+ root[newname] = root[oldname]
+ root[newname].__name__ = newname
+ del root[oldname]
+ self.flash('Renamed `%s` to `%s`.' % (oldname, newname))
+ self.redirect(self.url(self.context, 'applications'))
return
-class Index(AdminViewBase):
+class Index(grok.View):
"""A redirector to the real frontpage.
"""
grok.name('index.html') # The root folder is not a grok.Model
grok.require('grok.ManageApplications')
+ grok.context(IRootFolder)
- def update(self):
- apps = zope.component.getAllUtilitiesRegisteredFor(
- grok.interfaces.IApplication)
- self.applications = ("%s.%s" % (x.__module__, x.__name__)
- for x in apps)
- # Go to the first page immediately.
- self.redirect(self.url('applications'))
-
-
-class Applications(AdminViewBase):
- """View for application management.
- """
- grok.name('applications')
- grok.require('grok.ManageApplications')
-
-
- def update(self):
- # Available apps...
- apps = zope.component.getAllUtilitiesRegisteredFor(
- grok.interfaces.IApplication)
- self.applications = (
- {'name': "%s.%s" % (x.__module__, x.__name__),
- 'docurl':("%s.%s" % (x.__module__, x.__name__)).replace('.', '/'),
- 'descr': x.__doc__}
- for x in apps)
-
- # Installed apps...
- inst_apps = [x for x in self.context.values()
- if hasattr(x, '__class__') and x.__class__ in apps
- and not issubclass(x.__class__, Broken)]
- inst_apps.sort(lambda x, y: cmp(x.__name__, y.__name__))
- self.installed_applications = inst_apps
-
- # Broken apps...
- broken_apps = [{'obj':y, 'name':x} for x,y in self.context.items()
- if isinstance(y, Broken)]
- broken_apps.sort(lambda x, y: cmp(x['name'], y['name']))
- self.broken_applications = broken_apps
-
-
-class AdminMessageSource(grok.GlobalUtility):
-
- grok.name('admin')
- zope.interface.implements(z3c.flashmessage.interfaces.IMessageSource)
-
- message = None
-
- def send(self, message, type='admin'):
- self.message = z3c.flashmessage.message.PersistentMessage(message,
- type)
-
- def list(self, type=None):
- if self.message is None:
- return
- if type is None or self.message.type == type:
- yield self.message
-
- def delete(self, message):
- if message is self.message:
- self.message = None
- else:
- raise KeyError(message)
-
-
-class GrokAdminMacros(AdminViewBase):
- """Provides the o-wrap layout.
- """
- grok.context(Interface)
-
-
-class Server(AdminViewBase, ZODBControlView):
- """Zope3 management screen.
- """
- grok.require('grok.ManageApplications')
-
- @property
- def security_notifier_url(self):
- """Get the URL to look up for security warnings.
- """
- return self.security_notifier.lookup_url
-
- @property
- def security_notifier(self):
- """Get a local security notifier.
-
- The security notifier is installed as a local utility by an
- event handler in the security module.
- """
- site = grok.getSite()
- site_manager = site.getSiteManager()
- return site_manager.queryUtility(ISecurityNotifier, default=None)
-
- @property
- def secnotes_enabled(self):
- if self.security_notifier is None:
- # Safety belt if installation of notifier failed
- return False
- return self.security_notifier.enabled
-
- @property
- def secnotes_message(self):
- if self.security_notifier is None:
- return u'Security notifier is not installed.'
- return self.security_notifier.getNotification()
-
- @property
- def server_control(self):
- return zope.component.queryUtility(IServerControl, '', None)
-
- @property
- def runtime_info(self):
- riv = RuntimeInfoView()
- riv.context = applicationController
- return riv.runtimeInfo()
-
- @property
- def current_message(self):
- source = zope.component.getUtility(
- z3c.flashmessage.interfaces.IMessageSource, name='admin')
- messages = list(source.list())
- if messages:
- return messages[0]
-
- def updateSecurityNotifier(self, setsecnotes=None, setsecnotesource=None,
- secnotesource=None):
- if self.security_notifier is None:
- return
- if setsecnotesource is not None:
- self.security_notifier.setLookupURL(secnotesource)
- if setsecnotes is not None:
- if self.security_notifier.enabled is True:
- self.security_notifier.disable()
- else:
- self.security_notifier.enable()
- if self.secnotes_enabled is False:
- return
- return
-
- def update(self, time=None, restart=None, shutdown=None,
- setsecnotes=None, secnotesource=None, setsecnotesource=None,
- admin_message=None, submitted=False, dbName="", pack=None,
- days=0):
-
- # Packing control
- if pack is not None:
- return self.pack(dbName, days)
-
- # Security notification control
- self.updateSecurityNotifier(setsecnotes, setsecnotesource,
- secnotesource)
-
-
- if not submitted:
- return
-
- # Admin message control
- source = zope.component.getUtility(
- z3c.flashmessage.interfaces.IMessageSource, name='admin')
- if admin_message is not None:
- source.send(admin_message)
- elif getattr(source, 'current_message', False):
- source.delete(source.current_message)
-
- # Restart control
- if time is not None:
- try:
- time = int(time)
- except:
- time = 0
- else:
- time = 0
-
- if restart is not None:
- self.server_control.restart(time)
- elif shutdown is not None:
- self.server_control.shutdown(time)
-
- self.redirect(self.url())
-
- def pack(self, dbName, days):
- try:
- days = int(days)
- except ValueError:
- flash('Error: Invalid Number')
- return
- db = zope.component.getUtility(IDatabase, name=dbName)
- print "DB: ", db, days
- db.pack(days=days)
- return
- try:
- db.pack(days=days)
- flash('ZODB `%s` successfully packed.' % (dbName))
- except FileStorageError, err:
- flash('ERROR packing ZODB `%s`: %s' % (dbName, err))
+ def render(self):
+ grokui_url = self.url(self.context) + '/++grokui++/applications'
+ self.redirect(grokui_url)
Copied: grokui.admin/trunk/versions.cfg (from rev 108638, grokui.admin/branches/fancy-layout/versions.cfg)
===================================================================
--- grokui.admin/trunk/versions.cfg (rev 0)
+++ grokui.admin/trunk/versions.cfg 2010-01-29 15:59:54 UTC (rev 108639)
@@ -0,0 +1,115 @@
+# This is a copy of grok/versions.cfg revision 102959.
+#
+# Don't make local modifications here, just override it explicitly in
+# your buildout's [versions] part.
+
+[versions]
+ClientForm = 0.2.9
+grokcore.component = 1.7
+grokcore.formlib = 1.3
+grokcore.security = 1.2
+grokcore.view = 1.11
+grokcore.viewlet = 1.2
+martian = 0.11
+mechanize = 0.1.7b
+pytz = 2007k
+RestrictedPython = 3.4.2
+simplejson = 1.7.1
+z3c.autoinclude = 0.2.2
+z3c.flashmessage = 1.0
+z3c.recipe.eggbasket = 0.4.3
+z3c.testsetup = 0.4
+zc.catalog = 1.2.0
+ZConfig = 2.5.1
+zc.recipe.testrunner = 1.0.0
+zdaemon = 2.0.2
+ZODB3 = 3.8.3
+zodbcode = 3.4.0
+zope.annotation = 3.4.1
+zope.app.apidoc = 3.4.3
+zope.app.applicationcontrol = 3.4.3
+zope.app.appsetup = 3.4.1
+zope.app.authentication = 3.4.4
+zope.app.basicskin = 3.4.0
+zope.app.broken = 3.4.0
+zope.app.catalog = 3.5.1
+zope.app.component = 3.4.1
+zope.app.container = 3.5.6
+zope.app.content = 3.4.0
+zope.app.debug = 3.4.1
+zope.app.dependable = 3.4.0
+zope.app.error = 3.5.1
+zope.app.exception = 3.4.1
+zope.app.file = 3.4.4
+zope.app.folder = 3.4.0
+zope.app.form = 3.4.1
+zope.app.generations = 3.4.1
+zope.app.http = 3.4.1
+zope.app.i18n = 3.4.4
+zope.app.interface = 3.4.0
+zope.app.intid = 3.4.1
+zope.app.keyreference = 3.4.1
+zope.app.locales = 3.4.5
+zope.app.onlinehelp = 3.4.1
+zope.app.pagetemplate = 3.4.1
+zope.app.preference = 3.4.1
+zope.app.principalannotation = 3.4.0
+zope.app.publication = 3.4.3
+zope.app.publisher = 3.5.1
+zope.app.renderer = 3.4.0
+zope.app.rotterdam = 3.4.1
+zope.app.schema = 3.4.0
+zope.app.security = 3.5.2
+zope.app.securitypolicy = 3.4.6
+zope.app.server = 3.4.2
+zope.app.session = 3.5.1
+zope.app.skins = 3.4.0
+zope.app.testing = 3.4.3
+zope.app.tree = 3.4.0
+zope.app.twisted = 3.4.1
+zope.app.wsgi = 3.4.2
+zope.app.zapi = 3.4.0
+zope.app.zcmlfiles = 3.4.3
+zope.app.zopeappgenerations = 3.4.0
+zope.cachedescriptors = 3.4.1
+zope.component = 3.4.0
+zope.configuration = 3.4.0
+zope.contentprovider = 3.4.0
+zope.contenttype = 3.4.0
+zope.copypastemove = 3.4.0
+zope.datetime = 3.4.0
+zope.deferredimport = 3.4.0
+zope.deprecation = 3.4.0
+zope.dottedname = 3.4.2
+zope.dublincore = 3.4.0
+zope.error = 3.5.1
+zope.event = 3.4.0
+zope.exceptions = 3.4.0
+zope.filerepresentation = 3.4.0
+zope.formlib = 3.4.0
+zope.hookable = 3.4.0
+zope.i18n = 3.4.0
+zope.i18nmessageid = 3.4.3
+zope.index = 3.4.1
+zope.interface = 3.4.1
+zope.lifecycleevent = 3.4.0
+zope.location = 3.4.0
+zope.minmax = 1.1.0
+zope.modulealias = 3.4.0
+zope.pagetemplate = 3.4.0
+zope.proxy = 3.4.2
+zope.publisher = 3.4.9
+zope.schema = 3.4.0
+zope.security = 3.4.1
+zope.securitypolicy = 3.4.1
+zope.server = 3.4.3
+zope.session = 3.4.1
+zope.size = 3.4.0
+zope.structuredtext = 3.4.0
+zope.tal = 3.4.1
+zope.tales = 3.4.0
+zope.testbrowser = 3.4.2
+zope.testing = 3.7.6
+zope.thread = 3.4
+zope.traversing = 3.4.1
+zope.viewlet = 3.4.2
More information about the checkins
mailing list