Skip to content

Commit

Permalink
1) Fix up some code in APIDoc dealing with new attrs of registration …
Browse files Browse the repository at this point in the history
…objects.

   Not sure if this will break its handling of old persistent registration objects.
2) Expose the template object itself.
  • Loading branch information
philikon committed Feb 28, 2006
1 parent b20d055 commit 44140d7
Show file tree
Hide file tree
Showing 2 changed files with 189 additions and 0 deletions.
188 changes: 188 additions & 0 deletions presentation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
##############################################################################
#
# 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.
#
##############################################################################
"""Views/Presentation Utilities
$Id$
"""
from types import ClassType, FunctionType
from zope.component.site import AdapterRegistration
from zope.interface import Interface

from zope.app import zapi
from zope.app.apidoc.utilities import getPythonPath, relativizePath
from zope.app.apidoc.utilities import getPermissionIds
from zope.app.apidoc.component import getParserInfoInfoDictionary
from zope.app.apidoc.component import getInterfaceInfoDictionary
from zope.app.publisher.browser.icon import IconViewFactory

from zope.publisher.interfaces import IRequest, ILayer
from zope.publisher.interfaces.browser import IBrowserRequest
from zope.publisher.interfaces.xmlrpc import IXMLRPCRequest
from zope.publisher.interfaces.http import IHTTPRequest
from zope.publisher.interfaces.ftp import IFTPRequest

SPECIFIC_INTERFACE_LEVEL = 1
EXTENDED_INTERFACE_LEVEL = 2
GENERIC_INTERFACE_LEVEL = 4

BROWSER_DIRECTIVES_MODULE = 'zope.app.publisher.browser.viewmeta'
XMLRPC_DIRECTIVES_MODULE = 'zope.app.publisher.xmlrpc.metaconfigure'
JSONRPC_DIRECTIVES_MODULE = 'jsonserver.metaconfigure'

def getViewFactoryData(factory):
"""Squeeze some useful information out of the view factory"""
info = {'path': None, 'url': None, 'template': None, 'resource': None,
'referencable': True}

# Always determine the most basic factory
# Commonly, factories are wrapped to provide security or location, for
# example. If those wrappers play nice, then they provide a `factory`
# attribute, that points to the original factory.
while hasattr(factory, 'factory'):
factory = factory.factory

if hasattr(factory, '__name__') and \
factory.__name__.startswith('SimpleViewClass'):
# In the case of a SimpleView, the base is really what we are
# interested in. Usually the first listed class is the interesting one.
base = factory.__bases__[0]
info['path'] = base.__module__ + '.' + base.__name__
info['template'] = relativizePath(factory.index.filename)
info['template_obj'] = factory.index

# Basic Type is a factory
elif isinstance(factory, (str, unicode, float, int, list, tuple)):
info['referencable'] = False

elif factory.__module__ is not None and \
factory.__module__.startswith(BROWSER_DIRECTIVES_MODULE):
info['path'] = getPythonPath(factory.__bases__[0])

# XML-RPC view factory, generated during registration
elif factory.__module__ is not None and \
factory.__module__.startswith(XMLRPC_DIRECTIVES_MODULE):

# Those factories are method publisher and security wrapped
info['path'] = getPythonPath(factory.__bases__[0].__bases__[0])

# JSON-RPC view factory, generated during registration
# This is needed for the 3rd party jsonserver implementation
# TODO: See issue http://www.zope.org/Collectors/Zope3-dev/504, ri
elif factory.__module__ is not None and \
factory.__module__.startswith(JSONRPC_DIRECTIVES_MODULE):

# Those factories are method publisher and security wrapped
info['path'] = getPythonPath(factory.__bases__[0].__bases__[0])

# A factory that is a class instance; since we cannot reference instances,
# reference the class.
elif not hasattr(factory, '__name__'):
info['path'] = getPythonPath(factory.__class__)

# A simple class-based factory
elif type(factory) in (type, ClassType):
info['path'] = getPythonPath(factory)

# We have tried our best; just get the Python path as good as you can.
else:
info['path'] = getPythonPath(factory)

if info['referencable']:
info['url'] = info['path'].replace('.', '/')

if isinstance(factory, IconViewFactory):
info['resource'] = factory.rname

return info


def getPresentationType(iface):
"""Get the presentation type from a layer interface."""
# Note that the order of the requests matters here, since we want to
# inspect the most specific one first. For example, IBrowserRequest is also
# an IHTTPRequest.
for type in [IBrowserRequest, IXMLRPCRequest, IHTTPRequest, IFTPRequest]:
if iface.isOrExtends(type):
return type
return iface


def getViews(iface, type=IRequest):
"""Get all view registrations for a particular interface."""
gsm = zapi.getGlobalSiteManager()
for reg in gsm.registrations():
if (isinstance(reg, AdapterRegistration) and
len(reg.required) > 0 and
reg.required[-1] is not None and
reg.required[-1].isOrExtends(type)):

for required_iface in reg.required[:-1]:
if required_iface is None or iface.isOrExtends(required_iface):
yield reg


def filterViewRegistrations(regs, iface, level=SPECIFIC_INTERFACE_LEVEL):
"""Return only those registrations that match the specifed level"""
for reg in regs:
if level & GENERIC_INTERFACE_LEVEL:
for required_iface in reg.required[:-1]:
if required_iface in (Interface, None):
yield reg
continue

if level & EXTENDED_INTERFACE_LEVEL:
for required_iface in reg.required[:-1]:
if required_iface is not Interface and \
iface.extends(required_iface):
yield reg
continue

if level & SPECIFIC_INTERFACE_LEVEL:
for required_iface in reg.required[:-1]:
if required_iface is iface:
yield reg
continue


def getViewInfoDictionary(reg):
"""Build up an information dictionary for a view registration."""
# get configuration info
if isinstance(reg.info, (str, unicode)):
doc = reg.info
zcml = None
else:
doc = None
zcml = getParserInfoInfoDictionary(reg.info)

# get layer
layer = None
if ILayer.providedBy(reg.required[-1]):
layer = getInterfaceInfoDictionary(reg.required[-1])


info = {'name' : reg.name or '<i>no name</i>',
'type' : getPythonPath(getPresentationType(reg.required[-1])),
'factory' : getViewFactoryData(reg.factory),
'required': [getInterfaceInfoDictionary(iface)
for iface in reg.required],
'provided' : getInterfaceInfoDictionary(reg.provided),
'layer': layer,
'doc': doc,
'zcml': zcml
}

# Educated guess of the attribute name
info.update(getPermissionIds('publishTraverse', klass=reg.factory))

return info
1 change: 1 addition & 0 deletions presentation.txt
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ the template path:
'referencable': True,
'resource': None,
'template': 'zope/app/apidoc/browser/index.pt',
'template_obj': <BoundPageTemplateFile of None>,
'url': 'zope/app/pagetemplate/simpleviewclass/simple'}

So in the result above we see what the function returns. It is a dictionary
Expand Down

0 comments on commit 44140d7

Please sign in to comment.