It turns out we'll still have to wrap content providers because there might

be legacy implementations out there needing it.  Therefore we need to keep
our own ProviderExpression implementation.

Added legacy tests for content providers and viewlets
parent bc64089e
......@@ -12,11 +12,52 @@
#
##############################################################################
"""Provider expression.
This module solely exists for backwards-compatibility. Please import
TALESProviderExpression from zope.contentprovider.tales.
"""
import zope.event
import zope.interface
import zope.component
from zope.tales import expressions
from zope.contentprovider import interfaces, tales
from zope.location.interfaces import ILocation
from Acquisition.interfaces import IAcquirer
class Z2ProviderExpression(expressions.StringExpr):
zope.interface.implements(interfaces.ITALESProviderExpression)
# This is mostly a copy of
# zope.contentprovider.tales.TALESProviderExpression's __call__
# method.
def __call__(self, econtext):
name = super(Z2ProviderExpression, self).__call__(econtext)
context = econtext.vars['context']
request = econtext.vars['request']
view = econtext.vars['view']
# Try to look up the provider.
provider = zope.component.queryMultiAdapter(
(context, request, view), interfaces.IContentProvider, name)
# Provide a useful error message, if the provider was not found.
if provider is None:
raise interfaces.ContentProviderLookupError(name)
# add the __name__ attribute if it implements ILocation
if ILocation.providedBy(provider):
provider.__name__ = name
# ATTN: This is where we are different from
# TALESProviderExpression: We support Acquisition wrapping.
if IAcquirer.providedBy(provider):
provider = provider.__of__(context)
# Insert the data gotten from the context
tales.addTALNamespaceData(provider, econtext)
# Stage 1: Do the state update.
zope.event.notify(interfaces.BeforeUpdateEvent(provider, request))
provider.update()
# BBB
from zope.contentprovider.tales import TALESProviderExpression \
as Z2ProviderExpression
# Stage 2: Render the HTML content.
return provider.render()
......@@ -18,6 +18,8 @@ which mix-in one of the Acquisition base classes without knowing
better) still work.
"""
import Acquisition
from zope.interface import implements
from zope.contentprovider.interfaces import IContentProvider
from Products.Five import BrowserView
from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
......@@ -54,3 +56,52 @@ class Implicit(Acquisition.Implicit):
class ImplicitWithTemplate(Acquisition.Implicit):
template = ViewPageTemplateFile('falcon.pt')
class ExplicitContentProvider(Acquisition.Explicit):
implements(IContentProvider)
def __init__(self, context, request, view):
self.context = context
self.request = request
self.view = view
# Normally, a content provider should set __parent__ to view
# or context. This one doesn't do this on purpose to ensure
# it works without.
def update(self):
# Make sure that the content provider is acquisition wrapped.
assert self.aq_parent == self.context
assert self.aq_base == self
def render(self):
return 'Content provider inheriting from Explicit'
class ExplicitViewlet(Acquisition.Explicit):
def __init__(self, context, request, view, manager):
self.context = context
self.request = request
def update(self):
pass
def render(self):
return 'Viewlet inheriting from Explicit'
class BrowserViewViewlet(BrowserView):
def __init__(self, context, request, view, manager):
# This is the tricky bit. super(...).__init__ wouldn't
# necessarily have to resolve to BrowserView.__init__ because
# <browser:viewlet /> generates classes on the fly with a
# mix-in base class...
super(BrowserViewViewlet, self).__init__(context, request)
self.view = view
self.manager = manager
def update(self):
pass
def render(self):
return 'BrowserView viewlet'
......@@ -63,5 +63,46 @@
permission="zope.Public"
/>
<!-- Content providers and viewlets -->
<adapter
for="* * *"
provides="zope.contentprovider.interfaces.IContentProvider"
factory=".aqlegacy.ExplicitContentProvider"
name="aqlegacyprovider"
/>
<browser:page
for="*"
name="aqlegacyprovider"
template="legacyprovider.pt"
permission="zope.Public"
/>
<browser:viewletManager
name="aqlegacymanager"
permission="zope.Public"
/>
<browser:viewlet
for="*"
class=".aqlegacy.ExplicitViewlet"
name="explicit"
permission="zope.Public"
/>
<browser:viewlet
for="*"
class=".aqlegacy.BrowserViewViewlet"
name="browserview"
permission="zope.Public"
/>
<browser:page
for="*"
name="aqlegacymanager"
template="legacymanager.pt"
permission="zope.Public"
/>
</configure>
\ No newline at end of file
......@@ -119,6 +119,19 @@ first place...):
<p>The falcon has taken flight</p>
Testing legacy content providers and viewlets
=============================================
>>> browser.open('http://localhost/test_folder_1_/aqlegacyprovider')
>>> print browser.contents
<p>Content provider inheriting from Explicit</p>
>>> browser.open('http://localhost/test_folder_1_/aqlegacymanager')
>>> print browser.contents
<p>BrowserView viewlet
Viewlet inheriting from Explicit</p>
Clean up
--------
......
<p tal:content="provider:aqlegacymanager" />
<p tal:content="provider:aqlegacyprovider" />
......@@ -30,7 +30,6 @@ from zope.tales.pythonexpr import PythonExpr
from zope.traversing.interfaces import ITraversable
from zope.traversing.adapters import traversePathElement
from zope.proxy import removeAllProxies
from zope.contentprovider.tales import TALESProviderExpression
import zope.app.pagetemplate.engine
import OFS.interfaces
......@@ -38,6 +37,7 @@ from MultiMapping import MultiMapping
from Acquisition import aq_base
from zExceptions import NotFound, Unauthorized
from Products.Five.browser.providerexpression import Z2ProviderExpression
from Products.PageTemplates import ZRPythonExpr
from Products.PageTemplates.DeferExpr import LazyExpr
from Products.PageTemplates.GlobalTranslationService import getGlobalTranslationService
......@@ -345,7 +345,7 @@ def createZopeEngine():
e.registerType('not', NotExpr)
e.registerType('defer', DeferExpr)
e.registerType('lazy', LazyExpr)
e.registerType('provider', TALESProviderExpression)
e.registerType('provider', Z2ProviderExpression)
e.registerBaseName('modules', SecureModuleImporter)
return e
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment