← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] ~twom/launchpad:oci-recipe-target into launchpad:master

 

Tom Wardill has proposed merging ~twom/launchpad:oci-recipe-target into launchpad:master with ~twom/launchpad:oci-recipe-name as a prerequisite.

Commit message:
Implement OCIRecipeTarget

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

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

Add model, interfaces, ZCML and security.cfg

-- 
Your team Launchpad code reviewers is requested to review the proposed merge of ~twom/launchpad:oci-recipe-target into launchpad:master.
diff --git a/database/schema/security.cfg b/database/schema/security.cfg
index 2a760b5..d72c691 100644
--- a/database/schema/security.cfg
+++ b/database/schema/security.cfg
@@ -1239,6 +1239,7 @@ public.message                          = SELECT, INSERT, UPDATE
 public.milestone                        = SELECT, INSERT, UPDATE
 public.openididentifier                 = SELECT
 public.ocirecipename                    = SELECT, INSERT, UPDATE
+public.ocirecipetarget                  = SELECT, INSERT, UPDATE, DELETE
 public.packageupload                    = SELECT, INSERT, UPDATE
 public.packageuploadbuild               = SELECT, INSERT, UPDATE
 public.packageuploadcustom              = SELECT, INSERT, UPDATE
@@ -1415,6 +1416,7 @@ public.messagechunk                     = SELECT, INSERT
 public.milestone                        = SELECT
 public.milestonetag                     = SELECT
 public.ocirecipename                    = SELECT
+public.ocirecipetarget                  = SELECT
 public.openididentifier                 = SELECT
 public.packagecopyjob                   = SELECT, INSERT
 public.packagediff                      = SELECT, INSERT, UPDATE, DELETE
@@ -1532,6 +1534,7 @@ public.messagechunk                     = SELECT, INSERT
 public.milestone                        = SELECT
 public.milestonetag                     = SELECT
 public.ocirecipename                    = SELECT
+public.ocirecipetarget                  = SELECT
 public.openididentifier                 = SELECT
 public.packagecopyjob                   = SELECT, INSERT, UPDATE
 public.packagediff                      = SELECT, UPDATE
@@ -1635,6 +1638,7 @@ public.messagechunk                     = SELECT, INSERT
 public.milestone                        = SELECT
 public.milestonetag                     = SELECT
 public.ocirecipename                    = SELECT
+public.ocirecipetarget                  = SELECT
 public.person                           = SELECT
 public.personlanguage                   = SELECT
 public.personsettings                   = SELECT
@@ -1837,6 +1841,7 @@ public.messagechunk                     = SELECT, INSERT
 public.milestone                        = SELECT
 public.milestonetag                     = SELECT, INSERT, DELETE
 public.ocirecipename                    = SELECT
+public.ocirecipetarget                  = SELECT
 public.openididentifier                 = SELECT
 public.packageset                       = SELECT
 public.packagesetgroup                  = SELECT
@@ -1957,6 +1962,7 @@ public.libraryfilecontent               = SELECT, INSERT
 public.message                          = SELECT, INSERT
 public.messagechunk                     = SELECT, INSERT
 public.ocirecipename                    = SELECT
+public.ocirecipetarget                  = SELECT
 public.openididentifier                 = SELECT
 public.person                           = SELECT
 public.product                          = SELECT
@@ -2015,6 +2021,7 @@ public.message                          = SELECT, INSERT
 public.messagechunk                     = SELECT, INSERT
 public.milestone                        = SELECT
 public.ocirecipename                    = SELECT
+public.ocirecipetarget                  = SELECT
 public.person                           = SELECT
 public.personsettings                   = SELECT
 public.previewdiff                      = SELECT, INSERT
@@ -2152,6 +2159,7 @@ public.message                          = SELECT, INSERT
 public.messagechunk                     = SELECT, INSERT
 public.milestonetag                     = SELECT
 public.ocirecipename                    = SELECT
+public.ocirecipetarget                  = SELECT
 public.person                           = SELECT, INSERT
 public.personsettings                   = SELECT, INSERT
 public.product                          = SELECT, INSERT, UPDATE
@@ -2269,6 +2277,7 @@ public.nameblacklist                    = SELECT, UPDATE
 public.oauthaccesstoken                 = SELECT, UPDATE
 public.oauthrequesttoken                = SELECT, UPDATE
 public.ocirecipename                    = SELECT
+public.ocirecipetarget                  = SELECT
 public.officialbugtag                   = SELECT
 public.openididentifier                 = SELECT, UPDATE
 public.packagecopyrequest               = SELECT, UPDATE
@@ -2387,6 +2396,7 @@ public.logintoken                       = SELECT, DELETE
 public.mailinglistsubscription          = SELECT, DELETE
 public.milestonetag                     = SELECT
 public.ocirecipename                    = SELECT
+public.ocirecipetarget                  = SELECT
 public.openidconsumerassociation        = SELECT, DELETE
 public.openidconsumernonce              = SELECT, DELETE
 public.person                           = SELECT, DELETE
@@ -2540,6 +2550,7 @@ public.emailaddress                     = SELECT
 public.gitrepository                    = SELECT
 public.job                              = SELECT, INSERT, UPDATE
 public.ocirecipename                    = SELECT
+public.ocirecipetarget                  = SELECT
 public.person                           = SELECT
 public.packaging                        = SELECT
 public.product                          = SELECT, UPDATE
@@ -2563,6 +2574,7 @@ public.bugtaskflat                      = SELECT
 public.distribution                     = SELECT
 public.distroseries                     = SELECT
 public.ocirecipename                    = SELECT
+public.ocirecipetarget                  = SELECT
 public.product                          = SELECT
 public.productseries                    = SELECT
 public.sourcepackagename                = SELECT
@@ -2575,6 +2587,7 @@ public.distribution                     = SELECT
 public.gitrepository                    = SELECT
 public.job                              = SELECT, UPDATE
 public.ocirecipename                    = SELECT
+public.ocirecipetarget                  = SELECT
 public.person                           = SELECT
 public.product                          = SELECT
 public.snap                             = SELECT
diff --git a/lib/lp/registry/configure.zcml b/lib/lp/registry/configure.zcml
index 047a31b..f2dc350 100644
--- a/lib/lp/registry/configure.zcml
+++ b/lib/lp/registry/configure.zcml
@@ -734,6 +734,29 @@
             interface="lp.registry.interfaces.ocirecipename.IOCIRecipeNameSet"/>
     </class>
 
+    <!-- OCIRecipeTarget -->
+    <class
+        class="lp.registry.model.ocirecipetarget.OCIRecipeTarget">
+        <require
+            permission="launchpad.View"
+            interface="lp.registry.interfaces.ocirecipetarget.IOCIRecipeTargetView"/>
+        <require
+            permission="launchpad.Edit"
+            interface="lp.registry.interfaces.ocirecipetarget.IOCIRecipeTargetEditableAttributes" />
+    </class>
+    <securedutility
+        class="lp.registry.model.ocirecipetarget.OCIRecipeTarget"
+        provides="lp.registry.interfaces.ocirecipetarget.IOCIRecipeTarget">
+        <allow
+            interface="lp.registry.interfaces.ocirecipetarget.IOCIRecipeTarget"/>
+    </securedutility>
+    <securedutility
+        class="lp.registry.model.ocirecipetarget.OCIRecipeTarget"
+        provides="lp.registry.interfaces.ocirecipetarget.IOCIRecipeTargetSource">
+        <allow
+            interface="lp.registry.interfaces.ocirecipetarget.IOCIRecipeTargetSource"/>
+    </securedutility>
+
     <!-- SourcePackageName -->
 
     <class
diff --git a/lib/lp/registry/interfaces/ocirecipetarget.py b/lib/lp/registry/interfaces/ocirecipetarget.py
new file mode 100644
index 0000000..3c9d46d
--- /dev/null
+++ b/lib/lp/registry/interfaces/ocirecipetarget.py
@@ -0,0 +1,87 @@
+from lazr.restful.declarations import (
+    export_as_webservice_entry,
+    exported,
+    )
+from lazr.restful.fields import Reference
+from zope.interface import Interface
+from zope.schema import (
+    Bool,
+    Datetime,
+    Int,
+    Text,
+    )
+
+from lp import _
+from lp.registry.interfaces.distribution import IDistribution
+from lp.registry.interfaces.ocirecipename import IOCIRecipeName
+from lp.registry.interfaces.person import IPerson
+from lp.registry.interfaces.product import IProduct
+from lp.registry.interfaces.role import IHasOwner
+
+
+class IOCIRecipeTargetView(Interface):
+    """IOCIRecipeTarget attributes that require launchpad.View permision."""
+
+    id = Int(title=_("OCI Recipe Target ID"),
+             required=True,
+             readonly=True
+             )
+    date_created = Datetime(title=_("Date created"), required=True)
+    date_last_modified = Datetime(title=_("Date last modified"), required=True)
+
+    registrant = exported(Reference(
+        IPerson,
+        title=_("The person that registered this recipe."),
+        required=True))
+
+class IOCIRecipeTargetEditableAttributes(IHasOwner):
+    """IOCIRecipeTarget attributes that can be edited.
+
+    These attributes need launchpad.View to see, and launchpad.Edit to change.
+    """
+
+    project = exported(Reference(
+        IProduct,
+        title=_("The project that this recipe is for.")))
+    distribution = exported(Reference(
+        IDistribution,
+        title=_("The distribution that this recipe is associated with.")))
+    ocirecipename = exported(Reference(
+        IOCIRecipeName,
+        title=_("The name of this recipe."),
+        required=True))
+    description = exported(Text(title=_("The description for this recipe.")))
+    bug_supervisor = exported(Reference(
+        IPerson,
+        title=_("The supervisor for bug reports on this recipe.")))
+    bug_reporting_guidelines = exported(Text(
+        title=_("Guidelines for reporting bugs with this recipe")))
+    bug_reported_acknowledgement = exported(Text(
+        title=_("Text displayed on a bug being successfully filed")))
+    enable_bugfiling_duplicate_search = exported(Bool(
+        title=_("Enable duplicate search on filing a bug on this recipe."),
+        required=True,
+        default=True))
+
+class IOCIRecipeTarget(IOCIRecipeTargetView,
+                       IOCIRecipeTargetEditableAttributes):
+
+    export_as_webservice_entry()
+
+
+class IOCIRecipeTargetSource(Interface):
+    """A utility of this interface that can be used to create and access
+       recipe targets.
+    """
+
+    def new(registrant, project, distribution, ocirecipename,
+            date_created=None, description=None, bug_supervisor=None,
+            bug_reporting_guidelines=None, bug_reported_acknowledgement=None,
+            bugfiling_duplicate_search=False):
+        """Create an `IOCIRecipeTarget`."""
+
+    def getByProject(project):
+        """Get the OCIRecipeTargets for a given project."""
+
+    def getByDistribution(distribution):
+        """Get the OCIRecipeTargets for a given distribution."""
diff --git a/lib/lp/registry/model/ocirecipetarget.py b/lib/lp/registry/model/ocirecipetarget.py
new file mode 100644
index 0000000..65db363
--- /dev/null
+++ b/lib/lp/registry/model/ocirecipetarget.py
@@ -0,0 +1,100 @@
+from datetime import datetime
+import pytz
+from storm.locals import (
+    Bool,
+    DateTime,
+    Int,
+    Reference,
+    Unicode,
+    )
+from zope.interface import (
+    implementer,
+    provider,
+    )
+
+from lp.services.database.interfaces import (
+    IMasterStore,
+    IStore,
+    )
+from lp.services.database.stormbase import StormBase
+from lp.registry.interfaces.ocirecipetarget import (
+    IOCIRecipeTarget,
+    IOCIRecipeTargetSource,
+    )
+
+
+@implementer(IOCIRecipeTarget)
+@provider(IOCIRecipeTargetSource)
+class OCIRecipeTarget(StormBase):
+    """See `IOCIRecipeTarget` and `IOCIRecipeTargetSource`."""
+
+    __storm_table__ = "OCIRecipeTarget"
+
+    id = Int(primary=True)
+    date_created = DateTime(
+        name="date_created", tzinfo=pytz.UTC, allow_none=False)
+    date_last_modified = DateTime(
+        name="date_last_modified", tzinfo=pytz.UTC, allow_none=False)
+
+    registrant_id = Int(name='registrant', allow_none=False)
+    registrant = Reference(registrant_id, "Person.id")
+
+    project_id = Int(name="project", allow_none=True)
+    project = Reference(project_id, "Product.id")
+
+    distribution_id = Int(name="distribution", allow_none=True)
+    distribution = Reference(distribution_id, "Distribution.id")
+
+    ocirecipename_id = Int(name="ocirecipename", allow_none=False)
+    ocirecipename = Reference(ocirecipename_id, "OCIRecipeName.id")
+
+    description = Unicode(name="description")
+
+    bug_supervisor_id = Int(name="bug_supervisor", allow_none=True)
+    bug_supervisor = Reference(bug_supervisor_id, "Person.id")
+
+    bug_reporting_guidelines = Unicode(name="bug_reporting_guidelines")
+    bug_reported_acknowledgement = Unicode(name="bug_reported_acknowledgement")
+    enable_bugfiling_duplicate_search = Bool(
+        name="enable_bugfiling_duplicate_search")
+
+    @staticmethod
+    def new(registrant, project, distribution, ocirecipename,
+                 date_created=None, description=None, bug_supervisor=None,
+                 bug_reporting_guidelines=None,
+                 bug_reported_acknowledgement=None,
+                 bugfiling_duplicate_search=False):
+        """See `IOCIRecipeTargetSource.new`."""
+        store = IMasterStore(OCIRecipeTarget)
+        target = OCIRecipeTarget()
+        if not date_created:
+            created_date = datetime.now(pytz.timezone('UTC'))
+            target.date_created = created_date
+            target.date_last_modified = created_date
+        target.registrant = registrant
+        target.project = project
+        target.distribution = distribution
+        target.ocirecipename = ocirecipename
+        target.description = description
+        target.bug_supervisor = bug_supervisor,
+        target.bug_reporting_guidelines = bug_reporting_guidelines
+        target.enable_bugfiling_duplicate_search = bugfiling_duplicate_search
+        store.add(target)
+        return target
+
+    @staticmethod
+    def getByProject(project):
+        """See `IOCIRecipeTargetSource`."""
+        targets = IStore(OCIRecipeTarget).find(
+            OCIRecipeTarget, OCIRecipeTarget.project == project).order_by(
+                OCIRecipeTarget.date_created)
+        return targets
+
+    @staticmethod
+    def getByDistribution(distribution):
+        """See `IOCIRecipeTargetSource`."""
+        targets = IStore(OCIRecipeTarget).find(
+            OCIRecipeTarget,
+            OCIRecipeTarget.distribution == distribution).order_by(
+                OCIRecipeTarget.date_created)
+        return targets
diff --git a/lib/lp/registry/tests/test_ocirecipetarget.py b/lib/lp/registry/tests/test_ocirecipetarget.py
index 5333cf6..560842b 100644
--- a/lib/lp/registry/tests/test_ocirecipetarget.py
+++ b/lib/lp/registry/tests/test_ocirecipetarget.py
@@ -4,9 +4,13 @@ from __future__ import absolute_import, print_function, unicode_literals
 
 __metaclass__ = type
 
+from lp.services.database.interfaces import IStore
 from lp.registry.model.ocirecipename import OCIRecipeName
 from lp.registry.model.ocirecipetarget import OCIRecipeTarget
-from lp.testing import TestCaseWithFactory
+from lp.testing import (
+    admin_logged_in,
+    TestCaseWithFactory,
+    )
 from lp.testing.layers import DatabaseFunctionalLayer
 
 
@@ -15,10 +19,29 @@ class OCIRecipeTargetTest(TestCaseWithFactory):
     layer = DatabaseFunctionalLayer
 
     def test_create(self):
-        name = OCIRecipeName(name="Test OCI Recipe Name")
-        registrant = self.factory.makePerson()
+        recipe_target = self.factory.makeOCIRecipeTarget()
+        self.assertTrue(recipe_target)
+
+    def test_getByProduct(self):
         project = self.factory.makeProduct()
+        recipe_target = self.factory.makeOCIRecipeTarget(project=project)
+
+        # Make sure there's more than one to get the result from
+        self.factory.makeOCIRecipeTarget(project=self.factory.makeProduct())
+
+        fetched_targets = OCIRecipeTarget.getByProject(project)
+        self.assertEqual(1, fetched_targets.count())
+        self.assertEqual(recipe_target, fetched_targets.first())
+
+    def test_getByDistribution(self):
         distribution = self.factory.makeDistribution()
-        target = OCIRecipeTarget(registrant, project, distribution, name)
-        print(target.date_created)
-        self.assertTrue(target)
+        recipe_target = self.factory.makeOCIRecipeTarget(
+            distribution=distribution)
+
+        # Make sure there's more than one to get the result from
+        self.factory.makeOCIRecipeTarget(
+            distribution=self.factory.makeDistribution())
+
+        fetched_targets = OCIRecipeTarget.getByDistribution(distribution)
+        self.assertEqual(1, fetched_targets.count())
+        self.assertEqual(recipe_target, fetched_targets.first())
diff --git a/lib/lp/testing/factory.py b/lib/lp/testing/factory.py
index 1d421fe..5098a11 100644
--- a/lib/lp/testing/factory.py
+++ b/lib/lp/testing/factory.py
@@ -201,7 +201,10 @@ from lp.registry.interfaces.mailinglistsubscription import (
     MailingListAutoSubscribePolicy,
     )
 from lp.registry.interfaces.ocirecipename import IOCIRecipeNameSet
-from lp.registry.interfaces.ocirecipetarget import IOCIRecipeTarget
+from lp.registry.interfaces.ocirecipetarget import (
+    IOCIRecipeTarget,
+    IOCIRecipeTargetSource,
+    )
 from lp.registry.interfaces.packaging import (
     IPackagingUtil,
     PackagingType,
@@ -4903,6 +4906,24 @@ class BareLaunchpadObjectFactory(ObjectFactory):
             name = self.getUniqueString(u"oci-base-name")
         return getUtility(IOCIRecipeNameSet).new(name)
 
+    def makeOCIRecipeTarget(self, registrant=None, project=None,
+                            distribution=None, ocirecipename=None,
+                            date_created=None, description=None,
+                            bug_supervisor=None, bug_reporting_guidelines=None,
+                            bug_reported_acknowledgement=None,
+                            bugfiling_duplicate_search=False):
+        """Make a new OCIRecipeTarget."""
+        if registrant is None:
+            registrant = self.makePerson()
+        if project is None and distribution is None:
+            project = self.makeProduct()
+        if ocirecipename is None:
+            ocirecipename = self.makeOCIRecipeName()
+        return getUtility(IOCIRecipeTargetSource).new(
+            registrant, project, distribution, ocirecipename, date_created,
+            description, bug_supervisor, bug_reporting_guidelines,
+            bug_reported_acknowledgement, bugfiling_duplicate_search)
+
 
 # Some factory methods return simple Python types. We don't add
 # security wrappers for them, as well as for objects created by