~launchpad-pqm/launchpad/devel

10121.2.9 by Henning Eggers
Added doc test for PersonRoles.
1
= PersonRoles =
2
10121.2.14 by Henning Eggers
Documentation and code improvements as per review.
3
To make it more convenient to check which roles a person has,
10121.2.9 by Henning Eggers
Added doc test for PersonRoles.
4
the IPersonRoles adapter is provided. It's main use is to easily check if a
5
person is the member of a celebrity team or is a celebrity person. In
6
addition, methods for common checks are provided, too.
7
8
The IPersonRoles interface is closely tight to the ILaunchpadCelebrities
9
interface. Any addition or removal of a person celebrity must be reflected in
10
adding or removing the corresponding property in IPersonRoles. Luckily the
10121.2.14 by Henning Eggers
Documentation and code improvements as per review.
11
celebrities.txt doctest includes a check for this and will give useful
12
information on which attribute needs to be added or removed. Both interfaces
10121.2.9 by Henning Eggers
Added doc test for PersonRoles.
13
are found in the same file. There is no need to adapt the implementation
14
class PersonRoles, though (thanks to __getattr__).
15
16
PersonRoles is most prominent in AuthenticationBase in security.py. The user
10121.2.14 by Henning Eggers
Documentation and code improvements as per review.
17
parameter to checkAuthenticated is a PersonRoles object (was a Person object).
10121.2.9 by Henning Eggers
Added doc test for PersonRoles.
18
19
20
== The person object and the adapter ==
21
22
PersonRoles is registered as an unnamed adapter for IPersonRoles.
23
13130.1.8 by Curtis Hovey
Updated import of hasdriver.
24
    >>> from lp.registry.interfaces.role import IPersonRoles
10121.2.9 by Henning Eggers
Added doc test for PersonRoles.
25
    >>> person = factory.makePerson()
26
    >>> print IPersonRoles(person)
13130.1.6 by Curtis Hovey
Move ILaunchpadCelebrity to lp.app.
27
    <lp.registry.model.personroles.PersonRoles object at ...>
10121.2.9 by Henning Eggers
Added doc test for PersonRoles.
28
29
The original Person object can be reached through the person attribute.
30
31
    >>> roles = IPersonRoles(person)
32
    >>> print roles.person is person
33
    True
34
35
36
== Celebrity persons ==
37
38
There are a number of celebrity persons defined in ILaunchpadCelebrities.
39
PersonRoles has a corresponding attribute of the same name prefixed with
40
"in_" to check if the person in question is a member of this celebrity or is
41
this celebrity. The following tests are identical.
42
13130.1.6 by Curtis Hovey
Move ILaunchpadCelebrity to lp.app.
43
    >>> from lp.app.interfaces.launchpad import ILaunchpadCelebrities
10121.2.9 by Henning Eggers
Added doc test for PersonRoles.
44
    >>> rosetta_experts = getUtility(ILaunchpadCelebrities).rosetta_experts
45
    >>> print person.inTeam(rosetta_experts)
46
    False
47
48
    >>> print roles.in_rosetta_experts
49
    False
50
51
The test will succeed once we make person a member of the team. Need to be an
52
admin to do that.
53
54
    >>> login("foo.bar@canonical.com")
55
    >>> rosetta_experts.addMember(person, rosetta_experts.teamowner)
56
    (True, ...Approved>)
57
    >>> print roles.in_rosetta_experts
58
    True
59
60
To stay consistent, all attributes are prefixed with "in_" although the
10121.2.14 by Henning Eggers
Documentation and code improvements as per review.
61
attribute names of ILaunchpadCelebrities are not all lexically correct
62
plurals, nor are all the attributes teams. This makes for odd sounding
10121.2.9 by Henning Eggers
Added doc test for PersonRoles.
63
attribute names in IPersonRoles.
64
65
    >>> print roles.in_admin
66
    False
67
    >>> print roles.in_janitor
68
    False
69
70
    >>> janitor = getUtility(ILaunchpadCelebrities).janitor
71
    >>> janitor_roles = IPersonRoles(janitor)
72
    >>> print janitor_roles.in_janitor
73
    True
74
75
76
== inTeam ==
77
78
The Person.inTeam method is available directly through PersonRoles. This can
79
be used to check for any non-celebrity team.
80
81
    >>> new_team = factory.makeTeam()
82
    >>> new_team.addMember(person, new_team.teamowner)
83
    (True, ...Approved>)
84
    >>> print person.inTeam(new_team)
85
    True
86
87
    >>> print roles.inTeam(new_team)
88
    True
89
90
91
== isOwner, isDriver ==
92
93
We can easily check for ownership and drivership. This is admittedly not much
94
shorter than calling inTeam but clearer to read.
95
96
    >>> product = factory.makeProduct(owner=person)
97
    >>> print roles.isOwner(product)
98
    True
99
100
    >>> print roles.isDriver(product)
101
    False
102
    >>> product.driver = person
103
    >>> print roles.isDriver(product)
104
    True
105
106
107
== isOneOfDrivers ==
108
109
If an object implements IHasDrivers it lists all drivers of the object and
110
possible parent objects. The method isOneOfDrivers lets us check for those.
111
112
    >>> productseries = factory.makeProductSeries(product=product)
113
    >>> print roles.isDriver(productseries)
114
    False
115
    >>> print roles.isOneOfDrivers(productseries)
116
    True
117
118
119
== isOneOf ==
120
121
Finally, sometimes a person may be one of multiple roles for an object. The
122
method isOneOf makes checking all of these a breeze.
123
124
    >>> spec = factory.makeSpecification()
125
    >>> spec.assignee = person
126
    >>> print roles.isOwner(spec)
127
    False
128
    >>> print roles.isOneOf(spec, ['owner', 'approver', 'assignee'])
129
    True