Source code for zope.app.apidoc.codemodule.browser.zcml

##############################################################################
#
# 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 Element Views

"""
__docformat__ = "reStructuredText"

from zope.configuration.fields import GlobalObject, GlobalInterface, Tokens
from zope.interface.interfaces import IInterface
from zope.schema import getFieldNamesInOrder
from zope.security.proxy import isinstance, removeSecurityProxy
from zope.traversing.api import getParent
from zope.traversing.browser import absoluteURL

from zope.app.apidoc.interfaces import IDocumentationModule
from zope.app.apidoc.utilities import getPythonPath, isReferencable
from zope.app.apidoc.browser.utilities import findAPIDocumentationRoot
from zope.app.apidoc.browser.utilities import findAPIDocumentationRootURL

from zope.app.apidoc.zcmlmodule import quoteNS
from zope.app.apidoc.codemodule.interfaces import IRootDirective

def findDocModule(obj):
    if IDocumentationModule.providedBy(obj):
        return obj
    return findDocModule(getParent(obj))

def _compareAttrs(x, nameOrder):
    if x['name'] in nameOrder:
        valueX = nameOrder.index(x['name'])
    else:
        valueX = 999999
    return valueX


[docs]class DirectiveDetails(object): """Details about ZCML directives.""" context = None request = None def fullTagName(self): context = removeSecurityProxy(self.context) ns, name = context.name if context.prefixes.get(ns): return '%s:%s' %(context.prefixes[ns], name) return name def line(self): return str(removeSecurityProxy(self.context).info.line) def highlight(self): if self.request.get('line') == self.line(): return 'highlight' return '' def url(self): directive = removeSecurityProxy(self.context) subDirective = None # Sub-directives are not directly documented, so use parent parent = getParent(directive) if not (IRootDirective.providedBy(parent) or IRootDirective.providedBy(directive)): subDirective = directive directive = parent ns, name = directive.name # Sometimes ns is `None`, especially in the slug files, where no # namespaces are used. ns = quoteNS(ns or 'ALL') zcml = findAPIDocumentationRoot(self.context, self.request)['ZCML'] if name not in zcml[ns]: ns = 'ALL' link = '%s/ZCML/%s/%s/index.html' % ( findAPIDocumentationRootURL(self.context, self.request), ns, name) if subDirective: link += '#' + subDirective.name[1] return link def objectURL(self, value, field, rootURL): naked = removeSecurityProxy(self.context) bound = field.bind(naked.context) obj = bound.fromUnicode(value) if obj is None: return try: isInterface = IInterface.providedBy(obj) except (AttributeError, TypeError): # pragma: no cover # probably an object that does not like to play nice with the CA isInterface = False # The object might be an instance; in this case get a link to the class if not hasattr(obj, '__name__'): # pragma: no cover obj = getattr(obj, '__class__') path = getPythonPath(obj) if isInterface: apidoc_url = findAPIDocumentationRootURL(self.context, self.request) return '%s/Interface/%s/index.html' % (apidoc_url, path) if isReferencable(path): return rootURL + '/%s/index.html' %(path.replace('.', '/')) def attributes(self): context = removeSecurityProxy(self.context) attrs = [{'name': (ns and context.prefixes[ns]+':' or '') + name, 'value': value, 'url': None, 'values': []} for (ns, name), value in context.attrs.items()] names = context.schema.names(True) rootURL = absoluteURL(findDocModule(self), self.request) for attr in attrs: name = attr['name'] if attr['name'] in names else attr['name'] + '_' field = context.schema.get(name) if isinstance(field, (GlobalObject, GlobalInterface)): attr['url'] = self.objectURL(attr['value'], field, rootURL) elif isinstance(field, Tokens): field = field.value_type values = attr['value'].strip().split() if len(values) == 1: attr['value'] = values[0] attr['url'] = self.objectURL(values[0], field, rootURL) else: for value in values: if isinstance(field, (GlobalObject, GlobalInterface)): url = self.objectURL(value, field, rootURL) else: # pragma: no cover break attr['values'].append({'value': value, 'url': url}) # Make sure that the attributes are in the same order they are defined # in the schema. fieldNames = getFieldNamesInOrder(context.schema) fieldNames = [name.endswith('_') and name[:-1] or name for name in fieldNames] attrs.sort(key=lambda x: _compareAttrs(x, fieldNames)) if not IRootDirective.providedBy(context): return attrs xmlns = [] for uri, prefix in context.prefixes.items(): name = ':' + prefix if prefix else '' xmlns.append({'name': 'xmlns' + name, 'value': uri, 'url': None, 'values': []}) xmlns.sort(key=lambda x: x['name']) return xmlns + attrs def hasSubDirectives(self): return len(removeSecurityProxy(self.context).subs) != 0 def getElements(self): context = removeSecurityProxy(self.context) return context.subs