Commit c65b1dcc authored by Jérome Perrin's avatar Jérome Perrin

TextDocument: only call substitution method if it is used

One typical usage of substitution is Event_setTextContentFromNotificationMessage
which uses notification message to set the subject and the body of mail
message, which calls the substitution method twice, even if in most of
the cases the subject does not embed any substitution.
parent bcb5e588
Pipeline #40213 failed with stage
in 0 seconds
...@@ -172,6 +172,27 @@ class TestNotificationMessageModule(ERP5TypeTestCase): ...@@ -172,6 +172,27 @@ class TestNotificationMessageModule(ERP5TypeTestCase):
self.assertRaises(KeyError, doc.convert, 'html', safe_substitute=False) self.assertRaises(KeyError, doc.convert, 'html', safe_substitute=False)
self.assertRaises(KeyError, doc.asSubjectText, safe_substitute=False) self.assertRaises(KeyError, doc.asSubjectText, safe_substitute=False)
def test_lazy_substitution(self):
"""Tests that substitution method is not called when content does
not access any substitution variable.
"""
module = self.portal.notification_message_module
createZODBPythonScript(self.portal,
'NotificationMessage_getErrorSubstitutionMapping',
'**kw',
'''raise ValueError("should not be called")''')
doc = module.newContent(portal_type='Notification Message',
title='title',
content_type='text/plain',
text_content='text_content',
text_content_substitution_mapping_method_id=
'NotificationMessage_getErrorSubstitutionMapping')
mime, text = doc.convert('txt')
self.assertEqual('text/plain', mime)
self.assertEqual('text_content', text.rstrip())
self.assertEqual('title', doc.asSubjectText())
def test_substitution_lazy_dict(self): def test_substitution_lazy_dict(self):
"""Substitution script just needs to return an object implementing """Substitution script just needs to return an object implementing
__getitem__ protocol. __getitem__ protocol.
......
...@@ -89,16 +89,25 @@ class TextDocument(CachedConvertableMixin, BaseConvertableFileMixin, TextContent ...@@ -89,16 +89,25 @@ class TextDocument(CachedConvertableMixin, BaseConvertableFileMixin, TextContent
' mapping method %s from %r, so the content will not be' ' mapping method %s from %r, so the content will not be'
' substituted.' % (method_id, self.getRelativeUrl())) ' substituted.' % (method_id, self.getRelativeUrl()))
return text return text
mapping = method(**kw)
# unicode() # unicode()
is_str = isinstance(text, str) is_str = isinstance(text, str)
if six.PY2 and is_str: if six.PY2 and is_str:
text = str2unicode(text) text = str2unicode(text)
class UnicodeMapping: class LazyUnicodeMapping:
"""Lazily calls the substitution method if some substitution is needed
and manage the str/unicode on py2.
"""
_mapping = None
@property
def mapping(self):
if self._mapping is None:
self._mapping = method(**kw)
return self._mapping
def __getitem__(self, item): def __getitem__(self, item):
v = mapping[item] v = self.mapping[item]
if six.PY2: if six.PY2:
if isinstance(v, str): if isinstance(v, str):
v = str2unicode(v) v = str2unicode(v)
...@@ -108,7 +117,7 @@ class TextDocument(CachedConvertableMixin, BaseConvertableFileMixin, TextContent ...@@ -108,7 +117,7 @@ class TextDocument(CachedConvertableMixin, BaseConvertableFileMixin, TextContent
if not isinstance(v, str): if not isinstance(v, str):
v = str(v) v = str(v)
return v return v
unicode_mapping = UnicodeMapping() unicode_mapping = LazyUnicodeMapping()
if safe_substitute: if safe_substitute:
text = Template(text).safe_substitute(unicode_mapping) text = Template(text).safe_substitute(unicode_mapping)
......
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