← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] lp:~cjwatson/launchpad/close-account-packaging into lp:launchpad

 

Colin Watson has proposed merging lp:~cjwatson/launchpad/close-account-packaging into lp:launchpad.

Commit message:
Handle packaging-related references in close-account.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~cjwatson/launchpad/close-account-packaging/+merge/361004
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~cjwatson/launchpad/close-account-packaging into lp:launchpad.
=== modified file 'lib/lp/registry/scripts/closeaccount.py'
--- lib/lp/registry/scripts/closeaccount.py	2018-12-04 13:00:56 +0000
+++ lib/lp/registry/scripts/closeaccount.py	2018-12-17 15:03:37 +0000
@@ -105,6 +105,7 @@
         ('messageapproval', 'posted_by'),
         ('packagecopyrequest', 'requester'),
         ('packagediff', 'requester'),
+        ('packageupload', 'signing_key_owner'),
         ('personlocation', 'last_modified_by'),
         ('persontransferjob', 'major_person'),
         ('persontransferjob', 'minor_person'),
@@ -117,6 +118,9 @@
         ('sourcepackagepublishinghistory', 'removed_by'),
         ('sourcepackagepublishinghistory', 'sponsor'),
         ('sourcepackagerecipebuild', 'requester'),
+        ('sourcepackagerelease', 'creator'),
+        ('sourcepackagerelease', 'maintainer'),
+        ('sourcepackagerelease', 'signing_key_owner'),
         ('specification', 'approver'),
         ('specification', 'completer'),
         ('specification', 'drafter'),
@@ -267,6 +271,10 @@
         ('ArchivePermission', 'person'),
         ('GitRuleGrant', 'grantee'),
         ('SharingJob', 'grantee'),
+
+        # Soyuz reporting
+        ('LatestPersonSourcePackageReleaseCache', 'creator'),
+        ('LatestPersonSourcePackageReleaseCache', 'maintainer'),
         ]
     for table, person_id_column in removals:
         table_notification(table)

=== modified file 'lib/lp/registry/scripts/tests/test_closeaccount.py'
--- lib/lp/registry/scripts/tests/test_closeaccount.py	2018-12-04 17:33:38 +0000
+++ lib/lp/registry/scripts/tests/test_closeaccount.py	2018-12-17 15:03:37 +0000
@@ -17,19 +17,26 @@
 from zope.security.proxy import removeSecurityProxy
 
 from lp.answers.enums import QuestionStatus
+from lp.app.interfaces.launchpad import ILaunchpadCelebrities
 from lp.registry.interfaces.person import IPersonSet
 from lp.registry.scripts.closeaccount import CloseAccountScript
+from lp.scripts.garbo import PopulateLatestPersonSourcePackageReleaseCache
 from lp.services.database.sqlbase import flush_database_caches
 from lp.services.identity.interfaces.account import (
     AccountStatus,
     IAccountSet,
     )
 from lp.services.identity.interfaces.emailaddress import IEmailAddressSet
-from lp.services.log.logger import BufferLogger
+from lp.services.log.logger import (
+    BufferLogger,
+    DevNullLogger,
+    )
 from lp.services.scripts.base import LaunchpadScriptFailure
+from lp.soyuz.enums import PackagePublishingStatus
+from lp.soyuz.tests.test_publishing import SoyuzTestPublisher
 from lp.testing import TestCaseWithFactory
 from lp.testing.dbuser import dbuser
-from lp.testing.layers import ZopelessDatabaseLayer
+from lp.testing.layers import LaunchpadZopelessLayer
 
 
 class TestCloseAccount(TestCaseWithFactory):
@@ -41,7 +48,7 @@
     script.  See Bug #120506 for more details.
     """
 
-    layer = ZopelessDatabaseLayer
+    layer = LaunchpadZopelessLayer
 
     def makeScript(self, test_args):
         script = CloseAccountScript(test_args=test_args)
@@ -248,3 +255,29 @@
         for question_status, question in questions.items():
             self.assertEqual(question_status, question.status)
             self.assertIsNone(question.whiteboard)
+
+    def test_handles_packaging_references(self):
+        person = self.factory.makePerson()
+        person_id = person.id
+        account_id = person.account.id
+        self.factory.makeGPGKey(person)
+        publisher = SoyuzTestPublisher()
+        publisher.person = person
+        ubuntu = getUtility(ILaunchpadCelebrities).ubuntu
+        spph = publisher.getPubSource(
+            status=PackagePublishingStatus.PUBLISHED,
+            distroseries=ubuntu.currentseries,
+            maintainer=person, creator=person)
+        with dbuser('garbo_frequently'):
+            job = PopulateLatestPersonSourcePackageReleaseCache(
+                DevNullLogger())
+            while not job.isDone():
+                job(chunk_size=100)
+        self.assertTrue(person.hasMaintainedPackages())
+        script = self.makeScript([nativeString(person.name)])
+        with dbuser('launchpad'):
+            self.runScript(script)
+        self.assertRemoved(account_id, person_id)
+        self.assertEqual(person, spph.package_maintainer)
+        self.assertEqual(person, spph.package_creator)
+        self.assertFalse(person.hasMaintainedPackages())

=== modified file 'lib/lp/scripts/garbo.py'
--- lib/lp/scripts/garbo.py	2018-05-01 08:59:57 +0000
+++ lib/lp/scripts/garbo.py	2018-12-17 15:03:37 +0000
@@ -648,6 +648,7 @@
     def __call__(self, chunk_size):
         cache_filter_data = []
         new_records = dict()
+        person_ids = set()
         # Create a map of new published spr data for creators and maintainers.
         # The map is keyed on (creator/maintainer, archive, spn, distroseries).
         for new_published_spr_data in self.getPendingUpdates()[:chunk_size]:
@@ -661,8 +662,10 @@
                 maintainer_id, None, archive_id, distroseries_id, spn_id)
             creator_key = (
                 None, creator_id, archive_id, distroseries_id, spn_id)
-            new_records[maintainer_key] = maintainer_key + value
-            new_records[creator_key] = creator_key + value
+            new_records[maintainer_key] = list(maintainer_key + value)
+            new_records[creator_key] = list(creator_key + value)
+            person_ids.add(maintainer_id)
+            person_ids.add(creator_id)
             self.last_spph_id = spph_id
 
         # Gather all the current cached reporting records corresponding to the
@@ -689,14 +692,32 @@
             existing_records[key] = pytz.UTC.localize(
                 lpsprc_record.dateuploaded)
 
+        # Gather account statuses for creators and maintainers.
+        # Deactivating or closing an account removes its LPSPRC rows, and we
+        # don't want to resurrect them.
+        account_statuses = dict(self.store.find(
+            (Person.id, Account.status),
+            Person.id.is_in(person_ids), Person.account == Account.id))
+        ignore_statuses = (AccountStatus.DEACTIVATED, AccountStatus.CLOSED)
+        for new_record in new_records.values():
+            if (new_record[0] is not None and
+                    account_statuses.get(new_record[0]) in ignore_statuses):
+                new_record[0] = None
+            if (new_record[1] is not None and
+                    account_statuses.get(new_record[1]) in ignore_statuses):
+                new_record[1] = None
+
         # Figure out what records from the new published spr data need to be
         # inserted and updated into the cache table.
         inserts = dict()
         updates = dict()
         for key, new_published_spr_data in new_records.items():
             existing_dateuploaded = existing_records.get(key, None)
-            new_dateuploaded = new_published_spr_data[7]
-            if existing_dateuploaded is None:
+            new_maintainer, new_creator, _, _, _, _, _, new_dateuploaded, _ = (
+                new_published_spr_data)
+            if new_maintainer is None and new_creator is None:
+                continue
+            elif existing_dateuploaded is None:
                 target = inserts
             else:
                 target = updates

=== modified file 'lib/lp/scripts/tests/test_garbo.py'
--- lib/lp/scripts/tests/test_garbo.py	2018-05-01 08:59:57 +0000
+++ lib/lp/scripts/tests/test_garbo.py	2018-12-17 15:03:37 +0000
@@ -29,9 +29,15 @@
     Storm,
     )
 from storm.store import Store
+from testtools.content import Content
+from testtools.content_type import UTF8_TEXT
 from testtools.matchers import (
+    AfterPreprocessing,
     Equals,
     GreaterThan,
+    Is,
+    MatchesListwise,
+    MatchesStructure,
     )
 import transaction
 from zope.component import getUtility
@@ -417,6 +423,9 @@
         self.log_buffer = StringIO()
         handler = logging.StreamHandler(self.log_buffer)
         self.log.addHandler(handler)
+        self.addDetail(
+            'garbo-log',
+            Content(UTF8_TEXT, lambda: [self.log_buffer.getvalue()]))
 
     def runFrequently(self, maximum_chunk_size=2, test_args=()):
         switch_dbuser('garbo_daily')
@@ -1380,12 +1389,12 @@
     def test_PopulateLatestPersonSourcePackageReleaseCache(self):
         switch_dbuser('testadmin')
         # Make some same test data - we create published source package
-        # releases for 2 different creators and maintainers.
+        # releases for three different creators and maintainers.
         creators = []
-        for _ in range(2):
+        for _ in range(3):
             creators.append(self.factory.makePerson())
         maintainers = []
-        for _ in range(2):
+        for _ in range(3):
             maintainers.append(self.factory.makePerson())
 
         spn = self.factory.makeSourcePackageName()
@@ -1415,9 +1424,22 @@
             creator=creators[1], maintainer=maintainers[1],
             distroseries=distroseries, sourcepackagename=spn,
             date_uploaded=datetime(2010, 12, 4, tzinfo=UTC))
+        self.factory.makeSourcePackagePublishingHistory(
+            status=PackagePublishingStatus.PUBLISHED,
+            sourcepackagerelease=spr4)
+        spr5 = self.factory.makeSourcePackageRelease(
+            creator=creators[2], maintainer=maintainers[2],
+            distroseries=distroseries, sourcepackagename=spn,
+            date_uploaded=datetime(2010, 12, 5, tzinfo=UTC))
         spph_1 = self.factory.makeSourcePackagePublishingHistory(
             status=PackagePublishingStatus.PUBLISHED,
-            sourcepackagerelease=spr4)
+            sourcepackagerelease=spr5)
+
+        # Some of the creators and maintainers have inactive accounts.
+        removeSecurityProxy(creators[2].account).status = (
+            AccountStatus.DEACTIVATED)
+        removeSecurityProxy(maintainers[2].account).status = (
+            AccountStatus.CLOSED)
 
         transaction.commit()
         self.runFrequently()
@@ -1430,31 +1452,37 @@
                 params=[u'PopulateLatestPersonSourcePackageReleaseCache']
             ).get_one())
 
-        def _assert_release_by_creator(creator, spr):
+        def _assert_releases_by_creator(creator, sprs):
             release_records = store.find(
                 LatestPersonSourcePackageReleaseCache,
                 LatestPersonSourcePackageReleaseCache.creator_id == creator.id)
-            [record] = list(release_records)
-            self.assertEqual(spr.creator, record.creator)
-            self.assertIsNone(record.maintainer_id)
-            self.assertEqual(
-                spr.dateuploaded, UTC.localize(record.dateuploaded))
+            self.assertThat(list(release_records), MatchesListwise([
+                MatchesStructure(
+                    creator=Equals(spr.creator),
+                    maintainer_id=Is(None),
+                    dateuploaded=AfterPreprocessing(
+                        UTC.localize, Equals(spr.dateuploaded)))
+                for spr in sprs]))
 
-        def _assert_release_by_maintainer(maintainer, spr):
+        def _assert_releases_by_maintainer(maintainer, sprs):
             release_records = store.find(
                 LatestPersonSourcePackageReleaseCache,
                 LatestPersonSourcePackageReleaseCache.maintainer_id ==
                 maintainer.id)
-            [record] = list(release_records)
-            self.assertEqual(spr.maintainer, record.maintainer)
-            self.assertIsNone(record.creator_id)
-            self.assertEqual(
-                spr.dateuploaded, UTC.localize(record.dateuploaded))
+            self.assertThat(list(release_records), MatchesListwise([
+                MatchesStructure(
+                    maintainer=Equals(spr.maintainer),
+                    creator_id=Is(None),
+                    dateuploaded=AfterPreprocessing(
+                        UTC.localize, Equals(spr.dateuploaded)))
+                for spr in sprs]))
 
-        _assert_release_by_creator(creators[0], spr2)
-        _assert_release_by_creator(creators[1], spr4)
-        _assert_release_by_maintainer(maintainers[0], spr3)
-        _assert_release_by_maintainer(maintainers[1], spr4)
+        _assert_releases_by_creator(creators[0], [spr2])
+        _assert_releases_by_creator(creators[1], [spr4])
+        _assert_releases_by_creator(creators[2], [])
+        _assert_releases_by_maintainer(maintainers[0], [spr3])
+        _assert_releases_by_maintainer(maintainers[1], [spr4])
+        _assert_releases_by_maintainer(maintainers[2], [])
 
         job_data = load_garbo_job_state(
             'PopulateLatestPersonSourcePackageReleaseCache')
@@ -1463,21 +1491,23 @@
         # Create a newer published source package release and ensure the
         # release cache table is correctly updated.
         switch_dbuser('testadmin')
-        spr5 = self.factory.makeSourcePackageRelease(
+        spr6 = self.factory.makeSourcePackageRelease(
             creator=creators[1], maintainer=maintainers[1],
             distroseries=distroseries, sourcepackagename=spn,
             date_uploaded=datetime(2010, 12, 5, tzinfo=UTC))
         spph_2 = self.factory.makeSourcePackagePublishingHistory(
             status=PackagePublishingStatus.PUBLISHED,
-            sourcepackagerelease=spr5)
+            sourcepackagerelease=spr6)
 
         transaction.commit()
         self.runFrequently()
 
-        _assert_release_by_creator(creators[0], spr2)
-        _assert_release_by_creator(creators[1], spr5)
-        _assert_release_by_maintainer(maintainers[0], spr3)
-        _assert_release_by_maintainer(maintainers[1], spr5)
+        _assert_releases_by_creator(creators[0], [spr2])
+        _assert_releases_by_creator(creators[1], [spr6])
+        _assert_releases_by_creator(creators[2], [])
+        _assert_releases_by_maintainer(maintainers[0], [spr3])
+        _assert_releases_by_maintainer(maintainers[1], [spr6])
+        _assert_releases_by_maintainer(maintainers[2], [])
 
         job_data = load_garbo_job_state(
             'PopulateLatestPersonSourcePackageReleaseCache')


Follow ups