diff --git a/browser/apidoc.py b/browser/apidoc.py index 4918c186..f1f4b6f2 100644 --- a/browser/apidoc.py +++ b/browser/apidoc.py @@ -17,6 +17,8 @@ """ __docformat__ = 'restructuredtext' +from zope.i18n import translate +from zope.security.proxy import removeSecurityProxy from zope.app.apidoc.utilities import renderText class APIDocumentationView(object): @@ -28,8 +30,10 @@ def getModuleList(self): Example:: >>> from zope.app.apidoc import APIDocumentation + >>> from zope.publisher.browser import TestRequest >>> view = APIDocumentationView() + >>> view.request = TestRequest() >>> view.context = APIDocumentation(None, '++apidoc++') >>> info = view.getModuleList() >>> info = [(i['name'], i['title']) for i in info] @@ -38,8 +42,15 @@ def getModuleList(self): """ items = list(self.context.items()) items.sort() - return [{'name': name, - 'title': module.title, - 'description': renderText(module.description, - module.__class__.__module__)} - for name, module in items ] + result = [] + for name, module in items: + description = removeSecurityProxy(module.description) + description = translate(description, context=self.request, + default=description) + description = renderText(description, module.__class__.__module__) + if not isinstance(description, unicode): + description = unicode(description, "utf-8") + result.append({'name': name, + 'title': module.title, + 'description': description}) + return result diff --git a/classmodule/__init__.py b/classmodule/__init__.py index 81870bf0..09fad285 100644 --- a/classmodule/__init__.py +++ b/classmodule/__init__.py @@ -549,7 +549,7 @@ class ClassModule(Module): title = _('Classes') # See zope.app.apidoc.interfaces.IDocumentationModule - description = """ + description = _(""" This module allows you to get an overview of the modules and classes defined in the Zope 3 framework and its supporting packages. There are two methods to navigate through the modules to find the classes you are @@ -569,7 +569,7 @@ class is found, it is represented as a bold entry in the list. implemented interfaces, attributes and methods, but it also lists the interface that requires a method or attribute to be implemented and the permissions required to access it. - """ + """) rootModules = ['ZConfig', 'ZODB', 'transaction', 'zdaemon', 'zope'] def __init__(self): diff --git a/ifacemodule/__init__.py b/ifacemodule/__init__.py index 38d293a1..66d2c73c 100644 --- a/ifacemodule/__init__.py +++ b/ifacemodule/__init__.py @@ -75,7 +75,7 @@ class InterfaceModule(ReadContainerBase): title = _('Interfaces') # See zope.app.apidoc.interfaces.IDocumentationModule - description = """ + description = _(""" All used and important interfaces are registered through the interface service. While it would be possible to just list all attributes, it is hard on the user to read such an overfull list. Therefore, interfaces that @@ -85,7 +85,7 @@ class InterfaceModule(ReadContainerBase): information, including of course the declared attributes/fields and methods, but also available adapters, services and utilities that provide this interface. - """ + """) def get(self, key, default=None): """See zope.app.interfaces.container.IReadContainer""" diff --git a/servicemodule/__init__.py b/servicemodule/__init__.py new file mode 100644 index 00000000..fdc07cc1 --- /dev/null +++ b/servicemodule/__init__.py @@ -0,0 +1,115 @@ +############################################################################## +# +# 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. +# +############################################################################## +"""Service Documentation Module + +$Id$ +""" +from zope.interface import implements +from zope.component import ComponentLookupError + +from zope.app import zapi +from zope.app.location.interfaces import ILocation +from zope.app.apidoc.interfaces import IDocumentationModule +from zope.app.apidoc.utilities import ReadContainerBase +from zope.app.servicenames import Services +from zope.app.i18n import ZopeMessageIDFactory as _ + +class Service(object): + """Object representing a service in the API documentation""" + + implements(ILocation) + + def __init__(self, parent, name, iface, impl): + """Initialize Service object.""" + self.__parent__ = parent + self.__name__ = name + self.interface = iface + self.implementations = impl + + +class ServiceModule(ReadContainerBase): + r"""Represent the Documentation of all Interfaces. + + This documentation is implemented using a simply 'IReadContainer'. The + items of the container are all the interfaces listed in the closest + interface service and above. + + Demonstration:: + + >>> from zope.app.tests import placelesssetup as setup + >>> setup.setUp() + + >>> module = ServiceModule() + + >>> module.get('Utilities').__name__ + 'Utilities' + + >>> module.get('foo') is None + True + + >>> print '\n'.join([id for id, iface in module.items()][:4]) + Adapters + Presentation + Services + Utilities + + >>> setup.tearDown() + """ + + implements(IDocumentationModule) + + # See zope.app.apidoc.interfaces.IDocumentationModule + title = _('Services') + + # See zope.app.apidoc.interfaces.IDocumentationModule + description = _(""" + The services module let's the reader browse through all defined + services. It uses the service name as a key. In general services can be + queried using:: + + >>> from zope.app import zapi + >>> service = zapi.getService('ServiceName') + + Here we used 'None' as the context by default, which means that + always a global service is returned. If you use an object that has + a location in the traversal tree, you will generally get the closest + service, which includes the local ones. The first argument is the + service name, which you can replace with any name listed in this + module's menu. + + For each service, the attributes and methods of the service interface are + presented. At the end a list of implementations is given. + """) + + def get(self, key, default=None): + """See zope.app.container.interfaces.IReadContainer""" + service = zapi.getService(Services) + items = service.getServiceDefinitions() + + for name, iface in items: + if name == key: + try: + impl = service.getService(name) + except ComponentLookupError: + impl = None + return Service(self, name, iface, [impl]) + + return default + + def items(self): + """See zope.app.container.interfaces.IReadContainer""" + service = zapi.getService(Services) + items = service.getServiceDefinitions() + items.sort() + return [(name, self.get(name)) for name, iface in items] diff --git a/utilitymodule/__init__.py b/utilitymodule/__init__.py index b278a7af..06298d97 100644 --- a/utilitymodule/__init__.py +++ b/utilitymodule/__init__.py @@ -127,7 +127,7 @@ class UtilityModule(ReadContainerBase): title = _('Utilities') # See zope.app.apidoc.interfaces.IDocumentationModule - description = """ + description = _(""" Utilities are also nicely registered in a service, so that it is easy to create a listing of available utilities. A utility is identified by the providing interface and a name, which can be empty. The menu provides you @@ -136,7 +136,7 @@ class UtilityModule(ReadContainerBase): Again, the documentation of a utility lists all the attributes/fields and methods the utility provides and provides a link to the implementation. - """ + """) def get(self, key, default=None): parts = key.split('.') diff --git a/viewmodule/__init__.py b/viewmodule/__init__.py index 5be566a6..9d551285 100644 --- a/viewmodule/__init__.py +++ b/viewmodule/__init__.py @@ -65,7 +65,7 @@ class ViewModule(object): title = _('Presentations') # See zope.app.apidoc.interfaces.IDocumentationModule - description = """ + description = _(""" The Presentations (or Views) module is somewhat crazy, since a view or resource cannot be identified by a single interface or name, but of four to five pieces of information. Conclusively, the menu lets you select an @@ -87,7 +87,7 @@ class ViewModule(object): Completely independent of all this, there is a link "Show Skins, Layers and Usages" that brings you to a simple screen that shows the mapping of the layers to skins and provides a list of available usages. - """ + """) def getSkins(self): """Get the names of all available skins. diff --git a/zcmlmodule/__init__.py b/zcmlmodule/__init__.py index 9f0cc543..17a4f16d 100644 --- a/zcmlmodule/__init__.py +++ b/zcmlmodule/__init__.py @@ -192,7 +192,7 @@ class ZCMLModule(ReadContainerBase): title = _('ZCML Reference') # See zope.app.apidoc.interfaces.IDocumentationModule - description = """ + description = _(""" This module presents you with a complete list of ZCML directives and serves therefore well as reference. The menu provides you with a tree that organizes the directives by namespaces. @@ -203,7 +203,7 @@ class ZCMLModule(ReadContainerBase): file the directive was declared in. At the end a list of available subdirectives is given, also listing the implemented interface and available attributes. - """ + """) def _makeDocStructure(self): # Some trivial caching