1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
|
# Copyright 2009-2011 Canonical Ltd. This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).
# pylint: disable-msg=E0211,E0213
"""Interfaces related to bug nomination."""
__metaclass__ = type
__all__ = [
'BugNominationStatusError',
'NominationError',
'IBugNomination',
'IBugNominationForm',
'IBugNominationSet',
'BugNominationStatus',
'NominationSeriesObsoleteError']
import httplib
from lazr.enum import (
DBEnumeratedType,
DBItem,
)
from lazr.restful.declarations import (
call_with,
error_status,
export_as_webservice_entry,
export_read_operation,
export_write_operation,
exported,
REQUEST_USER,
)
from lazr.restful.fields import (
Reference,
ReferenceChoice,
)
from zope.interface import (
Attribute,
Interface,
)
from zope.schema import (
Choice,
Datetime,
Int,
Set,
)
from canonical.launchpad import _
from lp.app.interfaces.launchpad import IHasDateCreated
from lp.app.validators.validation import can_be_nominated_for_series
from lp.bugs.interfaces.bug import IBug
from lp.bugs.interfaces.hasbug import IHasBug
from lp.bugs.interfaces.bugtarget import IBugTarget
from lp.registry.interfaces.distroseries import IDistroSeries
from lp.registry.interfaces.productseries import IProductSeries
from lp.registry.interfaces.role import IHasOwner
from lp.services.fields import PublicPersonChoice
@error_status(httplib.BAD_REQUEST)
class NominationError(Exception):
"""The bug cannot be nominated for this release."""
@error_status(httplib.BAD_REQUEST)
class NominationSeriesObsoleteError(Exception):
"""A bug cannot be nominated for an obsolete series."""
@error_status(httplib.BAD_REQUEST)
class BugNominationStatusError(Exception):
"""A error occurred while trying to set a bug nomination status."""
class BugNominationStatus(DBEnumeratedType):
"""Bug Nomination Status.
The status of the decision to fix a bug in a specific release.
"""
PROPOSED = DBItem(10, """
Nominated
This nomination hasn't yet been reviewed, or is still under
review.
""")
APPROVED = DBItem(20, """
Approved
The release management team has approved fixing the bug for this
release.
""")
DECLINED = DBItem(30, """
Declined
The release management team has declined fixing the bug for this
release.
""")
class IBugNomination(IHasBug, IHasOwner, IHasDateCreated):
"""A nomination for a bug to be fixed in a specific series.
A nomination can apply to an IDistroSeries or an IProductSeries.
"""
export_as_webservice_entry(publish_web_link=False)
# We want to customize the titles and descriptions of some of the
# attributes of our parent interfaces, so we redefine those specific
# attributes below.
id = Int(title=_("Bug Nomination #"))
bug = exported(Reference(schema=IBug, readonly=True))
date_created = exported(Datetime(
title=_("Date Submitted"),
description=_("The date on which this nomination was submitted."),
required=True, readonly=True))
date_decided = exported(Datetime(
title=_("Date Decided"),
description=_(
"The date on which this nomination was approved or declined."),
required=False, readonly=True))
distroseries = exported(ReferenceChoice(
title=_("Series"), required=False, readonly=True,
vocabulary="DistroSeries", schema=IDistroSeries))
productseries = exported(ReferenceChoice(
title=_("Series"), required=False, readonly=True,
vocabulary="ProductSeries", schema=IProductSeries))
owner = exported(PublicPersonChoice(
title=_('Submitter'), required=True, readonly=True,
vocabulary='ValidPersonOrTeam'))
ownerID = Attribute('The db id of the owner.')
decider = exported(PublicPersonChoice(
title=_('Decided By'), required=False, readonly=True,
vocabulary='ValidPersonOrTeam'))
target = exported(Reference(
schema=IBugTarget,
title=_("The IProductSeries or IDistroSeries of this nomination.")))
status = exported(Choice(
title=_("Status"), vocabulary=BugNominationStatus,
default=BugNominationStatus.PROPOSED, readonly=True))
@call_with(approver=REQUEST_USER)
@export_write_operation()
def approve(approver):
"""Approve this bug for fixing in a series.
:approver: The IPerson that approves this nomination and that
will own the created bugtasks.
The status is set to APPROVED and the appropriate IBugTask(s)
are created for the nomination target.
A nomination in any state can be approved. If the nomination is
/already/ approved, this method is a noop.
"""
@call_with(decliner=REQUEST_USER)
@export_write_operation()
def decline(decliner):
"""Decline this bug for fixing in a series.
:decliner: The IPerson that declines this nomination.
The status is set to DECLINED.
If called on a nomination that is in APPROVED state, a
BugNominationStatusError is raised. If the nomination was
already DECLINED, this method is a noop.
"""
# Helper methods for making status checking more readable.
def isProposed():
"""Is this nomination in Proposed state?"""
def isDeclined():
"""Is this nomination in Declined state?"""
def isApproved():
"""Is this nomination in Approved state?"""
@call_with(person=REQUEST_USER)
@export_read_operation()
def canApprove(person):
"""Is this person allowed to approve the nomination?"""
class IBugNominationSet(Interface):
"""The set of IBugNominations."""
def get(id):
"""Get a nomination by its ID.
Returns an IBugNomination. Raises a NotFoundError is the
nomination was not found.
"""
class IBugNominationForm(Interface):
"""The browser form for nominating bugs for series."""
nominatable_series = Set(
title=_("Series that can be nominated"), required=True,
value_type=Choice(vocabulary="BugNominatableSeries"),
constraint=can_be_nominated_for_series)
|