Modify

Opened 3 years ago

Last modified 21 months ago

#8677 new defect

"prefix" not defined when sending email

Reported by: anonymous Owned by: hasienda
Priority: normal Component: AnnouncerPlugin
Severity: normal Keywords: email notification template decorator
Cc: rjollos, doki_pen Trac Release: 0.12

Description

Having an issue with TracAnnouncer and sending emails.

Python: version 2.4
TracAnnouncer: 0.12.1.dev

I'm trying to change some information in a ticket and the following error appears in the log. No emails seem to work at all.

2011-04-05 13:27:50,279 Trac[api] ERROR: AnnouncementSystem failed.
Traceback (most recent call last):
  File "/usr/lib/python2.4/site-packages/TracAnnouncer-0.12.1.dev-py2.4.egg/announcer/api.py", line 560, in _real_send
    evt)
  File "/usr/lib/python2.4/site-packages/TracAnnouncer-0.12.1.dev-py2.4.egg/announcer/distributors/mail.py", line 355, in distribute
    self._do_send(transport, event, k, v, fmtdict[k])
  File "/usr/lib/python2.4/site-packages/TracAnnouncer-0.12.1.dev-py2.4.egg/announcer/distributors/mail.py", line 508, in _do_send
    decorator.decorate_message(event, rootMessage, decorators)
  File "/usr/lib/python2.4/site-packages/TracAnnouncer-0.12.1.dev-py2.4.egg/announcer/email_decorators.py", line 237, in decorate_message
    return next_decorator(event, message, decorates)
  File "/usr/lib/python2.4/site-packages/TracAnnouncer-0.12.1.dev-py2.4.egg/announcer/util/mail.py", line 48, in next_decorator
    return next.decorate_message(event, message, decorates)
  File "/usr/lib/python2.4/site-packages/TracAnnouncer-0.12.1.dev-py2.4.egg/announcer/email_decorators.py", line 203, in decorate_message
    return next_decorator(event, message, decorates)
  File "/usr/lib/python2.4/site-packages/TracAnnouncer-0.12.1.dev-py2.4.egg/announcer/util/mail.py", line 48, in next_decorator
    return next.decorate_message(event, message, decorates)
  File "/usr/lib/python2.4/site-packages/TracAnnouncer-0.12.1.dev-py2.4.egg/announcer/email_decorators.py", line 174, in decorate_message
    action=event.category
  File "/usr/lib/python2.4/site-packages/Genshi-0.6-py2.4.egg/genshi/core.py", line 183, in render
  File "/usr/lib/python2.4/site-packages/Genshi-0.6-py2.4.egg/genshi/output.py", line 57, in encode
  File "/usr/lib/python2.4/site-packages/Genshi-0.6-py2.4.egg/genshi/output.py", line 569, in __call__
  File "/usr/lib/python2.4/site-packages/Genshi-0.6-py2.4.egg/genshi/core.py", line 272, in _ensure
  File "/usr/lib/python2.4/site-packages/Genshi-0.6-py2.4.egg/genshi/template/base.py", line 605, in _include
  File "/usr/lib/python2.4/site-packages/Genshi-0.6-py2.4.egg/genshi/template/base.py", line 565, in _flatten
  File "/usr/lib/python2.4/site-packages/Genshi-0.6-py2.4.egg/genshi/template/base.py", line 277, in _eval_expr
  File "/usr/lib/python2.4/site-packages/Genshi-0.6-py2.4.egg/genshi/template/eval.py", line 178, in evaluate
  File "<string>", line 1, in <Expression u'prefix'>
  File "/usr/lib/python2.4/site-packages/Genshi-0.6-py2.4.egg/genshi/template/eval.py", line 309, in lookup_name
  File "/usr/lib/python2.4/site-packages/Genshi-0.6-py2.4.egg/genshi/template/eval.py", line 410, in undefined
UndefinedError: "prefix" not defined

Attachments (0)

Change History (5)

comment:1 Changed 21 months ago by hasienda

  • Cc rjollos doki_pen added
  • Keywords email notification template decorator added
  • Owner changed from doki_pen to hasienda

So this is certainly a local configuration issue. Here is how I found out about it:

I've traced the questionable code back to http://trac-hacks.org/browser/announcerplugin/trunk/announcer/email_decorators.py?rev=9675.

The error raised in template render time, when the email subject has been constructed from a Genshi NewTextTemplate. At the revision above the template is configurable by Option 'ticket_email_subject' defaulting to

"Ticket #${ticket.id}: ${ticket['summary']} {% if action %}[${action}]{% end %}"

Luckily I happen to own some historic announcer configuration sections here, and interestingly there is one with the following line:

[announcer]
ticket_subject_template = $prefix #$ticket.id: $summary

I can't see, when this initially came in, but I'm sure, that updating just the option name to 'ticket_email_subject' would have got you exactly into this mess, where there was an undefined variable 'prefix'. In fact, the only valid variables are determined by the code, and seem to be unchanged for long. These are:

  • ticket
  • event
  • action

Any other Genshi template variable name was bound to fail miserably.

It might be disputed, if allowing arbitrary strings for this option has even been a bright idea, because not understanding the option could bring you into trouble like evidenced by this ticket, but this might be true for other options as well.

I've just verified this with trunk code, and it still fails the same way, because the relevant code in announcer.email_decorators.TicketSubjectEmailDecorator is still unchanged.

comment:2 Changed 21 months ago by hasienda

Btw, if you remove '$prefix' you'll trap into another error: UndefinedError: "summary" not defined- foreseeable, right?

comment:3 Changed 21 months ago by hasienda

(In [12336]) TracAnnouncer: Harden the TicketSubjectEmailDecorator, refs #8677.

Use the default subject template, if a TemplateError is raised when
rendering a custom Genshi text template.

Changes are accompanied by some of the usual PEP8 and other nit-picks, of
which slimmer imports seem like the biggest advantage.

comment:4 Changed 21 months ago by hasienda

A developer's side-note:

During the clean-up process I did wonder, how str.join() would compete to the string substitution used here in message subject assignments. Here are some numbers:

$> python2.5
Python 2.5.5 (r255:77872, Nov 28 2010, 19:00:19) 
[GCC 4.4.5] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import timeit
>>> t = timeit.Timer('"%s%s" % ("prefix", "subject")')
>>> t.timeit(10000)
0.0061161518096923828
>>> t.timeit(10000)
0.0062630176544189453
>>> t.timeit(10000)
0.0061619281768798828
>>> t.timeit(10000)
0.0062689781188964844
>>> t.timeit(10000)
0.00611114501953125
>>> t = timeit.Timer('"".join(["prefix", "subject"])')
>>> t.timeit(10000)
0.0067720413208007812
>>> t.timeit(10000)
0.0066740512847900391
>>> t.timeit(10000)
0.0066788196563720703
>>> t.timeit(10000)
0.0068469047546386719
>>> t.timeit(10000)
0.0067121982574462891
>>> quit()

$> python2.6
Python 2.6.6 (r266:84292, Dec 27 2010, 00:02:40) 
[GCC 4.4.5] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import timeit
>>> t = timeit.Timer('"%s%s" % ("prefix", "subject")')
>>> t.timeit(10000)
0.0043671131134033203
>>> t.timeit(10000)
0.0044519901275634766
>>> t.timeit(10000)
0.0043587684631347656
>>> t.timeit(10000)
0.0043540000915527344
>>> t.timeit(10000)
0.0045208930969238281
>>> t = timeit.Timer('"".join(["prefix", "subject"])')
>>> t.timeit(10000)
0.0054268836975097656
>>> t.timeit(10000)
0.0055758953094482422
>>> t.timeit(10000)
0.0055720806121826172
>>> t.timeit(10000)
0.0056071281433105469
>>> t.timeit(10000)
0.0055680274963378906
>>> quit()

$> python2.7
Python 2.7.3rc2 (default, Apr 22 2012, 22:35:38) 
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import timeit
>>> t = timeit.Timer('"%s%s" % ("prefix", "subject")')
>>> t.timeit(10000)
0.003893136978149414
>>> t.timeit(10000)
0.0037920475006103516
>>> t.timeit(10000)
0.003863096237182617
>>> t.timeit(10000)
0.003821849822998047
>>> t.timeit(10000)
0.003679037094116211
>>> t = timeit.Timer('"".join(["prefix", "subject"])')
>>> t.timeit(10000)
0.0046541690826416016
>>> t.timeit(10000)
0.004675149917602539
>>> t.timeit(10000)
0.004548072814941406
>>> t.timeit(10000)
0.00466609001159668
>>> t.timeit(10000)
0.004542827606201172

Conclusion: Python improves significantly over time, and Python versions matter.

While for my test configuration in 2.5 the string substitution has a 7 % lead over the string join method, this raises to 20 % in 2.6 and 18 % in 2.7 - all Debian packaged Python versions. More than 30 % speed gain from Python 2.5 to 2.7, where string substitution again has the more significant drop of execution times, suggest a preference in Python.

So use string substitution, where applicable. But possibly more important: seems like Python>=2.6 has better overall performance in the tested string handling.

comment:5 Changed 21 months ago by hasienda

Now, there is Python3, even if it's still far from approaching it in Trac, even more valid for Trac plugins. Here you go:

$> python3.1 
Python 3.1.3 (r313:86834, Nov 28 2010, 11:28:10) 
[GCC 4.4.5] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import timeit
>>> t = timeit.Timer('"%s%s" % ("prefix", "subject")')
>>> t.timeit(10000)
0.00569915771484375
>>> t.timeit(10000)
0.005681037902832031
>>> t.timeit(10000)
0.005716085433959961
>>> t.timeit(10000)
0.005676984786987305
>>> t.timeit(10000)
0.005697011947631836
>>> t = timeit.Timer('"".join(["prefix", "subject"])')
>>> t.timeit(10000)
0.005447864532470703
>>> t.timeit(10000)
0.006100893020629883
>>> t.timeit(10000)
0.0055201053619384766
>>> t.timeit(10000)
0.005483865737915039
>>> t.timeit(10000)
0.005517005920410156

Interesting, so the string class in Python3 (basestring and unicode gone, str is all unicode now) comes at a price. It's still faster than Python2.5, and the differences between the string methods seem to vanish. I wouldn't be surprised, if they are even executed in parts by same code internally.

Just found another hint in release notes for Python3.0.1:

A new system for built-in string formatting operations replaces the % string formatting operator. (However, the % operator is still supported; it will be deprecated in Python 3.1 and removed from the language at some later time.) Read PEP 3101 for the full scoop.

Add Comment

Modify Ticket

Action
as new .
Author


E-mail address and user name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.