Skip to content

Commit 256f538

Browse files
committed
Merge branch 'python-2-3' into development
2 parents 926847f + b51ef5b commit 256f538

19 files changed

+550
-524
lines changed

README.md

Lines changed: 39 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,28 +2,46 @@
22
Simple, lightweight and scalable Python API wrapper for the Cisco Spark APIs
33

44
## Overview
5-
A single Pythonic wrapper class representing the Cisco Spark API interfaces and returned JSON objects as method calls that return native Python objects.
5+
Provides single Pythonic wrapper class that represents the Cisco Spark API interfaces and returned JSON objects as native Python objects.
66

7+
* Supports Python versions 2 and 3.
8+
79
* Leverages generator containers and RFC5988 web linking to provide simple and efficient 'paging' of Cisco Spark data objects returned by the Cisco Spark clout.
810

911
* All Cisco Spark JSON objects and attributes are represented as native python objects.
1012
* As new Cisco Spark attributes are added and returned by the Spark cloud service, they will be automatically available in the respective Python objects - no library update required.
1113
* New object types can be quickly created and modeled by via the generic SparkData class, or you can easily subclass SparkData to provide additional functionality.
1214

13-
* The CiscoSparkAPI class facilitates the creation of simple 'connection objects' that are associated with the access_token used to create the object. All API calls are wrapped by this single class, and are available via a simple hierarchical structure - like api.rooms.list().
14-
* API defaults are provided to make getting connected simple, and can be easily overridden if needed.
15-
* The only setting required to get connected is your Cisco Spark Access Token (see [developer.ciscospark.com](https://developer.ciscospark.com/getting-started.html)).
15+
* The CiscoSparkAPI class facilitates the creation of simple 'connection objects.' All API calls are wrapped by this single class, and are available via a simple hierarchical structure - like CiscoSparkAPI.rooms.list().
16+
* Argument defaults are provided to make getting connected simple, and can be easily overridden if needed.
17+
* The only setting required to get connected is your Cisco Spark Access Token (see [developer.ciscospark.com](https://developer.ciscospark.com/getting-started.html)). When creating a new CiscoSparkAPI object, you may provide your access token one of two ways:
18+
1. By setting a SPARK_ACCESS_TOKEN environment variable.
19+
2. Via the ```CiscoSparkAPI(access_token="")``` argument.
1620
* All API calls are provided as simple method calls on the API connection objects.
1721

18-
### Examples
22+
23+
## Installation
24+
ciscosparkapi is available on PyPI. Install it via PIP, or alternatively you can download the package from GitHub and install it via setuptools.
25+
26+
**PIP Installation**
27+
```
28+
$ pip install ciscosparkapi
29+
```
30+
31+
**git / setuptools Installation**
32+
```
33+
$ git clone https://github.com/CiscoDevNet/ciscosparkapi.git
34+
$ python setup.py install
35+
```
36+
37+
## Examples
1938

2039
```python
21-
import os
2240
from ciscosparkapi import CiscoSparkAPI
2341

2442

25-
access_token = os.environ['SPARK_ACCESS_TOKEN']
26-
api = CiscoSparkAPI(access_token, timeout=60)
43+
# By default retrieves your access token from the SPARK_ACCESS_TOKEN environement variable
44+
api = CiscoSparkAPI()
2745

2846

2947
rooms = api.rooms.list() # Returns an generator container providing support for RFC5988 paging
@@ -32,22 +50,24 @@ for room in rooms: # Efficiently iterates through returned objects
3250

3351

3452
# Creating a list from the returned generator containers is easy
35-
team_list = list(api.teams.list())
36-
print team_list
53+
teams = api.teams.list()
54+
team_list = list(teams)
55+
print teams_list
3756
```
3857

3958

40-
## Community Development Project Information
41-
This is a collaborative community development project to create two packages to be published to the Python Package Index:
59+
## Current Status
60+
**Beta(s) Released!**
4261

43-
1. [**ciscosparkapi**](https://github.com/CiscoDevNet/ciscosparkapi) - A simple, scalable and lightweight API wrapper for the Cisco Spark services APIs
44-
2. [**ciscosparksdk**](https://github.com/CiscoDevNet/ciscosparksdk) - Additional features and functionality useful to Cisco Spark API developers
62+
Please check the [releases page](https://github.com/CiscoDevNet/ciscosparkapi/releases) for details on the latest releases.
4563

46-
All are welcome to contribute to this project. Information on contributing this project can be found [here in the project Charter](https://github.com/CiscoDevNet/spark-python-packages-team/blob/master/Charter.md).
64+
We have released the first beta distributions for this package! Please test out the package for your use cases, and raise [issues](https://github.com/CiscoDevNet/ciscosparkapi/issues) for any problems you encounter. Also, **PLEASE** create new [issues](https://github.com/CiscoDevNet/ciscosparkapi/issues) to provide any feedback on the package API structure (names, method calls and etc.). The package APIs are still subject to change, and we would like to get these nailed down before we release v1 for the package.
4765

48-
## Current Status
49-
**Wrappers for all Cisco API endpoints and data objects have now been completed!**
5066

67+
## Community Development Project Information
68+
This is a collaborative community development project working to create two packages to be published to the Python Package Index:
69+
70+
1. [**ciscosparkapi**](https://github.com/CiscoDevNet/ciscosparkapi) - Simple, lightweight and scalable Python API wrapper for the Cisco Spark APIs
71+
2. [**ciscosparksdk**](https://github.com/CiscoDevNet/ciscosparksdk) - Additional features and functionality useful to developers building on Cisco Spark API
5172

52-
_Beta release imminent._
53-
We are preparing to release the first _beta_ for this package. Please test out the package for your use cases, and raise issues for any problems you encounter. Also, **PLEASE** create new issues to provide feedback and foster discussion on the package API structure (names, method calls and etc.). The package APIs are still subject to change, and I would like to get these nailed down before we release v1 for the package.
73+
Contributions and feedback are welcome. Information on contributing this project can be found [here in the project Charter](https://github.com/CiscoDevNet/spark-python-packages-team/blob/master/Charter.md).

ciscosparkapi/__init__.py

Lines changed: 25 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,31 @@
1+
# -*- coding: utf-8 -*-
12
"""Python API wrapper for the Cisco Spark APIs."""
23

34

5+
from __future__ import absolute_import
6+
from builtins import object
7+
from six import string_types
8+
9+
import os
10+
11+
from .exceptions import ciscosparkapiException, SparkApiError
12+
from .restsession import RestSession
13+
from .api.accesstokens import AccessToken, AccessTokensAPI
14+
from .api.people import Person, PeopleAPI
15+
from .api.rooms import Room, RoomsAPI
16+
from .api.memberships import Membership, MembershipsAPI
17+
from .api.messages import Message, MessagesAPI
18+
from .api.teams import Team, TeamsAPI
19+
from .api.teammemberships import TeamMembership, TeamMembershipsAPI
20+
from .api.webhooks import Webhook, WebhooksAPI
21+
22+
423
# Versioneer version control
524
from ._version import get_versions
625
__version__ = get_versions()['version']
726
del get_versions
827

928

10-
import os
11-
12-
from exceptions import ciscosparkapiException, SparkApiError
13-
from restsession import RestSession
14-
from api.accesstokens import AccessToken, AccessTokensAPI
15-
from api.people import Person, PeopleAPI
16-
from api.rooms import Room, RoomsAPI
17-
from api.memberships import Membership, MembershipsAPI
18-
from api.messages import Message, MessagesAPI
19-
from api.teams import Team, TeamsAPI
20-
from api.teammemberships import TeamMembership, TeamMembershipsAPI
21-
from api.webhooks import Webhook, WebhooksAPI
22-
23-
2429
DEFAULT_BASE_URL = 'https://api.ciscospark.com/v1/'
2530

2631

@@ -46,10 +51,10 @@ def __init__(self, access_token=None, base_url=DEFAULT_BASE_URL,
4651
via one of these two methods.
4752
4853
Args:
49-
access_token(unicode, str): The access token to be used for API
54+
access_token(string_types): The access token to be used for API
5055
calls to the Cisco Spark service. Defaults to checking for a
5156
SPARK_ACCESS_TOKEN environment variable.
52-
base_url(unicode, str): The base URL to be prefixed to the
57+
base_url(string_types): The base URL to be prefixed to the
5358
individual API endpoint suffixes.
5459
Defaults to ciscosparkapi.DEFAULT_BASE_URL.
5560
timeout(int): Timeout (in seconds) for RESTful HTTP requests.
@@ -61,21 +66,21 @@ def __init__(self, access_token=None, base_url=DEFAULT_BASE_URL,
6166
Raises:
6267
AssertionError: If the parameter types are incorrect.
6368
ciscosparkapiException: If an access token is not provided via the
64-
access_token argument or SPARK_ACCESS_TOKEN environement
69+
access_token argument or SPARK_ACCESS_TOKEN environment
6570
variable.
6671
6772
"""
6873
# Process args
69-
assert access_token is None or isinstance(access_token, basestring)
70-
assert isinstance(base_url, basestring)
74+
assert access_token is None or isinstance(access_token, string_types)
75+
assert isinstance(base_url, string_types)
7176
assert isinstance(timeout, int)
7277
spark_access_token = os.environ.get('SPARK_ACCESS_TOKEN', None)
7378
access_token = access_token if access_token else spark_access_token
7479
if not access_token:
7580
error_message = "You must provide an access token to interact " \
7681
"with the Cisco Spark APIs, either via the " \
7782
"access_token argument or via a " \
78-
"SPARK_ACCESS_TOKEN environement variable. " \
83+
"SPARK_ACCESS_TOKEN environment variable. " \
7984
"None provided."
8085
raise ciscosparkapiException(error_message)
8186
session_args = {u'timeout': timeout}

ciscosparkapi/_version.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
# -*- coding: utf-8 -*-
12

23
# This file helps to compute a version number in source trees obtained from
34
# git-archive tarball (such as those provided by githubs download-from-tag
@@ -9,6 +10,9 @@
910
# versioneer-0.16 (https://github.com/warner/python-versioneer)
1011

1112
"""Git implementation of _version.py."""
13+
from __future__ import print_function
14+
from builtins import str
15+
from builtins import object
1216

1317
import errno
1418
import os
@@ -29,7 +33,7 @@ def get_keywords():
2933
return keywords
3034

3135

32-
class VersioneerConfig:
36+
class VersioneerConfig(object):
3337
"""Container for Versioneer configuration parameters."""
3438

3539

ciscosparkapi/api/accesstokens.py

Lines changed: 42 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
# -*- coding: utf-8 -*-
12
"""Cisco Spark Access-Tokens-API wrapper classes.
23
34
Classes:
@@ -9,16 +10,21 @@
910
"""
1011

1112

12-
import urlparse
13+
from future import standard_library
14+
standard_library.install_aliases()
15+
from builtins import object
16+
from six import string_types
17+
18+
import urllib.parse
1319

1420
import requests
1521

16-
from ciscosparkapi.helper import utf8, ERC, validate_base_url, \
22+
from ciscosparkapi.helper import ERC, validate_base_url, \
1723
check_response_code, extract_and_parse_json
1824
from ciscosparkapi.sparkdata import SparkData
1925

2026

21-
API_ENDPOINT = u"access_token"
27+
API_ENDPOINT = "access_token"
2228

2329

2430
class AccessToken(SparkData):
@@ -28,7 +34,7 @@ def __init__(self, json):
2834
"""Init a new AccessToken data object from a JSON dictionary or string.
2935
3036
Args:
31-
json(dict, unicode, str): Input JSON object.
37+
json(dict, string_types): Input JSON object.
3238
3339
Raises:
3440
TypeError: If the input object is not a dictionary or string.
@@ -39,22 +45,22 @@ def __init__(self, json):
3945
@property
4046
def access_token(self):
4147
"""Cisco Spark access_token."""
42-
return self._json.get(u'access_token')
48+
return self._json.get('access_token')
4349

4450
@property
4551
def expires_in(self):
4652
"""Access token expires_in number of seconds."""
47-
return self._json.get(u'expires_in')
53+
return self._json.get('expires_in')
4854

4955
@property
5056
def refresh_token(self):
5157
"""refresh_token used to request a new/refreshed access_token."""
52-
return self._json.get(u'refresh_token')
58+
return self._json.get('refresh_token')
5359

5460
@property
5561
def refresh_token_expires_in(self):
5662
"""refresh_token_expires_in number of seconds."""
57-
return self._json.get(u'refresh_token_expires_in')
63+
return self._json.get('refresh_token_expires_in')
5864

5965

6066
class AccessTokensAPI(object):
@@ -69,21 +75,21 @@ def __init__(self, base_url, timeout=None):
6975
"""Init a new AccessTokensAPI object with the provided RestSession.
7076
7177
Args:
72-
base_url(unicode, str): The base URL the API endpoints.
78+
base_url(string_types): The base URL the API endpoints.
7379
timeout(int): Timeout in seconds for the API requests.
7480
7581
Raises:
7682
AssertionError: If the parameter types are incorrect.
7783
7884
"""
79-
assert isinstance(base_url, basestring)
85+
assert isinstance(base_url, string_types)
8086
assert timeout is None or isinstance(timeout, int)
8187
super(AccessTokensAPI, self).__init__()
82-
self._base_url = validate_base_url(base_url)
88+
self._base_url = str(validate_base_url(base_url))
8389
self._timeout = timeout
84-
self._endpoint_url = urlparse.urljoin(self.base_url, API_ENDPOINT)
90+
self._endpoint_url = urllib.parse.urljoin(self.base_url, API_ENDPOINT)
8591
self._request_kwargs = {}
86-
self._request_kwargs[u"timeout"] = timeout
92+
self._request_kwargs["timeout"] = timeout
8793

8894
@property
8995
def base_url(self):
@@ -100,13 +106,13 @@ def get(self, client_id, client_secret, code, redirect_uri):
100106
invoke the APIs.
101107
102108
Args:
103-
client_id(unicode, str): Provided when you created your
109+
client_id(string_types): Provided when you created your
104110
integration.
105-
client_secret(unicode, str): Provided when you created your
111+
client_secret(string_types): Provided when you created your
106112
integration.
107-
code(unicode, str): The Authorization Code provided by the user
113+
code(string_types): The Authorization Code provided by the user
108114
OAuth process.
109-
redirect_uri(unicode, str): The redirect URI used in the user OAuth
115+
redirect_uri(string_types): The redirect URI used in the user OAuth
110116
process.
111117
112118
Returns:
@@ -119,17 +125,17 @@ def get(self, client_id, client_secret, code, redirect_uri):
119125
120126
"""
121127
# Process args
122-
assert isinstance(client_id, basestring)
123-
assert isinstance(client_secret, basestring)
124-
assert isinstance(code, basestring)
125-
assert isinstance(redirect_uri, basestring)
128+
assert isinstance(client_id, string_types)
129+
assert isinstance(client_secret, string_types)
130+
assert isinstance(code, string_types)
131+
assert isinstance(redirect_uri, string_types)
126132
# Build request parameters
127133
data = {}
128-
data[u"grant_type"] = u"authorization_code"
129-
data[u"client_id"] = utf8(client_id)
130-
data[u"client_secret"] = utf8(client_secret)
131-
data[u"code"] = utf8(code)
132-
data[u"redirect_uri"] = utf8(redirect_uri)
134+
data["grant_type"] = "authorization_code"
135+
data["client_id"] = client_id
136+
data["client_secret"] = client_secret
137+
data["code"] = code
138+
data["redirect_uri"] = redirect_uri
133139
# API request
134140
response = requests.post(self._endpoint_url, data=data,
135141
**self._request_kwargs)
@@ -142,11 +148,11 @@ def refresh(self, client_id, client_secret, refresh_token):
142148
"""Return a refreshed Access Token via the provided refresh_token.
143149
144150
Args:
145-
client_id(unicode, str): Provided when you created your
151+
client_id(string_types): Provided when you created your
146152
integration.
147-
client_secret(unicode, str): Provided when you created your
153+
client_secret(string_types): Provided when you created your
148154
integration.
149-
refresh_token(unicode, str): Provided when you requested the Access
155+
refresh_token(string_types): Provided when you requested the Access
150156
Token.
151157
152158
Returns:
@@ -159,15 +165,15 @@ def refresh(self, client_id, client_secret, refresh_token):
159165
160166
"""
161167
# Process args
162-
assert isinstance(client_id, basestring)
163-
assert isinstance(client_secret, basestring)
164-
assert isinstance(refresh_token, basestring)
168+
assert isinstance(client_id, string_types)
169+
assert isinstance(client_secret, string_types)
170+
assert isinstance(refresh_token, string_types)
165171
# Build request parameters
166172
data = {}
167-
data[u"grant_type"] = u"refresh_token"
168-
data[u"client_id"] = utf8(client_id)
169-
data[u"client_secret"] = utf8(client_secret)
170-
data[u"refresh_token"] = utf8(refresh_token)
173+
data["grant_type"] = "refresh_token"
174+
data["client_id"] = client_id
175+
data["client_secret"] = client_secret
176+
data["refresh_token"] = refresh_token
171177
# API request
172178
response = requests.post(self._endpoint_url, data=data,
173179
**self._request_kwargs)

0 commit comments

Comments
 (0)