launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #28082
[Merge] ~cjwatson/launchpad:commercial-subscription-distribution into launchpad:master
Colin Watson has proposed merging ~cjwatson/launchpad:commercial-subscription-distribution into launchpad:master.
Commit message:
Add basic support for commercial subscriptions to distributions
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
For more details, see:
https://code.launchpad.net/~cjwatson/launchpad/+git/launchpad/+merge/415306
These are used to control the ability to use privacy features.
There isn't much in the way of tests here yet, because writing those needs privacy support in the `Distribution` model which is a rather more involved affair, but this gets some of the simple bits out of the way.
--
Your team Launchpad code reviewers is requested to review the proposed merge of ~cjwatson/launchpad:commercial-subscription-distribution into launchpad:master.
diff --git a/lib/lp/_schema_circular_imports.py b/lib/lp/_schema_circular_imports.py
index 7c99b77..9f981c0 100644
--- a/lib/lp/_schema_circular_imports.py
+++ b/lib/lp/_schema_circular_imports.py
@@ -429,6 +429,11 @@ patch_reference_property(IBuildFarmJob, 'buildqueue_record', IBuildQueue)
# IComment
patch_reference_property(IComment, 'comment_author', IPerson)
+# ICommercialSubscription
+patch_reference_property(ICommercialSubscription, 'product', IProduct)
+patch_reference_property(
+ ICommercialSubscription, 'distribution', IDistribution)
+
# IDistribution
patch_collection_property(IDistribution, 'series', IDistroSeries)
patch_collection_property(IDistribution, 'derivatives', IDistroSeries)
diff --git a/lib/lp/bugs/browser/tests/test_bugtarget_filebug.py b/lib/lp/bugs/browser/tests/test_bugtarget_filebug.py
index 3a693b3..3d4928f 100644
--- a/lib/lp/bugs/browser/tests/test_bugtarget_filebug.py
+++ b/lib/lp/bugs/browser/tests/test_bugtarget_filebug.py
@@ -385,7 +385,7 @@ class TestFileBugViewBase(FileBugViewMixin, TestCaseWithFactory):
if bug_sharing_policy:
if not IProduct.providedBy(target):
raise ValueError("Only Product supports this.")
- self.factory.makeCommercialSubscription(product=target)
+ self.factory.makeCommercialSubscription(pillar=target)
with person_logged_in(owner):
target.setBugSharingPolicy(bug_sharing_policy)
with person_logged_in(owner):
@@ -476,7 +476,7 @@ class TestFileBugViewBase(FileBugViewMixin, TestCaseWithFactory):
# The vocabulary for information_type when filing a bug is created
# correctly for a project with a proprietary sharing policy.
product = self.factory.makeProduct(official_malone=True)
- self.factory.makeCommercialSubscription(product=product)
+ self.factory.makeCommercialSubscription(pillar=product)
with person_logged_in(product.owner):
product.setBugSharingPolicy(BugSharingPolicy.PROPRIETARY)
view = create_initialized_view(
@@ -777,7 +777,7 @@ class TestFileBugForNonBugSupervisors(TestCaseWithFactory):
}
product = self.factory.makeProduct(official_malone=True)
if bug_sharing_policy:
- self.factory.makeCommercialSubscription(product=product)
+ self.factory.makeCommercialSubscription(pillar=product)
with person_logged_in(product.owner):
product.setBugSharingPolicy(bug_sharing_policy)
anyone = self.factory.makePerson()
diff --git a/lib/lp/bugs/mail/tests/test_handler.py b/lib/lp/bugs/mail/tests/test_handler.py
index 20dadf6..65033d2 100644
--- a/lib/lp/bugs/mail/tests/test_handler.py
+++ b/lib/lp/bugs/mail/tests/test_handler.py
@@ -249,7 +249,7 @@ class MaloneHandlerProcessTestCase(TestCaseWithFactory):
def test_new_bug_with_sharing_policy_proprietary(self):
project = self.factory.makeProduct(name='fnord')
- self.factory.makeCommercialSubscription(product=project)
+ self.factory.makeCommercialSubscription(pillar=project)
with person_logged_in(project.owner):
project.setBugSharingPolicy(BugSharingPolicy.PROPRIETARY)
transaction.commit()
diff --git a/lib/lp/code/browser/tests/test_branch.py b/lib/lp/code/browser/tests/test_branch.py
index ceaac7c..ac77d79 100644
--- a/lib/lp/code/browser/tests/test_branch.py
+++ b/lib/lp/code/browser/tests/test_branch.py
@@ -1225,7 +1225,7 @@ class TestBranchEditViewInformationTypes(TestCaseWithFactory):
# proprietary allow only embargoed and proprietary types.
owner = self.factory.makePerson()
product = self.factory.makeProduct(owner=owner)
- self.factory.makeCommercialSubscription(product=product)
+ self.factory.makeCommercialSubscription(pillar=product)
with person_logged_in(owner):
product.setBranchSharingPolicy(
BranchSharingPolicy.EMBARGOED_OR_PROPRIETARY)
@@ -1240,7 +1240,7 @@ class TestBranchEditViewInformationTypes(TestCaseWithFactory):
# allow only the proprietary type.
owner = self.factory.makePerson()
product = self.factory.makeProduct(owner=owner)
- self.factory.makeCommercialSubscription(product=product)
+ self.factory.makeCommercialSubscription(pillar=product)
with person_logged_in(owner):
product.setBranchSharingPolicy(BranchSharingPolicy.PROPRIETARY)
branch = self.factory.makeBranch(
diff --git a/lib/lp/code/browser/tests/test_gitrepository.py b/lib/lp/code/browser/tests/test_gitrepository.py
index 6b3e480..05c7043 100644
--- a/lib/lp/code/browser/tests/test_gitrepository.py
+++ b/lib/lp/code/browser/tests/test_gitrepository.py
@@ -1309,7 +1309,7 @@ class TestGitRepositoryEditViewInformationTypes(TestCaseWithFactory):
# types.
owner = self.factory.makePerson()
project = self.factory.makeProduct(owner=owner)
- self.factory.makeCommercialSubscription(product=project)
+ self.factory.makeCommercialSubscription(pillar=project)
with person_logged_in(owner):
project.setBranchSharingPolicy(
BranchSharingPolicy.EMBARGOED_OR_PROPRIETARY)
@@ -1325,7 +1325,7 @@ class TestGitRepositoryEditViewInformationTypes(TestCaseWithFactory):
# proprietary allow only the proprietary type.
owner = self.factory.makePerson()
product = self.factory.makeProduct(owner=owner)
- self.factory.makeCommercialSubscription(product=product)
+ self.factory.makeCommercialSubscription(pillar=product)
with person_logged_in(owner):
product.setBranchSharingPolicy(BranchSharingPolicy.PROPRIETARY)
repository = self.factory.makeGitRepository(
diff --git a/lib/lp/code/model/tests/test_branchnamespace.py b/lib/lp/code/model/tests/test_branchnamespace.py
index d0dad62..aff13b1 100644
--- a/lib/lp/code/model/tests/test_branchnamespace.py
+++ b/lib/lp/code/model/tests/test_branchnamespace.py
@@ -391,7 +391,7 @@ class TestProjectBranchNamespacePrivacyWithInformationType(
if person is None:
person = self.factory.makePerson()
product = self.factory.makeProduct()
- self.factory.makeCommercialSubscription(product=product)
+ self.factory.makeCommercialSubscription(pillar=product)
with person_logged_in(product.owner):
product.setBranchSharingPolicy(sharing_policy)
namespace = ProjectBranchNamespace(person, product)
diff --git a/lib/lp/code/model/tests/test_gitnamespace.py b/lib/lp/code/model/tests/test_gitnamespace.py
index eb11aa9..ac469e9 100644
--- a/lib/lp/code/model/tests/test_gitnamespace.py
+++ b/lib/lp/code/model/tests/test_gitnamespace.py
@@ -620,7 +620,7 @@ class TestProjectGitNamespacePrivacyWithInformationType(TestCaseWithFactory):
if person is None:
person = self.factory.makePerson()
project = self.factory.makeProduct()
- self.factory.makeCommercialSubscription(product=project)
+ self.factory.makeCommercialSubscription(pillar=project)
with person_logged_in(project.owner):
project.setBranchSharingPolicy(sharing_policy)
namespace = ProjectGitNamespace(person, project)
diff --git a/lib/lp/registry/browser/configure.zcml b/lib/lp/registry/browser/configure.zcml
index 63443a0..07fada1 100644
--- a/lib/lp/registry/browser/configure.zcml
+++ b/lib/lp/registry/browser/configure.zcml
@@ -654,7 +654,7 @@
<browser:url
for="lp.registry.interfaces.commercialsubscription.ICommercialSubscription"
path_expression="string:+commercialsubscription/${id}"
- attribute_to_parent="product"
+ attribute_to_parent="pillar"
/>
<browser:url
for="lp.registry.interfaces.jabber.IJabberID"
diff --git a/lib/lp/registry/browser/distribution.py b/lib/lp/registry/browser/distribution.py
index 4f11395..6ae28d7 100644
--- a/lib/lp/registry/browser/distribution.py
+++ b/lib/lp/registry/browser/distribution.py
@@ -196,6 +196,10 @@ class DistributionNavigation(
def traverse_archive(self, name):
return self.context.getArchive(name)
+ @stepthrough('+commercialsubscription')
+ def traverse_commercialsubscription(self, name):
+ return self.context.commercial_subscription
+
def _resolveSeries(self, name):
try:
return self.context[name], False
diff --git a/lib/lp/registry/interfaces/commercialsubscription.py b/lib/lp/registry/interfaces/commercialsubscription.py
index 81b064a..62c1ec1 100644
--- a/lib/lp/registry/interfaces/commercialsubscription.py
+++ b/lib/lp/registry/interfaces/commercialsubscription.py
@@ -12,7 +12,10 @@ from lazr.restful.declarations import (
exported_as_webservice_entry,
)
from lazr.restful.fields import ReferenceChoice
-from zope.interface import Interface
+from zope.interface import (
+ Attribute,
+ Interface,
+ )
from zope.schema import (
Bool,
Datetime,
@@ -38,15 +41,30 @@ class ICommercialSubscription(Interface):
product = exported(
ReferenceChoice(
title=_("Product which has commercial subscription"),
- required=True,
+ required=False,
readonly=True,
vocabulary='Product',
- # Really IProduct. See lp/registry/interfaces/product.py
+ # Really IProduct, patched in _schema_circular_imports.py.
schema=Interface,
description=_(
"Project for which this commercial subscription is "
"applied.")))
+ distribution = exported(
+ ReferenceChoice(
+ title=_("Distribution which has commercial subscription"),
+ required=False,
+ readonly=True,
+ vocabulary='Distribution',
+ # Really IDistribution, patched in _schema_circular_imports.py.
+ schema=Interface,
+ description=_(
+ "Distribution for which this commercial subscription is "
+ "applied.")))
+
+ pillar = Attribute(
+ "Pillar for which this commercial subscription is applied.")
+
date_created = exported(
Datetime(
title=_('Date Created'),
diff --git a/lib/lp/registry/interfaces/distribution.py b/lib/lp/registry/interfaces/distribution.py
index 69d9540..6c9b00d 100644
--- a/lib/lp/registry/interfaces/distribution.py
+++ b/lib/lp/registry/interfaces/distribution.py
@@ -82,6 +82,9 @@ from lp.registry.enums import (
VCSType,
)
from lp.registry.interfaces.announcement import IMakesAnnouncements
+from lp.registry.interfaces.commercialsubscription import (
+ ICommercialSubscription,
+ )
from lp.registry.interfaces.distributionmirror import IDistributionMirror
from lp.registry.interfaces.distroseries import DistroSeriesNameField
from lp.registry.interfaces.karma import IKarmaContext
@@ -449,6 +452,13 @@ class IDistributionPublic(
"to a different canonical URL."),
readonly=False, required=False))
+ commercial_subscription = exported(Reference(
+ ICommercialSubscription,
+ title=_("Commercial subscriptions"),
+ description=_(
+ "An object which contains the timeframe and the voucher code of a "
+ "subscription.")))
+
def getArchiveIDList(archive=None):
"""Return a list of archive IDs suitable for sqlvalues() or quote().
diff --git a/lib/lp/registry/interfaces/product.py b/lib/lp/registry/interfaces/product.py
index 120a9fe..2d0c179 100644
--- a/lib/lp/registry/interfaces/product.py
+++ b/lib/lp/registry/interfaces/product.py
@@ -1190,5 +1190,3 @@ from lp.registry.interfaces.distributionsourcepackage import ( # noqa: E402
patch_reference_property(
IDistributionSourcePackage, 'upstream_product', IProduct)
-
-patch_reference_property(ICommercialSubscription, 'product', IProduct)
diff --git a/lib/lp/registry/model/commercialsubscription.py b/lib/lp/registry/model/commercialsubscription.py
index 1620c27..fc467b9 100644
--- a/lib/lp/registry/model/commercialsubscription.py
+++ b/lib/lp/registry/model/commercialsubscription.py
@@ -21,7 +21,9 @@ from lp.registry.errors import CannotDeleteCommercialSubscription
from lp.registry.interfaces.commercialsubscription import (
ICommercialSubscription,
)
+from lp.registry.interfaces.distribution import IDistribution
from lp.registry.interfaces.person import validate_public_person
+from lp.registry.interfaces.product import IProduct
from lp.services.database.constants import UTC_NOW
from lp.services.database.stormbase import StormBase
@@ -33,9 +35,12 @@ class CommercialSubscription(StormBase):
id = Int(primary=True)
- product_id = Int(name='product', allow_none=False)
+ product_id = Int(name='product', allow_none=True)
product = Reference(product_id, 'Product.id')
+ distribution_id = Int(name='distribution', allow_none=True)
+ distribution = Reference(distribution_id, 'Distribution.id')
+
date_created = DateTime(tzinfo=pytz.UTC, allow_none=False, default=UTC_NOW)
date_last_modified = DateTime(
tzinfo=pytz.UTC, allow_none=False, default=UTC_NOW)
@@ -53,10 +58,17 @@ class CommercialSubscription(StormBase):
sales_system_id = Unicode(allow_none=False)
whiteboard = Unicode(default=None)
- def __init__(self, product, date_starts, date_expires, registrant,
+ def __init__(self, pillar, date_starts, date_expires, registrant,
purchaser, sales_system_id, whiteboard):
super().__init__()
- self.product = product
+ if IProduct.providedBy(pillar):
+ self.product = pillar
+ self.distribution = None
+ elif IDistribution.providedBy(pillar):
+ self.product = None
+ self.distribution = pillar
+ else:
+ raise AssertionError("Unknown pillar: %r" % pillar)
self.date_starts = date_starts
self.date_expires = date_expires
self.registrant = registrant
@@ -65,6 +77,11 @@ class CommercialSubscription(StormBase):
self.whiteboard = whiteboard
@property
+ def pillar(self):
+ return (
+ self.product if self.product_id is not None else self.distribution)
+
+ @property
def is_active(self):
"""See `ICommercialSubscription`"""
now = datetime.datetime.now(pytz.timezone('UTC'))
diff --git a/lib/lp/registry/model/distribution.py b/lib/lp/registry/model/distribution.py
index b993152..867c4df 100644
--- a/lib/lp/registry/model/distribution.py
+++ b/lib/lp/registry/model/distribution.py
@@ -120,6 +120,7 @@ from lp.registry.interfaces.role import IPersonRoles
from lp.registry.interfaces.series import SeriesStatus
from lp.registry.interfaces.sourcepackagename import ISourcePackageName
from lp.registry.model.announcement import MakesAnnouncements
+from lp.registry.model.commercialsubscription import CommercialSubscription
from lp.registry.model.distributionmirror import (
DistributionMirror,
MirrorCDImageDistroSeries,
@@ -343,6 +344,11 @@ class Distribution(SQLBase, BugTargetBase, MakesAnnouncements,
# Sharing policy for distributions is always PUBLIC.
return SpecificationSharingPolicy.PUBLIC
+ @cachedproperty
+ def commercial_subscription(self):
+ return IStore(CommercialSubscription).find(
+ CommercialSubscription, distribution=self).one()
+
@property
def uploaders(self):
"""See `IDistribution`."""
diff --git a/lib/lp/registry/model/product.py b/lib/lp/registry/model/product.py
index f213c1d..0d9235c 100644
--- a/lib/lp/registry/model/product.py
+++ b/lib/lp/registry/model/product.py
@@ -985,7 +985,7 @@ class Product(SQLBase, BugTargetBase, MakesAnnouncements,
"Complimentary 30 day subscription. -- Launchpad %s" %
now.date().isoformat())
subscription = CommercialSubscription(
- product=self, date_starts=now, date_expires=date_expires,
+ pillar=self, date_starts=now, date_expires=date_expires,
registrant=lp_janitor, purchaser=lp_janitor,
sales_system_id=sales_system_id, whiteboard=whiteboard)
get_property_cache(self).commercial_subscription = subscription
diff --git a/lib/lp/registry/stories/webservice/xx-distribution.txt b/lib/lp/registry/stories/webservice/xx-distribution.txt
index f0748c2..4f98323 100644
--- a/lib/lp/registry/stories/webservice/xx-distribution.txt
+++ b/lib/lp/registry/stories/webservice/xx-distribution.txt
@@ -28,6 +28,7 @@ And for every distribution we publish most of its attributes.
bug_reporting_guidelines: None
bug_supervisor_link: None
cdimage_mirrors_collection_link: 'http://.../ubuntu/cdimage_mirrors'
+ commercial_subscription_link: None
current_series_link: 'http://.../ubuntu/hoary'
date_created: '2006-10-16T18:31:43.415195+00:00'
default_traversal_policy: 'Series'
diff --git a/lib/lp/registry/tests/test_product.py b/lib/lp/registry/tests/test_product.py
index d0eb5a6..c037549 100644
--- a/lib/lp/registry/tests/test_product.py
+++ b/lib/lp/registry/tests/test_product.py
@@ -1237,7 +1237,7 @@ class TestProductBugInformationTypes(TestCaseWithFactory):
def makeProductWithPolicy(self, bug_sharing_policy):
product = self.factory.makeProduct()
- self.factory.makeCommercialSubscription(product=product)
+ self.factory.makeCommercialSubscription(pillar=product)
with person_logged_in(product.owner):
product.setBugSharingPolicy(bug_sharing_policy)
return product
@@ -1290,7 +1290,7 @@ class TestProductSpecificationPolicyAndInformationTypes(TestCaseWithFactory):
def makeProductWithPolicy(self, specification_sharing_policy):
product = self.factory.makeProduct()
- self.factory.makeCommercialSubscription(product=product)
+ self.factory.makeCommercialSubscription(pillar=product)
with person_logged_in(product.owner):
product.setSpecificationSharingPolicy(
specification_sharing_policy)
@@ -1658,7 +1658,7 @@ class BaseSharingPolicyTests:
def test_commercial_admin_can_set_policy(self):
# Commercial admins can set sharing policies for commercial projects.
- self.factory.makeCommercialSubscription(product=self.product)
+ self.factory.makeCommercialSubscription(pillar=self.product)
self.setSharingPolicy(self.public_policy, self.commercial_admin)
self.assertEqual(self.public_policy, self.getSharingPolicy())
@@ -1686,7 +1686,7 @@ class BaseSharingPolicyTests:
def test_proprietary_allowed_with_commercial_sub(self):
# All policies are valid when there's a current commercial
# subscription.
- self.factory.makeCommercialSubscription(product=self.product)
+ self.factory.makeCommercialSubscription(pillar=self.product)
for policy in self.enum.items:
self.setSharingPolicy(policy, self.commercial_admin)
self.assertEqual(policy, self.getSharingPolicy())
@@ -1695,7 +1695,7 @@ class BaseSharingPolicyTests:
# Setting a policy that allows Proprietary creates a
# corresponding access policy and shares it with the the
# maintainer.
- self.factory.makeCommercialSubscription(product=self.product)
+ self.factory.makeCommercialSubscription(pillar=self.product)
self.assertEqual(
[InformationType.PRIVATESECURITY, InformationType.USERDATA],
[policy.type for policy in
@@ -1730,7 +1730,7 @@ class BaseSharingPolicyTests:
for ap in ap_source.findByPillar([pillar])]
# Now change the sharing policies to PROPRIETARY
- self.factory.makeCommercialSubscription(product=product)
+ self.factory.makeCommercialSubscription(pillar=product)
with person_logged_in(product.owner):
product.setBugSharingPolicy(BugSharingPolicy.PROPRIETARY)
# Just bug sharing policy has been changed so all previous policy
@@ -1817,7 +1817,7 @@ class ProductBranchSharingPolicyTestCase(BaseSharingPolicyTests,
# Setting a policy that allows Embargoed creates a
# corresponding access policy and shares it with the the
# maintainer.
- self.factory.makeCommercialSubscription(product=self.product)
+ self.factory.makeCommercialSubscription(pillar=self.product)
self.assertEqual(
[InformationType.PRIVATESECURITY, InformationType.USERDATA],
[policy.type for policy in
diff --git a/lib/lp/registry/tests/test_product_webservice.py b/lib/lp/registry/tests/test_product_webservice.py
index 4f6e465..5808836 100644
--- a/lib/lp/registry/tests/test_product_webservice.py
+++ b/lib/lp/registry/tests/test_product_webservice.py
@@ -57,7 +57,7 @@ class TestProduct(TestCaseWithFactory):
# branch_sharing_policy can be set via the API.
product = self.factory.makeProduct()
owner = product.owner
- self.factory.makeCommercialSubscription(product=product)
+ self.factory.makeCommercialSubscription(pillar=product)
webservice = webservice_for_person(
owner, permission=OAuthPermission.WRITE_PRIVATE)
response = self.patch(
@@ -88,7 +88,7 @@ class TestProduct(TestCaseWithFactory):
# bug_sharing_policy can be set via the API.
product = self.factory.makeProduct()
owner = product.owner
- self.factory.makeCommercialSubscription(product=product)
+ self.factory.makeCommercialSubscription(pillar=product)
webservice = webservice_for_person(
product.owner, permission=OAuthPermission.WRITE_PRIVATE)
response = self.patch(
diff --git a/lib/lp/scripts/tests/test_garbo.py b/lib/lp/scripts/tests/test_garbo.py
index 99f36cd..70384af 100644
--- a/lib/lp/scripts/tests/test_garbo.py
+++ b/lib/lp/scripts/tests/test_garbo.py
@@ -1361,7 +1361,7 @@ class TestGarbo(FakeAdapterMixin, TestCaseWithFactory):
# in use by artifacts or allowed by the project sharing policy.
switch_dbuser('testadmin')
product = self.factory.makeProduct()
- self.factory.makeCommercialSubscription(product=product)
+ self.factory.makeCommercialSubscription(pillar=product)
self.factory.makeAccessPolicy(product, InformationType.PROPRIETARY)
naked_product = removeSecurityProxy(product)
naked_product.bug_sharing_policy = BugSharingPolicy.PROPRIETARY
diff --git a/lib/lp/testing/factory.py b/lib/lp/testing/factory.py
index 0ef41bb..b098cba 100644
--- a/lib/lp/testing/factory.py
+++ b/lib/lp/testing/factory.py
@@ -4691,26 +4691,32 @@ class BareLaunchpadObjectFactory(ObjectFactory):
}
return fileupload
- def makeCommercialSubscription(self, product, expired=False,
+ def makeCommercialSubscription(self, pillar, expired=False,
voucher_id='new'):
- """Create a commercial subscription for the given product."""
+ """Create a commercial subscription for the given pillar."""
+ if IProduct.providedBy(pillar):
+ find_kwargs = {"product": pillar}
+ elif IDistribution.providedBy(pillar):
+ find_kwargs = {"distribution": pillar}
+ else:
+ raise AssertionError("Unknown pillar: %r" % pillar)
if IStore(CommercialSubscription).find(
- CommercialSubscription, product=product).one() is not None:
+ CommercialSubscription, **find_kwargs).one() is not None:
raise AssertionError(
- "The product under test already has a CommercialSubscription.")
+ "The pillar under test already has a CommercialSubscription.")
if expired:
expiry = datetime.now(pytz.UTC) - timedelta(days=1)
else:
expiry = datetime.now(pytz.UTC) + timedelta(days=30)
commercial_subscription = CommercialSubscription(
- product=product,
+ pillar=pillar,
date_starts=datetime.now(pytz.UTC) - timedelta(days=90),
date_expires=expiry,
- registrant=product.owner,
- purchaser=product.owner,
+ registrant=pillar.owner,
+ purchaser=pillar.owner,
sales_system_id=voucher_id,
whiteboard='')
- del get_property_cache(product).commercial_subscription
+ del get_property_cache(pillar).commercial_subscription
return commercial_subscription
def grantCommercialSubscription(self, person):