Merge lp:~michael.nelson/launchpad/429318-copy-archives-timeout into lp:launchpad
- 429318-copy-archives-timeout
- Merge into devel
Status: | Merged |
---|---|
Approved by: | Julian Edwards |
Approved revision: | no longer in the source branch. |
Merged at revision: | not available |
Proposed branch: | lp:~michael.nelson/launchpad/429318-copy-archives-timeout |
Merge into: | lp:launchpad |
Diff against target: | None lines |
To merge this branch: | bzr merge lp:~michael.nelson/launchpad/429318-copy-archives-timeout |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Julian Edwards (community) | Approve | ||
Review via email: mp+11896@code.launchpad.net |
Commit message
Description of the change
Michael Nelson (michael.nelson) wrote : | # |
Julian Edwards (julian-edwards) wrote : | # |
review needs-fixing
Thanks for this fix Michael. I have the usual comments in-line.
On Wednesday 16 September 2009 16:55:13 Michael Nelson wrote:
> I'm not sure if selecting the SourcePackageRe
> I'm only using them to count etc. I could also use
> SourcePackagePu
> (2) there are already methods on IArchive for this (that do not enable
> me to do what I need here.)
I think it's fine - in fact the old way of doing it was pretty inefficient
even without the prejoin problem.
> I've had to use removeSecurityProxy to be able to get to the difference
> method of ResultSet - this is because the interface at
> zope.storm.
> _find_spec (which is accessed by the difference method).
>
> I'll create a bug for this and XXX it.
Ok, thanks.
>+ def getSourcePackag
Can you make this build_status please.
>+ """Return the releases for this archive.
>+
>+ :param buildstatus: If specified, only the distinct releases with
>+ builds in the specified build status will be returned.
>+ :return: A `ResultSet` of distinct `SourcePackageR
>+ archive.
>+ """
>
>+ def getSourcePackag
And here of course.
>+ """See `IArchive`."""
>+ store = getUtility(
Is using the main store deliberate? I would have thought
store = Store.of(self)
should suffice?
>+
>+ extra_exprs = []
>+ if buildstatus is not None:
>+ extra_exprs.
>+
>+ result_set = store.find(
PEP-8 - line feed after the open paren. please.
>+ Build.sourcepac
>+ Build.archive == self,
>+ *extra_exprs)
>+
>+ result_
>+ return result_set
>
> class ArchiveSet:
> implements(
>
>=== modified file 'lib/lp/
>--- lib/lp/
>+++ lib/lp/
>@@ -14,6 +14,7 @@
> from lp.registry.
> from lp.soyuz.
> from lp.soyuz.
>+from lp.soyuz.
> from lp.soyuz.
> from lp.soyuz.
> from lp.testing import TestCaseWithFactory
>@@ -243,5 +244,54 @@
> [u'1.0', u'0.5'], versions,
> "The latest version was not first.")
>
>+
>+class TestGetSourcePa
>+
>+ layer = LaunchpadZopele
>+
>+ def setUp(self):
>+ super(TestGetSo
>+ self.publisher = SoyuzTestPublis
>+ self.publisher.
>+
>+ # Create an archive wit...
Michael Nelson (michael.nelson) wrote : | # |
Julian Edwards wrote:
> Review: Needs Fixing
> review needs-fixing
>
> Thanks for this fix Michael. I have the usual comments in-line.
>
> On Wednesday 16 September 2009 16:55:13 Michael Nelson wrote:
>> I'm not sure if selecting the SourcePackageRe
>> I'm only using them to count etc. I could also use
>> SourcePackagePu
>> (2) there are already methods on IArchive for this (that do not enable
>> me to do what I need here.)
>
> I think it's fine - in fact the old way of doing it was pretty inefficient
> even without the prejoin problem.
Yes - I was only thinking of PPAs when I wrote it. So I'm all for the
new version, I just wasn't sure if selecting SourcePackageRe
the best way.
>
>> I've had to use removeSecurityProxy to be able to get to the difference
>> method of ResultSet - this is because the interface at
>> zope.storm.
>> _find_spec (which is accessed by the difference method).
>>
>> I'll create a bug for this and XXX it.
>
> Ok, thanks.
>
Added XXX with bug 431203.
>> + def getSourcePackag
>
> Can you make this build_status please.
>
Done.
>> + """Return the releases for this archive.
>> +
>> + :param buildstatus: If specified, only the distinct releases with
>> + builds in the specified build status will be returned.
>> + :return: A `ResultSet` of distinct `SourcePackageR
>> + archive.
>> + """
>>
>
>> + def getSourcePackag
>
> And here of course.
Yep.
>
>> + """See `IArchive`."""
>> + store = getUtility(
>
> Is using the main store deliberate? I would have thought
> store = Store.of(self)
> should suffice?
Done.
>
>> +
>> + extra_exprs = []
>> + if buildstatus is not None:
>> + extra_exprs.
>> +
>> + result_set = store.find(
>
> PEP-8 - line feed after the open paren. please.
Gar - sorry.
>
>> + Build.sourcepac
>> + Build.archive == self,
>> + *extra_exprs)
>> +
>> + result_
>> + return result_set
>>
>> class ArchiveSet:
>> implements(
>>
>> === modified file 'lib/lp/
>> --- lib/lp/
>> +++ lib/lp/
>> @@ -14,6 +14,7 @@
>> from lp.registry.
>> from lp.soyuz.
>> from lp.soyuz.
>> +from lp.soyuz.
>> from lp.soyuz.
>> from lp.soyuz.
>> from lp.testing import TestCaseWithFactory
>> @@ -243,5 +244,54 @@
>> ...
1 | === modified file 'lib/lp/soyuz/browser/archive.py' |
2 | --- lib/lp/soyuz/browser/archive.py 2009-09-16 15:38:07 +0000 |
3 | +++ lib/lp/soyuz/browser/archive.py 2009-09-17 07:13:40 +0000 |
4 | @@ -852,18 +852,18 @@ |
5 | """Return the number of building/waiting to build packages.""" |
6 | |
7 | sprs_building = self.context.getSourcePackageReleases( |
8 | - buildstatus = BuildStatus.BUILDING) |
9 | + build_status = BuildStatus.BUILDING) |
10 | sprs_waiting = self.context.getSourcePackageReleases( |
11 | - buildstatus = BuildStatus.NEEDSBUILD) |
12 | + build_status = BuildStatus.NEEDSBUILD) |
13 | |
14 | pkgs_building_count = sprs_building.count() |
15 | |
16 | # A package is not counted as waiting if it already has at least |
17 | # one build building. |
18 | - # Note: because neither the 'difference' method or the '_find_spec' |
19 | - # property are exposed via storm.zope.interfaces.IResultSet, |
20 | - # we need to remove the proxy for both results to use |
21 | - # the difference method. |
22 | + # XXX Michael Nelson 20090917 bug 431203. Because neither the |
23 | + # 'difference' method or the '_find_spec' property are exposed via |
24 | + # storm.zope.interfaces.IResultSet, we need to remove the proxy for |
25 | + # both results to use the difference method. |
26 | naked_sprs_waiting = removeSecurityProxy(sprs_waiting) |
27 | naked_sprs_building = removeSecurityProxy(sprs_building) |
28 | |
29 | |
30 | === modified file 'lib/lp/soyuz/doc/archive.txt' |
31 | --- lib/lp/soyuz/doc/archive.txt 2009-08-28 06:41:25 +0000 |
32 | +++ lib/lp/soyuz/doc/archive.txt 2009-09-17 07:12:09 +0000 |
33 | @@ -888,6 +888,25 @@ |
34 | 2 |
35 | |
36 | |
37 | +== Getting an Archive's source-package releases == |
38 | + |
39 | +The method getSourcePackageReleases() is provided to return the unique |
40 | +source-package releases for the archive. By default, all releases will |
41 | +be returned, but you can also ask for releases with builds in a certain |
42 | +state. |
43 | + |
44 | + >>> from lp.soyuz.interfaces.build import BuildStatus |
45 | + >>> releases = cprov_archive.getSourcePackageReleases( |
46 | + ... build_status=BuildStatus.FULLYBUILT) |
47 | + >>> for release in releases: |
48 | + ... print release.title |
49 | + mozilla-firefox - 0.9 |
50 | + pmount - 0.1-1 |
51 | + iceweasel - 1.0 |
52 | + |
53 | +For further details see the `TestGetSourcePackageReleases` unit-test. |
54 | + |
55 | + |
56 | == Sources available for deletions == |
57 | |
58 | 'getSourcesForDeletion' is the base for '+delete-packages' page on PPA |
59 | |
60 | === modified file 'lib/lp/soyuz/interfaces/archive.py' |
61 | --- lib/lp/soyuz/interfaces/archive.py 2009-09-16 15:22:15 +0000 |
62 | +++ lib/lp/soyuz/interfaces/archive.py 2009-09-17 07:12:09 +0000 |
63 | @@ -739,10 +739,10 @@ |
64 | :return: True if the person is allowed to upload the source package. |
65 | """ |
66 | |
67 | - def getSourcePackageReleases(buildstatus=None): |
68 | + def getSourcePackageReleases(build_status=None): |
69 | """Return the releases for this archive. |
70 | |
71 | - :param buildstatus: If specified, only the distinct releases with |
72 | + :param build_status: If specified, only the distinct releases with |
73 | builds in the specified build status will be returned. |
74 | :return: A `ResultSet` of distinct `SourcePackageReleases` for this |
75 | archive. |
76 | |
77 | === modified file 'lib/lp/soyuz/model/archive.py' |
78 | --- lib/lp/soyuz/model/archive.py 2009-09-16 15:22:15 +0000 |
79 | +++ lib/lp/soyuz/model/archive.py 2009-09-17 07:12:09 +0000 |
80 | @@ -1186,15 +1186,16 @@ |
81 | |
82 | return subscription |
83 | |
84 | - def getSourcePackageReleases(self, buildstatus=None): |
85 | + def getSourcePackageReleases(self, build_status=None): |
86 | """See `IArchive`.""" |
87 | - store = getUtility(IStoreSelector).get(MAIN_STORE, DEFAULT_FLAVOR) |
88 | + store = Store.of(self) |
89 | |
90 | extra_exprs = [] |
91 | - if buildstatus is not None: |
92 | - extra_exprs.append(Build.buildstate == buildstatus) |
93 | + if build_status is not None: |
94 | + extra_exprs.append(Build.buildstate == build_status) |
95 | |
96 | - result_set = store.find(SourcePackageRelease, |
97 | + result_set = store.find( |
98 | + SourcePackageRelease, |
99 | Build.sourcepackagereleaseID == SourcePackageRelease.id, |
100 | Build.archive == self, |
101 | *extra_exprs) |
102 | |
103 | === modified file 'lib/lp/soyuz/tests/test_archive.py' |
104 | --- lib/lp/soyuz/tests/test_archive.py 2009-09-16 15:22:15 +0000 |
105 | +++ lib/lp/soyuz/tests/test_archive.py 2009-09-17 07:12:09 +0000 |
106 | @@ -287,7 +287,7 @@ |
107 | build.buildstate = BuildStatus.NEEDSBUILD |
108 | |
109 | result = self.archive.getSourcePackageReleases( |
110 | - buildstatus=BuildStatus.NEEDSBUILD) |
111 | + build_status=BuildStatus.NEEDSBUILD) |
112 | |
113 | self.failUnlessEqual(1, result.count()) |
114 | self.failUnlessEqual( |
Julian Edwards (julian-edwards) wrote : | # |
merge approve
review approve
On Thursday 17 September 2009 08:18:08 Michael Nelson wrote:
> Yes - I was only thinking of PPAs when I wrote it. So I'm all for the
> new version, I just wasn't sure if selecting SourcePackageRe
> the best way.
Well I was thinking of the previous use of Python sets rather than distinct
SQL clauses :)
> Yes, I wonder whether it would even be worthwhile splitting the content
> class up using mixins to match the documentation. Also think it would be
> great to improve the documentation by moving lots of the unit tests
> there to actual python unittests, leaving the documentation much more
> readable. But I think that would take planning and time?
Yes, it's certainly something for a rainy day.
For me, doctests should contain basic instructions on how to use the content
class and its methods. Testing corner cases belong in a unit test, but I
don't think your new test is that.
Our problem is that Soyuz depends heavily on setting up a lot of data, so
doctests tend to be full of calls to the STP and factory, which muddies the
story, so I can see why you made it a unit test.
Ho hum.
> For the moment, I've added a brief section in archive.txt with a
> reference to the unit test. See what you think.
It's fine, thanks.
Land it!
Preview Diff
1 | === modified file 'lib/lp/soyuz/browser/archive.py' |
2 | --- lib/lp/soyuz/browser/archive.py 2009-09-11 17:55:23 +0000 |
3 | +++ lib/lp/soyuz/browser/archive.py 2009-09-16 15:38:07 +0000 |
4 | @@ -33,6 +33,7 @@ |
5 | from zope.component import getUtility |
6 | from zope.formlib import form |
7 | from zope.interface import implements, Interface |
8 | +from zope.security.proxy import removeSecurityProxy |
9 | from zope.schema import Choice, List, TextLine |
10 | from zope.schema.interfaces import IContextSourceBinder |
11 | from zope.schema.vocabulary import SimpleVocabulary, SimpleTerm |
12 | @@ -850,23 +851,24 @@ |
13 | def num_pkgs_building(self): |
14 | """Return the number of building/waiting to build packages.""" |
15 | |
16 | - building = getUtility(IBuildSet).getBuildsForArchive( |
17 | - self.context, status=BuildStatus.BUILDING) |
18 | - needs_build = getUtility(IBuildSet).getBuildsForArchive( |
19 | - self.context, status=BuildStatus.NEEDSBUILD) |
20 | - |
21 | - # Create a set of all source package releases that have builds |
22 | - # waiting to build, as well as a set of those with building builds. |
23 | - needs_build_set = set( |
24 | - build.sourcepackagerelease for build in needs_build) |
25 | - |
26 | - building_set = set( |
27 | - build.sourcepackagerelease for build in building) |
28 | + sprs_building = self.context.getSourcePackageReleases( |
29 | + buildstatus = BuildStatus.BUILDING) |
30 | + sprs_waiting = self.context.getSourcePackageReleases( |
31 | + buildstatus = BuildStatus.NEEDSBUILD) |
32 | + |
33 | + pkgs_building_count = sprs_building.count() |
34 | |
35 | # A package is not counted as waiting if it already has at least |
36 | # one build building. |
37 | - pkgs_building_count = len(building_set) |
38 | - pkgs_waiting_count = len(needs_build_set.difference(building_set)) |
39 | + # Note: because neither the 'difference' method or the '_find_spec' |
40 | + # property are exposed via storm.zope.interfaces.IResultSet, |
41 | + # we need to remove the proxy for both results to use |
42 | + # the difference method. |
43 | + naked_sprs_waiting = removeSecurityProxy(sprs_waiting) |
44 | + naked_sprs_building = removeSecurityProxy(sprs_building) |
45 | + |
46 | + pkgs_waiting_count = naked_sprs_waiting.difference( |
47 | + naked_sprs_building).count() |
48 | |
49 | # The total is just used for conditionals in the template. |
50 | return { |
51 | |
52 | === modified file 'lib/lp/soyuz/interfaces/archive.py' |
53 | --- lib/lp/soyuz/interfaces/archive.py 2009-09-02 21:28:11 +0000 |
54 | +++ lib/lp/soyuz/interfaces/archive.py 2009-09-16 15:22:15 +0000 |
55 | @@ -739,6 +739,14 @@ |
56 | :return: True if the person is allowed to upload the source package. |
57 | """ |
58 | |
59 | + def getSourcePackageReleases(buildstatus=None): |
60 | + """Return the releases for this archive. |
61 | + |
62 | + :param buildstatus: If specified, only the distinct releases with |
63 | + builds in the specified build status will be returned. |
64 | + :return: A `ResultSet` of distinct `SourcePackageReleases` for this |
65 | + archive. |
66 | + """ |
67 | |
68 | class IArchiveView(IHasBuildRecords): |
69 | """Archive interface for operations restricted by view privilege.""" |
70 | |
71 | === modified file 'lib/lp/soyuz/model/archive.py' |
72 | --- lib/lp/soyuz/model/archive.py 2009-09-10 12:59:56 +0000 |
73 | +++ lib/lp/soyuz/model/archive.py 2009-09-16 15:22:15 +0000 |
74 | @@ -1186,6 +1186,21 @@ |
75 | |
76 | return subscription |
77 | |
78 | + def getSourcePackageReleases(self, buildstatus=None): |
79 | + """See `IArchive`.""" |
80 | + store = getUtility(IStoreSelector).get(MAIN_STORE, DEFAULT_FLAVOR) |
81 | + |
82 | + extra_exprs = [] |
83 | + if buildstatus is not None: |
84 | + extra_exprs.append(Build.buildstate == buildstatus) |
85 | + |
86 | + result_set = store.find(SourcePackageRelease, |
87 | + Build.sourcepackagereleaseID == SourcePackageRelease.id, |
88 | + Build.archive == self, |
89 | + *extra_exprs) |
90 | + |
91 | + result_set.config(distinct=True).order_by(SourcePackageRelease.id) |
92 | + return result_set |
93 | |
94 | class ArchiveSet: |
95 | implements(IArchiveSet) |
96 | |
97 | === modified file 'lib/lp/soyuz/tests/test_archive.py' |
98 | --- lib/lp/soyuz/tests/test_archive.py 2009-07-27 14:45:01 +0000 |
99 | +++ lib/lp/soyuz/tests/test_archive.py 2009-09-16 15:22:15 +0000 |
100 | @@ -14,6 +14,7 @@ |
101 | from lp.registry.interfaces.distribution import IDistributionSet |
102 | from lp.soyuz.interfaces.archive import IArchiveSet |
103 | from lp.soyuz.interfaces.binarypackagerelease import BinaryPackageFormat |
104 | +from lp.soyuz.interfaces.build import BuildStatus |
105 | from lp.soyuz.interfaces.publishing import PackagePublishingStatus |
106 | from lp.soyuz.tests.test_publishing import SoyuzTestPublisher |
107 | from lp.testing import TestCaseWithFactory |
108 | @@ -243,5 +244,54 @@ |
109 | [u'1.0', u'0.5'], versions, |
110 | "The latest version was not first.") |
111 | |
112 | + |
113 | +class TestGetSourcePackageReleases(TestCaseWithFactory): |
114 | + |
115 | + layer = LaunchpadZopelessLayer |
116 | + |
117 | + def setUp(self): |
118 | + super(TestGetSourcePackageReleases, self).setUp() |
119 | + self.publisher = SoyuzTestPublisher() |
120 | + self.publisher.prepareBreezyAutotest() |
121 | + |
122 | + # Create an archive with some published binaries. |
123 | + self.archive = self.factory.makeArchive() |
124 | + binaries_foo = self.publisher.getPubBinaries( |
125 | + archive=self.archive, binaryname="foo-bin") |
126 | + binaries_bar = self.publisher.getPubBinaries( |
127 | + archive=self.archive, binaryname="bar-bin") |
128 | + |
129 | + # Collect the builds for reference. |
130 | + self.builds_foo = [ |
131 | + binary.binarypackagerelease.build for binary in binaries_foo] |
132 | + self.builds_bar = [ |
133 | + binary.binarypackagerelease.build for binary in binaries_bar] |
134 | + |
135 | + # Collect the source package releases for reference. |
136 | + self.sourcepackagereleases = [ |
137 | + self.builds_foo[0].sourcepackagerelease, |
138 | + self.builds_bar[0].sourcepackagerelease, |
139 | + ] |
140 | + |
141 | + def test_getSourcePackageReleases_with_no_params(self): |
142 | + # With no params all source package releases are returned. |
143 | + sprs = self.archive.getSourcePackageReleases() |
144 | + |
145 | + self.assertContentEqual(self.sourcepackagereleases, sprs) |
146 | + |
147 | + def test_getSourcePackageReleases_with_buildstatus(self): |
148 | + # Results are filtered by the specified buildstatus. |
149 | + |
150 | + # Set the builds for one of the sprs to needs build. |
151 | + for build in self.builds_foo: |
152 | + build.buildstate = BuildStatus.NEEDSBUILD |
153 | + |
154 | + result = self.archive.getSourcePackageReleases( |
155 | + buildstatus=BuildStatus.NEEDSBUILD) |
156 | + |
157 | + self.failUnlessEqual(1, result.count()) |
158 | + self.failUnlessEqual( |
159 | + self.sourcepackagereleases[0], result[0]) |
160 | + |
161 | def test_suite(): |
162 | return unittest.TestLoader().loadTestsFromName(__name__) |
= Summary =
This branch aims to fix bug 429318 by replacing the code used for num_pkgs_ building with storm-code, so that (1) the unused
ArchiveView.
prefetch data is not included in the result, and (2) the builds do not
need to be iterated.
== Proposed fix ==
See the description on bug 429318.
== Pre-implementation notes ==
I'm not sure if selecting the SourcePackageRe leases is the right thing - blishingHistory - but (1) it would be an extra join, and
I'm only using them to count etc. I could also use
SourcePackagePu
(2) there are already methods on IArchive for this (that do not enable
me to do what I need here.)
== Implementation details ==
I've had to use removeSecurityProxy to be able to get to the difference interfaces. IResultSet does not include difference, or
method of ResultSet - this is because the interface at
zope.storm.
_find_spec (which is accessed by the difference method).
I'll create a bug for this and XXX it.
== Tests ==
bin/test -vv -t archive-views.txt -t TestGetSourcePa ckageReleases
== Demo and Q/A ==
No UI change.
To Q/A: /edge.launchpad .net/ubuntu/ +archive/ test-rebuild- 20090909/ +index
https:/
(currently times out).
= Launchpad lint =
Checking for conflicts. and issues in doctests and templates.
Running jslint, xmllint, pyflakes, and pylint.
Using normal rules.
Linting changed files: soyuz/tests/ test_archive. py soyuz/interface s/archive. py soyuz/model/ archive. py soyuz/browser/ archive. py
lib/lp/
lib/lp/
lib/lp/
lib/lp/
== Pylint notices ==
lib/lp/ soyuz/interface s/archive. py declarations' (No module fields' (No module named
38: [F0401] Unable to import 'lazr.enum' (No module named enum)
51: [F0401] Unable to import 'lazr.restful.
named restful)
57: [F0401] Unable to import 'lazr.restful.
restful)
lib/lp/ soyuz/model/ archive. py .event' (No module named
14: [F0401] Unable to import 'lazr.lifecycle
lifecycle)
--
Michael