[Zope3-checkins] SVN: Zope3/trunk/src/zope/app/apidoc/ - Created
APIDOC skin, since I wanted to override existing views.
Stephan Richter
srichter at cosmos.phy.tufts.edu
Mon Oct 31 00:16:33 EST 2005
Log message for revision 39760:
- Created APIDOC skin, since I wanted to override existing views.
- Created custom not found view.
- Fixed up apidoc code to cause less failures during static apidoc
generation.
- Improved reporting and debugging capabilities in the static apidoc
generator.
- The static apidoc generator now will store error pages as well.
Changed:
U Zope3/trunk/src/zope/app/apidoc/apidoc.py
U Zope3/trunk/src/zope/app/apidoc/bookmodule/configure.zcml
U Zope3/trunk/src/zope/app/apidoc/bookmodule/metadirectives.py
A Zope3/trunk/src/zope/app/apidoc/browser/README.txt
U Zope3/trunk/src/zope/app/apidoc/browser/configure.zcml
U Zope3/trunk/src/zope/app/apidoc/browser/ftests.py
A Zope3/trunk/src/zope/app/apidoc/browser/notfound.pt
A Zope3/trunk/src/zope/app/apidoc/browser/skin.py
U Zope3/trunk/src/zope/app/apidoc/classregistry.py
U Zope3/trunk/src/zope/app/apidoc/codemodule/README.txt
U Zope3/trunk/src/zope/app/apidoc/codemodule/browser/README.txt
U Zope3/trunk/src/zope/app/apidoc/codemodule/browser/class_.py
U Zope3/trunk/src/zope/app/apidoc/codemodule/browser/class_index.pt
U Zope3/trunk/src/zope/app/apidoc/codemodule/browser/configure.zcml
U Zope3/trunk/src/zope/app/apidoc/codemodule/browser/introspector.pt
U Zope3/trunk/src/zope/app/apidoc/codemodule/browser/introspector.py
U Zope3/trunk/src/zope/app/apidoc/codemodule/browser/module.py
U Zope3/trunk/src/zope/app/apidoc/codemodule/browser/module_index.pt
U Zope3/trunk/src/zope/app/apidoc/codemodule/browser/textfile_index.pt
U Zope3/trunk/src/zope/app/apidoc/codemodule/browser/zcml.py
U Zope3/trunk/src/zope/app/apidoc/codemodule/class_.py
U Zope3/trunk/src/zope/app/apidoc/codemodule/interfaces.py
U Zope3/trunk/src/zope/app/apidoc/codemodule/module.py
U Zope3/trunk/src/zope/app/apidoc/codemodule/text.py
U Zope3/trunk/src/zope/app/apidoc/codemodule/zcml.py
U Zope3/trunk/src/zope/app/apidoc/component.py
U Zope3/trunk/src/zope/app/apidoc/component.txt
U Zope3/trunk/src/zope/app/apidoc/ifacemodule/browser.py
U Zope3/trunk/src/zope/app/apidoc/ifacemodule/component_macros.pt
U Zope3/trunk/src/zope/app/apidoc/ifacemodule/configure.zcml
U Zope3/trunk/src/zope/app/apidoc/interface.py
U Zope3/trunk/src/zope/app/apidoc/interface.txt
U Zope3/trunk/src/zope/app/apidoc/static.py
U Zope3/trunk/src/zope/app/apidoc/typemodule/configure.zcml
U Zope3/trunk/src/zope/app/apidoc/utilities.py
U Zope3/trunk/src/zope/app/apidoc/utilities.txt
U Zope3/trunk/src/zope/app/apidoc/utilitymodule/configure.zcml
U Zope3/trunk/src/zope/app/apidoc/utilitymodule/index.pt
U Zope3/trunk/src/zope/app/apidoc/zcmlmodule/configure.zcml
-=-
Modified: Zope3/trunk/src/zope/app/apidoc/apidoc.py
===================================================================
--- Zope3/trunk/src/zope/app/apidoc/apidoc.py 2005-10-31 05:03:42 UTC (rev 39759)
+++ Zope3/trunk/src/zope/app/apidoc/apidoc.py 2005-10-31 05:16:32 UTC (rev 39760)
@@ -13,7 +13,7 @@
##############################################################################
"""Zope 3 API Documentation
-$Id: __init__.py 26777 2004-07-27 08:12:32Z hdima $
+$Id$
"""
__docformat__ = 'restructuredtext'
@@ -22,6 +22,7 @@
from zope.app import zapi
from zope.app.location import locate
from zope.app.location.interfaces import ILocation
+from zope.app.publisher.browser import applySkin
from interfaces import IDocumentationModule
from utilities import ReadContainerBase
@@ -38,7 +39,7 @@
def __init__(self, parent, name):
self.__parent__ = parent
self.__name__ = name
-
+
def get(self, key, default=None):
"""See zope.app.container.interfaces.IReadContainer"""
utility = zapi.queryUtility(IDocumentationModule, key, default)
@@ -55,17 +56,19 @@
locate(value, self, key)
utils.append((key, value))
return utils
-
+
class apidocNamespace(object):
"""Used to traverse to an API Documentation."""
def __init__(self, ob, request=None):
+ if request:
+ from zope.app.apidoc.browser.skin import APIDOC
+ applySkin(request, APIDOC)
self.context = ob
-
+
def traverse(self, name, ignore):
return handleNamespace(self.context, name)
def handleNamespace(ob, name):
"""Used to traverse to an API Documentation."""
return APIDocumentation(ob, '++apidoc++'+name)
-
Modified: Zope3/trunk/src/zope/app/apidoc/bookmodule/configure.zcml
===================================================================
--- Zope3/trunk/src/zope/app/apidoc/bookmodule/configure.zcml 2005-10-31 05:03:42 UTC (rev 39759)
+++ Zope3/trunk/src/zope/app/apidoc/bookmodule/configure.zcml 2005-10-31 05:16:32 UTC (rev 39760)
@@ -23,14 +23,16 @@
class=".browser.Menu"
name="menu.html"
template="menu.pt"
+ layer="..browser.skin.apidoc"
/>
-
+
<browser:page
for=".book.IBookModule"
permission="zope.app.apidoc.UseAPIDoc"
class=".browser.Menu"
name="staticmenu.html"
template="static_menu.pt"
+ layer="..browser.skin.apidoc"
/>
<browser:page
@@ -39,6 +41,7 @@
class="zope.app.onlinehelp.browser.OnlineHelpTopicView"
name="show.html"
template="chapter.pt"
+ layer="..browser.skin.apidoc"
/>
<include file="book.zcml" />
Modified: Zope3/trunk/src/zope/app/apidoc/bookmodule/metadirectives.py
===================================================================
--- Zope3/trunk/src/zope/app/apidoc/bookmodule/metadirectives.py 2005-10-31 05:03:42 UTC (rev 39759)
+++ Zope3/trunk/src/zope/app/apidoc/bookmodule/metadirectives.py 2005-10-31 05:16:32 UTC (rev 39760)
@@ -47,10 +47,9 @@
resources = Tokens(
title=u"A list of resources.",
- description=u"""\
- A list of resources which shall be user for the chapter.
- The resources must be located in the same directory as
- the chapter.
+ description=u"""
+ A list of resources which shall be user for the chapter. The
+ resources must be located in the same directory as the chapter.
""",
value_type=TextLine(),
required=False
Added: Zope3/trunk/src/zope/app/apidoc/browser/README.txt
===================================================================
--- Zope3/trunk/src/zope/app/apidoc/browser/README.txt 2005-10-31 05:03:42 UTC (rev 39759)
+++ Zope3/trunk/src/zope/app/apidoc/browser/README.txt 2005-10-31 05:16:32 UTC (rev 39760)
@@ -0,0 +1,44 @@
+=====================
+Generic API Doc Views
+=====================
+
+Get a browser started:
+
+ >>> from zope.testbrowser import Browser
+ >>> browser = Browser()
+ >>> browser.addHeader('Authorization', 'Basic mgr:mgrpw')
+
+
+Not Found View
+--------------
+
+The `APIDOC` skin defines a custom not found view, since it fits the look and
+feel better and does not have all the O-wrap clutter:
+
+ >>> browser.open('http://localhost/++apidoc++/non-existent/')
+ Traceback (most recent call last):
+ ...
+ HTTPError: HTTP Error 404: Not Found
+
+ >>> from urllib2 import HTTPError
+ >>> try:
+ ... browser.open('http://localhost/++apidoc++/non-existent/')
+ ... except HTTPError, error:
+ ... pass
+
+ >>> print error.read()
+ Status: 404 Not Found
+ Content-Length: ...
+ Content-Type: text/html;charset=utf-8
+ ...
+ <h1 class="details-header">
+ Page Not Found
+ </h1>
+ <BLANKLINE>
+ <p>
+ While broken links occur occassionally, they are considered bugs. Please
+ report any broken link to
+ <a href="mailto:zope3-dev at zope.org">zope3-dev at zope.org</a>.
+ </p>
+ ...
+
Property changes on: Zope3/trunk/src/zope/app/apidoc/browser/README.txt
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: Zope3/trunk/src/zope/app/apidoc/browser/configure.zcml
===================================================================
--- Zope3/trunk/src/zope/app/apidoc/browser/configure.zcml 2005-10-31 05:03:42 UTC (rev 39759)
+++ Zope3/trunk/src/zope/app/apidoc/browser/configure.zcml 2005-10-31 05:16:32 UTC (rev 39760)
@@ -2,14 +2,26 @@
xmlns="http://namespaces.zope.org/browser"
i18n_domain="zope">
- <resource name="apidoc.css" file="apidoc.css" />
+ <layer
+ name="apidoc"
+ interface=".skin.apidoc" />
+ <skin
+ name="APIDOC"
+ interface=".skin.APIDOC" />
+
+ <resource
+ name="apidoc.css"
+ file="apidoc.css"
+ />
+
<page
for="*"
name="apidoc_macros"
permission="zope.View"
class=".macros.APIDocumentationMacros"
allowed_interface="zope.interface.common.mapping.IItemMapping"
+ layer=".skin.apidoc"
/>
<page
@@ -17,6 +29,7 @@
name="menu_macros"
permission="zope.View"
template="menu_macros.pt"
+ layer=".skin.apidoc"
/>
<page
@@ -24,6 +37,7 @@
name="static_menu_macros"
permission="zope.View"
template="static_menu_macros.pt"
+ layer=".skin.apidoc"
/>
<page
@@ -31,6 +45,7 @@
name="details_macros"
permission="zope.View"
template="details_macros.pt"
+ layer=".skin.apidoc"
/>
<resource
@@ -51,7 +66,8 @@
<pages
for="zope.app.apidoc.apidoc.APIDocumentation"
class=".apidoc.APIDocumentationView"
- permission="zope.app.apidoc.UseAPIDoc">
+ permission="zope.app.apidoc.UseAPIDoc"
+ layer=".skin.apidoc">
<page
name="index.html"
@@ -76,7 +92,8 @@
<pages
for="zope.app.apidoc.apidoc.APIDocumentation"
class=".apidoc.APIDocumentationView"
- permission="zope.app.apidoc.UseAPIDoc">
+ permission="zope.app.apidoc.UseAPIDoc"
+ layer=".skin.apidoc">
<page
name="static.html"
@@ -96,7 +113,17 @@
</pages>
+ <!-- Error Views -->
+ <page
+ for="zope.publisher.interfaces.INotFound"
+ name="index.html"
+ permission="zope.Public"
+ template="notfound.pt"
+ class="zope.app.exception.browser.notfound.NotFound"
+ layer=".skin.apidoc"
+ />
+
<!-- Preference Views -->
<page
@@ -105,6 +132,7 @@
class=".preference.APIDocPreferencesTree"
permission="zope.View"
attribute="apidocTree"
+ layer=".skin.apidoc"
/>
<page
@@ -112,6 +140,7 @@
permission="zope.Public"
name="apidocMenu.html"
template="prefmenu.pt"
+ layer=".skin.apidoc"
/>
<page
@@ -120,6 +149,7 @@
name="apidocIndex.html"
template="prefIndex.pt"
class="zope.app.preference.browser.EditPreferenceGroup"
+ layer=".skin.apidoc"
/>
</configure>
Modified: Zope3/trunk/src/zope/app/apidoc/browser/ftests.py
===================================================================
--- Zope3/trunk/src/zope/app/apidoc/browser/ftests.py 2005-10-31 05:03:42 UTC (rev 39759)
+++ Zope3/trunk/src/zope/app/apidoc/browser/ftests.py 2005-10-31 05:16:32 UTC (rev 39760)
@@ -16,7 +16,9 @@
$Id$
"""
import unittest
+from zope.testing import doctest
from zope.app.testing.functional import BrowserTestCase
+from zope.app.testing.functional import FunctionalDocFileSuite
class APIDocTests(BrowserTestCase):
"""Just a couple of tests ensuring that the templates render."""
@@ -63,6 +65,9 @@
def test_suite():
return unittest.TestSuite((
unittest.makeSuite(APIDocTests),
+ FunctionalDocFileSuite(
+ "README.txt",
+ optionflags=doctest.ELLIPSIS | doctest.NORMALIZE_WHITESPACE),
))
if __name__ == '__main__':
Added: Zope3/trunk/src/zope/app/apidoc/browser/notfound.pt
===================================================================
--- Zope3/trunk/src/zope/app/apidoc/browser/notfound.pt 2005-10-31 05:03:42 UTC (rev 39759)
+++ Zope3/trunk/src/zope/app/apidoc/browser/notfound.pt 2005-10-31 05:16:32 UTC (rev 39760)
@@ -0,0 +1,15 @@
+<html metal:use-macro="context/@@apidoc_macros/details" i18n:domain="zope">
+<body metal:fill-slot="contents">
+
+ <h1 class="details-header" >
+ Page Not Found
+ </h1>
+
+ <p>
+ While broken links occur occassionally, they are considered bugs. Please
+ report any broken link to
+ <a href="mailto:zope3-dev at zope.org">zope3-dev at zope.org</a>.
+ </p>
+
+</body>
+</html>
Property changes on: Zope3/trunk/src/zope/app/apidoc/browser/notfound.pt
___________________________________________________________________
Name: svn:eol-style
+ native
Added: Zope3/trunk/src/zope/app/apidoc/browser/skin.py
===================================================================
--- Zope3/trunk/src/zope/app/apidoc/browser/skin.py 2005-10-31 05:03:42 UTC (rev 39759)
+++ Zope3/trunk/src/zope/app/apidoc/browser/skin.py 2005-10-31 05:16:32 UTC (rev 39760)
@@ -0,0 +1,28 @@
+##############################################################################
+#
+# Copyright (c) 2004 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.
+#
+##############################################################################
+"""`APIdoc` skin.
+
+$Id$
+"""
+__docformat__ = "reStructuredText"
+
+from zope.publisher.interfaces.browser import IBrowserRequest
+from zope.publisher.interfaces.browser import IDefaultBrowserLayer
+
+class apidoc(IBrowserRequest):
+ """The `apidoc` layer."""
+
+class APIDOC(apidoc, IDefaultBrowserLayer):
+ """The `APIDOC` skin."""
+
Property changes on: Zope3/trunk/src/zope/app/apidoc/browser/skin.py
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: Zope3/trunk/src/zope/app/apidoc/classregistry.py
===================================================================
--- Zope3/trunk/src/zope/app/apidoc/classregistry.py 2005-10-31 05:03:42 UTC (rev 39759)
+++ Zope3/trunk/src/zope/app/apidoc/classregistry.py 2005-10-31 05:16:32 UTC (rev 39760)
@@ -20,7 +20,8 @@
__import_unknown_modules__ = False
# List of modules that should never be imported.
-IGNORE_MODULES = []
+# TODO: List hard-coded for now.
+IGNORE_MODULES = ['twisted']
import sys
Modified: Zope3/trunk/src/zope/app/apidoc/codemodule/README.txt
===================================================================
--- Zope3/trunk/src/zope/app/apidoc/codemodule/README.txt 2005-10-31 05:03:42 UTC (rev 39759)
+++ Zope3/trunk/src/zope/app/apidoc/codemodule/README.txt 2005-10-31 05:16:32 UTC (rev 39760)
@@ -7,7 +7,7 @@
>>> from zope.app.apidoc import codemodule
provides systematic and autogenerated documentation about the content of your
-Zope 3 related Python packages. The code module can be created like this:
+Zope 3 related Python packages. The code module can be created like this:
>>> cm = codemodule.codemodule.CodeModule()
Modified: Zope3/trunk/src/zope/app/apidoc/codemodule/browser/README.txt
===================================================================
--- Zope3/trunk/src/zope/app/apidoc/codemodule/browser/README.txt 2005-10-31 05:03:42 UTC (rev 39759)
+++ Zope3/trunk/src/zope/app/apidoc/codemodule/browser/README.txt 2005-10-31 05:16:32 UTC (rev 39760)
@@ -22,7 +22,7 @@
The module details are easily created, since we can just use the traversal
process to get a module documentation object:
- >>> details = browser.module.ModuleDetails()
+ >>> details = browser.module.ModuleDetails(None, None)
>>> details.context = zapi.traverse(cm,
... 'zope/app/apidoc/codemodule/codemodule')
>>> from zope.publisher.browser import TestRequest
@@ -51,6 +51,7 @@
'istextfile': False,
'iszcmlfile': False,
'name': 'CodeModule',
+ 'path': 'zope.app.apidoc.codemodule.class_.CodeModule',
'url': 'http://127.0.0.1/zope/app/apidoc/codemodule/codemodule/CodeModule'}]
`getBreadCrumbs()`
@@ -139,10 +140,14 @@
Get all implemented interfaces (as paths) of this class.
>>> pprint(details.getInterfaces())
- ['zope.app.apidoc.interfaces.IDocumentationModule',
- 'zope.app.location.interfaces.ILocation',
- 'zope.app.apidoc.codemodule.interfaces.IModuleDocumentation',
- 'zope.app.container.interfaces.IReadContainer']
+ [{'path': 'zope.app.apidoc.interfaces.IDocumentationModule',
+ 'url': 'zope.app.apidoc.interfaces.IDocumentationModule'},
+ {'path': 'zope.app.location.interfaces.ILocation',
+ 'url': 'zope.app.location.interfaces.ILocation'},
+ {'path': 'zope.app.apidoc.codemodule.interfaces.IModuleDocumentation',
+ 'url': 'zope.app.apidoc.codemodule.interfaces.IModuleDocumentation'},
+ {'path': 'zope.app.container.interfaces.IReadContainer',
+ 'url': 'zope.app.container.interfaces.IReadContainer'}]
`getAttributes()`
~~~~~~~~~~~~~~~~~
@@ -150,7 +155,8 @@
Get all attributes of this class.
>>> pprint(details.getAttributes()[1])
- {'interface': 'zope.app.apidoc.interfaces.IDocumentationModule',
+ {'interface': {'path': 'zope.app.apidoc.interfaces.IDocumentationModule',
+ 'url': 'zope.app.apidoc.interfaces.IDocumentationModule'},
'name': 'title',
'read_perm': None,
'type': 'Message',
@@ -170,7 +176,8 @@
'signature': '()',
'write_perm': None},
{'doc': u'',
- 'interface': 'zope.interface.common.mapping.IEnumerableMapping',
+ 'interface': {'path': 'zope.interface.common.mapping.IEnumerableMapping',
+ 'url': 'zope.interface.common.mapping.IEnumerableMapping'},
'name': 'values',
'read_perm': None,
'signature': '()',
Modified: Zope3/trunk/src/zope/app/apidoc/codemodule/browser/class_.py
===================================================================
--- Zope3/trunk/src/zope/app/apidoc/codemodule/browser/class_.py 2005-10-31 05:03:42 UTC (rev 39759)
+++ Zope3/trunk/src/zope/app/apidoc/codemodule/browser/class_.py 2005-10-31 05:16:32 UTC (rev 39760)
@@ -16,6 +16,8 @@
$Id: browser.py 29143 2005-02-14 22:43:16Z srichter $
"""
__docformat__ = 'restructuredtext'
+
+import inspect
import types
from zope.proxy import removeAllProxies
from zope.security.proxy import removeSecurityProxy
@@ -34,6 +36,13 @@
path = getPythonPath(type)
return isReferencable(path) and path.replace('.', '/') or None
+def getInterfaceInfo(iface):
+ if iface is None:
+ return None
+ path = getPythonPath(iface)
+ return {'path': path,
+ 'url': isReferencable(path) and path or None}
+
class ClassDetails(object):
"""Represents the details of the class."""
@@ -48,6 +57,7 @@
entries.sort(lambda x, y: cmp(x['path'], y['path']))
return entries
+
def _listClasses(self, classes):
"""Prepare a list of classes for presentation."""
info = []
@@ -59,13 +69,14 @@
# accessing __name__ and __module__.
unwrapped_cls = removeAllProxies(cls)
path = getPythonPath(unwrapped_cls)
+ url = None
try:
klass = zapi.traverse(codeModule, path.replace('.', '/'))
url = zapi.absoluteURL(klass, self.request)
except TraversalError:
# If one of the classes is implemented in C, we will not
# be able to find it.
- url = None
+ pass
info.append({'path': path or None, 'url': url})
return info
@@ -78,7 +89,8 @@
def getInterfaces(self):
"""Get all implemented interfaces (as paths) of this class."""
- return map(getPythonPath, self.context.getInterfaces())
+ return [getInterfaceInfo(iface)
+ for iface in self.context.getInterfaces()]
def getAttributes(self):
@@ -95,7 +107,7 @@
'value': `attr`,
'type': type(attr).__name__,
'type_link': getTypeLink(type(attr)),
- 'interface': getPythonPath(iface)}
+ 'interface': getInterfaceInfo(iface)}
entry.update(getPermissionIds(name, klass.getSecurityChecker()))
attrs.append(entry)
return attrs
@@ -114,16 +126,17 @@
entry = {'name': name,
'signature': "(...)",
'doc': renderText(attr.__doc__ or '',
- zapi.getParent(self.context).getPath()),
- 'interface': getPythonPath(iface)}
+ 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 '',
- zapi.getParent(self.context).getPath()),
- 'interface': getPythonPath(iface)}
+ inspect.getmodule(attr)),
+ 'interface': getInterfaceInfo(iface)}
entry.update(getPermissionIds(name, klass.getSecurityChecker()))
methods.append(entry)
return methods
Modified: Zope3/trunk/src/zope/app/apidoc/codemodule/browser/class_index.pt
===================================================================
--- Zope3/trunk/src/zope/app/apidoc/codemodule/browser/class_index.pt 2005-10-31 05:03:42 UTC (rev 39759)
+++ Zope3/trunk/src/zope/app/apidoc/codemodule/browser/class_index.pt 2005-10-31 05:16:32 UTC (rev 39760)
@@ -26,10 +26,8 @@
tal:attributes="href string:${base/url}/index.html"
tal:content="base/path"
tal:condition="base/url" />
- <div tal:condition="not: base/url">
- <span tal:replace="base/path" />
- <span i18n:translate="">(C-based class)</span>
- </div>
+ <span tal:replace="base/path"
+ tal:condition="not: base/url"/>
</li>
</ul>
@@ -48,8 +46,11 @@
<li tal:repeat="iface ifaces">
<a href=""
tal:attributes="href
- string:${view/getBaseURL}/Interface/$iface/index.html"
- tal:content="iface" />
+ string:${view/getBaseURL}/Interface/${iface/url}/index.html"
+ tal:content="iface/path"
+ tal:condition="iface/url"/>
+ <span tal:replace="iface/path"
+ tal:condition="not: iface/url"/>
</li>
</ul>
@@ -87,8 +88,12 @@
<i i18n:translate="">Interface:</i>
<a href=""
tal:attributes="href
- string:${view/getBaseURL}/Interface/${attr/interface}/index.html"
- tal:content="attr/interface">Iface</a><br />
+ string:${view/getBaseURL}/Interface/${attr/interface/url}/index.html"
+ tal:content="attr/interface/path"
+ tal:condition="attr/interface/url" />
+ <span tal:replace="attr/interface/path"
+ tal:condition="not: attr/interface/url" />
+ <br />
</span>
<span class="small"
tal:condition="python: attr['read_perm'] and attr['write_perm']">
@@ -128,8 +133,12 @@
<i i18n:translate="">Interface:</i>
<a href=""
tal:attributes="href
- string:${view/getBaseURL}/Interface/${method/interface}/index.html"
- tal:content="method/interface">Iface</a><br/>
+ string:${view/getBaseURL}/Interface/${method/interface/url}/index.html"
+ tal:content="method/interface/path"
+ tal:condition="method/interface/url" />
+ <span tal:replace="method/interface/path"
+ tal:condition="not: method/interface/url" />
+ <br/>
</span>
<span class="small"
Modified: Zope3/trunk/src/zope/app/apidoc/codemodule/browser/configure.zcml
===================================================================
--- Zope3/trunk/src/zope/app/apidoc/codemodule/browser/configure.zcml 2005-10-31 05:03:42 UTC (rev 39759)
+++ Zope3/trunk/src/zope/app/apidoc/codemodule/browser/configure.zcml 2005-10-31 05:16:32 UTC (rev 39760)
@@ -7,56 +7,64 @@
permission="zope.app.apidoc.UseAPIDoc"
class=".menu.Menu"
name="menu.html"
- template="menu.pt" />
+ template="menu.pt"
+ layer="zope.app.apidoc.browser.skin.apidoc" />
<page
for="..codemodule.CodeModule"
permission="zope.app.apidoc.UseAPIDoc"
class=".menu.Menu"
name="staticmenu.html"
- template="static_menu.pt" />
+ template="static_menu.pt"
+ layer="zope.app.apidoc.browser.skin.apidoc" />
<page
for="..interfaces.IModuleDocumentation"
permission="zope.app.apidoc.UseAPIDoc"
class=".module.ModuleDetails"
name="index.html"
- template="module_index.pt" />
+ template="module_index.pt"
+ layer="zope.app.apidoc.browser.skin.apidoc" />
<page
for="..interfaces.IClassDocumentation"
permission="zope.app.apidoc.UseAPIDoc"
class=".class_.ClassDetails"
name="index.html"
- template="class_index.pt" />
+ template="class_index.pt"
+ layer="zope.app.apidoc.browser.skin.apidoc" />
<page
for="..interfaces.IFunctionDocumentation"
permission="zope.app.apidoc.UseAPIDoc"
class=".function.FunctionDetails"
name="index.html"
- template="function_index.pt" />
+ template="function_index.pt"
+ layer="zope.app.apidoc.browser.skin.apidoc" />
<page
for="..text.TextFile"
permission="zope.app.apidoc.UseAPIDoc"
class=".text.TextFileDetails"
name="index.html"
- template="textfile_index.pt" />
+ template="textfile_index.pt"
+ layer="zope.app.apidoc.browser.skin.apidoc" />
<!-- ZCML File -->
<page
for="..interfaces.IZCMLFile"
name="index.html"
template="zcmlfile_index.pt"
- permission="zope.View"/>
+ permission="zope.View"
+ layer="zope.app.apidoc.browser.skin.apidoc" />
<page
name="display"
for="..interfaces.IDirective"
template="directive.pt"
class=".zcml.DirectiveDetails"
- permission="zope.ManageContent"/>
+ permission="zope.ManageContent"
+ layer="zope.app.apidoc.browser.skin.apidoc" />
<include file="introspector.zcml" />
Modified: Zope3/trunk/src/zope/app/apidoc/codemodule/browser/introspector.pt
===================================================================
--- Zope3/trunk/src/zope/app/apidoc/codemodule/browser/introspector.pt 2005-10-31 05:03:42 UTC (rev 39759)
+++ Zope3/trunk/src/zope/app/apidoc/codemodule/browser/introspector.pt 2005-10-31 05:16:32 UTC (rev 39760)
@@ -1,7 +1,7 @@
<html metal:use-macro="context/@@standard_macros/view">
<head>
<metal:block fill-slot="extrahead">
- <link type="text/css" rel="stylesheet" href="introspector.css"
+ <link type="text/css" rel="stylesheet" href="apidoc.css"
tal:attributes="href context/++resource++apidoc.css" />
</metal:block>
</head>
@@ -63,8 +63,8 @@
<li tal:repeat="iface ifaces">
<a href=""
tal:attributes="href
- string:${view/getBaseURL}/Interface/$iface/index.html"
- tal:content="iface" />
+ string:${view/getBaseURL}/Interface/${iface/url}/index.html"
+ tal:content="iface/path" />
</li>
</ul>
@@ -83,7 +83,6 @@
tal:condition="base/url" />
<div tal:condition="not: base/url">
<span tal:replace="base/path" />
- <span i18n:translate="">(C-based class)</span>
</div>
</li>
</ul>
@@ -129,7 +128,7 @@
<i i18n:translate="">Interface:</i>
<a href=""
tal:attributes="href
- string:${view/getBaseURL}/Interface/${attr/interface}/index.html"
+ string:${view/getBaseURL}/Interface/${attr/interface}/index.html"
tal:content="attr/interface">Iface</a><br />
</span>
<span class="small"
Modified: Zope3/trunk/src/zope/app/apidoc/codemodule/browser/introspector.py
===================================================================
--- Zope3/trunk/src/zope/app/apidoc/codemodule/browser/introspector.py 2005-10-31 05:03:42 UTC (rev 39759)
+++ Zope3/trunk/src/zope/app/apidoc/codemodule/browser/introspector.py 2005-10-31 05:16:32 UTC (rev 39760)
@@ -22,7 +22,7 @@
import zope.interface
import zope.security.proxy
-from zope.interface import directlyProvidedBy
+from zope.interface import directlyProvidedBy, directlyProvides
from zope.app import zapi, apidoc, annotation
from zope.app.location import location
from zope.app.publisher.browser import BrowserView
@@ -100,10 +100,16 @@
path = apidoc.utilities.getPythonPath(
context.__class__).replace('.', '/')
+ # the ++apidoc++ namespace overrides the skin, so make sure we can get
+ # it back.
+ direct = list(directlyProvidedBy(request))
+
self.klassView = zapi.traverse(
TraversalRoot(),
'/++apidoc++/Code/%s/@@index.html' %path, request=request)
+ directlyProvides(request, direct)
+
def parent(self):
return zapi.getParent(self.context)
Modified: Zope3/trunk/src/zope/app/apidoc/codemodule/browser/module.py
===================================================================
--- Zope3/trunk/src/zope/app/apidoc/codemodule/browser/module.py 2005-10-31 05:03:42 UTC (rev 39759)
+++ Zope3/trunk/src/zope/app/apidoc/codemodule/browser/module.py 2005-10-31 05:16:32 UTC (rev 39760)
@@ -22,18 +22,33 @@
from zope.app import zapi
from zope.app.i18n import ZopeMessageFactory as _
+from zope.app.publisher.browser import BrowserView
-from zope.app.apidoc.utilities import renderText, columnize
+from zope.app.apidoc.apidoc import APIDocumentation
+from zope.app.apidoc.utilities import getPythonPath, renderText, columnize
from zope.app.apidoc.codemodule.module import Module
from zope.app.apidoc.codemodule.class_ import Class
from zope.app.apidoc.codemodule.function import Function
from zope.app.apidoc.codemodule.text import TextFile
from zope.app.apidoc.codemodule.zcml import ZCMLFile
+def findAPIDocumentationRoot(obj, request):
+ if zapi.isinstance(obj, APIDocumentation):
+ return zapi.absoluteURL(obj, request)
+ return findAPIDocumentationRoot(zapi.getParent(obj), request)
-class ModuleDetails(object):
+
+class ModuleDetails(BrowserView):
"""Represents the details of the module."""
+ def __init__(self, context, request):
+ super(ModuleDetails, self).__init__(context, request)
+ try:
+ self.apidocRoot = findAPIDocumentationRoot(context, request)
+ except TypeError:
+ # Probably context without location; it's a test
+ self.apidocRoot = ''
+
def getDoc(self):
"""Get the doc string of the module STX formatted."""
text = self.context.getDocString()
@@ -47,6 +62,8 @@
def getEntries(self, columns=True):
"""Return info objects for all modules and classes in this module."""
entries = [{'name': name,
+ # only for interfaces; should be done differently somewhen
+ 'path': getPythonPath(removeAllProxies(obj)),
'url': zapi.absoluteURL(obj, self.request),
'ismodule': zapi.isinstance(obj, Module),
'isinterface': zapi.isinstance(
Modified: Zope3/trunk/src/zope/app/apidoc/codemodule/browser/module_index.pt
===================================================================
--- Zope3/trunk/src/zope/app/apidoc/codemodule/browser/module_index.pt 2005-10-31 05:03:42 UTC (rev 39759)
+++ Zope3/trunk/src/zope/app/apidoc/codemodule/browser/module_index.pt 2005-10-31 05:16:32 UTC (rev 39760)
@@ -28,27 +28,28 @@
<li tal:repeat="entry column">
<a href=""
tal:condition="entry/ismodule"
- tal:attributes="href string:./${entry/name}/index.html"
+ tal:attributes="href string:${entry/url}/index.html"
tal:content="entry/name" />
<a href=""
tal:condition="entry/isinterface"
- tal:attributes="href string:./${entry/name}/index.html"
+ tal:attributes="
+ href string:${view/apidocRoot}/Interface/${entry/path}/index.html"
tal:content="structure string:<b><i>${entry/name}</i></b>" />
<a href=""
tal:condition="entry/isclass"
- tal:attributes="href string:./${entry/name}/index.html"
+ tal:attributes="href string:${entry/url}/index.html"
tal:content="structure string:<b>${entry/name}</b>" />
<a href=""
tal:condition="entry/isfunction"
- tal:attributes="href string:./${entry/name}/index.html"
+ tal:attributes="href string:${entry/url}/index.html"
tal:content="structure string:<i>${entry/name}</i>" />
<a href=""
tal:condition="entry/iszcmlfile"
- tal:attributes="href string:./${entry/name}/index.html"
+ tal:attributes="href string:${entry/url}/index.html"
tal:content="structure string:<i>${entry/name}</i>" />
<a href=""
tal:condition="entry/istextfile"
- tal:attributes="href string:./${entry/name}/index.html"
+ tal:attributes="href string:${entry/url}/index.html"
tal:content="structure string:<i>${entry/name}</i>" />
</li>
</ul></td>
Modified: Zope3/trunk/src/zope/app/apidoc/codemodule/browser/textfile_index.pt
===================================================================
--- Zope3/trunk/src/zope/app/apidoc/codemodule/browser/textfile_index.pt 2005-10-31 05:03:42 UTC (rev 39759)
+++ Zope3/trunk/src/zope/app/apidoc/codemodule/browser/textfile_index.pt 2005-10-31 05:16:32 UTC (rev 39760)
@@ -1,4 +1,10 @@
<html metal:use-macro="views/apidoc_macros/details">
+<head>
+ <base href=""
+ metal:fill-slot="headers"
+ tal:attributes="href request/URL/-1" />
+</head>
+
<body metal:fill-slot="contents">
<div class="documentation"
Modified: Zope3/trunk/src/zope/app/apidoc/codemodule/browser/zcml.py
===================================================================
--- Zope3/trunk/src/zope/app/apidoc/codemodule/browser/zcml.py 2005-10-31 05:03:42 UTC (rev 39759)
+++ Zope3/trunk/src/zope/app/apidoc/codemodule/browser/zcml.py 2005-10-31 05:16:32 UTC (rev 39760)
@@ -55,7 +55,7 @@
def fullTagName(self):
context = removeSecurityProxy(self.context)
ns, name = context.name
- if context.prefixes[ns]:
+ if context.prefixes.get(ns):
return '%s:%s' %(context.prefixes[ns], name)
else:
return name
@@ -78,7 +78,9 @@
subDirective = directive
directive = parent
ns, name = directive.name
- ns = quoteNS(ns)
+ # Sometimes ns is `None`, especially in the slug files, where no
+ # namespaces are used.
+ ns = quoteNS(ns or 'ALL')
zcml = zapi.getUtility(IDocumentationModule, 'ZCML')
if name not in zcml[ns]:
ns = 'ALL'
@@ -89,7 +91,8 @@
return link
def objectURL(self, value, field, rootURL):
- bound = field.bind(self.context.context)
+ naked = removeSecurityProxy(self.context)
+ bound = field.bind(naked.context)
obj = bound.fromUnicode(value)
if obj is None:
return
Modified: Zope3/trunk/src/zope/app/apidoc/codemodule/class_.py
===================================================================
--- Zope3/trunk/src/zope/app/apidoc/codemodule/class_.py 2005-10-31 05:03:42 UTC (rev 39759)
+++ Zope3/trunk/src/zope/app/apidoc/codemodule/class_.py 2005-10-31 05:16:32 UTC (rev 39760)
@@ -76,18 +76,20 @@
def getAttributes(self):
"""See IClassDocumentation."""
- return [(name, obj, iface) for name, obj, iface
- in self._iterAllAttributes()
- if not (ismethod(obj) or ismethoddescriptor(obj))]
+ return [(name, obj, iface)
+ for name, obj, iface in self._iterAllAttributes()
+ if not (ismethod(obj) or ismethoddescriptor(obj))]
def getMethods(self):
"""See IClassDocumentation."""
- return [(name, obj, iface) for name, obj, iface
- in self._iterAllAttributes() if ismethod(obj)]
+ return [(name, obj, iface)
+ for name, obj, iface in self._iterAllAttributes()
+ if ismethod(obj)]
def getMethodDescriptors(self):
- return [(name, obj, iface) for name, obj, iface
- in self._iterAllAttributes() if ismethoddescriptor(obj)]
+ return [(name, obj, iface)
+ for name, obj, iface in self._iterAllAttributes()
+ if ismethoddescriptor(obj)]
def getSecurityChecker(self):
"""See IClassDocumentation."""
Modified: Zope3/trunk/src/zope/app/apidoc/codemodule/interfaces.py
===================================================================
--- Zope3/trunk/src/zope/app/apidoc/codemodule/interfaces.py 2005-10-31 05:03:42 UTC (rev 39759)
+++ Zope3/trunk/src/zope/app/apidoc/codemodule/interfaces.py 2005-10-31 05:16:32 UTC (rev 39760)
@@ -30,7 +30,7 @@
The utilities will be simple strings, representing the modules Python
dotted name.
- """
+ """
class IModuleDocumentation(IReadContainer):
"""Representation of a Python module for documentation.
Modified: Zope3/trunk/src/zope/app/apidoc/codemodule/module.py
===================================================================
--- Zope3/trunk/src/zope/app/apidoc/codemodule/module.py 2005-10-31 05:03:42 UTC (rev 39759)
+++ Zope3/trunk/src/zope/app/apidoc/codemodule/module.py 2005-10-31 05:16:32 UTC (rev 39760)
@@ -96,8 +96,7 @@
attr.__module__ == self._module.__name__:
if not hasattr(attr, '__name__') or \
- attr.__name__ != name or \
- name.startswith('_'):
+ attr.__name__ != name:
continue
if isinstance(attr, (types.ClassType, types.TypeType)):
@@ -150,4 +149,8 @@
def items(self):
"""See zope.app.container.interfaces.IReadContainer."""
- return self._children.items()
+ # Only publicize public objects, even though we do keep track of
+ # private ones
+ return [(name, value)
+ for name, value in self._children.items()
+ if not name.startswith('_')]
Modified: Zope3/trunk/src/zope/app/apidoc/codemodule/text.py
===================================================================
--- Zope3/trunk/src/zope/app/apidoc/codemodule/text.py 2005-10-31 05:03:42 UTC (rev 39759)
+++ Zope3/trunk/src/zope/app/apidoc/codemodule/text.py 2005-10-31 05:16:32 UTC (rev 39760)
@@ -11,7 +11,7 @@
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
-"""Function representation for code browser
+"""Function representation for code browser
$Id: __init__.py 29143 2005-02-14 22:43:16Z srichter $
"""
@@ -29,7 +29,7 @@
self.__name__ = name
def getContent(self):
- file = open(self.path, 'r')
+ file = open(self.path, 'rb')
content = file.read()
file.close()
- return content
+ return content.decode('utf-8')
Modified: Zope3/trunk/src/zope/app/apidoc/codemodule/zcml.py
===================================================================
--- Zope3/trunk/src/zope/app/apidoc/codemodule/zcml.py 2005-10-31 05:03:42 UTC (rev 39759)
+++ Zope3/trunk/src/zope/app/apidoc/codemodule/zcml.py 2005-10-31 05:16:32 UTC (rev 39760)
@@ -16,6 +16,7 @@
$Id$
"""
__docformat__ = "reStructuredText"
+import copy
from xml.sax import make_parser
from xml.sax.xmlreader import InputSource
from xml.sax.handler import feature_namespaces
@@ -41,6 +42,10 @@
def startPrefixMapping(self, prefix, uri):
self.prefixes[uri] = prefix
+ def evaluateCondition(self, expression):
+ # We always want to process/show all ZCML directives.
+ return True
+
def startElementNS(self, name, qname, attrs):
# The last stack item is parent of the stack item that we are about to
# create
@@ -105,8 +110,12 @@
self.__name__ = name
def rootElement(self):
- # Get the context that was originally generated during startup.
- context = zope.app.appsetup.appsetup.getConfigContext()
+ # Get the context that was originally generated during startup and
+ # create a new context using its registrations
+ real_context = zope.app.appsetup.appsetup.getConfigContext()
+ context = config.ConfigurationMachine()
+ context._registry = copy.copy(real_context._registry)
+ context._features = copy.copy(real_context._features)
context.package = self.package
# Shut up i18n domain complaints
Modified: Zope3/trunk/src/zope/app/apidoc/component.py
===================================================================
--- Zope3/trunk/src/zope/app/apidoc/component.py 2005-10-31 05:03:42 UTC (rev 39759)
+++ Zope3/trunk/src/zope/app/apidoc/component.py 2005-10-31 05:16:32 UTC (rev 39760)
@@ -231,8 +231,16 @@
# provided interface id
iface_id = '%s.%s' % (reg.provided.__module__, reg.provided.getName())
+ # Determine the URL
+ if isinstance(component, InterfaceClass):
+ url = 'Interface/%s' %path
+ else:
+ url = None
+ if isReferencable(path):
+ url = 'Code/%s' % path.replace('.', '/')
+
return {'name': reg.name or _('<i>no name</i>'),
'url_name': utilitymodule.encodeName(reg.name or '__noname__'),
'iface_id': iface_id,
'path': path,
- 'url': isReferencable(path) and path.replace('.', '/') or None}
+ 'url': url}
Modified: Zope3/trunk/src/zope/app/apidoc/component.txt
===================================================================
--- Zope3/trunk/src/zope/app/apidoc/component.txt 2005-10-31 05:03:42 UTC (rev 39759)
+++ Zope3/trunk/src/zope/app/apidoc/component.txt 2005-10-31 05:16:32 UTC (rev 39760)
@@ -344,5 +344,5 @@
{'iface_id': 'zope.app.apidoc.doctest.IFooBar',
'name': u'<i>no name</i>',
'path': 'zope.app.apidoc.doctest.MyFooBar',
- 'url': 'zope/app/apidoc/doctest/MyFooBar',
+ 'url': 'Code/zope/app/apidoc/doctest/MyFooBar',
'url_name': 'X19ub25hbWVfXw=='}
Modified: Zope3/trunk/src/zope/app/apidoc/ifacemodule/browser.py
===================================================================
--- Zope3/trunk/src/zope/app/apidoc/ifacemodule/browser.py 2005-10-31 05:03:42 UTC (rev 39759)
+++ Zope3/trunk/src/zope/app/apidoc/ifacemodule/browser.py 2005-10-31 05:16:32 UTC (rev 39760)
@@ -16,6 +16,7 @@
$Id$
"""
__docformat__ = 'restructuredtext'
+import inspect
from zope.interface import Interface
from zope.publisher.interfaces import IRequest
@@ -78,8 +79,8 @@
# We must remove all proxies here, so that we get the context's
# __module__ attribute. If we only remove security proxies, the
# location proxy's module will be returned.
- return renderText(self.context.__doc__,
- removeSecurityProxy(self.context).__module__)
+ iface = removeAllProxies(self.context)
+ return renderText(iface.__doc__, inspect.getmodule(iface))
def getBases(self):
"""Get all bases of this class
@@ -91,7 +92,10 @@
>>> details.getBases()
['zope.interface.Interface']
"""
- return [getPythonPath(base) for base in self.context.__bases__]
+ # Persistent interfaces are security proxied, so we need to strip the
+ # security proxies off
+ iface = removeSecurityProxy(self.context)
+ return [getPythonPath(base) for base in iface.__bases__]
def getTypes(self):
"""Return a list of interface types that are specified for this
Modified: Zope3/trunk/src/zope/app/apidoc/ifacemodule/component_macros.pt
===================================================================
--- Zope3/trunk/src/zope/app/apidoc/ifacemodule/component_macros.pt 2005-10-31 05:03:42 UTC (rev 39759)
+++ Zope3/trunk/src/zope/app/apidoc/ifacemodule/component_macros.pt 2005-10-31 05:16:32 UTC (rev 39760)
@@ -90,7 +90,7 @@
<span i18n:translate="">Component:</span>
<code style="font-size: 100%">
<a href=""
- tal:attributes="href string:$rootURL/Code/${utility/url}/index.html"
+ tal:attributes="href string:$rootURL/${utility/url}/index.html"
tal:content="utility/path"
tal:condition="utility/url" />
<span tal:condition="not: utility/url" tal:replace="utility/path" />
Modified: Zope3/trunk/src/zope/app/apidoc/ifacemodule/configure.zcml
===================================================================
--- Zope3/trunk/src/zope/app/apidoc/ifacemodule/configure.zcml 2005-10-31 05:03:42 UTC (rev 39759)
+++ Zope3/trunk/src/zope/app/apidoc/ifacemodule/configure.zcml 2005-10-31 05:16:32 UTC (rev 39760)
@@ -22,6 +22,7 @@
permission="zope.View"
class=".macros.InterfaceDetailsMacros"
allowed_interface="zope.interface.common.mapping.IItemMapping"
+ layer="zope.app.apidoc.browser.skin.apidoc"
/>
<browser:page
@@ -29,6 +30,7 @@
name="iface_macros"
permission="zope.View"
template="iface_macros.pt"
+ layer="zope.app.apidoc.browser.skin.apidoc"
/>
<browser:page
@@ -36,6 +38,7 @@
name="component_macros"
permission="zope.View"
template="component_macros.pt"
+ layer="zope.app.apidoc.browser.skin.apidoc"
/>
<browser:page
@@ -43,6 +46,7 @@
name="presentation_macros"
permission="zope.View"
template="presentation_macros.pt"
+ layer="zope.app.apidoc.browser.skin.apidoc"
/>
<!-- The name for the interface content cannot be 'index.html', since -->
@@ -54,6 +58,7 @@
class=".browser.InterfaceDetails"
name="index.html"
template="index.pt"
+ layer="zope.app.apidoc.browser.skin.apidoc"
/>
<!-- Interface Documentation Module Menu -->
@@ -64,6 +69,7 @@
class=".menu.Menu"
name="menu.html"
template="menu.pt"
+ layer="zope.app.apidoc.browser.skin.apidoc"
/>
<browser:page
@@ -72,6 +78,7 @@
class=".menu.Menu"
name="staticmenu.html"
template="static_menu.pt"
+ layer="zope.app.apidoc.browser.skin.apidoc"
/>
<preferenceGroup
Modified: Zope3/trunk/src/zope/app/apidoc/interface.py
===================================================================
--- Zope3/trunk/src/zope/app/apidoc/interface.py 2005-10-31 05:03:42 UTC (rev 39759)
+++ Zope3/trunk/src/zope/app/apidoc/interface.py 2005-10-31 05:16:32 UTC (rev 39760)
@@ -17,12 +17,14 @@
"""
__docformat__ = 'restructuredtext'
+import inspect
+
from zope.interface import Interface, providedBy
from zope.interface.interfaces import IInterface, ISpecification
from zope.interface.interfaces import IElement, IAttribute, IMethod
from zope.schema.interfaces import IField
-from zope.app.apidoc.utilities import getPythonPath, renderText
+from zope.app.apidoc.utilities import getPythonPath, renderText, getDocFormat
def getElements(iface, type=IElement):
@@ -72,7 +74,7 @@
# Remove interfaces provided by every interface instance
types.remove(ISpecification)
types.remove(IElement)
- types.remove(Interface)
+ types.remove(Interface)
# Remove interface provided by every interface type
types.remove(IInterface)
return types
@@ -94,25 +96,33 @@
return iface
# If not even a `IField`-based interface was found, return the first
- # interface of the implemented interfaces list.
+ # interface of the implemented interfaces list.
return field_iface or ifaces[0]
-
-def getAttributeInfoDictionary(attr, format='zope.source.rest'):
+
+def _getDocFormat(attr):
+ module = inspect.getmodule(attr.interface)
+ return getDocFormat(module)
+
+
+def getAttributeInfoDictionary(attr, format=None):
"""Return a page-template-friendly information dictionary."""
+ format = format or _getDocFormat(attr)
return {'name': attr.getName(),
'doc': renderText(attr.getDoc() or u'', format=format)}
-def getMethodInfoDictionary(method, format='zope.source.rest'):
+def getMethodInfoDictionary(method, format=None):
"""Return a page-template-friendly information dictionary."""
+ format = format or _getDocFormat(method)
return {'name': method.getName(),
'signature': method.getSignatureString(),
'doc': renderText(method.getDoc() or u'', format=format)}
-def getFieldInfoDictionary(field, format='zope.source.rest'):
+def getFieldInfoDictionary(field, format=None):
"""Return a page-template-friendly information dictionary."""
+ format = format or _getDocFormat(field)
info = {'name': field.getName(),
'required': field.required,
Modified: Zope3/trunk/src/zope/app/apidoc/interface.txt
===================================================================
--- Zope3/trunk/src/zope/app/apidoc/interface.txt 2005-10-31 05:03:42 UTC (rev 39759)
+++ Zope3/trunk/src/zope/app/apidoc/interface.txt 2005-10-31 05:16:32 UTC (rev 39760)
@@ -129,7 +129,7 @@
interface.
>>> interface.getFields(IFoo) #doctest: +ELLIPSIS
- [('foo', <zope.schema._bootstrapfields.Field object at ...>),
+ [('foo', <zope.schema._bootstrapfields.Field object at ...>),
('bar', <zope.schema._bootstrapfields.TextLine object at ...>)]
Note that this returns the same result as `getFieldsInOrder()` with the fields
@@ -225,7 +225,7 @@
This function returns a page-template-friendly dictionary for a method:
>>> pprint(interface.getMethodInfoDictionary(IFoo['blah'])) #doc
- {'doc':
+ {'doc':
u'<p>This is the <cite>blah</cite> method.</p>\n',
'name': 'blah',
'signature': '(one, two, three=None, *args, **kwargs)'}
Modified: Zope3/trunk/src/zope/app/apidoc/static.py
===================================================================
--- Zope3/trunk/src/zope/app/apidoc/static.py 2005-10-31 05:03:42 UTC (rev 39759)
+++ Zope3/trunk/src/zope/app/apidoc/static.py 2005-10-31 05:16:32 UTC (rev 39760)
@@ -22,18 +22,18 @@
import sys
import time
import urllib2
+import warnings
import HTMLParser
import zope.testbrowser
import mechanize
from zope.app.testing import functional
-from zope.deprecation import __show__
from zope.app.apidoc import classregistry
# Setup the user feedback detail level.
-VERBOSITY = 4
+VERBOSITY = 5
VERBOSITY_MAP = {1: 'ERROR', 2: 'WARNING', 3: 'INFO'}
@@ -48,6 +48,8 @@
USERNAME = 'mgr'
PASSWORD = 'mgrpw'
+DEBUG = False
+
# A mapping of HTML elements that can contain links to the attribute that
# actually contains the link
urltags = {
@@ -196,12 +198,15 @@
def start(self):
"""Start the retrieval of the apidoc."""
t0 = time.time()
- __show__.off()
self.visited = []
self.counter = 0
- self.errors = 0
+ self.linkErrors = 0
+ self.htmlErrors = 0
+ # Turn off deprecation warnings
+ warnings.filterwarnings("ignore", category=DeprecationWarning)
+
if not os.path.exists(self.rootDir):
os.mkdir(self.rootDir)
@@ -212,10 +217,13 @@
self.browser.setUserAndPassword(USERNAME, PASSWORD)
self.browser.urltags = urltags
- #self.browser.addheaders.append(('X-zope-handle-errors', False))
- classregistry.IGNORE_MODULES = ['twisted']
+ if DEBUG:
+ self.browser.addheaders.append(('X-zope-handle-errors', False))
+ classregistry.IGNORE_MODULES = ['twisted',
+ 'zope.app.twisted.ftp.test']
+
# Work through all links until there are no more to work on.
self.sendMessage('Starting retrieval.')
while self.linkQueue:
@@ -227,16 +235,16 @@
self.showStatistics(link)
self.processLink(link)
- __show__.on()
t1 = time.time()
- self.sendMessage("Run time: %.3f sec real" % (t1-t0))
+ self.sendMessage("Run time: %.3f sec" % (t1-t0))
self.sendMessage("Links: %i" %self.counter)
- self.sendMessage("Errors: %i" %self.errors)
+ self.sendMessage("Link Retrieval Errors: %i" %self.linkErrors)
+ self.sendMessage("HTML ParsingErrors: %i" %self.htmlErrors)
def showStatistics(self, link):
self.counter += 1
- if VERBOSITY >= 3:
+ if VERBOSITY >= 5:
url = link.absoluteURL[-(self.maxWidth):]
sys.stdout.write('\r' + ' '*(self.maxWidth+13))
sys.stdout.write('\rLink %5d: %s' % (self.counter, url))
@@ -265,21 +273,29 @@
self.browser.open(link.callableURL)
except urllib2.HTTPError, error:
# Something went wrong with retrieving the page.
- self.errors += 1
+ self.linkErrors += 1
self.sendMessage(
'%s (%i): %s' % (error.msg, error.code, link.callableURL), 2)
self.sendMessage('+-> Reference: ' + link.referenceURL, 2)
- return
+ # Now set the error page as the response
+ from ClientCookie._Util import response_seek_wrapper
+ self.browser._response = response_seek_wrapper(error)
except (urllib2.URLError, ValueError):
# We had a bad URL running the publisher browser
- self.errors += 1
+ self.linkErrors += 1
self.sendMessage('Bad URL: ' + link.callableURL, 2)
self.sendMessage('+-> Reference: ' + link.referenceURL, 2)
return
- #except Exception, error:
- # import pdb; pdb.set_trace()
- # return
+ except Exception, error:
+ # This should never happen outside the debug mode. We really want
+ # to catch all exceptions, so that we can investigate them.
+ if DEBUG:
+ import pdb; pdb.set_trace()
+ return
+ # Get the response content
+ contents = self.browser.contents
+
# Make sure the directory exists and get a file path.
relativeURL = url.replace(URL, '')
dir = self.rootDir
@@ -293,16 +309,16 @@
filepath = os.path.join(dir, filename)
- # Get the response content
- contents = self.browser.contents
-
# Now retrieve all links
if self.browser.viewing_html():
try:
links = self.browser.links()
- except HTMLParser.HTMLParseError:
+ except HTMLParser.HTMLParseError, error:
+ self.htmlErrors += 1
self.sendMessage('Failed to parse HTML: ' + url, 1)
+ self.sendMessage('+-> %s: line %i, column %s' % (
+ error.msg, error.lineno, error.offset), 1)
links = []
links = [Link(mech_link, url) for mech_link in links]
@@ -322,9 +338,15 @@
contents = contents.replace(link.originalURL, '/'.join(parts))
# Write the data into the file
- file = open(filepath, 'w')
- file.write(contents)
- file.close()
+ try:
+ file = open(filepath, 'w')
+ file.write(contents)
+ file.close()
+ except IOError:
+ # The file already exists, so it is a duplicate and a bad one,
+ # since the URL misses `index.hml`. ReST can produce strange URLs
+ # that produce this problem, and we have little control over it.
+ pass
# Cleanup; this is very important, otherwise we are opening too many
# files.
Modified: Zope3/trunk/src/zope/app/apidoc/typemodule/configure.zcml
===================================================================
--- Zope3/trunk/src/zope/app/apidoc/typemodule/configure.zcml 2005-10-31 05:03:42 UTC (rev 39759)
+++ Zope3/trunk/src/zope/app/apidoc/typemodule/configure.zcml 2005-10-31 05:16:32 UTC (rev 39760)
@@ -8,7 +8,7 @@
</class>
<class class=".type.TypeInterface">
- <allow interface="zope.app.container.interfaces.IReadContainer"
+ <allow interface="zope.app.container.interfaces.IReadContainer"
attributes="interface" />
</class>
@@ -25,14 +25,16 @@
class=".browser.Menu"
name="menu.html"
template="menu.pt"
+ layer="zope.app.apidoc.browser.skin.apidoc"
/>
-
+
<browser:page
for=".type.TypeModule"
permission="zope.app.apidoc.UseAPIDoc"
class=".browser.Menu"
name="staticmenu.html"
template="static_menu.pt"
- />
+ layer="zope.app.apidoc.browser.skin.apidoc"
+ />
</configure>
Modified: Zope3/trunk/src/zope/app/apidoc/utilities.py
===================================================================
--- Zope3/trunk/src/zope/app/apidoc/utilities.py 2005-10-31 05:03:42 UTC (rev 39759)
+++ Zope3/trunk/src/zope/app/apidoc/utilities.py 2005-10-31 05:16:32 UTC (rev 39760)
@@ -34,11 +34,13 @@
from zope.app.i18n import ZopeMessageFactory as _
from zope.app.container.interfaces import IReadContainer
-from zope.app.apidoc.classregistry import safe_import
+from zope.app.apidoc.classregistry import safe_import, IGNORE_MODULES
_remove_html_overhead = re.compile(
r'(?sm)^<html.*<body.*?>\n(.*)</body>\n</html>\n')
+space_re = re.compile('\n^( *)\S', re.M)
+
_marker = object()
BASEDIR = dirname(dirname(dirname(zope.__file__)))
@@ -114,14 +116,32 @@
# Sometimes no path exists, so make a simple check first; example: None
if path is None:
return False
- module_name, obj_name = path.rsplit('.', 1)
+
+ # There are certain paths that we do not want to reference, most often
+ # because they are outside the scope of this documentation
+ for exclude_name in IGNORE_MODULES:
+ if path.startswith(exclude_name):
+ return False
+ split_path = path.rsplit('.', 1)
+ if len(split_path) == 2:
+ module_name, obj_name = split_path
+ else:
+ module_name, obj_name = split_path[0], None
+
# Do not allow private attributes to be accessible
- if (obj_name.startswith('_') and
+ if (obj_name is not None and
+ obj_name.startswith('_') and
not (obj_name.startswith('__') and obj_name.endswith('__'))):
return False
module = safe_import(module_name)
if module is None:
return False
+
+ # If the module imported correctly and no name is provided, then we are
+ # all good.
+ if obj_name is None:
+ return True
+
obj = getattr(module, obj_name, _marker)
if obj is _marker:
return False
@@ -271,27 +291,17 @@
"""Convert a module's __docformat__ specification to a renderer source
id"""
format = getattr(module, '__docformat__', 'structuredtext').lower()
+ # The format can also contain the language, so just get the first part
+ format = format.split(' ')[0]
return _format_dict.get(format, 'zope.source.stx')
def dedentString(text):
"""Dedent the docstring, so that docutils can correctly render it."""
- dedent = 0
- lines = text.split('\n')
- for line in lines[1:]:
- if line != '':
- for char in line:
- if char == ' ':
- dedent += 1
- else:
- break
- break
+ dedent = min([len(match) for match in space_re.findall(text)] or [0])
+ return re.compile('\n {%i}' % dedent, re.M).sub('\n', text)
- for index in range(1, len(lines)):
- lines[index] = lines[index][dedent:]
- return '\n'.join(lines)
-
def renderText(text, module=None, format=None, dedent=True):
if not text:
return u''
Modified: Zope3/trunk/src/zope/app/apidoc/utilities.txt
===================================================================
--- Zope3/trunk/src/zope/app/apidoc/utilities.txt 2005-10-31 05:03:42 UTC (rev 39759)
+++ Zope3/trunk/src/zope/app/apidoc/utilities.txt 2005-10-31 05:16:32 UTC (rev 39760)
@@ -213,6 +213,17 @@
be referenced somehow. But that's not true, partially by design of apidoc, but
also due to limitations of the Python language itself.
+First, here are some cases that work:
+
+ >>> utilities.isReferencable('zope')
+ True
+ >>> utilities.isReferencable('zope.app')
+ True
+ >>> utilities.isReferencable('zope.app.apidoc.apidoc.APIDocumentation')
+ True
+ >>> utilities.isReferencable('zope.app.apidoc.apidoc.handleNamespace')
+ True
+
The first case is ``None``. When you ask for the python path of ``None``, you
get ``None``, so that result should not be referencable:
@@ -249,7 +260,7 @@
>>> utilities.isReferencable(path)
False
-Finally, since API doc does not allow the documentation of instances yet, it
+Next, since API doc does not allow the documentation of instances yet, it
is not possible to document singletons, so they are not referencable:
>>> class Singelton(object):
@@ -263,7 +274,26 @@
>>> utilities.isReferencable('zope.app.apidoc.doctest.Singelton')
False
+Finally, the global ``IGNORE_MODULES`` list from the class registry is also
+used to give a negative answer. If a module is listed in ``IGNORE_MODULES``,
+then ``False`` is returned.
+ >>> import classregistry
+ >>> classregistry.IGNORE_MODULES.append('zope.app.apidoc')
+
+ >>> utilities.isReferencable('zope.app')
+ True
+ >>> utilities.isReferencable('zope.app.apidoc')
+ False
+ >>> utilities.isReferencable('zope.app.apidoc.apidoc.APIDocumentation')
+ False
+
+ >>> classregistry.IGNORE_MODULES.pop()
+ 'zope.app.apidoc'
+ >>> utilities.isReferencable('zope.app.apidoc')
+ True
+
+
`getPermissionIds(name, checker=_marker, klass=_marker)`
--------------------------------------------------------
@@ -609,7 +639,17 @@
endorse restructured text, so that many files are still in the structured text
format. All converted and new modules will have the `__docformat__` attribute.
+The `__docformat__` attribute can also optionally specify a language field. We
+simply ignore it:
+ >>> class Module(object):
+ ... pass
+ >>> module = Module()
+ >>> module.__docformat__ = 'restructuredtext en'
+ >>> utilities.getDocFormat(module)
+ 'zope.source.rest'
+
+
`dendentString(text)`
---------------------
@@ -655,7 +695,8 @@
Again, the whitespace was removed only after the first line. Also note that
the function determines the indentation level correctly. So what happens if
-there are multiple indentation levels? Well, the first occurrence wins:
+there are multiple indentation levels? The smallest amount of indentation is
+chosen:
>>> def func():
... '''Short description
@@ -673,7 +714,25 @@
Second Level
<BLANKLINE>
+ >>> def func():
+ ... '''Short description
+ ...
+ ... $$$ print 'example'
+ ... example
+ ...
+ ... And now the description.
+ ... '''
+ >>> print utilities.dedentString(func.__doc__)
+ Short description
+ <BLANKLINE>
+ $$$ print 'example'
+ example
+ <BLANKLINE>
+ And now the description.
+ <BLANKLINE>
+
+
`renderText(text, module=None, format=None)`
--------------------------------------------
Modified: Zope3/trunk/src/zope/app/apidoc/utilitymodule/configure.zcml
===================================================================
--- Zope3/trunk/src/zope/app/apidoc/utilitymodule/configure.zcml 2005-10-31 05:03:42 UTC (rev 39759)
+++ Zope3/trunk/src/zope/app/apidoc/utilitymodule/configure.zcml 2005-10-31 05:16:32 UTC (rev 39760)
@@ -26,20 +26,26 @@
permission="zope.app.apidoc.UseAPIDoc"
class=".browser.Menu"
name="menu.html"
- template="menu.pt" />
+ template="menu.pt"
+ layer="zope.app.apidoc.browser.skin.apidoc"
+ />
<browser:page
for=".utilitymodule.UtilityModule"
permission="zope.app.apidoc.UseAPIDoc"
class=".browser.Menu"
name="staticmenu.html"
- template="static_menu.pt" />
+ template="static_menu.pt"
+ layer="zope.app.apidoc.browser.skin.apidoc"
+ />
<browser:page
for=".utilitymodule.Utility"
permission="zope.app.apidoc.UseAPIDoc"
class=".browser.UtilityDetails"
name="index.html"
- template="index.pt" />
+ template="index.pt"
+ layer="zope.app.apidoc.browser.skin.apidoc"
+ />
</configure>
Modified: Zope3/trunk/src/zope/app/apidoc/utilitymodule/index.pt
===================================================================
--- Zope3/trunk/src/zope/app/apidoc/utilitymodule/index.pt 2005-10-31 05:03:42 UTC (rev 39759)
+++ Zope3/trunk/src/zope/app/apidoc/utilitymodule/index.pt 2005-10-31 05:16:32 UTC (rev 39760)
@@ -7,7 +7,7 @@
<h1 class="details-header">
<a href=""
tal:attributes="
- href string:../../../Interface/${iface/getId}/index.html"
+ href string:$rootURL/Interface/${iface/getId}/index.html"
tal:content="iface/getId" /> <br />
<tal:block i18n:translate="">(Name: "<span
tal:replace="view/getName" i18n:name="name" />")</tal:block>
@@ -20,8 +20,12 @@
<span i18n:translate="">Component:</span>
<a href=""
tal:attributes="href
- string:../../../Code/${component/url}/index.html"
- tal:content="component/path" /></h3>
+ string:$rootURL/${component/url}/index.html"
+ tal:content="component/path"
+ tal:condition="component/url" />
+ <span tal:replace="component/path"
+ tal:condition="not: component/url" />
+ </h3>
</div>
<div class="indent">
Modified: Zope3/trunk/src/zope/app/apidoc/zcmlmodule/configure.zcml
===================================================================
--- Zope3/trunk/src/zope/app/apidoc/zcmlmodule/configure.zcml 2005-10-31 05:03:42 UTC (rev 39759)
+++ Zope3/trunk/src/zope/app/apidoc/zcmlmodule/configure.zcml 2005-10-31 05:16:32 UTC (rev 39760)
@@ -17,30 +17,36 @@
</class>
<utility
- provides="zope.app.apidoc.interfaces.IDocumentationModule"
- factory=".ZCMLModule"
- name="ZCML" />
+ provides="zope.app.apidoc.interfaces.IDocumentationModule"
+ factory=".ZCMLModule"
+ name="ZCML" />
<browser:page
- for=".ZCMLModule"
- class=".browser.Menu"
- permission="zope.app.apidoc.UseAPIDoc"
- name="menu.html"
- template="menu.pt" />
+ for=".ZCMLModule"
+ class=".browser.Menu"
+ permission="zope.app.apidoc.UseAPIDoc"
+ name="menu.html"
+ template="menu.pt"
+ layer="zope.app.apidoc.browser.skin.apidoc"
+ />
<browser:page
- for=".ZCMLModule"
- class=".browser.Menu"
- permission="zope.app.apidoc.UseAPIDoc"
- name="staticmenu.html"
- template="static_menu.pt" />
+ for=".ZCMLModule"
+ class=".browser.Menu"
+ permission="zope.app.apidoc.UseAPIDoc"
+ name="staticmenu.html"
+ template="static_menu.pt"
+ layer="zope.app.apidoc.browser.skin.apidoc"
+ />
<browser:page
- for=".Directive"
- class=".browser.DirectiveDetails"
- permission="zope.app.apidoc.UseAPIDoc"
- name="index.html"
- template="index.pt" />
+ for=".Directive"
+ class=".browser.DirectiveDetails"
+ permission="zope.app.apidoc.UseAPIDoc"
+ name="index.html"
+ template="index.pt"
+ layer="zope.app.apidoc.browser.skin.apidoc"
+ />
</configure>
More information about the Zope3-Checkins
mailing list