# HG changeset patch
# Parent b1fc15dd86f8c150b73fd518575a61d452d040d5
TracAnnouncer: Add wiki-to-html formatting for attachment description, when html email is used, refs #10584.
diff --git a/announcerplugin/trunk/announcer/formatters.py b/announcerplugin/trunk/announcer/formatters.py
--- a/announcerplugin/trunk/announcer/formatters.py
+++ b/announcerplugin/trunk/announcer/formatters.py
@@ -2,6 +2,8 @@
#
# Copyright (c) 2008, Stephen Hansen
# Copyright (c) 2009, Robert Corsaro
+# Copyright (c) 2012, Ryan J Ollos
+# Copyright (c) 2012, Steffen Hoffmann
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution.
@@ -12,8 +14,8 @@
from genshi import HTML
from genshi.template import NewTextTemplate, MarkupTemplate, TemplateLoader
-from trac.config import Option, IntOption, ListOption, BoolOption
-from trac.core import *
+from trac.config import BoolOption, ListOption
+from trac.core import implements
from trac.mimeview import Context
from trac.test import Mock, MockPerm
from trac.ticket.api import TicketSystem
@@ -25,7 +27,9 @@
from trac.wiki.model import WikiPage
from announcer.api import IAnnouncementFormatter
+from announcer.api import _, N_
from announcer.compat import exception_to_unicode
+from announcer.pref import AnnouncerTemplateProvider
def diff_cleanup(gen):
@@ -43,25 +47,21 @@
for value in gen:
yield ' ' + value
-diff_header = """Index: %(name)s
-==============================================================================
---- %(name)s (version: %(oldversion)s)
-+++ %(name)s (version: %(version)s)
-"""
-class TicketFormatter(Component):
+class TicketFormatter(AnnouncerTemplateProvider):
+
implements(IAnnouncementFormatter)
ticket_email_header_fields = ListOption('announcer',
'ticket_email_header_fields',
'owner, reporter, milestone, priority, severity',
- doc="""Comma seperated list of fields to appear in tickets.
- Use * to include all headers.""")
+ doc=N_("""Comma-separated list of fields to appear in tickets.
+ Use * to include all headers."""))
ticket_link_with_comment = BoolOption('announcer',
'ticket_link_with_comment',
'false',
- """Include last change anchor in the ticket URL.""")
+ N_("""Include last change anchor in the ticket URL."""))
def styles(self, transport, realm):
if realm == "ticket":
@@ -248,12 +248,14 @@
output = stream.render()
return output
-class WikiFormatter(Component):
+
+class WikiFormatter(AnnouncerTemplateProvider):
+
implements(IAnnouncementFormatter)
wiki_email_diff = BoolOption('announcer', 'wiki_email_diff',
"true",
- """Should a wiki diff be sent with emails?""")
+ N_("""Should a wiki diff be sent with emails?"""))
def styles(self, transport, realm):
if realm == "wiki":
@@ -287,6 +289,14 @@
data["diff_link"] = self.env.abs_href('wiki', page.name,
action="diff", version=page.version)
if self.wiki_email_diff:
+ # DEVEL: Formatter needs req object to get preferred language.
+ diff_header = _("""
+Index: %(name)s
+==============================================================================
+--- %(name)s (version: %(oldversion)s)
++++ %(name)s (version: %(version)s)
+""")
+
diff = "\n"
diff += diff_header % { 'name': page.name,
'version': page.version,
@@ -302,7 +312,7 @@
dirs += provider.get_templates_dirs()
templates = TemplateLoader(dirs, variable_lookup='lenient')
template = templates.load('wiki_email_plaintext.txt',
- cls=NewTextTemplate)
+ cls=NewTextTemplate)
if template:
stream = template.generate(**data)
output = stream.render('text')
diff --git a/announcerplugin/trunk/announcer/templates/ticket_email_mimic.html b/announcerplugin/trunk/announcer/templates/ticket_email_mimic.html
--- a/announcerplugin/trunk/announcer/templates/ticket_email_mimic.html
+++ b/announcerplugin/trunk/announcer/templates/ticket_email_mimic.html
@@ -150,7 +150,7 @@
-
+
diff --git a/announcerplugin/trunk/announcer/tests/formatters.py b/announcerplugin/trunk/announcer/tests/formatters.py
--- a/announcerplugin/trunk/announcer/tests/formatters.py
+++ b/announcerplugin/trunk/announcer/tests/formatters.py
@@ -2,61 +2,109 @@
#
# Copyright (c) 2009, Robert Corsaro
# Copyright (c) 2012, Steffen Hoffmann
+# Copyright (c) 2012, Ryan J Ollos
+# Copyright (c) 2012, Steffen Hoffmann
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution.
#
+import shutil
+import tempfile
import unittest
+from pkg_resources import resource_filename
+
+from trac.attachment import Attachment
from trac.test import EnvironmentStub
+from trac.ticket.model import Ticket
+from trac.web.chrome import Chrome
from announcer.formatters import TicketFormatter, WikiFormatter
+from announcer.producers import TicketChangeEvent
-class TicketFormatterTestCase(unittest.TestCase):
+class FormatterTestCase(unittest.TestCase):
def setUp(self):
- self.env = EnvironmentStub()
- self.out = TicketFormatter(self.env)
+ self.env = EnvironmentStub(enable=['trac.*', 'announcer.formatters.*'])
+ self.env.path = tempfile.mkdtemp()
+
+ def tearDown(self):
+ shutil.rmtree(self.env.path)
+
+
+class TicketFormatterTestCase(FormatterTestCase):
+
+ def setUp(self):
+ FormatterTestCase.setUp(self)
+ self.tf = TicketFormatter(self.env)
# Tests
+ def test_add_attachment_html_notification(self):
+ ticket = Ticket(self.env)
+ ticket['description'] = 'Some ticket description'
+ ticket['summary'] = 'Some ticket summary'
+ ticket['type'] = 'defect'
+ ticket['status'] = 'new'
+ ticket.insert()
+
+ attachment = Attachment(self.env, ticket)
+ attachment.description = "`Some` '''!WikiFormatted''' ''text''"
+ attachment.filename = 'somefile.txt'
+ event = TicketChangeEvent('ticket', 'changed', ticket,
+ author='user1', attachment=attachment)
+ actual = self.tf.format([], 'ticket', 'text/html', event)
+
+ filename = resource_filename(__name__, 'attachment_notification.html')
+ file = open('attachment_notification.html', 'r')
+ expected = file.read()
+ file.close()
+ self.assertEqual(expected, actual)
+
def test_styles(self):
- self.assertTrue('text/html' in self.out.styles('email', 'ticket'))
- self.assertTrue('text/plain' in self.out.styles('email', 'ticket'))
- self.assertFalse('text/plain' in self.out.styles('email', 'wiki'))
+ self.assertTrue('text/html' in self.tf.styles('email', 'ticket'))
+ self.assertTrue('text/plain' in self.tf.styles('email', 'ticket'))
+ self.assertFalse('text/plain' in self.tf.styles('email', 'wiki'))
self.assertEqual('text/plain',
- self.out.alternative_style_for('email', 'ticket',
- 'text/blah'))
+ self.tf.alternative_style_for('email', 'ticket',
+ 'text/blah'))
self.assertEqual('text/plain',
- self.out.alternative_style_for('email', 'ticket',
- 'text/html'))
+ self.tf.alternative_style_for('email', 'ticket',
+ 'text/html'))
self.assertEqual(None,
- self.out.alternative_style_for('email', 'ticket',
- 'text/plain'))
+ self.tf.alternative_style_for('email', 'ticket',
+ 'text/plain'))
+ def test_template_dirs_added(self):
+ self.assertTrue(self.tf in Chrome(self.env).template_providers)
-class WikiFormatterTestCase(unittest.TestCase):
+
+class WikiFormatterTestCase(FormatterTestCase):
+
def setUp(self):
- self.env = EnvironmentStub()
- self.out = WikiFormatter(self.env)
+ FormatterTestCase.setUp(self)
+ self.wf = WikiFormatter(self.env)
# Tests
def test_styles(self):
# HMTL format for email notifications is yet unsupported for wiki.
- #self.assertTrue('text/html' in self.out.styles('email', 'wiki'))
- self.assertTrue('text/plain' in self.out.styles('email', 'wiki'))
- self.assertFalse('text/plain' in self.out.styles('email', 'ticket'))
+ #self.assertTrue('text/html' in self.tf.styles('email', 'wiki'))
+ self.assertTrue('text/plain' in self.wf.styles('email', 'wiki'))
+ self.assertFalse('text/plain' in self.wf.styles('email', 'ticket'))
self.assertEqual('text/plain',
- self.out.alternative_style_for('email', 'wiki',
- 'text/blah'))
+ self.wf.alternative_style_for('email', 'wiki',
+ 'text/blah'))
self.assertEqual('text/plain',
- self.out.alternative_style_for('email', 'wiki',
- 'text/html'))
+ self.wf.alternative_style_for('email', 'wiki',
+ 'text/html'))
self.assertEqual(None,
- self.out.alternative_style_for('email', 'wiki',
- 'text/plain'))
+ self.wf.alternative_style_for('email', 'wiki',
+ 'text/plain'))
+
+ def test_template_dirs_added(self):
+ self.assertTrue(self.wf in Chrome(self.env).template_providers)
def suite():