launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #06357
[Merge] lp:~stevenk/launchpad/kill-entitlements into lp:launchpad
Steve Kowalik has proposed merging lp:~stevenk/launchpad/kill-entitlements into lp:launchpad.
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
For more details, see:
https://code.launchpad.net/~stevenk/launchpad/kill-entitlements/+merge/92888
Kill the never used entitlements interface/model and supporting scripts.
The database table will be dropped in a separate branch.
--
https://code.launchpad.net/~stevenk/launchpad/kill-entitlements/+merge/92888
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~stevenk/launchpad/kill-entitlements into lp:launchpad.
=== modified file 'database/sampledata/current-dev.sql'
--- database/sampledata/current-dev.sql 2012-01-27 09:29:19 +0000
+++ database/sampledata/current-dev.sql 2012-02-14 00:24:21 +0000
@@ -4032,17 +4032,6 @@
ALTER TABLE emailaddress ENABLE TRIGGER ALL;
-ALTER TABLE entitlement DISABLE TRIGGER ALL;
-
-INSERT INTO entitlement (id, person, entitlement_type, quota, amount_used, date_starts, date_expires, registrant, date_created, approved_by, date_approved, state, whiteboard, is_dirty, distribution, product, project) VALUES (1, 17, 10, 100, 0, '2007-06-11 12:00:00', '2008-06-11 12:00:00', NULL, '2007-06-10 12:00:00', NULL, NULL, 30, NULL, true, NULL, NULL, NULL);
-INSERT INTO entitlement (id, person, entitlement_type, quota, amount_used, date_starts, date_expires, registrant, date_created, approved_by, date_approved, state, whiteboard, is_dirty, distribution, product, project) VALUES (2, 17, 20, 200, 0, '2007-06-11 12:00:00', '2008-06-11 12:00:00', NULL, '2007-06-10 12:00:00', NULL, NULL, 30, NULL, true, NULL, NULL, NULL);
-INSERT INTO entitlement (id, person, entitlement_type, quota, amount_used, date_starts, date_expires, registrant, date_created, approved_by, date_approved, state, whiteboard, is_dirty, distribution, product, project) VALUES (4, 18, 10, 5, 0, '2007-06-11 12:00:00', '2007-06-11 00:00:00', NULL, '2007-06-11 00:44:19.267601', NULL, NULL, 30, NULL, true, NULL, NULL, NULL);
-INSERT INTO entitlement (id, person, entitlement_type, quota, amount_used, date_starts, date_expires, registrant, date_created, approved_by, date_approved, state, whiteboard, is_dirty, distribution, product, project) VALUES (5, 18, 10, 3, 0, '2007-06-11 12:00:00', '2007-06-11 00:00:00', NULL, '2007-06-11 01:02:48.538842', NULL, NULL, 30, NULL, true, NULL, NULL, NULL);
-
-
-ALTER TABLE entitlement ENABLE TRIGGER ALL;
-
-
ALTER TABLE faq DISABLE TRIGGER ALL;
INSERT INTO faq (id, title, tags, content, product, distribution, owner, date_created, last_updated_by, date_last_updated, fti) VALUES (1, 'Wireless Networking Documentation', 'wifi', 'Installation instructions for many wireless cards can be found at:
=== modified file 'database/sampledata/current.sql'
--- database/sampledata/current.sql 2012-01-27 09:29:19 +0000
+++ database/sampledata/current.sql 2012-02-14 00:24:21 +0000
@@ -3965,17 +3965,6 @@
ALTER TABLE emailaddress ENABLE TRIGGER ALL;
-ALTER TABLE entitlement DISABLE TRIGGER ALL;
-
-INSERT INTO entitlement (id, person, entitlement_type, quota, amount_used, date_starts, date_expires, registrant, date_created, approved_by, date_approved, state, whiteboard, is_dirty, distribution, product, project) VALUES (1, 17, 10, 100, 0, '2007-06-11 12:00:00', '2008-06-11 12:00:00', NULL, '2007-06-10 12:00:00', NULL, NULL, 30, NULL, true, NULL, NULL, NULL);
-INSERT INTO entitlement (id, person, entitlement_type, quota, amount_used, date_starts, date_expires, registrant, date_created, approved_by, date_approved, state, whiteboard, is_dirty, distribution, product, project) VALUES (2, 17, 20, 200, 0, '2007-06-11 12:00:00', '2008-06-11 12:00:00', NULL, '2007-06-10 12:00:00', NULL, NULL, 30, NULL, true, NULL, NULL, NULL);
-INSERT INTO entitlement (id, person, entitlement_type, quota, amount_used, date_starts, date_expires, registrant, date_created, approved_by, date_approved, state, whiteboard, is_dirty, distribution, product, project) VALUES (4, 18, 10, 5, 0, '2007-06-11 12:00:00', '2007-06-11 00:00:00', NULL, '2007-06-11 00:44:19.267601', NULL, NULL, 30, NULL, true, NULL, NULL, NULL);
-INSERT INTO entitlement (id, person, entitlement_type, quota, amount_used, date_starts, date_expires, registrant, date_created, approved_by, date_approved, state, whiteboard, is_dirty, distribution, product, project) VALUES (5, 18, 10, 3, 0, '2007-06-11 12:00:00', '2007-06-11 00:00:00', NULL, '2007-06-11 01:02:48.538842', NULL, NULL, 30, NULL, true, NULL, NULL, NULL);
-
-
-ALTER TABLE entitlement ENABLE TRIGGER ALL;
-
-
ALTER TABLE faq DISABLE TRIGGER ALL;
INSERT INTO faq (id, title, tags, content, product, distribution, owner, date_created, last_updated_by, date_last_updated, fti) VALUES (1, 'Wireless Networking Documentation', 'wifi', 'Installation instructions for many wireless cards can be found at:
=== modified file 'lib/lp/registry/configure.zcml'
--- lib/lp/registry/configure.zcml 2012-02-13 05:50:16 +0000
+++ lib/lp/registry/configure.zcml 2012-02-14 00:24:21 +0000
@@ -1710,29 +1710,6 @@
permission="launchpad.Edit"
interface="lp.registry.interfaces.productrelease.IProductReleaseFileEditRestricted"/>
</class>
- <class
- class="lp.registry.model.entitlement.Entitlement">
- <require
- permission="launchpad.View"
- interface="lp.registry.interfaces.entitlement.IEntitlement"/>
- <require
- permission="launchpad.Admin"
- set_schema="lp.registry.interfaces.entitlement.IEntitlement"/>
- </class>
-
- <!-- EntitlementSet -->
-
- <class
- class="lp.registry.model.entitlement.EntitlementSet">
- <allow
- interface="lp.registry.interfaces.entitlement.IEntitlementSet"/>
- </class>
- <securedutility
- class="lp.registry.model.entitlement.EntitlementSet"
- provides="lp.registry.interfaces.entitlement.IEntitlementSet">
- <allow
- interface="lp.registry.interfaces.entitlement.IEntitlementSet"/>
- </securedutility>
<!-- SuiteSourcePackage -->
<class
=== removed file 'lib/lp/registry/doc/entitlement.txt'
--- lib/lp/registry/doc/entitlement.txt 2011-12-30 06:14:56 +0000
+++ lib/lp/registry/doc/entitlement.txt 1970-01-01 00:00:00 +0000
@@ -1,333 +0,0 @@
-= Entitlements =
-
-Entitlements are a means of recording features and privileges
-Launchpad users have been assigned. The business model for these
-assignments is not important, but it could be through a commercial
-arrangement or through a grant that applies to everyone.
-
- >>> from datetime import datetime
- >>> import pytz
- >>> from lp.services.database.sqlbase import flush_database_updates
- >>> from lp.testing import login
- >>> from lp.services.webapp.testing import verifyObject
- >>> from lp.registry.interfaces.entitlement import (
- ... EntitlementQuota,
- ... EntitlementState,
- ... EntitlementType,
- ... IEntitlement,
- ... IEntitlementSet,
- ... )
- >>> from lp.registry.interfaces.person import IPersonSet
-
-The logged in user must be an admin in order to change the quota.
-
- >>> from lp.app.interfaces.launchpad import ILaunchpadCelebrities
- >>> login("foo.bar@xxxxxxxxxxxxx")
- >>> foobar = getUtility(ILaunchBag).user
- >>> lp_admins = getUtility(ILaunchpadCelebrities).admin
- >>> foobar.inTeam(lp_admins)
- True
- >>> entitlements = getUtility(IEntitlementSet)
- >>> entitlements_in_sample_data = entitlements.count()
-
-Find a team with an entitlement.
-
- >>> personset = getUtility(IPersonSet)
- >>> ubuntu_team = personset.getByName('ubuntu-team')
-
-An entitlement grants privilege to use a restricted feature. The
-'quota' is the number of instances being granted and the
-entitlement_type is the feature being enabled. The 'person' is the
-person or team being granted the right. The state for a granted
-entitlement is ACTIVE and the expiration and start dates can be specified.
-
- >>> UTC = pytz.timezone('UTC')
- >>> entitlement = getUtility(IEntitlementSet).new(
- ... quota=5,
- ... entitlement_type=EntitlementType.PRIVATE_BUGS,
- ... person=ubuntu_team,
- ... state=EntitlementState.ACTIVE,
- ... date_expires=datetime(2038, 6, 11, tzinfo=UTC),
- ... amount_used=0)
- >>> verifyObject(IEntitlement, entitlement)
- True
-
-The person can be accessed and shown to be correct.
-
- >>> print entitlement.person.name
- ubuntu-team
-
-If the current date is after the start date (if not None) or before
-the expiration date (if not None) then the in_date_range test will
-pass.
-
- >>> entitlement.in_date_range
- True
-
-== Quota checking ==
-
-If the amount used is less than the quota value the exceeded_quota
-test will be false.
-
- >>> entitlement.quota = 100
- >>> entitlement.amount_used = 0
- >>> entitlement.exceeded_quota
- False
-
-The quota is not exceeded, the date is in range, and the state is
-ACTIVE, so the entitlement is valid.
-
- >>> entitlement.is_valid
- True
-
-If the amount used is equal to the quota 'exceeded_quota' should still
-be false and 'is_valid' is still true.
-
- >>> entitlement.quota = 100
- >>> entitlement.amount_used = 100
- >>> entitlement.exceeded_quota
- False
- >>> entitlement.is_valid
- True
-
-However if the amount_used to exceeds the quota, the exceeded quota is
-true and the entitlement is no longer valid.
-
- >>> entitlement.quota = 100
- >>> entitlement.amount_used = 101
- >>> entitlement.exceeded_quota
- True
- >>> entitlement.is_valid
- False
-
-If the quota is UNLIMITED the exceeded quota test is false even when
-using a really large value for amount used. The entitlement remains
-valid.
-
-We use math.pow here, since __builtin__.pow is overridden by twisted.conch.
-
- >>> import math
- >>> entitlement.quota = EntitlementQuota.UNLIMITED
- >>> entitlement.amount_used = math.pow(10,9)
- >>> entitlement.exceeded_quota
- False
- >>> entitlement.is_valid
- True
-
-Calling incrementAmountUsed increases the value by one.
-
- >>> entitlement.quota = 10
- >>> entitlement.amount_used = 9
- >>> entitlement.incrementAmountUsed()
- >>> entitlement.amount_used
- 10
-
-Attempting to increment past the quota will cause an error.
-
- >>> entitlement.incrementAmountUsed()
- Traceback (most recent call last):
- ...
- EntitlementQuotaExceededError: ...
-
-If the entitlement is invalid for any reason, attempting to increment
-the amount used will cause an error.
-
- >>> entitlement.state = EntitlementState.INACTIVE
- >>> entitlement.quota = 50
- >>> entitlement.incrementAmountUsed()
- Traceback (most recent call last):
- ...
- EntitlementInvalidError: ...
-
-
-== Date range checking ==
-
-The 'in_date_range' attribute can be used to tell whether the
-entitlement is valid with respect to the start date and expires date.
-When the current date is out of range the entitlement is considered
-invalid.
-
-When the entitlement does not have a start date or an expiration date
-then those values are not checked. If no start date is given the
-expiration date is still used, and vice versa. If both start date and
-expiration date are None then no date range checking is performed and
-the entitlement is valid with respect to dates.
-
-Remove the start and expiration dates and the date range will be
-valid.
-
- >>> entitlement.state = EntitlementState.ACTIVE
- >>> entitlement.date_starts = None
- >>> entitlement.date_expires = None
- >>> entitlement.in_date_range
- True
- >>> entitlement.is_valid
- True
-
- >>> from datetime import datetime, timedelta
- >>> from pytz import UTC
- >>> now = datetime.now(UTC)
- >>> yesterday = now - timedelta(days = 1)
- >>> tomorrow = now + timedelta(days = 1)
-
-If the start date is in the past and the expiration date is not set
-this condition is considered an open-ended entitlement and we are
-still in its range.
-
- >>> entitlement.date_starts = yesterday
- >>> entitlement.in_date_range
- True
- >>> entitlement.is_valid
- True
-
-If the start date is in the future the date is not in range and the
-entitlement is invalid.
-
- >>> entitlement.date_starts = tomorrow
- >>> entitlement.in_date_range
- False
- >>> entitlement.is_valid
- False
-
-If the expires date is in the past, we are not in its date range and
-the entitlement is not valid.
-
- >>> entitlement.date_starts = None
- >>> entitlement.date_expires = yesterday
- >>> entitlement.in_date_range
- False
- >>> entitlement.is_valid
- False
-
-If the expiration date is in the future the date range is satisfied
-and the entitlement is valid.
-
- >>> entitlement.date_expires = tomorrow
- >>> entitlement.in_date_range
- True
- >>> entitlement.is_valid
- True
-
-If the start date is in the past and the expires date is in the future
-the date range is again satisfied and the entitlement is valid.
-
- >>> entitlement.date_starts = yesterday
- >>> entitlement.date_expires = tomorrow
- >>> entitlement.in_date_range
- True
- >>> entitlement.is_valid
- True
-
-
-== Security ==
-
-Viewing the entitlement's attributes is restricted to the
-entitlement's owner, the entitlement's registrant (or to a member of
-these teams), and to Launchpad administrators.
-
-If logged in as an anonymous user the entitlement values cannot be
-viewed. A security-wrapped entitlement must be used to exercise the
-security adapters.
-
- >>> entitlement = ubuntu_team.entitlements[0]
- >>> entitlement.quota = 50
- >>> login(ANONYMOUS)
- >>> entitlement.quota
- Traceback (most recent call last):
- ...
- Unauthorized: (<Entitlement..., 'quota', 'launchpad.View')
-
-
- >>> entitlement.quota=10
- Traceback (most recent call last):
- ...
- Unauthorized: (<Entitlement..., 'quota', 'launchpad.Admin')
-
-Authenticated Launchpad users who are not the owner or team member are
-similarly restricted.
-
- >>> login('no-priv@xxxxxxxxxxxxx')
- >>> entitlement.quota
- Traceback (most recent call last):
- ...
- Unauthorized: (<Entitlement..., 'quota', 'launchpad.View')
-
-
- >>> entitlement.quota=10
- Traceback (most recent call last):
- ...
- Unauthorized: (<Entitlement..., 'quota', 'launchpad.Admin')
-
-Add the current user to the team and the user can now access
-attributes. Since ubuntu-team is restricted, an administrator must be
-listed as a reviewer for the membership to go through.
-
- >>> from lp.registry.interfaces.teammembership import TeamMembershipStatus
- >>> nopriv = getUtility(ILaunchBag).user
- >>> mark = personset.getByName('mark')
- >>> nopriv.join(ubuntu_team)
-
- # Login as the team's owner in order to be able to change its memberships.
- >>> login(ubuntu_team.teamowner.preferredemail.email)
- >>> ubuntu_team.setMembershipData(nopriv, TeamMembershipStatus.APPROVED, mark)
- >>> login('no-priv@xxxxxxxxxxxxx')
-
- >>> flush_database_updates()
- >>> nopriv in ubuntu_team.activemembers
- True
- >>> nopriv.inTeam(ubuntu_team)
- True
- >>> entitlement.quota
- 50
-
- >>> entitlement.quota=10
- Traceback (most recent call last):
- ...
- Unauthorized: (<Entitlement..., 'quota', 'launchpad.Admin')
-
-
-= EntitlementSet =
-
-All of the entitlements can be obtained using IEntitlementSet.
-
- >>> login("foo.bar@xxxxxxxxxxxxx")
- >>> entitlements = getUtility(IEntitlementSet)
-
-One entitlement was created in the previous examples.
-
- >>> entitlements.count() - entitlements_in_sample_data
- 1
-
-To look up an entitlement from the set, simply use the 'get' with the id.
-
- >>> entitlement2 = entitlements.get(entitlement.id)
- >>> entitlement2.id == entitlement.id
- True
-
-Get all of the valid entitlements for ubuntu_team.
-
- >>> valid_list = getUtility(IEntitlementSet).getValidForPerson(ubuntu_team)
- >>> len(valid_list)
- 1
-
-A new entitlement for the ubuntu_team can be created, increasing the
-number of valid entitlements.
-
- >>> entitlement = getUtility(IEntitlementSet).new(
- ... quota=50,
- ... entitlement_type=EntitlementType.PRIVATE_BRANCHES,
- ... person=ubuntu_team,
- ... state=EntitlementState.ACTIVE,
- ... date_expires=datetime(2038, 6, 11, tzinfo=UTC),
- ... amount_used=0)
- >>> valid_list = getUtility(IEntitlementSet).getValidForPerson(ubuntu_team)
- >>> len(valid_list)
- 2
-
-Setting the original entitlement to INACTIVE will now reduce the
-number of valid entitlements.
-
- >>> entitlement.state = EntitlementState.INACTIVE
- >>> valid_list = getUtility(IEntitlementSet).getValidForPerson(ubuntu_team)
- >>> len(valid_list)
- 1
=== removed file 'lib/lp/registry/interfaces/entitlement.py'
--- lib/lp/registry/interfaces/entitlement.py 2011-12-24 16:54:44 +0000
+++ lib/lp/registry/interfaces/entitlement.py 1970-01-01 00:00:00 +0000
@@ -1,242 +0,0 @@
-# Copyright 2009 Canonical Ltd. This software is licensed under the
-# GNU Affero General Public License version 3 (see the file LICENSE).
-
-# pylint: disable-msg=E0211,E0213
-
-"""Entitlement interfaces."""
-
-__metaclass__ = type
-
-__all__ = [
- 'EntitlementInvalidError',
- 'EntitlementQuota',
- 'EntitlementQuotaExceededError',
- 'EntitlementState',
- 'EntitlementType',
- 'IEntitlement',
- 'IEntitlementSet',
- ]
-
-from lazr.enum import (
- DBEnumeratedType,
- DBItem,
- )
-from zope.interface import (
- Attribute,
- Interface,
- )
-from zope.schema import (
- Bool,
- Choice,
- Datetime,
- Int,
- )
-
-from lp import _
-from lp.services.fields import Whiteboard
-
-
-class EntitlementQuotaExceededError(Exception):
- """The quota has been exceeded for the entitlement."""
-
-
-class EntitlementInvalidError(Exception):
- """The entitlement is not valid."""
-
-
-class EntitlementType(DBEnumeratedType):
- """The set of features supported via entitlements.
-
- The listed features may be enabled by the granting of an entitlement.
- """
-
- PRIVATE_BRANCHES = DBItem(10, """
- Private Branches
-
- The ability to create branches which are only visible to the team.
- """)
-
- PRIVATE_BUGS = DBItem(20, """
- Private Bugs
-
- The ability to create private bugs which are only visible to the team.
- """)
-
- PRIVATE_TEAMS = DBItem(30, """
- Private Teams
-
- The ability to create private teams which are only visible to parent
- teams.
- """)
-
-
-class EntitlementState(DBEnumeratedType):
- """States for an entitlement.
-
- The entitlement may start life as a REQUEST that is then granted and
- made ACTIVE. At some point the entitlement may be revoked by marking
- as INACTIVE.
- """
-
- REQUESTED = DBItem(10, """
- Entitlement has been requested.
-
- The entitlement is inactive in this state.
- """)
-
- ACTIVE = DBItem(20, """
- The entitlement is active.
-
- The entitlement is approved in Launchpad or was imported in the
- active state.
- """)
-
- INACTIVE = DBItem(30, """
- The entitlement is inactive.
-
- The entitlement has be deactivated.
- """)
-
-
-class IEntitlement(Interface):
- """An entitlement the right to use a specific feature in Launchpad.
-
- Entitlements can be granted in an unlimited quantity or with a given
- quota. They have a start date and optionally an expiration date. An
- entitlement is invalid if it is not active, the quota is exceeded, or if
- it is expired.
- """
-
- id = Int(
- title=_("Entitlement id"),
- required=True,
- readonly=True)
- person = Choice(
- title=_('Person'),
- required=True,
- readonly=True,
- vocabulary='ValidPersonOrTeam',
- description=_("Person or team to whom the entitlements is assigned."))
- date_created = Datetime(
- title=_("Date Created"),
- description=_("The date on which this entitlement was created."),
- required=True,
- readonly=True)
- date_starts = Datetime(
- title=_("Date Starts"),
- description=_("The date on which this entitlement starts."),
- readonly=False)
- date_expires = Datetime(
- title=_("Date Expires"),
- description=_("The date on which this entitlement expires."),
- readonly=False)
- entitlement_type = Choice(
- title=_("Type of entitlement."),
- required=True,
- vocabulary='EntitlementType',
- description=_("Type of feature for this entitlement."),
- readonly=True)
- quota = Int(
- title=_("Allocated quota."),
- required=True,
- description=_(
- "A quota is the number of a feature allowed by this entitlement, "
- "for instance 50 private bugs."))
- amount_used = Int(
- title=_("Amount used."),
- description=_(
- "The amount used is the number of instances of a feature "
- "the person has used so far."))
- registrant = Choice(
- title=_('Registrant'),
- vocabulary='ValidPersonOrTeam',
- description=_(
- "Person who registered the entitlement. "
- "May be None if created automatically."),
- readonly=True)
- approved_by = Choice(
- title=_('Approved By'),
- vocabulary='ValidPersonOrTeam',
- description=_(
- "Person who approved the entitlement. "
- "May be None if created automatically."),
- readonly=True)
- state = Choice(
- title=_("State"),
- required=True,
- vocabulary='EntitlementState',
- description = _("Current state of the entitlement."))
-
- whiteboard = Whiteboard(title=_('Whiteboard'), required=False,
- description=_('Notes on the current status of the entitlement.'))
-
- is_dirty = Bool(
- title=_("Dirty?"),
- description=_(
- "Is the entitlement 'dirty', i.e. has been written since the "
- "most recent update to an external system?"))
-
- is_valid = Attribute(
- "Is this entitlement valid?")
-
- exceeded_quota = Attribute(
- "If the quota is not unlimited, is it exceeded?")
-
- in_date_range = Attribute(
- "Has the start date passed but not the expiration date?")
-
- def incrementAmountUsed():
- """Add one to the amount used."""
-
-
-class IEntitlementSet(Interface):
- """Interface representing a set of Entitlements."""
-
- def __getitem__(entitlement_id):
- """Return the entitlement with the given id.
-
- Raise NotFoundError if there is no such entitlement.
- """
-
- def __iter__():
- """Return an iterator that will go through all entitlements."""
-
- def count():
- """Return the number of entitlements in the database."""
-
- def get(entitlement_id, default=None):
- """Return the entitlement with the given id.
-
- Return the default value if there is no such entitlement.
- """
-
- def getForPerson(person):
- """Return the entitlements for the person or team.
-
- Get all entitlements for a person.
- """
-
- def getValidForPerson(person):
- """Return a list of valid entitlements for the person or team.
-
- Get all valid entitlements for a person. None is returned if no valid
- entitlements are found.
- """
-
- def getDirty():
- """Return the entitlements that have the dirty bit set.
-
- Get all entitlements that are marked as dirty.
- """
-
- def new(person, quota, entitlement_type, state,
- is_dirty=True, date_created=None, date_expires=None,
- date_starts=None, amount_used=None, registrant=None,
- approved_by=None):
- """Create a new entitlement."""
-
-
-class EntitlementQuota:
- """This class stores constants for entitlements quotas."""
-
- UNLIMITED = 0
=== modified file 'lib/lp/registry/interfaces/person.py'
--- lib/lp/registry/interfaces/person.py 2012-02-13 23:02:42 +0000
+++ lib/lp/registry/interfaces/person.py 2012-02-14 00:24:21 +0000
@@ -1022,8 +1022,6 @@
# Really IArchive, see archive.py
value_type=Reference(schema=Interface)))
- entitlements = Attribute("List of Entitlements for this person or team.")
-
structural_subscriptions = Attribute(
"The structural subscriptions for this person.")
=== removed file 'lib/lp/registry/model/entitlement.py'
--- lib/lp/registry/model/entitlement.py 2011-12-30 06:14:56 +0000
+++ lib/lp/registry/model/entitlement.py 1970-01-01 00:00:00 +0000
@@ -1,189 +0,0 @@
-# Copyright 2009 Canonical Ltd. This software is licensed under the
-# GNU Affero General Public License version 3 (see the file LICENSE).
-
-# pylint: disable-msg=E0611,W0212
-
-__metaclass__ = type
-__all__ = ['Entitlement', 'EntitlementSet']
-
-from datetime import datetime
-
-import pytz
-from sqlobject import (
- BoolCol,
- ForeignKey,
- IntCol,
- SQLObjectNotFound,
- StringCol,
- )
-from zope.interface import implements
-
-from lp.app.errors import NotFoundError
-from lp.registry.interfaces.entitlement import (
- EntitlementInvalidError,
- EntitlementQuota,
- EntitlementQuotaExceededError,
- EntitlementState,
- EntitlementType,
- IEntitlement,
- IEntitlementSet,
- )
-from lp.services.database.constants import DEFAULT
-from lp.services.database.datetimecol import UtcDateTimeCol
-from lp.services.database.enumcol import EnumCol
-from lp.services.database.sqlbase import SQLBase
-
-
-class Entitlement(SQLBase):
- """A table recording the entitlements for a person or team."""
-
- implements(IEntitlement)
- _table = 'Entitlement'
- _defaultOrder = ['person', '-date_expires']
-
- person = ForeignKey(
- dbName='person', foreignKey='Person',
- default=None, notNull=True)
- date_created = UtcDateTimeCol(notNull=True, default=DEFAULT)
- date_starts = UtcDateTimeCol(notNull=False, default=None)
- date_expires = UtcDateTimeCol(notNull=False, default=None)
-
- entitlement_type = EnumCol(
- dbName='entitlement_type',
- notNull=True,
- enum=EntitlementType,
- default=EntitlementType.PRIVATE_BUGS)
- quota = IntCol(notNull=True)
- amount_used = IntCol(notNull=True, default=0)
- registrant = ForeignKey(
- dbName='registrant', foreignKey='Person',
- default=None, notNull=False)
- approved_by = ForeignKey(
- dbName='approved_by', foreignKey='Person',
- default=None, notNull=False)
- state = EnumCol(
- dbName='state',
- notNull=True,
- enum=EntitlementState,
- default=EntitlementState.INACTIVE)
- whiteboard = StringCol(notNull=False, default=None)
- is_dirty = BoolCol(dbName="is_dirty", notNull=True, default=True)
-
- @property
- def exceeded_quota(self):
- """See IEntitlement."""
- if self.quota == EntitlementQuota.UNLIMITED:
- return False
- else:
- return self.amount_used > self.quota
-
- def _isExpired(self, now=None):
- if now is None:
- now = datetime.now(pytz.timezone('UTC'))
- if self.date_expires is None:
- return False
- else:
- return now > self.date_expires
-
- def _hasNotYetStarted(self, now=None):
- if now is None:
- now = datetime.now(pytz.timezone('UTC'))
- if self.date_starts is None:
- return False
- else:
- return now < self.date_starts
-
- @property
- def in_date_range(self):
- """See IEntitlement."""
- now = datetime.now(pytz.timezone('UTC'))
- too_late = self._isExpired(now)
- too_early = self._hasNotYetStarted(now)
- just_right = not (too_late or too_early)
- return just_right
-
- @property
- def is_valid(self):
- """See IEntitlement."""
- if self.state != EntitlementState.ACTIVE:
- return False
- else:
- return self.in_date_range and not self.exceeded_quota
-
- def incrementAmountUsed(self):
- """See IEntitlement."""
- if not self.is_valid:
- raise EntitlementInvalidError(
- "This entitlement is invalid and cannot be used.")
-
- self.amount_used += 1
-
- if self.exceeded_quota:
- self.amount_used -= 1
- raise EntitlementQuotaExceededError(
- "The quota for this entitlement has been exceeded.")
-
-
-class EntitlementSet:
- """The set of all entitlements."""
-
- implements(IEntitlementSet)
-
- def __getitem__(self, entitlement_id):
- """See `IEntitlementSet`."""
- entitlement = self.get(entitlement_id)
- if entitlement is None:
- raise NotFoundError(entitlement_id)
- return entitlement
-
- def __iter__(self):
- """See `IEntitlementSet`."""
- return iter(Entitlement.select())
-
- def count(self):
- """See `IEntitlementSet`."""
- return Entitlement.select().count()
-
- def get(self, entitlement_id, default=None):
- """See `IEntitlementSet`."""
- try:
- return Entitlement.get(entitlement_id)
- except SQLObjectNotFound:
- return default
-
- def getForPerson(self, person):
- """See `IEntitlementSet`."""
- return Entitlement.selectBy(person=person)
-
- def getValidForPerson(self, person):
- """See `IEntitlementSet`."""
- entitlements = self.getForPerson(person)
- return [entitlement for entitlement in entitlements
- if entitlement.is_valid]
-
- def getDirty(self):
- """See `IEntitlementSet`."""
- return Entitlement.selectBy(is_dirty=True)
-
- def new(self, person, quota, entitlement_type,
- state, is_dirty=True, date_created=None, date_starts=None,
- date_expires=None, amount_used=0, registrant=None,
- approved_by=None, whiteboard=None):
- """See `IEntitlementSet`."""
-
- if date_created is None:
- date_created = datetime.now(pytz.timezone('UTC'))
-
- return Entitlement(
- person=person,
- quota=quota,
- entitlement_type=entitlement_type,
- state=state,
- is_dirty=is_dirty,
- date_created=date_created,
- date_starts=date_starts,
- date_expires=date_expires,
- amount_used=amount_used,
- registrant=registrant,
- approved_by=approved_by,
- whiteboard=whiteboard)
=== modified file 'lib/lp/registry/model/person.py'
--- lib/lp/registry/model/person.py 2012-02-13 23:02:42 +0000
+++ lib/lp/registry/model/person.py 2012-02-14 00:24:21 +0000
@@ -595,7 +595,6 @@
_ircnicknames = SQLMultipleJoin('IrcID', joinColumn='person')
jabberids = SQLMultipleJoin('JabberID', joinColumn='person')
- entitlements = SQLMultipleJoin('Entitlement', joinColumn='person')
visibility = EnumCol(
enum=PersonVisibility,
default=PersonVisibility.PUBLIC,
=== removed file 'lib/lp/registry/scripts/entitlement.py'
--- lib/lp/registry/scripts/entitlement.py 2011-12-19 23:38:16 +0000
+++ lib/lp/registry/scripts/entitlement.py 1970-01-01 00:00:00 +0000
@@ -1,330 +0,0 @@
-# Copyright 2009-2011 Canonical Ltd. This software is licensed under the
-# GNU Affero General Public License version 3 (see the file LICENSE).
-
-"""Import entitlements from Salesforce.
-
-Provide a class that allows the writing and reading of entitlement exchange
-files and a class to create and update entitlements in Launchpad.
-"""
-
-__metaclass__ = type
-__all__ = [
- 'EntitlementExchange',
- 'EntitlementImporter',
- 'InvalidFormat',
- 'NoSuchEntitlement',
- 'UnsupportedVersion',
- ]
-
-import cStringIO
-import csv
-import datetime
-import re
-import time
-
-import pytz
-from zope.component import getUtility
-
-from lp.app.errors import NotFoundError
-from lp.registry.interfaces.entitlement import (
- EntitlementState,
- EntitlementType,
- IEntitlementSet,
- )
-from lp.registry.interfaces.person import IPersonSet
-from lp.services.unicode_csv import (
- UnicodeDictReader,
- UnicodeDictWriter,
- )
-
-
-COMMENT = '#'
-COMMA = ','
-
-
-class NoSuchEntitlement(Exception):
- """Used if a non-existent entitlement is specified."""
-
-
-class UnsupportedVersion(Exception):
- """Used if the version is not supported."""
-
-
-class InvalidFormat(Exception):
- """Used if the file format is not as expected."""
-
-
-class RequiredValueMissing(Exception):
- """Used if a required value was not provided."""
-
-
-class EntitlementExchange:
- """Define the exchange format for entitlement data.
-
- Writers of entitlement data should use the 'writerFactory' method to
- obtain a writer object. Readers should use the 'readerFactory'. They
- return a UnicodeDictWriter and UnicodeDictReader respectively.
-
- Any changes to the list of fieldnames or their order will require an
- increment in the version value.
- """
-
- file_header = "%s Entitlement exchange format version" % COMMENT
- version = 1
- version_re = re.compile(
- "^%s (\d+)" % file_header)
-
- fieldnames = [
- 'id', 'ext_id', 'person_name', 'entitlement_type', 'quota',
- 'amount_used', 'date_starts', 'date_expires', 'date_created',
- 'registrant_name', 'approved_by_name', 'state', 'whiteboard',
- ]
-
- @staticmethod
- def _preprocessData(in_file):
- """Verify the version and remove comments."""
- version_line = in_file.readline()
- match = EntitlementExchange.version_re.search(version_line)
- if not match:
- raise InvalidFormat(
- "The first line does not have valid version information.")
- read_version = int(match.group(1))
- if EntitlementExchange.version != read_version:
- raise UnsupportedVersion(
- "Version %d of the file format is not supported." %
- read_version)
- lines= [line for line in in_file.readlines()
- if not line.lstrip().startswith(COMMENT)]
- return "".join(lines)
-
- @staticmethod
- def readerFactory(in_file):
- """Return a properly provisioned reader.
-
- Assumes data in the file is UTF-8 encoded.
- """
-
- filedata = EntitlementExchange._preprocessData(in_file)
- return UnicodeDictReader(cStringIO.StringIO(filedata),
- EntitlementExchange.fieldnames,
- skipinitialspace=True,
- quoting=csv.QUOTE_ALL)
-
- @staticmethod
- def writerFactory(filedescriptor):
- """Return a properly provisioned writer.
-
- Data in the file will be UTF-8 encoded.
- """
-
- filedescriptor.write(
- "%s %d\n" % (EntitlementExchange.file_header,
- EntitlementExchange.version))
- filedescriptor.write(
- "%s %s\n" % (COMMENT,
- COMMA.join(EntitlementExchange.fieldnames)))
- writer = UnicodeDictWriter(filedescriptor,
- EntitlementExchange.fieldnames,
- skipinitialspace=True,
- quoting=csv.QUOTE_ALL)
- return writer
-
-
-class EntitlementImporter:
- """Class for writing and updating entitlement data.
-
- Methods create_entitlements and update_entitlements are called with a list
- of dictionaries representing entitlement data.
- """
- def __init__(self, logger):
- self.logger = logger
-
- def _replacePersonName(self, entitlement, old_key, new_key,
- row_no, required=False):
- """Replace a person's name with a Person object in the entitlement.
-
- Raise RequiredValueMissing if the old_key is not found in the
- entitlement dictionary and required is True.
- Raise NotFoundError if no matching person can be found.
- """
- person_name = entitlement.get(old_key, '')
- del entitlement[old_key]
- if person_name == '':
- if required:
- raise RequiredValueMissing(
- "'person_name' not supplied in row %d." % row_no)
- else:
- return entitlement
- person = getUtility(IPersonSet).getByName(person_name)
- if person is None:
- self.logger.error(
- "[E%d] Person '%s' is not found." % (
- row_no, person_name))
- raise NotFoundError(
- "Person '%s' not supplied in row %d." % (
- person_name, row_no))
- entitlement[new_key] = person
- return entitlement
-
- def _normalizeEntitlement(
- self, entitlement, row_no, person_required=True):
- """Normalize a dictionary representing an entitlement.
-
- Convert names of people and teams to database objects and
- convert string representations of numerics to the correct type.
- Remove any keys in the dictionary that do not correspond to attributes
- on an Entitlement.
- """
- entitlement = self._replacePersonName(
- entitlement, 'person_name', 'person', row_no, person_required)
- entitlement = self._replacePersonName(
- entitlement, 'registrant_name', 'registrant', row_no)
- entitlement = self._replacePersonName(
- entitlement, 'approved_by_name', 'approved_by', row_no)
-
- # Remove the 'ext_id' since it is not part of the Launchpad data.
- del entitlement['ext_id']
-
- # Convert numeric data from string to int.
- for field in ['id', 'quota', 'entitlement_type', 'state', 'amount_used']:
- if entitlement[field]:
- entitlement[field] = int(entitlement[field])
-
- # Convert strings to dates.
- for field in ['date_starts', 'date_expires', 'date_created']:
- if entitlement[field]:
- date_string = entitlement[field]
- if len(date_string) == len('YYYY-mm-dd'):
- year, month, day, hour, minute, second = time.strptime(
- date_string, '%Y-%m-%d')[:6]
- elif len(date_string) == len('YYYY-mm-dd HH:MM:SS'):
- year, month, day, hour, minute, second = time.strptime(
- date_string, '%Y-%m-%d %H:%M:%S')[:6]
- else:
- raise AssertionError(
- 'Unknown date format: %s' % date_string)
- entitlement[field] = datetime.datetime(
- year, month, day, hour, minute, second,
- tzinfo=pytz.timezone('UTC'))
-
- # Convert the entitlement_type and state to the corresponding
- # database objects.
- if entitlement['entitlement_type']:
- entitlement_type = entitlement['entitlement_type']
- entitlement['entitlement_type'] = (
- EntitlementType.items.mapping[entitlement_type])
-
- if entitlement['state']:
- state = entitlement['state']
- entitlement['state'] = (
- EntitlementState.items.mapping[state])
-
- # Remove the entries from the dictionary that only have placeholder
- # data.
- for key, value in entitlement.items():
- if value == '':
- del entitlement[key]
- return entitlement
-
- def _checkRequired(self, entitlement, required, row_no):
- """Check to see that all required keys are in the entitlement."""
- for key in required:
- val = entitlement.get(key, '')
- # Test for None or ''. No boolean variable are expected.
- if val == '':
- self.logger.error(
- "[E%d] A required key is missing: %s." % (row_no, key))
- return False
- return True
-
- def createEntitlements(self, entitlements):
- """Create a new entitlement for each in the list.
-
- Return a list of sparsely populated dictionaries suitable for writing
- as a return CSV file.
- """
-
- required = ['ext_id', 'person_name', 'quota', 'entitlement_type',
- 'state']
- entitlement_set = getUtility(IEntitlementSet)
- new_entitlements = []
- for row_no, entitlement in enumerate(entitlements):
- if self._checkRequired(entitlement, required, row_no) is False:
- continue
- ext_id = entitlement.get('ext_id')
- try:
- normalized_entitlement = self._normalizeEntitlement(
- entitlement, row_no)
- except NotFoundError:
- continue
- except RequiredValueMissing:
- continue
-
- new_entitlement = entitlement_set.new(**normalized_entitlement)
-
- if new_entitlement is not None:
- # Add a dictionary with id and ext_id to the list of
- # new entitlements.
- new_entitlements.append(dict(id=str(new_entitlement.id),
- ext_id=ext_id))
- return new_entitlements
-
- def updateEntitlements(self, entitlements):
- """Update an existing entitlement.
-
- The entitlement must already exist. A list of dictionaries with the
- ids of the entitlments that were modified is returned.
- """
-
- modified = []
- required = ['id']
- for row_no, upd_entitlement in enumerate(entitlements):
- if not self._checkRequired(upd_entitlement, required, row_no):
- continue
- # The ext_id must be cached before the data is normalized.
- ext_id = upd_entitlement.get('ext_id')
-
- try:
- norm_entitlement = self._normalizeEntitlement(
- upd_entitlement, row_no, person_required=False)
- except NotFoundError:
- continue
- except RequiredValueMissing:
- continue
-
- lp_id = norm_entitlement.get('id')
- entitlement_set = getUtility(IEntitlementSet)
-
- existing = entitlement_set.get(lp_id)
- if existing is None:
- self.logger.error(
- "[E%d] Invalid entitlement id: %d" % (row_no,
- lp_id))
- continue
-
- succeeded = True
- for (key, val) in norm_entitlement.items():
- if key == 'id':
- pass
- elif key == 'person':
- self.logger.info(
- "[E%d] You may not change the person for the "
- "entitlement." % (row_no))
- succeeded = False
- break
- elif key == 'whiteboard':
- # Append the whiteboard value rather than replacing it.
- existing.whiteboard = "%s\n%s" % (existing.whiteboard,
- val)
- elif key in ['entitlement_type', 'quota', 'amount_used',
- 'date_starts', 'date_expires', 'date_created',
- 'registrant', 'approved_by', 'state']:
- setattr(existing, key, val)
- else:
- self.logger.error(
- "[E%d] Unrecognized key: %s." % (row_no, key))
- succeeded = False
- break
- if succeeded:
- modified.append(dict(id=str(lp_id)))
- return modified
=== removed file 'lib/lp/registry/tests/test_entitlementimport.py'
--- lib/lp/registry/tests/test_entitlementimport.py 2012-01-01 02:58:52 +0000
+++ lib/lp/registry/tests/test_entitlementimport.py 1970-01-01 00:00:00 +0000
@@ -1,184 +0,0 @@
-# Copyright 2009 Canonical Ltd. This software is licensed under the
-# GNU Affero General Public License version 3 (see the file LICENSE).
-
-"""Test EntitlementExchange and EntitlementImporter."""
-
-__metaclass__ = type
-
-from cStringIO import StringIO
-import logging
-import unittest
-
-from zope.testing.loghandler import Handler
-
-from lp.registry.scripts.entitlement import (
- EntitlementExchange,
- EntitlementImporter,
- InvalidFormat,
- UnsupportedVersion,
- )
-from lp.testing.layers import LaunchpadZopelessLayer
-
-
-class EntitlementExchangeTestCase(unittest.TestCase):
- """Test EntitlementExchange methods."""
- layer = LaunchpadZopelessLayer
-
- def test_preprocessData(self):
- """The preprocessor verifies the header and removes comments."""
- # Wrong header
- data = ("# bad format data\n"
- "more data")
- in_file = StringIO(data)
- self.assertRaises(
- InvalidFormat, EntitlementExchange._preprocessData, in_file)
-
- # Invalid version
- data = ("# Entitlement exchange format version 0\n"
- "more data")
- in_file = StringIO(data)
- self.assertRaises(
- UnsupportedVersion, EntitlementExchange._preprocessData, in_file)
-
- # Only one line should remain after processing
- data = ("# Entitlement exchange format version 1\n"
- "# comment line\n"
- " # another comment\n"
- "'name', 'date' #valid line")
- in_file = StringIO(data)
- processed = EntitlementExchange._preprocessData(in_file)
- self.assertEqual(len(processed.split('\n')), 1)
-
-class EntitlementImporterTestCase(unittest.TestCase):
- """Test EntitlementImport methods."""
- layer = LaunchpadZopelessLayer
-
- def setUp(self):
- """Setup the test environment and retrieve useful instances."""
- self.log = logging.getLogger("test_entitlement")
- self.log.setLevel(logging.INFO)
- self.handler = Handler(self)
- self.handler.add(self.log.name)
-
- def tearDown(self):
- """Teardown the test environment."""
- self.layer.txn.commit()
- self.handler.close()
-
- def _getImporterAndReader(self, data):
- in_file = StringIO(data)
- importer = EntitlementImporter(self.log)
- return importer, EntitlementExchange.readerFactory(in_file)
-
- def _testCreate(self, data):
- importer, reader = self._getImporterAndReader(data)
- return importer.createEntitlements(reader)
-
- def _testUpdate(self, data):
- importer, reader = self._getImporterAndReader(data)
- return importer.updateEntitlements(reader)
-
- def test_manipulateEntitlement(self):
- """Test creating and updating entitlements."""
-
- def test_wrongVersion(self):
- """Wrong version."""
- data = r"""# Entitlement exchange format version 0"""
- in_file = StringIO(data)
- importer = EntitlementImporter(self.log)
- self.assertRaises(UnsupportedVersion,
- EntitlementExchange.readerFactory,
- in_file)
-
- def test_successfulInsert(self):
- """Successfully insert an entitlement."""
- data = ("# Entitlement exchange format version 1\n"
- ",A-100, lifeless, 10, 100, 0, 2007-06-14, , , "
- "keybuk, keybuk, 20,")
- results = self._testCreate(data)
- self.assertEqual(len(results), 1)
-
- def test_insertUsingNonExistentPerson(self):
- """Attempt to insert using a non-existent person."""
- data = ("# Entitlement exchange format version 1\n"
- ",A-100, persona_non_grata, 10, 100, 0, 2007-06-14, , , "
- "keybuk, keybuk, 20,")
- results = self._testCreate(data)
- self.handler.assertLogsMessage(
- "[E0] Person 'persona_non_grata' "
- "is not found.", level=logging.ERROR)
-
- def test_omitQuota(self):
- """Omit the quota and get an error."""
- data = ("# Entitlement exchange format version 1\n"
- ",A-100, lifeless, 10, , 0, 2007-06-14, , , "
- "keybuk, keybuk, 20,")
- results = self._testCreate(data)
- self.handler.assertLogsMessage(
- "[E0] A required key is missing: quota.",
- level=logging.ERROR)
-
- def test_omitPerson(self):
- """Omit the person and get an error."""
- data = ("# Entitlement exchange format version 1\n"
- ",A-100, , 10, 100, 0, 2007-06-14, , , "
- "keybuk, keybuk, 20,")
- results = self._testCreate(data)
- self.handler.assertLogsMessage(
- "[E0] A required key is missing: person_name.",
- level=logging.ERROR)
-
- def test_omitExtId(self):
- """Omit the ext_id and get an error."""
- data = ("# Entitlement exchange format version 1\n"
- ",, lifeless, 10, 100, 0, 2007-06-14, , , "
- "keybuk, keybuk, 20,")
- results = self._testCreate(data)
- self.handler.assertLogsMessage(
- "[E0] A required key is missing: ext_id.",
- level=logging.ERROR)
-
- def test_omitEntitlementType(self):
- """Omit the entitlement_type and get an error."""
- data = ("# Entitlement exchange format version 1\n"
- ",A-100, lifeless, , 100, 0, 2007-06-14, , , "
- "keybuk, keybuk, 20,")
- results = self._testCreate(data)
- self.handler.assertLogsMessage(
- "[E0] A required key is missing: entitlement_type.",
- level=logging.ERROR)
-
- def test_omitState(self):
- """Omit the state and get an error."""
- data = ("# Entitlement exchange format version 1\n"
- ",A-100, lifeless, 10, 100, 0, 2007-06-14, , , "
- "keybuk, keybuk, ,")
- results = self._testCreate(data)
- self.handler.assertLogsMessage(
- "[E0] A required key is missing: state.",
- level=logging.ERROR)
-
- def test_updateWithInvalidId(self):
- """Update using an invalid entitlement id."""
- data = ("# Entitlement exchange format version 1\n"
- "9999,A-100,kiko, ,1500, , , , , , , , ")
- results = self._testUpdate(data)
- self.handler.assertLogsMessage(
- "[E0] Invalid entitlement id: 9999",
- level=logging.ERROR)
-
- def test_updateChangingPerson(self):
- """Changing the person, which isn't allowed."""
- data = ("# Entitlement exchange format version 1\n"
- ",A-100, lifeless, 10, 100, 0, 2007-06-14, , , "
- "keybuk, keybuk, 20,")
- results = self._testCreate(data)
- self.assertEqual(len(results), 1)
- valid_id = results[0].get('id')
- data = ("# Entitlement exchange format version 1\n"
- " %s, A-100, kiko, , 1500, , , , , , , , " %
- valid_id)
- results = self._testUpdate(data)
- self.handler.assertLogsMessage(
- "[E0] You may not change the person for the entitlement.",
- level=logging.INFO)
=== modified file 'lib/lp/security.py'
--- lib/lp/security.py 2012-02-08 05:07:20 +0000
+++ lib/lp/security.py 2012-02-14 00:24:21 +0000
@@ -103,7 +103,6 @@
IDistroSeriesDifferenceEdit,
)
from lp.registry.interfaces.distroseriesparent import IDistroSeriesParent
-from lp.registry.interfaces.entitlement import IEntitlement
from lp.registry.interfaces.gpg import IGPGKey
from lp.registry.interfaces.irc import IIrcID
from lp.registry.interfaces.location import IPersonLocation
@@ -2249,26 +2248,6 @@
user.inTeam(self.obj.target_branch.reviewer))
-class ViewEntitlement(AuthorizationBase):
- """Permissions to view IEntitlement objects.
-
- Allow the owner of the entitlement, the entitlement registrant,
- or any member of the team or any admin to view the entitlement.
- """
- permission = 'launchpad.View'
- usedfor = IEntitlement
-
- def checkAuthenticated(self, user):
- """Is the user able to view an Entitlement attribute?
-
- Any team member can edit a branch subscription for their team.
- Launchpad Admins can also edit any branch subscription.
- """
- return (user.inTeam(self.obj.person) or
- user.inTeam(self.obj.registrant) or
- user.in_admin)
-
-
class AdminDistroSeriesLanguagePacks(
OnlyRosettaExpertsAndAdmins,
EditDistroSeriesByReleaseManagerOrDistroOwnersOrAdmins):
=== removed file 'scripts/entitlements-to-lp.py'
--- scripts/entitlements-to-lp.py 2012-01-01 03:13:08 +0000
+++ scripts/entitlements-to-lp.py 1970-01-01 00:00:00 +0000
@@ -1,83 +0,0 @@
-#!/usr/bin/python -S
-#
-# Copyright 2009 Canonical Ltd. This software is licensed under the
-# GNU Affero General Public License version 3 (see the file LICENSE).
-
-# pylint: disable-msg=W0403
-import _pythonpath
-
-import logging
-import sys
-
-from lp.registry.scripts.entitlement import (
- EntitlementExchange,
- EntitlementImporter,
- )
-from lp.services.scripts.base import LaunchpadScript
-
-
-class ImportEntitlementsScript(LaunchpadScript):
- """Script for to import entitlement data into Launchpad."""
-
- description = "Create or update entitlements."
- usage = ("usage: %s [-c|--create | -u|--update] file_name" %
- sys.argv[0])
-
- loglevel = logging.INFO
-
- def add_my_options(self):
- """See `LaunchpadScript`."""
- self.parser.add_option(
- '-c', '--create', action='store_const', const='create',
- help='Create new entitlements', dest='action')
- self.parser.add_option(
- '-u', '--update', action='store_const', const='update',
- help='Update existing entitlements', dest='action')
- self.parser.add_option(
- '-f', '--infile', action='store', default='-',
- help='Input file name ("-" for stdin)', dest='in_file_name')
- self.parser.add_option(
- '-o', '--outfile', action='store', default='-',
- help='Output file name ("-" for stdout)', dest='out_file_name')
-
- def main(self):
- """See `LaunchpadScript`."""
-
- action = self.options.action
-
- if self.options.in_file_name == '-':
- in_file = sys.stdin
- else:
- in_file = open(self.options.in_file_name, "rb")
-
- if self.options.out_file_name == '-':
- out_file = sys.stdout
- else:
- out_file = open(self.options.out_file_name, "wb")
-
- # get a reader and writer
- reader = EntitlementExchange.readerFactory(in_file)
- entitlement_writer = EntitlementImporter(self.logger)
- importer = EntitlementImporter(self.logger)
- if action == 'create':
- out_data = importer.createEntitlements(reader)
- elif action == 'update':
- out_data = importer.updateEntitlements(reader)
- elif action is None:
- self.logger.error("No action specified. Use either -c or -u.")
- return 1
- else:
- self.logger.error("Invalid action: %s\n" % action)
- return 1
-
- self.txn.commit()
-
- if out_data:
- writer = EntitlementExchange.writerFactory(out_file)
- writer.writerows(out_data)
- return 0
-
-if __name__ == '__main__':
- script = ImportEntitlementsScript(
- 'lp.services.scripts.entitlements')
- script.run()