[Checkins] SVN: Sandbox/ulif/grok-adminui/src/grok/ Moved ftests back to grok due to register problems. Added support for browsing class methods.

Uli Fouquet uli at gnufix.de
Mon Jul 16 10:15:27 EDT 2007


Log message for revision 78030:
  Moved ftests back to grok due to register problems. Added support for browsing class methods.

Changed:
  U   Sandbox/ulif/grok-adminui/src/grok/admin/docgrok.py
  U   Sandbox/ulif/grok-adminui/src/grok/admin/docgrok.txt
  D   Sandbox/ulif/grok-adminui/src/grok/admin/ftests/
  U   Sandbox/ulif/grok-adminui/src/grok/admin/view.py
  U   Sandbox/ulif/grok-adminui/src/grok/admin/view_templates/docgrokclassview.pt
  A   Sandbox/ulif/grok-adminui/src/grok/ftests/admin/
  A   Sandbox/ulif/grok-adminui/src/grok/ftests/admin/__init__.py
  A   Sandbox/ulif/grok-adminui/src/grok/ftests/admin/apps.py
  U   Sandbox/ulif/grok-adminui/src/grok/ftests/test_grok_functional.py

-=-
Modified: Sandbox/ulif/grok-adminui/src/grok/admin/docgrok.py
===================================================================
--- Sandbox/ulif/grok-adminui/src/grok/admin/docgrok.py	2007-07-16 13:35:09 UTC (rev 78029)
+++ Sandbox/ulif/grok-adminui/src/grok/admin/docgrok.py	2007-07-16 14:15:26 UTC (rev 78030)
@@ -12,6 +12,7 @@
 from zope.dottedname.resolve import resolve
 from zope.interface.interface import InterfaceClass
 from zope.security.proxy import isinstance
+from zope.security.proxy import removeSecurityProxy
 from zope.proxy import removeAllProxies
 
 import os
@@ -30,6 +31,7 @@
 from zope.app.apidoc.codemodule.class_ import Class
 from zope.app.apidoc.codemodule.text import TextFile
 from zope.app.apidoc.utilities import renderText
+from zope.app.apidoc.utilities import getFunctionSignature
 
 grok.context(IRootFolder)
 grok.define_permission('grok.ManageApplications')
@@ -139,7 +141,10 @@
             ob = resolve(dotted_path)
         except ImportError:
             None
-    if not IApplication.implementedBy( ob ):
+    try:
+        if not IApplication.implementedBy( ob ):
+            return None
+    except TypeError:
         return None
     return DocGrokGrokApplication(dotted_path)
 
@@ -192,6 +197,16 @@
         return doc_grok
     return DocGrok(dotted_path)
 
+def getInterfaceInfo(iface):
+    from zope.app.apidoc.utilities import getPythonPath
+    from zope.app.apidoc.utilities import isReferencable
+    if iface is None:
+        return None
+    path = getPythonPath(iface)
+    return {'path': path,
+            'url': isReferencable(path) and path or None}
+
+
 class DocGrokGrokker(InstanceGrokker):
     """A grokker that groks DocGroks.
 
@@ -503,7 +518,7 @@
         mod_apidoc = Module( None, None, self.module, False)
         self.apidoc = Class( mod_apidoc, self.name, self.klass)
 
-    def getFilePath( self ):
+    def getFilePath(self):
         if not hasattr( self.module, "__file__" ):
             return None
         filename = self.module.__file__
@@ -511,6 +526,56 @@
             filename = filename[:-1]
         return filename
 
+    def getMethods(self):
+        """Get all methods of this class."""
+        from zope.app.apidoc.utilities import getPythonPath, getPermissionIds
+        methods = []
+        # remove the security proxy, so that `attr` is not proxied. We could
+        # unproxy `attr` for each turn, but that would be less efficient.
+        #
+        # `getPermissionIds()` also expects the class's security checker not
+        # to be proxied.
+        klass = removeSecurityProxy(self.apidoc)
+        #klass = resolve(context.path)
+        for name, attr, iface in klass.getMethodDescriptors():
+            entry = {'name': name,
+                     'signature': "(...)",
+                     'doc':attr.__doc__ or '',
+                     'attr' : attr,
+                     'interface' : iface}
+            entry.update(getPermissionIds(name, klass.getSecurityChecker()))
+            methods.append(entry)
+
+        for name, attr, iface in klass.getMethods():
+            entry = {'name': name,
+                     'signature': getFunctionSignature(attr),
+                     'doc':attr.__doc__ or '',
+                     'attr' : attr,
+                     'interface' : iface}
+            entry.update(getPermissionIds(name, klass.getSecurityChecker()))
+            methods.append(entry)
+        return methods
+            
+        for name, attr, iface in klass.getMethodDescriptors():
+            entry = {'name': name,
+                     'signature': "(...)",
+                     'doc': renderText(attr.__doc__ or '',
+                                       inspect.getmodule(attr)),
+                     'interface': getInterfaceInfo(iface)}
+            entry.update(getPermissionIds(name, klass.getSecurityChecker()))
+            methods.append(entry)
+
+        for name, attr, iface in klass.getMethods():
+            entry = {'name': name,
+                     'signature': getFunctionSignature(attr),
+                     'doc': renderText(attr.__doc__ or '',
+                                       inspect.getmodule(attr)),
+                     'interface': getInterfaceInfo(iface)}
+            entry.update(getPermissionIds(name, klass.getSecurityChecker()))
+            methods.append(entry)
+        return methods
+
+
 class DocGrokInterface(DocGrokClass):
     """This doctor cares for interfaces.
     """

Modified: Sandbox/ulif/grok-adminui/src/grok/admin/docgrok.txt
===================================================================
--- Sandbox/ulif/grok-adminui/src/grok/admin/docgrok.txt	2007-07-16 13:35:09 UTC (rev 78029)
+++ Sandbox/ulif/grok-adminui/src/grok/admin/docgrok.txt	2007-07-16 14:15:26 UTC (rev 78030)
@@ -8,9 +8,16 @@
 apidoc feature. It should be easy to handle and informative in
 content. Main target are developers new to Grok.
 
-DocGrok is there to generate documentation for nearly everything
-living in a running Zope 3 instance.
+DocGrok is a helper to generate documentation for nearly everything
+living in a running Zope 3 instance. Basically it provides
+'information'-objects for different types of things, like modules,
+classes, functions, textfiles etc. 
 
+A ``DocGrok`` therefore is an object wich normally is bound to a
+certain entity, which is describable by a dotted path. It provides
+special methods to get information about the thing, a certain
+``DocGrok`` is bound to.
+
 .. contents::
 
 
@@ -36,7 +43,14 @@
 
     http://localhost:8080/docgrok/grok/admin
 
+In this way nearly all things can be described, which can be described
+by a dotted name notation and which are accessible at runtime. Also
+normal Python elements can be examined, say, the ``os.path`` package
 
+    http://localhost:8080/docgrok/os/path
+
+and many more.
+
 Calling the doctor directly
 +++++++++++++++++++++++++++
 

Modified: Sandbox/ulif/grok-adminui/src/grok/admin/view.py
===================================================================
--- Sandbox/ulif/grok-adminui/src/grok/admin/view.py	2007-07-16 13:35:09 UTC (rev 78029)
+++ Sandbox/ulif/grok-adminui/src/grok/admin/view.py	2007-07-16 14:15:26 UTC (rev 78030)
@@ -438,6 +438,21 @@
         return self._listClasses(
           [iface for iface in self.context.apidoc.getInterfaces()])
 
+    def getMethods(self):
+        import inspect
+        methods = self.context.getMethods()
+        for m in methods:
+            m['doc'] = self.getDoc(m['doc'])
+            m['doc'] = renderText(m['attr'].__doc__ or '',
+                                  inspect.getmodule(m['attr']))
+            m['interface'] = self._listClasses([m['interface']])
+            pass
+        return methods
+        return self.context.getMethods()
+
+    def getMethodDescriptors(self):
+        return self.context.apidoc.getMethodDescriptors()
+
     def _listClasses(self, classes):
         info = []
         for cls in classes:

Modified: Sandbox/ulif/grok-adminui/src/grok/admin/view_templates/docgrokclassview.pt
===================================================================
--- Sandbox/ulif/grok-adminui/src/grok/admin/view_templates/docgrokclassview.pt	2007-07-16 13:35:09 UTC (rev 78029)
+++ Sandbox/ulif/grok-adminui/src/grok/admin/view_templates/docgrokclassview.pt	2007-07-16 14:15:26 UTC (rev 78030)
@@ -82,6 +82,10 @@
 
 	<h2>Interfaces</h2>
 
+	<div class="docgrok-annotation1">
+	  This class implements the following interfaces:
+	</div>
+
 	<div class="docgrok-entry" tal:repeat="item view/getInterfaces">
 	  interface
 	  <span class="docgrok-pathvalue">
@@ -114,10 +118,6 @@
 	  </div>
 	</div>
 
-	<div tal:repeat="iface view/getInterfaces">
-	  <div tal:content="python: str(iface)">asd</div>
-	</div>
-<!--
 	<h2>Functions:</h2>
 
 	<div class="docgrok-entry" tal:repeat="item view/getEntries">
@@ -139,66 +139,76 @@
 	      Use <span class="docgrok-pycode1">from <span
 	      tal:replace="context/path">x</span> import <span
 	      tal:replace="item/name">y</span></span> to make the
-	      functionality of this class available in your application
+	      functionality of this function available in your application
 	      or component.
 	    </div>
 	  </div>
 	</div>
 
-	<h2>Interfaces:</h2>
-
-	<div class="docgrok-entry" tal:repeat="item view/getEntries">
-	  <div tal:condition="item/isinterface">
+	<h2>Methods:</h2>
+	<div class="docgrok-entry" tal:repeat="item view/getMethods">
+	  <div class="docgrok-description1">
 	    <div class="docgrok-pathvalue">
-	      interface
-	      <a href=""
-		 tal:attributes="href string:${view/root_url}/docgrok/${item/url}" 
-		 tal:content="item/name">
-		InterfaceName
-	      </a>
+	      <span tal:content="item/name">methodname</span><span tal:content="item/signature">(signature)</span>
 	    </div>
-	    <div class="docgrok-annotation2"
-		 tal:condition="item/doc"
-		 tal:content="structure item/doc">
+	  </div>
+	  <div class="docgrok-annotation2"
+	       tal:condition="item/doc"
+	       tal:content="structure item/doc">
+	    Doc
+	  </div>
+	  <div class="docgrok-annotation2">
+	    <div class="docgrok-entry" tal:repeat="iface item/interface">
+	      <span class="docgrok-description2">interface:</span>
+	      <span class="docgrok-pathvalue">
+		<a href=""
+		   tal:attributes="href string:${view/root_url}/docgrok/${iface/url}" 
+		   tal:content="iface/name">
+		  ClassName
+		</a>
+	      </span>
+	      in
+	      <span class="docgrok-pathvalue">
+		<a href=""
+		   tal:repeat="part iface/path_parts"
+		   tal:attributes="href string:${view/root_url}${part/url}">
+		  
+		  <span tal:replace="part/name" />
+		</a>
+	      </span>
+	      <div class="docgrok-annotation2"
+		   tal:condition="iface/doc"
+		   tal:content="structure iface/doc">
+	      </div>
+	      <div class="docgrok-annotation2"
+		   tal:condition="not: iface/doc">
+		Use <span class="docgrok-pycode1">from <span
+		tal:replace="iface/path">x</span> import <span
+		tal:replace="iface/name">y</span></span> to make the
+		functionality of this class available in your application
+		or component.
+	      </div>
 	    </div>
-	    <div class="docgrok-annotation2"
-		 tal:condition="not: item/doc">
-	      Use <span class="docgrok-pycode1">from <span
-	      tal:replace="context/path">x</span> import <span
-	      tal:replace="item/name">y</span></span> to make this
-	      interface definition available in your application
-	      or component.
-	    </div>
+	    
 	  </div>
-	</div>
 
-	<h2>Classes:</h2>
 
-	<div class="docgrok-entry" tal:repeat="item view/getEntries">
-	  <div tal:condition="item/isclass">
-	    <div class="docgrok-pathvalue">
-	      class
-	      <a href=""
-		 tal:attributes="href string:${view/root_url}/docgrok/${item/url}" 
-		 tal:content="item/name">
-		ClassName
-	      </a>
+	  <div class="docgrok-annotation2">
+	    <span class="docgrok-description2">permissions:</span>
+	    <div class="docgrok-annotation2">
+	      read: 
+	      <span tal:content="item/read_perm">None</span>
 	    </div>
-	    <div class="docgrok-annotation2"
-		 tal:condition="item/doc"
-		 tal:content="structure item/doc">
+	    <div class="docgrok-annotation2">
+	      write: 
+	      <span tal:content="item/write_perm">None</span>
 	    </div>
-	    <div class="docgrok-annotation2"
-		 tal:condition="not: item/doc">
-	      Use <span class="docgrok-pycode1">from <span
-	      tal:replace="context/path">x</span> import <span
-	      tal:replace="item/name">y</span></span> to make the
-	      functionality of this class available in your application
-	      or component.
-	    </div>
 	  </div>
+
+
 	</div>
--->
+
+
       </div>
 
     </div>

Added: Sandbox/ulif/grok-adminui/src/grok/ftests/admin/__init__.py
===================================================================
--- Sandbox/ulif/grok-adminui/src/grok/ftests/admin/__init__.py	                        (rev 0)
+++ Sandbox/ulif/grok-adminui/src/grok/ftests/admin/__init__.py	2007-07-16 14:15:26 UTC (rev 78030)
@@ -0,0 +1,2 @@
+# this is a package
+

Added: Sandbox/ulif/grok-adminui/src/grok/ftests/admin/apps.py
===================================================================
--- Sandbox/ulif/grok-adminui/src/grok/ftests/admin/apps.py	                        (rev 0)
+++ Sandbox/ulif/grok-adminui/src/grok/ftests/admin/apps.py	2007-07-16 14:15:26 UTC (rev 78030)
@@ -0,0 +1,75 @@
+"""
+  
+We fetch the standard page, which should provide us a menu to get all
+installable grok applications/components.
+
+  >>> import grok
+  >>> grok.grok('grok.ftests.admin.apps')
+
+  >>> from zope.testbrowser.testing import Browser
+  >>> browser = Browser()
+  >>> browser.addHeader('Authorization', 'Basic mgr:mgrpw')
+  >>> browser.handleErrors = False
+  >>> browser.open("http://localhost/")
+  >>> print browser.contents
+  <html xmlns="http://www.w3.org/1999/xhtml">
+  ...
+  ...      <legend>Add application</legend>
+  ...
+
+We are able to add a mammoth manager...
+
+  >>> browser.getControl('Name your new app:',index=13).value = 'my-mammoth-manager'
+  >>> browser.getControl('Create',index=13).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>
+  ...
+
+Launch the added mammoth manager
+
+  >>> mylink = browser.getLink('my-mammoth-manager (MammothManager)').click()
+  >>> print browser.contents
+  Let's manage some mammoths!
+
+  >>> print browser.url
+  http://localhost/my-mammoth-manager
+
+We are able to delete installed mammoth-managers
+
+  >>> browser.open("http://localhost/")
+  >>> print browser.contents
+  <html xmlns="http://www.w3.org/1999/xhtml">
+  ...
+  ... <legend>Installed applications</legend>
+  ...
+  >>> ctrl = browser.getControl(name='items')
+  >>> ctrl.getControl(value='my-mammoth-manager').selected = True
+  >>> browser.getControl('Delete Selected').click()
+  >>> print browser.contents
+  <html xmlns="http://www.w3.org/1999/xhtml">
+  ...
+  ...<legend>Add application</legend>
+  ...
+
+"""
+
+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!"

Modified: Sandbox/ulif/grok-adminui/src/grok/ftests/test_grok_functional.py
===================================================================
--- Sandbox/ulif/grok-adminui/src/grok/ftests/test_grok_functional.py	2007-07-16 13:35:09 UTC (rev 78029)
+++ Sandbox/ulif/grok-adminui/src/grok/ftests/test_grok_functional.py	2007-07-16 14:15:26 UTC (rev 78030)
@@ -43,7 +43,7 @@
 def test_suite():
     suite = unittest.TestSuite()
     for name in ['view', 'static', 'xmlrpc', 'traversal', 'form', 'url',
-                 'security', 'utility', 'catalog']:
+                 'security', 'utility', 'catalog','admin']:
         suite.addTest(suiteFromPackage(name))
     return suite
 



More information about the Checkins mailing list