679
679
cache.objects['total_comments_and_activity'] = (
680
680
self.total_comments + self.total_activity)
681
681
cache.objects['initial_comment_batch_offset'] = (
682
self.visible_initial_comments)
682
self.visible_initial_comments + 1)
683
683
cache.objects['first visible_recent_comment'] = (
684
684
self.total_comments - self.visible_recent_comments)
727
727
def comments(self):
728
728
"""Return the bugtask's comments."""
729
return self._getComments()
731
def _getComments(self, slice_info=None):
729
732
show_spam_controls = check_permission(
730
733
'launchpad.Admin', self.context.bug)
731
return get_comments_for_bugtask(self.context, truncate=True,
734
return get_comments_for_bugtask(
735
self.context, truncate=True, slice_info=slice_info,
732
736
for_display=True, show_spam_controls=show_spam_controls)
735
739
def interesting_activity(self):
740
return self._getInterestingActivity()
742
def _getInterestingActivity(self, earliest_activity_date=None,
743
latest_activity_date=None):
736
744
"""A sequence of interesting bug activity."""
745
if (earliest_activity_date is not None and
746
latest_activity_date is not None):
747
# Only get the activity for the date range that we're
748
# interested in to save us from processing too much.
749
activity = self.context.bug.getActivityForDateRange(
750
start_date=earliest_activity_date,
751
end_date=latest_activity_date)
753
activity = self.context.bug.activity
737
754
bug_change_re = (
738
755
'affects|description|security vulnerability|'
739
756
'summary|tags|visibility')
742
759
'(assignee|importance|milestone|status)')
743
760
interesting_match = re.compile(
744
761
"^(%s|%s)$" % (bug_change_re, bugtask_change_re)).match
762
interesting_activity = tuple(
746
763
BugActivityItem(activity)
747
for activity in self.context.bug.activity
764
for activity in activity
748
765
if interesting_match(activity.whatchanged) is not None)
766
# This is a bit kludgy but it means that interesting_activity is
767
# populated correctly for all subsequent calls.
768
self._interesting_activity_cached_value = interesting_activity
769
return interesting_activity
750
771
def _getEventGroups(self, batch_size=None, offset=None):
751
772
# Ensure truncation results in < max_length comments as expected
753
774
+ config.malone.comments_list_truncate_newest_to
754
775
< config.malone.comments_list_max_length)
756
if not self.visible_comments_truncated_for_display:
777
if (not self.visible_comments_truncated_for_display and
757
779
comments = self.comments
780
elif batch_size is not None:
781
# If we're limiting to a given set of comments, we work on
782
# just that subset of comments from hereon in, which saves
783
# on processing time a bit.
785
offset = self.visible_initial_comments
786
comments = self._getComments([
787
slice(offset, offset+batch_size)])
759
789
# the comment function takes 0-offset counts where comment 0 is
760
790
# the initial description, so we need to add one to the limits
762
792
oldest_count = 1 + self.visible_initial_comments
763
793
new_count = 1 + self.total_comments - self.visible_recent_comments
764
show_spam_controls = check_permission(
765
'launchpad.Admin', self.context.bug)
766
comments = get_comments_for_bugtask(
767
self.context, truncate=True, for_display=True,
769
slice(None, oldest_count), slice(new_count, None)],
770
show_spam_controls=show_spam_controls)
795
slice(None, oldest_count),
796
slice(new_count, None),
798
comments = self._getComments(slice_info)
772
800
visible_comments = get_visible_comments(
773
801
comments, user=self.user)
802
if len(visible_comments) > 0 and batch_size is not None:
803
first_comment = visible_comments[0]
804
last_comment = visible_comments[-1]
805
interesting_activity = (
806
self._getInterestingActivity(
807
earliest_activity_date=first_comment.datecreated,
808
latest_activity_date=last_comment.datecreated))
810
interesting_activity = self.interesting_activity
775
812
event_groups = group_comments_with_activity(
776
813
comments=visible_comments,
777
activities=self.interesting_activity,
778
batch_size=batch_size, offset=offset)
814
activities=interesting_activity)
779
815
return event_groups
901
937
def total_activity(self):
902
938
"""Return the count of all activity items for the bug."""
903
return self.context.bug.activity.count()
939
# Ignore the first activity item, since it relates to the bug's
941
return self.context.bug.activity.count() - 1
905
943
def wasDescriptionModified(self):
906
944
"""Return a boolean indicating whether the description was modified"""
1064
1102
return int(self.request.form_ng.getOne('offset'))
1065
1103
except TypeError:
1066
# We return visible_initial_comments, since otherwise we'd
1104
# We return visible_initial_comments + 1, since otherwise we'd
1067
1105
# end up repeating comments that are already visible on the
1069
return self.visible_initial_comments
1106
# page. The +1 accounts for the fact that bug comments are
1107
# essentially indexed from 1 due to comment 0 being the
1108
# initial bug description.
1109
return self.visible_initial_comments + 1
1072
1112
def batch_size(self):
1085
1125
def next_offset(self):
1086
1126
return self.offset + self.batch_size
1089
1129
def _event_groups(self):
1090
1130
"""See `BugTaskView`."""
1131
batch_size = self.batch_size
1132
if (batch_size > (self.total_comments) or
1133
not self.has_more_comments_and_activity):
1134
# If the batch size is big enough to encompass all the
1135
# remaining comments and activity, trim it so that we don't
1137
if self.offset == self.visible_initial_comments + 1:
1138
offset_to_remove = self.visible_initial_comments
1140
offset_to_remove = self.offset
1142
self.total_comments - self.visible_recent_comments -
1143
# This last bit is to make sure that _getEventGroups()
1144
# doesn't accidentally inflate the batch size later on.
1091
1146
return self._getEventGroups(
1092
batch_size=self.batch_size,
1147
batch_size=batch_size, offset=self.offset)
1095
1149
@cachedproperty
1096
1150
def has_more_comments_and_activity(self):
1097
1151
"""Return True if there are more camments and activity to load."""
1099
len(self.activity_and_comments) > 0 and
1100
1153
self.next_offset < (self.total_comments + self.total_activity))