Merge lp:~pcjc2/launchpad/allow-empty-comments into lp:launchpad

Proposed by Peter Clifton
Status: Merged
Approved by: Graham Binns
Approved revision: no longer in the source branch.
Merged at revision: 12128
Proposed branch: lp:~pcjc2/launchpad/allow-empty-comments
Merge into: lp:launchpad
Diff against target: 218 lines (+92/-42)
3 files modified
lib/lp/bugs/scripts/bugimport.py (+3/-1)
lib/lp/bugs/scripts/tests/test_bugimport.py (+77/-30)
scripts/bug-import.py (+12/-11)
To merge this branch: bzr merge lp:~pcjc2/launchpad/allow-empty-comments
Reviewer Review Type Date Requested Status
Graham Binns (community) code Approve
Peter Clifton (community) Abstain
Review via email: mp+43449@code.launchpad.net

Commit message

[r=gmb][ui=none][bug=692951] Avoid insersion of an "<empty comment>" placeholder for imported bug comments which contain an attachment.

Description of the change

Without this change, it is not possible for the import to give the same clean, uncluttered blank comments you see when adding files directly from within the launchpad web-interface.

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

Hi Peter,

Thanks for this branch. I'm marking it "Needs Fixing" because your
change is untested. We're very strict about adding tests for new
features in Launchpad, and there needs to be a unit test for this new
code before it can land.

The new test should go in lib/lp/bugs/scripts/tests/test_bugimport.py,
along with the other bug import tests. If you need any help writing the
test feel free to ping me (gmb) or Gavin (allenap) in #launchpad-dev on
Freenode.

Besides the test issue I've got one other comment:

37 self.parser.add_option('--dont-verify-users', dest='verify_users',
38 help="Don't verify newly created users",
39 action='store_false', default=True)
40 + self.parser.add_option('--allow-empty-comments',
41 + dest='allow_empty_comments',
42 + help="Allow empty bug comments",
43 + action='store_true', default=False)

It would be really great if you could format this, and the lines above
it (which are formatted incorrectly) according to our style guide, which
is thus:

        self.parser.add_option(
            '--allow-empty-comments', dest='allow_empty_comments',
            help="Allow empty bug comments", action='store_true',
            default=False)

review: Needs Fixing (code)
Revision history for this message
Peter Clifton (pcjc2) wrote :

Thanks for the review, I'll get onto that when I get a moment.

Is there any chance of getting it merged soon when that is fixed?

I've got our SourceForge bug data for two upstream projects I'm working on (and hoping to move to Launchpad), but they will not import properly without this patch. Is there a particular development / release cycle which will need to be synced up with before we can (for example), use this modification to do an import to Staging for testing?

Revision history for this message
Peter Clifton (pcjc2) wrote :

I have updated branch with the following changes:

1. Reformated option arguments as per previous code review
2. Removed --allow-empty-comments option previously added in the branch
3. Instead, added a test for attachments when generating the comment message.
   This then drops the place-holder "<empty comment>" for those with attachments.
4. Extended the bugimport unit test to check the new behaviour.

review: Needs Resubmitting
Revision history for this message
Peter Clifton (pcjc2) :
review: Abstain
Revision history for this message
Graham Binns (gmb) wrote :

Hi Peter,

I'm really pleased with this branch - nice work! I've got a couple of stylistic nitpicks but it's nothing major. Once those are fixed I'll push it into our merge machinery for you.

9 + # If there is no attachment and no comment text, use a place-holder
10 + no_attachments = get_element (commentnode, 'attachment') == None

It took me a couple of seconds to parse this. I think it would be better as part of the conditional that follows it, thus:

    # If there is no attachment and no comment text, use a place-holder.
    if (get_element(commentnode, 'attachment') is None and
        (text is None or text == '')):
        ...

66 + self.assertEqual(message4.owner.preferredemail.email,
67 + '<email address hidden>')
68 + self.assertEqual(message4.datecreated.isoformat(),
69 + '2005-01-01T14:00:00+00:00')
70 + self.assertEqual(message4.subject, 'Re: A test bug')
71 + self.assertEqual(message4.text_contents, '<empty comment>')
72 + self.assertEqual(message4.bugattachments.count(), 0)
73 +
74 + # Message 5:
75 + self.assertEqual(message5.owner.preferredemail.email,
76 + '<email address hidden>')
77 + self.assertEqual(message5.datecreated.isoformat(),
78 + '2005-01-01T15:00:00+00:00')

I know that all the other asserts in the test are formatted like this, and I don't expect you to correct those too (I'll file a bug about cleaning it up), but these should be formatted as I said in my other review:

    self.assertEqual(
        message5.datecreated.isoformat(), ...)

And so on.

review: Needs Fixing (code)
Revision history for this message
Graham Binns (gmb) :
review: Approve (code)
Revision history for this message
Jelmer Vernooij (jelmer) wrote :

Hi Graham, are you landing this branch ?

Revision history for this message
Graham Binns (gmb) wrote :

On Monday, 20 December 2010, Jelmer Vernooij <email address hidden> wrote:
> Hi Graham, are you landing this branch ?

Yes. I was waiting for confirmation of the contributors' agreement
dance having been concluded. I'll land this tomorrow.

--
Graham Binns
http://grahambinns.com

Revision history for this message
Graham Binns (gmb) wrote :

Hi Peter,

I've passed this on to Gavin Panella (allenap) and Deryck Hodge (deryck) to handle, as I'm taking the day off sick. Hopefully we can find out what's happened with your Contributor Agreement paperwork and get this landed ASAP.

Cheers,

Graham

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/lp/bugs/scripts/bugimport.py'
2--- lib/lp/bugs/scripts/bugimport.py 2010-08-20 20:31:18 +0000
3+++ lib/lp/bugs/scripts/bugimport.py 2010-12-16 17:06:41 +0000
4@@ -408,7 +408,9 @@
5 if date is None:
6 raise BugXMLSyntaxError('No date for comment %r' % title)
7 text = get_value(commentnode, 'text')
8- if text is None or text == '':
9+ # If there is no comment text and no attachment, use a place-holder
10+ if ((text is None or text == '') and
11+ get_element(commentnode, 'attachment') is None):
12 text = '<empty comment>'
13 return getUtility(IMessageSet).fromText(title, text, sender, date)
14
15
16=== modified file 'lib/lp/bugs/scripts/tests/test_bugimport.py'
17--- lib/lp/bugs/scripts/tests/test_bugimport.py 2010-10-04 19:50:45 +0000
18+++ lib/lp/bugs/scripts/tests/test_bugimport.py 2010-12-16 17:06:41 +0000
19@@ -427,6 +427,25 @@
20 <contents>QSBwYXRjaA==</contents>
21 </attachment>
22 </comment>
23+ <comment>
24+ <!-- empty comment -->
25+ <sender name="nobody"/>
26+ <date>2005-01-01T14:00:00Z</date>
27+ <text></text>
28+ </comment>
29+ <comment>
30+ <!-- empty comment with attachment -->
31+ <sender name="nobody"/>
32+ <date>2005-01-01T15:00:00Z</date>
33+ <text></text>
34+ <attachment>
35+ <type>UNSPECIFIED</type>
36+ <filename>hello.txt</filename>
37+ <title>Hello</title>
38+ <mimetype>text/plain</mimetype>
39+ <contents>SGVsbG8gd29ybGQ=</contents>
40+ </attachment>
41+ </comment>
42 </bug>'''
43
44 duplicate_bug = '''\
45@@ -491,50 +510,55 @@
46 self.assertNotEqual(bug, None)
47 # check bug attributes
48 self.assertEqual(bug.owner.preferredemail.email, 'foo@example.com')
49- self.assertEqual(bug.datecreated.isoformat(),
50- '2004-10-12T12:00:00+00:00')
51+ self.assertEqual(
52+ bug.datecreated.isoformat(), '2004-10-12T12:00:00+00:00')
53 self.assertEqual(bug.title, 'A test bug')
54 self.assertEqual(bug.description, 'A modified bug description')
55 self.assertEqual(bug.private, True)
56 self.assertEqual(bug.security_related, True)
57 self.assertEqual(bug.name, 'some-bug')
58- self.assertEqual(sorted(cve.sequence for cve in bug.cves),
59- ['2005-2730', '2005-2736', '2005-2737'])
60+ self.assertEqual(
61+ sorted(cve.sequence for cve in bug.cves),
62+ ['2005-2730', '2005-2736', '2005-2737'])
63 self.assertEqual(bug.tags, ['bar', 'foo'])
64 self.assertEqual(len(bug.getDirectSubscribers()), 2)
65- self.assertEqual(sorted(person.preferredemail.email
66- for person in bug.getDirectSubscribers()),
67- ['foo@example.com', 'test@canonical.com'])
68+ self.assertEqual(
69+ sorted(person.preferredemail.email for person in
70+ bug.getDirectSubscribers()),
71+ ['foo@example.com', 'test@canonical.com'])
72 # There are two bug watches
73 self.assertEqual(bug.watches.count(), 2)
74- self.assertEqual(sorted(watch.url for watch in bug.watches),
75- ['http://bugzilla.gnome.org/show_bug.cgi?id=43',
76- 'https://bugzilla.mozilla.org/show_bug.cgi?id=42'])
77+ self.assertEqual(
78+ sorted(watch.url for watch in bug.watches),
79+ ['http://bugzilla.gnome.org/show_bug.cgi?id=43',
80+ 'https://bugzilla.mozilla.org/show_bug.cgi?id=42'])
81
82 # There should only be one bug task (on netapplet):
83 self.assertEqual(len(bug.bugtasks), 1)
84 bugtask = bug.bugtasks[0]
85 self.assertEqual(bugtask.product, product)
86- self.assertEqual(bugtask.datecreated.isoformat(),
87- '2004-10-12T12:00:00+00:00')
88+ self.assertEqual(
89+ bugtask.datecreated.isoformat(), '2004-10-12T12:00:00+00:00')
90 self.assertEqual(bugtask.importance, BugTaskImportance.HIGH)
91 self.assertEqual(bugtask.status, BugTaskStatus.CONFIRMED)
92- self.assertEqual(bugtask.assignee.preferredemail.email,
93- 'bar@example.com')
94+ self.assertEqual(
95+ bugtask.assignee.preferredemail.email, 'bar@example.com')
96 self.assertNotEqual(bugtask.milestone, None)
97 self.assertEqual(bugtask.milestone.name, 'future')
98
99- # there are three comments:
100- self.assertEqual(bug.messages.count(), 3)
101+ # there are five comments:
102+ self.assertEqual(bug.messages.count(), 5)
103 message1 = bug.messages[0]
104 message2 = bug.messages[1]
105 message3 = bug.messages[2]
106+ message4 = bug.messages[3]
107+ message5 = bug.messages[4]
108
109 # Message 1:
110- self.assertEqual(message1.owner.preferredemail.email,
111- 'foo@example.com')
112- self.assertEqual(message1.datecreated.isoformat(),
113- '2004-10-12T12:00:00+00:00')
114+ self.assertEqual(
115+ message1.owner.preferredemail.email, 'foo@example.com')
116+ self.assertEqual(
117+ message1.datecreated.isoformat(), '2004-10-12T12:00:00+00:00')
118 self.assertEqual(message1.subject, 'A test bug')
119 self.assertEqual(message1.text_contents, 'Original description')
120 self.assertEqual(message1.bugattachments.count(), 1)
121@@ -545,19 +569,19 @@
122 self.assertEqual(attachment.libraryfile.mimetype, 'text/plain')
123
124 # Message 2:
125- self.assertEqual(message2.owner.preferredemail.email,
126- 'bug-importer@launchpad.net')
127- self.assertEqual(message2.datecreated.isoformat(),
128- '2005-01-01T11:00:00+00:00')
129+ self.assertEqual(
130+ message2.owner.preferredemail.email, 'bug-importer@launchpad.net')
131+ self.assertEqual(
132+ message2.datecreated.isoformat(), '2005-01-01T11:00:00+00:00')
133 self.assertEqual(message2.subject, 'Re: A test bug')
134- self.assertEqual(message2.text_contents,
135- 'A comment from an anonymous user')
136+ self.assertEqual(
137+ message2.text_contents, 'A comment from an anonymous user')
138
139 # Message 3:
140- self.assertEqual(message3.owner.preferredemail.email,
141- 'mark@example.com')
142- self.assertEqual(message3.datecreated.isoformat(),
143- '2005-01-01T13:00:00+00:00')
144+ self.assertEqual(
145+ message3.owner.preferredemail.email, 'mark@example.com')
146+ self.assertEqual(
147+ message3.datecreated.isoformat(), '2005-01-01T13:00:00+00:00')
148 self.assertEqual(message3.subject, 'Re: A test bug')
149 self.assertEqual(
150 message3.text_contents,
151@@ -581,6 +605,29 @@
152 # mime type forced to text/plain because we have a patch
153 self.assertEqual(attachment2.libraryfile.mimetype, 'text/plain')
154
155+ # Message 4:
156+ self.assertEqual(
157+ message4.owner.preferredemail.email, 'bug-importer@launchpad.net')
158+ self.assertEqual(
159+ message4.datecreated.isoformat(), '2005-01-01T14:00:00+00:00')
160+ self.assertEqual(message4.subject, 'Re: A test bug')
161+ self.assertEqual(message4.text_contents, '<empty comment>')
162+ self.assertEqual(message4.bugattachments.count(), 0)
163+
164+ # Message 5:
165+ self.assertEqual(
166+ message5.owner.preferredemail.email, 'bug-importer@launchpad.net')
167+ self.assertEqual(
168+ message5.datecreated.isoformat(), '2005-01-01T15:00:00+00:00')
169+ self.assertEqual(message5.subject, 'Re: A test bug')
170+ self.assertEqual(message5.text_contents, '')
171+ self.assertEqual(message5.bugattachments.count(), 1)
172+ attachment = message5.bugattachments[0]
173+ self.assertEqual(attachment.type, BugAttachmentType.UNSPECIFIED)
174+ self.assertEqual(attachment.title, 'Hello')
175+ self.assertEqual(attachment.libraryfile.filename, 'hello.txt')
176+ self.assertEqual(attachment.libraryfile.mimetype, 'text/plain')
177+
178 self.assertNoPendingNotifications(bug)
179
180 def test_duplicate_bug(self):
181
182=== modified file 'scripts/bug-import.py'
183--- scripts/bug-import.py 2010-11-08 12:52:43 +0000
184+++ scripts/bug-import.py 2010-12-16 17:06:41 +0000
185@@ -22,21 +22,22 @@
186 loglevel = logging.INFO
187
188 def add_my_options(self):
189- self.parser.add_option('-p', '--product', metavar='PRODUCT',
190- action='store',
191- help='Which product to export',
192- type='string', dest='product', default=None)
193- self.parser.add_option('--cache', metavar='FILE', action='store',
194- help='Cache for bug ID mapping',
195- type='string', dest='cache_filename',
196- default='bug-map.pickle')
197+ self.parser.add_option(
198+ '-p', '--product', metavar='PRODUCT', action='store',
199+ help='Which product to export', type='string', dest='product',
200+ default=None)
201+ self.parser.add_option(
202+ '--cache', metavar='FILE', action='store',
203+ help='Cache for bug ID mapping', type='string',
204+ dest='cache_filename', default='bug-map.pickle')
205 # XXX: jamesh 2007-04-11 bugs=86352
206 # Not verifying users created by a bug import can result in
207 # problems with mail notification, so should not be used for
208 # imports.
209- self.parser.add_option('--dont-verify-users', dest='verify_users',
210- help="Don't verify newly created users",
211- action='store_false', default=True)
212+ self.parser.add_option(
213+ '--dont-verify-users', dest='verify_users',
214+ help="Don't verify newly created users", action='store_false',
215+ default=True)
216
217 def main(self):
218 if self.options.product is None: