Merge lp:~gmb/launchpad/expose-level-bug-704685 into lp:launchpad

Proposed by Graham Binns
Status: Merged
Approved by: Данило Шеган
Approved revision: no longer in the source branch.
Merged at revision: 12272
Proposed branch: lp:~gmb/launchpad/expose-level-bug-704685
Merge into: lp:launchpad
Diff against target: 154 lines (+54/-8)
5 files modified
lib/canonical/launchpad/components/apihelpers.py (+15/-0)
lib/canonical/launchpad/interfaces/_schema_circular_imports.py (+5/-0)
lib/lp/bugs/interfaces/bug.py (+8/-1)
lib/lp/bugs/interfaces/bugsubscription.py (+9/-7)
lib/lp/bugs/stories/webservice/xx-bug.txt (+17/-0)
To merge this branch: bzr merge lp:~gmb/launchpad/expose-level-bug-704685
Reviewer Review Type Date Requested Status
Данило Шеган (community) code Approve
Review via email: mp+46829@code.launchpad.net

Description of the change

This branch exposes BugNotificationLevel via the WebService API. It also
exports the level parameter of IBug.subscribe() so that people can
subscribe at a given BugNotificationLevel.

== lib/canonical/launchpad/components/apihelpers.py ==

 - With Leonard's help I've added a helper to allow us to patch the
   vocabulary of a Choice param when exported via the API.

== lib/canonical/launchpad/interfaces/_schema_circular_imports.py ==

 - I've added some circular-import-avoidance code here. If it weren't
   for the CI problem I would have used copy_field to copy
   IBugSubscription['bug_notification_level'].

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

 - I've added the declaration of level as an operation parameter for
   IBug.subscribe().

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

 - I've exported IBugSubscription.bug_notification_level.

== lib/lp/bugs/stories/webservice/xx-bug.txt ==

 - I've updated the existing webservice tests to cover the new
   functionality.

To post a comment you must log in.
Revision history for this message
Данило Шеган (danilo) wrote :

Notes from the across-the-table discussion:
 – This is only for direct subscriptions, not for structural subscriptions.
 — There are no existing tests for any of the patch_* functions, so none are provided for this thing
 — When asked about any "negative" tests, Graham noticed himself that test for patching (editing) a BugSubscriptionLevel is missing, and promised to add it.

With that in mind, all good, and approved on the condition of adding a test.

review: Approve (code)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/canonical/launchpad/components/apihelpers.py'
2--- lib/canonical/launchpad/components/apihelpers.py 2010-04-22 04:34:39 +0000
3+++ lib/canonical/launchpad/components/apihelpers.py 2011-01-20 18:32:02 +0000
4@@ -16,6 +16,7 @@
5 __all__ = [
6 'patch_entry_return_type',
7 'patch_choice_parameter_type',
8+ 'patch_choice_vocabulary',
9 'patch_collection_property',
10 'patch_collection_return_type',
11 'patch_plain_parameter_type',
12@@ -111,3 +112,17 @@
13 :param collection_type: The `Collection` type.
14 """
15 exported_class[property_name].value_type.schema = collection_type
16+
17+
18+def patch_choice_vocabulary(exported_class, method_name, param_name,
19+ vocabulary):
20+ """Set the `Vocabulary` for a `Choice` parameter for a given method.
21+
22+ :param exported_class: The class containing the property.
23+ :param property_name: The name of the property whose type you need
24+ to patch.
25+ :param vocabulary: The `Vocabulary` type.
26+ """
27+ exported_class[method_name].queryTaggedValue(
28+ LAZR_WEBSERVICE_EXPORTED)[
29+ 'params'][param_name].vocabulary = vocabulary
30
31=== modified file 'lib/canonical/launchpad/interfaces/_schema_circular_imports.py'
32--- lib/canonical/launchpad/interfaces/_schema_circular_imports.py 2010-12-22 07:53:52 +0000
33+++ lib/canonical/launchpad/interfaces/_schema_circular_imports.py 2011-01-20 18:32:02 +0000
34@@ -20,6 +20,7 @@
35
36 from canonical.launchpad.components.apihelpers import (
37 patch_choice_parameter_type,
38+ patch_choice_vocabulary,
39 patch_collection_property,
40 patch_collection_return_type,
41 patch_entry_return_type,
42@@ -80,6 +81,7 @@
43 HWBus,
44 IHWSubmission,
45 )
46+from lp.registry.enum import BugNotificationLevel
47 from lp.registry.interfaces.distribution import IDistribution
48 from lp.registry.interfaces.distributionmirror import IDistributionMirror
49 from lp.registry.interfaces.distributionsourcepackage import (
50@@ -486,6 +488,9 @@
51 IBug, 'getNominationFor', 'target', IBugTarget)
52 patch_plain_parameter_type(
53 IBug, 'getNominations', 'target', IBugTarget)
54+patch_choice_vocabulary(
55+ IBug, 'subscribe', 'level', BugNotificationLevel)
56+
57
58 # IFrontPageBugAddForm
59 patch_reference_property(IFrontPageBugAddForm, 'bugtarget', IBugTarget)
60
61=== modified file 'lib/lp/bugs/interfaces/bug.py'
62--- lib/lp/bugs/interfaces/bug.py 2010-11-04 02:32:16 +0000
63+++ lib/lp/bugs/interfaces/bug.py 2011-01-20 18:32:02 +0000
64@@ -24,6 +24,7 @@
65
66 from textwrap import dedent
67
68+from lazr.enum import DBEnumeratedType
69 from lazr.lifecycle.snapshot import doNotSnapshot
70 from lazr.restful.declarations import (
71 call_with,
72@@ -435,7 +436,13 @@
73 # subscription-related methods
74
75 @operation_parameters(
76- person=Reference(IPerson, title=_('Person'), required=True))
77+ person=Reference(IPerson, title=_('Person'), required=True),
78+ # level actually uses BugNotificationLevel as its vocabulary,
79+ # but due to circular import problems we fix that in
80+ # _schema_circular_imports.py rather than here.
81+ level=Choice(
82+ vocabulary=DBEnumeratedType, required=False,
83+ title=_('Level')))
84 @call_with(subscribed_by=REQUEST_USER, suppress_notify=False)
85 @export_write_operation()
86 def subscribe(person, subscribed_by, suppress_notify=True, level=None):
87
88=== modified file 'lib/lp/bugs/interfaces/bugsubscription.py'
89--- lib/lp/bugs/interfaces/bugsubscription.py 2010-09-09 21:00:54 +0000
90+++ lib/lp/bugs/interfaces/bugsubscription.py 2011-01-20 18:32:02 +0000
91@@ -48,13 +48,15 @@
92 bug = exported(Reference(
93 IBug, title=_("Bug"), required=True, readonly=True))
94 bugID = Int(title=u"The bug id.", readonly=True)
95- bug_notification_level = Choice(
96- title=_("Bug notification level"), required=True,
97- vocabulary=BugNotificationLevel,
98- default=BugNotificationLevel.COMMENTS,
99- description=_(
100- "The volume and type of bug notifications "
101- "this subscription will generate."))
102+ bug_notification_level = exported(
103+ Choice(
104+ title=_("Bug notification level"), required=True,
105+ vocabulary=BugNotificationLevel,
106+ default=BugNotificationLevel.COMMENTS,
107+ description=_(
108+ "The volume and type of bug notifications "
109+ "this subscription will generate.")),
110+ readonly=True)
111 date_created = exported(
112 Datetime(title=_('Date subscribed'), required=True, readonly=True))
113 subscribed_by = exported(PersonChoice(
114
115=== modified file 'lib/lp/bugs/stories/webservice/xx-bug.txt'
116--- lib/lp/bugs/stories/webservice/xx-bug.txt 2011-01-17 21:51:09 +0000
117+++ lib/lp/bugs/stories/webservice/xx-bug.txt 2011-01-20 18:32:02 +0000
118@@ -825,6 +825,7 @@
119 ... pprint_entry(entry)
120 ... print
121 bug_link: u'http://.../bugs/1'
122+ bug_notification_level: u'Discussion'
123 date_created: u'2006-10-16T18:31:43.156104+00:00'
124 person_link: u'http://.../~name12'
125 resource_type_link: u'http://.../#bug_subscription'
126@@ -844,6 +845,7 @@
127 ... subscription_entries[1]['self_link']).jsonBody()
128 >>> pprint_entry(subscription)
129 bug_link: u'http://.../bugs/1'
130+ bug_notification_level: u'Discussion'
131 date_created: u'2006-10-16T18:31:43.154816+00:00'
132 person_link: u'http://.../~stevea'
133 resource_type_link: u'http://.../#bug_subscription'
134@@ -874,6 +876,21 @@
135 ... bug_one['self_link'], 'unsubscribe')
136 HTTP/1.1 200 Ok...
137
138+An individual can subscribe themself at a given BugNotificationLevel.
139+
140+ >>> new_subscription = webservice.named_post(
141+ ... bug_one['self_link'], 'subscribe',
142+ ... person=webservice.getAbsoluteUrl('/~cprov'),
143+ ... level=u"Details").jsonBody()
144+ >>> pprint_entry(new_subscription)
145+ bug_link: u'.../bugs/1'
146+ bug_notification_level: u'Discussion'
147+ date_created: u'...'
148+ person_link: u'...'
149+ resource_type_link: u'...'
150+ self_link: u'...'
151+ subscribed_by_link: u'...'
152+
153 If one person tries to unsubscribe another individual, the web
154 service will return an unauthorized error.
155