← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] ~andrey-fedoseev/launchpad:uct-import-upstream-packaging-model into launchpad:master

 

Andrey Fedoseev has proposed merging ~andrey-fedoseev/launchpad:uct-import-upstream-packaging-model into launchpad:master.

Commit message:
UCT import: use `Packaging` model for `upstream`

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~andrey-fedoseev/launchpad/+git/launchpad/+merge/429109

Previously, we were trying to find an LP `Product` with exactly the same name as a package in UCT record to handle the status of `upstream`.

Now, we use the `Packaging` model to locate a `Product` by package name.

More specifically, we use the `DistributionSourcePackage.upstream_product` property for that.
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of ~andrey-fedoseev/launchpad:uct-import-upstream-packaging-model into launchpad:master.
diff --git a/lib/lp/bugs/scripts/tests/test_uct.py b/lib/lp/bugs/scripts/tests/test_uct.py
index 00f995d..7d2688d 100644
--- a/lib/lp/bugs/scripts/tests/test_uct.py
+++ b/lib/lp/bugs/scripts/tests/test_uct.py
@@ -186,14 +186,17 @@ class TextCVE(TestCaseWithFactory):
             status=SeriesStatus.DEVELOPMENT,
             name="kinetic",
         )
-        product_1 = self.factory.makeProduct()
-        product_2 = self.factory.makeProduct()
-        dsp1 = self.factory.makeDistributionSourcePackage(
-            sourcepackagename=product_1.name, distribution=ubuntu
-        )
-        dsp2 = self.factory.makeDistributionSourcePackage(
-            sourcepackagename=product_2.name, distribution=ubuntu
-        )
+        dsp1 = self.factory.makeDistributionSourcePackage(distribution=ubuntu)
+        dsp2 = self.factory.makeDistributionSourcePackage(distribution=ubuntu)
+        product_1 = self.factory.makePackagingLink(
+            sourcepackagename=dsp1.sourcepackagename,
+            distroseries=current_series,
+        ).productseries.product
+        product_2 = self.factory.makePackagingLink(
+            sourcepackagename=dsp2.sourcepackagename,
+            distroseries=current_series,
+        ).productseries.product
+
         assignee = self.factory.makePerson()
 
         self.uct_record = UCTRecord(
@@ -374,12 +377,14 @@ class TextCVE(TestCaseWithFactory):
             upstream_packages=[
                 CVE.UpstreamPackage(
                     package=product_1,
+                    package_name=dsp1.sourcepackagename,
                     importance=None,
                     status=BugTaskStatus.FIXRELEASED,
                     status_explanation="reason 4",
                 ),
-                CVE.SeriesPackage(
+                CVE.UpstreamPackage(
                     package=product_2,
+                    package_name=dsp2.sourcepackagename,
                     importance=None,
                     status=BugTaskStatus.FIXRELEASED,
                     status_explanation="",
@@ -450,14 +455,21 @@ class TestUCTImporterExporter(TestCaseWithFactory):
             status=SeriesStatus.CURRENT,
             name="trusty",
         )
-        self.product_1 = self.factory.makeProduct()
-        self.product_2 = self.factory.makeProduct()
         self.ubuntu_package = self.factory.makeDistributionSourcePackage(
-            sourcepackagename=self.product_1.name, distribution=self.ubuntu
+            distribution=self.ubuntu
         )
         self.esm_package = self.factory.makeDistributionSourcePackage(
-            sourcepackagename=self.product_2.name, distribution=self.esm
+            distribution=self.esm
         )
+        self.product_1 = self.factory.makePackagingLink(
+            sourcepackagename=self.ubuntu_package.sourcepackagename,
+            distroseries=self.ubuntu_current_series,
+        ).productseries.product
+        self.product_2 = self.factory.makePackagingLink(
+            sourcepackagename=self.esm_package.sourcepackagename,
+            distroseries=self.esm_current_series,
+        ).productseries.product
+
         for series in (
             self.ubuntu_supported_series,
             self.ubuntu_current_series,
@@ -548,12 +560,14 @@ class TestUCTImporterExporter(TestCaseWithFactory):
             upstream_packages=[
                 CVE.UpstreamPackage(
                     package=self.product_1,
+                    package_name=self.ubuntu_package.sourcepackagename,
                     importance=BugTaskImportance.HIGH,
                     status=BugTaskStatus.FIXRELEASED,
                     status_explanation="fix released",
                 ),
                 CVE.UpstreamPackage(
                     package=self.product_2,
+                    package_name=self.esm_package.sourcepackagename,
                     importance=BugTaskImportance.LOW,
                     status=BugTaskStatus.WONTFIX,
                     status_explanation="ignored",
@@ -646,7 +660,7 @@ class TestUCTImporterExporter(TestCaseWithFactory):
             self.assertIn(upstream_package.package, bug_tasks_by_target)
             t = bug_tasks_by_target[upstream_package.package]
             package_importance = package_importances[
-                upstream_package.package.name
+                upstream_package.package_name.name
             ]
             sp_importance = upstream_package.importance or package_importance
             self.assertEqual(sp_importance, t.importance)
diff --git a/lib/lp/bugs/scripts/uct/models.py b/lib/lp/bugs/scripts/uct/models.py
index 440f79d..caf9072 100644
--- a/lib/lp/bugs/scripts/uct/models.py
+++ b/lib/lp/bugs/scripts/uct/models.py
@@ -18,7 +18,6 @@ from lp.bugs.interfaces.bugtask import BugTaskImportance, BugTaskStatus
 from lp.registry.interfaces.distribution import IDistributionSet
 from lp.registry.interfaces.distroseries import IDistroSeriesSet
 from lp.registry.interfaces.person import IPersonSet
-from lp.registry.interfaces.product import IProductSet
 from lp.registry.interfaces.series import SeriesStatus
 from lp.registry.interfaces.sourcepackagename import ISourcePackageNameSet
 from lp.registry.model.distribution import Distribution
@@ -440,6 +439,7 @@ class CVE:
         "UpstreamPackage",
         (
             ("package", Product),
+            ("package_name", SourcePackageName),
             ("importance", Optional[BugTaskImportance]),
             ("status", BugTaskStatus),
             ("status_explanation", str),
@@ -530,10 +530,13 @@ class CVE:
 
         distro_packages = []
         series_packages = []
-        upstream_packages = []
 
         spn_set = getUtility(ISourcePackageNameSet)
 
+        upstream_statuses = (
+            OrderedDict()
+        )  # type: Dict[SourcePackageName, UCTRecord.SeriesPackageStatus]
+
         for uct_package in uct_record.packages:
             source_package_name = spn_set.getOrCreateByName(uct_package.name)
             package_importance = (
@@ -558,19 +561,7 @@ class CVE:
                 )
 
                 if uct_package_status.series == "upstream":
-                    product = cls.get_product(uct_package.name)
-                    if product is None:
-                        continue
-                    upstream_packages.append(
-                        cls.UpstreamPackage(
-                            package=product,
-                            importance=series_package_importance,
-                            status=cls.BUG_TASK_STATUS_MAP[
-                                uct_package_status.status
-                            ],
-                            status_explanation=uct_package_status.reason,
-                        )
-                    )
+                    upstream_statuses[source_package_name] = uct_package_status
                     continue
 
                 distro_series = cls.get_distro_series(
@@ -603,6 +594,37 @@ class CVE:
                     )
                 )
 
+        upstream_packages = []
+        for source_package_name, upstream_status in upstream_statuses.items():
+            for distro_package in distro_packages:
+                if (
+                    source_package_name
+                    != distro_package.package.sourcepackagename
+                ):
+                    continue
+                product = distro_package.package.upstream_product
+                if product is not None:
+                    break
+            else:
+                logger.warning(
+                    "Could not find the assignee: %s", uct_record.assigned_to
+                )
+                product = None
+
+            upstream_packages.append(
+                cls.UpstreamPackage(
+                    package=product,
+                    package_name=source_package_name,
+                    importance=(
+                        cls.PRIORITY_MAP[upstream_status.priority]
+                        if upstream_status.priority
+                        else None
+                    ),
+                    status=cls.BUG_TASK_STATUS_MAP[upstream_status.status],
+                    status_explanation=upstream_status.reason,
+                )
+            )
+
         if uct_record.assigned_to:
             assignee = getUtility(IPersonSet).getByName(uct_record.assigned_to)
             if not assignee:
@@ -708,7 +730,7 @@ class CVE:
                     else None
                 ),
             )
-            package_name = upstream_package.package.name
+            package_name = upstream_package.package_name.name
             if package_name in packages_by_name:
                 packages_by_name[package_name].statuses.append(status)
             else:
@@ -801,10 +823,3 @@ class CVE:
                 "Could not find the distro series: %s", distro_series_name
             )
         return distro_series
-
-    @classmethod
-    def get_product(cls, product_name: str) -> Optional[Product]:
-        product = getUtility(IProductSet).getByName(product_name)
-        if not product:
-            logger.warning("Could not find the product: %s", product_name)
-        return product
diff --git a/lib/lp/bugs/scripts/uct/uctexport.py b/lib/lp/bugs/scripts/uct/uctexport.py
index 65e274c..85e4ae0 100644
--- a/lib/lp/bugs/scripts/uct/uctexport.py
+++ b/lib/lp/bugs/scripts/uct/uctexport.py
@@ -4,7 +4,7 @@
 import logging
 from collections import defaultdict
 from pathlib import Path
-from typing import List, NamedTuple, Optional
+from typing import Dict, List, NamedTuple, Optional
 
 from zope.component import getUtility
 from zope.security.proxy import removeSecurityProxy
@@ -20,6 +20,7 @@ from lp.registry.model.distributionsourcepackage import (
 )
 from lp.registry.model.product import Product
 from lp.registry.model.sourcepackage import SourcePackage
+from lp.registry.model.sourcepackagename import SourcePackageName
 
 __all__ = [
     "UCTExporter",
@@ -112,6 +113,7 @@ class UCTExporter:
         #  DistroPackage importance
         package_importances = {}
 
+        package_name_by_product = {}  # type: Dict[Product, SourcePackageName]
         # We need to process all distribution package tasks before processing
         # the distro-series tasks to collect importance value for each package.
         distro_packages = []
@@ -119,6 +121,9 @@ class UCTExporter:
             target = removeSecurityProxy(bug_task.target)
             if not isinstance(target, DistributionSourcePackage):
                 continue
+            product = target.upstream_product
+            if product:
+                package_name_by_product[product] = target.sourcepackagename
             dp_importance = bug_task.importance
             package_importances[target.sourcepackagename] = dp_importance
             distro_packages.append(
@@ -157,11 +162,19 @@ class UCTExporter:
             target = removeSecurityProxy(bug_task.target)
             if not isinstance(target, Product):
                 continue
+            if target not in package_name_by_product:
+                logger.warning(
+                    "Could not find a source package for product %s",
+                    target.name,
+                )
+                continue
+            package_name = package_name_by_product[target]
             up_importance = bug_task.importance
             package_importance = package_importances.get(target.name)
             upstream_packages.append(
                 CVE.UpstreamPackage(
                     package=target,
+                    package_name=package_name,
                     importance=(
                         up_importance
                         if up_importance != package_importance
diff --git a/lib/lp/bugs/scripts/uct/uctimport.py b/lib/lp/bugs/scripts/uct/uctimport.py
index 5f94703..71823fe 100644
--- a/lib/lp/bugs/scripts/uct/uctimport.py
+++ b/lib/lp/bugs/scripts/uct/uctimport.py
@@ -393,7 +393,7 @@ class UCTImporter:
             if isinstance(sp, CVE.SeriesPackage):
                 package_name = sp.package.sourcepackagename.name
             elif isinstance(sp, CVE.UpstreamPackage):
-                package_name = sp.package.name
+                package_name = sp.package_name.name
             else:
                 raise AssertionError()
             package_importance = package_importances[package_name]