Source code for zope.app.apidoc.zcmlmodule

##############################################################################
#
# Copyright (c) 2004 Zope Foundation 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.
#
##############################################################################
"""ZCML Documentation module

The ZCML documentation module reads all of the meta directives (but does not
execute them) and uses the collected data to generate the tree. The result of
the evaluation is stored in thread-global variables, so that we have to parse
the files only once.

"""
__docformat__ = 'restructuredtext'

from zope.configuration import docutils
from zope.i18nmessageid import ZopeMessageFactory as _
from zope.interface import implementer
from zope.location.interfaces import ILocation

import zope.app.appsetup.appsetup
from zope.app.apidoc.interfaces import IDocumentationModule
from zope.app.apidoc.utilities import ReadContainerBase
from zope.app.apidoc.utilities import DocumentationModuleBase

# Caching variables, so that the meta-ZCML files need to be read only once
namespaces = None
subdirs = None

[docs]def quoteNS(ns): """Quotes a namespace to make it URL-secure.""" ns = ns.replace(':', '_co_') ns = ns.replace('/', '_sl_') return ns
[docs]def unquoteNS(ns): """Un-quotes a namespace from a URL-secure version.""" ns = ns.replace('_sl_', '/') ns = ns.replace('_co_', ':') return ns
@implementer(ILocation)
[docs]class Namespace(ReadContainerBase): """Simple namespace object for the ZCML Documentation Module. This container has :class:`Directive` items as its values. """ def __init__(self, parent, name): self.__parent__ = parent self.__realname__ = name self.__name__ = self.getQuotedName()
[docs] def getShortName(self): """Get the short name of the namespace.""" name = self.__realname__ if name.startswith('http://namespaces.zope.org/'): name = name[27:] return name
[docs] def getFullName(self): """Get the full name of the namespace.""" return self.__realname__
[docs] def getQuotedName(self): """Get the full name, but quoted for a URL.""" name = self.getFullName() name = quoteNS(name) return name
def get(self, key, default=None): _makeDocStructure() ns = self.getFullName() if key not in namespaces[ns]: return default schema, handler, info = namespaces[ns][key] sd = subdirs.get((ns, key), []) directive = Directive(self, key, schema, handler, info, sd) return directive def items(self): _makeDocStructure() return sorted(((key, self.get(key)) for key in namespaces[self.getFullName()].keys()))
@implementer(ILocation)
[docs]class Directive(object): """Represents a ZCML Directive.""" def __init__(self, ns, name, schema, handler, info, subdirs): self.__parent__ = ns self.__name__ = name self.schema = schema self.handler = handler self.info = info self.subdirs = subdirs
@implementer(IDocumentationModule)
[docs]class ZCMLModule(DocumentationModuleBase): r""" Represent the Documentation of all ZCML namespaces. The items of the container are tuples of globally known namespaces found in the :func:`appsetup config context <zope.app.appsetup.appsetup.getConfigContext>`. """ #: Title. title = _('ZCML Reference') #: 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. The documentation contents for each directive tells you all the available attributes and their semantics. It also provides a link to the interface the directive confirms to. If available, it will even tell you the file the directive was declared in. At the end a list of available subdirectives is given, also listing the implemented interface and available attributes. """)
[docs] def get(self, key, default=None): """Get the namespace by name; long and abbreviated names work. """ _makeDocStructure() key = unquoteNS(key) if key in namespaces: return Namespace(self, key) # TODO: Search for other packages outside this root. full_key = 'http://namespaces.zope.org/' + key if full_key in namespaces: return Namespace(self, full_key) return default
def items(self): _makeDocStructure() result = [] for key in namespaces: namespace = Namespace(self, key) # We need to make sure that we use the quoted URL as key result.append((namespace.getQuotedName(), namespace)) result.sort() return result
def _makeDocStructure(): # Some trivial caching global namespaces global subdirs if namespaces is not None and subdirs is not None: return context = zope.app.appsetup.appsetup.getConfigContext() assert context is not None namespaces, subdirs = docutils.makeDocStructures(context) # Empty keys are not so good for a container if '' in namespaces: namespaces['ALL'] = namespaces[''] del namespaces[''] def _clear(): global namespaces global subdirs namespaces = None subdirs = None from zope.testing.cleanup import addCleanUp addCleanUp(_clear)