Merge lp:~abentley/launchpad/product-specifications-storm into lp:launchpad

Proposed by Aaron Bentley on 2012-10-16
Status: Merged
Merged at revision: 16167
Proposed branch: lp:~abentley/launchpad/product-specifications-storm
Merge into: lp:launchpad
Prerequisite: lp:~abentley/launchpad/product-specifications-tests
Diff against target: 107 lines (+9/-44)
2 files modified
lib/lp/blueprints/model/specification.py (+4/-2)
lib/lp/registry/model/product.py (+5/-42)
To merge this branch: bzr merge lp:~abentley/launchpad/product-specifications-storm
Reviewer Review Type Date Requested Status
Deryck Hodge (community) 2012-10-16 Approve on 2012-10-17
Review via email: mp+130002@code.launchpad.net

Commit Message

Reimplement Product.specifications.

Description of the Change

= Summary =
Make it easy to implement privacy for Product.specifications.

== Proposed fix ==
Reimplement Product.specifications in terms of get_specification_filters.

== Pre-implementation notes ==
None.

== LOC Rationale ==
Part of Private Products.

== Implementation details ==
None

== Tests ==
bin/test test_product.py -t TestSpecifications

== Demo and Q/A ==
None

= Launchpad lint =

Checking for conflicts and issues in changed files.

Linting changed files:
  lib/lp/testing/factory.py
  lib/lp/blueprints/model/specification.py
  lib/lp/blueprints/model/sprint.py
  lib/lp/registry/model/product.py
  lib/lp/registry/model/person.py
  lib/lp/registry/tests/test_person.py
  lib/lp/registry/tests/test_product.py

To post a comment you must log in.
Deryck Hodge (deryck) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/lp/blueprints/model/specification.py'
2--- lib/lp/blueprints/model/specification.py 2012-10-16 18:11:17 +0000
3+++ lib/lp/blueprints/model/specification.py 2012-10-17 14:46:55 +0000
4@@ -977,7 +977,7 @@
5 elif sort == SpecificationSort.DATE:
6 return (Desc(Specification.datecreated), Specification.id)
7
8- def _preload_specifications_people(self, query):
9+ def _preload_specifications_people(self, clauses):
10 """Perform eager loading of people and their validity for query.
11
12 :param query: a string query generated in the 'specifications'
13@@ -986,6 +986,8 @@
14 """
15 # Circular import.
16 from lp.registry.model.person import Person
17+ if isinstance(clauses, basestring):
18+ clauses = [SQL(clauses)]
19
20 def cache_people(rows):
21 # Find the people we need:
22@@ -1018,7 +1020,7 @@
23
24 results = Store.of(self).find(
25 Specification,
26- SQL(query),
27+ *clauses
28 )
29 return DecoratedResultSet(results, pre_iter_hook=cache_people)
30
31
32=== modified file 'lib/lp/registry/model/product.py'
33--- lib/lp/registry/model/product.py 2012-10-16 14:28:22 +0000
34+++ lib/lp/registry/model/product.py 2012-10-17 14:46:55 +0000
35@@ -92,11 +92,10 @@
36 )
37 from lp.app.model.launchpad import InformationTypeMixin
38 from lp.blueprints.enums import (
39- SpecificationDefinitionStatus,
40 SpecificationFilter,
41- SpecificationImplementationStatus,
42 )
43 from lp.blueprints.model.specification import (
44+ get_specification_filters,
45 HasSpecificationsMixin,
46 Specification,
47 SPECIFICATION_POLICY_ALLOWED_TYPES,
48@@ -193,7 +192,6 @@
49 )
50 from lp.services.database.lpstorm import IStore
51 from lp.services.database.sqlbase import (
52- quote,
53 SQLBase,
54 sqlvalues,
55 )
56@@ -1357,47 +1355,12 @@
57 # - completeness.
58 # - informational.
59 #
60- base = 'Specification.product = %s' % self.id
61- query = base
62- # look for informational specs
63- if SpecificationFilter.INFORMATIONAL in filter:
64- query += (' AND Specification.implementation_status = %s' %
65- quote(SpecificationImplementationStatus.INFORMATIONAL))
66-
67- # filter based on completion. see the implementation of
68- # Specification.is_complete() for more details
69- completeness = Specification.completeness_clause
70-
71- if SpecificationFilter.COMPLETE in filter:
72- query += ' AND ( %s ) ' % completeness
73- elif SpecificationFilter.INCOMPLETE in filter:
74- query += ' AND NOT ( %s ) ' % completeness
75-
76- # Filter for validity. If we want valid specs only then we should
77- # exclude all OBSOLETE or SUPERSEDED specs
78- if SpecificationFilter.VALID in filter:
79- query += (' AND Specification.definition_status NOT IN '
80- '( %s, %s ) ' % sqlvalues(
81- SpecificationDefinitionStatus.OBSOLETE,
82- SpecificationDefinitionStatus.SUPERSEDED))
83-
84- # ALL is the trump card
85- if SpecificationFilter.ALL in filter:
86- query = base
87-
88- # Filter for specification text
89- for constraint in filter:
90- if isinstance(constraint, basestring):
91- # a string in the filter is a text search filter
92- query += ' AND Specification.fti @@ ftq(%s) ' % quote(
93- constraint)
94-
95+ clauses = [Specification.product == self]
96+ clauses.extend(get_specification_filters(filter))
97 if prejoin_people:
98- results = self._preload_specifications_people(query)
99+ results = self._preload_specifications_people(clauses)
100 else:
101- results = Store.of(self).find(
102- Specification,
103- SQL(query))
104+ results = Store.of(self).find(Specification, *clauses)
105 results.order_by(order)
106 if quantity is not None:
107 results = results[:quantity]