LaunchpadCelebrities

Not logged in - Log In / Register

Launchpad Celebrities

Authors: SteveAlexander, DanielDebonzi
Created: Tue Feb 8 15:40:59 UTC 2005
Status: ApprovedSpecification, InfrastructureSpecification
Implementor: Infrastructure team
Contributors: StuartBishop

Introduction

There are some objects in Launchpad that are very well known, and required for the correct operation of the system. Code often wants to refer to these specific objects directly. For example:

At present, these objects are refered to by name, hardcoded as string literals, for example in the IAuthorization adapter code in canonical/launchpad/security.py.

In the future we may decide to have a LaunchpadCelebrities table that has a single column linking to the Person table to represent these teams, as well as specific columns that link to ubuntu, debian, launchpad etc.

For now we will improve the code by having a single idiom for getting hold of one of these core objects.

We also need to have some "abstract crowds", such as "all people", "nobody", "anonymous users", that are used by the security code. We can make these crowds celebrities, and have a single idiom for getting hold of them.

API

Here's an example of using ILaunchpadCelebrities.

from canonical.launchpad.interfaces import ILaunchpadCelebrities

celebs = getUtility(ILaunchpadCelebrities)
print ITeam(celebs.admin).members
print ITeam(celebs.vcs_imports).members
# ...and so on.

Here is an example of how using the ILaunchpadCelebrities utility for an IAuthorization adapter changes it from the current state of affairs.

BEFORE

   1 class AdminByAdminsTeam(AuthorizationBase):
   2     permission = 'launchpad.Admin'
   3     usedfor = Interface
   4 
   5     def checkPermission(self, user):
   6         return person.inTeam('admins')

AFTER

   1 class AdminByAdminsTeam(AuthorizationBase):
   2     permission = 'launchpad.Admin'
   3     usedfor = Interface
   4 
   5     def checkPermission(self, user):
   6         adminteam = getUtility(ILaunchpadCelebrities).admin
   7         return user in ICrowd(adminteam)

AFTER, including CrowdControl

   1 class AdminByAdminsTeam(AuthorizationBase):
   2     permission = 'launchpad.Admin'
   3     usedfor = Interface
   4 
   5     def getAllowedCrowd(self):
   6         superteam = getUtility(ILaunchpadCelebrities).super
   7         return ICrowd(superteam)

The interface looks like this.

from zope.interface import Interface, Attribute

class ILaunchpadCelebrities(Interface):
    """The global teams in Launchpad that are responsible for global things."""

    super = Attribute("The super team.")
    buildmaster = Attribute("Build Daemon Admins")
    codeofconduct = Attribute("CoC Admin team")
    maloneexpert = Attribute("Malone experts")
    debian = Attribute("The debian distribution.")
    ubuntu = Attribute("The ubuntu distribution.")
    vcs_imports = Attribute("The 'vcs-imports' team.")

    # Special celebrities for use in authorization code.
    nobody = Attribute("The empty crowd.")
    people = Attribute("The Crowd of all People.")
    anonymous = Attribute("The Crowd that represents anonymous Users of the system.")
    absolutelyeverybody = Attribute("All people.  celebs.people + celebs.anonymous.")

Note that coding style to use the celebrities should always explicitly cast them to what you need. So, like this:

celebs = getUtility(ICelebrities)
print ICrowd(celebs.people)
print celebs.ubuntu
print celebs.ubuntu.project

Implementation

The production implementation of ILaunchpadCelebrities will be similar to the ILaunchBag implementation in that it will be a utility that implements its attributes as read-only properties. Each property will look up the relevant object by its name from its database class. The implementation is tied to the database, and so will live in canonical/launchpad/database/.

An implementation with more indirection would use the IPersonSet utility to look up the teams.

It is up to the implementor to choose which approach to take, remembering that premature optimization is the root of all evil.

To actually determine team membership, the team should be adapted to an ICrowd as documented in TeamParticipationUsage

Notes

All of the celebrity objects must be set up as part of the initial data in the database, for development, production, dogfood and testing.

Ideally the Launchpad application should confirm that it is able to acquire all of the celebrities during startup and refuse to run without them. Otherwise we run the risk of a celebrity not being present right from the start.

The DBA is also responsible for populating the database with more core teams information.

A stubbed-out utility can be used for unit tests, where this is appropriate.

We should consider creating the stub ILaunchpadCelebrities as part of the implementation.

Getting the most out of this system depends on making initZopeless have an option to read in ZCML files, and make utilities available.

Possible confusion about the type of a celebrity

It may be that using getUtility(ILaunchpadCelebrities).something will read ambiguously in code, and lead to errors. If this turns out to happen, we will encourage users of ICelebrities to explicitly cast the celeb to the desired interface. We may need to implement an IDistribution to IProject adapter for this, so that it is clear whether the the debian and ubuntu celebrities are used as projects or distributions. We can enforce this casting by making the actual celebrities into proxy objects that insist on being cast, using a __conform__ method.

We will not do this in the initial implementation, and see how it goes in practice before starting this kind of bondage and discipline.

LaunchpadCelebrities (last edited 2019-11-08 11:48:09 by cjwatson)