8687.15.15
by Karl Fogel
Add the copyright header block to files under lib/lp/bugs/. |
1 |
# Copyright 2009 Canonical Ltd. This software is licensed under the
|
2 |
# GNU Affero General Public License version 3 (see the file LICENSE).
|
|
3607.4.9
by Bjorn Tillenius
use BugComment instead of BugMessage. |
3 |
|
4 |
"""Bug comment browser view classes."""
|
|
5 |
||
6 |
__metaclass__ = type |
|
7283.3.1
by Graham Binns
Changed comment_syncing_team. |
7 |
__all__ = [ |
8 |
'BugComment', |
|
12075.3.14
by Gavin Panella
Move group_comments_with_activity() to lp.bugs.browser.bugcomment. |
9 |
'BugCommentBoxExpandedReplyView', |
10 |
'BugCommentBoxView', |
|
11 |
'BugCommentBreadcrumb', |
|
7283.3.1
by Graham Binns
Changed comment_syncing_team. |
12 |
'BugCommentView', |
8461.2.2
by Bjorn Tillenius
Provide a custom XHTML representation of a bug comment. |
13 |
'BugCommentXHTMLRepresentation', |
7283.3.1
by Graham Binns
Changed comment_syncing_team. |
14 |
'build_comments_from_chunks', |
13500.3.9
by j.c.sackett
Fixed formatting. |
15 |
'group_comments_with_activity', |
16 |
]
|
|
3607.4.9
by Bjorn Tillenius
use BugComment instead of BugMessage. |
17 |
|
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
18 |
from datetime import ( |
19 |
datetime, |
|
20 |
timedelta, |
|
21 |
)
|
|
12075.3.14
by Gavin Panella
Move group_comments_with_activity() to lp.bugs.browser.bugcomment. |
22 |
from itertools import ( |
23 |
chain, |
|
24 |
groupby, |
|
25 |
)
|
|
26 |
from operator import itemgetter |
|
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
27 |
|
28 |
from lazr.restful.interfaces import IWebServiceClientRequest |
|
9232.2.70
by Stuart Bishop
Cache bug comments more aggressively |
29 |
from pytz import utc |
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
30 |
from zope.component import ( |
31 |
adapts, |
|
32 |
getMultiAdapter, |
|
33 |
getUtility, |
|
34 |
)
|
|
35 |
from zope.interface import ( |
|
36 |
implements, |
|
37 |
Interface, |
|
38 |
)
|
|
39 |
||
14612.2.1
by William Grant
format-imports on lib/. So many imports. |
40 |
from lp.bugs.interfaces.bugmessage import IBugComment |
14605.1.1
by Curtis Hovey
Moved canonical.config to lp.services. |
41 |
from lp.services.config import config |
14612.2.1
by William Grant
format-imports on lib/. So many imports. |
42 |
from lp.services.features import getFeatureFlag |
43 |
from lp.services.librarian.browser import ProxiedLibraryFileAlias |
|
14600.2.2
by Curtis Hovey
Moved webapp to lp.services. |
44 |
from lp.services.webapp import ( |
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
45 |
canonical_url, |
46 |
LaunchpadView, |
|
47 |
)
|
|
14600.2.2
by Curtis Hovey
Moved webapp to lp.services. |
48 |
from lp.services.webapp.breadcrumb import Breadcrumb |
49 |
from lp.services.webapp.interfaces import ILaunchBag |
|
3504.1.51
by kiko
r=bradb Refactor fetching of bug comments to issue O(1) queries. Essentially inverts the way we build the bug comments, fetching all the chunks first, grouping them by message. Should be a major performance boost for the bug page. |
50 |
|
51 |
||
12075.3.14
by Gavin Panella
Move group_comments_with_activity() to lp.bugs.browser.bugcomment. |
52 |
COMMENT_ACTIVITY_GROUPING_WINDOW = timedelta(minutes=5) |
53 |
||
54 |
||
12929.7.39
by j.c.sackett
Added spam controls to bug comments. |
55 |
def build_comments_from_chunks( |
14302.4.1
by Ian Booth
Allow users in project roles and comment owners to hide comments |
56 |
bugtask, truncate=False, slice_info=None, show_spam_controls=False, |
57 |
user=None): |
|
12376.1.2
by Robert Collins
Basic implementation in place, tests not updated. |
58 |
"""Build BugComments from MessageChunks.
|
12840.7.3
by j.c.sackett
Lint fixes. |
59 |
|
12376.1.2
by Robert Collins
Basic implementation in place, tests not updated. |
60 |
:param truncate: Perform truncation of large messages.
|
61 |
:param slice_info: If not None, an iterable of slices to retrieve.
|
|
62 |
"""
|
|
63 |
chunks = bugtask.bug.getMessagesForView(slice_info=slice_info) |
|
64 |
# This would be better as part of indexed_messages eager loading.
|
|
3504.1.51
by kiko
r=bradb Refactor fetching of bug comments to issue O(1) queries. Essentially inverts the way we build the bug comments, fetching all the chunks first, grouping them by message. Should be a major performance boost for the bug page. |
65 |
comments = {} |
12376.1.2
by Robert Collins
Basic implementation in place, tests not updated. |
66 |
for bugmessage, message, chunk in chunks: |
67 |
bug_comment = comments.get(message.id) |
|
3553.3.23
by Brad Bollenbach
small tweaks to kiko's patch |
68 |
if bug_comment is None: |
12929.7.46
by j.c.sackett
Lint fixes. |
69 |
bug_comment = BugComment( |
70 |
bugmessage.index, message, bugtask, visible=message.visible, |
|
14302.4.1
by Ian Booth
Allow users in project roles and comment owners to hide comments |
71 |
show_spam_controls=show_spam_controls, user=user) |
12376.1.2
by Robert Collins
Basic implementation in place, tests not updated. |
72 |
comments[message.id] = bug_comment |
12840.7.3
by j.c.sackett
Lint fixes. |
73 |
# This code path is currently only used from a BugTask view which
|
74 |
# has already loaded all the bug watches. If we start lazy loading
|
|
12376.1.6
by Robert Collins
Test (and fix) Bug.getMessagesForView. |
75 |
# those, or not needing them we will need to batch lookup watches
|
76 |
# here.
|
|
12376.1.2
by Robert Collins
Basic implementation in place, tests not updated. |
77 |
if bugmessage.bugwatchID is not None: |
78 |
bug_comment.bugwatch = bugmessage.bugwatch |
|
79 |
bug_comment.synchronized = ( |
|
80 |
bugmessage.remote_comment_id is not None) |
|
3553.3.23
by Brad Bollenbach
small tweaks to kiko's patch |
81 |
bug_comment.chunks.append(chunk) |
5796.3.4
by Bjorn Tillenius
move code. |
82 |
|
83 |
for comment in comments.values(): |
|
12376.1.2
by Robert Collins
Basic implementation in place, tests not updated. |
84 |
# Once we have all the chunks related to a comment populated,
|
5796.3.4
by Bjorn Tillenius
move code. |
85 |
# we get the text set up for display.
|
86 |
comment.setupText(truncate=truncate) |
|
3504.1.51
by kiko
r=bradb Refactor fetching of bug comments to issue O(1) queries. Essentially inverts the way we build the bug comments, fetching all the chunks first, grouping them by message. Should be a major performance boost for the bug page. |
87 |
return comments |
3607.4.9
by Bjorn Tillenius
use BugComment instead of BugMessage. |
88 |
|
89 |
||
13955.1.1
by Graham Binns
Batched activity now no longer pulls in results that have already been shown. |
90 |
def group_comments_with_activity(comments, activities): |
12075.3.14
by Gavin Panella
Move group_comments_with_activity() to lp.bugs.browser.bugcomment. |
91 |
"""Group comments and activity together for human consumption.
|
92 |
||
93 |
Generates a stream of comment instances (with the activity grouped within)
|
|
94 |
or `list`s of grouped activities.
|
|
95 |
||
12376.1.4
by Robert Collins
Fix known bugs. |
96 |
:param comments: An iterable of `BugComment` instances, which should be
|
97 |
sorted by index already.
|
|
12075.3.14
by Gavin Panella
Move group_comments_with_activity() to lp.bugs.browser.bugcomment. |
98 |
:param activities: An iterable of `BugActivity` instances.
|
99 |
"""
|
|
100 |
window = COMMENT_ACTIVITY_GROUPING_WINDOW |
|
101 |
||
102 |
comment_kind = "comment" |
|
12376.1.4
by Robert Collins
Fix known bugs. |
103 |
if comments: |
104 |
max_index = comments[-1].index + 1 |
|
105 |
else: |
|
106 |
max_index = 0 |
|
12075.3.14
by Gavin Panella
Move group_comments_with_activity() to lp.bugs.browser.bugcomment. |
107 |
comments = ( |
12840.7.3
by j.c.sackett
Lint fixes. |
108 |
(comment.datecreated, comment.index, |
109 |
comment.owner, comment_kind, comment) |
|
12075.3.14
by Gavin Panella
Move group_comments_with_activity() to lp.bugs.browser.bugcomment. |
110 |
for comment in comments) |
111 |
activity_kind = "activity" |
|
112 |
activity = ( |
|
12840.7.3
by j.c.sackett
Lint fixes. |
113 |
(activity.datechanged, max_index, |
114 |
activity.person, activity_kind, activity) |
|
12075.3.14
by Gavin Panella
Move group_comments_with_activity() to lp.bugs.browser.bugcomment. |
115 |
for activity in activities) |
12376.1.4
by Robert Collins
Fix known bugs. |
116 |
# when an action and a comment happen at the same time, the action comes
|
117 |
# second, when two events are tied the comment index is used to
|
|
118 |
# disambiguate.
|
|
119 |
events = sorted(chain(comments, activity), key=itemgetter(0, 1, 2)) |
|
12075.3.14
by Gavin Panella
Move group_comments_with_activity() to lp.bugs.browser.bugcomment. |
120 |
|
121 |
def gen_event_windows(events): |
|
122 |
"""Generate event windows.
|
|
123 |
||
124 |
Yields `(window_index, kind, event)` tuples, where `window_index` is
|
|
125 |
an integer, and is incremented each time the windowing conditions are
|
|
126 |
triggered.
|
|
127 |
||
12376.1.4
by Robert Collins
Fix known bugs. |
128 |
:param events: An iterable of `(date, ignored, actor, kind, event)`
|
129 |
tuples in order.
|
|
12075.3.14
by Gavin Panella
Move group_comments_with_activity() to lp.bugs.browser.bugcomment. |
130 |
"""
|
131 |
window_comment, window_actor = None, None |
|
132 |
window_index, window_end = 0, None |
|
12376.1.4
by Robert Collins
Fix known bugs. |
133 |
for date, _, actor, kind, event in events: |
12075.3.14
by Gavin Panella
Move group_comments_with_activity() to lp.bugs.browser.bugcomment. |
134 |
window_ended = ( |
135 |
# A window may contain only one comment.
|
|
136 |
(window_comment is not None and kind is comment_kind) or |
|
137 |
# All events must have happened within a given timeframe.
|
|
138 |
(window_end is None or date >= window_end) or |
|
139 |
# All events within the window must belong to the same actor.
|
|
140 |
(window_actor is None or actor != window_actor)) |
|
141 |
if window_ended: |
|
142 |
window_comment, window_actor = None, actor |
|
143 |
window_index, window_end = window_index + 1, date + window |
|
144 |
if kind is comment_kind: |
|
145 |
window_comment = event |
|
146 |
yield window_index, kind, event |
|
147 |
||
148 |
event_windows = gen_event_windows(events) |
|
149 |
event_windows_grouper = groupby(event_windows, itemgetter(0)) |
|
150 |
for window_index, window_group in event_windows_grouper: |
|
151 |
window_group = [ |
|
152 |
(kind, event) for (index, kind, event) in window_group] |
|
153 |
for kind, event in window_group: |
|
154 |
if kind is comment_kind: |
|
155 |
window_comment = event |
|
156 |
window_comment.activity.extend( |
|
157 |
event for (kind, event) in window_group |
|
158 |
if kind is activity_kind) |
|
159 |
yield window_comment |
|
160 |
# There's only one comment per window.
|
|
161 |
break
|
|
162 |
else: |
|
163 |
yield [event for (kind, event) in window_group] |
|
164 |
||
165 |
||
3607.4.9
by Bjorn Tillenius
use BugComment instead of BugMessage. |
166 |
class BugComment: |
3504.1.51
by kiko
r=bradb Refactor fetching of bug comments to issue O(1) queries. Essentially inverts the way we build the bug comments, fetching all the chunks first, grouping them by message. Should be a major performance boost for the bug page. |
167 |
"""Data structure that holds all data pertaining to a bug comment.
|
3607.4.9
by Bjorn Tillenius
use BugComment instead of BugMessage. |
168 |
|
3504.1.51
by kiko
r=bradb Refactor fetching of bug comments to issue O(1) queries. Essentially inverts the way we build the bug comments, fetching all the chunks first, grouping them by message. Should be a major performance boost for the bug page. |
169 |
It keeps track of which index it has in the bug comment list and
|
3607.4.9
by Bjorn Tillenius
use BugComment instead of BugMessage. |
170 |
also provides functionality to truncate the comment.
|
3504.1.51
by kiko
r=bradb Refactor fetching of bug comments to issue O(1) queries. Essentially inverts the way we build the bug comments, fetching all the chunks first, grouping them by message. Should be a major performance boost for the bug page. |
171 |
|
172 |
Note that although this class is called BugComment it really takes
|
|
173 |
as an argument a bugtask. The reason for this is to allow
|
|
174 |
canonical_url()s of BugComments to take you to the correct
|
|
175 |
(task-specific) location.
|
|
3607.4.9
by Bjorn Tillenius
use BugComment instead of BugMessage. |
176 |
"""
|
177 |
implements(IBugComment) |
|
3504.1.51
by kiko
r=bradb Refactor fetching of bug comments to issue O(1) queries. Essentially inverts the way we build the bug comments, fetching all the chunks first, grouping them by message. Should be a major performance boost for the bug page. |
178 |
|
12929.7.39
by j.c.sackett
Added spam controls to bug comments. |
179 |
def __init__( |
180 |
self, index, message, bugtask, activity=None, |
|
14302.4.1
by Ian Booth
Allow users in project roles and comment owners to hide comments |
181 |
visible=True, show_spam_controls=False, user=None): |
12929.7.39
by j.c.sackett
Added spam controls to bug comments. |
182 |
|
3504.1.51
by kiko
r=bradb Refactor fetching of bug comments to issue O(1) queries. Essentially inverts the way we build the bug comments, fetching all the chunks first, grouping them by message. Should be a major performance boost for the bug page. |
183 |
self.index = index |
3607.4.11
by Bjorn Tillenius
define a canonical url for IBugComment and use it. |
184 |
self.bugtask = bugtask |
5796.3.1
by Bjorn Tillenius
quick hack |
185 |
self.bugwatch = None |
3504.1.51
by kiko
r=bradb Refactor fetching of bug comments to issue O(1) queries. Essentially inverts the way we build the bug comments, fetching all the chunks first, grouping them by message. Should be a major performance boost for the bug page. |
186 |
|
187 |
self.title = message.title |
|
3847.2.47
by Mark Shuttleworth
Add tests for new bug comment behaviour, and extra bug sample data. |
188 |
self.display_title = False |
3504.1.51
by kiko
r=bradb Refactor fetching of bug comments to issue O(1) queries. Essentially inverts the way we build the bug comments, fetching all the chunks first, grouping them by message. Should be a major performance boost for the bug page. |
189 |
self.datecreated = message.datecreated |
190 |
self.owner = message.owner |
|
5127.1.2
by Christian Reis
Fix for bug #139327, comments are missing in +text view. Also adds fields for privacy, security and dates created. |
191 |
self.rfc822msgid = message.rfc822msgid |
3504.1.51
by kiko
r=bradb Refactor fetching of bug comments to issue O(1) queries. Essentially inverts the way we build the bug comments, fetching all the chunks first, grouping them by message. Should be a major performance boost for the bug page. |
192 |
|
193 |
self.chunks = [] |
|
194 |
self.bugattachments = [] |
|
10017.2.2
by Abel Deuring
added property BugComment.patches; removed attachment that are patches from BugComment.bugattachments; separate display of regular attachments and patches on bug pages |
195 |
self.patches = [] |
3504.1.51
by kiko
r=bradb Refactor fetching of bug comments to issue O(1) queries. Essentially inverts the way we build the bug comments, fetching all the chunks first, grouping them by message. Should be a major performance boost for the bug page. |
196 |
|
8128.8.2
by Graham Binns
Added activity param to BugComment. |
197 |
if activity is None: |
198 |
activity = [] |
|
199 |
||
200 |
self.activity = activity |
|
201 |
||
6293.1.1
by Tom Berger
reply to remore bug comments ui |
202 |
self.synchronized = False |
12376.1.2
by Robert Collins
Basic implementation in place, tests not updated. |
203 |
self.visible = visible |
14302.4.3
by Ian Booth
Add feature flag |
204 |
# We use a feature flag to control users deleting their own comments.
|
205 |
user_owns_comment = False |
|
206 |
flag = 'disclosure.users_hide_own_bug_comments.enabled' |
|
207 |
if bool(getFeatureFlag(flag)): |
|
208 |
user_owns_comment = user is not None and user == self.owner |
|
14302.4.1
by Ian Booth
Allow users in project roles and comment owners to hide comments |
209 |
self.show_spam_controls = show_spam_controls or user_owns_comment |
5292.4.8
by Graham Binns
Added +comments page for bug watches and associated tests. |
210 |
|
5292.4.1
by Graham Binns
Comments are now filtered properly. Imported comments say that they are. |
211 |
@property
|
8137.17.24
by Barry Warsaw
thread merge |
212 |
def show_for_admin(self): |
213 |
"""Show hidden comments for Launchpad admins.
|
|
214 |
||
215 |
This is used in templates to add a class to hidden
|
|
216 |
comments to enable display for admins, so the admin
|
|
12840.7.3
by j.c.sackett
Lint fixes. |
217 |
can see the comment even after it is hidden. Since comments
|
218 |
aren't published unless the user is registry or admin, this
|
|
219 |
can just check if the comment is visible.
|
|
8137.17.24
by Barry Warsaw
thread merge |
220 |
"""
|
12840.7.3
by j.c.sackett
Lint fixes. |
221 |
return not self.visible |
8137.17.24
by Barry Warsaw
thread merge |
222 |
|
3504.1.51
by kiko
r=bradb Refactor fetching of bug comments to issue O(1) queries. Essentially inverts the way we build the bug comments, fetching all the chunks first, grouping them by message. Should be a major performance boost for the bug page. |
223 |
def setupText(self, truncate=False): |
4787.1.5
by Graham Binns
Kiko's review changes. |
224 |
"""Set the text for display and truncate it if necessary.
|
225 |
||
226 |
Note that this method must be called before either isIdenticalTo() or
|
|
227 |
isEmpty() are called, since to do otherwise would mean that they could
|
|
228 |
return false positives and negatives respectively.
|
|
229 |
"""
|
|
3504.1.51
by kiko
r=bradb Refactor fetching of bug comments to issue O(1) queries. Essentially inverts the way we build the bug comments, fetching all the chunks first, grouping them by message. Should be a major performance boost for the bug page. |
230 |
comment_limit = config.malone.max_comment_size |
231 |
||
6025.2.1
by Abel Deuring
fix for bug 163991: Attachments for initial comment are not displayed |
232 |
bits = [unicode(chunk.content) |
6025.2.3
by Abel Deuring
implemented another reviewer remark |
233 |
for chunk in self.chunks |
234 |
if chunk.content is not None and len(chunk.content) > 0] |
|
3504.1.51
by kiko
r=bradb Refactor fetching of bug comments to issue O(1) queries. Essentially inverts the way we build the bug comments, fetching all the chunks first, grouping them by message. Should be a major performance boost for the bug page. |
235 |
text = self.text_contents = '\n\n'.join(bits) |
236 |
||
237 |
if truncate and comment_limit and len(text) > comment_limit: |
|
3691.62.33
by kiko
Fix some of our test bustage. As part of this, don't deduct 3 from max_comment_size, because it breaks for max_comment_sizes under 3. Reorganize the bugcomment.txt test somewhat to account for comment omission. |
238 |
# Note here that we truncate at comment_limit, and not
|
239 |
# comment_limit - 3; while it would be nice to account for
|
|
240 |
# the ellipsis, this breaks down when the comment limit is
|
|
241 |
# less than 3 (which can happen in a testcase) and it makes
|
|
242 |
# counting the strings harder.
|
|
243 |
self.text_for_display = "%s..." % text[:comment_limit] |
|
3504.1.51
by kiko
r=bradb Refactor fetching of bug comments to issue O(1) queries. Essentially inverts the way we build the bug comments, fetching all the chunks first, grouping them by message. Should be a major performance boost for the bug page. |
244 |
self.was_truncated = True |
3607.4.9
by Bjorn Tillenius
use BugComment instead of BugMessage. |
245 |
else: |
246 |
self.text_for_display = text |
|
3504.1.51
by kiko
r=bradb Refactor fetching of bug comments to issue O(1) queries. Essentially inverts the way we build the bug comments, fetching all the chunks first, grouping them by message. Should be a major performance boost for the bug page. |
247 |
self.was_truncated = False |
3607.4.9
by Bjorn Tillenius
use BugComment instead of BugMessage. |
248 |
|
3691.134.10
by kiko
Fix for bug 60574, Comments/Audit trail does not show multiple attachments. Check comment titles and attachment lists to ensure that we don't omit too much, and properly test the feature. |
249 |
def isIdenticalTo(self, other): |
4787.1.5
by Graham Binns
Kiko's review changes. |
250 |
"""Compare this BugComment to another and return True if they are
|
251 |
identical.
|
|
252 |
"""
|
|
3869.1.3
by Diogo Matsubara
Fix bug 88531 (Comment shown in activity log but missing from bug page) |
253 |
if self.owner != other.owner: |
254 |
return False |
|
3691.134.10
by kiko
Fix for bug 60574, Comments/Audit trail does not show multiple attachments. Check comment titles and attachment lists to ensure that we don't omit too much, and properly test the feature. |
255 |
if self.text_for_display != other.text_for_display: |
256 |
return False |
|
257 |
if self.title != other.title: |
|
258 |
return False |
|
10017.2.2
by Abel Deuring
added property BugComment.patches; removed attachment that are patches from BugComment.bugattachments; separate display of regular attachments and patches on bug pages |
259 |
if (self.bugattachments or self.patches or other.bugattachments or |
260 |
other.patches): |
|
3691.134.10
by kiko
Fix for bug 60574, Comments/Audit trail does not show multiple attachments. Check comment titles and attachment lists to ensure that we don't omit too much, and properly test the feature. |
261 |
# We shouldn't collapse comments which have attachments;
|
262 |
# there's really no possible identity in that case.
|
|
263 |
return False |
|
264 |
return True |
|
265 |
||
4787.1.1
by Graham Binns
Empty comments will no longer show up on the index page of a bug task. (So if a comment with an attachment but no body has its attachment removed, the comment will disappear, too.) |
266 |
def isEmpty(self): |
267 |
"""Return True if text_for_display is empty."""
|
|
6025.2.1
by Abel Deuring
fix for bug 163991: Attachments for initial comment are not displayed |
268 |
|
4767.5.43
by Graham Binns
Fixed a formatting snafu. |
269 |
return (len(self.text_for_display) == 0 and |
10017.2.2
by Abel Deuring
added property BugComment.patches; removed attachment that are patches from BugComment.bugattachments; separate display of regular attachments and patches on bug pages |
270 |
len(self.bugattachments) == 0 and len(self.patches) == 0) |
4787.1.1
by Graham Binns
Empty comments will no longer show up on the index page of a bug task. (So if a comment with an attachment but no body has its attachment removed, the comment will disappear, too.) |
271 |
|
6293.1.1
by Tom Berger
reply to remore bug comments ui |
272 |
@property
|
273 |
def add_comment_url(self): |
|
274 |
return canonical_url(self.bugtask, view_name='+addcomment') |
|
275 |
||
8128.8.6
by Graham Binns
Moved activity table into a macro and added styling; added show_footer property to BugComment. |
276 |
@property
|
277 |
def show_footer(self): |
|
278 |
"""Return True if the footer should be shown for this comment."""
|
|
12929.7.47
by j.c.sackett
Some quick fixes for tests. |
279 |
return bool( |
12929.7.39
by j.c.sackett
Added spam controls to bug comments. |
280 |
len(self.activity) > 0 or |
281 |
self.bugwatch or |
|
282 |
self.show_spam_controls) |
|
8128.8.6
by Graham Binns
Moved activity table into a macro and added styling; added show_footer property to BugComment. |
283 |
|
9232.2.70
by Stuart Bishop
Cache bug comments more aggressively |
284 |
@property
|
285 |
def rendered_cache_time(self): |
|
286 |
"""The number of seconds we can cache the rendered comment for.
|
|
287 |
||
288 |
Bug comments are cached with 'authenticated' visibility, so
|
|
289 |
should contain no information hidden from some users. We use
|
|
290 |
'authenticated' rather than 'public' as email addresses are
|
|
291 |
obfuscated for unauthenticated users.
|
|
292 |
"""
|
|
293 |
now = datetime.now(tz=utc) |
|
12075.3.13
by Gavin Panella
Prevent caching of bug comments that are less than 5 minutes old. |
294 |
|
295 |
# The major factor in how long we can cache a bug comment is the
|
|
296 |
# timestamp. For up to 5 minutes comments and activity can be grouped
|
|
297 |
# together as related, so do not cache.
|
|
298 |
if self.datecreated > now - COMMENT_ACTIVITY_GROUPING_WINDOW: |
|
299 |
# Don't return 0 because that indicates no time limit.
|
|
300 |
return -1 |
|
301 |
||
302 |
# The rendering of the timestamp changes every minute for the first
|
|
303 |
# hour because we say '7 minutes ago'.
|
|
304 |
elif self.datecreated > now - timedelta(hours=1): |
|
9232.2.70
by Stuart Bishop
Cache bug comments more aggressively |
305 |
return 60 |
306 |
||
307 |
# Don't cache for long if we are waiting for synchronization.
|
|
308 |
elif self.bugwatch and not self.synchronized: |
|
13500.5.2
by j.c.sackett
Lint fixes. |
309 |
return 5 * 60 |
9232.2.70
by Stuart Bishop
Cache bug comments more aggressively |
310 |
|
311 |
# For the rest of the first day, the rendering changes every
|
|
312 |
# hour. '4 hours ago'. Expire in 15 minutes so the timestamp
|
|
313 |
# is at most 15 minutes out of date.
|
|
314 |
elif self.datecreated > now - timedelta(days=1): |
|
13500.5.2
by j.c.sackett
Lint fixes. |
315 |
return 15 * 60 |
9232.2.70
by Stuart Bishop
Cache bug comments more aggressively |
316 |
|
317 |
# Otherwise, cache away. Lets cache for 6 hours. We don't want
|
|
318 |
# to cache for too long as there are still things that can
|
|
319 |
# become stale - eg. if a bug attachment has been deleted we
|
|
320 |
# should stop rendering the link.
|
|
321 |
else: |
|
13500.5.2
by j.c.sackett
Lint fixes. |
322 |
return 6 * 60 * 60 |
9232.2.70
by Stuart Bishop
Cache bug comments more aggressively |
323 |
|
3607.4.9
by Bjorn Tillenius
use BugComment instead of BugMessage. |
324 |
|
325 |
class BugCommentView(LaunchpadView): |
|
326 |
"""View for a single bug comment."""
|
|
327 |
||
328 |
def __init__(self, context, request): |
|
329 |
# We use the current bug task as the context in order to get the
|
|
330 |
# menu and portlets working.
|
|
331 |
bugtask = getUtility(ILaunchBag).bugtask |
|
332 |
LaunchpadView.__init__(self, bugtask, request) |
|
3607.4.12
by Bjorn Tillenius
s/message/comment/ |
333 |
self.comment = context |
8461.1.1
by Bjorn Tillenius
Move the rendering of a comment box into a view. |
334 |
|
12929.7.47
by j.c.sackett
Some quick fixes for tests. |
335 |
@property
|
336 |
def show_spam_controls(self): |
|
337 |
return self.comment.show_spam_controls |
|
13500.5.2
by j.c.sackett
Lint fixes. |
338 |
|
9232.1.1
by Deryck Hodge
Update bugcomment-index to 3.0 UI. Drop portlets, which |
339 |
def page_title(self): |
340 |
return 'Comment %d for bug %d' % ( |
|
341 |
self.comment.index, self.context.bug.id) |
|
342 |
||
13500.3.3
by j.c.sackett
Adds privacy ribbon to comments. |
343 |
@property
|
14412.3.2
by mbp at canonical
bugcomment page description is the text of the comment |
344 |
def page_description(self): |
345 |
return self.comment.text_contents |
|
346 |
||
347 |
@property
|
|
13500.3.3
by j.c.sackett
Adds privacy ribbon to comments. |
348 |
def privacy_notice_classes(self): |
349 |
if not self.context.bug.private: |
|
350 |
return 'hidden' |
|
351 |
else: |
|
352 |
return '' |
|
353 |
||
8461.1.1
by Bjorn Tillenius
Move the rendering of a comment box into a view. |
354 |
|
11235.6.3
by Abel Deuring
update those tests that are affected by the switch to ProxiedLibraryFileAlias |
355 |
class BugCommentBoxViewMixin: |
356 |
"""A class which provides proxied Librarian URLs for bug attachments."""
|
|
357 |
||
12929.7.49
by j.c.sackett
Better spam control check. |
358 |
@property
|
359 |
def show_spam_controls(self): |
|
360 |
if hasattr(self.context, 'show_spam_controls'): |
|
13500.5.2
by j.c.sackett
Lint fixes. |
361 |
return self.context.show_spam_controls |
12929.7.49
by j.c.sackett
Better spam control check. |
362 |
elif (hasattr(self, 'comment') and |
13500.5.2
by j.c.sackett
Lint fixes. |
363 |
hasattr(self.comment, 'show_spam_controls')): |
364 |
return self.comment.show_spam_controls |
|
12929.7.49
by j.c.sackett
Better spam control check. |
365 |
else: |
13500.5.2
by j.c.sackett
Lint fixes. |
366 |
return False |
12929.7.47
by j.c.sackett
Some quick fixes for tests. |
367 |
|
11235.6.3
by Abel Deuring
update those tests that are affected by the switch to ProxiedLibraryFileAlias |
368 |
def proxiedUrlOfLibraryFileAlias(self, attachment): |
369 |
"""Return the proxied URL for the Librarian file of the attachment."""
|
|
370 |
return ProxiedLibraryFileAlias( |
|
371 |
attachment.libraryfile, attachment).http_url |
|
372 |
||
373 |
||
374 |
class BugCommentBoxView(LaunchpadView, BugCommentBoxViewMixin): |
|
8461.1.1
by Bjorn Tillenius
Move the rendering of a comment box into a view. |
375 |
"""Render a comment box with reply field collapsed."""
|
376 |
||
377 |
expand_reply_box = False |
|
378 |
||
379 |
||
11235.6.3
by Abel Deuring
update those tests that are affected by the switch to ProxiedLibraryFileAlias |
380 |
class BugCommentBoxExpandedReplyView(LaunchpadView, BugCommentBoxViewMixin): |
8461.1.1
by Bjorn Tillenius
Move the rendering of a comment box into a view. |
381 |
"""Render a comment box with reply field expanded."""
|
382 |
||
383 |
expand_reply_box = True |
|
8461.2.2
by Bjorn Tillenius
Provide a custom XHTML representation of a bug comment. |
384 |
|
385 |
||
386 |
class BugCommentXHTMLRepresentation: |
|
387 |
adapts(IBugComment, IWebServiceClientRequest) |
|
388 |
implements(Interface) |
|
389 |
||
390 |
def __init__(self, comment, request): |
|
391 |
self.comment = comment |
|
392 |
self.request = request |
|
393 |
||
394 |
def __call__(self): |
|
395 |
"""Render `BugComment` as XHTML using the webservice."""
|
|
396 |
comment_view = getMultiAdapter( |
|
397 |
(self.comment, self.request), name="+box") |
|
398 |
return comment_view() |
|
399 |
||
10542.12.2
by Karl Fogel
Fix bug #78565: no direct link from bug comment page to corresponding bug. |
400 |
|
401 |
class BugCommentBreadcrumb(Breadcrumb): |
|
402 |
"""Breadcrumb for an `IBugComment`."""
|
|
403 |
||
404 |
def __init__(self, context): |
|
405 |
super(BugCommentBreadcrumb, self).__init__(context) |
|
406 |
||
407 |
@property
|
|
408 |
def text(self): |
|
409 |
return "Comment #%d" % self.context.index |