[Zope-dev] Path expression traversal in z3c.pt

Albertas Agejevas alga at pov.lt
Fri Sep 24 07:01:47 EDT 2010


Hi,

I tried switching to z3c.pt in one of our projects and found an
incompatibility with zope.app.pagetemplate.  It is not obvious whether
it is a bug or a feature, so I thought I should bring it up here.
Here is a doctest illustrating the incompatibility.

First, let's set up both types of templates:

    >>> from zope.pagetemplate.pagetemplate import PageTemplate
    >>> from zope.app.pagetemplate.engine import TrustedAppPT
    >>> class ZopePageTemplate(TrustedAppPT, PageTemplate):
    ...      def __init__(self, source):
    ...           self.pt_edit(source, '')

    >>> from z3c.pt.pagetemplate import PageTemplate as Z3CPageTemplate
    >>> from z3c.pt.expressions import path_translator
    >>> from zope.component import provideUtility
    >>> provideUtility(path_translator, name="path")

Normally, traversing in path expressions prefers attributes over
items, but makes an exception for dict objects.

    >>> arg = {'copy': 1}
    >>> ZopePageTemplate("<p tal:content='options/arg/copy'/>")(arg=arg)
    u'<p>1</p>\n'

    >>> Z3CPageTemplate("<p tal:content='options/arg/copy'/>")(arg=arg)
    u'<p>1</p>'

However, attribute lookup takes precedence for other dict-like objects:

    >>> from UserDict import UserDict
    >>> arg = UserDict()
    >>> arg['copy'] = '1'

    >>> ZopePageTemplate("<p tal:content='options/arg/copy'/>")(arg=arg)
    u"<p>{'copy': '1'}</p>\n"

    >>> Z3CPageTemplate("<p tal:content='options/arg/copy'/>")(arg=arg)
    u"<p>{'copy': '1'}</p>"

However, Zope lets the user override this behaviour by providing a
traversing adapter:

    >>> from zope.traversing.interfaces import ITraversable
    >>> from zope.interface import implements
    >>> class MyDict(UserDict):
    ...     implements(ITraversable)
    ...     def traverse(self, name, path):
    ...          return self[name]

    >>> arg = MyDict()
    >>> arg['copy'] = '1'
    >>> ZopePageTemplate("<p tal:content='options/arg/copy'/>")(arg=arg)
    u'<p>1</p>\n'

    >>> Z3CPageTemplate("<p tal:content='options/arg/copy'/>")(arg=arg)
    u"<p>{'copy': '1'}</p>"

Here the behaviour diverges, as
zope.app.pagetemplates.engine.ZopeTraverser looks for an ITraversable
adapter and gets DefaultTraversable to implement the default
behaviour, whereas z3c.pt.expressions.ZopeTraverser tries the
attribute lookup before looking up the adapter.

To summarize, z3c.pt prefers attribute lookup to traversable adapters,
whereas zope.app.pagetemplate doesn't.

Is this divergence a bug or a feature?  Anyhow, it should be either
unified or documented.

Albertas
-- 
http://pov.lt -- ZTK/BlueBream consulting and development


More information about the Zope-Dev mailing list