1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
|
Locations for People and Teams
==============================
The PersonLocation object stores information about the location and time
zone of a person. It also remembers who provided that information, and
when. This is designed to make it possible to have people provide
location / time zone info for other people in a wiki style.
>>> from canonical.launchpad.webapp.testing import verifyObject
>>> from lp.registry.interfaces.location import IObjectWithLocation
>>> from lp.registry.interfaces.person import IPersonSet
>>> personset = getUtility(IPersonSet)
A Person implements the IObjectWithLocation interface.
>>> login('test@canonical.com')
>>> marilize = personset.getByName('marilize')
>>> verifyObject(IObjectWithLocation, marilize)
True
A Person has a PersonLocation record, if there is any location
information associated with them. That implements the IPersonLocation
interface.
>>> from lp.registry.interfaces.location import IPersonLocation
>>> marilize.location
<PersonLocation...
>>> verifyObject(IPersonLocation, marilize.location)
True
In some cases, a person has a time zone, but no location.
>>> print marilize.time_zone
Africa/Maseru
>>> print marilize.latitude
None
The location for a person is set with the "setLocation" method. This
requires that the user providing the information is passed as a
parameter.
A user cannot set another user's location.
>>> jdub = personset.getByName('jdub')
>>> login_person(jdub)
>>> cprov = personset.getByName('cprov')
>>> cprov.setLocation(-43.0, -62.1, 'America/Sao_Paulo', jdub)
Traceback (most recent call last):
...
Unauthorized:...
A user can set his own location.
>>> login_person(cprov)
>>> cprov.setLocation(-43.2, -61.93, 'America/Sao_Paulo', cprov)
cprov can change his location information. We need to deal
with some floating point precision issues here, hence the rounding.
>>> login_person(cprov)
>>> cprov.setLocation(-43.52, -61.93, 'America/Sao_Paulo', cprov)
>>> abs(cprov.latitude + 43.52) < 0.001
True
Admins can set a user's location.
>>> admin = personset.getByName('name16')
>>> login_person(admin)
>>> cprov.setLocation(-43.0, -62.1, 'America/Sao_Paulo', admin)
>>> abs(cprov.longitude + 62.1) < 0.001
True
We cannot store a location for a team, though.
>>> guadamen = personset.getByName('guadamen')
>>> guadamen.setLocation(34.5, 23.1, 'Africa/Maseru', jdub)
Traceback (most recent call last):
...
AssertionError:...
Nor can we set only the latitude of a person.
>>> cprov.setLocation(-43.0, None, 'America/Sao_Paulo', admin)
Traceback (most recent call last):
...
AssertionError:...
Similarly, we can't set only the longitude.
>>> cprov.setLocation(None, -43.0, 'America/Sao_Paulo', admin)
Traceback (most recent call last):
...
AssertionError:...
We can get lists of the participants in a team that do, or do not, have
locations. Specifically, we mean latitude/longitude data, not time zone
data.
When we get mapped participants, and unmapped participants, we only mean
the individuals, not other teams. We'll show that guadamen has a
sub-team, ubuntu-team, and that it still does not appear in either
mapped_participants or unmapped_participants (although its members do).
>>> for member in guadamen.activemembers:
... if member.teamowner is not None:
... print member.name
ubuntu-team
>>> len(guadamen.getMappedParticipants())
2
>>> for mapped in guadamen.getMappedParticipants():
... if mapped.teamowner is not None:
... print mapped.name
>>> guadamen.unmapped_participants.count()
7
>>> for unmapped in guadamen.unmapped_participants:
... if unmapped.teamowner is not None:
... print unmapped.name
When we iterate over the mapped_participants in a team, their locations
have been pre-cached so that we don't hit the database everytime we
access a person's .location property.
>>> from lp.services.propertycache import get_property_cache
>>> for mapped in guadamen.getMappedParticipants():
... cache = get_property_cache(mapped)
... if ("location" not in cache or
... not verifyObject(IPersonLocation, cache.location)):
... print 'No cached location on %s' % mapped.name
The mapped_participants methods takes a optional argument to limit the
number of persons in the returned list.
>>> mapped = guadamen.getMappedParticipants(limit=1)
>>> len(mapped)
1
The count of mapped and unmapped members can also be retrieved, which is
faster than getting the resultset of members.
>>> guadamen.mapped_participants_count
2
>>> guadamen.unmapped_participants_count
7
The bounds of the mapped members can be retrieved. It is a dict that contains
the minimum maximum, and central longitudes and latitudes.
>>> bounds = guadamen.getMappedParticipantsBounds()
>>> for key in sorted(bounds):
... print "%s: %s" % (key, bounds[key])
center_lat: 4...
center_lng: -30...
max_lat: 52...
max_lng: 0...
min_lat: -43...
min_lng: -62...
Calling getMappedParticipantsBounds() on a team without members is an error.
>>> unmapped_team = factory.makeTeam()
>>> unmapped_team.getMappedParticipantsBounds()
Traceback (most recent call last):
...
AssertionError: This method cannot be called when
mapped_participants_count == 0.
Location visibility
-------------------
Some people may not want their location to be disclosed to others, so
we provide a way for them to hide their location from other users. By
default a person's location is visible.
>>> salgado = personset.getByName('salgado')
>>> login_person(salgado)
>>> salgado.setLocation(-43.0, -62.1, 'America/Sao_Paulo', salgado)
>>> salgado.location.visible
True
>>> salgado.location.latitude
-43...
>>> login_person(jdub)
>>> salgado.location.latitude
-43...
But it can be changed through the setLocationVisibility() method. If the
visibility is set to False, only the person himself will be able to see
the location data except for time zone.
>>> login_person(salgado)
>>> salgado.setLocationVisibility(False)
>>> salgado.location.visible
False
>>> login_person(jdub)
>>> print salgado.time_zone
America/Sao_Paulo
>>> salgado.latitude
Traceback (most recent call last):
...
Unauthorized:...
>>> salgado.longitude
Traceback (most recent call last):
...
Unauthorized:...
>>> salgado.location.latitude
Traceback (most recent call last):
...
Unauthorized:...
A team's .mapped_participants will also exclude the members who made
their location invisible.
>>> admins = personset.getByName('admins')
>>> salgado in admins.activemembers
True
>>> salgado in admins.getMappedParticipants()
False
|