Skip to content

Commit eaafb62

Browse files
committed
Update the PeopleAPI
Ensure all currently documented Spark API request parameters are represented in the package’s API. Refactor the request methods to defer request-construction errors to the Spark-API (future proofing and simplifies the number of exception types that need to be caught). Refactor parameter type checking to utilize a common package utility function, which raises `TypeError`s when parameter types are incorrect (more accurate exception representation - TypeError as opposed to AssertionError).
1 parent 1630ce1 commit eaafb62

File tree

2 files changed

+193
-111
lines changed

2 files changed

+193
-111
lines changed

ciscosparkapi/api/people.py

Lines changed: 139 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
44
Classes:
55
Person: Models a Spark 'person' JSON object as a native Python object.
6-
PeopleAPI: Wrappers the Cisco Spark People-API and exposes the API calls as
7-
Python method calls that return native Python objects.
6+
PeopleAPI: Wraps the Cisco Spark People-API and exposes the APIs as native
7+
Python methods that return native Python objects.
88
99
"""
1010

@@ -19,8 +19,11 @@
1919
from builtins import *
2020
from past.builtins import basestring
2121

22-
from ciscosparkapi.exceptions import ciscosparkapiException
23-
from ciscosparkapi.utils import generator_container
22+
from ciscosparkapi.utils import (
23+
check_type,
24+
dict_from_items_with_values,
25+
generator_container,
26+
)
2427
from ciscosparkapi.restsession import RestSession
2528
from ciscosparkapi.sparkdata import SparkData
2629

@@ -32,7 +35,7 @@
3235

3336

3437
class Person(SparkData):
35-
"""Model a Spark 'person' JSON object as a native Python object."""
38+
"""Model a Spark person JSON object as a native Python object."""
3639

3740
def __init__(self, json):
3841
"""Initialize a Person data object from a dictionary or JSON string.
@@ -58,13 +61,7 @@ def id(self):
5861

5962
@property
6063
def emails(self):
61-
"""Email address(es) of the person.
62-
63-
CURRENT LIMITATION: Spark (today) only allows you to provide a single
64-
email address for a person. The list data type was selected to enable
65-
future support for providing multiple email address.
66-
67-
"""
64+
"""Email address(es) of the person."""
6865
return self._json['emails']
6966

7067
@property
@@ -149,20 +146,23 @@ def __init__(self, session):
149146
API calls to the Cisco Spark service.
150147
151148
Raises:
152-
AssertionError: If the parameter types are incorrect.
149+
TypeError: If the parameter types are incorrect.
153150
154151
"""
155-
assert isinstance(session, RestSession)
152+
check_type(session, RestSession)
153+
156154
super(PeopleAPI, self).__init__()
155+
157156
self._session = session
158157

159158
@generator_container
160-
def list(self, email=None, displayName=None, orgId=None, id=None, max=None, **query_params):
159+
def list(self, email=None, displayName=None, id=None, orgId=None, max=None,
160+
**query_params):
161161
"""List people
162162
163163
This method supports Cisco Spark's implementation of RFC5988 Web
164164
Linking to provide pagination support. It returns a generator
165-
container that incrementally yield all people returned by the
165+
container that incrementally yields all people returned by the
166166
query. The generator will automatically request additional 'pages' of
167167
responses from Spark as needed until all responses have been returned.
168168
The container makes the generator safe for reuse. A new API call will
@@ -174,190 +174,218 @@ def list(self, email=None, displayName=None, orgId=None, id=None, max=None, **qu
174174
email(basestring): The e-mail address of the person to be found.
175175
displayName(basestring): The complete or beginning portion of
176176
the displayName to be searched.
177-
id(basestring): List people by ID. Accepts up to 85 person IDs separated by commas.
177+
id(basestring): List people by ID. Accepts up to 85 person IDs
178+
separated by commas.
178179
orgId(basestring): The organization id.
179180
max(int): Limits the maximum number of people returned from the
180181
Spark service per request.
182+
**query_params: Additional query parameters (provides support for
183+
query parameters that may be added in the future).
181184
182185
Returns:
183-
GeneratorContainer: When iterated, the GeneratorContainer, yields
184-
the people returned by the Cisco Spark query.
186+
GeneratorContainer: A GeneratorContainer which, when iterated,
187+
yields the people returned by the Cisco Spark query.
185188
186189
Raises:
187-
AssertionError: If the parameter types are incorrect.
190+
TypeError: If the parameter types are incorrect.
188191
SparkApiError: If the Cisco Spark cloud returns an error.
189192
190193
"""
191-
# Process args
192-
assert email is None or isinstance(email, basestring)
193-
assert displayName is None or isinstance(displayName, basestring)
194-
assert orgId is None or isinstance(orgId, basestring)
195-
assert id is None or isinstance(id, basestring)
196-
assert max is None or isinstance(max, int)
197-
params = {}
198-
if id:
199-
params["id"] = id
200-
elif email:
201-
params['email'] = email
202-
elif displayName:
203-
params['displayName'] = displayName
204-
if orgId:
205-
params["orgId"] = orgId
206-
if max:
207-
params['max'] = max
208-
# Process query_param keyword arguments
209-
if query_params:
210-
params.update(query_params)
194+
check_type(id, basestring)
195+
check_type(email, basestring)
196+
check_type(displayName, basestring)
197+
check_type(orgId, basestring)
198+
check_type(max, int)
199+
200+
params = dict_from_items_with_values(
201+
query_params,
202+
id=id,
203+
email=email,
204+
displayName=displayName,
205+
orgId=orgId,
206+
max=max,
207+
)
208+
211209
# API request - get items
212210
items = self._session.get_items('people', params=params)
211+
213212
# Yield Person objects created from the returned items JSON objects
214213
for item in items:
215214
yield Person(item)
216215

217-
def create(self, emails, **person_attributes):
216+
def create(self, emails, displayName=None, firstName=None, lastName=None,
217+
avatar=None, orgId=None, roles=None, licenses=None,
218+
**person_attributes):
218219
"""Create a new user account for a given organization
219220
220221
Only an admin can create a new user account.
221222
222-
You must specify displayName and/or firstName and lastName.
223-
224223
Args:
225-
emails(list): Email address(es) of the person. (list of strings)
226-
CURRENT LIMITATION: Spark (today) only allows you to provide a
227-
single email address for a person. The list data type was
228-
selected to enable future support for providing multiple email
229-
address.
230-
**person_attributes
231-
displayName(basestring): Full name of the person
232-
firstName(basestring): First name of the person
233-
lastName(basestring): Last name of the person
234-
avatar(basestring): URL to the person's avatar in PNG format
224+
emails(list): Email address(es) of the person (list of strings).
225+
displayName(basestring): Full name of the person.
226+
firstName(basestring): First name of the person.
227+
lastName(basestring): Last name of the person.
228+
avatar(basestring): URL to the person's avatar in PNG format.
235229
orgId(basestring): ID of the organization to which this
236-
person belongs
230+
person belongs.
237231
roles(list): Roles of the person (list of strings containing
238-
the role IDs to be assigned to the person)
232+
the role IDs to be assigned to the person).
239233
licenses(list): Licenses allocated to the person (list of
240-
strings containing the license IDs to be allocated to the
241-
person)
234+
strings - containing the license IDs to be allocated to the
235+
person).
236+
**person_attributes: Additional person attributes (provides support
237+
for attributes that may be added in the future).
242238
243239
Returns:
244-
Person: With the details of the created person.
240+
Person: A Person object with the details of the created person.
245241
246242
Raises:
247-
AssertionError: If the parameter types are incorrect.
248-
ciscosparkapiException: If required parameters have been omitted.
243+
TypeError: If the parameter types are incorrect.
249244
SparkApiError: If the Cisco Spark cloud returns an error.
250245
251246
"""
252-
# Process args
253-
assert isinstance(emails, list) and len(emails) == 1
254-
post_data = {}
255-
post_data['emails'] = emails
256-
post_data.update(person_attributes)
247+
check_type(emails, list, may_be_none=False)
248+
check_type(displayName, basestring)
249+
check_type(firstName, basestring)
250+
check_type(lastName, basestring)
251+
check_type(avatar, basestring)
252+
check_type(orgId, basestring)
253+
check_type(roles, list)
254+
check_type(licenses, list)
255+
256+
post_data = dict_from_items_with_values(
257+
person_attributes,
258+
emails=emails,
259+
displayName=displayName,
260+
firstName=firstName,
261+
lastName=lastName,
262+
avatar=avatar,
263+
orgId=orgId,
264+
roles=roles,
265+
licenses=licenses,
266+
)
257267

258268
# API request
259-
json_obj = self._session.post('people', json=post_data)
269+
json_data = self._session.post('people', json=post_data)
260270

261271
# Return a Room object created from the returned JSON object
262-
return Person(json_obj)
272+
return Person(json_data)
263273

264-
def update(self, personId, **person_attributes):
274+
def update(self, personId, emails=None, displayName=None, firstName=None,
275+
lastName=None, avatar=None, orgId=None, roles=None,
276+
licenses=None, **person_attributes):
265277
"""Update details for a person, by ID.
266278
267-
Only an admin can update a person details.
279+
Only an admin can update a person's details.
280+
281+
Email addresses for a person cannot be changed via the Spark API.
282+
283+
Include all details for the person. This action expects all user
284+
details to be present in the request. A common approach is to first GET
285+
the person's details, make changes, then PUT both the changed and
286+
unchanged values.
268287
269288
Args:
270-
personId(basestring): The ID of the person to be updated.
271-
**person_attributes
272-
emails(list): Email address(es) of the person. (list of
273-
strings) CURRENT LIMITATION: Spark (today) only allows you
274-
to provide a single email address for a person. The list
275-
data type was selected to enable future support for
276-
providing multiple email address.
277-
displayName(basestring): Full name of the person
278-
firstName(basestring): First name of the person
279-
lastName(basestring): Last name of the person
280-
avatar(basestring): URL to the person's avatar in PNG format
289+
personId(basestring): The 'id' of the person to be updated.
290+
emails(list): Email address(es) of the person (list of strings).
291+
displayName(basestring): Full name of the person.
292+
firstName(basestring): First name of the person.
293+
lastName(basestring): Last name of the person.
294+
avatar(basestring): URL to the person's avatar in PNG format.
281295
orgId(basestring): ID of the organization to which this
282-
person belongs
296+
person belongs.
283297
roles(list): Roles of the person (list of strings containing
284-
the role IDs to be assigned to the person)
298+
the role IDs to be assigned to the person).
285299
licenses(list): Licenses allocated to the person (list of
286-
strings containing the license IDs to be allocated to the
287-
person)
300+
strings - containing the license IDs to be allocated to the
301+
person).
302+
**person_attributes: Additional person attributes (provides support
303+
for attributes that may be added in the future).
288304
289305
Returns:
290-
Person: With the updated person details.
306+
Person: A Person object with the updated details.
291307
292308
Raises:
293-
AssertionError: If the parameter types are incorrect.
294-
ciscosparkapiException: If an update attribute is not provided.
309+
TypeError: If the parameter types are incorrect.
295310
SparkApiError: If the Cisco Spark cloud returns an error.
296311
297312
"""
298-
# Process args
299-
assert isinstance(personId, basestring)
300-
301-
# Process update_attributes keyword arguments
302-
if not person_attributes:
303-
error_message = "At least one **update_attributes keyword " \
304-
"argument must be specified."
305-
raise ciscosparkapiException(error_message)
313+
check_type(emails, list)
314+
check_type(displayName, basestring)
315+
check_type(firstName, basestring)
316+
check_type(lastName, basestring)
317+
check_type(avatar, basestring)
318+
check_type(orgId, basestring)
319+
check_type(roles, list)
320+
check_type(licenses, list)
321+
322+
put_data = dict_from_items_with_values(
323+
person_attributes,
324+
emails=emails,
325+
displayName=displayName,
326+
firstName=firstName,
327+
lastName=lastName,
328+
avatar=avatar,
329+
orgId=orgId,
330+
roles=roles,
331+
licenses=licenses,
332+
)
306333

307334
# API request
308-
json_obj = self._session.put('people/' + personId,
309-
json=person_attributes)
335+
json_data = self._session.put('people/' + personId, json=put_data)
310336

311337
# Return a Person object created from the returned JSON object
312-
return Person(json_obj)
338+
return Person(json_data)
313339

314340
def get(self, personId):
315341
"""Get person details, by personId.
316342
317343
Args:
318-
personId(basestring): The personID of the person.
344+
personId(basestring): The 'id' of the person to be retrieved.
319345
320346
Returns:
321-
Person: With the details of the requested person.
347+
Person: A Person object with the details of the requested person.
322348
323349
Raises:
324-
AssertionError: If the parameter types are incorrect.
350+
TypeError: If the parameter types are incorrect.
325351
SparkApiError: If the Cisco Spark cloud returns an error.
326352
327353
"""
328-
# Process args
329-
assert isinstance(personId, basestring)
354+
check_type(personId, basestring, may_be_none=False)
355+
330356
# API request
331-
json_obj = self._session.get('people/' + personId)
357+
json_data = self._session.get('people/' + personId)
358+
332359
# Return a Person object created from the response JSON data
333-
return Person(json_obj)
360+
return Person(json_data)
334361

335362
def delete(self, personId):
336363
"""Remove a person from the system.
337364
338365
Only an admin can remove a person.
339366
340367
Args:
341-
personId(basestring): The personID of the person.
368+
personId(basestring): The 'id' of the person to be deleted.
342369
343370
Raises:
344371
AssertionError: If the parameter types are incorrect.
345372
SparkApiError: If the Cisco Spark cloud returns an error.
346373
347374
"""
348-
# Process args
349-
assert isinstance(personId, basestring)
375+
check_type(personId, basestring, may_be_none=False)
376+
350377
# API request
351378
self._session.delete('people/' + personId)
352379

353380
def me(self):
354-
"""Get the person details of the account accessing the API 'me'.
381+
"""Get the details of the person accessing the API.
355382
356383
Raises:
357384
SparkApiError: If the Cisco Spark cloud returns an error.
358385
359386
"""
360387
# API request
361-
json_obj = self._session.get('people/me')
388+
json_data = self._session.get('people/me')
389+
362390
# Return a Person object created from the response JSON data
363-
return Person(json_obj)
391+
return Person(json_data)

0 commit comments

Comments
 (0)