Skip to content

Commit

Permalink
Merged from trunk r26049:
Browse files Browse the repository at this point in the history
Updated adapter API

as described in:

  http://mail.zope.org/pipermail/zope3-dev/2004-July/011537.html

- query/getAdapter now require a name argument and ignore
  whether the object being adapted provides or conforms to the
  interface.

- New functions 'getAdapterInContext' and 'queryAdapterInContext'
  can be used to do content-dependent simple adapation.  They
  will return the object being adapted if it provides the desired
  interface and will return the result of calling __conform__ if the
  object conforms to the interface.

IMPORTANT

  To do simple adaptation, just call the desired interface:

    adapter = iface(ob) or iface(ob, default)
  • Loading branch information
Jim Fulton committed Jul 6, 2004
1 parent 3fbd2de commit 3ce3429
Showing 1 changed file with 272 additions and 0 deletions.
272 changes: 272 additions & 0 deletions viewmodule/__init__.py
@@ -0,0 +1,272 @@
##############################################################################
#
# 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.
#
##############################################################################
"""View Documentation Module
$Id$
"""
from zope.app import zapi
from zope.interface import implements, classImplements, Interface, Attribute
from zope.component.presentation import SkinRegistration
from zope.component.presentation import DefaultSkinRegistration
from zope.component.presentation import LayerRegistration
from zope.app.apidoc.interfaces import IDocumentationModule
from zope.app.apidoc.utilities import relativizePath
from zope.proxy import removeAllProxies
from zope.app.i18n import ZopeMessageIDFactory as _

# XXX: Temporary hack, since registering an adapter for a particular class is
# broken.
class ISkinRegistration(Interface): pass
classImplements(SkinRegistration, ISkinRegistration)

class ILayerRegistration(Interface): pass
classImplements(LayerRegistration, ILayerRegistration)


class ISkinDocumentation(Interface):
"""Provides useful information of skins for documentation."""

name = Attribute("""Name of the skin.""")

layers = Attribute("A list of ILayerDocumentation objects that represent "
"the layers of this skin.")

doc = Attribute("A string that describes the skin and/or its origin.")

default = Attribute("Set to true, if the skin is the default skin.")


class ILayerDocumentation(Interface):
"""Provides useful information of layers for documentation."""

name = Attribute("""Name of the layer.""")

doc = Attribute("A string that describes the skin and/or its origin.")


class ViewModule(object):
"""Represent the Documentation of all Views."""

implements(IDocumentationModule)

# See zope.app.apidoc.interfaces.IDocumentationModule
title = _('Presentations')

# See zope.app.apidoc.interfaces.IDocumentationModule
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
interface and a presentation type for which views should be found.
By default, the resulting views exclude views that have no required
interface ('None') or are registered to require
'zope.interface.Interface'. To see these additional views, click on
"Show all views".
Once you click on "Show" you will be presented with a list of all
applicable views. The views are sorted by layer. The views are mainly
identified by name, since this is what you use in a URL for
example. Information provided for each view include the required
interface, the presentation type and the permission. If possible, the
system also tries to extract some information from the factory, like the
view class, the template or resource.
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.
Examples::
>>> module = ViewModule()
>>> skins = [skin.name for skin in module.getSkins()]
>>> skins.sort()
>>> skins
['skinA', 'skinB', 'skinC']
>>> pres = zapi.getGlobalService('Presentation')
>>> pres.defineSkin('skinD', ['layer3'])
>>> skins = [skin.name for skin in module.getSkins()]
>>> skins.sort()
>>> skins
['skinA', 'skinB', 'skinC', 'skinD']
"""
# Only the global presentation service defines skins
service = zapi.getGlobalService('Presentation')
skins = [ISkinDocumentation(reg)
for reg in service.registrations()
if isinstance(reg, SkinRegistration)]
skins.sort(lambda x, y: cmp(x.name, y.name))
return skins


class SkinDocumentation(object):
"""Adapter for global skin registration objects.
This is used as a wrapper to output end-user friendlier information. We
also always want the documentation of a layer registration to be a string,
which the 'LayerRegistration.doc' attribute does not guarantee.
Examples::
>>> from zope.app.apidoc.tests import pprint
>>> pres = zapi.getGlobalService('Presentation')
>>> reg = pres._registrations[('skin', 'skinA')]
>>> doc = SkinDocumentation(reg)
>>> doc.name
'skinA'
>>> doc.default
True
>>> pprint(doc.layers)
[LayerDocumentation('default')]
>>> reg = pres._registrations[('skin', 'skinC')]
>>> doc = SkinDocumentation(reg)
>>> doc.name
'skinC'
>>> doc.default
False
>>> pprint(doc.layers)
[LayerDocumentation('layer4'),
LayerDocumentation('layer2'),
LayerDocumentation('layer1'),
LayerDocumentation('default')]
"""
implements(ISkinDocumentation)

def __init__(self, context):
self.context = context

# See ISkinDocumentation
name = property(lambda self: self.context.skin)

def isDefault(self):
"""Return whether this skin is the default skin."""
service = zapi.getService('Presentation')
for registration in service.registrations():
if isinstance(registration, DefaultSkinRegistration) and \
registration.skin == self.context.skin:
return True
return False

# See ISkinDocumentation
default = property(isDefault)

def getLayers(self):
"""Get a list of all layers in this skin.
Each element of the list is a LayerDocumentation component.
"""
service = zapi.getService('Presentation')
layers = [ILayerDocumentation(reg)
for reg in service.registrations()
if (isinstance(reg, LayerRegistration) and
reg.layer in self.context.layers)]


if 'default' in self.context.layers:
default = LayerRegistration('default',
'This is a predefined skin.')
layers.append(ILayerDocumentation(default))
return layers

# See ISkinDocumentation
layers = property(getLayers)

def getDoc(self):
"""Generate documentation."""
if isinstance(self.context.doc, (str, unicode)):
return self.context.doc

# We can safely assume that for global skin registrations we have an
# configuration info object.
info = removeAllProxies(self.context.doc)
doc = _('$file (line $line)')
doc.mapping = {'file': relativizePath(info.file),
'line': info.line}
return doc

# See ISkinDocumentation
doc = property(getDoc)

def __repr__(self):
"""Representation of the object in a doctest-friendly format."""
return '%s(%r, %r)' % (
self.__class__.__name__,
self.name, self.context.layers)


class LayerDocumentation(object):
"""Adapter for global layer registration objects.
This is used as a wrapper to output end-user friendlier information. We
also always want the documentation of a layer registration to be a string,
which the 'LayerRegistration.doc' attribute does not guarantee.
Examples::
>>> from zope.app.apidoc.tests import pprint
>>> LayerRegistration = type('LayerRegistration', (object,),
... {'layer': u'help', 'doc': u'documentation'})
>>> ParserInfo = type('ParserInfo', (object,),
... {'file': u'Zope3/src/zope/app/configure.zcml',
... 'line': 5})
>>> reg = LayerRegistration()
>>> layerdoc = LayerDocumentation(reg)
>>> layerdoc.name
u'help'
>>> layerdoc.doc
u'documentation'
>>> reg.doc = ParserInfo()
>>> layerdoc.doc
u'$file (line $line)'
>>> pprint(layerdoc.doc.mapping)
[('file', u'Zope3/src/zope/app/configure.zcml'), ('line', 5)]
"""
implements(ILayerDocumentation)

def __init__(self, context):
self.context = context

# See ILayerDocumentation
name = property(lambda self: self.context.layer)

def getDoc(self):
"""Generate documentation."""
if isinstance(self.context.doc, (str, unicode)):
return self.context.doc

# We can safely assume that for global layer registrations we have an
# configuration info object.
info = removeAllProxies(self.context.doc)
doc = _('$file (line $line)')
doc.mapping = {'file': relativizePath(info.file),
'line': info.line}
return doc

# See ILayerDocumentation
doc = property(getDoc)

def __repr__(self):
"""Representation of the object in a doctest-friendly format."""
return '%s(%r)' % (self.__class__.__name__, self.name)

0 comments on commit 3ce3429

Please sign in to comment.