def test_delete(self): req = MockRequest(self.env, authname='joe') with self.env.db_transaction: ids = [ self._add_subscriber(req, 'TicketSubscriber1'), self._add_subscriber(req, 'TicketSubscriber2'), self._add_subscriber(req, 'TicketSubscriber3'), self._add_subscriber(req, 'XmppSubscriber1', distributor='xmpp', adverb='never'), self._add_subscriber(req, 'XmppSubscriber2', distributor='xmpp') ] self.assertEqual( 5, self.env.db_query( """\ SELECT COUNT(*) FROM notify_subscription WHERE sid=%s AND authenticated=%s""", ('joe', 1))[0][0]) Subscription.delete(self.env, ids[1]) rows = self.env.db_query( """\ SELECT id, distributor, priority, class FROM notify_subscription WHERE sid=%s AND authenticated=%s ORDER BY distributor, priority""", ('joe', 1)) self.assertEqual((ids[0], 'email', 1, 'TicketSubscriber1'), rows[0]) self.assertEqual((ids[2], 'email', 2, 'TicketSubscriber3'), rows[1]) self.assertEqual((ids[3], 'xmpp', 1, 'XmppSubscriber1'), rows[2]) self.assertEqual((ids[4], 'xmpp', 2, 'XmppSubscriber2'), rows[3]) self.assertEqual(4, len(rows))
def _move_rule(self, arg, req): tokens = [as_int(val, 0) for val in arg.split('-', 1)] if len(tokens) == 2: rule_id, priority = tokens if rule_id > 0 and priority > 0: session = req.session Subscription.move(self.env, rule_id, priority, session.sid, session.authenticated)
def _add_rule(self, arg, req): rule = Subscription(self.env) rule['sid'] = req.session.sid rule['authenticated'] = 1 if req.session.authenticated else 0 rule['distributor'] = arg rule['format'] = req.args.get('format-%s' % arg, '') rule['adverb'] = req.args['new-adverb-%s' % arg] rule['class'] = req.args['new-rule-%s' % arg] Subscription.add(self.env, rule)
def _add_subscription(self, **kwargs): subscription = { 'sid': None, 'authenticated': 1, 'distributor': 'email', 'format': 'text/plain', 'adverb': 'always', 'class': 'TestSubscriber' } subscription.update(kwargs) Subscription.add(self.env, subscription)
def matches(self, event): if event.realm != 'ticket': return if event.category not in ('created', 'changed', 'attachment added', 'attachment deleted'): return # CC field is stored as comma-separated string. Parse to set. chrome = Chrome(self.env) to_set = lambda cc: set(chrome.cc_list(cc)) cc_set = to_set(event.target['cc'] or '') # Harvest previous CC field if 'fields' in event.changes and 'cc' in event.changes['fields']: cc_set.update(to_set(event.changes['fields']['cc']['old'])) matcher = RecipientMatcher(self.env) klass = self.__class__.__name__ sids = set() for cc in cc_set: recipient = matcher.match_recipient(cc) if not recipient: continue sid, auth, addr = recipient # Default subscription for s in self.default_subscriptions(): yield (s[0], s[1], sid, auth, addr, s[2], s[3], s[4]) if sid: sids.add((sid,auth)) for s in Subscription.find_by_sids_and_class(self.env, sids, klass): yield s.subscription_tuple()
def matches(self, event): if event.realm != 'ticket': return if event.category not in ('created', 'changed', 'attachment added', 'attachment deleted'): return updaters = [row[0] for row in self.env.db_query(""" SELECT DISTINCT author FROM ticket_change WHERE ticket=%s """, (event.target.id, ))] matcher = RecipientMatcher(self.env) klass = self.__class__.__name__ sids = set() for previous_updater in updaters: if previous_updater == event.author: continue recipient = matcher.match_recipient(previous_updater) if not recipient: continue sid, auth, addr = recipient # Default subscription for s in self.default_subscriptions(): yield (s[0], s[1], sid, auth, addr, s[2], s[3], s[4]) if sid: sids.add((sid,auth)) for s in Subscription.find_by_sids_and_class(self.env, sids, klass): yield s.subscription_tuple()
def matches(self, event): if event.realm != 'ticket': return if event.category not in ('created', 'changed', 'attachment added', 'attachment deleted'): return ticket = event.target owners = [ticket['owner']] # Harvest previous owner if 'fields' in event.changes and 'owner' in event.changes['fields']: owners.append(event.changes['fields']['owner']['old']) matcher = RecipientMatcher(self.env) klass = self.__class__.__name__ sids = set() for owner in owners: recipient = matcher.match_recipient(owner) if not recipient: continue sid, auth, addr = recipient # Default subscription for s in self.default_subscriptions(): yield (s[0], s[1], sid, auth, addr, s[2], s[3], s[4]) if sid: sids.add((sid,auth)) for s in Subscription.find_by_sids_and_class(self.env, sids, klass): yield s.subscription_tuple()
def _add_subscriber(self, req, class_, distributor='email', format='text/plain', adverb='always'): session = req.session args = {'sid': session.sid, 'authenticated': session.authenticated, 'distributor': distributor, 'format': format, 'adverb': adverb, 'class': class_} return Subscription.add(self.env, args)
def matches(self, event): if event.realm != 'ticket': return if event.category not in ('created', 'changed', 'attachment added', 'attachment deleted'): return ticket = event.target owners = [ticket['owner']] # Harvest previous owner if 'fields' in event.changes and 'owner' in event.changes['fields']: owners.append(event.changes['fields']['owner']['old']) matcher = RecipientMatcher(self.env) klass = self.__class__.__name__ sids = set() for owner in owners: recipient = matcher.match_recipient(owner) if not recipient: continue sid, auth, addr = recipient # Default subscription for s in self.default_subscriptions(): yield s[0], s[1], sid, auth, addr, s[2], s[3], s[4] if sid: sids.add((sid, auth)) for s in Subscription.find_by_sids_and_class(self.env, sids, klass): yield s.subscription_tuple()
def matches(self, event): if event.realm != 'ticket': return if event.category == 'batchmodify': for ticket_event in event.get_ticket_change_events(self.env): for m in self.matches(ticket_event): yield m return if event.category not in ('created', 'changed', 'attachment added', 'attachment deleted'): return ticket = event.target matcher = RecipientMatcher(self.env) recipient = matcher.match_recipient(ticket['reporter']) if not recipient: return sid, auth, addr = recipient # Default subscription for s in self.default_subscriptions(): yield (s[0], s[1], sid, auth, addr, s[2], s[3], s[4]) if sid: klass = self.__class__.__name__ for s in Subscription.find_by_sids_and_class( self.env, ((sid, auth), ), klass): yield s.subscription_tuple()
def matches(self, event): if event.realm != 'ticket': return if event.category not in ('created', 'changed', 'attachment added', 'attachment deleted'): return # CC field is stored as comma-separated string. Parse to set. chrome = Chrome(self.env) to_set = lambda cc: set(chrome.cc_list(cc)) cc_set = to_set(event.target['cc'] or '') # Harvest previous CC field if 'fields' in event.changes and 'cc' in event.changes['fields']: cc_set.update(to_set(event.changes['fields']['cc']['old'])) matcher = RecipientMatcher(self.env) klass = self.__class__.__name__ sids = set() for cc in cc_set: recipient = matcher.match_recipient(cc) if not recipient: continue sid, auth, addr = recipient # Default subscription for s in self.default_subscriptions(): yield s[0], s[1], sid, auth, addr, s[2], s[3], s[4] if sid: sids.add((sid, auth)) for s in Subscription.find_by_sids_and_class(self.env, sids, klass): yield s.subscription_tuple()
def matches(self, event): if event.realm != 'ticket' or event.category != 'created': return klass = self.__class__.__name__ for s in Subscription.find_by_class(self.env, klass): yield s.subscription_tuple()
def _ticket_change_subscribers(subscriber, candidates): if not candidates: return if not isinstance(candidates, (list, set, tuple)): candidates = [candidates] # Get members of permission groups groups = PermissionSystem(subscriber.env).get_groups_dict() for cc in set(candidates): if cc in groups: candidates.remove(cc) candidates.update(groups[cc]) matcher = RecipientMatcher(subscriber.env) klass = subscriber.__class__.__name__ sids = set() for candidate in candidates: recipient = matcher.match_recipient(candidate) if not recipient: continue sid, auth, addr = recipient # Default subscription for s in subscriber.default_subscriptions(): yield s[0], s[1], sid, auth, addr, s[2], s[3], s[4] if sid: sids.add((sid, auth)) for s in Subscription.find_by_sids_and_class(subscriber.env, sids, klass): yield s.subscription_tuple()
def matches(self, event): if event.realm != 'ticket': return if event.category not in ('created', 'changed', 'attachment added', 'attachment deleted'): return updaters = [ row[0] for row in self.env.db_query( """ SELECT DISTINCT author FROM ticket_change WHERE ticket=%s """, (event.target.id, )) ] matcher = RecipientMatcher(self.env) klass = self.__class__.__name__ sids = set() for previous_updater in updaters: if previous_updater == event.author: continue recipient = matcher.match_recipient(previous_updater) if not recipient: continue sid, auth, addr = recipient # Default subscription for s in self.default_subscriptions(): yield s[0], s[1], sid, auth, addr, s[2], s[3], s[4] if sid: sids.add((sid, auth)) for s in Subscription.find_by_sids_and_class(self.env, sids, klass): yield s.subscription_tuple()
def _add_subscription(self, **kwargs): props = {'sid': None, 'authenticated': 1, 'distributor': 'email', 'format': 'text/plain', 'adverb': 'always', 'class': 'TicketOwnerSubscriber'} props.update((k.rstrip('_'), (v or None) if isinstance(v, basestring) else v) for k, v in kwargs.iteritems()) assert props['sid'] is not None return Subscription.add(self.env, props)
def _replace_rules(self, arg, req): subscriptions = [] for transport in self._iter_transports(): format_ = req.args.getfirst('format-' + transport) format_ = self._normalize_format(format_, transport) req.session.set('notification.format.%s' % transport, format_, '') adverbs = req.args.getlist('adverb-' + transport) classes = req.args.getlist('class-' + transport) for idx in xrange(min(len(adverbs), len(classes))): subscriptions.append({'distributor': transport, 'format': format_, 'adverb': adverbs[idx], 'class': classes[idx]}) sid = req.session.sid authenticated = req.session.authenticated with self.env.db_transaction: Subscription.replace_all(self.env, sid, authenticated, subscriptions)
def test_update_format_by_distributor_and_sid(self): self._insert_rows() Subscription.update_format_by_distributor_and_sid( self.env, 'email', 'joe', True, 'application/pdf') rows = self.env.db_query("""\ SELECT distributor, format, priority, adverb, class FROM notify_subscription WHERE sid=%s AND authenticated=%s ORDER BY distributor, priority""", ('joe', 1)) expected = [ ('email', 'application/pdf', 1, 'always', 'EmailSubscriber1'), ('email', 'application/pdf', 2, 'always', 'EmailSubscriber2'), ('email', 'application/pdf', 3, 'always', 'EmailSubscriber3'), ('irc', 'text/plain', 1, 'never', 'IrcSubscriber1'), ('irc', 'text/plain', 2, 'never', 'IrcSubscriber2'), ('irc', 'text/plain', 3, 'never', 'IrcSubscriber3'), ('xmpp', 'text/html', 1, 'always', 'XmppSubscriber1'), ('xmpp', 'text/plain', 2, 'never', 'XmppSubscriber2'), ('xmpp', 'text/html', 3, 'never', 'XmppSubscriber3'), ] self.assertEqual(expected, rows)
def test_find_by_sid_and_distributor(self): self._insert_rows() items = Subscription.find_by_sid_and_distributor(self.env, 'joe', True, 'xmpp') self.assertEqual(['joe'] * 3, self._props(items, 'sid')) self.assertEqual([1] * 3, self._props(items, 'authenticated')) self.assertEqual(['xmpp'] * 3, self._props(items, 'distributor')) self.assertEqual(['text/html', 'text/plain', 'text/html'], self._props(items, 'format')) self.assertEqual([1, 2, 3], self._props(items, 'priority')) self.assertEqual(['always', 'never', 'never'], self._props(items, 'adverb')) self.assertEqual(['XmppSubscriber1', 'XmppSubscriber2', 'XmppSubscriber3'], self._props(items, 'class'))
def _replace_rules(self, arg, req): subscriptions = [] for transport in self._iter_transports(): format_ = req.args.getfirst('format-' + transport) styles = self._get_supported_styles(transport) if not styles: format_ = None elif format_ not in styles: format_ = styles[0] adverbs = req.args.getlist('adverb-' + transport) classes = req.args.getlist('class-' + transport) for idx in xrange(min(len(adverbs), len(classes))): subscriptions.append({'distributor': transport, 'format': format_, 'adverb': adverbs[idx], 'class': classes[idx]}) sid = req.session.sid authenticated = req.session.authenticated with self.env.db_transaction: Subscription.replace_all(self.env, sid, authenticated, subscriptions)
def test_find_by_sids_and_class(self): self._insert_rows() sids = [('joe', True), ('jes', True), ('jan', True), ('jim', True)] items = Subscription.find_by_sids_and_class(self.env, sids, 'IrcSubscriber3') self.assertEqual(['joe', 'jim'], self._props(items, 'sid')) self.assertEqual([1] * 2, self._props(items, 'authenticated')) self.assertEqual(['irc'] * 2, self._props(items, 'distributor')) self.assertEqual(['text/plain', 'text/html'], self._props(items, 'format')) self.assertEqual([3, 3], self._props(items, 'priority')) self.assertEqual(['never', 'always'], self._props(items, 'adverb')) self.assertEqual(['IrcSubscriber3', 'IrcSubscriber3'], self._props(items, 'class'))
def test_move(self): def query_subs(): return self.env.db_query( """\ SELECT distributor, priority, class FROM notify_subscription WHERE sid=%s AND authenticated=%s ORDER BY distributor, priority""", ('joe', 1)) req = MockRequest(self.env, authname='joe') with self.env.db_transaction: rule_ids = {} for class_, distributor in [('EmailSubscriber1', 'email'), ('EmailSubscriber2', 'email'), ('EmailSubscriber3', 'email'), ('EmailSubscriber4', 'email'), ('XmppSubscriber1', 'xmpp'), ('XmppSubscriber2', 'xmpp')]: rule_ids[(class_, distributor)] = \ self._add_subscriber(req, class_, distributor) self.assertEqual([ ('email', 1, 'EmailSubscriber1'), ('email', 2, 'EmailSubscriber2'), ('email', 3, 'EmailSubscriber3'), ('email', 4, 'EmailSubscriber4'), ('xmpp', 1, 'XmppSubscriber1'), ('xmpp', 2, 'XmppSubscriber2'), ], query_subs()) Subscription.move(self.env, rule_ids[('EmailSubscriber3', 'email')], 1) self.assertEqual([ ('email', 1, 'EmailSubscriber3'), ('email', 2, 'EmailSubscriber1'), ('email', 3, 'EmailSubscriber2'), ('email', 4, 'EmailSubscriber4'), ('xmpp', 1, 'XmppSubscriber1'), ('xmpp', 2, 'XmppSubscriber2'), ], query_subs()) Subscription.move(self.env, rule_ids[('EmailSubscriber1', 'email')], 4) self.assertEqual([ ('email', 1, 'EmailSubscriber3'), ('email', 2, 'EmailSubscriber2'), ('email', 3, 'EmailSubscriber4'), ('email', 4, 'EmailSubscriber1'), ('xmpp', 1, 'XmppSubscriber1'), ('xmpp', 2, 'XmppSubscriber2'), ], query_subs()) Subscription.move(self.env, rule_ids[('EmailSubscriber3', 'email')], 3) self.assertEqual([ ('email', 1, 'EmailSubscriber2'), ('email', 2, 'EmailSubscriber4'), ('email', 3, 'EmailSubscriber3'), ('email', 4, 'EmailSubscriber1'), ('xmpp', 1, 'XmppSubscriber1'), ('xmpp', 2, 'XmppSubscriber2'), ], query_subs())
def _replace_rules(self, arg, req): subscriptions = [] for transport in self._iter_transports(): format_ = req.args.getfirst('format-' + transport) styles = self._get_supported_styles(transport) if not styles: format_ = None elif format_ not in styles: format_ = styles[0] adverbs = req.args.getlist('adverb-' + transport) classes = req.args.getlist('class-' + transport) for idx in xrange(min(len(adverbs), len(classes))): subscriptions.append({ 'distributor': transport, 'format': format_, 'adverb': adverbs[idx], 'class': classes[idx] }) sid = req.session.sid authenticated = req.session.authenticated with self.env.db_transaction: Subscription.replace_all(self.env, sid, authenticated, subscriptions)
def test_replace_all(self): def query(sid, authenticated): return self.env.db_query( """\ SELECT distributor, format, priority, adverb, class FROM notify_subscription WHERE sid=%s AND authenticated=%s ORDER BY distributor, priority""", (sid, authenticated)) req = MockRequest(self.env, authname='joe') sess = req.session items = [ ('email', 'text/plain', 'always', 'TicketSubscriber1'), ('email', 'text/html', 'always', 'TicketSubscriber2'), ('email', 'text/html', 'always', 'TicketSubscriber3'), ('xmpp', 'text/html', 'never', 'XmppSubscriber1'), ('xmpp', 'text/plain', 'always', 'XmppSubscriber2'), ] items = [ dict(zip(('distributor', 'format', 'adverb', 'class'), item)) for item in items ] Subscription.replace_all(self.env, sess.sid, sess.authenticated, items) rows = query('joe', 1) expected = [ ('email', 'text/plain', 1, 'always', 'TicketSubscriber1'), ('email', 'text/html', 2, 'always', 'TicketSubscriber2'), ('email', 'text/html', 3, 'always', 'TicketSubscriber3'), ('xmpp', 'text/html', 1, 'never', 'XmppSubscriber1'), ('xmpp', 'text/plain', 2, 'always', 'XmppSubscriber2'), ] self.assertEqual(expected, rows) items = [ ('email', 'text/plain', 'never', 'TicketSubscriber3'), ('xmpp', 'text/html', 'always', 'XmppSubscriber1'), ] items = [ dict(zip(('distributor', 'format', 'adverb', 'class'), item)) for item in items ] Subscription.replace_all(self.env, sess.sid, sess.authenticated, items) rows = query('joe', 1) expected = [ ('email', 'text/plain', 1, 'never', 'TicketSubscriber3'), ('xmpp', 'text/html', 1, 'always', 'XmppSubscriber1'), ] self.assertEqual(expected, rows) Subscription.replace_all(self.env, sess.sid, sess.authenticated, []) self.assertEqual([], query('joe', 1))
def matches(self, event): if event.realm != 'ticket': return if event.category not in ('created', 'changed', 'attachment added', 'attachment deleted'): return matcher = RecipientMatcher(self.env) recipient = matcher.match_recipient(event.author) if not recipient: return sid, auth, addr = recipient # Default subscription for s in self.default_subscriptions(): yield (s[0], s[1], sid, auth, addr, s[2], s[3], s[4]) if sid: klass = self.__class__.__name__ for s in Subscription.find_by_sids_and_class(self.env, ((sid,auth),), klass): yield s.subscription_tuple()
def matches(self, event): if event.realm != 'ticket': return if event.category not in ('created', 'changed', 'attachment added', 'attachment deleted'): return matcher = RecipientMatcher(self.env) recipient = matcher.match_recipient(event.author) if not recipient: return sid, auth, addr = recipient # Default subscription for s in self.default_subscriptions(): yield s[0], s[1], sid, auth, addr, s[2], s[3], s[4] if sid: klass = self.__class__.__name__ for s in Subscription.find_by_sids_and_class( self.env, ((sid, auth), ), klass): yield s.subscription_tuple()
def _ticket_change_subscribers(subscriber, candidates): if not candidates: return if not isinstance(candidates, (list, set, tuple)): candidates = [candidates] matcher = RecipientMatcher(subscriber.env) klass = subscriber.__class__.__name__ sids = set() for candidate in candidates: recipient = matcher.match_recipient(candidate) if not recipient: continue sid, auth, addr = recipient # Default subscription for s in subscriber.default_subscriptions(): yield s[0], s[1], sid, auth, addr, s[2], s[3], s[4] if sid: sids.add((sid, auth)) for s in Subscription.find_by_sids_and_class(subscriber.env, sids, klass): yield s.subscription_tuple()
def _move_rule(self, arg, req): (rule_id, new_priority) = arg.split('-') if int(new_priority) >= 1: Subscription.move(self.env, rule_id, int(new_priority))
def _find_subscriptions(self): klass = self.__class__.__name__ return Subscription.find_by_class(self.env, klass)
def _iter_rules(self, req, transport): session = req.session for r in Subscription.find_by_sid_and_distributor( self.env, session.sid, session.authenticated, transport): yield r
def _delete_rule(self, arg, req): Subscription.delete(self.env, arg)
def _set_format(self, arg, req): format_ = req.args.getfirst('format-%s' % arg) format_ = self._normalize_format(format_, arg) req.session.set('notification.format.%s' % arg, format_, '') Subscription.update_format_by_distributor_and_sid( self.env, arg, req.session.sid, req.session.authenticated, format_)
def _set_format(self, arg, req): Subscription.update_format_by_distributor_and_sid( self.env, arg, req.session.sid, req.session.authenticated, req.args['format-%s' % arg])
def _delete_rule(self, arg, req): session = req.session Subscription.delete(self.env, arg, session.sid, session.authenticated)
def render_preference_panel(self, req, panel, path_info=None): if req.method == 'POST': action_arg = req.args.get('action', '') m = re.match('^([^_]+)_(.+)', action_arg) if m: action, arg = m.groups() handler = self.post_handlers.get(action) if handler: handler(arg, req) add_notice(req, _("Your preferences have been saved.")) req.redirect(req.href.prefs('notification')) data = {'rules': {}, 'subscribers': []} desc_map = {} defaults = [] data['formatters'] = {} data['selected_format'] = {} data['adverbs'] = ('always', 'never') data['adverb_labels'] = dict(always=_("Notify"), never=_("Never notify")) for i in self.subscribers: if not i.description(): continue if not req.session.authenticated and i.requires_authentication(): continue data['subscribers'].append({ 'class': i.__class__.__name__, 'description': i.description() }) desc_map[i.__class__.__name__] = i.description() if hasattr(i, 'default_subscriptions'): defaults.extend(i.default_subscriptions()) for t in self._iter_transports(): data['rules'][t] = [] styles = self._get_supported_styles(t) data['formatters'][t] = styles data['selected_format'][t] = styles[0] for r in Subscription.find_by_sid_and_distributor( self.env, req.session.sid, req.session.authenticated, t): if desc_map.get(r['class']): data['rules'][t].append({ 'id': r['id'], 'adverb': r['adverb'], 'class': r['class'], 'description': desc_map[r['class']], 'priority': r['priority'] }) data['selected_format'][t] = r['format'] data['default_rules'] = {} for r in sorted(defaults, key=itemgetter(3)): klass, dist, format, priority, adverb = r if not data['default_rules'].get(dist): data['default_rules'][dist] = [] if desc_map.get(klass): data['default_rules'][dist].append({ 'adverb': adverb, 'description': desc_map.get(klass) }) Chrome(self.env).add_jquery_ui(req) return 'prefs_notification.html', dict(data=data)
def _add_subscription(self, **kwargs): subscription = {'sid': None, 'authenticated': 1, 'distributor': 'email', 'format': 'text/plain', 'adverb': 'always', 'class': 'TestSubscriber'} subscription.update(kwargs) Subscription.add(self.env, subscription)
def _set_format(self, arg, req): Subscription.update_format_by_distributor_and_sid(self.env, arg, req.session.sid, req.session.authenticated, req.args['format-%s' % arg])
def render_preference_panel(self, req, panel, path_info=None): if req.method == 'POST': action_arg = req.args.get('action', '') m = re.match('^([^_]+)_(.+)', action_arg) if m: action, arg = m.groups() handler = self.post_handlers.get(action) if handler: handler(arg, req) add_notice(req, _("Your preferences have been saved.")) req.redirect(req.href.prefs('notification')) data = {'rules':{}, 'subscribers':[]} desc_map = {} defaults = [] data['formatters'] = {} data['selected_format'] = {} data['adverbs'] = ('always', 'never') data['adverb_labels'] = dict(always=_("Notify"), never=_("Never notify")) for i in self.subscribers: if not i.description(): continue if not req.session.authenticated and i.requires_authentication(): continue data['subscribers'].append({ 'class': i.__class__.__name__, 'description': i.description() }) desc_map[i.__class__.__name__] = i.description() if hasattr(i, 'default_subscriptions'): defaults.extend(i.default_subscriptions()) for t in self._iter_transports(): data['rules'][t] = [] styles = self._get_supported_styles(t) data['formatters'][t] = styles data['selected_format'][t] = styles[0] for r in Subscription.find_by_sid_and_distributor(self.env, req.session.sid, req.session.authenticated, t): if desc_map.get(r['class']): data['rules'][t].append({ 'id': r['id'], 'adverb': r['adverb'], 'class': r['class'], 'description': desc_map[r['class']], 'priority': r['priority'] }) data['selected_format'][t] = r['format'] data['default_rules'] = {} for r in sorted(defaults, key=itemgetter(3)): klass, dist, format, priority, adverb = r if not data['default_rules'].get(dist): data['default_rules'][dist] = [] if desc_map.get(klass): data['default_rules'][dist].append({ 'adverb': adverb, 'description': desc_map.get(klass) }) Chrome(self.env).add_jquery_ui(req) return 'prefs_notification.html', dict(data=data)