Modify

Opened 14 years ago

Closed 8 years ago

Last modified 8 years ago

#8677 closed defect (fixed)

"prefix" not defined when sending email

Reported by: anonymous Owned by: Steffen Hoffmann
Priority: normal Component: AnnouncerPlugin
Severity: normal Keywords: email notification template decorator
Cc: Ryan J Ollos, Robert Corsaro 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 (8)

comment:1 Changed 12 years ago by Steffen Hoffmann

Cc: Ryan J Ollos Robert Corsaro added; anonymous removed
Keywords: email notification template decorator added
Owner: changed from Robert Corsaro to Steffen Hoffmann

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 12 years ago by Steffen Hoffmann

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

comment:3 Changed 12 years ago by Steffen Hoffmann

(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 12 years ago by Steffen Hoffmann

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 12 years ago by Steffen Hoffmann

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.

comment:6 Changed 8 years ago by Ryan J Ollos

Owner: Steffen Hoffmann deleted

comment:7 Changed 8 years ago by Ryan J Ollos

Resolution: fixed
Status: newclosed

comment:8 Changed 8 years ago by Ryan J Ollos

Owner: set to Steffen Hoffmann

Modify Ticket

Change Properties
Set your email in Preferences
Action
as closed The owner will remain Steffen Hoffmann.
The resolution will be deleted. Next status will be 'reopened'.

Add Comment


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

 
Note: See TracTickets for help on using tickets.