← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] ~cjwatson/launchpad:distroseries-translation-stats into launchpad:master

 

Colin Watson has proposed merging ~cjwatson/launchpad:distroseries-translation-stats into launchpad:master.

Commit message:
Add and export DistroSeries.getTranslationTemplateStatistics

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~cjwatson/launchpad/+git/launchpad/+merge/435396

This will allow us to generate the `*_potemplate-stats.json` files in https://people.canonical.com/~people-l10n/data/ubuntu-l10n/ using a simple webservice client rather than using a script with direct database access.  (We could generate `*_package-stats.json` in a similar way, but so far I haven't found anything that uses those files.)
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of ~cjwatson/launchpad:distroseries-translation-stats into launchpad:master.
diff --git a/lib/lp/registry/interfaces/distroseries.py b/lib/lp/registry/interfaces/distroseries.py
index 03e6d68..22fddd0 100644
--- a/lib/lp/registry/interfaces/distroseries.py
+++ b/lib/lp/registry/interfaces/distroseries.py
@@ -6,6 +6,7 @@
 __all__ = [
     "DerivationError",
     "DistroSeriesNameField",
+    "DistroSeriesTranslationTemplateStatistics",
     "IDistroSeries",
     "IDistroSeriesEditRestricted",
     "IDistroSeriesPublic",
@@ -13,6 +14,8 @@ __all__ = [
 ]
 
 import http.client
+import typing
+from datetime import datetime
 
 from lazr.lifecycle.snapshot import doNotSnapshot
 from lazr.restful.declarations import (
@@ -31,6 +34,7 @@ from lazr.restful.declarations import (
     rename_parameters_as,
 )
 from lazr.restful.fields import CollectionField, Reference, ReferenceChoice
+from typing_extensions import TypedDict
 from zope.component import getUtility
 from zope.interface import Attribute, Interface
 from zope.schema import Bool, Choice, Datetime, List, Object, TextLine
@@ -165,6 +169,30 @@ class DistroSeriesVersionField(UniqueField):
             raise LaunchpadValidationError("'%s': %s" % (version, error))
 
 
+DistroSeriesTranslationTemplateStatistics = TypedDict(
+    "DistroSeriesTranslationTemplateStatistics",
+    {
+        # The name of the source package that uses the template.
+        "sourcepackage": str,
+        # The translation domain for the template.
+        "translation_domain": str,
+        # The name of the template.
+        "template_name": str,
+        # The number of translation messages for the template.
+        "total": int,
+        # Whether the template is active.
+        "enabled": bool,
+        # Whether the template is part of a language pack.
+        "languagepack": bool,
+        # A number that describes how important this template is; templates
+        # with higher priorities should be translated first.
+        "priority": int,
+        # When the template was last updated.
+        "date_last_updated": datetime,
+    },
+)
+
+
 class IDistroSeriesPublic(
     ISeriesMixin,
     IHasAppointedDriver,
@@ -1098,6 +1126,28 @@ class IDistroSeriesPublic(
             comment.
         """
 
+    @export_read_operation()
+    @operation_for_version("devel")
+    def getTranslationTemplateStatistics() -> typing.List[
+        DistroSeriesTranslationTemplateStatistics
+    ]:
+        """Return statistics for translation templates in this series.
+
+        The return value is a list of dicts for each template in the series,
+        each of which has this form::
+
+            {
+                "sourcepackage": ...,
+                "translation_domain": ...,
+                "name": ...,
+                "total": ...,
+                "enabled": ...,
+                "languagepack": ...,
+                "priority": ...,
+                "date_last_updated": ...,
+            }
+        """
+
 
 class IDistroSeriesEditRestricted(Interface):
     """IDistroSeries properties which require launchpad.Edit."""
diff --git a/lib/lp/registry/model/distroseries.py b/lib/lp/registry/model/distroseries.py
index 7844249..68f102f 100644
--- a/lib/lp/registry/model/distroseries.py
+++ b/lib/lp/registry/model/distroseries.py
@@ -13,6 +13,7 @@ __all__ = [
 import collections
 from io import BytesIO
 from operator import itemgetter
+from typing import List
 
 import apt_pkg
 from lazr.delegates import delegate_to
@@ -41,6 +42,7 @@ from lp.buildmaster.model.processor import Processor
 from lp.registry.errors import NoSuchDistroSeries
 from lp.registry.interfaces.distroseries import (
     DerivationError,
+    DistroSeriesTranslationTemplateStatistics,
     IDistroSeries,
     IDistroSeriesSet,
 )
@@ -1704,6 +1706,42 @@ class DistroSeries(
             self, since=since, source_package_name=source_package_name
         )
 
+    def getTranslationTemplateStatistics(
+        self,
+    ) -> List[DistroSeriesTranslationTemplateStatistics]:
+        """See `IDistroSeries`."""
+        rows = (
+            IStore(POTemplate)
+            .find(
+                (
+                    SourcePackageName.name,
+                    POTemplate.translation_domain,
+                    POTemplate.name,
+                    POTemplate.messagecount,
+                    POTemplate.iscurrent,
+                    POTemplate.languagepack,
+                    POTemplate.priority,
+                    POTemplate.date_last_updated,
+                ),
+                POTemplate.distroseries == self,
+                POTemplate.sourcepackagename == SourcePackageName.id,
+            )
+            .order_by(SourcePackageName.name, POTemplate.name)
+        )
+        return [
+            {
+                "sourcepackage": row[0],
+                "translation_domain": row[1],
+                "template_name": row[2],
+                "total": row[3],
+                "enabled": row[4],
+                "languagepack": row[5],
+                "priority": row[6],
+                "date_last_updated": row[7],
+            }
+            for row in rows
+        ]
+
 
 @implementer(IDistroSeriesSet)
 class DistroSeriesSet:
diff --git a/lib/lp/registry/tests/test_distroseries.py b/lib/lp/registry/tests/test_distroseries.py
index ab3c6bf..2c7c329 100644
--- a/lib/lp/registry/tests/test_distroseries.py
+++ b/lib/lp/registry/tests/test_distroseries.py
@@ -712,6 +712,42 @@ class TestDistroSeriesWebservice(TestCaseWithFactory):
         self.assertEqual(209, response.status)
         self.assertTrue(distroseries.language_pack_full_export_requested)
 
+    def test_translation_template_statistics(self):
+        distroseries = self.factory.makeDistroSeries()
+        templates = [
+            self.factory.makePOTemplate(distroseries=distroseries)
+            for _ in range(3)
+        ]
+        removeSecurityProxy(templates[0]).messagecount = 100
+        removeSecurityProxy(templates[0]).priority = 10
+        removeSecurityProxy(templates[1]).iscurrent = False
+        removeSecurityProxy(templates[2]).languagepack = True
+        self.factory.makePOTemplate()
+        distroseries_url = api_url(distroseries)
+        webservice = webservice_for_person(None, default_api_version="devel")
+        response = webservice.named_get(
+            distroseries_url, "getTranslationTemplateStatistics"
+        )
+        self.assertEqual(200, response.status)
+        self.assertEqual(
+            [
+                {
+                    "sourcepackage": template.sourcepackage.name,
+                    "translation_domain": template.translation_domain,
+                    "template_name": template.name,
+                    "total": template.messagecount,
+                    "enabled": template.iscurrent,
+                    "languagepack": template.languagepack,
+                    "priority": template.priority,
+                    "date_last_updated": (
+                        template.date_last_updated.isoformat()
+                    ),
+                }
+                for template in templates
+            ],
+            response.jsonBody(),
+        )
+
 
 class TestDistroSeriesSet(TestCaseWithFactory):