Hi Gary, There are very few things wrong with this branch, and of the notes I've made below one's a vague suggestion, one's a comment and only the last two are things that I think need to be acted on before this lands. Great work by both everyone involved. [1] Here: 56 + def initialize(self): 57 + super(BugSubscriptionListView, self).initialize() 58 + subscriptions = get_structural_subscriptions_for_bug( 59 + self.context.bug, self.user) 60 + expose_user_administered_teams_to_js(self.request, self.user) 61 + expose_user_subscriptions_to_js( 62 + self.user, subscriptions, self.request) 63 + expose_enum_to_js(self.request, BugTaskImportance, 'importances') 64 + expose_enum_to_js(self.request, BugTaskStatus, 'statuses') 65 + and here: 117 + def initialize(self): 118 + super(TargetSubscriptionView, self).initialize() 119 + expose_user_administered_teams_to_js(self.request, self.user) 120 + subscriptions = get_structural_subscriptions_for_target( 121 + self.context, self.user) 122 + expose_user_subscriptions_to_js( 123 + self.user, subscriptions, self.request) 124 + expose_enum_to_js(self.request, BugTaskImportance, 'importances') 125 + expose_enum_to_js(self.request, BugTaskStatus, 'statuses') 126 + the code is almost identical (save for where the `subscriptions` list comes from. Might it be worth wrapping this stuff up in a mixin, something like: class StructuralSubscriptionJSMixin: """A mixin that exposes structural-subscription data in JS. Descendants of this mixin must define a `subscriptions` property that returns a list of the subscriptions to cache in the JS of the page. """ def initialize(self): super(StructuralSubscriptionJSMixin, self).initialize() expose_user_administered_teams_to_js(self.request, self.user) expose_user_subscriptions_to_js( self.user, self.subscriptions, self.request) expose_enum_to_js(self.request, BugTaskImportance, 'importances') expose_enum_to_js(self.request, BugTaskStatus, 'statuses') (Though that's only really worth the effort if we are going to do this anywhere else, I suppose). [2] 214 + record = info[target] = dict( I really don't like this idiom; it took me about 30s to work out what was actually going on (admittedly, my headcold probably isn't helping). I'd prefer it if we had this as: record = dict(...) info[target] = record [3] 249 + # It's a start. A win for commentary, there. [4] 435 + # [{'filters': [{'filter': <....BugSubscriptionFilter object at ...>, 436 + # 'subscriber_is_team': True, 437 + # 'subscriber_link': u'.../api/.../~team-name...', 438 + # 'subscriber_title': u'Team Name...', 439 + # 'user_is_team_admin': True}], 440 + # 'target_title': u'title...', 441 + # 'target_url': u'http://127.0.0.1/product-name...'}] I couldn't tell whether this is deliberately left in or not. If not, let's lose it, if so, please add some comments to explain why it's here. [4] 601 + required=False)) 602 + @call_with(subscribed_by=REQUEST_USER) There needs to be a blank line here to avoid confusion.