← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] lp:~cjwatson/launchpad/distroseries-publishing-options into lp:launchpad

 

Colin Watson has proposed merging lp:~cjwatson/launchpad/distroseries-publishing-options into lp:launchpad.

Commit message:
Model DistroSeries.publishing_options, and add a garbo job to populate it from backports_not_automatic and include_long_descriptions.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~cjwatson/launchpad/distroseries-publishing-options/+merge/278242

Model DistroSeries.publishing_options, and add a garbo job to populate it from backports_not_automatic and include_long_descriptions.

See https://code.launchpad.net/~cjwatson/launchpad/db-distroseries-publishing-options/+merge/278241 for the rationale.
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~cjwatson/launchpad/distroseries-publishing-options into lp:launchpad.
=== modified file 'database/schema/security.cfg'
--- database/schema/security.cfg	2015-11-11 18:12:24 +0000
+++ database/schema/security.cfg	2015-11-21 11:14:12 +0000
@@ -2301,6 +2301,7 @@
 public.codeimportresult                 = SELECT, DELETE
 public.commercialsubscription           = SELECT, UPDATE
 public.diff                             = SELECT, DELETE
+public.distroseries                     = SELECT, UPDATE
 public.emailaddress                     = SELECT, UPDATE, DELETE
 public.garbojobstate                    = SELECT, INSERT, UPDATE, DELETE
 public.gitjob                           = SELECT, DELETE

=== modified file 'lib/lp/registry/model/distroseries.py'
--- lib/lp/registry/model/distroseries.py	2015-10-13 13:22:08 +0000
+++ lib/lp/registry/model/distroseries.py	2015-11-21 11:14:12 +0000
@@ -1,4 +1,4 @@
-# Copyright 2009-2014 Canonical Ltd.  This software is licensed under the
+# Copyright 2009-2015 Canonical Ltd.  This software is licensed under the
 # GNU Affero General Public License version 3 (see the file LICENSE).
 
 """Database classes for a distribution series."""
@@ -34,6 +34,7 @@
     Or,
     SQL,
     )
+from storm.locals import JSON
 from storm.store import (
     EmptyResultSet,
     Store,
@@ -252,8 +253,11 @@
         foreignKey="LanguagePack", dbName="language_pack_proposed",
         notNull=False, default=None)
     language_pack_full_export_requested = BoolCol(notNull=True, default=False)
-    backports_not_automatic = BoolCol(notNull=True, default=False)
-    include_long_descriptions = BoolCol(notNull=True, default=True)
+    _backports_not_automatic = BoolCol(
+        dbName="backports_not_automatic", notNull=True, default=False)
+    _include_long_descriptions = BoolCol(
+        dbName="include_long_descriptions", notNull=True, default=True)
+    publishing_options = JSON("publishing_options")
 
     language_packs = SQLMultipleJoin(
         'LanguagePack', joinColumn='distroseries', orderBy='-date_exported')
@@ -790,6 +794,38 @@
             distroseries=self, type=LanguagePackType.DELTA,
             updates=self.language_pack_base, orderBy='-date_exported')
 
+    @property
+    def backports_not_automatic(self):
+        if self.publishing_options is not None:
+            return self.publishing_options.get(
+                "backports_not_automatic", False)
+        else:
+            return self._backports_not_automatic
+
+    @backports_not_automatic.setter
+    def backports_not_automatic(self, value):
+        assert isinstance(value, bool)
+        if self.publishing_options is not None:
+            self.publishing_options["backports_not_automatic"] = value
+        else:
+            self._backports_not_automatic = value
+
+    @property
+    def include_long_descriptions(self):
+        if self.publishing_options is not None:
+            return self.publishing_options.get(
+                "include_long_descriptions", True)
+        else:
+            return self._include_long_descriptions
+
+    @include_long_descriptions.setter
+    def include_long_descriptions(self, value):
+        assert isinstance(value, bool)
+        if self.publishing_options is not None:
+            self.publishing_options["include_long_descriptions"] = value
+        else:
+            self._include_long_descriptions = value
+
     def _customizeSearchParams(self, search_params):
         """Customize `search_params` for this distribution series."""
         search_params.setDistroSeries(self)

=== modified file 'lib/lp/scripts/garbo.py'
--- lib/lp/scripts/garbo.py	2015-10-01 07:17:36 +0000
+++ lib/lp/scripts/garbo.py	2015-11-21 11:14:12 +0000
@@ -70,6 +70,7 @@
     )
 from lp.hardwaredb.model.hwdb import HWSubmission
 from lp.registry.model.commercialsubscription import CommercialSubscription
+from lp.registry.model.distroseries import DistroSeries
 from lp.registry.model.person import (
     Person,
     PersonSettings,
@@ -1461,6 +1462,40 @@
         transaction.commit()
 
 
+class DistroSeriesPublishingOptionsPopulator(TunableLoop):
+    """Populates DistroSeries.publishing_options."""
+
+    maximum_chunk_size = 5000
+
+    def __init__(self, log, abort_time=None):
+        super(DistroSeriesPublishingOptionsPopulator, self).__init__(
+            log, abort_time)
+        self.start_at = 1
+        self.store = IMasterStore(DistroSeries)
+
+    def findSeries(self):
+        return self.store.find(
+            DistroSeries,
+            DistroSeries.id >= self.start_at).order_by(DistroSeries.id)
+
+    def isDone(self):
+        return self.findSeries().is_empty()
+
+    def __call__(self, chunk_size):
+        all_series = list(self.findSeries()[:chunk_size])
+        for series in all_series:
+            if series.publishing_options is None:
+                naked_series = removeSecurityProxy(series)
+                series.publishing_options = {
+                    "backports_not_automatic":
+                        naked_series._backports_not_automatic,
+                    "include_long_descriptions":
+                        naked_series._include_long_descriptions,
+                    }
+        self.start_at = all_series[-1].id + 1
+        transaction.commit()
+
+
 class BaseDatabaseGarbageCollector(LaunchpadCronScript):
     """Abstract base class to run a collection of TunableLoops."""
     script_name = None  # Script name for locking and database user. Override.
@@ -1739,6 +1774,7 @@
         CodeImportEventPruner,
         CodeImportResultPruner,
         DiffPruner,
+        DistroSeriesPublishingOptionsPopulator,
         GitJobPruner,
         HWSubmissionEmailLinker,
         LiveFSFilePruner,

=== modified file 'lib/lp/scripts/tests/test_garbo.py'
--- lib/lp/scripts/tests/test_garbo.py	2015-09-28 12:22:30 +0000
+++ lib/lp/scripts/tests/test_garbo.py	2015-11-21 11:14:12 +0000
@@ -122,8 +122,8 @@
 from lp.soyuz.model.livefsbuild import LiveFSFile
 from lp.soyuz.model.reporting import LatestPersonSourcePackageReleaseCache
 from lp.testing import (
+    admin_logged_in,
     FakeAdapterMixin,
-    admin_logged_in,
     person_logged_in,
     TestCase,
     TestCaseWithFactory,
@@ -1433,6 +1433,33 @@
         for person in people_enf_true:
             _assert_enf_by_person(person, True)
 
+    def test_DistroSeriesPublishingOptionsPopulator(self):
+        switch_dbuser('testadmin')
+        all_series = []
+        all_options = (
+            (False, False), (False, True), (True, False), (True, True))
+        for backports_not_automatic, include_long_descriptions in all_options:
+            series = self.factory.makeDistroSeries()
+            naked_series = removeSecurityProxy(series)
+            naked_series._backports_not_automatic = backports_not_automatic
+            naked_series._include_long_descriptions = include_long_descriptions
+            all_series.append(series)
+
+        self.runDaily()
+
+        for series, (backports_not_automatic, include_long_descriptions) in (
+                zip(all_series, all_options)):
+            expected_options = {
+                "backports_not_automatic": backports_not_automatic,
+                "include_long_descriptions": include_long_descriptions,
+                }
+            naked_series = removeSecurityProxy(series)
+            self.assertEqual(expected_options, naked_series.publishing_options)
+            self.assertEqual(
+                backports_not_automatic, series.backports_not_automatic)
+            self.assertEqual(
+                include_long_descriptions, series.include_long_descriptions)
+
 
 class TestGarboTasks(TestCaseWithFactory):
     layer = LaunchpadZopelessLayer


Follow ups