[Checkins] SVN: grok/trunk/ Admin UI support for broken objects and
minor fixes.
Uli Fouquet
uli at gnufix.de
Fri Aug 31 23:24:22 EDT 2007
Log message for revision 79411:
Admin UI support for broken objects and minor fixes.
* admin UI now supports deletion of broken apps.
* class browser now displays interfaces in modules.
Changed:
U grok/trunk/CHANGES.txt
U grok/trunk/src/grok/admin/docgrok.py
D grok/trunk/src/grok/admin/static/GROK_Logo.jpg
D grok/trunk/src/grok/admin/static/grok-relax.jpg
D grok/trunk/src/grok/admin/static/grok-relax5.png
U grok/trunk/src/grok/admin/view.py
U grok/trunk/src/grok/admin/view_templates/applications.pt
U grok/trunk/src/grok/admin/view_templates/docgrokclassview.pt
U grok/trunk/src/grok/admin/view_templates/docgrokgrokapplicationview.pt
U grok/trunk/src/grok/admin/view_templates/docgrokinterfaceview.pt
U grok/trunk/src/grok/admin/view_templates/docgrokmoduleview.pt
U grok/trunk/src/grok/admin/view_templates/docgrokpackageview.pt
U grok/trunk/src/grok/admin/view_templates/docgroktextfileview.pt
U grok/trunk/src/grok/admin/view_templates/docgrokview.pt
A grok/trunk/src/grok/admin/view_templates/grokadminmacros.pt
U grok/trunk/src/grok/admin/view_templates/index.pt
U grok/trunk/src/grok/admin/view_templates/inspect.pt
D grok/trunk/src/grok/admin/view_templates/macros.pt
U grok/trunk/src/grok/admin/view_templates/server.pt
A grok/trunk/src/grok/ftests/admin/apackage/
U grok/trunk/src/grok/ftests/admin/apps.py
A grok/trunk/src/grok/ftests/admin/brokenobjs.py
A grok/trunk/src/grok/ftests/admin/docgrok.py
A grok/trunk/src/grok/ftests/admin/macros.py
U grok/trunk/src/grok/ftests/admin/objectbrowser.py
-=-
Modified: grok/trunk/CHANGES.txt
===================================================================
--- grok/trunk/CHANGES.txt 2007-09-01 02:56:29 UTC (rev 79410)
+++ grok/trunk/CHANGES.txt 2007-09-01 03:24:21 UTC (rev 79411)
@@ -12,6 +12,13 @@
* Add the grok.Role component base class.
+* The admin UI now displays and offers deletion of broken objects.
+
+Bug fixes
+---------
+
+* The admin UI now shows interfaces in modules.
+
Restructuring
-------------
Modified: grok/trunk/src/grok/admin/docgrok.py
===================================================================
--- grok/trunk/src/grok/admin/docgrok.py 2007-09-01 02:56:29 UTC (rev 79410)
+++ grok/trunk/src/grok/admin/docgrok.py 2007-09-01 03:24:21 UTC (rev 79411)
@@ -59,6 +59,7 @@
class ManageApplications(grok.Permission):
grok.name('grok.ManageApplications')
+
def find_filepath(dotted_path):
"""Find the filepath for a dotted name.
@@ -492,7 +493,11 @@
ob = resolve(self.path)
filename = ob.__file__
module_info = ModuleInfo(filename, self.path)
- infos = module_info.getSubModuleInfos()
+ try:
+ infos = module_info.getSubModuleInfos(exclude_tests=False)
+ except TypeError:
+ # Another version of martian.scan is installed
+ infos = module_info.getSubModuleInfos()
if filter_func is not None:
infos = filter(filter_func, infos)
result = []
Deleted: grok/trunk/src/grok/admin/static/GROK_Logo.jpg
===================================================================
(Binary files differ)
Deleted: grok/trunk/src/grok/admin/static/grok-relax.jpg
===================================================================
(Binary files differ)
Deleted: grok/trunk/src/grok/admin/static/grok-relax5.png
===================================================================
(Binary files differ)
Modified: grok/trunk/src/grok/admin/view.py
===================================================================
--- grok/trunk/src/grok/admin/view.py 2007-09-01 02:56:29 UTC (rev 79410)
+++ grok/trunk/src/grok/admin/view.py 2007-09-01 03:24:21 UTC (rev 79411)
@@ -11,7 +11,8 @@
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
-"""Views for grok admin UI"""
+"""Views for the grok admin UI"""
+
import grok
import os
import inspect
@@ -26,6 +27,9 @@
from grok.admin.utilities import getPathLinksForObject, getPathLinksForClass
from grok.admin.utilities import getPathLinksForDottedName, getParentURL
+from ZODB.broken import Broken
+from BTrees.OOBTree import OOBTree
+
import zope.component
from zope.interface import Interface
from zope.interface.interface import InterfaceClass
@@ -43,6 +47,7 @@
from zope.app.folder.interfaces import IRootFolder
from zope.app.security.interfaces import ILogout, IAuthentication
from zope.app.security.interfaces import IUnauthenticatedPrincipal
+from zope.exceptions import DuplicationError
from zope.proxy import removeAllProxies
from zope.tal.taldefs import attrEscape
@@ -69,10 +74,18 @@
if name is None or name == "":
self.redirect(self.url(self.context))
return
+ if name is None or name == "":
+ self.redirect(self.url(self.context))
+ return
app = zope.component.getUtility(grok.interfaces.IApplication,
name=application)
- self.context[name] = app()
- self.flash(u'Added %s `%s`.' % (application, name))
+ try:
+ self.context[name] = app()
+ self.flash(u'Added %s `%s`.' % (application, name))
+ except DuplicationError:
+ self.flash(
+ u'Name `%s` already in use. Please choose another name.' % (
+ name,))
self.redirect(self.url(self.context))
@@ -86,11 +99,34 @@
if items is None:
self.redirect(self.url(self.context))
return
+ msg = u''
if not isinstance(items, list):
items = [items]
for name in items:
- del self.context[name]
- self.flash(u'Application %s was successfully deleted.' % (name,))
+ try:
+ del self.context[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.
+ obj = self.context[name]
+ if not hasattr(self.context, 'data'):
+ msg = (
+ u'%sCould not delete application `%s`: no '
+ u'`data` attribute found.\n' % (msg, name))
+ continue
+ if not isinstance(self.context.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
+ msg = (u'%sBroken application `%s` was successfully '
+ u'deleted.\n' % (msg, name))
+
+ self.flash(msg)
self.redirect(self.url(self.context))
@@ -121,7 +157,7 @@
return not IUnauthenticatedPrincipal.providedBy(self.request.principal)
-class Macros(GAIAView):
+class GrokAdminMacros(GAIAView):
"""Provides the o-wrap layout."""
grok.context(Interface)
@@ -275,8 +311,10 @@
class Applications(GAIAView):
- """View for application management."""
+ """View for application management.
+ """
+
grok.name('applications')
grok.require('grok.ManageApplications')
@@ -288,17 +326,32 @@
return result
def update(self):
+ from ZODB import broken
+
+ from zope.app.broken.broken import IBroken
+
+ # 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('.', '/')}
+ for x in apps)
+
+ # Installed apps...
inst_apps = [x for x in self.context.values()
- if hasattr(x, '__class__') and x.__class__ in apps]
- self.applications = (
- {'name': "%s.%s" % (x.__module__, x.__name__),
- 'docurl':("%s.%s" % (x.__module__, x.__name__)).replace('.', '/')}
- for x in apps)
+ 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')
@@ -521,12 +574,14 @@
entry['isfunction'] = True
if hasattr(obj, 'getSignature'):
entry['signature'] = obj.getSignature()
- elif (isinstance(obj,Module) and
+ elif (isinstance(obj, Module) and
os.path.basename(obj.getFileName()) in
['__init.py__', '__init__.pyc', '__init__.pyo']):
entry['ispackage'] = True
- elif isinstance(obj,Module):
+ elif isinstance(obj, Module):
entry['ismodule'] = True
+ elif isinstance(obj, InterfaceClass):
+ entry['isinterface'] = True
entries.append(entry)
entries.sort(lambda x, y: cmp(x['name'], y['name']))
Modified: grok/trunk/src/grok/admin/view_templates/applications.pt
===================================================================
--- grok/trunk/src/grok/admin/view_templates/applications.pt 2007-09-01 02:56:29 UTC (rev 79410)
+++ grok/trunk/src/grok/admin/view_templates/applications.pt 2007-09-01 03:24:21 UTC (rev 79411)
@@ -1,16 +1,22 @@
-<html metal:use-macro="context/@@macros/gaia-page">
+<html metal:use-macro="context/@@grokadminmacros/gaia-page">
<div metal:fill-slot="content">
<form tal:define="apps context/values"
- tal:attributes="action string:${context/@@absolute_url}/delete"
- tal:condition="apps|nothing">
- <fieldset
- tal:condition="python: len(view.installed_applications)">
+ tal:attributes="action string:${context/@@absolute_url}/delete">
+
+ <fieldset>
<legend>Installed applications</legend>
- <div tal:repeat="app view/installed_applications">
+
+ <div tal:condition="not: python: len(view.installed_applications)">
+ <p class="menu-description1">Currently no working applications are
+ installed.</p>
+ </div>
+
+ <div tal:condition="python: len(view.installed_applications) or True"
+ tal:repeat="app view/installed_applications">
<input type="checkbox"
class="checkbox"
- tal:attributes="value app/__name__;
+ tal:attributes="value app/__name__;
name string:items" />
<a tal:attributes="href string:${context/@@absolute_url}/${app/__name__}">
<span tal:replace="app/__name__"/>
@@ -18,21 +24,28 @@
</a>
[<a href=""
- tal:attributes="href string:${context/@@absolute_url}/${app/__name__}/@@inspect.html"
+ tal:attributes="href string:${context/@@absolute_url}/${app/__name__}/@@inspect.html"
>object browser</a>]
</div>
+ <div tal:condition="view/broken_applications">
+ <br/><div class="emph">Broken applications:</div>
+ </div>
+ <div tal:repeat="app view/broken_applications">
+ <input type="checkbox"
+ class="checkbox"
+ tal:attributes="value app/name;
+ name string:items" />
+ <span tal:content="app/name" />
+ (broken type: <span tal:replace="string:${app/obj/__class__/__module__}.${app/obj/__class__/__name__}"/>). This application is broken!
+ </div>
+
<p>
- <input class="button" type="submit" value="Delete Selected"/></p>
+ <input tal:condition="python:len(view.installed_applications)+len(view.broken_applications) > 0"
+ class="button" type="submit" value="Delete Selected"/></p>
</fieldset>
</form>
- <fieldset
- tal:condition="not: python: len(view.installed_applications)">
- <legend>Installed applications</legend>
- <p class="menu-description1">Currently no applications are installed.</p>
- </fieldset>
-
<fieldset>
<legend>Add application</legend>
Modified: grok/trunk/src/grok/admin/view_templates/docgrokclassview.pt
===================================================================
--- grok/trunk/src/grok/admin/view_templates/docgrokclassview.pt 2007-09-01 02:56:29 UTC (rev 79410)
+++ grok/trunk/src/grok/admin/view_templates/docgrokclassview.pt 2007-09-01 03:24:21 UTC (rev 79411)
@@ -1,4 +1,4 @@
-<html metal:use-macro="view/app_root/@@macros/gaia-page">
+<html metal:use-macro="view/app_root/@@grokadminmacros/gaia-page">
<head>
<title>DocGrok page title</title>
</head>
Modified: grok/trunk/src/grok/admin/view_templates/docgrokgrokapplicationview.pt
===================================================================
--- grok/trunk/src/grok/admin/view_templates/docgrokgrokapplicationview.pt 2007-09-01 02:56:29 UTC (rev 79410)
+++ grok/trunk/src/grok/admin/view_templates/docgrokgrokapplicationview.pt 2007-09-01 03:24:21 UTC (rev 79411)
@@ -1,4 +1,4 @@
-<html metal:use-macro="view/app_root/@@macros/gaia-page">
+<html metal:use-macro="view/app_root/@@grokadminmacros/gaia-page">
<head>
<title>DocGrok page title</title>
</head>
Modified: grok/trunk/src/grok/admin/view_templates/docgrokinterfaceview.pt
===================================================================
--- grok/trunk/src/grok/admin/view_templates/docgrokinterfaceview.pt 2007-09-01 02:56:29 UTC (rev 79410)
+++ grok/trunk/src/grok/admin/view_templates/docgrokinterfaceview.pt 2007-09-01 03:24:21 UTC (rev 79411)
@@ -1,4 +1,4 @@
-<html metal:use-macro="view/app_root/@@macros/gaia-page">
+<html metal:use-macro="view/app_root/@@grokadminmacros/gaia-page">
<head>
<title>DocGrok page title</title>
</head>
Modified: grok/trunk/src/grok/admin/view_templates/docgrokmoduleview.pt
===================================================================
--- grok/trunk/src/grok/admin/view_templates/docgrokmoduleview.pt 2007-09-01 02:56:29 UTC (rev 79410)
+++ grok/trunk/src/grok/admin/view_templates/docgrokmoduleview.pt 2007-09-01 03:24:21 UTC (rev 79411)
@@ -1,4 +1,4 @@
-<html metal:use-macro="view/app_root/@@macros/gaia-page">
+<html metal:use-macro="view/app_root/@@grokadminmacros/gaia-page">
<head>
<title>DocGrok page title</title>
</head>
Modified: grok/trunk/src/grok/admin/view_templates/docgrokpackageview.pt
===================================================================
--- grok/trunk/src/grok/admin/view_templates/docgrokpackageview.pt 2007-09-01 02:56:29 UTC (rev 79410)
+++ grok/trunk/src/grok/admin/view_templates/docgrokpackageview.pt 2007-09-01 03:24:21 UTC (rev 79411)
@@ -1,4 +1,4 @@
-<html metal:use-macro="view/app_root/@@macros/gaia-page">
+<html metal:use-macro="view/app_root/@@grokadminmacros/gaia-page">
<head>
<title>DocGrokPackage page title</title>
</head>
Modified: grok/trunk/src/grok/admin/view_templates/docgroktextfileview.pt
===================================================================
--- grok/trunk/src/grok/admin/view_templates/docgroktextfileview.pt 2007-09-01 02:56:29 UTC (rev 79410)
+++ grok/trunk/src/grok/admin/view_templates/docgroktextfileview.pt 2007-09-01 03:24:21 UTC (rev 79411)
@@ -1,4 +1,4 @@
-<html metal:use-macro="view/app_root/@@macros/gaia-page">
+<html metal:use-macro="view/app_root/@@grokadminmacros/gaia-page">
<head>
<title>DocGrok page title</title>
</head>
Modified: grok/trunk/src/grok/admin/view_templates/docgrokview.pt
===================================================================
--- grok/trunk/src/grok/admin/view_templates/docgrokview.pt 2007-09-01 02:56:29 UTC (rev 79410)
+++ grok/trunk/src/grok/admin/view_templates/docgrokview.pt 2007-09-01 03:24:21 UTC (rev 79411)
@@ -1,4 +1,4 @@
-<html metal:use-macro="view/app_root/@@macros/gaia-page">
+<html metal:use-macro="view/app_root/@@grokadminmacros/gaia-page">
<head>
<title>DocGrok page title</title>
</head>
Copied: grok/trunk/src/grok/admin/view_templates/grokadminmacros.pt (from rev 79403, Sandbox/ulif/grok-adminui-experimental/src/grok/admin/view_templates/grokadminmacros.pt)
===================================================================
--- grok/trunk/src/grok/admin/view_templates/grokadminmacros.pt (rev 0)
+++ grok/trunk/src/grok/admin/view_templates/grokadminmacros.pt 2007-09-01 03:24:21 UTC (rev 79411)
@@ -0,0 +1,107 @@
+<html xmlns="http://www.w3.org/1999/xhtml"
+ i18n:domain="zope"
+ metal:define-macro="gaia-page">
+ <head>
+ <title
+ metal:define-slot="title"
+ >grok administration interface</title>
+ <link metal:define-slot="header"
+ rel="stylesheet" type="text/css" href="static/grok.css"
+ tal:on-error="nothing"
+ tal:attributes="href view/static/grok.css" />
+ <metal:block define-slot="extrahead">
+ </metal:block>
+ </head>
+
+ <body>
+ <div tal:condition="not:exists: view/root_url">
+ This template (grokadminmacros.pt in grok.admin) must be called
+ from a view with defined root_url.
+ </div>
+ <div tal:condition="exists: view/root_url">
+ <div id="banner">
+ <a href="/" id="logo">
+ <img alt="Grok" src="images/grok-admin.jpg" height="40"
+ tal:attributes="src view/static/grok-admin.jpg" />
+ </a>
+ </div>
+
+ <div id="logout" metal:define-macro="logged_user">
+ <span tal:condition="view/is_authenticated">
+ <span i18n:translate="">User:
+ <span tal:replace="request/principal/title"
+ i18n:name="user_title">User</span>
+ </span>
+ </span>
+ </div>
+
+ <div id="breadcrumbs">
+ <div id="banner-shadow">
+
+ </div>
+ </div>
+ <div id="fireplace">
+ <img alt="grok_relax_image" src="images/grok-relax5.gif"
+ tal:attributes="src view/static/grok-relax5.gif" />
+ </div>
+ <div id="menu-links"
+ metal:define-slot="menu-links"
+ tal:define="currview python:view.url()">
+ <span class="menu-link-inactive"
+ tal:define="target string:${view/root_url}/applications">
+ <a href="applications"
+ tal:condition="python: target != currview"
+ tal:attributes="href target"
+ >Applications</a>
+ <span class="emph"
+ tal:condition="python: target == currview">
+ Applications
+ </span>
+ </span>
+
+ <span class="menu-link-inactive"
+ tal:define="target string:${view/root_url}/server"
+ >
+ <a href="z3index"
+ tal:condition="python: target != currview"
+ tal:attributes="href target"
+ >Server Control</a>
+ <span class="emph"
+ tal:condition="python: target == currview">
+ Server Control
+ </span>
+ </span>
+<!--
+
+ <a href=""
+ tal:attributes="href view/root_url">Debug</a>
+-->
+
+ <a href=""
+ tal:attributes="href string:${view/root_url}/docgrok/">
+ <span tal:attributes="class python:view.in_docgrok() and 'emph'"
+ >Documentation</span>
+ </a>
+ </div>
+
+ <div id="content">
+
+ <div id="messages" tal:content="structure context/@@messages" />
+
+ <div metal:define-slot="content">
+
+ <h1>Welcome to Grok!</h1>
+
+ <div>
+ Your friendly and easy way to Zope 3.
+ </div>
+
+ </div>
+ <div>
+ <p id="footer-copyright">© Copyright 2007, The Zope Foundation<br />Design inspired by Sebastian Ware</p>
+ </div>
+ </div>
+
+ </div>
+ </body>
+</html>
Modified: grok/trunk/src/grok/admin/view_templates/index.pt
===================================================================
--- grok/trunk/src/grok/admin/view_templates/index.pt 2007-09-01 02:56:29 UTC (rev 79410)
+++ grok/trunk/src/grok/admin/view_templates/index.pt 2007-09-01 03:24:21 UTC (rev 79411)
@@ -1,4 +1,4 @@
-<html metal:use-macro="context/@@macros/gaia-page">
+<html metal:use-macro="context/@@grokadminmacros/gaia-page">
<div metal:fill-slot="content">
<h1></h1>
<div class="logo">
Modified: grok/trunk/src/grok/admin/view_templates/inspect.pt
===================================================================
--- grok/trunk/src/grok/admin/view_templates/inspect.pt 2007-09-01 02:56:29 UTC (rev 79410)
+++ grok/trunk/src/grok/admin/view_templates/inspect.pt 2007-09-01 03:24:21 UTC (rev 79411)
@@ -1,4 +1,4 @@
-<html metal:use-macro="context/@@macros/gaia-page">
+<html metal:use-macro="context/@@grokadminmacros/gaia-page">
<div metal:fill-slot="content">
<h1>
<span tal:content="view/info/name" />
Deleted: grok/trunk/src/grok/admin/view_templates/macros.pt
===================================================================
--- grok/trunk/src/grok/admin/view_templates/macros.pt 2007-09-01 02:56:29 UTC (rev 79410)
+++ grok/trunk/src/grok/admin/view_templates/macros.pt 2007-09-01 03:24:21 UTC (rev 79411)
@@ -1,102 +0,0 @@
-<html xmlns="http://www.w3.org/1999/xhtml"
- i18n:domain="zope"
- metal:define-macro="gaia-page">
- <head>
- <title
- metal:define-slot="title"
- >grok administration interface</title>
- <link metal:define-slot="header"
- rel="stylesheet" type="text/css" href="static/grok.css"
- tal:attributes="href view/static/grok.css" />
- <metal:block define-slot="extrahead">
- </metal:block>
- </head>
-
- <body>
- <div>
- <div id="banner">
- <a href="/" id="logo">
- <img alt="Grok" src="images/grok-admin.jpg" height="40"
- tal:attributes="src view/static/grok-admin.jpg" />
- </a>
- </div>
-
- <div id="logout" metal:define-macro="logged_user">
- <span tal:condition="view/is_authenticated">
- <span i18n:translate="">User:
- <span tal:replace="request/principal/title"
- i18n:name="user_title">User</span>
- </span>
- </span>
- </div>
-
- <div id="breadcrumbs">
- <div id="banner-shadow">
-
- </div>
- </div>
- <div id="fireplace">
- <img alt="grok_relax_image" src="images/grok-relax5.gif"
- tal:attributes="src view/static/grok-relax5.gif" />
- </div>
- <div id="menu-links"
- metal:define-slot="menu-links"
- tal:define="currview python:view.url()">
- <span class="menu-link-inactive"
- tal:define="target string:${view/root_url}/applications">
- <a href="applications"
- tal:condition="python: target != currview"
- tal:attributes="href target"
- >Applications</a>
- <span class="emph"
- tal:condition="python: target == currview">
- Applications
- </span>
- </span>
-
- <span class="menu-link-inactive"
- tal:define="target string:${view/root_url}/server"
- >
- <a href="z3index"
- tal:condition="python: target != currview"
- tal:attributes="href target"
- >Server Control</a>
- <span class="emph"
- tal:condition="python: target == currview">
- Server Control
- </span>
- </span>
-<!--
-
- <a href=""
- tal:attributes="href view/root_url">Debug</a>
--->
-
- <a href=""
- tal:attributes="href string:${view/root_url}/docgrok/">
- <span tal:attributes="class python:view.in_docgrok() and 'emph'"
- >Documentation</span>
- </a>
- </div>
-
- <div id="content">
-
- <div id="messages" tal:content="structure context/@@messages" />
-
- <div metal:define-slot="content">
-
- <h1>Welcome to Grok!</h1>
-
- <div>
- Your friendly and easy way to Zope 3.
- </div>
-
- </div>
- <div>
- <p id="footer-copyright">© Copyright 2007, The Zope Foundation<br />Design inspired by Sebastian Ware</p>
- </div>
- </div>
-
- </div>
- </body>
-</html>
Modified: grok/trunk/src/grok/admin/view_templates/server.pt
===================================================================
--- grok/trunk/src/grok/admin/view_templates/server.pt 2007-09-01 02:56:29 UTC (rev 79410)
+++ grok/trunk/src/grok/admin/view_templates/server.pt 2007-09-01 03:24:21 UTC (rev 79411)
@@ -1,4 +1,4 @@
-<html metal:use-macro="context/@@macros/gaia-page">
+<html metal:use-macro="context/@@grokadminmacros/gaia-page">
<div metal:fill-slot="content">
<h1>Manage your Zope 3 instance</h1>
Copied: grok/trunk/src/grok/ftests/admin/apackage (from rev 79403, Sandbox/ulif/grok-adminui-experimental/src/grok/ftests/admin/apackage)
Modified: grok/trunk/src/grok/ftests/admin/apps.py
===================================================================
--- grok/trunk/src/grok/ftests/admin/apps.py 2007-09-01 02:56:29 UTC (rev 79410)
+++ grok/trunk/src/grok/ftests/admin/apps.py 2007-09-01 03:24:21 UTC (rev 79411)
@@ -33,26 +33,22 @@
>>> print browser.contents
<html xmlns="http://www.w3.org/1999/xhtml">
...
- ... <p ...>Currently no applications are installed.</p>
+ ... <p ...>Currently no working...applications are installed.</p>
...
We are able to add a mammoth manager...
- >>> browser.getControl('Name your new app:', index=1).value = 'my-mammoth-manager'
- >>> browser.getControl('Create', index=1).click()
+ >>> subform = browser.getForm(name='MammothManager')
+ >>> subform.getControl('Name your new app:').value = 'my-mammoth-manager'
+ >>> subform.getControl('Create').click()
>>> print browser.contents
<html xmlns="http://www.w3.org/1999/xhtml">
...
- ... <legend>Installed applications</legend>
- ... <input type="checkbox" class="checkbox" name="items"
- value="my-mammoth-manager" />
- <a href="http://localhost/my-mammoth-manager">
- my-mammoth-manager
- (MammothManager)
- </a>
- ... <legend>Add application</legend>
+ ...<legend>Installed applications</legend>
...
+ ...<a href="http://localhost/my-mammoth-manager">
+ ...
Launch the added mammoth manager
@@ -87,7 +83,7 @@
>>> print browser.contents
<html xmlns="http://www.w3.org/1999/xhtml">
...
- ... <p ...>Currently no applications are installed.</p>
+ ... <p ...>Currently no working applications...are installed.</p>
...
...<legend>Add application</legend>
...
Copied: grok/trunk/src/grok/ftests/admin/brokenobjs.py (from rev 79403, Sandbox/ulif/grok-adminui-experimental/src/grok/ftests/admin/brokenobjs.py)
===================================================================
--- grok/trunk/src/grok/ftests/admin/brokenobjs.py (rev 0)
+++ grok/trunk/src/grok/ftests/admin/brokenobjs.py 2007-09-01 03:24:21 UTC (rev 79411)
@@ -0,0 +1,85 @@
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+"""
+
+The admin-UI now supports detection and deletion of broken objects. It
+is still limited to IApplication objects in the root folder. Options
+to repair broken objects are also still missing.
+
+We first setup the environment:
+
+ >>> from zope.testbrowser.testing import Browser
+ >>> browser = Browser()
+ >>> browser.addHeader('Authorization', 'Basic mgr:mgrpw')
+
+If no broken applications are in the root, everything should look as
+usual:
+
+ >>> browser.open('http://localhost/applications')
+ >>> 'Broken applications:' not in browser.contents
+ True
+
+Now we grok this module, to have a new application type available,
+which is intentionally broken:
+
+ >>> browser.open('http://localhost/applications')
+ >>> 'PseudoBroken' in browser.contents
+ True
+
+We add an instance of that new type:
+
+ >>> subform = browser.getForm(name='PseudoBroken')
+ >>> subform
+ <zope.testbrowser.browser.Form object at 0x...>
+
+ >>> subform.getControl('Name your new app').value = 'mybrokenobj'
+ >>> subform.getControl('Create').click()
+
+and the broken object should show up in the applications list:
+
+ >>> print browser.contents
+ <html xmlns="http://www.w3.org/1999/xhtml">
+ ...
+ ...Currently no working applications are...installed...
+ ...
+ ...Broken applications:...
+ ...
+ ...(broken type: grok.ftests.admin.brokenobjs.PseudoBroken)...
+ ...This application is broken!...
+ ...
+
+If we want to delete the broken object, we can do so:
+
+ >>> ctrl = browser.getControl(name='items')
+ >>> ctrl.getControl(value='mybrokenobj').selected = True
+ >>> browser.getControl('Delete Selected').click()
+ >>> print browser.contents
+ <html xmlns="http://www.w3.org/1999/xhtml">
+ ...
+ ...Application `mybrokenobj` was successfully deleted.
+ ...
+
+and the 'Broken applications' section won't show up anymore:
+
+ >>> 'Broken applications:' not in browser.contents
+ True
+
+
+"""
+import grok
+from ZODB.broken import Broken
+class PseudoBroken(grok.Application, grok.Container, Broken):
+ """A class intentionally broken.
+ """
+ pass
Copied: grok/trunk/src/grok/ftests/admin/docgrok.py (from rev 79403, Sandbox/ulif/grok-adminui-experimental/src/grok/ftests/admin/docgrok.py)
===================================================================
--- grok/trunk/src/grok/ftests/admin/docgrok.py (rev 0)
+++ grok/trunk/src/grok/ftests/admin/docgrok.py 2007-09-01 03:24:21 UTC (rev 79411)
@@ -0,0 +1,105 @@
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+"""
+=================================
+DocGrok: a class browser for Grok
+=================================
+
+DocGrok offers an extensible class browser for packages, modules,
+classes and similar things. To use it in your own application see
+``docgrok.txt`` in the ``grok.admin`` package.
+
+Here only the functionality as a class browser for the admin-UI is
+covered.
+
+Overview page
+-------------
+
+When we go to the documentation section, we should get an overview:
+
+ >>> from zope.testbrowser.testing import Browser
+ >>> browser = Browser()
+ >>> browser.addHeader('Authorization', 'Basic mgr:mgrpw')
+ >>> browser.open('http://localhost/')
+ >>> browser.getLink('Documentation').click()
+ >>> print browser.contents
+ <html xmlns="http://www.w3.org/1999/xhtml">
+ ... Welcome to DocGrok...
+
+The overview offers us direct links to the zope package,
+
+ >>> link = browser.getLink('browse the zope package')
+ >>> link
+ <Link text='browse the zope package' url='http://localhost/docgrok/zope'>
+
+the grok package,
+
+ >>> link = browser.getLink('browse the grok package')
+ >>> link
+ <Link text='browse the grok package' url='http://localhost/docgrok/grok'>
+
+and a link to the internal object browser, which is different from the
+class browser, and shows the ZODB root:
+
+ >>> link = browser.getLink('ZODB root folder')
+ >>> link
+ <Link text='ZODB root folder' url='http://localhost/@@inspect.html'>
+
+There are several things, that can be displayed by the class
+browser. We start with packages.
+
+
+DocGrok for packages
+--------------------
+
+We placed a package in the ``apackage`` directory. Let's try to fetch
+documentation for it. We form a URL string, that contains the
+package's dotted name with dots replaced by slashes:
+
+ >>> pkg_dotted_name = __name__.rsplit('.',1)[0]
+ >>> url_path = 'http://localhost/docgrok/%s/apackage' % (
+ ... pkg_dotted_name.replace('.', '/'))
+ >>> browser.open(url_path)
+
+Is it the documentation of the ``apackage`` package?
+
+ >>> print browser.contents
+ <html xmlns="http://www.w3.org/1999/xhtml">
+ ...
+ ...<span><a ...>.apackage</a></span>...
+ ...
+ ...(Python Package)...
+ ...
+
+Okay. In the page top we should have links to the various parent
+packages contained in the dotted name of the examined package:
+
+ >>> browser.getLink('grok')
+ <Link text='grok' url='http://localhost/docgrok/grok'>
+
+ >>> browser.getLink('ftests')
+ <Link text='.ftests' url='http://localhost/docgrok/grok/ftests'>
+
+and so on.
+
+
+DocGrok for modules
+-------------------
+
+DocGrok for classes
+-------------------
+
+
+
+"""
Copied: grok/trunk/src/grok/ftests/admin/macros.py (from rev 79403, Sandbox/ulif/grok-adminui-experimental/src/grok/ftests/admin/macros.py)
===================================================================
--- grok/trunk/src/grok/ftests/admin/macros.py (rev 0)
+++ grok/trunk/src/grok/ftests/admin/macros.py 2007-09-01 03:24:21 UTC (rev 79411)
@@ -0,0 +1,68 @@
+##############################################################################
+#
+# 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/gaia-page">
+</html>
+""")
+
Modified: grok/trunk/src/grok/ftests/admin/objectbrowser.py
===================================================================
--- grok/trunk/src/grok/ftests/admin/objectbrowser.py 2007-09-01 02:56:29 UTC (rev 79410)
+++ grok/trunk/src/grok/ftests/admin/objectbrowser.py 2007-09-01 03:24:21 UTC (rev 79411)
@@ -134,14 +134,3 @@
"""
-
-import grok
-
-class MammothManager(grok.Application, grok.Container):
- """A mammoth manager"""
- pass
-
-class Index(grok.View):#
-
- def render(self):
- return u"Let's manage some mammoths!"
More information about the Checkins
mailing list