Merge lp:~gmb/launchpad/link-attachment-bug-524296 into lp:launchpad/db-devel

Proposed by Graham Binns
Status: Merged
Approved by: Graham Binns
Approved revision: not available
Merged at revision: not available
Proposed branch: lp:~gmb/launchpad/link-attachment-bug-524296
Merge into: lp:launchpad/db-devel
Diff against target: 224 lines (+114/-12)
4 files modified
lib/lp/bugs/configure.zcml (+21/-2)
lib/lp/bugs/doc/bugattachments.txt (+69/-6)
lib/lp/bugs/interfaces/bug.py (+12/-0)
lib/lp/bugs/model/bug.py (+12/-4)
To merge this branch: bzr merge lp:~gmb/launchpad/link-attachment-bug-524296
Reviewer Review Type Date Requested Status
Abel Deuring (community) code Approve
Review via email: mp+19694@code.launchpad.net

Commit message

It's now possible to link existing LibraryFileAliases to a Bug as attachments.

To post a comment you must log in.
Revision history for this message
Graham Binns (gmb) wrote :

This branch adds a linkAttachment() method to IBug and changes
Bug.addAttachment() to use the new linkAttachment() method.

The linkAttachment() method is needed because, when dealing with
uploaded apport blobs we need to be able to link existing
LibraryFileAliases to a bug as attachments rather than creating new
ones.

== lib/lp/bugs/configure.zcml ==

 - I've updated the zcml for IBug / Bug to allow the linkAttachment()
   method for Launchpad.Edit.

== lib/lp/bugs/doc/bugattachments.txt ==

 - I've added tests to cover the new linkAttachment() method. The tests
   for addAttachment() also cover it indirectly.

== lib/lp/bugs/interfaces/bug.py ==

 - I've added a definition of linkAttachment().

== lib/lp/bugs/model/bug.py ==

 - I've added an implementation of linkAttachment().

Revision history for this message
Abel Deuring (adeuring) wrote :

Hi Graham,

a nice small and clean branch, r=me.

Reading the diff, I noticed in line 11 of the diff that the value of "set_attributes" looks really scrambled: lots of spaces but no line breaks. I know that you did not change anything there, but could you please re-format it similar to the value of "attributes", as a drive-by fix?

review: Approve (code)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/lp/bugs/configure.zcml'
2--- lib/lp/bugs/configure.zcml 2010-02-12 21:34:23 +0000
3+++ lib/lp/bugs/configure.zcml 2010-02-19 11:43:16 +0000
4@@ -666,8 +666,27 @@
5 addChange
6 markAsDuplicate
7 linkHWSubmission
8- unlinkHWSubmission"
9- set_attributes="datecreated date_last_updated name title description ownerID owner duplicateof communityscore communitytimestamp hits hitstimestamp activityscore activitytimestamp activity initial_message security_related tags who_made_private date_made_private"/>
10+ unlinkHWSubmission
11+ linkAttachment"
12+ set_attributes="
13+ activity initial_message
14+ activityscore
15+ activitytimestamp
16+ communityscore
17+ communitytimestamp
18+ date_last_updated
19+ date_made_private
20+ datecreated
21+ duplicateof
22+ hits
23+ hitstimestamp
24+ name
25+ owner
26+ ownerID
27+ security_related
28+ tags
29+ title description
30+ who_made_private"/>
31 <require
32 permission="launchpad.AnyPerson"
33 attributes="
34
35=== modified file 'lib/lp/bugs/doc/bugattachments.txt'
36--- lib/lp/bugs/doc/bugattachments.txt 2010-02-17 20:00:14 +0000
37+++ lib/lp/bugs/doc/bugattachments.txt 2010-02-19 11:43:16 +0000
38@@ -1,4 +1,5 @@
39-= Bug Attachments =
40+Bug Attachments
41+===============
42
43 Files can be attached to bugs. There are two types of attachment, Patch
44 and Unspecified. Patch means a proposed fix to the bug, Unspecified
45@@ -17,7 +18,8 @@
46 0
47
48
49-== Creating attachments ==
50+Creating attachments
51+--------------------
52
53 To create an attachment, call IBug.addAttachment. It will emit an
54 ObjectCreatedEvent in order to trigger email notifications:
55@@ -291,7 +293,8 @@
56 >>> event_listener.unregister()
57
58
59-== Security ==
60+Security
61+--------
62
63 If a user can view/edit the bug the attachment is attached to, he can
64 also view/edit the attachment. At the moment the bug_one is public, so
65@@ -373,7 +376,8 @@
66 True
67
68
69-== Search for attachments ==
70+Search for attachments
71+----------------------
72
73 We can search for attachment of a specific types:
74
75@@ -439,7 +443,8 @@
76 False
77
78
79-== Deleting attachments ==
80+Deleting attachments
81+--------------------
82
83 It's also possible to delete attachments.
84
85@@ -481,7 +486,8 @@
86 http://.../foo.baz
87
88
89-== Bugs with patches ==
90+Bugs with patches
91+-----------------
92
93 A bug that has patch attachments associated with it has its `has_patches`
94 property returning True.
95@@ -513,3 +519,60 @@
96 >>> bug_two.has_patches
97 True
98
99+
100+Linking existing LibraryFileAliases as attachments
101+--------------------------------------------------
102+
103+It's possible to link an existing LibraryFileAliases to a bug as an
104+attachment by calling the bug's linkAttachment() method.
105+
106+ >>> from canonical.launchpad.interfaces.librarian import (
107+ ... ILibraryFileAliasSet)
108+
109+ >>> file_content = "Hello, world"
110+ >>> content_type = "text/plain"
111+ >>> file_alias = getUtility(ILibraryFileAliasSet).create(
112+ ... name='foobar', size=len(file_content),
113+ ... file=StringIO(file_content), contentType=content_type)
114+ >>> transaction.commit()
115+
116+ >>> bug = factory.makeBug()
117+ >>> bug.linkAttachment(
118+ ... owner=bug.owner, file_alias=file_alias,
119+ ... comment="Some attachment")
120+ <BugAttachment ...>
121+
122+ >>> bug.attachments.count()
123+ 1
124+ >>> attachment = bug.attachments[0]
125+ >>> print attachment.title
126+ foobar
127+
128+The attachment will have a type of BugAttachmentType.UNSPECIFIED, since
129+we didn't specify that it was a patch.
130+
131+ >>> print attachment.type.title
132+ Unspecified
133+
134+We can specify that the attachment is a patch and give it a more
135+meaningful description.
136+
137+ >>> file_alias = getUtility(ILibraryFileAliasSet).create(
138+ ... name='anotherfoobar', size=len(file_content),
139+ ... file=StringIO(file_content), contentType=content_type)
140+ >>> transaction.commit()
141+
142+ >>> bug.linkAttachment(
143+ ... owner=bug.owner, file_alias=file_alias,
144+ ... comment="Some attachment", is_patch=True,
145+ ... description="An attachment of some sort")
146+ <BugAttachment ...>
147+
148+ >>> bug.attachments.count()
149+ 2
150+ >>> attachment = bug.attachments[1]
151+ >>> print attachment.title
152+ An attachment of some sort
153+
154+ >>> print attachment.type.title
155+ Patch
156
157=== modified file 'lib/lp/bugs/interfaces/bug.py'
158--- lib/lp/bugs/interfaces/bug.py 2010-02-09 20:10:31 +0000
159+++ lib/lp/bugs/interfaces/bug.py 2010-02-19 11:43:16 +0000
160@@ -513,6 +513,18 @@
161 :is_patch: A boolean.
162 """
163
164+ def linkAttachment(owner, file_alias, comment, is_patch=False,
165+ description=None):
166+ """Link an `ILibraryFileAlias` to this bug.
167+
168+ :owner: An IPerson.
169+ :file_alias: The `ILibraryFileAlias` to link to this bug.
170+ :description: A brief description of the attachment.
171+ :comment: An IMessage or string.
172+ :filename: A string.
173+ :is_patch: A boolean.
174+ """
175+
176 def linkCVE(cve, user):
177 """Ensure that this CVE is linked to this bug."""
178
179
180=== modified file 'lib/lp/bugs/model/bug.py'
181--- lib/lp/bugs/model/bug.py 2010-02-11 13:54:07 +0000
182+++ lib/lp/bugs/model/bug.py 2010-02-19 11:43:16 +0000
183@@ -904,10 +904,8 @@
184 filecontent = data.read()
185
186 if is_patch:
187- attach_type = BugAttachmentType.PATCH
188 content_type = 'text/plain'
189 else:
190- attach_type = BugAttachmentType.UNSPECIFIED
191 if content_type is None:
192 content_type, encoding = guess_content_type(
193 name=filename, body=filecontent)
194@@ -916,10 +914,20 @@
195 name=filename, size=len(filecontent),
196 file=StringIO(filecontent), contentType=content_type)
197
198+ return self.linkAttachment(
199+ owner, filealias, comment, is_patch, description)
200+
201+ def linkAttachment(self, owner, file_alias, comment, is_patch=False,
202+ description=None):
203+ if is_patch:
204+ attach_type = BugAttachmentType.PATCH
205+ else:
206+ attach_type = BugAttachmentType.UNSPECIFIED
207+
208 if description:
209 title = description
210 else:
211- title = filename
212+ title = file_alias.filename
213
214 if IMessage.providedBy(comment):
215 message = comment
216@@ -928,7 +936,7 @@
217 owner=owner, subject=description, content=comment)
218
219 return getUtility(IBugAttachmentSet).create(
220- bug=self, filealias=filealias, attach_type=attach_type,
221+ bug=self, filealias=file_alias, attach_type=attach_type,
222 title=title, message=message, send_notifications=True)
223
224 def hasBranch(self, branch):

Subscribers

People subscribed via source and target branches

to status/vote changes: