1
Locations for People and Teams
2
==============================
4
The PersonLocation object stores information about the location and time
5
zone of a person. It also remembers who provided that information, and
6
when. This is designed to make it possible to have people provide
7
location / time zone info for other people in a wiki style.
9
>>> from canonical.launchpad.webapp.testing import verifyObject
10
>>> from lp.registry.interfaces.location import IObjectWithLocation
11
>>> from lp.registry.interfaces.person import IPersonSet
12
>>> personset = getUtility(IPersonSet)
14
A Person implements the IObjectWithLocation interface.
16
>>> login('test@canonical.com')
17
>>> marilize = personset.getByName('marilize')
18
>>> verifyObject(IObjectWithLocation, marilize)
21
A Person has a PersonLocation record, if there is any location
22
information associated with them. That implements the IPersonLocation
25
>>> from lp.registry.interfaces.location import IPersonLocation
28
>>> verifyObject(IPersonLocation, marilize.location)
31
In some cases, a person has a time zone, but no location.
33
>>> print marilize.time_zone
35
>>> print marilize.latitude
38
The location for a person is set with the "setLocation" method. This
39
requires that the user providing the information is passed as a
42
A user cannot set another user's location.
44
>>> jdub = personset.getByName('jdub')
45
>>> login_person(jdub)
46
>>> cprov = personset.getByName('cprov')
47
>>> cprov.setLocation(-43.0, -62.1, 'America/Sao_Paulo', jdub)
48
Traceback (most recent call last):
52
A user can set his own location.
54
>>> login_person(cprov)
55
>>> cprov.setLocation(-43.2, -61.93, 'America/Sao_Paulo', cprov)
57
cprov can change his location information. We need to deal
58
with some floating point precision issues here, hence the rounding.
60
>>> login_person(cprov)
61
>>> cprov.setLocation(-43.52, -61.93, 'America/Sao_Paulo', cprov)
62
>>> abs(cprov.latitude + 43.52) < 0.001
65
Admins can set a user's location.
67
>>> admin = personset.getByName('name16')
68
>>> login_person(admin)
69
>>> cprov.setLocation(-43.0, -62.1, 'America/Sao_Paulo', admin)
70
>>> abs(cprov.longitude + 62.1) < 0.001
73
We cannot store a location for a team, though.
75
>>> guadamen = personset.getByName('guadamen')
76
>>> guadamen.setLocation(34.5, 23.1, 'Africa/Maseru', jdub)
77
Traceback (most recent call last):
81
Nor can we set only the latitude of a person.
83
>>> cprov.setLocation(-43.0, None, 'America/Sao_Paulo', admin)
84
Traceback (most recent call last):
88
Similarly, we can't set only the longitude.
90
>>> cprov.setLocation(None, -43.0, 'America/Sao_Paulo', admin)
91
Traceback (most recent call last):
95
We can get lists of the participants in a team that do, or do not, have
96
locations. Specifically, we mean latitude/longitude data, not time zone
99
When we get mapped participants, and unmapped participants, we only mean
100
the individuals, not other teams. We'll show that guadamen has a
101
sub-team, ubuntu-team, and that it still does not appear in either
102
mapped_participants or unmapped_participants (although its members do).
104
>>> for member in guadamen.activemembers:
105
... if member.teamowner is not None:
106
... print member.name
108
>>> len(guadamen.getMappedParticipants())
110
>>> for mapped in guadamen.getMappedParticipants():
111
... if mapped.teamowner is not None:
112
... print mapped.name
113
>>> guadamen.unmapped_participants.count()
115
>>> for unmapped in guadamen.unmapped_participants:
116
... if unmapped.teamowner is not None:
117
... print unmapped.name
119
When we iterate over the mapped_participants in a team, their locations
120
have been pre-cached so that we don't hit the database everytime we
121
access a person's .location property.
123
>>> from lp.services.propertycache import get_property_cache
124
>>> for mapped in guadamen.getMappedParticipants():
125
... cache = get_property_cache(mapped)
126
... if ("location" not in cache or
127
... not verifyObject(IPersonLocation, cache.location)):
128
... print 'No cached location on %s' % mapped.name
130
The mapped_participants methods takes a optional argument to limit the
131
number of persons in the returned list.
133
>>> mapped = guadamen.getMappedParticipants(limit=1)
137
The count of mapped and unmapped members can also be retrieved, which is
138
faster than getting the resultset of members.
140
>>> guadamen.mapped_participants_count
142
>>> guadamen.unmapped_participants_count
145
The bounds of the mapped members can be retrieved. It is a dict that contains
146
the minimum maximum, and central longitudes and latitudes.
148
>>> bounds = guadamen.getMappedParticipantsBounds()
149
>>> for key in sorted(bounds):
150
... print "%s: %s" % (key, bounds[key])
158
Calling getMappedParticipantsBounds() on a team without members is an error.
160
>>> unmapped_team = factory.makeTeam()
161
>>> unmapped_team.getMappedParticipantsBounds()
162
Traceback (most recent call last):
164
AssertionError: This method cannot be called when
165
mapped_participants_count == 0.
171
Some people may not want their location to be disclosed to others, so
172
we provide a way for them to hide their location from other users. By
173
default a person's location is visible.
175
>>> salgado = personset.getByName('salgado')
176
>>> login_person(salgado)
177
>>> salgado.setLocation(-43.0, -62.1, 'America/Sao_Paulo', salgado)
178
>>> salgado.location.visible
180
>>> salgado.location.latitude
183
>>> login_person(jdub)
184
>>> salgado.location.latitude
187
But it can be changed through the setLocationVisibility() method. If the
188
visibility is set to False, only the person himself will be able to see
189
the location data except for time zone.
191
>>> login_person(salgado)
192
>>> salgado.setLocationVisibility(False)
193
>>> salgado.location.visible
196
>>> login_person(jdub)
197
>>> print salgado.time_zone
200
Traceback (most recent call last):
203
>>> salgado.longitude
204
Traceback (most recent call last):
207
>>> salgado.location.latitude
208
Traceback (most recent call last):
212
A team's .mapped_participants will also exclude the members who made
213
their location invisible.
215
>>> admins = personset.getByName('admins')
216
>>> salgado in admins.activemembers
218
>>> salgado in admins.getMappedParticipants()