[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