← Back to team overview

launchpad-reviewers team mailing list archive

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

 

Henning Eggers has proposed merging lp:~henninge/launchpad/devel-710591-sharing-info-groundwork-0 into lp:launchpad.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~henninge/launchpad/devel-710591-sharing-info-groundwork-0/+merge/48416

= 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
-- 
https://code.launchpad.net/~henninge/launchpad/devel-710591-sharing-info-groundwork-0/+merge/48416
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~henninge/launchpad/devel-710591-sharing-info-groundwork-0 into lp:launchpad.
=== modified file '.bzrignore'
--- .bzrignore	2011-01-16 19:04:25 +0000
+++ .bzrignore	2011-02-03 01:28:56 +0000
@@ -76,3 +76,4 @@
 librarian.log
 configs/testrunner_*
 configs/testrunner-appserver_*
+.idea

=== added file 'lib/lp/translations/utilities/tests/test_translation_sharing_info.py'
--- lib/lp/translations/utilities/tests/test_translation_sharing_info.py	1970-01-01 00:00:00 +0000
+++ lib/lp/translations/utilities/tests/test_translation_sharing_info.py	2011-02-03 01:28:56 +0000
@@ -0,0 +1,298 @@
+# Copyright 2009 Canonical Ltd.  This software is licensed under the
+# GNU Affero General Public License version 3 (see the file LICENSE).
+
+# pylint: disable-msg=C0102
+
+__metaclass__ = type
+
+from canonical.testing.layers import ZopelessDatabaseLayer
+from lp.testing import TestCaseWithFactory
+from lp.translations.utilities.translationsharinginfo import (
+    get_ubuntu_sharing_info,
+    get_upstream_sharing_info,
+    has_ubuntu_template,
+    has_upstream_template,
+    )
+
+
+class TestTranslationSharingInfo(TestCaseWithFactory):
+    """Tests for `get_upstream_sharing_info` and `get_ubuntu_sharing_info`"""
+
+    layer = ZopelessDatabaseLayer
+
+    def _makeSourcePackage(self):
+        """Create a distroseries and a sourcepackagename."""
+        distroseries = self.factory.makeUbuntuDistroSeries()
+        sourcepackagename = self.factory.makeSourcePackageName()
+        return (distroseries, sourcepackagename)
+
+    def _makeUpstreamProductSeries(self, distroseries, sourcepackagename):
+        """Create a product series and link it to the source package."""
+        productseries = self.factory.makeProductSeries()
+        sourcepackage = self.factory.makeSourcePackage(
+            sourcepackagename, distroseries)
+        owner = self.factory.makePerson()
+        sourcepackage.setPackaging(productseries, owner)
+        return productseries
+
+    def test_no_upstream(self):
+        # With no upstream the sharing information on a source package will
+        # be empty.
+        distroseries, sourcepackagename = self._makeSourcePackage()
+        self.assertEquals(
+            [],
+            get_upstream_sharing_info(
+                distroseries=distroseries,
+                sourcepackagename=sourcepackagename))
+
+    def test_no_upstream_with_name(self):
+        # With no upstream the sharing information on a source package will
+        # be empty, even when searching for a specific template name.
+        distroseries, sourcepackagename = self._makeSourcePackage()
+        templatename = self.factory.getUniqueString()
+        self.assertEquals(
+            [],
+            get_upstream_sharing_info(
+                distroseries=distroseries,
+                sourcepackagename=sourcepackagename,
+                templatename=templatename))
+
+    def test_upstream_no_template(self):
+        # With an upstream without a template the sharing information on a
+        # source package will be empty.
+        distroseries, sourcepackagename = self._makeSourcePackage()
+        productseries = self._makeUpstreamProductSeries(
+            distroseries, sourcepackagename)
+        self.assertEquals(
+            [(productseries, None)],
+            get_upstream_sharing_info(
+                distroseries=distroseries,
+                sourcepackagename=sourcepackagename))
+
+    def test_upstream_no_template_with_name(self):
+        # With an upstream without a template the sharing information on a
+        # source package will be empty, even when searching for a specific
+        # template name.
+        distroseries, sourcepackagename = self._makeSourcePackage()
+        productseries = self._makeUpstreamProductSeries(
+            distroseries, sourcepackagename)
+        templatename = self.factory.getUniqueString()
+        self.assertEquals(
+            [(productseries, None)],
+            get_upstream_sharing_info(
+                distroseries=distroseries,
+                sourcepackagename=sourcepackagename,
+                templatename=templatename))
+
+    def test_upstream_one_template(self):
+        # With an upstream template the sharing information on a
+        # source package will return that.
+        distroseries, sourcepackagename = self._makeSourcePackage()
+        productseries = self._makeUpstreamProductSeries(
+            distroseries, sourcepackagename)
+        potemplate = self.factory.makePOTemplate(productseries=productseries)
+        self.assertEquals(
+            [(productseries, potemplate)],
+            get_upstream_sharing_info(
+                distroseries=distroseries,
+                sourcepackagename=sourcepackagename))
+
+    def test_upstream_one_template_with_name(self):
+        # With an upstream template the sharing information on a
+        # source package will return that, even when searching for a
+        # specific template name.
+        distroseries, sourcepackagename = self._makeSourcePackage()
+        productseries = self._makeUpstreamProductSeries(
+            distroseries, sourcepackagename)
+        templatename = self.factory.getUniqueString()
+        potemplate = self.factory.makePOTemplate(
+            productseries=productseries, name=templatename)
+        self.assertEquals(
+            [(productseries, potemplate)],
+            get_upstream_sharing_info(
+                distroseries=distroseries,
+                sourcepackagename=sourcepackagename,
+                templatename=templatename))
+
+    def test_upstream_one_template_with_different_name(self):
+        # With an upstream template the sharing information on a
+        # source package will be empty if a different name is queried.
+        distroseries, sourcepackagename = self._makeSourcePackage()
+        productseries = self._makeUpstreamProductSeries(
+            distroseries, sourcepackagename)
+        templatename = self.factory.getUniqueString()
+        self.factory.makePOTemplate(
+            productseries=productseries, name=templatename)
+        different_templatename = self.factory.getUniqueString()
+        self.assertEquals(
+            [(productseries, None)],
+            get_upstream_sharing_info(
+                distroseries=distroseries,
+                sourcepackagename=sourcepackagename,
+                templatename=different_templatename))
+
+    def test_no_ubuntu(self):
+        # With no sourcepackage the sharing information on a source package
+        # will be empty.
+        productseries = self.factory.makeProductSeries()
+        self.assertEquals(
+            [],
+            get_ubuntu_sharing_info(productseries=productseries))
+
+    def test_no_ubuntu_with_name(self):
+        # With no sourcepackage the sharing information on a source package
+        # will be empty, even when searching for a specific template name.
+        productseries = self.factory.makeProductSeries()
+        templatename = self.factory.getUniqueString()
+        self.assertEquals(
+            [],
+            get_ubuntu_sharing_info(
+                productseries=productseries, templatename=templatename))
+
+    def test_ubuntu_no_template(self):
+        # With a sourcepackage without a template the sharing information
+        # on a productseries will be empty.
+        distroseries, sourcepackagename = self._makeSourcePackage()
+        productseries = self._makeUpstreamProductSeries(
+            distroseries, sourcepackagename)
+        self.assertEquals(
+            [(distroseries, sourcepackagename, None)],
+            get_ubuntu_sharing_info(productseries=productseries))
+
+    def test_ubuntu_no_template_with_name(self):
+        # With a sourcepackage without a template the sharing information
+        # on a productseries will be empty, even when searching for a
+        # specific template name.
+        distroseries, sourcepackagename = self._makeSourcePackage()
+        productseries = self._makeUpstreamProductSeries(
+            distroseries, sourcepackagename)
+        templatename = self.factory.getUniqueString()
+        self.assertEquals(
+            [(distroseries, sourcepackagename, None)],
+            get_ubuntu_sharing_info(
+                productseries=productseries, templatename=templatename))
+
+    def test_ubuntu_one_template(self):
+        # With a sourcepackage template the sharing information on a
+        # source package will return that.
+        distroseries, sourcepackagename = self._makeSourcePackage()
+        productseries = self._makeUpstreamProductSeries(
+            distroseries, sourcepackagename)
+        potemplate = self.factory.makePOTemplate(
+            distroseries=distroseries, sourcepackagename=sourcepackagename)
+        self.assertEquals(
+            [(distroseries, sourcepackagename, potemplate)],
+            get_ubuntu_sharing_info(
+                productseries=productseries))
+
+    def test_ubuntu_one_template_with_name(self):
+        # With a sourcepackage template the sharing information on a
+        # productseries will return that, even when searching for a
+        # specific template name.
+        distroseries, sourcepackagename = self._makeSourcePackage()
+        productseries = self._makeUpstreamProductSeries(
+            distroseries, sourcepackagename)
+        templatename = self.factory.getUniqueString()
+        potemplate = self.factory.makePOTemplate(
+            distroseries=distroseries, sourcepackagename=sourcepackagename,
+            name=templatename)
+        self.assertEquals(
+            [(distroseries, sourcepackagename, potemplate)],
+            get_ubuntu_sharing_info(
+                productseries=productseries, templatename=templatename))
+
+    def test_ubuntu_one_template_with_different_name(self):
+        # With a sourcepackage template the sharing information on a
+        # productseries will  be empty if a different name is queried.
+        distroseries, sourcepackagename = self._makeSourcePackage()
+        productseries = self._makeUpstreamProductSeries(
+            distroseries, sourcepackagename)
+        templatename = self.factory.getUniqueString()
+        self.factory.makePOTemplate(
+            distroseries=distroseries, sourcepackagename=sourcepackagename,
+            name=templatename)
+        different_templatename = self.factory.getUniqueString()
+        self.assertEquals(
+            [(distroseries, sourcepackagename, None)],
+            get_ubuntu_sharing_info(
+                productseries=productseries,
+                templatename=different_templatename))
+
+    def test_has_upstream_template_no_productseries(self):
+        distroseries, sourcepackagename = self._makeSourcePackage()
+        templatename = self.factory.getUniqueString()
+
+        self.assertFalse(
+            has_upstream_template(
+                distroseries, sourcepackagename, templatename))
+
+    def test_has_upstream_template_no_template(self):
+        distroseries, sourcepackagename = self._makeSourcePackage()
+        productseries = self._makeUpstreamProductSeries(
+            distroseries, sourcepackagename)
+        templatename = self.factory.getUniqueString()
+
+        self.assertFalse(
+            has_upstream_template(
+                distroseries, sourcepackagename, templatename))
+
+    def test_has_upstream_template_one_template(self):
+        distroseries, sourcepackagename = self._makeSourcePackage()
+        productseries = self._makeUpstreamProductSeries(
+            distroseries, sourcepackagename)
+        templatename = self.factory.getUniqueString()
+        self.factory.makePOTemplate(
+            productseries=productseries, name=templatename)
+
+        self.assertTrue(
+            has_upstream_template(
+                distroseries, sourcepackagename, templatename))
+
+    def test_has_upstream_template_one_template_wrong_name(self):
+        distroseries, sourcepackagename = self._makeSourcePackage()
+        productseries = self._makeUpstreamProductSeries(
+            distroseries, sourcepackagename)
+        self.factory.makePOTemplate(productseries=productseries)
+        different_templatename = self.factory.getUniqueString()
+
+        self.assertFalse(
+            has_upstream_template(
+                distroseries, sourcepackagename, different_templatename))
+
+    def test_has_ubuntu_template_no_sourcepackage(self):
+        productseries = self.factory.makeProductSeries()
+        templatename = self.factory.getUniqueString()
+
+        self.assertFalse(has_ubuntu_template(productseries, templatename))
+
+    def test_has_ubuntu_template_no_template(self):
+        distroseries, sourcepackagename = self._makeSourcePackage()
+        productseries = self._makeUpstreamProductSeries(
+            distroseries, sourcepackagename)
+        templatename = self.factory.getUniqueString()
+
+        self.assertFalse(has_ubuntu_template(productseries, templatename))
+
+    def test_has_ubuntu_template_one_template(self):
+        distroseries, sourcepackagename = self._makeSourcePackage()
+        productseries = self._makeUpstreamProductSeries(
+            distroseries, sourcepackagename)
+        templatename = self.factory.getUniqueString()
+        self.factory.makePOTemplate(
+            distroseries=distroseries, sourcepackagename=sourcepackagename,
+            name=templatename)
+
+        self.assertTrue(has_ubuntu_template(productseries, templatename))
+
+    def test_has_ubuntu_template_one_template_wrong_name(self):
+        distroseries, sourcepackagename = self._makeSourcePackage()
+        productseries = self._makeUpstreamProductSeries(
+            distroseries, sourcepackagename)
+        templatename = self.factory.getUniqueString()
+        self.factory.makePOTemplate(
+            distroseries=distroseries, sourcepackagename=sourcepackagename,
+            name=templatename)
+        different_templatename = self.factory.getUniqueString()
+
+        self.assertFalse(
+            has_ubuntu_template(productseries, different_templatename))

=== added file 'lib/lp/translations/utilities/translationsharinginfo.py'
--- lib/lp/translations/utilities/translationsharinginfo.py	1970-01-01 00:00:00 +0000
+++ lib/lp/translations/utilities/translationsharinginfo.py	2011-02-03 01:28:56 +0000
@@ -0,0 +1,160 @@
+# Copyright 2011 Canonical Ltd.  This software is licensed under the
+# GNU Affero General Public License version 3 (see the file LICENSE).
+
+"""Provide sharing information."""
+
+__metaclass__ = type
+__all__ = [
+    'get_ubuntu_sharing_info',
+    'get_upstream_sharing_info',
+    'has_ubuntu_template',
+    'has_upstream_template',
+    ]
+
+from storm.expr import (\
+    And,
+    Join,
+    LeftJoin,
+    )
+
+from canonical.launchpad.interfaces.lpstorm import IStore
+from lp.registry.model.distroseries import DistroSeries
+from lp.registry.model.packaging import Packaging
+from lp.registry.model.productseries import ProductSeries
+from lp.registry.model.sourcepackagename import SourcePackageName
+from lp.translations.model.potemplate import POTemplate
+
+
+def find_ubuntu_sharing_info(productseries, templatename=None,
+                             template_only=False):
+    """Return a `ResultSet` of sharing information for this productseries.
+
+    Target is either a productseries or a source package.
+    :param productseries: The target productseries or None.
+    :param templatename: The name of the template to find information for or
+        None to get information about any sharing template in any series.
+    :param template_only: Return only `POTemplate` instances.
+    :returns: A result set of ('Distroseries', SourcePackageName, POTemplate)
+        tuples.
+    """
+
+    # SELECT *
+    # FROM Packaging
+    # JOIN Distroseries
+    #   ON Packaging.distroseries = Distroseries.id
+    # JOIN SourcePackageName
+    #   ON Packaging.sourcepackagename = SourcePackageName.id
+    # LEFT JOIN POTemplate
+    #   ON Packaging.distroseries = POTemplate.distroseries AND
+    #      Packaging.sourcepackagename = POTemplate.sourcepackagename AND
+    #      POTemplate.name = templatename
+    # WHERE Packaging.productseries = productseries
+    #
+    if templatename is None:
+        potemplate_condition = And(
+            Packaging.distroseriesID == POTemplate.distroseriesID,
+            Packaging.sourcepackagenameID == POTemplate.sourcepackagenameID)
+    else:
+        potemplate_condition = And(
+            Packaging.distroseriesID == POTemplate.distroseriesID,
+            Packaging.sourcepackagenameID ==
+                POTemplate.sourcepackagenameID,
+            POTemplate.name == templatename)
+    if template_only:
+        prejoin = Join(
+            Packaging,
+            POTemplate,
+            potemplate_condition)
+        result_classes = POTemplate
+    else:
+        prejoin = LeftJoin(
+            Join(
+                Join(
+                    Packaging, DistroSeries,
+                    Packaging.distroseriesID == DistroSeries.id),
+                SourcePackageName,
+                Packaging.sourcepackagenameID == SourcePackageName.id),
+            POTemplate,
+            potemplate_condition)
+        result_classes = (DistroSeries, SourcePackageName, POTemplate)
+    conditions = [
+        Packaging.productseries == productseries,
+        ]
+    return IStore(Packaging).using(prejoin).find(
+        result_classes, *conditions)
+
+
+def find_upstream_sharing_info(distroseries, sourcepackagename,
+                              templatename=None, template_only=False):
+    """Return a `ResultSet` of sharing information for this sourcepackage.
+
+    :param distroseries: The target distroseries or None.
+    :param sourcepackagename: The target sourcepackagename or None.
+    :param templatename: The name of the template to find information for or
+        None to get information about any sharing template in any series.
+    :param template_only: Return only `POTemplate` instances.
+    :returns: A ResultSet of (ProductSeries, POTemplate) tuples.
+    """
+    # SELECT *
+    # FROM Packaging
+    # JOIN ProductSeries
+    #   ON Packaging.productseries = Productseris.id
+    # LEFT JOIN POTemplate
+    #   ON Packaging.productseries = POTemplate.productseries AND
+    #      POTemplate.name = templatename
+    # WHERE Packaging.distroseries = distroseries AND
+    #      Packaging.sourcepackagename = sourcepackagename
+    #
+    if templatename is None:
+        potemplate_condition = (
+            Packaging.productseriesID == POTemplate.productseriesID)
+    else:
+        potemplate_condition = And(
+            Packaging.productseriesID == POTemplate.productseriesID,
+            POTemplate.name == templatename)
+    if template_only:
+        prejoin = Join(
+            Packaging, POTemplate, potemplate_condition)
+        result_classes = POTemplate
+    else:
+        prejoin = LeftJoin(
+            Join(
+                Packaging, ProductSeries,
+                Packaging.productseriesID == ProductSeries.id),
+            POTemplate,
+            potemplate_condition)
+        result_classes = (ProductSeries, POTemplate)
+    conditions = [
+        Packaging.distroseries == distroseries,
+        Packaging.sourcepackagename == sourcepackagename,
+        ]
+
+    return IStore(Packaging).using(prejoin).find(
+        result_classes, *conditions)
+
+
+def get_ubuntu_sharing_info(productseries, templatename=None):
+    """Return a list of sharing information for the given target."""
+    return list(find_ubuntu_sharing_info(productseries, templatename))
+
+
+def get_upstream_sharing_info(distroseries, sourcepackagename,
+                              templatename=None):
+    """Return a list of sharing information for the given target."""
+    return list(find_upstream_sharing_info(
+        distroseries, sourcepackagename, templatename))
+
+
+def has_ubuntu_template(productseries, templatename):
+    """Check for existence of ubuntu template."""
+    result = find_ubuntu_sharing_info(
+        productseries, templatename, template_only=True)
+    return not result.is_empty()
+
+
+def has_upstream_template(distroseries, sourcepackagename, templatename):
+    """Check for existence of upstream template."""
+    result = find_upstream_sharing_info(
+            distroseries, sourcepackagename, templatename,
+            template_only=True)
+    return not result.is_empty()