← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] ~cjwatson/launchpad:person-oci-project into launchpad:master

 

Colin Watson has proposed merging ~cjwatson/launchpad:person-oci-project into launchpad:master with ~twom/launchpad:oci-gitrepository as a prerequisite.

Commit message:
Add PersonOCIProject

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)
Related bugs:
  Bug #1847444 in Launchpad itself: "Support OCI image building"
  https://bugs.launchpad.net/launchpad/+bug/1847444

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

This is analogous to PersonProduct and PersonDistributionSourcePackage, and helps us represent Git repositories for a person on an OCI project.
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of ~cjwatson/launchpad:person-oci-project into launchpad:master.
diff --git a/lib/lp/registry/browser/configure.zcml b/lib/lp/registry/browser/configure.zcml
index 44694a1..018a53c 100644
--- a/lib/lp/registry/browser/configure.zcml
+++ b/lib/lp/registry/browser/configure.zcml
@@ -1,4 +1,4 @@
-<!-- Copyright 2009-2015 Canonical Ltd.  This software is licensed under the
+<!-- Copyright 2009-2019 Canonical Ltd.  This software is licensed under the
      GNU Affero General Public License version 3 (see the file LICENSE).
 -->
 
@@ -2519,6 +2519,11 @@
                  PersonDistributionSourcePackageFacets"
         />
     <browser:url
+        for="lp.registry.interfaces.personociproject.IPersonOCIProject"
+        path_expression="string:${oci_project/pillar/name}/+oci/${oci_project/name}"
+        attribute_to_parent="person"
+        />
+    <browser:url
         for="lp.registry.interfaces.personproduct.IPersonProduct"
         path_expression="product/name"
         attribute_to_parent="person"
diff --git a/lib/lp/registry/configure.zcml b/lib/lp/registry/configure.zcml
index c5b2673..c95a7b2 100644
--- a/lib/lp/registry/configure.zcml
+++ b/lib/lp/registry/configure.zcml
@@ -1,4 +1,4 @@
-<!-- Copyright 2009-2018 Canonical Ltd.  This software is licensed under the
+<!-- Copyright 2009-2019 Canonical Ltd.  This software is licensed under the
      GNU Affero General Public License version 3 (see the file LICENSE).
 -->
 
@@ -2199,6 +2199,21 @@
             interface="lp.registry.interfaces.personnotification.IPersonNotificationSet"/>
     </securedutility>
 
+    <!-- PersonOCIProject -->
+
+    <class
+        class="lp.registry.model.personociproject.PersonOCIProject">
+        <allow
+            interface="lp.registry.interfaces.personociproject.IPersonOCIProject"/>
+    </class>
+
+    <securedutility
+        component="lp.registry.model.personociproject.PersonOCIProject"
+        provides="lp.registry.interfaces.personociproject.IPersonOCIProjectFactory">
+        <allow
+            interface="lp.registry.interfaces.personociproject.IPersonOCIProjectFactory"/>
+    </securedutility>
+
     <!-- PersonProduct -->
 
     <class
diff --git a/lib/lp/registry/interfaces/ociproject.py b/lib/lp/registry/interfaces/ociproject.py
index 64261b9..0750767 100644
--- a/lib/lp/registry/interfaces/ociproject.py
+++ b/lib/lp/registry/interfaces/ociproject.py
@@ -55,6 +55,7 @@ class IOCIProjectView(IHasGitRepositories, Interface):
         value_type=Reference(schema=Interface))
 
     name = Attribute(_("Name"))
+    display_name = Attribute(_("Display name for this OCI project."))
 
 
 class IOCIProjectEditableAttributes(IBugTarget):
diff --git a/lib/lp/registry/interfaces/personociproject.py b/lib/lp/registry/interfaces/personociproject.py
new file mode 100644
index 0000000..c2b89d2
--- /dev/null
+++ b/lib/lp/registry/interfaces/personociproject.py
@@ -0,0 +1,34 @@
+# Copyright 2019 Canonical Ltd.  This software is licensed under the
+# GNU Affero General Public License version 3 (see the file LICENSE).
+
+"""A person's view on an OCI project."""
+
+from __future__ import absolute_import, print_function, unicode_literals
+
+__metaclass__ = type
+__all__ = [
+    'IPersonOCIProject',
+    'IPersonOCIProjectFactory',
+    ]
+
+from lazr.restful.fields import Reference
+from zope.interface import Interface
+from zope.schema import TextLine
+
+from lp.registry.interfaces.ociproject import IOCIProject
+from lp.registry.interfaces.person import IPerson
+
+
+class IPersonOCIProject(Interface):
+    """A person's view on an OCI project."""
+
+    person = Reference(IPerson)
+    oci_project = Reference(IOCIProject)
+    displayname = TextLine()
+
+
+class IPersonOCIProjectFactory(Interface):
+    """Creates `IPersonOCIProject`s."""
+
+    def create(person, oci_project):
+        """Create and return an `IPersonOCIProject`."""
diff --git a/lib/lp/registry/model/ociproject.py b/lib/lp/registry/model/ociproject.py
index e718881..f0975b3 100644
--- a/lib/lp/registry/model/ociproject.py
+++ b/lib/lp/registry/model/ociproject.py
@@ -76,16 +76,13 @@ class OCIProject(BugTargetBase, StormBase):
         return self.distribution
 
     @property
-    def bugtargetname(self):
-        """See `IBugTarget`."""
+    def display_name(self):
+        """See `IOCIProject`."""
         return "OCI project %s for %s" % (
             self.ociprojectname.name, self.pillar.name)
 
-    @property
-    def bugtargetdisplayname(self):
-        """See `IBugTarget`."""
-        return "OCI project %s for %s" % (
-            self.ociprojectname.name, self.pillar.name)
+    bugtargetname = display_name
+    bugtargetdisplayname = display_name
 
     def newSeries(self, name, summary, registrant,
                   status=SeriesStatus.DEVELOPMENT, date_created=DEFAULT):
diff --git a/lib/lp/registry/model/personociproject.py b/lib/lp/registry/model/personociproject.py
new file mode 100644
index 0000000..92f4d10
--- /dev/null
+++ b/lib/lp/registry/model/personociproject.py
@@ -0,0 +1,46 @@
+# Copyright 2019 Canonical Ltd.  This software is licensed under the
+# GNU Affero General Public License version 3 (see the file LICENSE).
+
+"""A person's view on an OCI project."""
+
+from __future__ import absolute_import, print_function, unicode_literals
+
+__metaclass__ = type
+__all__ = []
+
+from zope.interface import (
+    implementer,
+    provider,
+    )
+
+from lp.registry.interfaces.personociproject import (
+    IPersonOCIProject,
+    IPersonOCIProjectFactory,
+    )
+
+
+@implementer(IPersonOCIProject)
+@provider(IPersonOCIProjectFactory)
+class PersonOCIProject:
+
+    def __init__(self, person, oci_project):
+        self.person = person
+        self.oci_project = oci_project
+
+    @staticmethod
+    def create(person, oci_project):
+        return PersonOCIProject(person, oci_project)
+
+    @property
+    def displayname(self):
+        return '%s in %s' % (
+            self.person.display_name, self.oci_project.display_name)
+
+    def __eq__(self, other):
+        return (
+            IPersonOCIProject.providedBy(other) and
+            self.person.id == other.person.id and
+            self.oci_project == other.oci_project)
+
+    def __ne__(self, other):
+        return not self == other
diff --git a/lib/lp/registry/tests/test_personociproject.py b/lib/lp/registry/tests/test_personociproject.py
new file mode 100644
index 0000000..650fa84
--- /dev/null
+++ b/lib/lp/registry/tests/test_personociproject.py
@@ -0,0 +1,35 @@
+# Copyright 2019 Canonical Ltd.  This software is licensed under the
+# GNU Affero General Public License version 3 (see the file LICENSE).
+
+"""Test the Person/OCIProject non-database class."""
+
+from __future__ import absolute_import, print_function, unicode_literals
+
+__metaclass__ = type
+
+from zope.component import getUtility
+
+from lp.registry.interfaces.personociproject import IPersonOCIProjectFactory
+from lp.services.webapp.publisher import canonical_url
+from lp.testing import TestCaseWithFactory
+from lp.testing.layers import DatabaseFunctionalLayer
+
+
+class TestPersonOCIProject(TestCaseWithFactory):
+    """Tests for `IPersonOCIProject`s."""
+
+    layer = DatabaseFunctionalLayer
+
+    def _makePersonOCIProject(self):
+        person = self.factory.makePerson()
+        oci_project = self.factory.makeOCIProject()
+        return getUtility(IPersonOCIProjectFactory).create(person, oci_project)
+
+    def test_canonical_url(self):
+        # The canonical_url of a person OCIProject is
+        # ~person/pillar/+oci/ociprojectname.
+        pocip = self._makePersonOCIProject()
+        expected = 'http://launchpad.test/~%s/%s/+oci/%s' % (
+            pocip.person.name, pocip.oci_project.pillar.name,
+            pocip.oci_project.name)
+        self.assertEqual(expected, canonical_url(pocip))