Ticket #13728 (new Bug)

Opened 3 years ago

Using Unicode TALES string: expressions cause KeyError: 'context'

Reported by: davidjb Owned by:
Priority: minor Milestone: 4.x
Component: Unknown Version:
Keywords: Cc:

Description

When trying to use a TALES string: expression, a KeyError is produced because the resulting expression context doesn't appear to have the required keys. Specifically, problematic expressions appear to be limited to those prefixed with "string:", for example:

u'string:${portal_url}'
u'string:${portal_url}/foobar'

This only causes an issue when the TALES expression is Unicode. Switching the above to byte strings produces to no issue. This isn't a solution, however, as submissions off forms (such as the ones being received in plone.app.contentrules) will likely be Unicode.

To reproduce:

from Products.CMFPlone.utils import getToolByName
from Products.CMFCore.Expression import Expression, createExprContext
portal_url = getToolByName(context, 'portal_url')
portal = portal_url.getPortalObject()
ec = createExprContext(context, portal, None)
expr = Expression(u'string:${portal_url}/foobar')
#Fails with ``KeyError: 'context'`` because ec.contexts['context'] is misssing
print expr(ec) 

#Succeeds in outputting URL
expr = Expression('string:${portal_url}')
print expr(ec) 

My thinking is that the problem is either with Products.CMFCore.Expression.createExprContext not adding enough into the contexts dictionary or a problem with the Products.PageTemplates.Expressions.ZopeContext._handleText (line 250) function expecting incorrect keys. It's worth noting that if a UnicodeDecodeError happens in that latter function, it expects a 'template' key to be present within the expression context as well -- something else that is missing.

I've worked around this issue for using TALES in plone.app.contentrules temporarily (in  https://github.com/plone/plone.app.contentrules/commit/f825dd9ffb6c434bd41c33219bc77e6f06c96bea) but the issue would affect any caller attempting to work with such an expression in the rest of Plone.

Example traceback from plone.app.contentrules:

Traceback (innermost last):
  Module ZPublisher.Publish, line 60, in publish
  Module ZPublisher.mapply, line 77, in mapply
  Module ZPublisher.Publish, line 46, in call_object
  Module plone.z3cform.layout, line 66, in __call__
  Module plone.z3cform.layout, line 50, in update
  Module plone.dexterity.browser.add, line 112, in update
  Module plone.z3cform.fieldsets.extensible, line 59, in update
  Module plone.z3cform.patch, line 30, in GroupForm_update
  Module z3c.form.group, line 141, in update
  Module plone.app.z3cform.csrf, line 21, in execute
  Module z3c.form.action, line 98, in execute
  Module z3c.form.button, line 315, in __call__
  Module z3c.form.button, line 170, in __call__
  Module plone.dexterity.browser.add, line 99, in handleAdd
  Module z3c.form.form, line 247, in createAndAdd
  Module plone.dexterity.browser.add, line 78, in add
  Module plone.dexterity.utils, line 167, in addContentToContainer
  Module OFS.ObjectManager, line 358, in _setObject
  Module zope.event, line 31, in notify
  Module zope.component.event, line 24, in dispatch
  Module zope.component._api, line 136, in subscribers
  Module zope.component.registry, line 321, in subscribers
  Module zope.interface.adapter, line 585, in subscribers
  Module plone.app.contentrules.handlers, line 179, in added
  Module plone.app.contentrules.handlers, line 118, in execute
  Module plone.contentrules.engine.executor, line 27, in __call__
  Module plone.contentrules.rule.rule, line 44, in __call__
  Module plone.app.contentrules.conditions.talesexpression, line 63, in __call__
  Module Products.CMFCore.Expression, line 47, in __call__
  Module Products.PageTemplates.Expressions, line 383, in __call__
  Module Products.PageTemplates.Expressions, line 226, in evaluateText
  Module Products.PageTemplates.Expressions, line 250, in _handleText
KeyError: 'context'
Note: See TracTickets for help on using tickets.