Merge lp:~michael.nelson/launchpad/distro-series-difference-message into lp:launchpad/db-devel

Proposed by Michael Nelson
Status: Merged
Approved by: Michael Nelson
Approved revision: no longer in the source branch.
Merged at revision: 9726
Proposed branch: lp:~michael.nelson/launchpad/distro-series-difference-message
Merge into: lp:launchpad/db-devel
Prerequisite: lp:~michael.nelson/launchpad/distro-series-difference-basic-model
Diff against target: 379 lines (+255/-4)
8 files modified
lib/lp/registry/configure.zcml (+12/-0)
lib/lp/registry/interfaces/distroseriesdifference.py (+8/-1)
lib/lp/registry/interfaces/distroseriesdifferencecomment.py (+57/-0)
lib/lp/registry/model/distroseriesdifference.py (+22/-1)
lib/lp/registry/model/distroseriesdifferencecomment.py (+67/-0)
lib/lp/registry/tests/test_distroseriesdifference.py (+29/-2)
lib/lp/registry/tests/test_distroseriesdifferencecomment.py (+44/-0)
lib/lp/testing/factory.py (+16/-0)
To merge this branch: bzr merge lp:~michael.nelson/launchpad/distro-series-difference-message
Reviewer Review Type Date Requested Status
Brad Crittenden (community) code Approve
Launchpad code reviewers Pending
Review via email: mp+33929@code.launchpad.net

Commit message

Add DistroSeriesDifferenceComment model.

Description of the change

Overview
========
Hi Brad or other reviewer :)

This branch adds the comment model for DistroSeriesDifferences, and then adds a IDistroSeriesDifference.addComment().

This is part of the work for:

https://dev.launchpad.net/LEP/DerivativeDistributions

To test:
bin/test -vv -m lp.registry.tests.test_distroseriesdifferencecomment -m lp.registry.tests.test_distroseriesdifference

No lint.

To post a comment you must log in.
Revision history for this message
Brad Crittenden (bac) wrote :

Hi Michael,

Thanks for this addition.

I think this would read better if the actual were on a line by itself.

279 + self.assertEqual(
280 + "Difference between distroseries 'Lucid' and 'Derilucid' "
281 + "for package 'foonew' (1.0/0.9)", ds_diff.title)

Otherwise it looks great.

review: Approve (code)
Revision history for this message
Michael Nelson (michael.nelson) wrote :

On Fri, Aug 27, 2010 at 7:31 PM, Brad Crittenden <email address hidden> wrote:
> Review: Approve code
> Hi Michael,
>
> Thanks for this addition.
>
> I think this would read better if the actual were on a line by itself.
>
> 279     +        self.assertEqual(
> 280     +            "Difference between distroseries 'Lucid' and 'Derilucid' "
> 281     +            "for package 'foonew' (1.0/0.9)", ds_diff.title)

Done, thanks Brad.

>
> Otherwise it looks great.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/lp/registry/configure.zcml'
2--- lib/lp/registry/configure.zcml 2010-08-31 08:57:45 +0000
3+++ lib/lp/registry/configure.zcml 2010-08-31 08:57:46 +0000
4@@ -113,6 +113,18 @@
5 class="lp.registry.model.distroseriesdifference.DistroSeriesDifference">
6 <allow interface="lp.registry.interfaces.distroseriesdifference.IDistroSeriesDifference"/>
7 </class>
8+
9+ <!-- DistroSeriesDifferenceComment -->
10+ <securedutility
11+ component="lp.registry.model.distroseriesdifferencecomment.DistroSeriesDifferenceComment"
12+ provides="lp.registry.interfaces.distroseriesdifferencecomment.IDistroSeriesDifferenceCommentSource">
13+ <allow interface="lp.registry.interfaces.distroseriesdifferencecomment.IDistroSeriesDifferenceCommentSource"/>
14+ </securedutility>
15+ <class
16+ class="lp.registry.model.distroseriesdifferencecomment.DistroSeriesDifferenceComment">
17+ <allow interface="lp.registry.interfaces.distroseriesdifferencecomment.IDistroSeriesDifferenceComment"/>
18+ </class>
19+
20 <class
21 class="lp.registry.model.distroseries.DistroSeries">
22 <allow
23
24=== modified file 'lib/lp/registry/interfaces/distroseriesdifference.py'
25--- lib/lp/registry/interfaces/distroseriesdifference.py 2010-08-31 08:57:45 +0000
26+++ lib/lp/registry/interfaces/distroseriesdifference.py 2010-08-31 08:57:46 +0000
27@@ -17,6 +17,7 @@
28 Choice,
29 Int,
30 Text,
31+ TextLine,
32 )
33
34 from canonical.launchpad import _
35@@ -81,6 +82,13 @@
36 description=_(
37 "The most recent published version in the parent series."))
38
39+ title = TextLine(
40+ title=_("Title"), readonly=True, required=False, description=_(
41+ "A human-readable name describing this difference."))
42+
43+ def addComment(owner, comment):
44+ """Add a comment on this difference."""
45+
46
47 class IDistroSeriesDifferenceSource(Interface):
48 """A utility of this interface can be used to create differences."""
49@@ -105,4 +113,3 @@
50 is not a derived series.
51 :return: A new `DistroSeriesDifference` object.
52 """
53-
54
55=== added file 'lib/lp/registry/interfaces/distroseriesdifferencecomment.py'
56--- lib/lp/registry/interfaces/distroseriesdifferencecomment.py 1970-01-01 00:00:00 +0000
57+++ lib/lp/registry/interfaces/distroseriesdifferencecomment.py 2010-08-31 08:57:46 +0000
58@@ -0,0 +1,57 @@
59+# Copyright 2010 Canonical Ltd. This software is licensed under the
60+# GNU Affero General Public License version 3 (see the file LICENSE).
61+
62+"""Distribution series difference messages."""
63+
64+__metaclass__ = type
65+__all__ = [
66+ 'IDistroSeriesDifferenceComment',
67+ 'IDistroSeriesDifferenceCommentSource',
68+ ]
69+
70+
71+from lazr.restful.fields import Reference
72+from zope.interface import Interface
73+from zope.schema import (
74+ Int,
75+ Text,
76+ )
77+
78+from canonical.launchpad import _
79+from canonical.launchpad.interfaces.message import IMessage
80+from lp.registry.interfaces.distroseriesdifference import (
81+ IDistroSeriesDifference,
82+ )
83+
84+
85+class IDistroSeriesDifferenceComment(Interface):
86+ """A comment for a distroseries difference record."""
87+
88+ id = Int(title=_('ID'), required=True, readonly=True)
89+
90+ distro_series_difference = Reference(
91+ IDistroSeriesDifference, title=_("Distro series difference"),
92+ required=True, readonly=True, description=_(
93+ "The distro series difference to which this message "
94+ "belongs."))
95+ message = Reference(
96+ IMessage, title=_("Message"), required=True, readonly=True,
97+ description=_("A comment about this difference."))
98+
99+ comment = Text(
100+ title=_("Comment text"), readonly=True, description=_(
101+ "The comment text for the related distro series difference."))
102+
103+
104+class IDistroSeriesDifferenceCommentSource(Interface):
105+ """A utility of this interface can be used to create comments."""
106+
107+ def new(distro_series_difference, owner, comment):
108+ """Create a new comment on a distro series difference.
109+
110+ :param distro_series_difference: The distribution series difference
111+ that is being commented on.
112+ :param owner: The person making the comment.
113+ :param comment: The comment.
114+ :return: A new `DistroSeriesDifferenceComment` object.
115+ """
116
117=== modified file 'lib/lp/registry/model/distroseriesdifference.py'
118--- lib/lp/registry/model/distroseriesdifference.py 2010-08-31 08:57:45 +0000
119+++ lib/lp/registry/model/distroseriesdifference.py 2010-08-31 08:57:46 +0000
120@@ -14,8 +14,8 @@
121 Int,
122 Reference,
123 Storm,
124- Unicode,
125 )
126+from zope.component import getUtility
127 from zope.interface import (
128 classProvides,
129 implements,
130@@ -32,6 +32,9 @@
131 IDistroSeriesDifference,
132 IDistroSeriesDifferenceSource,
133 )
134+from lp.registry.interfaces.distroseriesdifferencecomment import (
135+ IDistroSeriesDifferenceCommentSource,
136+ )
137
138
139 class DistroSeriesDifference(Storm):
140@@ -88,6 +91,19 @@
141 return self._getLatestSourcePub(for_parent=True)
142
143 @property
144+ def title(self):
145+ """See `IDistroSeriesDifference`."""
146+ parent_name = self.derived_series.parent_series.displayname
147+ return ("Difference between distroseries '%(parent_name)s' and "
148+ "'%(derived_name)s' for package '%(pkg_name)s' "
149+ "(%(versions)s)" % {
150+ 'parent_name': parent_name,
151+ 'derived_name': self.derived_series.displayname,
152+ 'pkg_name': self.source_package_name.name,
153+ 'versions': self._getVersions(),
154+ })
155+
156+ @property
157 def activity_log(self):
158 """See `IDistroSeriesDifference`."""
159 return u""
160@@ -115,3 +131,8 @@
161 if self.parent_source_pub is not None:
162 parent_src_pub_ver = self.parent_source_pub.source_package_version
163 return parent_src_pub_ver + "/" + src_pub_ver
164+
165+ def addComment(self, owner, comment):
166+ """See `IDistroSeriesDifference`."""
167+ return getUtility(IDistroSeriesDifferenceCommentSource).new(
168+ self, owner, comment)
169
170=== added file 'lib/lp/registry/model/distroseriesdifferencecomment.py'
171--- lib/lp/registry/model/distroseriesdifferencecomment.py 1970-01-01 00:00:00 +0000
172+++ lib/lp/registry/model/distroseriesdifferencecomment.py 2010-08-31 08:57:46 +0000
173@@ -0,0 +1,67 @@
174+# Copyright 2010 Canonical Ltd. This software is licensed under the
175+# GNU Affero General Public License version 3 (see the file LICENSE).
176+
177+"""A comment/message for a difference between two distribution series."""
178+
179+__metaclass__ = type
180+
181+__all__ = [
182+ 'DistroSeriesDifferenceComment',
183+ ]
184+
185+from email.Utils import make_msgid
186+
187+from storm.locals import (
188+ Int,
189+ Reference,
190+ Storm,
191+ )
192+from zope.interface import (
193+ classProvides,
194+ implements,
195+ )
196+
197+from canonical.launchpad.database.message import Message, MessageChunk
198+from canonical.launchpad.interfaces.lpstorm import IMasterStore
199+from lp.registry.interfaces.distroseriesdifferencecomment import (
200+ IDistroSeriesDifferenceComment,
201+ IDistroSeriesDifferenceCommentSource,
202+ )
203+
204+
205+class DistroSeriesDifferenceComment(Storm):
206+ """See `IDistroSeriesDifferenceComment`."""
207+ implements(IDistroSeriesDifferenceComment)
208+ classProvides(IDistroSeriesDifferenceCommentSource)
209+ __storm_table__ = 'DistroSeriesDifferenceMessage'
210+
211+ id = Int(primary=True)
212+
213+ distro_series_difference_id = Int(name='distro_series_difference',
214+ allow_none=False)
215+ distro_series_difference = Reference(
216+ distro_series_difference_id, 'DistroSeriesDifference.id')
217+
218+ message_id = Int(name="message", allow_none=False)
219+ message = Reference(message_id, 'Message.id')
220+
221+ @property
222+ def comment(self):
223+ """See `IDistroSeriesDifferenceComment`."""
224+ return self.message.text_contents
225+
226+ @staticmethod
227+ def new(distro_series_difference, owner, comment):
228+ """See `IDistroSeriesDifferenceCommentSource`."""
229+ msgid = make_msgid('distroseriesdifference')
230+ message = Message(
231+ parent=None, owner=owner, rfc822msgid=msgid,
232+ subject=distro_series_difference.title)
233+ MessageChunk(message=message, content=comment, sequence=1)
234+
235+ store = IMasterStore(DistroSeriesDifferenceComment)
236+ dsd_comment = DistroSeriesDifferenceComment()
237+ dsd_comment.distro_series_difference = distro_series_difference
238+ dsd_comment.message = message
239+
240+ return store.add(dsd_comment)
241
242=== modified file 'lib/lp/registry/tests/test_distroseriesdifference.py'
243--- lib/lp/registry/tests/test_distroseriesdifference.py 2010-08-31 08:57:45 +0000
244+++ lib/lp/registry/tests/test_distroseriesdifference.py 2010-08-31 08:57:46 +0000
245@@ -51,7 +51,7 @@
246 self.assertRaises(
247 NotADerivedSeriesError, distroseriesdifference_factory.new,
248 distro_series, source_package_name,
249- DistroSeriesDifferenceType.UNIQUE_TO_DERIVED_SERIES
250+ DistroSeriesDifferenceType.UNIQUE_TO_DERIVED_SERIES,
251 )
252
253 def test_source_pub(self):
254@@ -94,7 +94,7 @@
255 ds_diff.derived_series.parent_series,
256 ds_diff.parent_source_pub.distroseries)
257
258- def test_paren_source_pub_gets_latest_pending(self):
259+ def test_parent_source_pub_gets_latest_pending(self):
260 # The most recent publication is always returned, even if its pending.
261 ds_diff = self.factory.makeDistroSeriesDifference(
262 source_package_name_str="foonew")
263@@ -105,6 +105,33 @@
264
265 self.assertEqual(pending_pub, ds_diff.parent_source_pub)
266
267+ def test_title(self):
268+ # The title is a friendly description of the difference.
269+ parent_series = self.factory.makeDistroSeries(name="lucid")
270+ derived_series = self.factory.makeDistroSeries(
271+ parent_series=parent_series, name="derilucid")
272+ ds_diff = self.factory.makeDistroSeriesDifference(
273+ source_package_name_str="foonew", derived_series=derived_series,
274+ versions={
275+ 'parent': '1.0',
276+ 'derived': '0.9',
277+ })
278+
279+ self.assertEqual(
280+ "Difference between distroseries 'Lucid' and 'Derilucid' "
281+ "for package 'foonew' (1.0/0.9)",
282+ ds_diff.title)
283+
284+ def test_addComment(self):
285+ # Adding a comment creates a new DistroSeriesDifferenceComment
286+ ds_diff = self.factory.makeDistroSeriesDifference(
287+ source_package_name_str="foonew")
288+ person = self.factory.makePerson()
289+
290+ dsd_comment = ds_diff.addComment(person, "Wait until version 2.1")
291+
292+ self.assertEqual(ds_diff, dsd_comment.distro_series_difference)
293+
294
295 def test_suite():
296 return unittest.TestLoader().loadTestsFromName(__name__)
297
298=== added file 'lib/lp/registry/tests/test_distroseriesdifferencecomment.py'
299--- lib/lp/registry/tests/test_distroseriesdifferencecomment.py 1970-01-01 00:00:00 +0000
300+++ lib/lp/registry/tests/test_distroseriesdifferencecomment.py 2010-08-31 08:57:46 +0000
301@@ -0,0 +1,44 @@
302+# Copyright 2010 Canonical Ltd. This software is licensed under the
303+# GNU Affero General Public License version 3 (see the file LICENSE).
304+
305+"""Model tests for the DistroSeriesDifferenceComment class."""
306+
307+__metaclass__ = type
308+
309+from storm.store import Store
310+
311+from canonical.launchpad.webapp.testing import verifyObject
312+from canonical.testing import DatabaseFunctionalLayer
313+from lp.registry.interfaces.distroseriesdifferencecomment import (
314+ IDistroSeriesDifferenceComment,
315+ )
316+from lp.testing import TestCaseWithFactory
317+
318+
319+class DistroSeriesDifferenceCommentTestCase(TestCaseWithFactory):
320+
321+ layer = DatabaseFunctionalLayer
322+
323+ def test_implements_interface(self):
324+ # The implementation implements the interface correctly.
325+ dsd_comment = self.factory.makeDistroSeriesDifferenceComment()
326+ # Flush the store to ensure db constraints are triggered.
327+ Store.of(dsd_comment).flush()
328+
329+ verifyObject(IDistroSeriesDifferenceComment, dsd_comment)
330+
331+ def test_comment(self):
332+ # The comment attribute returns the text of the comment.
333+ dsd_comment = self.factory.makeDistroSeriesDifferenceComment(
334+ comment="Wait until version 2.3")
335+
336+ self.assertEqual("Wait until version 2.3", dsd_comment.comment)
337+
338+ def test_subject(self):
339+ # The subject of the message is set from the distro series diff
340+ # title.
341+ dsd_comment = self.factory.makeDistroSeriesDifferenceComment()
342+
343+ self.assertEqual(
344+ dsd_comment.distro_series_difference.title,
345+ dsd_comment.message.subject)
346
347=== modified file 'lib/lp/testing/factory.py'
348--- lib/lp/testing/factory.py 2010-08-31 08:57:45 +0000
349+++ lib/lp/testing/factory.py 2010-08-31 08:57:46 +0000
350@@ -164,6 +164,9 @@
351 from lp.registry.interfaces.distroseriesdifference import (
352 IDistroSeriesDifferenceSource,
353 )
354+from lp.registry.interfaces.distroseriesdifferencecomment import (
355+ IDistroSeriesDifferenceCommentSource,
356+ )
357 from lp.registry.interfaces.gpg import (
358 GPGKeyAlgorithm,
359 IGPGKeySet,
360@@ -1859,6 +1862,19 @@
361 return getUtility(IDistroSeriesDifferenceSource).new(
362 derived_series, source_package_name, difference_type)
363
364+ def makeDistroSeriesDifferenceComment(
365+ self, distro_series_difference=None, owner=None, comment=None):
366+ """Create a new distro series difference comment."""
367+ if distro_series_difference is None:
368+ distro_series_difference = self.makeDistroSeriesDifference()
369+ if owner is None:
370+ owner = self.makePerson()
371+ if comment is None:
372+ comment = self.getUniqueString('dsdcomment')
373+
374+ return getUtility(IDistroSeriesDifferenceCommentSource).new(
375+ distro_series_difference, owner, comment)
376+
377 def makeDistroArchSeries(self, distroseries=None,
378 architecturetag=None, processorfamily=None,
379 official=True, owner=None,

Subscribers

People subscribed via source and target branches

to status/vote changes: