Merge lp:~henninge/launchpad/devel-710591-sharing-info-groundwork-0 into lp:launchpad

Proposed by Henning Eggers
Status: Merged
Approved by: Henning Eggers
Approved revision: no longer in the source branch.
Merged at revision: 12320
Proposed branch: lp:~henninge/launchpad/devel-710591-sharing-info-groundwork-0
Merge into: lp:launchpad
Diff against target: 504 lines (+487/-0)
3 files modified
.bzrignore (+1/-0)
lib/lp/translations/utilities/tests/test_translation_sharing_info.py (+310/-0)
lib/lp/translations/utilities/translationsharinginfo.py (+176/-0)
To merge this branch: bzr merge lp:~henninge/launchpad/devel-710591-sharing-info-groundwork-0
Reviewer Review Type Date Requested Status
Deryck Hodge (community) code Approve
Review via email: mp+48416@code.launchpad.net

Commit message

[r=deryck][ui=none][no-qa] Provide translation sharing information.

Description of the change

= Summary =

For the current feature work but also to fix bug 710591, the information
about sharing template on the other side must be easily available. This
branch provides this informatioon through a couple of functions.

== Proposed fix ==

Provide functions that list information about the current sharing
information on the other side. "Other side" is an upstream product series
for a source package and an Ubuntu sourcepackage for a product series.

Translation sharing only happens when a template of the same name as the one
on this side exists but before that a packaging link is required. These
functions list both the content of the packaging link and any templates on
the other side, if any.

== Pre-implementation notes ==

I did not really consult anybody about this particular module although the
necessity for this functionality has been discussed.

== Implementation details ==

I had first considered creating an adapter on productseries and source
package but decided against it and chose the simpler approach. Since there
is no state information or anything, functions do the job just as well.

The find_* functions are meant to be internal functions that return Storm
ResultSets and the get_* and has_* functions make use of this. It may still
make sense to put the find_* functions into __all__, though.

== Tests ==

bin/test -vvcm lp.translations.utilities.tests.translationsharinginfo

== Demo and Q/A ==

None.

= Launchpad lint =

Checking for conflicts and issues in changed files.

Linting changed files:
  .bzrignore
  lib/lp/translations/utilities/translationsharinginfo.py
  lib/lp/translations/utilities/tests/test_translation_sharing_info.py

To post a comment you must log in.
Revision history for this message
Deryck Hodge (deryck) wrote :

Henning,

This looks good. Thanks for taking the time to jump on Mumble and talk this over with me. I really like the test, and appreciate you being thorough in covering all the various cases.

Some minor cleanups/clarifications could help:

 * Remove the pylint disable-msg declaration
 * Be consistent about comments on the test methods
    (Just so it's easy to scan the test and work out
     what is being tested)
 * Add clarify comments to the main module (docstring perhaps?)

This last one is because it was not clear to me where I would use these methods, or why I should prefer one over the other. So some documentation to clarify would help. And also prevent people importing all these functions and doing:

    if has_upstream_template():
        info = get_upstream_sharing_info()

To help prevent people firing off more queries then they they realize.

Thanks, again!

review: Approve (code)
Revision history for this message
Henning Eggers (henninge) wrote :

Thanks for the review. Please find my added comments below.

1=== modified file 'lib/lp/translations/utilities/tests/test_translation_sharing_info.py'
2--- lib/lp/translations/utilities/tests/test_translation_sharing_info.py 2011-02-03 01:13:32 +0000
3+++ lib/lp/translations/utilities/tests/test_translation_sharing_info.py 2011-02-03 18:18:29 +0000
4@@ -1,8 +1,6 @@
5 # Copyright 2009 Canonical Ltd. This software is licensed under the
6 # GNU Affero General Public License version 3 (see the file LICENSE).
7
8-# pylint: disable-msg=C0102
9-
10 __metaclass__ = type
11
12 from canonical.testing.layers import ZopelessDatabaseLayer
13@@ -219,6 +217,8 @@
14 templatename=different_templatename))
15
16 def test_has_upstream_template_no_productseries(self):
17+ # Without an upstream project, no upstream templates won't be
18+ # available either.
19 distroseries, sourcepackagename = self._makeSourcePackage()
20 templatename = self.factory.getUniqueString()
21
22@@ -227,6 +227,7 @@
23 distroseries, sourcepackagename, templatename))
24
25 def test_has_upstream_template_no_template(self):
26+ # No template exists on the upstream project.
27 distroseries, sourcepackagename = self._makeSourcePackage()
28 productseries = self._makeUpstreamProductSeries(
29 distroseries, sourcepackagename)
30@@ -237,6 +238,8 @@
31 distroseries, sourcepackagename, templatename))
32
33 def test_has_upstream_template_one_template(self):
34+ # There is one template on the upstream project that matches the
35+ # name.
36 distroseries, sourcepackagename = self._makeSourcePackage()
37 productseries = self._makeUpstreamProductSeries(
38 distroseries, sourcepackagename)
39@@ -249,6 +252,8 @@
40 distroseries, sourcepackagename, templatename))
41
42 def test_has_upstream_template_one_template_wrong_name(self):
43+ # There is one template on the upstream project but it matches not
44+ # the requested name.
45 distroseries, sourcepackagename = self._makeSourcePackage()
46 productseries = self._makeUpstreamProductSeries(
47 distroseries, sourcepackagename)
48@@ -260,12 +265,15 @@
49 distroseries, sourcepackagename, different_templatename))
50
51 def test_has_ubuntu_template_no_sourcepackage(self):
52+ # There is no Ubuntu source package, so no Ubuntu template can be
53+ # found.
54 productseries = self.factory.makeProductSeries()
55 templatename = self.factory.getUniqueString()
56
57 self.assertFalse(has_ubuntu_template(productseries, templatename))
58
59 def test_has_ubuntu_template_no_template(self):
60+ # The Ubuntu source package has no template.
61 distroseries, sourcepackagename = self._makeSourcePackage()
62 productseries = self._makeUpstreamProductSeries(
63 distroseries, sourcepackagename)
64@@ -274,6 +282,8 @@
65 self.assertFalse(has_ubuntu_template(productseries, templatename))
66
67 def test_has_ubuntu_template_one_template(self):
68+ # There is one template on the Ubuntu source package that matches
69+ # the name.
70 distroseries, sourcepackagename = self._makeSourcePackage()
71 productseries = self._makeUpstreamProductSeries(
72 distroseries, sourcepackagename)
73@@ -285,6 +295,8 @@
74 self.assertTrue(has_ubuntu_template(productseries, templatename))
75
76 def test_has_ubuntu_template_one_template_wrong_name(self):
77+ # There is one template on the Ubuntu source package but it matches
78+ # not the requested name.
79 distroseries, sourcepackagename = self._makeSourcePackage()
80 productseries = self._makeUpstreamProductSeries(
81 distroseries, sourcepackagename)
82
83=== modified file 'lib/lp/translations/utilities/translationsharinginfo.py'
84--- lib/lp/translations/utilities/translationsharinginfo.py 2011-02-03 01:13:32 +0000
85+++ lib/lp/translations/utilities/translationsharinginfo.py 2011-02-03 18:35:28 +0000
86@@ -1,7 +1,23 @@
87 # Copyright 2011 Canonical Ltd. This software is licensed under the
88 # GNU Affero General Public License version 3 (see the file LICENSE).
89
90-"""Provide sharing information."""
91+"""Provide sharing information.
92+
93+This module defines two different types of functions that provide
94+information about what sharing options are available on the other side of a
95+packaging link. Since they perform similar but slightly different complex
96+database queries combining them in any way will usually be wrong.
97+
98+get_ubuntu_sharing_info and get_upstream_sharing_info will give you
99+information about the source package or productseries respectively,
100+combined with possibly available templates. You can restrict the search
101+by specifying a template name.
102+
103+has_ubuntu_template and has_upstream_template make a direct search for a
104+template of the given name on the other side. They do not search for
105+source package or productseries but will only return True if an actual
106+template exists. That is a significant difference to the get_* functions.
107+"""
108
109 __metaclass__ = type
110 __all__ = [

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file '.bzrignore'
2--- .bzrignore 2011-01-16 19:04:25 +0000
3+++ .bzrignore 2011-02-03 18:46:24 +0000
4@@ -76,3 +76,4 @@
5 librarian.log
6 configs/testrunner_*
7 configs/testrunner-appserver_*
8+.idea
9
10=== added file 'lib/lp/translations/utilities/tests/test_translation_sharing_info.py'
11--- lib/lp/translations/utilities/tests/test_translation_sharing_info.py 1970-01-01 00:00:00 +0000
12+++ lib/lp/translations/utilities/tests/test_translation_sharing_info.py 2011-02-03 18:46:24 +0000
13@@ -0,0 +1,310 @@
14+# Copyright 2009 Canonical Ltd. This software is licensed under the
15+# GNU Affero General Public License version 3 (see the file LICENSE).
16+
17+__metaclass__ = type
18+
19+from canonical.testing.layers import ZopelessDatabaseLayer
20+from lp.testing import TestCaseWithFactory
21+from lp.translations.utilities.translationsharinginfo import (
22+ get_ubuntu_sharing_info,
23+ get_upstream_sharing_info,
24+ has_ubuntu_template,
25+ has_upstream_template,
26+ )
27+
28+
29+class TestTranslationSharingInfo(TestCaseWithFactory):
30+ """Tests for `get_upstream_sharing_info` and `get_ubuntu_sharing_info`"""
31+
32+ layer = ZopelessDatabaseLayer
33+
34+ def _makeSourcePackage(self):
35+ """Create a distroseries and a sourcepackagename."""
36+ distroseries = self.factory.makeUbuntuDistroSeries()
37+ sourcepackagename = self.factory.makeSourcePackageName()
38+ return (distroseries, sourcepackagename)
39+
40+ def _makeUpstreamProductSeries(self, distroseries, sourcepackagename):
41+ """Create a product series and link it to the source package."""
42+ productseries = self.factory.makeProductSeries()
43+ sourcepackage = self.factory.makeSourcePackage(
44+ sourcepackagename, distroseries)
45+ owner = self.factory.makePerson()
46+ sourcepackage.setPackaging(productseries, owner)
47+ return productseries
48+
49+ def test_no_upstream(self):
50+ # With no upstream the sharing information on a source package will
51+ # be empty.
52+ distroseries, sourcepackagename = self._makeSourcePackage()
53+ self.assertEquals(
54+ [],
55+ get_upstream_sharing_info(
56+ distroseries=distroseries,
57+ sourcepackagename=sourcepackagename))
58+
59+ def test_no_upstream_with_name(self):
60+ # With no upstream the sharing information on a source package will
61+ # be empty, even when searching for a specific template name.
62+ distroseries, sourcepackagename = self._makeSourcePackage()
63+ templatename = self.factory.getUniqueString()
64+ self.assertEquals(
65+ [],
66+ get_upstream_sharing_info(
67+ distroseries=distroseries,
68+ sourcepackagename=sourcepackagename,
69+ templatename=templatename))
70+
71+ def test_upstream_no_template(self):
72+ # With an upstream without a template the sharing information on a
73+ # source package will be empty.
74+ distroseries, sourcepackagename = self._makeSourcePackage()
75+ productseries = self._makeUpstreamProductSeries(
76+ distroseries, sourcepackagename)
77+ self.assertEquals(
78+ [(productseries, None)],
79+ get_upstream_sharing_info(
80+ distroseries=distroseries,
81+ sourcepackagename=sourcepackagename))
82+
83+ def test_upstream_no_template_with_name(self):
84+ # With an upstream without a template the sharing information on a
85+ # source package will be empty, even when searching for a specific
86+ # template name.
87+ distroseries, sourcepackagename = self._makeSourcePackage()
88+ productseries = self._makeUpstreamProductSeries(
89+ distroseries, sourcepackagename)
90+ templatename = self.factory.getUniqueString()
91+ self.assertEquals(
92+ [(productseries, None)],
93+ get_upstream_sharing_info(
94+ distroseries=distroseries,
95+ sourcepackagename=sourcepackagename,
96+ templatename=templatename))
97+
98+ def test_upstream_one_template(self):
99+ # With an upstream template the sharing information on a
100+ # source package will return that.
101+ distroseries, sourcepackagename = self._makeSourcePackage()
102+ productseries = self._makeUpstreamProductSeries(
103+ distroseries, sourcepackagename)
104+ potemplate = self.factory.makePOTemplate(productseries=productseries)
105+ self.assertEquals(
106+ [(productseries, potemplate)],
107+ get_upstream_sharing_info(
108+ distroseries=distroseries,
109+ sourcepackagename=sourcepackagename))
110+
111+ def test_upstream_one_template_with_name(self):
112+ # With an upstream template the sharing information on a
113+ # source package will return that, even when searching for a
114+ # specific template name.
115+ distroseries, sourcepackagename = self._makeSourcePackage()
116+ productseries = self._makeUpstreamProductSeries(
117+ distroseries, sourcepackagename)
118+ templatename = self.factory.getUniqueString()
119+ potemplate = self.factory.makePOTemplate(
120+ productseries=productseries, name=templatename)
121+ self.assertEquals(
122+ [(productseries, potemplate)],
123+ get_upstream_sharing_info(
124+ distroseries=distroseries,
125+ sourcepackagename=sourcepackagename,
126+ templatename=templatename))
127+
128+ def test_upstream_one_template_with_different_name(self):
129+ # With an upstream template the sharing information on a
130+ # source package will be empty if a different name is queried.
131+ distroseries, sourcepackagename = self._makeSourcePackage()
132+ productseries = self._makeUpstreamProductSeries(
133+ distroseries, sourcepackagename)
134+ templatename = self.factory.getUniqueString()
135+ self.factory.makePOTemplate(
136+ productseries=productseries, name=templatename)
137+ different_templatename = self.factory.getUniqueString()
138+ self.assertEquals(
139+ [(productseries, None)],
140+ get_upstream_sharing_info(
141+ distroseries=distroseries,
142+ sourcepackagename=sourcepackagename,
143+ templatename=different_templatename))
144+
145+ def test_no_ubuntu(self):
146+ # With no sourcepackage the sharing information on a source package
147+ # will be empty.
148+ productseries = self.factory.makeProductSeries()
149+ self.assertEquals(
150+ [],
151+ get_ubuntu_sharing_info(productseries=productseries))
152+
153+ def test_no_ubuntu_with_name(self):
154+ # With no sourcepackage the sharing information on a source package
155+ # will be empty, even when searching for a specific template name.
156+ productseries = self.factory.makeProductSeries()
157+ templatename = self.factory.getUniqueString()
158+ self.assertEquals(
159+ [],
160+ get_ubuntu_sharing_info(
161+ productseries=productseries, templatename=templatename))
162+
163+ def test_ubuntu_no_template(self):
164+ # With a sourcepackage without a template the sharing information
165+ # on a productseries will be empty.
166+ distroseries, sourcepackagename = self._makeSourcePackage()
167+ productseries = self._makeUpstreamProductSeries(
168+ distroseries, sourcepackagename)
169+ self.assertEquals(
170+ [(distroseries, sourcepackagename, None)],
171+ get_ubuntu_sharing_info(productseries=productseries))
172+
173+ def test_ubuntu_no_template_with_name(self):
174+ # With a sourcepackage without a template the sharing information
175+ # on a productseries will be empty, even when searching for a
176+ # specific template name.
177+ distroseries, sourcepackagename = self._makeSourcePackage()
178+ productseries = self._makeUpstreamProductSeries(
179+ distroseries, sourcepackagename)
180+ templatename = self.factory.getUniqueString()
181+ self.assertEquals(
182+ [(distroseries, sourcepackagename, None)],
183+ get_ubuntu_sharing_info(
184+ productseries=productseries, templatename=templatename))
185+
186+ def test_ubuntu_one_template(self):
187+ # With a sourcepackage template the sharing information on a
188+ # source package will return that.
189+ distroseries, sourcepackagename = self._makeSourcePackage()
190+ productseries = self._makeUpstreamProductSeries(
191+ distroseries, sourcepackagename)
192+ potemplate = self.factory.makePOTemplate(
193+ distroseries=distroseries, sourcepackagename=sourcepackagename)
194+ self.assertEquals(
195+ [(distroseries, sourcepackagename, potemplate)],
196+ get_ubuntu_sharing_info(
197+ productseries=productseries))
198+
199+ def test_ubuntu_one_template_with_name(self):
200+ # With a sourcepackage template the sharing information on a
201+ # productseries will return that, even when searching for a
202+ # specific template name.
203+ distroseries, sourcepackagename = self._makeSourcePackage()
204+ productseries = self._makeUpstreamProductSeries(
205+ distroseries, sourcepackagename)
206+ templatename = self.factory.getUniqueString()
207+ potemplate = self.factory.makePOTemplate(
208+ distroseries=distroseries, sourcepackagename=sourcepackagename,
209+ name=templatename)
210+ self.assertEquals(
211+ [(distroseries, sourcepackagename, potemplate)],
212+ get_ubuntu_sharing_info(
213+ productseries=productseries, templatename=templatename))
214+
215+ def test_ubuntu_one_template_with_different_name(self):
216+ # With a sourcepackage template the sharing information on a
217+ # productseries will be empty if a different name is queried.
218+ distroseries, sourcepackagename = self._makeSourcePackage()
219+ productseries = self._makeUpstreamProductSeries(
220+ distroseries, sourcepackagename)
221+ templatename = self.factory.getUniqueString()
222+ self.factory.makePOTemplate(
223+ distroseries=distroseries, sourcepackagename=sourcepackagename,
224+ name=templatename)
225+ different_templatename = self.factory.getUniqueString()
226+ self.assertEquals(
227+ [(distroseries, sourcepackagename, None)],
228+ get_ubuntu_sharing_info(
229+ productseries=productseries,
230+ templatename=different_templatename))
231+
232+ def test_has_upstream_template_no_productseries(self):
233+ # Without an upstream project, no upstream templates won't be
234+ # available either.
235+ distroseries, sourcepackagename = self._makeSourcePackage()
236+ templatename = self.factory.getUniqueString()
237+
238+ self.assertFalse(
239+ has_upstream_template(
240+ distroseries, sourcepackagename, templatename))
241+
242+ def test_has_upstream_template_no_template(self):
243+ # No template exists on the upstream project.
244+ distroseries, sourcepackagename = self._makeSourcePackage()
245+ productseries = self._makeUpstreamProductSeries(
246+ distroseries, sourcepackagename)
247+ templatename = self.factory.getUniqueString()
248+
249+ self.assertFalse(
250+ has_upstream_template(
251+ distroseries, sourcepackagename, templatename))
252+
253+ def test_has_upstream_template_one_template(self):
254+ # There is one template on the upstream project that matches the
255+ # name.
256+ distroseries, sourcepackagename = self._makeSourcePackage()
257+ productseries = self._makeUpstreamProductSeries(
258+ distroseries, sourcepackagename)
259+ templatename = self.factory.getUniqueString()
260+ self.factory.makePOTemplate(
261+ productseries=productseries, name=templatename)
262+
263+ self.assertTrue(
264+ has_upstream_template(
265+ distroseries, sourcepackagename, templatename))
266+
267+ def test_has_upstream_template_one_template_wrong_name(self):
268+ # There is one template on the upstream project but it matches not
269+ # the requested name.
270+ distroseries, sourcepackagename = self._makeSourcePackage()
271+ productseries = self._makeUpstreamProductSeries(
272+ distroseries, sourcepackagename)
273+ self.factory.makePOTemplate(productseries=productseries)
274+ different_templatename = self.factory.getUniqueString()
275+
276+ self.assertFalse(
277+ has_upstream_template(
278+ distroseries, sourcepackagename, different_templatename))
279+
280+ def test_has_ubuntu_template_no_sourcepackage(self):
281+ # There is no Ubuntu source package, so no Ubuntu template can be
282+ # found.
283+ productseries = self.factory.makeProductSeries()
284+ templatename = self.factory.getUniqueString()
285+
286+ self.assertFalse(has_ubuntu_template(productseries, templatename))
287+
288+ def test_has_ubuntu_template_no_template(self):
289+ # The Ubuntu source package has no template.
290+ distroseries, sourcepackagename = self._makeSourcePackage()
291+ productseries = self._makeUpstreamProductSeries(
292+ distroseries, sourcepackagename)
293+ templatename = self.factory.getUniqueString()
294+
295+ self.assertFalse(has_ubuntu_template(productseries, templatename))
296+
297+ def test_has_ubuntu_template_one_template(self):
298+ # There is one template on the Ubuntu source package that matches
299+ # the name.
300+ distroseries, sourcepackagename = self._makeSourcePackage()
301+ productseries = self._makeUpstreamProductSeries(
302+ distroseries, sourcepackagename)
303+ templatename = self.factory.getUniqueString()
304+ self.factory.makePOTemplate(
305+ distroseries=distroseries, sourcepackagename=sourcepackagename,
306+ name=templatename)
307+
308+ self.assertTrue(has_ubuntu_template(productseries, templatename))
309+
310+ def test_has_ubuntu_template_one_template_wrong_name(self):
311+ # There is one template on the Ubuntu source package but it matches
312+ # not the requested name.
313+ distroseries, sourcepackagename = self._makeSourcePackage()
314+ productseries = self._makeUpstreamProductSeries(
315+ distroseries, sourcepackagename)
316+ templatename = self.factory.getUniqueString()
317+ self.factory.makePOTemplate(
318+ distroseries=distroseries, sourcepackagename=sourcepackagename,
319+ name=templatename)
320+ different_templatename = self.factory.getUniqueString()
321+
322+ self.assertFalse(
323+ has_ubuntu_template(productseries, different_templatename))
324
325=== added file 'lib/lp/translations/utilities/translationsharinginfo.py'
326--- lib/lp/translations/utilities/translationsharinginfo.py 1970-01-01 00:00:00 +0000
327+++ lib/lp/translations/utilities/translationsharinginfo.py 2011-02-03 18:46:24 +0000
328@@ -0,0 +1,176 @@
329+# Copyright 2011 Canonical Ltd. This software is licensed under the
330+# GNU Affero General Public License version 3 (see the file LICENSE).
331+
332+"""Provide sharing information.
333+
334+This module defines two different types of functions that provide
335+information about what sharing options are available on the other side of a
336+packaging link. Since they perform similar but slightly different complex
337+database queries combining them in any way will usually be wrong.
338+
339+get_ubuntu_sharing_info and get_upstream_sharing_info will give you
340+information about the source package or productseries respectively,
341+combined with possibly available templates. You can restrict the search
342+by specifying a template name.
343+
344+has_ubuntu_template and has_upstream_template make a direct search for a
345+template of the given name on the other side. They do not search for
346+source package or productseries but will only return True if an actual
347+template exists. That is a significant difference to the get_* functions.
348+"""
349+
350+__metaclass__ = type
351+__all__ = [
352+ 'get_ubuntu_sharing_info',
353+ 'get_upstream_sharing_info',
354+ 'has_ubuntu_template',
355+ 'has_upstream_template',
356+ ]
357+
358+from storm.expr import (\
359+ And,
360+ Join,
361+ LeftJoin,
362+ )
363+
364+from canonical.launchpad.interfaces.lpstorm import IStore
365+from lp.registry.model.distroseries import DistroSeries
366+from lp.registry.model.packaging import Packaging
367+from lp.registry.model.productseries import ProductSeries
368+from lp.registry.model.sourcepackagename import SourcePackageName
369+from lp.translations.model.potemplate import POTemplate
370+
371+
372+def find_ubuntu_sharing_info(productseries, templatename=None,
373+ template_only=False):
374+ """Return a `ResultSet` of sharing information for this productseries.
375+
376+ Target is either a productseries or a source package.
377+ :param productseries: The target productseries or None.
378+ :param templatename: The name of the template to find information for or
379+ None to get information about any sharing template in any series.
380+ :param template_only: Return only `POTemplate` instances.
381+ :returns: A result set of ('Distroseries', SourcePackageName, POTemplate)
382+ tuples.
383+ """
384+
385+ # SELECT *
386+ # FROM Packaging
387+ # JOIN Distroseries
388+ # ON Packaging.distroseries = Distroseries.id
389+ # JOIN SourcePackageName
390+ # ON Packaging.sourcepackagename = SourcePackageName.id
391+ # LEFT JOIN POTemplate
392+ # ON Packaging.distroseries = POTemplate.distroseries AND
393+ # Packaging.sourcepackagename = POTemplate.sourcepackagename AND
394+ # POTemplate.name = templatename
395+ # WHERE Packaging.productseries = productseries
396+ #
397+ if templatename is None:
398+ potemplate_condition = And(
399+ Packaging.distroseriesID == POTemplate.distroseriesID,
400+ Packaging.sourcepackagenameID == POTemplate.sourcepackagenameID)
401+ else:
402+ potemplate_condition = And(
403+ Packaging.distroseriesID == POTemplate.distroseriesID,
404+ Packaging.sourcepackagenameID ==
405+ POTemplate.sourcepackagenameID,
406+ POTemplate.name == templatename)
407+ if template_only:
408+ prejoin = Join(
409+ Packaging,
410+ POTemplate,
411+ potemplate_condition)
412+ result_classes = POTemplate
413+ else:
414+ prejoin = LeftJoin(
415+ Join(
416+ Join(
417+ Packaging, DistroSeries,
418+ Packaging.distroseriesID == DistroSeries.id),
419+ SourcePackageName,
420+ Packaging.sourcepackagenameID == SourcePackageName.id),
421+ POTemplate,
422+ potemplate_condition)
423+ result_classes = (DistroSeries, SourcePackageName, POTemplate)
424+ conditions = [
425+ Packaging.productseries == productseries,
426+ ]
427+ return IStore(Packaging).using(prejoin).find(
428+ result_classes, *conditions)
429+
430+
431+def find_upstream_sharing_info(distroseries, sourcepackagename,
432+ templatename=None, template_only=False):
433+ """Return a `ResultSet` of sharing information for this sourcepackage.
434+
435+ :param distroseries: The target distroseries or None.
436+ :param sourcepackagename: The target sourcepackagename or None.
437+ :param templatename: The name of the template to find information for or
438+ None to get information about any sharing template in any series.
439+ :param template_only: Return only `POTemplate` instances.
440+ :returns: A ResultSet of (ProductSeries, POTemplate) tuples.
441+ """
442+ # SELECT *
443+ # FROM Packaging
444+ # JOIN ProductSeries
445+ # ON Packaging.productseries = Productseris.id
446+ # LEFT JOIN POTemplate
447+ # ON Packaging.productseries = POTemplate.productseries AND
448+ # POTemplate.name = templatename
449+ # WHERE Packaging.distroseries = distroseries AND
450+ # Packaging.sourcepackagename = sourcepackagename
451+ #
452+ if templatename is None:
453+ potemplate_condition = (
454+ Packaging.productseriesID == POTemplate.productseriesID)
455+ else:
456+ potemplate_condition = And(
457+ Packaging.productseriesID == POTemplate.productseriesID,
458+ POTemplate.name == templatename)
459+ if template_only:
460+ prejoin = Join(
461+ Packaging, POTemplate, potemplate_condition)
462+ result_classes = POTemplate
463+ else:
464+ prejoin = LeftJoin(
465+ Join(
466+ Packaging, ProductSeries,
467+ Packaging.productseriesID == ProductSeries.id),
468+ POTemplate,
469+ potemplate_condition)
470+ result_classes = (ProductSeries, POTemplate)
471+ conditions = [
472+ Packaging.distroseries == distroseries,
473+ Packaging.sourcepackagename == sourcepackagename,
474+ ]
475+
476+ return IStore(Packaging).using(prejoin).find(
477+ result_classes, *conditions)
478+
479+
480+def get_ubuntu_sharing_info(productseries, templatename=None):
481+ """Return a list of sharing information for the given target."""
482+ return list(find_ubuntu_sharing_info(productseries, templatename))
483+
484+
485+def get_upstream_sharing_info(distroseries, sourcepackagename,
486+ templatename=None):
487+ """Return a list of sharing information for the given target."""
488+ return list(find_upstream_sharing_info(
489+ distroseries, sourcepackagename, templatename))
490+
491+
492+def has_ubuntu_template(productseries, templatename):
493+ """Check for existence of ubuntu template."""
494+ result = find_ubuntu_sharing_info(
495+ productseries, templatename, template_only=True)
496+ return not result.is_empty()
497+
498+
499+def has_upstream_template(distroseries, sourcepackagename, templatename):
500+ """Check for existence of upstream template."""
501+ result = find_upstream_sharing_info(
502+ distroseries, sourcepackagename, templatename,
503+ template_only=True)
504+ return not result.is_empty()