7675.916.98
by Henning Eggers
Merged db-stable at r10026 (recife roll-back) but without accepting the changes. |
1 |
# Copyright 2009-2010 Canonical Ltd. This software is licensed under the
|
8687.15.14
by Karl Fogel
Add the copyright header block to files under lib/lp/blueprints/. |
2 |
# GNU Affero General Public License version 3 (see the file LICENSE).
|
3 |
||
4983.1.2
by Curtis Hovey
Added pylint exceptions to database classes. |
4 |
# pylint: disable-msg=E0611,W0212
|
2344
by Canonical.com Patch Queue Manager
[not r=kiko] specification tracker |
5 |
|
6 |
__metaclass__ = type |
|
3847.2.25
by Mark Shuttleworth
Test fixes and object interface compliance |
7 |
__all__ = [ |
8 |
'HasSpecificationsMixin', |
|
12579.2.6
by Tim Penhey
Move to module functions. |
9 |
'recursive_blocked_query', |
10 |
'recursive_dependent_query', |
|
3847.2.25
by Mark Shuttleworth
Test fixes and object interface compliance |
11 |
'Specification', |
12 |
'SpecificationSet', |
|
13 |
]
|
|
2344
by Canonical.com Patch Queue Manager
[not r=kiko] specification tracker |
14 |
|
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
15 |
from lazr.lifecycle.event import ( |
16 |
ObjectCreatedEvent, |
|
17 |
ObjectModifiedEvent, |
|
18 |
)
|
|
19 |
from lazr.lifecycle.objectdelta import ObjectDelta |
|
20 |
from sqlobject import ( |
|
21 |
BoolCol, |
|
22 |
ForeignKey, |
|
23 |
IntCol, |
|
24 |
SQLMultipleJoin, |
|
25 |
SQLRelatedJoin, |
|
26 |
StringCol, |
|
27 |
)
|
|
11474.3.1
by Robert Collins
Precache the is_person_valid status for specification assignments on Product and Distribution. |
28 |
from storm.locals import ( |
29 |
Desc, |
|
30 |
SQL, |
|
31 |
)
|
|
5821.16.5
by Francis J. Lacoste
Use Storm execute instead of cursor(). |
32 |
from storm.store import Store |
12588.3.4
by Tim Penhey
Define the filter_bugtasks_by_context interface. |
33 |
from zope.component import getUtility |
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
34 |
from zope.event import notify |
2344
by Canonical.com Patch Queue Manager
[not r=kiko] specification tracker |
35 |
from zope.interface import implements |
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
36 |
|
37 |
from canonical.database.constants import ( |
|
38 |
DEFAULT, |
|
39 |
UTC_NOW, |
|
40 |
)
|
|
2344
by Canonical.com Patch Queue Manager
[not r=kiko] specification tracker |
41 |
from canonical.database.datetimecol import UtcDateTimeCol |
3691.373.5
by Christian Reis
Move DBSchema and Item into webapp.enum, and put EnumCol into canonical.database.enumcol |
42 |
from canonical.database.enumcol import EnumCol |
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
43 |
from canonical.database.sqlbase import ( |
44 |
cursor, |
|
45 |
quote, |
|
46 |
SQLBase, |
|
47 |
sqlvalues, |
|
48 |
)
|
|
11474.3.1
by Robert Collins
Precache the is_person_valid status for specification assignments on Product and Distribution. |
49 |
from canonical.launchpad.components.decoratedresultset import ( |
50 |
DecoratedResultSet, |
|
51 |
)
|
|
3691.373.5
by Christian Reis
Move DBSchema and Item into webapp.enum, and put EnumCol into canonical.database.enumcol |
52 |
from canonical.launchpad.helpers import ( |
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
53 |
get_contact_email_addresses, |
54 |
)
|
|
13161.2.2
by Ian Booth
Add canBeUnsubscribedByUser and tests |
55 |
from lp.app.errors import UserCannotUnsubscribePerson |
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
56 |
from lp.blueprints.adapters import SpecificationDelta |
11824.1.2
by Tim Penhey
Fix imports for SpecificationDefinitionStatus. |
57 |
from lp.blueprints.enums import ( |
12498.3.2
by Curtis Hovey
Added NewSpecificationDefinitionStatus to define the set of enums that a new |
58 |
NewSpecificationDefinitionStatus, |
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
59 |
SpecificationDefinitionStatus, |
60 |
SpecificationFilter, |
|
61 |
SpecificationGoalStatus, |
|
62 |
SpecificationImplementationStatus, |
|
63 |
SpecificationLifecycleStatus, |
|
64 |
SpecificationPriority, |
|
65 |
SpecificationSort, |
|
66 |
)
|
|
11962.3.1
by Guilherme Salgado
merge james' safe-blueprints-model branch and solve conflicts |
67 |
from lp.blueprints.errors import TargetAlreadyHasSpecification |
11824.1.2
by Tim Penhey
Fix imports for SpecificationDefinitionStatus. |
68 |
from lp.blueprints.interfaces.specification import ( |
69 |
ISpecification, |
|
70 |
ISpecificationSet, |
|
71 |
)
|
|
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
72 |
from lp.blueprints.model.specificationbranch import SpecificationBranch |
73 |
from lp.blueprints.model.specificationbug import SpecificationBug |
|
8376.1.1
by Curtis Hovey
Migrated blueprint code to lp.blueprints. Resolved several circular import issues. Fixed specgraph 06-dependancies and 14-non-ascii-imagemap tests that fail on Jauny, but are fine on Hardy. |
74 |
from lp.blueprints.model.specificationdependency import ( |
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
75 |
SpecificationDependency, |
76 |
)
|
|
77 |
from lp.blueprints.model.specificationfeedback import SpecificationFeedback |
|
8376.1.1
by Curtis Hovey
Migrated blueprint code to lp.blueprints. Resolved several circular import issues. Fixed specgraph 06-dependancies and 14-non-ascii-imagemap tests that fail on Jauny, but are fine on Hardy. |
78 |
from lp.blueprints.model.specificationsubscription import ( |
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
79 |
SpecificationSubscription, |
80 |
)
|
|
81 |
from lp.bugs.interfaces.buglink import IBugLinkTarget |
|
12588.3.4
by Tim Penhey
Define the filter_bugtasks_by_context interface. |
82 |
from lp.bugs.interfaces.bugtask import ( |
83 |
BugTaskSearchParams, |
|
84 |
IBugTaskSet, |
|
85 |
)
|
|
12588.3.6
by Tim Penhey
Move the filter function to its own module to avoid circular dependencies. |
86 |
from lp.bugs.interfaces.bugtaskfilter import filter_bugtasks_by_context |
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
87 |
from lp.bugs.model.buglinktarget import BugLinkTargetMixin |
11962.3.3
by Guilherme Salgado
Create a new setTarget method on ISpecification, use it in retarget() and protect both with launchpad.Edit. Also started splitting ISpecification into several interfaces to make it easyer to protect them with different permissions |
88 |
from lp.registry.interfaces.distribution import IDistribution |
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
89 |
from lp.registry.interfaces.distroseries import IDistroSeries |
90 |
from lp.registry.interfaces.person import validate_public_person |
|
91 |
from lp.registry.interfaces.productseries import IProductSeries |
|
11962.3.3
by Guilherme Salgado
Create a new setTarget method on ISpecification, use it in retarget() and protect both with launchpad.Edit. Also started splitting ISpecification into several interfaces to make it easyer to protect them with different permissions |
92 |
from lp.registry.interfaces.product import IProduct |
13161.2.2
by Ian Booth
Add canBeUnsubscribedByUser and tests |
93 |
from lp.services.propertycache import ( |
94 |
cachedproperty, |
|
95 |
get_property_cache, |
|
96 |
)
|
|
13147.2.6
by Nigel Babu
There's already abstraction for this. |
97 |
|
2736.1.22
by Mark Shuttleworth
karma categories in the db, and karma for specs |
98 |
|
2344
by Canonical.com Patch Queue Manager
[not r=kiko] specification tracker |
99 |
|
12579.2.6
by Tim Penhey
Move to module functions. |
100 |
def recursive_blocked_query(spec): |
101 |
return """ |
|
102 |
RECURSIVE blocked(id) AS (
|
|
103 |
SELECT %s |
|
104 |
UNION
|
|
12579.2.8
by Tim Penhey
Tidy up the query, add the id to the repr, and sort the results. |
105 |
SELECT sd.specification
|
106 |
FROM specificationdependency sd, blocked b
|
|
12579.2.6
by Tim Penhey
Move to module functions. |
107 |
WHERE sd.dependency = b.id
|
108 |
)""" % spec.id |
|
109 |
||
110 |
||
111 |
def recursive_dependent_query(spec): |
|
112 |
return """ |
|
113 |
RECURSIVE dependencies(id) AS (
|
|
114 |
SELECT %s |
|
115 |
UNION
|
|
12579.2.8
by Tim Penhey
Tidy up the query, add the id to the repr, and sort the results. |
116 |
SELECT sd.dependency
|
117 |
FROM specificationdependency sd, dependencies d
|
|
12579.2.6
by Tim Penhey
Move to module functions. |
118 |
WHERE sd.specification = d.id
|
119 |
)""" % spec.id |
|
120 |
||
121 |
||
3691.109.23
by Francis J. Lacoste
* Define a BugLinkTargetMixin for base implementation of linkBug and unlinkBug. |
122 |
class Specification(SQLBase, BugLinkTargetMixin): |
2344
by Canonical.com Patch Queue Manager
[not r=kiko] specification tracker |
123 |
"""See ISpecification."""
|
124 |
||
3691.109.19
by Francis J. Lacoste
Make Specification implement IBugLinkTarget |
125 |
implements(ISpecification, IBugLinkTarget) |
2344
by Canonical.com Patch Queue Manager
[not r=kiko] specification tracker |
126 |
|
4476.5.4
by Tom Berger
implementation and tests complete |
127 |
_defaultOrder = ['-priority', 'definition_status', 'name', 'id'] |
2344
by Canonical.com Patch Queue Manager
[not r=kiko] specification tracker |
128 |
|
129 |
# db field names
|
|
130 |
name = StringCol(unique=True, notNull=True) |
|
131 |
title = StringCol(notNull=True) |
|
132 |
summary = StringCol(notNull=True) |
|
4476.5.10
by Tom Berger
sql-quote db enum values, don't just rely on them being integers; also other changes after review |
133 |
definition_status = EnumCol( |
134 |
schema=SpecificationDefinitionStatus, notNull=True, |
|
4476.5.4
by Tom Berger
implementation and tests complete |
135 |
default=SpecificationDefinitionStatus.NEW) |
2736.1.23
by Mark Shuttleworth
�karma restructuring, and test fixes |
136 |
priority = EnumCol(schema=SpecificationPriority, notNull=True, |
3348.1.40
by Mark Shuttleworth
Rename SpecPriority.PROPOSED to UNDEFINED |
137 |
default=SpecificationPriority.UNDEFINED) |
2344
by Canonical.com Patch Queue Manager
[not r=kiko] specification tracker |
138 |
assignee = ForeignKey(dbName='assignee', notNull=False, |
5485.1.13
by Edwin Grubbs
Sorta working |
139 |
foreignKey='Person', |
5821.2.40
by James Henstridge
* Move all the uses of public_person_validator over to the Storm |
140 |
storm_validator=validate_public_person, default=None) |
2344
by Canonical.com Patch Queue Manager
[not r=kiko] specification tracker |
141 |
drafter = ForeignKey(dbName='drafter', notNull=False, |
5485.1.13
by Edwin Grubbs
Sorta working |
142 |
foreignKey='Person', |
5821.2.40
by James Henstridge
* Move all the uses of public_person_validator over to the Storm |
143 |
storm_validator=validate_public_person, default=None) |
2344
by Canonical.com Patch Queue Manager
[not r=kiko] specification tracker |
144 |
approver = ForeignKey(dbName='approver', notNull=False, |
5485.1.13
by Edwin Grubbs
Sorta working |
145 |
foreignKey='Person', |
5821.2.40
by James Henstridge
* Move all the uses of public_person_validator over to the Storm |
146 |
storm_validator=validate_public_person, default=None) |
5485.1.17
by Edwin Grubbs
Fixed indentation |
147 |
owner = ForeignKey( |
148 |
dbName='owner', foreignKey='Person', |
|
5821.2.40
by James Henstridge
* Move all the uses of public_person_validator over to the Storm |
149 |
storm_validator=validate_public_person, notNull=True) |
2344
by Canonical.com Patch Queue Manager
[not r=kiko] specification tracker |
150 |
datecreated = UtcDateTimeCol(notNull=True, default=DEFAULT) |
9550.17.5
by Stuart Bishop
Expose Specification.private |
151 |
private = BoolCol(notNull=True, default=False) |
2344
by Canonical.com Patch Queue Manager
[not r=kiko] specification tracker |
152 |
product = ForeignKey(dbName='product', foreignKey='Product', |
153 |
notNull=False, default=None) |
|
154 |
productseries = ForeignKey(dbName='productseries', |
|
155 |
foreignKey='ProductSeries', notNull=False, default=None) |
|
156 |
distribution = ForeignKey(dbName='distribution', |
|
157 |
foreignKey='Distribution', notNull=False, default=None) |
|
5121.2.6
by Stuart Bishop
Some required code updates |
158 |
distroseries = ForeignKey(dbName='distroseries', |
4285.2.1
by Mark Shuttleworth
Massive renaming of distrorelease to distroseries |
159 |
foreignKey='DistroSeries', notNull=False, default=None) |
3203.1.8
by Mark Shuttleworth
Terminology cleanup, use "goal" for the distrorelease/productseries of spec |
160 |
goalstatus = EnumCol(schema=SpecificationGoalStatus, notNull=True, |
161 |
default=SpecificationGoalStatus.PROPOSED) |
|
3691.73.7
by Mark Shuttleworth
Keep detailed track of spec goal nomination and approval |
162 |
goal_proposer = ForeignKey(dbName='goal_proposer', notNull=False, |
5485.1.13
by Edwin Grubbs
Sorta working |
163 |
foreignKey='Person', |
5821.2.40
by James Henstridge
* Move all the uses of public_person_validator over to the Storm |
164 |
storm_validator=validate_public_person, default=None) |
3691.73.7
by Mark Shuttleworth
Keep detailed track of spec goal nomination and approval |
165 |
date_goal_proposed = UtcDateTimeCol(notNull=False, default=None) |
166 |
goal_decider = ForeignKey(dbName='goal_decider', notNull=False, |
|
5485.1.13
by Edwin Grubbs
Sorta working |
167 |
foreignKey='Person', |
5821.2.40
by James Henstridge
* Move all the uses of public_person_validator over to the Storm |
168 |
storm_validator=validate_public_person, default=None) |
3691.73.7
by Mark Shuttleworth
Keep detailed track of spec goal nomination and approval |
169 |
date_goal_decided = UtcDateTimeCol(notNull=False, default=None) |
2344
by Canonical.com Patch Queue Manager
[not r=kiko] specification tracker |
170 |
milestone = ForeignKey(dbName='milestone', |
171 |
foreignKey='Milestone', notNull=False, default=None) |
|
5821.2.8
by James Henstridge
Fix a few more issues uncovered by clicking around a bit. |
172 |
specurl = StringCol(notNull=False, default=None) |
2344
by Canonical.com Patch Queue Manager
[not r=kiko] specification tracker |
173 |
whiteboard = StringCol(notNull=False, default=None) |
2736.1.27
by Mark Shuttleworth
Move needs_discussion to spec table, and add a direction_approved flag. |
174 |
direction_approved = BoolCol(notNull=True, default=False) |
2736.1.32
by Mark Shuttleworth
specs: add man days estimate and risk of delivery |
175 |
man_days = IntCol(notNull=False, default=None) |
4476.5.10
by Tom Berger
sql-quote db enum values, don't just rely on them being integers; also other changes after review |
176 |
implementation_status = EnumCol( |
177 |
schema=SpecificationImplementationStatus, notNull=True, |
|
4476.5.4
by Tom Berger
implementation and tests complete |
178 |
default=SpecificationImplementationStatus.UNKNOWN) |
2736.1.41
by Mark Shuttleworth
record superseding specification |
179 |
superseded_by = ForeignKey(dbName='superseded_by', |
180 |
foreignKey='Specification', notNull=False, default=None) |
|
3691.73.9
by Mark Shuttleworth
Detect spec completion and record it when spec details change. |
181 |
completer = ForeignKey(dbName='completer', notNull=False, |
5485.1.13
by Edwin Grubbs
Sorta working |
182 |
foreignKey='Person', |
5821.2.40
by James Henstridge
* Move all the uses of public_person_validator over to the Storm |
183 |
storm_validator=validate_public_person, default=None) |
3691.73.9
by Mark Shuttleworth
Detect spec completion and record it when spec details change. |
184 |
date_completed = UtcDateTimeCol(notNull=False, default=None) |
3691.74.1
by Mark Shuttleworth
Track spec starting times and people. |
185 |
starter = ForeignKey(dbName='starter', notNull=False, |
5485.1.13
by Edwin Grubbs
Sorta working |
186 |
foreignKey='Person', |
5821.2.40
by James Henstridge
* Move all the uses of public_person_validator over to the Storm |
187 |
storm_validator=validate_public_person, default=None) |
3691.74.1
by Mark Shuttleworth
Track spec starting times and people. |
188 |
date_started = UtcDateTimeCol(notNull=False, default=None) |
2344
by Canonical.com Patch Queue Manager
[not r=kiko] specification tracker |
189 |
|
190 |
# useful joins
|
|
13101.1.1
by Nigel Babu
Fix the sort order and the tests that broke with it |
191 |
_subscriptions = SQLMultipleJoin('SpecificationSubscription', |
2344
by Canonical.com Patch Queue Manager
[not r=kiko] specification tracker |
192 |
joinColumn='specification', orderBy='id') |
3504.1.13
by kiko
Implement initial SQLRelatedJoin migration across Launchpad tree. Still needs to reconsider the Snapshot approach which will be a big performance hit. |
193 |
subscribers = SQLRelatedJoin('Person', |
2344
by Canonical.com Patch Queue Manager
[not r=kiko] specification tracker |
194 |
joinColumn='specification', otherColumn='person', |
3691.12.14
by Mark Shuttleworth
Test fixes |
195 |
intermediateTable='SpecificationSubscription', |
196 |
orderBy=['displayname', 'name']) |
|
3226.2.1
by Diogo Matsubara
Fix https://launchpad.net/products/launchpad/+bug/33625 (Change MultipleJoin to use the new SQLMultipleJoin.) |
197 |
feedbackrequests = SQLMultipleJoin('SpecificationFeedback', |
2344
by Canonical.com Patch Queue Manager
[not r=kiko] specification tracker |
198 |
joinColumn='specification', orderBy='id') |
3226.2.1
by Diogo Matsubara
Fix https://launchpad.net/products/launchpad/+bug/33625 (Change MultipleJoin to use the new SQLMultipleJoin.) |
199 |
sprint_links = SQLMultipleJoin('SprintSpecification', orderBy='id', |
2445
by Canonical.com Patch Queue Manager
[trivial] db tables for sprints |
200 |
joinColumn='specification') |
3504.1.13
by kiko
Implement initial SQLRelatedJoin migration across Launchpad tree. Still needs to reconsider the Snapshot approach which will be a big performance hit. |
201 |
sprints = SQLRelatedJoin('Sprint', orderBy='name', |
2445
by Canonical.com Patch Queue Manager
[trivial] db tables for sprints |
202 |
joinColumn='specification', otherColumn='sprint', |
203 |
intermediateTable='SprintSpecification') |
|
5485.1.18
by Edwin Grubbs
Fixed lots of lint issues |
204 |
bug_links = SQLMultipleJoin( |
205 |
'SpecificationBug', joinColumn='specification', orderBy='id') |
|
3504.1.13
by kiko
Implement initial SQLRelatedJoin migration across Launchpad tree. Still needs to reconsider the Snapshot approach which will be a big performance hit. |
206 |
bugs = SQLRelatedJoin('Bug', |
2344
by Canonical.com Patch Queue Manager
[not r=kiko] specification tracker |
207 |
joinColumn='specification', otherColumn='bug', |
2396
by Canonical.com Patch Queue Manager
[r=spiv] launchpad support tracker |
208 |
intermediateTable='SpecificationBug', orderBy='id') |
8698.10.5
by Paul Hummer
Fixed more tests |
209 |
linked_branches = SQLMultipleJoin('SpecificationBranch', |
3691.233.3
by Tim Penhey
interim checkin for specification branches, test fails at the moment |
210 |
joinColumn='specification', |
211 |
orderBy='id') |
|
3504.1.13
by kiko
Implement initial SQLRelatedJoin migration across Launchpad tree. Still needs to reconsider the Snapshot approach which will be a big performance hit. |
212 |
spec_dependency_links = SQLMultipleJoin('SpecificationDependency', |
213 |
joinColumn='specification', orderBy='id') |
|
214 |
||
215 |
dependencies = SQLRelatedJoin('Specification', joinColumn='specification', |
|
2344
by Canonical.com Patch Queue Manager
[not r=kiko] specification tracker |
216 |
otherColumn='dependency', orderBy='title', |
217 |
intermediateTable='SpecificationDependency') |
|
3504.1.13
by kiko
Implement initial SQLRelatedJoin migration across Launchpad tree. Still needs to reconsider the Snapshot approach which will be a big performance hit. |
218 |
blocked_specs = SQLRelatedJoin('Specification', joinColumn='dependency', |
2344
by Canonical.com Patch Queue Manager
[not r=kiko] specification tracker |
219 |
otherColumn='specification', orderBy='title', |
220 |
intermediateTable='SpecificationDependency') |
|
221 |
||
13101.1.1
by Nigel Babu
Fix the sort order and the tests that broke with it |
222 |
@cachedproperty
|
223 |
def subscriptions(self): |
|
224 |
"""Sort the subscriptions"""
|
|
13147.2.6
by Nigel Babu
There's already abstraction for this. |
225 |
from lp.registry.model.person import person_sort_key |
226 |
return sorted( |
|
227 |
self._subscriptions, key=lambda sub: person_sort_key(sub.person)) |
|
13101.1.5
by Nigel Babu
More fixes from sinzui |
228 |
|
2344
by Canonical.com Patch Queue Manager
[not r=kiko] specification tracker |
229 |
@property
|
230 |
def target(self): |
|
231 |
"""See ISpecification."""
|
|
232 |
if self.product: |
|
233 |
return self.product |
|
234 |
return self.distribution |
|
235 |
||
11962.3.3
by Guilherme Salgado
Create a new setTarget method on ISpecification, use it in retarget() and protect both with launchpad.Edit. Also started splitting ISpecification into several interfaces to make it easyer to protect them with different permissions |
236 |
def setTarget(self, target): |
2736.1.31
by Mark Shuttleworth
fix permissions issue with retargeting |
237 |
"""See ISpecification."""
|
11962.3.3
by Guilherme Salgado
Create a new setTarget method on ISpecification, use it in retarget() and protect both with launchpad.Edit. Also started splitting ISpecification into several interfaces to make it easyer to protect them with different permissions |
238 |
if IProduct.providedBy(target): |
239 |
self.product = target |
|
240 |
self.distribution = None |
|
241 |
elif IDistribution.providedBy(target): |
|
242 |
self.product = None |
|
243 |
self.distribution = target |
|
244 |
else: |
|
245 |
raise AssertionError("Unknown target: %s" % target) |
|
2736.1.31
by Mark Shuttleworth
fix permissions issue with retargeting |
246 |
|
11962.3.3
by Guilherme Salgado
Create a new setTarget method on ISpecification, use it in retarget() and protect both with launchpad.Edit. Also started splitting ISpecification into several interfaces to make it easyer to protect them with different permissions |
247 |
def retarget(self, target): |
248 |
"""See ISpecification."""
|
|
249 |
if self.target == target: |
|
3691.73.15
by Mark Shuttleworth
Ensure that specs on inactive products are filtered from listings. |
250 |
return
|
251 |
||
11138.2.1
by James Westby
Work towards having a blueprint model that is safe to export. |
252 |
self.validateMove(target) |
253 |
||
11962.3.3
by Guilherme Salgado
Create a new setTarget method on ISpecification, use it in retarget() and protect both with launchpad.Edit. Also started splitting ISpecification into several interfaces to make it easyer to protect them with different permissions |
254 |
# We must lose any goal we have set and approved/declined because we
|
255 |
# are moving to a different target that will have different
|
|
256 |
# policies and drivers.
|
|
2736.1.31
by Mark Shuttleworth
fix permissions issue with retargeting |
257 |
self.productseries = None |
4285.2.1
by Mark Shuttleworth
Massive renaming of distrorelease to distroseries |
258 |
self.distroseries = None |
3691.73.15
by Mark Shuttleworth
Ensure that specs on inactive products are filtered from listings. |
259 |
self.goalstatus = SpecificationGoalStatus.PROPOSED |
260 |
self.goal_proposer = None |
|
261 |
self.date_goal_proposed = None |
|
2736.1.31
by Mark Shuttleworth
fix permissions issue with retargeting |
262 |
self.milestone = None |
3691.73.15
by Mark Shuttleworth
Ensure that specs on inactive products are filtered from listings. |
263 |
|
11962.3.3
by Guilherme Salgado
Create a new setTarget method on ISpecification, use it in retarget() and protect both with launchpad.Edit. Also started splitting ISpecification into several interfaces to make it easyer to protect them with different permissions |
264 |
self.setTarget(target) |
3691.12.13
by Mark Shuttleworth
Fix #50814, now spec retargeting resets spec priority not definition status |
265 |
self.priority = SpecificationPriority.UNDEFINED |
266 |
self.direction_approved = False |
|
2736.1.31
by Mark Shuttleworth
fix permissions issue with retargeting |
267 |
|
11138.2.1
by James Westby
Work towards having a blueprint model that is safe to export. |
268 |
def validateMove(self, target): |
11962.3.3
by Guilherme Salgado
Create a new setTarget method on ISpecification, use it in retarget() and protect both with launchpad.Edit. Also started splitting ISpecification into several interfaces to make it easyer to protect them with different permissions |
269 |
"""See ISpecification."""
|
11138.2.1
by James Westby
Work towards having a blueprint model that is safe to export. |
270 |
if target.getSpecification(self.name) is not None: |
271 |
raise TargetAlreadyHasSpecification(target, self.name) |
|
272 |
||
3203.1.8
by Mark Shuttleworth
Terminology cleanup, use "goal" for the distrorelease/productseries of spec |
273 |
@property
|
274 |
def goal(self): |
|
275 |
"""See ISpecification."""
|
|
276 |
if self.productseries: |
|
277 |
return self.productseries |
|
4285.2.1
by Mark Shuttleworth
Massive renaming of distrorelease to distroseries |
278 |
return self.distroseries |
3203.1.8
by Mark Shuttleworth
Terminology cleanup, use "goal" for the distrorelease/productseries of spec |
279 |
|
3691.73.7
by Mark Shuttleworth
Keep detailed track of spec goal nomination and approval |
280 |
def proposeGoal(self, goal, proposer): |
281 |
"""See ISpecification."""
|
|
282 |
if goal is None: |
|
283 |
# we are clearing goals
|
|
284 |
self.productseries = None |
|
4285.2.1
by Mark Shuttleworth
Massive renaming of distrorelease to distroseries |
285 |
self.distroseries = None |
3691.73.7
by Mark Shuttleworth
Keep detailed track of spec goal nomination and approval |
286 |
elif IProductSeries.providedBy(goal): |
287 |
# set the product series as a goal
|
|
288 |
self.productseries = goal |
|
289 |
self.goal_proposer = proposer |
|
290 |
self.date_goal_proposed = UTC_NOW |
|
4285.2.1
by Mark Shuttleworth
Massive renaming of distrorelease to distroseries |
291 |
# and make sure there is no leftover distroseries goal
|
292 |
self.distroseries = None |
|
293 |
elif IDistroSeries.providedBy(goal): |
|
294 |
# set the distroseries goal
|
|
295 |
self.distroseries = goal |
|
3691.73.7
by Mark Shuttleworth
Keep detailed track of spec goal nomination and approval |
296 |
self.goal_proposer = proposer |
297 |
self.date_goal_proposed = UTC_NOW |
|
4285.2.1
by Mark Shuttleworth
Massive renaming of distrorelease to distroseries |
298 |
# and make sure there is no leftover distroseries goal
|
3691.73.7
by Mark Shuttleworth
Keep detailed track of spec goal nomination and approval |
299 |
self.productseries = None |
300 |
else: |
|
11235.5.5
by Curtis Hovey
Hushed lint. |
301 |
raise AssertionError('Inappropriate goal.') |
3691.73.7
by Mark Shuttleworth
Keep detailed track of spec goal nomination and approval |
302 |
# record who made the proposal, and when
|
303 |
self.goal_proposer = proposer |
|
304 |
self.date_goal_proposed = UTC_NOW |
|
305 |
# and of course set the goal status to PROPOSED
|
|
306 |
self.goalstatus = SpecificationGoalStatus.PROPOSED |
|
3691.73.21
by Mark Shuttleworth
Additional changes raised during review. |
307 |
# the goal should now also not have a decider
|
308 |
self.goal_decider = None |
|
309 |
self.date_goal_decided = None |
|
11962.3.2
by Guilherme Salgado
Create IHasDrivers.personHasDriverRights(person), to be used on security adapters and ISpecification.proposeGoal(). |
310 |
if goal is not None and goal.personHasDriverRights(proposer): |
311 |
self.acceptBy(proposer) |
|
3691.73.7
by Mark Shuttleworth
Keep detailed track of spec goal nomination and approval |
312 |
|
313 |
def acceptBy(self, decider): |
|
314 |
"""See ISpecification."""
|
|
315 |
self.goalstatus = SpecificationGoalStatus.ACCEPTED |
|
316 |
self.goal_decider = decider |
|
317 |
self.date_goal_decided = UTC_NOW |
|
318 |
||
319 |
def declineBy(self, decider): |
|
320 |
"""See ISpecification."""
|
|
321 |
self.goalstatus = SpecificationGoalStatus.DECLINED |
|
322 |
self.goal_decider = decider |
|
323 |
self.date_goal_decided = UTC_NOW |
|
324 |
||
2736.1.4
by Mark Shuttleworth
substantial cleanups of meeting system |
325 |
def getSprintSpecification(self, sprintname): |
326 |
"""See ISpecification."""
|
|
327 |
for sprintspecification in self.sprint_links: |
|
328 |
if sprintspecification.sprint.name == sprintname: |
|
329 |
return sprintspecification |
|
330 |
return None |
|
331 |
||
2736.1.34
by Mark Shuttleworth
start renaming specificationreview to specificationfeedback |
332 |
def getFeedbackRequests(self, person): |
333 |
"""See ISpecification."""
|
|
5622.3.15
by Christian Robottom Reis
Optimize specification feedback calls away; make sure we only use the View template for the actual page, not for portlets and etc., since the feedback stuff is only relevant for the page itself. |
334 |
fb = SpecificationFeedback.selectBy( |
335 |
specification=self, reviewer=person) |
|
336 |
return fb.prejoin(['requester']) |
|
2736.1.34
by Mark Shuttleworth
start renaming specificationreview to specificationfeedback |
337 |
|
3287.1.2
by Bjorn Tillenius
add ISpecification.notificationRecipientAddresses() |
338 |
def notificationRecipientAddresses(self): |
339 |
"""See ISpecification."""
|
|
340 |
related_people = [ |
|
341 |
self.owner, self.assignee, self.approver, self.drafter] |
|
342 |
related_people = [ |
|
343 |
person for person in related_people if person is not None] |
|
344 |
subscribers = [ |
|
345 |
subscription.person for subscription in self.subscriptions] |
|
346 |
addresses = set() |
|
347 |
for person in related_people + subscribers: |
|
7495.2.3
by Curtis Hovey
Renamed contactEmailAddresses => get_contact_email_addresses. Fixed long lines. |
348 |
addresses.update(get_contact_email_addresses(person)) |
3287.1.2
by Bjorn Tillenius
add ISpecification.notificationRecipientAddresses() |
349 |
return sorted(addresses) |
350 |
||
2736.1.16
by Mark Shuttleworth
ability to add someone else as a subscriber |
351 |
# emergent properties
|
352 |
@property
|
|
353 |
def is_incomplete(self): |
|
354 |
"""See ISpecification."""
|
|
2736.1.32
by Mark Shuttleworth
specs: add man days estimate and risk of delivery |
355 |
return not self.is_complete |
356 |
||
3348.1.11
by Mark Shuttleworth
Make IHasSpecifications.specifications filtered and use it |
357 |
# Several other classes need to generate lists of specifications, and
|
358 |
# one thing they often have to filter for is completeness. We maintain
|
|
359 |
# this single canonical query string here so that it does not have to be
|
|
360 |
# cargo culted into Product, Distribution, ProductSeries etc
|
|
3691.73.9
by Mark Shuttleworth
Detect spec completion and record it when spec details change. |
361 |
|
362 |
# Also note that there is a constraint in the database which ensures
|
|
363 |
# that date_completed is set if the spec is complete, and that db
|
|
364 |
# constraint parrots this definition exactly.
|
|
365 |
||
366 |
# NB NB NB if you change this definition PLEASE update the db constraint
|
|
3691.74.1
by Mark Shuttleworth
Track spec starting times and people. |
367 |
# Specification.specification_completion_recorded_chk !!!
|
11235.5.5
by Curtis Hovey
Hushed lint. |
368 |
completeness_clause = (""" |
4476.5.10
by Tom Berger
sql-quote db enum values, don't just rely on them being integers; also other changes after review |
369 |
Specification.implementation_status = %s OR |
370 |
Specification.definition_status IN ( %s, %s ) OR |
|
371 |
(Specification.implementation_status = %s AND |
|
372 |
Specification.definition_status = %s) |
|
373 |
""" % sqlvalues(SpecificationImplementationStatus.IMPLEMENTED.value, |
|
374 |
SpecificationDefinitionStatus.OBSOLETE.value, |
|
375 |
SpecificationDefinitionStatus.SUPERSEDED.value, |
|
376 |
SpecificationImplementationStatus.INFORMATIONAL.value, |
|
377 |
SpecificationDefinitionStatus.APPROVED.value)) |
|
3348.1.11
by Mark Shuttleworth
Make IHasSpecifications.specifications filtered and use it |
378 |
|
2736.1.32
by Mark Shuttleworth
specs: add man days estimate and risk of delivery |
379 |
@property
|
380 |
def is_complete(self): |
|
4476.5.10
by Tom Berger
sql-quote db enum values, don't just rely on them being integers; also other changes after review |
381 |
"""See `ISpecification`."""
|
382 |
# Implemented blueprints are by definition complete.
|
|
383 |
if (self.implementation_status == |
|
384 |
SpecificationImplementationStatus.IMPLEMENTED): |
|
385 |
return True |
|
386 |
# Obsolete and superseded blueprints are considered complete.
|
|
387 |
if self.definition_status in ( |
|
388 |
SpecificationDefinitionStatus.OBSOLETE, |
|
389 |
SpecificationDefinitionStatus.SUPERSEDED): |
|
390 |
return True |
|
391 |
# Approved information blueprints are also considered complete.
|
|
392 |
if ((self.implementation_status == |
|
393 |
SpecificationImplementationStatus.INFORMATIONAL) and |
|
394 |
(self.definition_status == |
|
395 |
SpecificationDefinitionStatus.APPROVED)): |
|
396 |
return True |
|
397 |
else: |
|
398 |
return False |
|
2736.1.16
by Mark Shuttleworth
ability to add someone else as a subscriber |
399 |
|
3691.74.1
by Mark Shuttleworth
Track spec starting times and people. |
400 |
# NB NB If you change this definition, please update the equivalent
|
401 |
# DB constraint Specification.specification_start_recorded_chk
|
|
402 |
# We choose to define "started" as the set of delivery states NOT
|
|
403 |
# in the values we select. Another option would be to say "anything less
|
|
404 |
# than a threshold" and to comment the dbschema that "anything not
|
|
405 |
# started should be less than the threshold". We'll see how maintainable
|
|
406 |
# this is.
|
|
11235.5.5
by Curtis Hovey
Hushed lint. |
407 |
started_clause = """ |
4476.5.10
by Tom Berger
sql-quote db enum values, don't just rely on them being integers; also other changes after review |
408 |
Specification.implementation_status NOT IN (%s, %s, %s, %s) OR |
409 |
(Specification.implementation_status = %s AND |
|
410 |
Specification.definition_status = %s) |
|
411 |
""" % sqlvalues(SpecificationImplementationStatus.UNKNOWN.value, |
|
4476.5.4
by Tom Berger
implementation and tests complete |
412 |
SpecificationImplementationStatus.NOTSTARTED.value, |
413 |
SpecificationImplementationStatus.DEFERRED.value, |
|
4476.5.10
by Tom Berger
sql-quote db enum values, don't just rely on them being integers; also other changes after review |
414 |
SpecificationImplementationStatus.INFORMATIONAL.value, |
415 |
SpecificationImplementationStatus.INFORMATIONAL.value, |
|
416 |
SpecificationDefinitionStatus.APPROVED.value) |
|
3691.109.27
by Francis J. Lacoste
Merge RF |
417 |
|
3691.74.1
by Mark Shuttleworth
Track spec starting times and people. |
418 |
@property
|
419 |
def is_started(self): |
|
420 |
"""See ISpecification. This is a code implementation of the
|
|
421 |
SQL in self.started_clause
|
|
422 |
"""
|
|
4476.5.4
by Tom Berger
implementation and tests complete |
423 |
return (self.implementation_status not in [ |
424 |
SpecificationImplementationStatus.UNKNOWN, |
|
425 |
SpecificationImplementationStatus.NOTSTARTED, |
|
426 |
SpecificationImplementationStatus.DEFERRED, |
|
427 |
SpecificationImplementationStatus.INFORMATIONAL, |
|
3691.74.1
by Mark Shuttleworth
Track spec starting times and people. |
428 |
]
|
4476.5.4
by Tom Berger
implementation and tests complete |
429 |
or ((self.implementation_status == |
430 |
SpecificationImplementationStatus.INFORMATIONAL) and |
|
431 |
(self.definition_status == |
|
432 |
SpecificationDefinitionStatus.APPROVED))) |
|
3691.74.1
by Mark Shuttleworth
Track spec starting times and people. |
433 |
|
11852.1.3
by Tim Penhey
Have the Specification.updateLifecycleStatus method called due to the object modified event in preparation of API exposure. |
434 |
@property
|
435 |
def lifecycle_status(self): |
|
436 |
"""Combine the is_complete and is_started emergent properties."""
|
|
437 |
if self.is_complete: |
|
438 |
return SpecificationLifecycleStatus.COMPLETE |
|
439 |
elif self.is_started: |
|
440 |
return SpecificationLifecycleStatus.STARTED |
|
441 |
else: |
|
442 |
return SpecificationLifecycleStatus.NOTSTARTED |
|
443 |
||
12534.3.1
by Tim Penhey
Some working. |
444 |
def setDefinitionStatus(self, definition_status, user): |
445 |
self.definition_status = definition_status |
|
446 |
self.updateLifecycleStatus(user) |
|
447 |
||
448 |
def setImplementationStatus(self, implementation_status, user): |
|
449 |
self.implementation_status = implementation_status |
|
450 |
self.updateLifecycleStatus(user) |
|
451 |
||
3691.74.1
by Mark Shuttleworth
Track spec starting times and people. |
452 |
def updateLifecycleStatus(self, user): |
3691.73.9
by Mark Shuttleworth
Detect spec completion and record it when spec details change. |
453 |
"""See ISpecification."""
|
3691.74.1
by Mark Shuttleworth
Track spec starting times and people. |
454 |
newstatus = None |
455 |
if self.is_started: |
|
5821.2.27
by James Henstridge
* Add block_implicit_flushes decorator that blocks flushes performed |
456 |
if self.starterID is None: |
3691.74.1
by Mark Shuttleworth
Track spec starting times and people. |
457 |
newstatus = SpecificationLifecycleStatus.STARTED |
458 |
self.date_started = UTC_NOW |
|
459 |
self.starter = user |
|
460 |
else: |
|
5821.2.27
by James Henstridge
* Add block_implicit_flushes decorator that blocks flushes performed |
461 |
if self.starterID is not None: |
3691.74.1
by Mark Shuttleworth
Track spec starting times and people. |
462 |
newstatus = SpecificationLifecycleStatus.NOTSTARTED |
463 |
self.date_started = None |
|
464 |
self.starter = None |
|
3691.73.9
by Mark Shuttleworth
Detect spec completion and record it when spec details change. |
465 |
if self.is_complete: |
5821.2.27
by James Henstridge
* Add block_implicit_flushes decorator that blocks flushes performed |
466 |
if self.completerID is None: |
3691.74.1
by Mark Shuttleworth
Track spec starting times and people. |
467 |
newstatus = SpecificationLifecycleStatus.COMPLETE |
3691.73.9
by Mark Shuttleworth
Detect spec completion and record it when spec details change. |
468 |
self.date_completed = UTC_NOW |
469 |
self.completer = user |
|
470 |
else: |
|
5821.2.27
by James Henstridge
* Add block_implicit_flushes decorator that blocks flushes performed |
471 |
if self.completerID is not None: |
3691.73.9
by Mark Shuttleworth
Detect spec completion and record it when spec details change. |
472 |
self.date_completed = None |
473 |
self.completer = None |
|
3691.74.1
by Mark Shuttleworth
Track spec starting times and people. |
474 |
if self.is_started: |
475 |
newstatus = SpecificationLifecycleStatus.STARTED |
|
476 |
else: |
|
477 |
newstatus = SpecificationLifecycleStatus.NOTSTARTED |
|
3691.109.27
by Francis J. Lacoste
Merge RF |
478 |
|
3691.74.1
by Mark Shuttleworth
Track spec starting times and people. |
479 |
return newstatus |
3691.73.9
by Mark Shuttleworth
Detect spec completion and record it when spec details change. |
480 |
|
2736.1.16
by Mark Shuttleworth
ability to add someone else as a subscriber |
481 |
@property
|
482 |
def is_blocked(self): |
|
483 |
"""See ISpecification."""
|
|
484 |
for spec in self.dependencies: |
|
485 |
if spec.is_incomplete: |
|
486 |
return True |
|
487 |
return False |
|
488 |
||
2736.1.32
by Mark Shuttleworth
specs: add man days estimate and risk of delivery |
489 |
@property
|
4285.2.1
by Mark Shuttleworth
Massive renaming of distrorelease to distroseries |
490 |
def has_accepted_goal(self): |
2736.1.32
by Mark Shuttleworth
specs: add man days estimate and risk of delivery |
491 |
"""See ISpecification."""
|
3279.1.4
by Mark Shuttleworth
Address review comments for r=kiko |
492 |
if (self.goal is not None and |
493 |
self.goalstatus == SpecificationGoalStatus.ACCEPTED): |
|
2736.1.32
by Mark Shuttleworth
specs: add man days estimate and risk of delivery |
494 |
return True |
2736.1.40
by Mark Shuttleworth
tweaks for [r=spiv] |
495 |
return False |
2736.1.32
by Mark Shuttleworth
specs: add man days estimate and risk of delivery |
496 |
|
2736.1.22
by Mark Shuttleworth
karma categories in the db, and karma for specs |
497 |
def getDelta(self, old_spec, user): |
498 |
"""See ISpecification."""
|
|
3691.431.1
by Tim Penhey
First checkin of branch emails. Nothing works yet, but need to switch |
499 |
delta = ObjectDelta(old_spec, self) |
8971.13.1
by Andrea Corbellini
When the whiteboard of a blueprint is edited, show the differences |
500 |
delta.recordNewValues(("title", "summary", |
3691.290.11
by Tim Penhey
Updates following review comments |
501 |
"specurl", "productseries", |
4285.2.1
by Mark Shuttleworth
Massive renaming of distrorelease to distroseries |
502 |
"distroseries", "milestone")) |
5543.8.11
by Tim Penhey
Lint line length fixes. |
503 |
delta.recordNewAndOld(("name", "priority", "definition_status", |
8971.13.1
by Andrea Corbellini
When the whiteboard of a blueprint is edited, show the differences |
504 |
"target", "approver", "assignee", "drafter", |
505 |
"whiteboard")) |
|
3691.290.11
by Tim Penhey
Updates following review comments |
506 |
delta.recordListAddedAndRemoved("bugs", |
507 |
"bugs_linked", |
|
508 |
"bugs_unlinked") |
|
4785.3.1
by Jeroen Vermeulen
Removed whitespace before EOLs. |
509 |
|
3691.431.1
by Tim Penhey
First checkin of branch emails. Nothing works yet, but need to switch |
510 |
if delta.changes: |
511 |
changes = delta.changes |
|
2736.1.22
by Mark Shuttleworth
karma categories in the db, and karma for specs |
512 |
changes["specification"] = self |
513 |
changes["user"] = user |
|
514 |
||
515 |
return SpecificationDelta(**changes) |
|
516 |
else: |
|
517 |
return None |
|
518 |
||
4476.5.4
by Tom Berger
implementation and tests complete |
519 |
@property
|
520 |
def informational(self): |
|
521 |
"""For backwards compatibility:
|
|
522 |
implemented as a value in implementation_status.
|
|
523 |
"""
|
|
524 |
return (self.implementation_status == |
|
525 |
SpecificationImplementationStatus.INFORMATIONAL) |
|
526 |
||
2344
by Canonical.com Patch Queue Manager
[not r=kiko] specification tracker |
527 |
# subscriptions
|
3691.73.1
by Mark Shuttleworth
Allow subscribers to be classed as essential to a spec's plan. |
528 |
def subscription(self, person): |
529 |
"""See ISpecification."""
|
|
3691.436.68
by Mark Shuttleworth
Offer the mentor the option to subscribe to the work |
530 |
return SpecificationSubscription.selectOneBy( |
531 |
specification=self, person=person) |
|
3691.73.1
by Mark Shuttleworth
Allow subscribers to be classed as essential to a spec's plan. |
532 |
|
533 |
def getSubscriptionByName(self, name): |
|
534 |
"""See ISpecification."""
|
|
535 |
for sub in self.subscriptions: |
|
536 |
if sub.person.name == name: |
|
537 |
return sub |
|
538 |
return None |
|
539 |
||
13161.2.1
by Ian Booth
Export (un)subscribe methods on ISpecification to web service |
540 |
def subscribe(self, person, subscribed_by=None, essential=False): |
541 |
"""See ISpecification."""
|
|
542 |
if subscribed_by is None: |
|
543 |
subscribed_by = person |
|
544 |
# Create or modify a user's subscription to this blueprint.
|
|
545 |
# First see if a relevant subscription exists, and if so, return it
|
|
3691.73.1
by Mark Shuttleworth
Allow subscribers to be classed as essential to a spec's plan. |
546 |
sub = self.subscription(person) |
4506.3.3
by Tom Berger
post review changes |
547 |
if sub is not None: |
4506.3.5
by Tom Berger
reply to review: make all parameters to specification.subscribe positional |
548 |
if sub.essential != essential: |
4506.3.3
by Tom Berger
post review changes |
549 |
# If a subscription already exists, but the value for
|
550 |
# 'essential' changes, there's no need to create a new
|
|
551 |
# subscription, but we modify the existing subscription
|
|
552 |
# and notify the user about the change.
|
|
4506.3.1
by Tom Berger
adds a new notification event for changes to a user's blueprint subscription and handles it by spamming the user, also adds tests for that behaviour and reformats the pagetest |
553 |
sub.essential = essential |
4506.3.3
by Tom Berger
post review changes |
554 |
# The second argument should really be a copy of sub with
|
555 |
# only the essential attribute changed, but we know
|
|
556 |
# that we can get away with not examining the attribute
|
|
557 |
# at all - it's a boolean!
|
|
7876.3.6
by Francis J. Lacoste
Used ISQLObject from lazr.lifecycle |
558 |
notify(ObjectModifiedEvent( |
13161.2.1
by Ian Booth
Export (un)subscribe methods on ISpecification to web service |
559 |
sub, sub, ['essential'], user=subscribed_by)) |
3691.73.1
by Mark Shuttleworth
Allow subscribers to be classed as essential to a spec's plan. |
560 |
return sub |
3348.1.13
by Mark Shuttleworth
Finish sprint specification filtering |
561 |
# since no previous subscription existed, create and return a new one
|
4506.3.1
by Tom Berger
adds a new notification event for changes to a user's blueprint subscription and handles it by spamming the user, also adds tests for that behaviour and reformats the pagetest |
562 |
sub = SpecificationSubscription(specification=self, |
3691.73.1
by Mark Shuttleworth
Allow subscribers to be classed as essential to a spec's plan. |
563 |
person=person, essential=essential) |
13101.1.5
by Nigel Babu
More fixes from sinzui |
564 |
property_cache = get_property_cache(self) |
565 |
if 'subscription' in property_cache: |
|
13147.2.6
by Nigel Babu
There's already abstraction for this. |
566 |
from lp.registry.model.person import person_sort_key |
13101.1.5
by Nigel Babu
More fixes from sinzui |
567 |
property_cache.subscriptions.append(sub) |
568 |
property_cache.subscriptions.sort( |
|
13147.2.6
by Nigel Babu
There's already abstraction for this. |
569 |
key=lambda sub: person_sort_key(sub.person)) |
570 |
notify(ObjectCreatedEvent(sub, user=subscribed_by)) |
|
4506.3.1
by Tom Berger
adds a new notification event for changes to a user's blueprint subscription and handles it by spamming the user, also adds tests for that behaviour and reformats the pagetest |
571 |
return sub |
2344
by Canonical.com Patch Queue Manager
[not r=kiko] specification tracker |
572 |
|
13161.2.1
by Ian Booth
Export (un)subscribe methods on ISpecification to web service |
573 |
def unsubscribe(self, person, unsubscribed_by): |
2344
by Canonical.com Patch Queue Manager
[not r=kiko] specification tracker |
574 |
"""See ISpecification."""
|
575 |
# see if a relevant subscription exists, and if so, delete it
|
|
13161.2.1
by Ian Booth
Export (un)subscribe methods on ISpecification to web service |
576 |
if person is None: |
577 |
person = unsubscribed_by |
|
2344
by Canonical.com Patch Queue Manager
[not r=kiko] specification tracker |
578 |
for sub in self.subscriptions: |
579 |
if sub.person.id == person.id: |
|
13161.2.2
by Ian Booth
Add canBeUnsubscribedByUser and tests |
580 |
if not sub.canBeUnsubscribedByUser(unsubscribed_by): |
581 |
raise UserCannotUnsubscribePerson( |
|
582 |
'%s does not have permission to unsubscribe %s.' % ( |
|
583 |
unsubscribed_by.displayname, |
|
584 |
person.displayname)) |
|
13101.1.2
by Nigel Babu
Update the cache correctly. |
585 |
get_property_cache(self).subscriptions.remove(sub) |
2344
by Canonical.com Patch Queue Manager
[not r=kiko] specification tracker |
586 |
SpecificationSubscription.delete(sub.id) |
587 |
return
|
|
588 |
||
3691.436.68
by Mark Shuttleworth
Offer the mentor the option to subscribe to the work |
589 |
def isSubscribed(self, person): |
10409.5.69
by Curtis Hovey
Removed answers and blueprints from canonical.launchpad.__init__. |
590 |
"""See lp.blueprints.interfaces.specification.ISpecification."""
|
3691.436.68
by Mark Shuttleworth
Offer the mentor the option to subscribe to the work |
591 |
if person is None: |
592 |
return False |
|
593 |
||
594 |
return bool(self.subscription(person)) |
|
595 |
||
2344
by Canonical.com Patch Queue Manager
[not r=kiko] specification tracker |
596 |
# queueing
|
2736.1.38
by Mark Shuttleworth
rename db table specificationreview to specificationfeedback [r=stub] |
597 |
def queue(self, reviewer, requester, queuemsg=None): |
2344
by Canonical.com Patch Queue Manager
[not r=kiko] specification tracker |
598 |
"""See ISpecification."""
|
2736.1.34
by Mark Shuttleworth
start renaming specificationreview to specificationfeedback |
599 |
for fbreq in self.feedbackrequests: |
2736.1.35
by Mark Shuttleworth
multiselector interface for clearing spec feedback requests |
600 |
if (fbreq.reviewer.id == reviewer.id and |
2736.1.38
by Mark Shuttleworth
rename db table specificationreview to specificationfeedback [r=stub] |
601 |
fbreq.requester == requester.id): |
2736.1.35
by Mark Shuttleworth
multiselector interface for clearing spec feedback requests |
602 |
# we have a relevant request already, update it
|
2736.1.34
by Mark Shuttleworth
start renaming specificationreview to specificationfeedback |
603 |
fbreq.queuemsg = queuemsg |
604 |
return fbreq |
|
2736.1.35
by Mark Shuttleworth
multiselector interface for clearing spec feedback requests |
605 |
# since no previous feedback request existed for this person,
|
606 |
# create a new one
|
|
2736.1.34
by Mark Shuttleworth
start renaming specificationreview to specificationfeedback |
607 |
return SpecificationFeedback( |
2344
by Canonical.com Patch Queue Manager
[not r=kiko] specification tracker |
608 |
specification=self, |
609 |
reviewer=reviewer, |
|
2736.1.38
by Mark Shuttleworth
rename db table specificationreview to specificationfeedback [r=stub] |
610 |
requester=requester, |
2344
by Canonical.com Patch Queue Manager
[not r=kiko] specification tracker |
611 |
queuemsg=queuemsg) |
612 |
||
2736.1.38
by Mark Shuttleworth
rename db table specificationreview to specificationfeedback [r=stub] |
613 |
def unqueue(self, reviewer, requester): |
2344
by Canonical.com Patch Queue Manager
[not r=kiko] specification tracker |
614 |
"""See ISpecification."""
|
615 |
# see if a relevant queue entry exists, and if so, delete it
|
|
2736.1.34
by Mark Shuttleworth
start renaming specificationreview to specificationfeedback |
616 |
for fbreq in self.feedbackrequests: |
2736.1.35
by Mark Shuttleworth
multiselector interface for clearing spec feedback requests |
617 |
if (fbreq.reviewer.id == reviewer.id and |
2736.1.38
by Mark Shuttleworth
rename db table specificationreview to specificationfeedback [r=stub] |
618 |
fbreq.requester.id == requester.id): |
2736.1.34
by Mark Shuttleworth
start renaming specificationreview to specificationfeedback |
619 |
SpecificationFeedback.delete(fbreq.id) |
2344
by Canonical.com Patch Queue Manager
[not r=kiko] specification tracker |
620 |
return
|
621 |
||
3691.109.23
by Francis J. Lacoste
* Define a BugLinkTargetMixin for base implementation of linkBug and unlinkBug. |
622 |
# Template methods for BugLinkTargetMixin
|
623 |
buglinkClass = SpecificationBug |
|
2344
by Canonical.com Patch Queue Manager
[not r=kiko] specification tracker |
624 |
|
3691.109.23
by Francis J. Lacoste
* Define a BugLinkTargetMixin for base implementation of linkBug and unlinkBug. |
625 |
def createBugLink(self, bug): |
626 |
"""See BugLinkTargetMixin."""
|
|
627 |
return SpecificationBug(specification=self, bug=bug) |
|
2344
by Canonical.com Patch Queue Manager
[not r=kiko] specification tracker |
628 |
|
2445
by Canonical.com Patch Queue Manager
[trivial] db tables for sprints |
629 |
# sprint linking
|
3657.1.1
by Mark Shuttleworth
Keep track of who nominated a spec for a sprint. |
630 |
def linkSprint(self, sprint, user): |
2445
by Canonical.com Patch Queue Manager
[trivial] db tables for sprints |
631 |
"""See ISpecification."""
|
11962.3.22
by Guilherme Salgado
Make sure Sprint actually implements IHasSpecifications |
632 |
from lp.blueprints.model.sprintspecification import ( |
633 |
SprintSpecification) |
|
2445
by Canonical.com Patch Queue Manager
[trivial] db tables for sprints |
634 |
for sprint_link in self.sprint_links: |
3691.73.5
by Mark Shuttleworth
Test fixes for sprint linking code and pages |
635 |
# sprints have unique names
|
636 |
if sprint_link.sprint.name == sprint.name: |
|
2445
by Canonical.com Patch Queue Manager
[trivial] db tables for sprints |
637 |
return sprint_link |
4473.1.2
by Tom Berger
move the auto-accepting code to the content object (on the way to possiblly removing it altogether later) |
638 |
sprint_link = SprintSpecification(specification=self, |
3691.73.4
by Mark Shuttleworth
Record the full lifecycle of sprint agenda nomination and approval. |
639 |
sprint=sprint, registrant=user) |
4473.1.10
by Tom Berger
post review changes |
640 |
if sprint.isDriver(user): |
4473.1.2
by Tom Berger
move the auto-accepting code to the content object (on the way to possiblly removing it altogether later) |
641 |
sprint_link.acceptBy(user) |
642 |
return sprint_link |
|
2445
by Canonical.com Patch Queue Manager
[trivial] db tables for sprints |
643 |
|
644 |
def unlinkSprint(self, sprint): |
|
645 |
"""See ISpecification."""
|
|
11962.3.22
by Guilherme Salgado
Make sure Sprint actually implements IHasSpecifications |
646 |
from lp.blueprints.model.sprintspecification import ( |
647 |
SprintSpecification) |
|
2445
by Canonical.com Patch Queue Manager
[trivial] db tables for sprints |
648 |
for sprint_link in self.sprint_links: |
3691.73.5
by Mark Shuttleworth
Test fixes for sprint linking code and pages |
649 |
# sprints have unique names
|
650 |
if sprint_link.sprint.name == sprint.name: |
|
2445
by Canonical.com Patch Queue Manager
[trivial] db tables for sprints |
651 |
SprintSpecification.delete(sprint_link.id) |
652 |
return sprint_link |
|
653 |
||
2344
by Canonical.com Patch Queue Manager
[not r=kiko] specification tracker |
654 |
# dependencies
|
655 |
def createDependency(self, specification): |
|
656 |
"""See ISpecification."""
|
|
657 |
for deplink in self.spec_dependency_links: |
|
658 |
if deplink.dependency.id == specification.id: |
|
659 |
return deplink |
|
660 |
return SpecificationDependency(specification=self, |
|
661 |
dependency=specification) |
|
662 |
||
663 |
def removeDependency(self, specification): |
|
664 |
"""See ISpecification."""
|
|
665 |
# see if a relevant dependency link exists, and if so, delete it
|
|
666 |
for deplink in self.spec_dependency_links: |
|
667 |
if deplink.dependency.id == specification.id: |
|
668 |
SpecificationDependency.delete(deplink.id) |
|
669 |
return deplink |
|
670 |
||
3691.12.2
by Mark Shuttleworth
Do not allow adding a spec dependency on a blocked spec, and fix #2428 |
671 |
@property
|
3348.1.13
by Mark Shuttleworth
Finish sprint specification filtering |
672 |
def all_deps(self): |
12579.3.2
by Tim Penhey
Move the SQL out. |
673 |
return Store.of(self).with_( |
12579.2.6
by Tim Penhey
Move to module functions. |
674 |
SQL(recursive_dependent_query(self))).find( |
12579.2.3
by Tim Penhey
Change the all_blocked and all_deps to use recursive queries, rather than a recursive algorithm and many queries. |
675 |
Specification, |
676 |
Specification.id != self.id, |
|
12579.2.9
by Tim Penhey
Tweaks to make the tests pass. Also add explicit ordering. |
677 |
SQL('Specification.id in (select id from dependencies)') |
678 |
).order_by(Specification.name, Specification.id) |
|
12579.2.3
by Tim Penhey
Change the all_blocked and all_deps to use recursive queries, rather than a recursive algorithm and many queries. |
679 |
|
7141.3.9
by Edwin Grubbs
Uncached spec.all_blocked |
680 |
@property
|
7141.3.2
by Edwin Grubbs
Added tests and comments. Re-introduced old Spec.all_blocked and moved all_blocked to cached_all_blocked_ids. |
681 |
def all_blocked(self): |
682 |
"""See `ISpecification`."""
|
|
12579.3.2
by Tim Penhey
Move the SQL out. |
683 |
return Store.of(self).with_( |
12579.2.6
by Tim Penhey
Move to module functions. |
684 |
SQL(recursive_blocked_query(self))).find( |
12579.2.3
by Tim Penhey
Change the all_blocked and all_deps to use recursive queries, rather than a recursive algorithm and many queries. |
685 |
Specification, |
686 |
Specification.id != self.id, |
|
12579.2.9
by Tim Penhey
Tweaks to make the tests pass. Also add explicit ordering. |
687 |
SQL('Specification.id in (select id from blocked)') |
688 |
).order_by(Specification.name, Specification.id) |
|
2344
by Canonical.com Patch Queue Manager
[not r=kiko] specification tracker |
689 |
|
3691.233.3
by Tim Penhey
interim checkin for specification branches, test fails at the moment |
690 |
# branches
|
3691.233.6
by James Henstridge
navigation support for spec branch link |
691 |
def getBranchLink(self, branch): |
692 |
return SpecificationBranch.selectOneBy( |
|
693 |
specificationID=self.id, branchID=branch.id) |
|
4785.3.1
by Jeroen Vermeulen
Removed whitespace before EOLs. |
694 |
|
8339.2.8
by Paul Hummer
Removed summary from ISpecificationBranch |
695 |
def linkBranch(self, branch, registrant): |
5543.8.6
by Tim Penhey
Adding notify events. |
696 |
branch_link = self.getBranchLink(branch) |
697 |
if branch_link is not None: |
|
698 |
return branch_link |
|
699 |
branch_link = SpecificationBranch( |
|
8339.2.8
by Paul Hummer
Removed summary from ISpecificationBranch |
700 |
specification=self, branch=branch, registrant=registrant) |
7876.3.6
by Francis J. Lacoste
Used ISQLObject from lazr.lifecycle |
701 |
notify(ObjectCreatedEvent(branch_link)) |
5543.8.6
by Tim Penhey
Adding notify events. |
702 |
return branch_link |
3691.233.3
by Tim Penhey
interim checkin for specification branches, test fails at the moment |
703 |
|
8698.10.9
by Paul Hummer
Responded to the review |
704 |
def unlinkBranch(self, branch, user): |
705 |
spec_branch = self.getBranchLink(branch) |
|
706 |
spec_branch.destroySelf() |
|
8698.10.3
by Paul Hummer
Integrated IHasLinkedBranches into the interfaces |
707 |
|
12588.3.4
by Tim Penhey
Define the filter_bugtasks_by_context interface. |
708 |
def getLinkedBugTasks(self, user): |
12588.3.16
by Tim Penhey
Merge devel. |
709 |
"""See `ISpecification`."""
|
12588.3.4
by Tim Penhey
Define the filter_bugtasks_by_context interface. |
710 |
params = BugTaskSearchParams(user=user, linked_blueprints=self.id) |
12588.3.16
by Tim Penhey
Merge devel. |
711 |
tasks = getUtility(IBugTaskSet).search(params) |
12588.3.21
by Tim Penhey
Remove branch specific bug task filtering, and add the possibility of titles to the generic link formatter. |
712 |
if self.distroseries is not None: |
713 |
context = self.distroseries |
|
714 |
elif self.distribution is not None: |
|
715 |
context = self.distribution |
|
716 |
elif self.productseries is not None: |
|
717 |
context = self.productseries |
|
718 |
else: |
|
719 |
context = self.product |
|
720 |
return filter_bugtasks_by_context(context, tasks) |
|
12588.3.4
by Tim Penhey
Define the filter_bugtasks_by_context interface. |
721 |
|
12579.3.6
by Tim Penhey
Add lotsa tests. |
722 |
def __repr__(self): |
12579.2.8
by Tim Penhey
Tidy up the query, add the id to the repr, and sort the results. |
723 |
return '<Specification %s %r for %r>' % ( |
724 |
self.id, self.name, self.target.name) |
|
12579.3.6
by Tim Penhey
Add lotsa tests. |
725 |
|
5543.8.10
by Tim Penhey
Updates following review. |
726 |
|
3847.2.2
by Mark Shuttleworth
Clean up blueprint pages |
727 |
class HasSpecificationsMixin: |
728 |
"""A mixin class that implements many of the common shortcut properties
|
|
729 |
for other classes that have specifications.
|
|
730 |
"""
|
|
731 |
||
5622.3.18
by Christian Robottom Reis
Implement another optimization for +roadmap by splitting it into its own view, and avoiding prejoining people when unnecessary (by adding a parameter to the specifications API). |
732 |
def specifications(self, sort=None, quantity=None, filter=None, |
733 |
prejoin_people=True): |
|
3847.2.2
by Mark Shuttleworth
Clean up blueprint pages |
734 |
"""See IHasSpecifications."""
|
735 |
# this should be implemented by the actual context class
|
|
736 |
raise NotImplementedError |
|
737 |
||
11474.3.1
by Robert Collins
Precache the is_person_valid status for specification assignments on Product and Distribution. |
738 |
def _specification_sort(self, sort): |
739 |
"""Return the storm sort order for 'specifications'.
|
|
11962.3.2
by Guilherme Salgado
Create IHasDrivers.personHasDriverRights(person), to be used on security adapters and ISpecification.proposeGoal(). |
740 |
|
11474.3.1
by Robert Collins
Precache the is_person_valid status for specification assignments on Product and Distribution. |
741 |
:param sort: As per HasSpecificationsMixin.specifications.
|
742 |
"""
|
|
743 |
# sort by priority descending, by default
|
|
744 |
if sort is None or sort == SpecificationSort.PRIORITY: |
|
745 |
return ( |
|
746 |
Desc(Specification.priority), Specification.definition_status, |
|
747 |
Specification.name) |
|
748 |
elif sort == SpecificationSort.DATE: |
|
749 |
return (Desc(Specification.datecreated), Specification.id) |
|
750 |
||
751 |
def _preload_specifications_people(self, query): |
|
752 |
"""Perform eager loading of people and their validity for query.
|
|
11962.3.2
by Guilherme Salgado
Create IHasDrivers.personHasDriverRights(person), to be used on security adapters and ISpecification.proposeGoal(). |
753 |
|
11474.3.1
by Robert Collins
Precache the is_person_valid status for specification assignments on Product and Distribution. |
754 |
:param query: a string query generated in the 'specifications'
|
755 |
method.
|
|
756 |
:return: A DecoratedResultSet with Person precaching setup.
|
|
757 |
"""
|
|
758 |
# Circular import.
|
|
759 |
from lp.registry.model.person import Person |
|
12498.3.2
by Curtis Hovey
Added NewSpecificationDefinitionStatus to define the set of enums that a new |
760 |
|
11515.3.1
by Robert Collins
Change the preloading strategy for specifications to do two queries : we were spending 16 seconds in storm. |
761 |
def cache_people(rows): |
762 |
# Find the people we need:
|
|
763 |
person_ids = set() |
|
764 |
for spec in rows: |
|
765 |
person_ids.add(spec.assigneeID) |
|
766 |
person_ids.add(spec.approverID) |
|
767 |
person_ids.add(spec.drafterID) |
|
768 |
person_ids.discard(None) |
|
769 |
if not person_ids: |
|
770 |
return
|
|
771 |
# Query those people
|
|
772 |
origin = [Person] |
|
773 |
columns = [Person] |
|
774 |
validity_info = Person._validity_queries() |
|
11474.3.2
by Robert Collins
Change the contract for Person._validity_queries to make callsites easier to read as suggested in review. |
775 |
origin.extend(validity_info["joins"]) |
776 |
columns.extend(validity_info["tables"]) |
|
777 |
decorators = validity_info["decorators"] |
|
11515.3.1
by Robert Collins
Change the preloading strategy for specifications to do two queries : we were spending 16 seconds in storm. |
778 |
personset = Store.of(self).using(*origin).find( |
779 |
tuple(columns), |
|
780 |
Person.id.is_in(person_ids), |
|
781 |
)
|
|
782 |
for row in personset: |
|
783 |
person = row[0] |
|
784 |
index = 1 |
|
785 |
for decorator in decorators: |
|
786 |
column = row[index] |
|
787 |
index += 1 |
|
788 |
decorator(person, column) |
|
12498.3.2
by Curtis Hovey
Added NewSpecificationDefinitionStatus to define the set of enums that a new |
789 |
|
11515.3.1
by Robert Collins
Change the preloading strategy for specifications to do two queries : we were spending 16 seconds in storm. |
790 |
results = Store.of(self).find( |
791 |
Specification, |
|
11474.3.1
by Robert Collins
Precache the is_person_valid status for specification assignments on Product and Distribution. |
792 |
SQL(query), |
793 |
)
|
|
11515.3.1
by Robert Collins
Change the preloading strategy for specifications to do two queries : we were spending 16 seconds in storm. |
794 |
return DecoratedResultSet(results, pre_iter_hook=cache_people) |
11474.3.1
by Robert Collins
Precache the is_person_valid status for specification assignments on Product and Distribution. |
795 |
|
3847.2.2
by Mark Shuttleworth
Clean up blueprint pages |
796 |
@property
|
3847.2.25
by Mark Shuttleworth
Test fixes and object interface compliance |
797 |
def valid_specifications(self): |
798 |
"""See IHasSpecifications."""
|
|
799 |
return self.specifications(filter=[SpecificationFilter.VALID]) |
|
800 |
||
801 |
@property
|
|
3847.2.2
by Mark Shuttleworth
Clean up blueprint pages |
802 |
def latest_specifications(self): |
803 |
"""See IHasSpecifications."""
|
|
804 |
return self.specifications(sort=SpecificationSort.DATE, quantity=5) |
|
805 |
||
806 |
@property
|
|
807 |
def latest_completed_specifications(self): |
|
808 |
"""See IHasSpecifications."""
|
|
809 |
return self.specifications(sort=SpecificationSort.DATE, quantity=5, |
|
11235.5.5
by Curtis Hovey
Hushed lint. |
810 |
filter=[SpecificationFilter.COMPLETE, ]) |
3847.2.2
by Mark Shuttleworth
Clean up blueprint pages |
811 |
|
812 |
@property
|
|
813 |
def specification_count(self): |
|
814 |
"""See IHasSpecifications."""
|
|
815 |
return self.specifications(filter=[SpecificationFilter.ALL]).count() |
|
816 |
||
817 |
||
818 |
class SpecificationSet(HasSpecificationsMixin): |
|
2344
by Canonical.com Patch Queue Manager
[not r=kiko] specification tracker |
819 |
"""The set of feature specifications."""
|
820 |
||
821 |
implements(ISpecificationSet) |
|
822 |
||
823 |
def __init__(self): |
|
824 |
"""See ISpecificationSet."""
|
|
2900.2.5
by Matthew Paul Thomas
fix self.titles in database/ |
825 |
self.title = 'Specifications registered in Launchpad' |
3691.14.3
by Mark Shuttleworth
Tweak layout of sprint and spec goal approval pagees |
826 |
self.displayname = 'All Specifications' |
2344
by Canonical.com Patch Queue Manager
[not r=kiko] specification tracker |
827 |
|
8805.7.3
by Edwin Grubbs
Optimized specification_status_counts. |
828 |
def getStatusCountsForProductSeries(self, product_series): |
829 |
"""See `ISpecificationSet`."""
|
|
830 |
cur = cursor() |
|
831 |
condition = """ |
|
832 |
(Specification.productseries = %s |
|
833 |
OR Milestone.productseries = %s) |
|
834 |
""" % sqlvalues(product_series, product_series) |
|
835 |
query = """ |
|
836 |
SELECT Specification.implementation_status, count(*)
|
|
837 |
FROM Specification
|
|
838 |
LEFT JOIN Milestone ON Specification.milestone = Milestone.id
|
|
839 |
WHERE
|
|
840 |
%s |
|
841 |
GROUP BY Specification.implementation_status
|
|
842 |
""" % condition |
|
843 |
cur.execute(query) |
|
844 |
return cur.fetchall() |
|
845 |
||
5616.1.1
by Aaron Bentley
Fix SpecificationSpec interface violations |
846 |
@property
|
847 |
def all_specifications(self): |
|
848 |
return Specification.select() |
|
849 |
||
2344
by Canonical.com Patch Queue Manager
[not r=kiko] specification tracker |
850 |
def __iter__(self): |
851 |
"""See ISpecificationSet."""
|
|
5616.1.1
by Aaron Bentley
Fix SpecificationSpec interface violations |
852 |
return iter(self.all_specifications) |
853 |
||
854 |
@property
|
|
855 |
def has_any_specifications(self): |
|
856 |
return self.all_specifications.count() != 0 |
|
2344
by Canonical.com Patch Queue Manager
[not r=kiko] specification tracker |
857 |
|
5622.3.18
by Christian Robottom Reis
Implement another optimization for +roadmap by splitting it into its own view, and avoiding prejoining people when unnecessary (by adding a parameter to the specifications API). |
858 |
def specifications(self, sort=None, quantity=None, filter=None, |
859 |
prejoin_people=True): |
|
3691.12.7
by Mark Shuttleworth
Allow for text-based searching of specs, fixing #3811 |
860 |
"""See IHasSpecifications."""
|
861 |
||
3691.12.18
by Mark Shuttleworth
Reviewer feedback |
862 |
# Make a new list of the filter, so that we do not mutate what we
|
863 |
# were passed as a filter
|
|
3691.12.7
by Mark Shuttleworth
Allow for text-based searching of specs, fixing #3811 |
864 |
if not filter: |
3691.12.18
by Mark Shuttleworth
Reviewer feedback |
865 |
# When filter is None or [] then we decide the default
|
3691.12.7
by Mark Shuttleworth
Allow for text-based searching of specs, fixing #3811 |
866 |
# which for a product is to show incomplete specs
|
867 |
filter = [SpecificationFilter.INCOMPLETE] |
|
868 |
||
869 |
# now look at the filter and fill in the unsaid bits
|
|
870 |
||
871 |
# defaults for completeness: if nothing is said about completeness
|
|
872 |
# then we want to show INCOMPLETE
|
|
873 |
completeness = False |
|
874 |
for option in [ |
|
875 |
SpecificationFilter.COMPLETE, |
|
876 |
SpecificationFilter.INCOMPLETE]: |
|
877 |
if option in filter: |
|
878 |
completeness = True |
|
879 |
if completeness is False: |
|
880 |
filter.append(SpecificationFilter.INCOMPLETE) |
|
3691.109.19
by Francis J. Lacoste
Make Specification implement IBugLinkTarget |
881 |
|
3691.12.7
by Mark Shuttleworth
Allow for text-based searching of specs, fixing #3811 |
882 |
# defaults for acceptance: in this case we have nothing to do
|
883 |
# because specs are not accepted/declined against a distro
|
|
884 |
||
885 |
# defaults for informationalness: we don't have to do anything
|
|
886 |
# because the default if nothing is said is ANY
|
|
887 |
||
888 |
# sort by priority descending, by default
|
|
889 |
if sort is None or sort == SpecificationSort.PRIORITY: |
|
5543.8.11
by Tim Penhey
Lint line length fixes. |
890 |
order = ['-priority', 'Specification.definition_status', |
891 |
'Specification.name'] |
|
3691.12.7
by Mark Shuttleworth
Allow for text-based searching of specs, fixing #3811 |
892 |
elif sort == SpecificationSort.DATE: |
3847.2.2
by Mark Shuttleworth
Clean up blueprint pages |
893 |
if SpecificationFilter.COMPLETE in filter: |
894 |
# if we are showing completed, we care about date completed
|
|
895 |
order = ['-Specification.date_completed', 'Specification.id'] |
|
896 |
else: |
|
897 |
# if not specially looking for complete, we care about date
|
|
898 |
# registered
|
|
899 |
order = ['-Specification.datecreated', 'Specification.id'] |
|
3691.12.7
by Mark Shuttleworth
Allow for text-based searching of specs, fixing #3811 |
900 |
|
901 |
# figure out what set of specifications we are interested in. for
|
|
902 |
# products, we need to be able to filter on the basis of:
|
|
903 |
#
|
|
904 |
# - completeness.
|
|
905 |
# - informational.
|
|
906 |
#
|
|
3691.109.27
by Francis J. Lacoste
Merge RF |
907 |
|
3691.73.15
by Mark Shuttleworth
Ensure that specs on inactive products are filtered from listings. |
908 |
# filter out specs on inactive products
|
909 |
base = """(Specification.product IS NULL OR |
|
910 |
Specification.product NOT IN
|
|
911 |
(SELECT Product.id FROM Product
|
|
912 |
WHERE Product.active IS FALSE))
|
|
913 |
"""
|
|
3691.12.7
by Mark Shuttleworth
Allow for text-based searching of specs, fixing #3811 |
914 |
query = base |
915 |
# look for informational specs
|
|
916 |
if SpecificationFilter.INFORMATIONAL in filter: |
|
4476.5.10
by Tom Berger
sql-quote db enum values, don't just rely on them being integers; also other changes after review |
917 |
query += (' AND Specification.implementation_status = %s ' % |
918 |
quote(SpecificationImplementationStatus.INFORMATIONAL.value)) |
|
3691.12.7
by Mark Shuttleworth
Allow for text-based searching of specs, fixing #3811 |
919 |
|
920 |
# filter based on completion. see the implementation of
|
|
921 |
# Specification.is_complete() for more details
|
|
11235.5.5
by Curtis Hovey
Hushed lint. |
922 |
completeness = Specification.completeness_clause |
3691.12.7
by Mark Shuttleworth
Allow for text-based searching of specs, fixing #3811 |
923 |
|
924 |
if SpecificationFilter.COMPLETE in filter: |
|
925 |
query += ' AND ( %s ) ' % completeness |
|
926 |
elif SpecificationFilter.INCOMPLETE in filter: |
|
927 |
query += ' AND NOT ( %s ) ' % completeness |
|
928 |
||
929 |
# Filter for validity. If we want valid specs only then we should
|
|
930 |
# exclude all OBSOLETE or SUPERSEDED specs
|
|
931 |
if SpecificationFilter.VALID in filter: |
|
6912.5.19
by Curtis Hovey
Revised XXX comment metadata to remove anonmalies from the XXX report. |
932 |
# XXX: kiko 2007-02-07: this is untested and was broken.
|
5543.8.11
by Tim Penhey
Lint line length fixes. |
933 |
query += ( |
934 |
' AND Specification.definition_status NOT IN ( %s, %s ) ' % |
|
4476.5.4
by Tom Berger
implementation and tests complete |
935 |
sqlvalues(SpecificationDefinitionStatus.OBSOLETE, |
4476.5.10
by Tom Berger
sql-quote db enum values, don't just rely on them being integers; also other changes after review |
936 |
SpecificationDefinitionStatus.SUPERSEDED)) |
3691.12.7
by Mark Shuttleworth
Allow for text-based searching of specs, fixing #3811 |
937 |
|
938 |
# ALL is the trump card
|
|
939 |
if SpecificationFilter.ALL in filter: |
|
940 |
query = base |
|
941 |
||
942 |
# Filter for specification text
|
|
943 |
for constraint in filter: |
|
3691.12.17
by Mark Shuttleworth
Reviewer feedback, and fix assumed globally unique names in name validation. |
944 |
if isinstance(constraint, basestring): |
945 |
# a string in the filter is a text search filter
|
|
3691.12.7
by Mark Shuttleworth
Allow for text-based searching of specs, fixing #3811 |
946 |
query += ' AND Specification.fti @@ ftq(%s) ' % quote( |
947 |
constraint) |
|
948 |
||
949 |
results = Specification.select(query, orderBy=order, limit=quantity) |
|
5622.3.18
by Christian Robottom Reis
Implement another optimization for +roadmap by splitting it into its own view, and avoiding prejoining people when unnecessary (by adding a parameter to the specifications API). |
950 |
if prejoin_people: |
951 |
results = results.prejoin(['assignee', 'approver', 'drafter']) |
|
952 |
return results |
|
3691.12.7
by Mark Shuttleworth
Allow for text-based searching of specs, fixing #3811 |
953 |
|
3194.1.6
by Diogo Matsubara
Fix https://launchpad.net/products/launchpad/+bug/3566 (Oops from registering a specification with an existing URL) |
954 |
def getByURL(self, url): |
955 |
"""See ISpecificationSet."""
|
|
956 |
specification = Specification.selectOneBy(specurl=url) |
|
957 |
if specification is None: |
|
3691.109.19
by Francis J. Lacoste
Make Specification implement IBugLinkTarget |
958 |
return None |
2920.2.2
by Diogo Matsubara
Fixes https://launchpad.net/products/launchpad/+bug/3436 (no sensible error message when adding a spec which has already been added.) and fixes https://launchpad.net/products/launchpad/+bug/4122 (The docstring of ISpecification is incorrect) |
959 |
return specification |
960 |
||
2396
by Canonical.com Patch Queue Manager
[r=spiv] launchpad support tracker |
961 |
@property
|
3847.2.5
by Mark Shuttleworth
Provide listings of upcoming sprints where relevant |
962 |
def coming_sprints(self): |
2445
by Canonical.com Patch Queue Manager
[trivial] db tables for sprints |
963 |
"""See ISpecificationSet."""
|
11962.3.22
by Guilherme Salgado
Make sure Sprint actually implements IHasSpecifications |
964 |
from lp.blueprints.model.sprint import Sprint |
3847.2.2
by Mark Shuttleworth
Clean up blueprint pages |
965 |
return Sprint.select("time_ends > 'NOW'", orderBy='time_starts', |
2445
by Canonical.com Patch Queue Manager
[trivial] db tables for sprints |
966 |
limit=5) |
967 |
||
4476.5.4
by Tom Berger
implementation and tests complete |
968 |
def new(self, name, title, specurl, summary, definition_status, |
2344
by Canonical.com Patch Queue Manager
[not r=kiko] specification tracker |
969 |
owner, approver=None, product=None, distribution=None, assignee=None, |
2736.1.23
by Mark Shuttleworth
�karma restructuring, and test fixes |
970 |
drafter=None, whiteboard=None, |
11962.3.11
by Guilherme Salgado
Remove getAllSpecifications and getValidSpecifications as these were created |
971 |
priority=SpecificationPriority.UNDEFINED): |
2344
by Canonical.com Patch Queue Manager
[not r=kiko] specification tracker |
972 |
"""See ISpecificationSet."""
|
12498.3.2
by Curtis Hovey
Added NewSpecificationDefinitionStatus to define the set of enums that a new |
973 |
# Adapt the NewSpecificationDefinitionStatus item to a
|
974 |
# SpecificationDefinitionStatus item.
|
|
12498.3.4
by Curtis Hovey
Make factory honour life cycle rules. |
975 |
status_name = definition_status.name |
976 |
status_names = NewSpecificationDefinitionStatus.items.mapping.keys() |
|
977 |
if status_name not in status_names: |
|
12498.3.2
by Curtis Hovey
Added NewSpecificationDefinitionStatus to define the set of enums that a new |
978 |
raise AssertionError( |
979 |
"definition_status must an item found in "
|
|
980 |
"NewSpecificationDefinitionStatus.") |
|
12498.3.4
by Curtis Hovey
Make factory honour life cycle rules. |
981 |
definition_status = SpecificationDefinitionStatus.items[status_name] |
3691.238.2
by Mark Shuttleworth
Revert spec change, will make that in my own branch. |
982 |
return Specification(name=name, title=title, specurl=specurl, |
4476.5.4
by Tom Berger
implementation and tests complete |
983 |
summary=summary, priority=priority, |
984 |
definition_status=definition_status, owner=owner, |
|
985 |
approver=approver, product=product, distribution=distribution, |
|
11962.3.11
by Guilherme Salgado
Remove getAllSpecifications and getValidSpecifications as these were created |
986 |
assignee=assignee, drafter=drafter, whiteboard=whiteboard) |
2344
by Canonical.com Patch Queue Manager
[not r=kiko] specification tracker |
987 |
|
5729.1.1
by Tom Berger
optimize the roadmap page |
988 |
def getDependencyDict(self, specifications): |
989 |
"""See `ISpecificationSet`."""
|
|
6527.1.4
by Brad Crittenden
Reverted extra change to getDependencyDict that caused problems. |
990 |
specification_ids = [spec.id for spec in specifications] |
991 |
||
992 |
if len(specification_ids) == 0: |
|
6527.1.2
by Brad Crittenden
Add ordering of results from getDependencyDict to sort by name and id also. |
993 |
return {} |
994 |
||
5821.16.5
by Francis J. Lacoste
Use Storm execute instead of cursor(). |
995 |
results = Store.of(specifications[0]).execute(""" |
5729.1.1
by Tom Berger
optimize the roadmap page |
996 |
SELECT SpecificationDependency.specification,
|
997 |
SpecificationDependency.dependency
|
|
998 |
FROM SpecificationDependency, Specification
|
|
999 |
WHERE SpecificationDependency.specification IN %s |
|
1000 |
AND SpecificationDependency.dependency = Specification.id
|
|
11235.5.5
by Curtis Hovey
Hushed lint. |
1001 |
ORDER BY Specification.priority DESC, Specification.name,
|
1002 |
Specification.id
|
|
5821.14.11
by James Henstridge
Make ISpecificationSet.getDependencyDict() work with result sets as well |
1003 |
""" % sqlvalues(specification_ids)).get_all() |
5729.1.1
by Tom Berger
optimize the roadmap page |
1004 |
|
1005 |
dependencies = {} |
|
1006 |
for spec_id, dep_id in results: |
|
1007 |
if spec_id not in dependencies: |
|
1008 |
dependencies[spec_id] = [] |
|
1009 |
dependency = Specification.get(dep_id) |
|
1010 |
dependencies[spec_id].append(dependency) |
|
1011 |
||
1012 |
return dependencies |
|
5729.1.2
by Tom Berger
changes after a review by curtis |
1013 |
|
1014 |
def get(self, spec_id): |
|
10409.5.69
by Curtis Hovey
Removed answers and blueprints from canonical.launchpad.__init__. |
1015 |
"""See lp.blueprints.interfaces.specification.ISpecificationSet."""
|
5729.1.2
by Tom Berger
changes after a review by curtis |
1016 |
return Specification.get(spec_id) |