Skip to content

Commit

Permalink
Add wrappers for new Admin API Endpoints (#31)
Browse files Browse the repository at this point in the history
* #30 Correct REST verb in team_membership.update()

Verb should be PUT instead of POST

* #20 Add people.create() and people.update() Admin methods

Add people.create() and people.update() methods to wrap the new people
admin API endpoints.

Update the Person properties to reflect new person object attributes.
Add property docstrings and have properties return `None` if not
present.

* #20 Add Organizations Admin API Wrapper

Add a wrapper for the new Organizations API endpoints.

* #20 Add Licenses Admin API Wrapper

Add a wrapper for the new Licenses API endpoints.

* #20 Add Roles Admin API Wrapper

Add a wrapper for the new Roles API endpoints.

* #20 Add the new Admin API wrappers to CiscoSparkAPI

Add the new Organizations, Licenses and Roles API wrappers to the
CiscoSparkAPI class.

* Correct REST verb in memberships.update()

Verb should be PUT instead of POST
  • Loading branch information
cmlccie authored Mar 6, 2017
1 parent 7bfab09 commit 6b43188
Show file tree
Hide file tree
Showing 23 changed files with 1,088 additions and 14 deletions.
17 changes: 15 additions & 2 deletions ciscosparkapi/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,17 @@

from .exceptions import ciscosparkapiException, SparkApiError
from .restsession import RestSession
from .api.accesstokens import AccessToken, AccessTokensAPI
from .api.people import Person, PeopleAPI
from .api.rooms import Room, RoomsAPI
from .api.memberships import Membership, MembershipsAPI
from .api.messages import Message, MessagesAPI
from .api.teams import Team, TeamsAPI
from .api.teammemberships import TeamMembership, TeamMembershipsAPI
from .api.webhooks import Webhook, WebhooksAPI
from .api.organizations import Organization, OrganizationsAPI
from .api.licenses import License, LicensesAPI
from .api.roles import Role, RolesAPI
from .api.accesstokens import AccessToken, AccessTokensAPI


__author__ = "Chris Lunsford"
Expand All @@ -34,6 +37,7 @@

DEFAULT_BASE_URL = 'https://api.ciscospark.com/v1/'
DEFAULT_TIMEOUT = 60
ACCESS_TOKEN_ENVIRONMENT_VARIABLE = 'SPARK_ACCESS_TOKEN'


class CiscoSparkAPI(object):
Expand All @@ -60,6 +64,12 @@ class CiscoSparkAPI(object):
:class:`webhooks <WebhooksAPI>`
:class:`organizations <OrganizationsAPI>`
:class:`licenses <LicensesAPI>`
:class:`roles <RolesAPI>`
:class:`access_tokens <AccessTokensAPI>`
"""
Expand Down Expand Up @@ -104,7 +114,7 @@ def __init__(self, access_token=None, base_url=DEFAULT_BASE_URL,
assert access_token is None or isinstance(access_token, string_types)
assert isinstance(base_url, string_types)
assert isinstance(timeout, int)
spark_access_token = os.environ.get('SPARK_ACCESS_TOKEN', None)
spark_access_token = os.environ.get(ACCESS_TOKEN_ENVIRONMENT_VARIABLE)
access_token = access_token if access_token else spark_access_token
if not access_token:
error_message = "You must provide an Spark access token to " \
Expand All @@ -128,6 +138,9 @@ def __init__(self, access_token=None, base_url=DEFAULT_BASE_URL,
self.teams = TeamsAPI(self._session)
self.team_memberships = TeamMembershipsAPI(self._session)
self.webhooks = WebhooksAPI(self._session)
self.organizations = OrganizationsAPI(self._session)
self.licenses = LicensesAPI(self._session)
self.roles = RolesAPI(self._session)
self.access_tokens = AccessTokensAPI(self.base_url, timeout=timeout)

@property
Expand Down
151 changes: 151 additions & 0 deletions ciscosparkapi/api/licenses.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
# -*- coding: utf-8 -*-
"""Cisco Spark Licenses API wrapper.
Classes:
License: Models a Spark License JSON object as a native Python object.
LicensesAPI: Wraps the Cisco Spark Licenses API and exposes the
API calls as Python method calls that return native Python objects.
"""


from builtins import object
from six import string_types

from ciscosparkapi.utils import generator_container
from ciscosparkapi.restsession import RestSession
from ciscosparkapi.sparkdata import SparkData


__author__ = "Chris Lunsford"
__author_email__ = "[email protected]"
__copyright__ = "Copyright (c) 2016 Cisco Systems, Inc."
__license__ = "MIT"


class License(SparkData):
"""Model a Spark License JSON object as a native Python object."""

def __init__(self, json):
"""Init a new License data object from a dict or JSON string.
Args:
json(dict, string_types): Input JSON object.
Raises:
TypeError: If the input object is not a dictionary or string.
"""
super(License, self).__init__(json)

@property
def id(self):
"""The unique id for the License."""
return self._json.get('id')

@property
def name(self):
"""The name of the License."""
return self._json.get('name')

@property
def totalUnits(self):
"""The total number of license units."""
return self._json.get('totalUnits')

@property
def consumedUnits(self):
"""The total number of license units consumed."""
return self._json.get('consumedUnits')


class LicensesAPI(object):
"""Cisco Spark Licenses API wrapper.
Wraps the Cisco Spark Licenses API and exposes the API calls as Python
method calls that return native Python objects.
"""

def __init__(self, session):
"""Init a new LicensesAPI object with the provided RestSession.
Args:
session(RestSession): The RESTful session object to be used for
API calls to the Cisco Spark service.
Raises:
AssertionError: If the parameter types are incorrect.
"""
assert isinstance(session, RestSession)
super(LicensesAPI, self).__init__()
self._session = session

@generator_container
def list(self, orgId=None, max=None):
"""List Licenses.
Optionally filtered by Organization (orgId parameter).
This method supports Cisco Spark's implementation of RFC5988 Web
Linking to provide pagination support. It returns a generator
container that incrementally yields all objects returned by the
query. The generator will automatically request additional 'pages' of
responses from Spark as needed until all responses have been returned.
The container makes the generator safe for reuse. A new API call will
be made, using the same parameters that were specified when the
generator was created, every time a new iterator is requested from the
container.
Args:
orgId(string_types): Filters the returned licenses to only include
those liceses associated with the specified Organization
(orgId).
max(int): Limits the maximum number of entries returned from the
Spark service per request (page size; requesting additional
pages is handled automatically).
Returns:
GeneratorContainer: When iterated, the GeneratorContainer, yields
the objects returned from the Cisco Spark query.
Raises:
AssertionError: If the parameter types are incorrect.
SparkApiError: If the Cisco Spark cloud returns an error.
"""
# Process args
assert orgId is None or isinstance(orgId, string_types)
assert max is None or isinstance(max, int)
params = {}
if orgId:
params['orgId'] = orgId
if max:
params['max'] = max
# API request - get items
items = self._session.get_items('licenses', params=params)
# Yield License objects created from the returned JSON objects
for item in items:
yield License(item)

def get(self, licenseId):
"""Get the details of a License, by id.
Args:
licenseId(string_types): The id of the License.
Returns:
License: With the details of the requested License.
Raises:
AssertionError: If the parameter types are incorrect.
SparkApiError: If the Cisco Spark cloud returns an error.
"""
# Process args
assert isinstance(licenseId, string_types)
# API request
json_obj = self._session.get('licenses/' + licenseId)
# Return a License object created from the returned JSON object
return License(json_obj)
4 changes: 2 additions & 2 deletions ciscosparkapi/api/memberships.py
Original file line number Diff line number Diff line change
Expand Up @@ -260,8 +260,8 @@ def update(self, membershipId, **update_attributes):
"argument must be specified."
raise ciscosparkapiException(error_message)
# API request
json_obj = self._session.post('memberships/' + membershipId,
json=update_attributes)
json_obj = self._session.put('memberships/' + membershipId,
json=update_attributes)
# Return a Membership object created from the response JSON data
return Membership(json_obj)

Expand Down
139 changes: 139 additions & 0 deletions ciscosparkapi/api/organizations.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
# -*- coding: utf-8 -*-
"""Cisco Spark Organizations API wrapper.
Classes:
Organization: Models a Spark Organization JSON object as a native Python
object.
OrganizationsAPI: Wraps the Cisco Spark Organizations API and exposes the
API calls as Python method calls that return native Python objects.
"""


from builtins import object
from six import string_types

from ciscosparkapi.utils import generator_container
from ciscosparkapi.restsession import RestSession
from ciscosparkapi.sparkdata import SparkData


__author__ = "Chris Lunsford"
__author_email__ = "[email protected]"
__copyright__ = "Copyright (c) 2016 Cisco Systems, Inc."
__license__ = "MIT"


class Organization(SparkData):
"""Model a Spark Organization JSON object as a native Python object."""

def __init__(self, json):
"""Init a new Organization data object from a dict or JSON string.
Args:
json(dict, string_types): Input JSON object.
Raises:
TypeError: If the input object is not a dictionary or string.
"""
super(Organization, self).__init__(json)

@property
def id(self):
"""The unique id for the Organization."""
return self._json.get('id')

@property
def displayName(self):
"""The human-friendly display name of the Organization."""
return self._json.get('displayName')

@property
def created(self):
"""The date and time the Organization was created."""
return self._json.get('created')


class OrganizationsAPI(object):
"""Cisco Spark Organizations API wrapper.
Wraps the Cisco Spark Organizations API and exposes the API calls as Python
method calls that return native Python objects.
"""

def __init__(self, session):
"""Init a new OrganizationsAPI object with the provided RestSession.
Args:
session(RestSession): The RESTful session object to be used for
API calls to the Cisco Spark service.
Raises:
AssertionError: If the parameter types are incorrect.
"""
assert isinstance(session, RestSession)
super(OrganizationsAPI, self).__init__()
self._session = session

@generator_container
def list(self, max=None):
"""List Organizations.
This method supports Cisco Spark's implementation of RFC5988 Web
Linking to provide pagination support. It returns a generator
container that incrementally yields all objects returned by the
query. The generator will automatically request additional 'pages' of
responses from Spark as needed until all responses have been returned.
The container makes the generator safe for reuse. A new API call will
be made, using the same parameters that were specified when the
generator was created, every time a new iterator is requested from the
container.
Args:
max(int): Limits the maximum number of entries returned from the
Spark service per request (page size; requesting additional
pages is handled automatically).
Returns:
GeneratorContainer: When iterated, the GeneratorContainer, yields
the objects returned from the Cisco Spark query.
Raises:
AssertionError: If the parameter types are incorrect.
SparkApiError: If the Cisco Spark cloud returns an error.
"""
# Process args
assert max is None or isinstance(max, int)
params = {}
if max:
params['max'] = max
# API request - get items
items = self._session.get_items('organizations', params=params)
# Yield Organization objects created from the returned JSON objects
for item in items:
yield Organization(item)

def get(self, orgId):
"""Get the details of an Organization, by id.
Args:
orgId(string_types): The id of the Organization.
Returns:
Organization: With the details of the requested Organization.
Raises:
AssertionError: If the parameter types are incorrect.
SparkApiError: If the Cisco Spark cloud returns an error.
"""
# Process args
assert isinstance(orgId, string_types)
# API request
json_obj = self._session.get('organizations/' + orgId)
# Return a Organization object created from the returned JSON object
return Organization(json_obj)
Loading

0 comments on commit 6b43188

Please sign in to comment.