def add_matches(doc): m = matches.get(doc['id'], {}) title = h.get_first(m, 'title') text = h.get_first(m, 'text') if title: title = (jinja2.escape(title) .replace('#ALLURA-HIGHLIGHT-START#', jinja2.Markup('<strong>')) .replace('#ALLURA-HIGHLIGHT-END#', jinja2.Markup('</strong>'))) if text: text = (jinja2.escape(text) .replace('#ALLURA-HIGHLIGHT-START#', jinja2.Markup('<strong>')) .replace('#ALLURA-HIGHLIGHT-END#', jinja2.Markup('</strong>'))) doc['title_match'] = title doc['text_match'] = text or h.get_first(doc, 'text') return doc
def test_post_methods(): d = M.Discussion(shortname='test', name='test') t = M.Thread.new(discussion_id=d._id, subject='Test Thread') p = t.post('This is a post') p2 = t.post('This is another post') assert p.discussion_class() == M.Discussion assert p.thread_class() == M.Thread assert p.attachment_class() == M.DiscussionAttachment p.commit() assert p.parent is None assert p.subject == 'Test Thread' assert_equals(p.attachments, []) assert 'wiki/_discuss' in p.url() assert p.reply_subject() == 'Re: Test Thread' assert p.link_text() == p.subject ss = p.history().first() assert 'version' in h.get_first(ss.index(), 'title') assert '#' in ss.shorthand_id() jsn = p.__json__() assert jsn["thread_id"] == t._id (p.approve() for p in (p, p2)) ThreadLocalORMSession.flush_all() assert t.num_replies == 2 p.spam() assert t.num_replies == 1 p.undo('ok') assert t.num_replies == 2 p.delete() assert t.num_replies == 1
def test_post_methods(): d = M.Discussion(shortname="test", name="test") t = M.Thread.new(discussion_id=d._id, subject="Test Thread") p = t.post("This is a post") p2 = t.post("This is another post") assert p.discussion_class() == M.Discussion assert p.thread_class() == M.Thread assert p.attachment_class() == M.DiscussionAttachment p.commit() assert p.parent is None assert p.subject == "Test Thread" assert p.attachments.count() == 0 assert "wiki/_discuss" in p.url() assert p.reply_subject() == "Re: Test Thread" assert p.link_text() == p.subject ss = p.history().first() assert "version" in h.get_first(ss.index(), "title") assert "#" in ss.shorthand_id() jsn = p.__json__() assert jsn["thread_id"] == t._id (p.approve() for p in (p, p2)) assert t.num_replies == 1 p2.spam() assert t.num_replies == 0 p.spam() assert t.num_replies == 0 p.delete() assert t.num_replies == 0
def handle_shortlink(self, lnk, sender, rcpt): art = lnk.ref.artifact if security.has_access(art, 'read', user=M.User.anonymous())(): index = art.index() text = index['snippet_s'] or h.get_first(index, 'title') url = urljoin(tg.config['base_url'], index['url_s']) self.notice(rcpt, '[%s] - [%s](%s)' % (lnk.link, text, url))
def handle_shortlink(self, lnk, sender, rcpt): art = lnk.ref.artifact if security.has_access(art, 'read', user=M.User.anonymous())(): index = art.index() text = index['snippet_s'] or h.get_first(index, 'title') url = urljoin(tg.config.get('base_url', 'http://sourceforge.net'), index['url_s']) self.notice(rcpt, '[%s] - [%s](%s)' % (lnk.link, text,url))
def subscribe( cls, user_id=None, project_id=None, app_config_id=None, artifact=None, topic=None, type='direct', n=1, unit='day'): if user_id is None: user_id = c.user._id if project_id is None: project_id = c.project._id if app_config_id is None: app_config_id = c.app.config._id tool_already_subscribed = cls.query.get(user_id=user_id, project_id=project_id, app_config_id=app_config_id, artifact_index_id=None) if tool_already_subscribed: return if artifact is None: artifact_title = 'All artifacts' artifact_url = None artifact_index_id = None else: i = artifact.index() artifact_title = h.get_first(i, 'title') artifact_url = artifact.url() artifact_index_id = i['id'] artifact_already_subscribed = cls.query.get(user_id=user_id, project_id=project_id, app_config_id=app_config_id, artifact_index_id=artifact_index_id) if artifact_already_subscribed: return d = dict( user_id=user_id, project_id=project_id, app_config_id=app_config_id, artifact_index_id=artifact_index_id, topic=topic) sess = session(cls) try: mbox = cls( type=type, frequency=dict(n=n, unit=unit), artifact_title=artifact_title, artifact_url=artifact_url, **d) sess.flush(mbox) except pymongo.errors.DuplicateKeyError: sess.expunge(mbox) mbox = cls.query.get(**d) mbox.artifact_title = artifact_title mbox.artifact_url = artifact_url mbox.type = type mbox.frequency.n = n mbox.frequency.unit = unit sess.flush(mbox) if not artifact_index_id: # Unsubscribe from individual artifacts when subscribing to the # tool for other_mbox in cls.query.find(dict( user_id=user_id, project_id=project_id, app_config_id=app_config_id)): if other_mbox != mbox: other_mbox.delete() return mbox
def test_post_methods(): d = M.Discussion(shortname='test', name='test') t = M.Thread.new(discussion_id=d._id, subject='Test Thread') p = t.post('This is a post') p2 = t.post('This is another post') assert p.discussion_class() == M.Discussion assert p.thread_class() == M.Thread assert p.attachment_class() == M.DiscussionAttachment p.commit() assert p.parent is None assert p.subject == 'Test Thread' assert p.attachments.count() == 0 assert 'wiki/_discuss' in p.url() assert p.reply_subject() == 'Re: Test Thread' assert p.link_text() == p.subject ss = p.history().first() assert 'version' in h.get_first(ss.index(), 'title') assert '#' in ss.shorthand_id() jsn = p.__json__() assert jsn["thread_id"] == t._id (p.approve() for p in (p, p2)) assert t.num_replies == 1 p2.spam() assert t.num_replies == 0 p.spam() assert t.num_replies == 0 p.delete() assert t.num_replies == 0
def test_get_first(): assert_equals(h.get_first({}, "title"), None) assert_equals(h.get_first({"title": None}, "title"), None) assert_equals(h.get_first({"title": "Value"}, "title"), "Value") assert_equals(h.get_first({"title": ["Value"]}, "title"), "Value") assert_equals(h.get_first({"title": []}, "title"), None) assert_equals(h.get_first({"title": ["Value"]}, "title"), "Value")
def test_get_first(): assert_equals(h.get_first({}, 'title'), None) assert_equals(h.get_first({'title': None}, 'title'), None) assert_equals(h.get_first({'title': 'Value'}, 'title'), 'Value') assert_equals(h.get_first({'title': ['Value']}, 'title'), 'Value') assert_equals(h.get_first({'title': []}, 'title'), None) assert_equals(h.get_first({'title': ['Value']}, 'title'), 'Value')
def post(cls, artifact, title=None, description=None, author=None, author_link=None, author_name=None, pubdate=None, link=None, **kw): """ Create a Feed item. Returns the item. But if anon doesn't have read access, create does not happen and None is returned """ # TODO: fix security system so we can do this correctly and fast from allura import model as M anon = M.User.anonymous() if not security.has_access(artifact, 'read', user=anon): return if not security.has_access(c.project, 'read', user=anon): return idx = artifact.index() if author is None: author = c.user if author_name is None: author_name = author.get_pref('display_name') if title is None: title = '%s modified by %s' % (h.get_first(idx, 'title'), author_name) if description is None: description = title if pubdate is None: pubdate = datetime.utcnow() if link is None: link = artifact.url() item = cls(ref_id=artifact.index_id(), neighborhood_id=artifact.app_config.project.neighborhood_id, project_id=artifact.app_config.project_id, app_config_id=artifact.app_config_id, tool_name=artifact.app_config.tool_name, title=title, description=g.markdown.convert(description), link=link, pubdate=pubdate, author_name=author_name, author_link=author_link or author.url()) unique_id = kw.pop('unique_id', None) if unique_id: item.unique_id = unique_id return item
def index(self): result = Artifact.index(self) original = self.original() if original: original_index = original.index() result.update(original_index) result['title'] = '%s (version %d)' % (h.get_first( original_index, 'title'), self.version) result.update(id=self.index_id(), version_i=self.version, author_username_t=self.author.username, author_display_name_t=self.author.display_name, timestamp_dt=self.timestamp, is_history_b=True) return result
def index(self): result = Artifact.index(self) original = self.original() if original: original_index = original.index() result.update(original_index) result['title'] = '%s (version %d)' % ( h.get_first(original_index, 'title'), self.version) result.update( id=self.index_id(), version_i=self.version, author_username_t=self.author.username, author_display_name_t=self.author.display_name, timestamp_dt=self.timestamp, is_history_b=True) return result
def get_discussion_thread(self, data=None): """Return the discussion thread and parent_id for this artifact. :return: (:class:`allura.model.discuss.Thread`, parent_thread_id (int)) """ from .discuss import Thread threads = Thread.query.find(dict(ref_id=self.index_id())).all() if not threads: idx = self.index() t = Thread.new(app_config_id=self.app_config_id, discussion_id=self.app_config.discussion_id, ref_id=idx['id'], subject='%s discussion' % h.get_first(idx, 'title')) elif len(threads) == 1: t = threads[0] else: # there should not be multiple threads, we'll merge them destination = threads.pop() for thread in threads: for post in thread.posts: post.thread_id = destination._id destination.num_replies += 1 destination.last_post_date = max( destination.last_post_date, post.mod_date) session(post).flush(post) session(post).expunge( post ) # so thread.posts ref later in the code doesn't use stale posts Thread.query.remove({ '_id': thread._id }) # NOT thread.delete() since that would remove its posts too thread.attachment_class().query.update( {'thread_id': thread._id}, {'$set': { 'thread_id': destination._id }}, multi=True) t = destination parent_id = None if data: in_reply_to = data.get('in_reply_to', []) if in_reply_to: parent_id = in_reply_to[0] return t, parent_id
def get_discussion_thread(self, data=None): '''Return the discussion thread for this artifact (possibly made more specific by the message_data)''' from .discuss import Thread t = Thread.query.get(ref_id=self.index_id()) if t is None: idx = self.index() t = Thread.new( discussion_id=self.app_config.discussion_id, ref_id=idx['id'], subject='%s discussion' % h.get_first(idx, 'title')) parent_id = None if data: in_reply_to = data.get('in_reply_to', []) if in_reply_to: parent_id = in_reply_to[0] return t, parent_id
def post(cls, artifact, title=None, description=None, author=None, author_link=None, author_name=None, pubdate=None, link=None, **kw): """ Create a Feed item. Returns the item. But if anon doesn't have read access, create does not happen and None is returned. """ if not Feed.has_access(artifact): return idx = artifact.index() if author is None: author = c.user if author_name is None: author_name = author.get_pref('display_name') if title is None: title = '%s modified by %s' % (h.get_first(idx, 'title'), author_name) if description is None: description = title if pubdate is None: pubdate = datetime.utcnow() if link is None: link = artifact.url() item = cls(ref_id=artifact.index_id(), neighborhood_id=artifact.app_config.project.neighborhood_id, project_id=artifact.app_config.project_id, app_config_id=artifact.app_config_id, tool_name=artifact.app_config.tool_name, title=title, description=g.markdown.convert(description), link=link, pubdate=pubdate, author_name=author_name, author_link=author_link or author.url()) unique_id = kw.pop('unique_id', None) if unique_id: item.unique_id = unique_id return item
def post(cls, artifact, title=None, description=None, author=None, author_link=None, author_name=None, pubdate=None, link=None, **kw): """ Create a Feed item. Returns the item. But if anon doesn't have read access, create does not happen and None is returned """ # TODO: fix security system so we can do this correctly and fast from allura import model as M anon = M.User.anonymous() if not security.has_access(artifact, 'read', user=anon): return if not security.has_access(c.project, 'read', user=anon): return idx = artifact.index() if author is None: author = c.user if author_name is None: author_name = author.get_pref('display_name') if title is None: title = '%s modified by %s' % ( h.get_first(idx, 'title'), author_name) if description is None: description = title if pubdate is None: pubdate = datetime.utcnow() if link is None: link = artifact.url() item = cls( ref_id=artifact.index_id(), neighborhood_id=artifact.app_config.project.neighborhood_id, project_id=artifact.app_config.project_id, app_config_id=artifact.app_config_id, tool_name=artifact.app_config.tool_name, title=title, description=g.markdown.convert(description), link=link, pubdate=pubdate, author_name=author_name, author_link=author_link or author.url()) unique_id = kw.pop('unique_id', None) if unique_id: item.unique_id = unique_id return item
def get_discussion_thread(self, data=None): """Return the discussion thread and parent_id for this artifact. :return: (:class:`allura.model.discuss.Thread`, parent_thread_id (int)) """ from .discuss import Thread t = Thread.query.get(ref_id=self.index_id()) if t is None: idx = self.index() t = Thread.new( discussion_id=self.app_config.discussion_id, ref_id=idx['id'], subject='%s discussion' % h.get_first(idx, 'title')) parent_id = None if data: in_reply_to = data.get('in_reply_to', []) if in_reply_to: parent_id = in_reply_to[0] return t, parent_id
def get_discussion_thread(self, data=None): """Return the discussion thread and parent_id for this artifact. :return: (:class:`allura.model.discuss.Thread`, parent_thread_id (int)) """ from .discuss import Thread t = Thread.query.get(ref_id=self.index_id()) if t is None: idx = self.index() t = Thread.new( app_config_id=self.app_config_id, discussion_id=self.app_config.discussion_id, ref_id=idx['id'], subject='%s discussion' % h.get_first(idx, 'title')) parent_id = None if data: in_reply_to = data.get('in_reply_to', []) if in_reply_to: parent_id = in_reply_to[0] return t, parent_id
def get_discussion_thread(self, data=None): """Return the discussion thread and parent_id for this artifact. :return: (:class:`allura.model.discuss.Thread`, parent_thread_id (int)) """ from .discuss import Thread threads = Thread.query.find(dict(ref_id=self.index_id())).all() if not threads: idx = self.index() t = Thread.new( app_config_id=self.app_config_id, discussion_id=self.app_config.discussion_id, ref_id=idx['id'], subject='%s discussion' % h.get_first(idx, 'title')) elif len(threads) == 1: t = threads[0] else: # there should not be multiple threads, we'll merge them destination = threads.pop() for thread in threads: for post in thread.posts: post.thread_id = destination._id destination.num_replies += 1 destination.last_post_date = max(destination.last_post_date, post.mod_date) session(post).flush(post) session(post).expunge(post) # so thread.posts ref later in the code doesn't use stale posts Thread.query.remove({'_id': thread._id}) # NOT thread.delete() since that would remove its posts too thread.attachment_class().query.update({'thread_id': thread._id}, {'$set': {'thread_id': destination._id}}, multi=True) t = destination parent_id = None if data: in_reply_to = data.get('in_reply_to', []) if in_reply_to: parent_id = in_reply_to[0] return t, parent_id
def post(cls, artifact, title=None, description=None, author=None, author_link=None, author_name=None, pubdate=None, link=None, **kw): """ Create a Feed item. Returns the item. But if anon doesn't have read access, create does not happen and None is returned. """ if not Feed.has_access(artifact): return idx = artifact.index() if author is None: author = c.user if author_name is None: author_name = author.get_pref('display_name') if title is None: title = '%s modified by %s' % ( h.get_first(idx, 'title'), author_name) if description is None: description = title if pubdate is None: pubdate = datetime.utcnow() if link is None: link = artifact.url() item = cls( ref_id=artifact.index_id(), neighborhood_id=artifact.app_config.project.neighborhood_id, project_id=artifact.app_config.project_id, app_config_id=artifact.app_config_id, tool_name=artifact.app_config.tool_name, title=title, description=g.markdown.convert(description), link=link, pubdate=pubdate, author_name=author_name, author_link=author_link or author.url()) unique_id = kw.pop('unique_id', None) if unique_id: item.unique_id = unique_id return item
def _make_notification(cls, artifact, topic, **kwargs): ''' Create a Notification instance based on an artifact. Special handling for comments when topic=='message' ''' from allura.model import Project idx = artifact.index() if artifact else None subject_prefix = '[%s:%s] ' % ( c.project.shortname, c.app.config.options.mount_point) post = '' if topic == 'message': post = kwargs.pop('post') text = post.text file_info = kwargs.pop('file_info', None) if file_info is not None: text = "%s\n\n\nAttachment:" % text if not isinstance(file_info, list): file_info = [file_info] for attach in file_info: attach.file.seek(0, 2) bytecount = attach.file.tell() attach.file.seek(0) text = "%s %s (%s; %s) " % (text, attach.filename, h.do_filesizeformat(bytecount), attach.type) subject = post.subject or '' if post.parent_id and not subject.lower().startswith('re:'): subject = 'Re: ' + subject author = post.author() msg_id = artifact.url() + post._id parent_msg_id = artifact.url() + post.parent_id if post.parent_id else artifact.message_id() d = dict( _id=msg_id, from_address=str(author._id) if author != User.anonymous() else None, reply_to_address='"%s" <%s>' % ( subject_prefix, getattr(artifact, 'email_address', u'*****@*****.**')), subject=subject_prefix + subject, text=text, in_reply_to=parent_msg_id, author_id=author._id, pubdate=datetime.utcnow()) elif topic == 'flash': n = cls(topic=topic, text=kwargs['text'], subject=kwargs.pop('subject', '')) return n else: subject = kwargs.pop('subject', '%s modified by %s' % ( h.get_first(idx, 'title'),c.user.get_pref('display_name'))) reply_to = '"%s" <%s>' % ( h.get_first(idx, 'title'), getattr(artifact, 'email_address', u'*****@*****.**')) d = dict( from_address=reply_to, reply_to_address=reply_to, subject=subject_prefix + subject, text=kwargs.pop('text', subject), author_id=c.user._id, pubdate=datetime.utcnow()) if kwargs.get('message_id'): d['_id'] = kwargs['message_id'] if c.user.get_pref('email_address'): d['from_address'] = '"%s" <%s>' % ( c.user.get_pref('display_name'), c.user.get_pref('email_address')) elif c.user.email_addresses: d['from_address'] = '"%s" <%s>' % ( c.user.get_pref('display_name'), c.user.email_addresses[0]) if not d.get('text'): d['text'] = '' try: ''' Add addional text to the notification e-mail based on the artifact type ''' template = cls.view.get_template('mail/' + artifact.type_s + '.txt') d['text'] += template.render(dict(c=c, g=g, config=config, data=artifact, post=post, h=h)) except jinja2.TemplateNotFound: pass except: ''' Catch any errors loading or rendering the template, but the notification still gets sent if there is an error ''' log.warn('Could not render notification template %s' % artifact.type_s, exc_info=True) assert d['reply_to_address'] is not None project = c.project if d.get('project_id', c.project._id) != c.project._id: project = Project.query.get(_id=d['project_id']) if project.notifications_disabled: log.info('Notifications disabled for project %s, not sending %s(%r)', project.shortname, topic, artifact) return None n = cls(ref_id=artifact.index_id(), topic=topic, link=kwargs.pop('link', artifact.url()), **d) return n
def _make_notification(cls, artifact, topic, **kwargs): ''' Create a Notification instance based on an artifact. Special handling for comments when topic=='message' ''' from allura.model import Project idx = artifact.index() if artifact else None subject_prefix = '[%s:%s] ' % ( c.project.shortname, c.app.config.options.mount_point) post = '' if topic == 'message': post = kwargs.pop('post') text = kwargs.get('text') or post.text file_info = kwargs.pop('file_info', None) if file_info is not None: text = "%s\n\n\nAttachments:\n" % text if not isinstance(file_info, list): file_info = [file_info] for attach in file_info: attach.file.seek(0, 2) bytecount = attach.file.tell() attach.file.seek(0) url = h.absurl('{}attachment/{}'.format( post.url(), h.urlquote(attach.filename))) text = "%s\n- [%s](%s) (%s; %s)" % ( text, attach.filename, url, h.do_filesizeformat(bytecount), attach.type) subject = post.subject or '' if post.parent_id and not subject.lower().startswith('re:'): subject = 'Re: ' + subject author = post.author() msg_id = kwargs.get('message_id') or artifact.url() + post._id parent_msg_id = artifact.url() + \ post.parent_id if post.parent_id else artifact.message_id() d = dict( _id=msg_id, from_address=str( author._id) if author != User.anonymous() else None, reply_to_address='"%s" <%s>' % ( subject_prefix, getattr( artifact, 'email_address', g.noreply)), subject=subject_prefix + subject, text=text, in_reply_to=parent_msg_id, references=cls._references(artifact, post), author_id=author._id, pubdate=datetime.utcnow()) elif topic == 'flash': n = cls(topic=topic, text=kwargs['text'], subject=kwargs.pop('subject', '')) return n else: subject = kwargs.pop('subject', '%s modified by %s' % ( h.get_first(idx, 'title'), c.user.get_pref('display_name'))) reply_to = '"%s" <%s>' % ( h.get_first(idx, 'title'), getattr(artifact, 'email_address', g.noreply)) d = dict( from_address=reply_to, reply_to_address=reply_to, subject=subject_prefix + subject, text=kwargs.pop('text', subject), author_id=c.user._id, pubdate=datetime.utcnow()) if kwargs.get('message_id'): d['_id'] = kwargs['message_id'] if c.user.get_pref('email_address'): d['from_address'] = '"%s" <%s>' % ( c.user.get_pref('display_name'), c.user.get_pref('email_address')) elif c.user.email_addresses: d['from_address'] = '"%s" <%s>' % ( c.user.get_pref('display_name'), c.user.email_addresses[0]) if not d.get('text'): d['text'] = '' try: ''' Add addional text to the notification e-mail based on the artifact type ''' template = cls.view.get_template( 'mail/' + artifact.type_s + '.txt') d['text'] += template.render(dict(c=c, g=g, config=config, data=artifact, post=post, h=h)) except jinja2.TemplateNotFound: pass except: ''' Catch any errors loading or rendering the template, but the notification still gets sent if there is an error ''' log.warn('Could not render notification template %s' % artifact.type_s, exc_info=True) assert d['reply_to_address'] is not None project = c.project if d.get('project_id', c.project._id) != c.project._id: project = Project.query.get(_id=d['project_id']) if project.notifications_disabled: log.debug( 'Notifications disabled for project %s, not sending %s(%r)', project.shortname, topic, artifact) return None n = cls(ref_id=artifact.index_id(), topic=topic, link=kwargs.pop('link', artifact.url()), **d) return n
def _make_notification(cls, artifact, topic, **kwargs): """ Create a Notification instance based on an artifact. Special handling for comments when topic=='message' """ from allura.model import Project idx = artifact.index() if artifact else None subject_prefix = "[%s:%s] " % (c.project.shortname, c.app.config.options.mount_point) post = "" if topic == "message": post = kwargs.pop("post") text = post.text file_info = kwargs.pop("file_info", None) if file_info is not None: text = "%s\n\n\nAttachment:" % text if not isinstance(file_info, list): file_info = [file_info] for attach in file_info: attach.file.seek(0, 2) bytecount = attach.file.tell() attach.file.seek(0) text = "%s %s (%s; %s) " % (text, attach.filename, h.do_filesizeformat(bytecount), attach.type) subject = post.subject or "" if post.parent_id and not subject.lower().startswith("re:"): subject = "Re: " + subject author = post.author() msg_id = artifact.url() + post._id parent_msg_id = artifact.url() + post.parent_id if post.parent_id else artifact.message_id() d = dict( _id=msg_id, from_address=str(author._id) if author != User.anonymous() else None, reply_to_address='"%s" <%s>' % (subject_prefix, getattr(artifact, "email_address", u"*****@*****.**")), subject=subject_prefix + subject, text=text, in_reply_to=parent_msg_id, author_id=author._id, pubdate=datetime.utcnow(), ) elif topic == "flash": n = cls(topic=topic, text=kwargs["text"], subject=kwargs.pop("subject", "")) return n else: subject = kwargs.pop( "subject", "%s modified by %s" % (h.get_first(idx, "title"), c.user.get_pref("display_name")) ) reply_to = '"%s" <%s>' % ( h.get_first(idx, "title"), getattr(artifact, "email_address", u"*****@*****.**"), ) d = dict( from_address=reply_to, reply_to_address=reply_to, subject=subject_prefix + subject, text=kwargs.pop("text", subject), author_id=c.user._id, pubdate=datetime.utcnow(), ) if kwargs.get("message_id"): d["_id"] = kwargs["message_id"] if c.user.get_pref("email_address"): d["from_address"] = '"%s" <%s>' % (c.user.get_pref("display_name"), c.user.get_pref("email_address")) elif c.user.email_addresses: d["from_address"] = '"%s" <%s>' % (c.user.get_pref("display_name"), c.user.email_addresses[0]) if not d.get("text"): d["text"] = "" try: """ Add addional text to the notification e-mail based on the artifact type """ template = cls.view.get_template("mail/" + artifact.type_s + ".txt") d["text"] += template.render(dict(c=c, g=g, config=config, data=artifact, post=post, h=h)) except jinja2.TemplateNotFound: pass except: """ Catch any errors loading or rendering the template, but the notification still gets sent if there is an error """ log.warn("Could not render notification template %s" % artifact.type_s, exc_info=True) assert d["reply_to_address"] is not None project = c.project if d.get("project_id", c.project._id) != c.project._id: project = Project.query.get(_id=d["project_id"]) if project.notifications_disabled: log.info("Notifications disabled for project %s, not sending %s(%r)", project.shortname, topic, artifact) return None n = cls(ref_id=artifact.index_id(), topic=topic, link=kwargs.pop("link", artifact.url()), **d) return n