[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>
 	  &nbsp;&nbsp;
 	  [<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">
+          &nbsp;
+        </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>
+        &nbsp;&nbsp;
+        <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>
+<!--
+        &nbsp;&nbsp;
+        <a href=""
+          tal:attributes="href view/root_url">Debug</a>
+-->
+        &nbsp;&nbsp;
+        <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">&copy; 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">
-          &nbsp;
-        </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>
-        &nbsp;&nbsp;
-        <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>
-<!--
-        &nbsp;&nbsp;
-        <a href=""
-          tal:attributes="href view/root_url">Debug</a>
--->
-        &nbsp;&nbsp;
-        <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">&copy; 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