Skip to content

Commit 72ed68f

Browse files
authored
Initial Project Documentation (#27)
* Convert README to reStructuredText and Revise #15 Initial README.rst * Update README.rst #15 Correct formatting issues and simplify text. * Update README.rst #15 Add examples and documentation sections and misc edits. * Switch package to use new README.rst #15 Delete old README.md and point setup.py to new README.rst * README.rst Update Sub-Title * Update README.rst * Update README.rst * Update README * Initial Sphinx setup Create new ‘docs’ directory. Run sphinx-quickstart in ‘docs’ * Update .gitignore Begin organizing .gitignore to identify used and unused entries. * Add README.rst to MANIFEST.in * Initial User-API documentation Create initial index.rst and the the User-API documentation. * Add copyright references to docs * Rename helper.py to utils.py Rename and refactor helper.py to utils.py to make naming more consistent with established practices. * Make xxxAPI.session private; Update docstrings for auto-documentation The session attribute in an API object should not be ‘public’, and therefore should be prefixed by an ‘_’. Update API classes’ method docstrings to eliminate warnings and enable proper auto-documentation by Sphinx autodoc extension. * Change Versioneer version numbering style The ‘pep440-post’ style better reflects post-release commits, and enables building of installable dev-builds with sortable version numbers. Additionally, going forward, the package release tags will incorporate a release status flag (a - alpha, b - beta, rc - release candidate) in the format: major.minor[flag]micro * Document __init__.py Update docstrings and User API Doc for the main package __init__.py module. * Update copyright in docs/conf.py This copyright reference shows up in the footers of the HTML docs generated by Sphinx. * Docs - Update index.rst * Initial Quickstart The Quickstart guide / tutorial is now finished!!! * Fix Documentation Bug #22 Report and needed corrections provided by @DJF3 -Thank you! * Finalize the Docs for Initial Release
1 parent f1ef248 commit 72ed68f

25 files changed

+1897
-152
lines changed

.gitignore

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,15 @@
1+
# TODO: Remove all unused entries
2+
3+
# ciscosparkapi Project
4+
dist/
5+
docs/_build/
6+
*.egg-info/
7+
8+
19
# Unversioned files
210
basic-tests.py
311

12+
413
# Byte-compiled / optimized / DLL files
514
__pycache__/
615
*.py[cod]
@@ -14,7 +23,6 @@ __pycache__/
1423
env/
1524
build/
1625
develop-eggs/
17-
dist/
1826
downloads/
1927
eggs/
2028
.eggs/
@@ -23,7 +31,6 @@ lib64/
2331
parts/
2432
sdist/
2533
var/
26-
*.egg-info/
2734
.installed.cfg
2835
*.egg
2936

@@ -63,9 +70,6 @@ instance/
6370
# Scrapy stuff:
6471
.scrapy
6572

66-
# Sphinx documentation
67-
docs/_build/
68-
6973
# PyBuilder
7074
target/
7175

MANIFEST.in

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
include LICENSE.txt
2-
include README.md
2+
include README.rst
33
include versioneer.py
44
include ciscosparkapi/_version.py

README.rst

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,21 @@ Simple, lightweight, scalable Python API wrapper for the Cisco Spark APIs
88

99
.. image:: https://img.shields.io/pypi/v/ciscosparkapi.svg
1010
:target: https://pypi.python.org/pypi/ciscosparkapi
11+
.. image:: https://readthedocs.org/projects/ciscosparkapi/badge/?version=latest
12+
:target: http://ciscosparkapi.readthedocs.io/en/latest/?badge=latest
1113

12-
Sure, working with the Cisco Spark APIs is easy (see `developer.ciscospark.com`_). They are *RESTful*, *naturally structured*, require only a *simple Access Token for authentication*, and *the data is elegantly represented in intuitive JSON*. What could be easier?
14+
**Important update!**
15+
Complete user documentation is now available on
16+
`ciscosparkapi.readthedocs.io`_ !
17+
18+
Please use the issues_ page to report any issues or feedback regarding the
19+
documentation.
20+
21+
22+
Introduction
23+
------------
24+
25+
Sure, working with the Cisco Spark APIs is easy (see `developer.ciscospark.com`_). They are RESTful, naturally structured, require only a simple Access Token for authentication, and the data is elegantly represented in intuitive JSON. What could be easier?
1326

1427
.. code-block:: python
1528
@@ -28,14 +41,14 @@ Sure, working with the Cisco Spark APIs is easy (see `developer.ciscospark.com`_
2841
if response.status_code == 200:
2942
# Great your message was posted!
3043
message_id = response.json['id']
31-
message_text = response.json['id']
44+
message_text = response.json['text']
3245
print("New message created, with ID:", message_id)
3346
print(message_text)
3447
else:
3548
# Oops something went wrong... Better do something about it.
3649
print(response.status_code, response.text)
3750
38-
Like I said, *EASY*. However, in use, the code can be rather repetitive...
51+
Like I said, EASY. However, in use, the code can become rather repetitive...
3952

4053
- You have to setup the environment every time
4154
- You have to remember URLs and request arguments (or reference the docs)
@@ -93,7 +106,8 @@ All of this, combined, lets you do powerful things simply:
93106
api.memberships.create(demo_room.id, personEmail=email)
94107
95108
# Post a message to the new room, and upload a file
96-
api.message.create(demo_room.id, text="Welcome to the room!", files=["welcome.jpg"])
109+
api.messages.create(demo_room.id, text="Welcome to the room!",
110+
files=["https://developer.ciscospark.com/images/[email protected]"])
97111
98112
That's more than six Spark API calls in less than 23 lines of script code (with comments)!
99113
...and likely more than that depending on how many rooms are returned by Spark (remember pagination is handled for you automatically)
@@ -138,6 +152,10 @@ Have a good example script you would like to share? Please feel free to contrib
138152
Documentation
139153
-------------
140154

155+
**Complete user documentation is now available!**
156+
157+
Read the Docs at `ciscosparkapi.readthedocs.io`_ !!
158+
141159
All of the user-facing methods have complete docstrings. You can view the docstrings for any method either from the `source files`_, or by using the Python ``help()`` function.
142160

143161
.. code-block:: python
@@ -160,8 +178,6 @@ All of the user-facing methods have complete docstrings. You can view the docst
160178
private 1:1 message.
161179
...
162180
163-
Full standalone online documentation is coming soon (it's on the backlog!).
164-
165181
166182
Contribution
167183
------------
@@ -193,6 +209,7 @@ Interested in contributing code?
193209
.. _PyCharm: https://www.jetbrains.com/pycharm/
194210
.. _examples: https://github.com/CiscoDevNet/ciscosparkapi/tree/master/examples
195211
.. _source files: https://github.com/CiscoDevNet/ciscosparkapi/tree/master/ciscosparkapi
212+
.. _ciscosparkapi.readthedocs.io: https://ciscosparkapi.readthedocs.io
196213
.. _ciscosparkapi: https://github.com/CiscoDevNet/ciscosparkapi
197214
.. _ciscosparksdk: https://github.com/CiscoDevNet/ciscosparksdk
198215
.. _issues: https://github.com/CiscoDevNet/ciscosparkapi/issues

ciscosparkapi/__init__.py

Lines changed: 47 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,40 @@
3333

3434

3535
DEFAULT_BASE_URL = 'https://api.ciscospark.com/v1/'
36+
DEFAULT_TIMEOUT = 60
3637

3738

3839
class CiscoSparkAPI(object):
39-
"""Cisco Spark API wrapper class."""
40+
"""Cisco Spark API wrapper.
41+
42+
Creates a 'session' for all API calls through a created CiscoSparkAPI
43+
object. The 'session' handles authentication, provides the needed headers,
44+
and checks all responses for error conditions.
45+
46+
CiscoSparkAPI wraps all of the individual Cisco Spark APIs and represents
47+
them in a simple hierarchical structure.
48+
49+
:CiscoSparkAPI: :class:`people <PeopleAPI>`
50+
51+
:class:`rooms <RoomsAPI>`
52+
53+
:class:`memberships <MembershipsAPI>`
54+
55+
:class:`messages <MessagesAPI>`
56+
57+
:class:`teams <TeamsAPI>`
58+
59+
:class:`team_memberships <TeamMembershipsAPI>`
60+
61+
:class:`webhooks <WebhooksAPI>`
62+
63+
:class:`access_tokens <AccessTokensAPI>`
64+
65+
"""
4066

4167
def __init__(self, access_token=None, base_url=DEFAULT_BASE_URL,
42-
timeout=60):
43-
"""Init a new CiscoSparkAPI object.
68+
timeout=DEFAULT_TIMEOUT):
69+
"""Create a new CiscoSparkAPI object.
4470
4571
An access token must be used when interacting with the Cisco Spark API.
4672
This package supports two methods for you to provide that access token:
@@ -49,9 +75,7 @@ def __init__(self, access_token=None, base_url=DEFAULT_BASE_URL,
4975
argument, when creating a new CiscoSparkAPI object.
5076
5177
2. If an access_token argument is not supplied, the package checks
52-
for a SPARK_ACCESS_TOKEN environment variable, and if available,
53-
it uses the value of this environment variable as the access_token
54-
when new CiscoSparkAPI objects are created.
78+
for a SPARK_ACCESS_TOKEN environment variable.
5579
5680
A ciscosparkapiException is raised if an access token is not provided
5781
via one of these two methods.
@@ -64,10 +88,10 @@ def __init__(self, access_token=None, base_url=DEFAULT_BASE_URL,
6488
individual API endpoint suffixes.
6589
Defaults to ciscosparkapi.DEFAULT_BASE_URL.
6690
timeout(int): Timeout (in seconds) for RESTful HTTP requests.
67-
Defaults to 60 seconds.
91+
Defaults to ciscosparkapi.DEFAULT_TIMEOUT.
6892
6993
Returns:
70-
CiscoSparkAPI: A new CiscoSparkAPI connection object.
94+
CiscoSparkAPI: A new CiscoSparkAPI object.
7195
7296
Raises:
7397
AssertionError: If the parameter types are incorrect.
@@ -83,38 +107,37 @@ def __init__(self, access_token=None, base_url=DEFAULT_BASE_URL,
83107
spark_access_token = os.environ.get('SPARK_ACCESS_TOKEN', None)
84108
access_token = access_token if access_token else spark_access_token
85109
if not access_token:
86-
error_message = "You must provide an access token to interact " \
87-
"with the Cisco Spark APIs, either via the " \
88-
"access_token argument or via a " \
89-
"SPARK_ACCESS_TOKEN environment variable. " \
90-
"None provided."
110+
error_message = "You must provide an Spark access token to " \
111+
"interact with the Cisco Spark APIs, either via " \
112+
"a SPARK_ACCESS_TOKEN environment variable " \
113+
"or via the access_token argument."
91114
raise ciscosparkapiException(error_message)
92115
session_args = {u'timeout': timeout}
93116

94117
# Create the API session
95118
# All of the API calls associated with a CiscoSparkAPI object will
96119
# leverage a single RESTful 'session' connecting to the Cisco Spark
97120
# cloud.
98-
self.session = RestSession(access_token, base_url, **session_args)
121+
self._session = RestSession(access_token, base_url, **session_args)
99122

100123
# Spark API wrappers
124+
self.people = PeopleAPI(self._session)
125+
self.rooms = RoomsAPI(self._session)
126+
self.memberships = MembershipsAPI(self._session)
127+
self.messages = MessagesAPI(self._session)
128+
self.teams = TeamsAPI(self._session)
129+
self.team_memberships = TeamMembershipsAPI(self._session)
130+
self.webhooks = WebhooksAPI(self._session)
101131
self.access_tokens = AccessTokensAPI(self.base_url, timeout=timeout)
102-
self.people = PeopleAPI(self.session)
103-
self.rooms = RoomsAPI(self.session)
104-
self.memberships = MembershipsAPI(self.session)
105-
self.messages = MessagesAPI(self.session)
106-
self.teams = TeamsAPI(self.session)
107-
self.team_memberships = TeamMembershipsAPI(self.session)
108-
self.webhooks = WebhooksAPI(self.session)
109132

110133
@property
111134
def access_token(self):
112-
return self.session.access_token
135+
return self._session.access_token
113136

114137
@property
115138
def base_url(self):
116-
return self.session.base_url
139+
return self._session.base_url
117140

118141
@property
119142
def timeout(self):
120-
return self.session.timeout
143+
return self._session.timeout

ciscosparkapi/api/accesstokens.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919

2020
import requests
2121

22-
from ciscosparkapi.helper import ERC, validate_base_url, \
22+
from ciscosparkapi.utils import ERC, validate_base_url, \
2323
check_response_code, extract_and_parse_json
2424
from ciscosparkapi.sparkdata import SparkData
2525

ciscosparkapi/api/memberships.py

Lines changed: 11 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
from six import string_types
1515

1616
from ciscosparkapi.exceptions import ciscosparkapiException
17-
from ciscosparkapi.helper import generator_container
17+
from ciscosparkapi.utils import generator_container
1818
from ciscosparkapi.restsession import RestSession
1919
from ciscosparkapi.sparkdata import SparkData
2020

@@ -79,10 +79,6 @@ class MembershipsAPI(object):
7979
Wrappers the Cisco Spark Memberships-API and exposes the API calls as
8080
Python method calls that return native Python objects.
8181
82-
Attributes:
83-
session(RestSession): The RESTful session object to be used for API
84-
calls to the Cisco Spark service.
85-
8682
"""
8783

8884
def __init__(self, session):
@@ -98,7 +94,7 @@ def __init__(self, session):
9894
"""
9995
assert isinstance(session, RestSession)
10096
super(MembershipsAPI, self).__init__()
101-
self.session = session
97+
self._session = session
10298

10399
@generator_container
104100
def list(self, roomId=None, personId=None, personEmail=None, max=None):
@@ -133,8 +129,9 @@ def list(self, roomId=None, personId=None, personEmail=None, max=None):
133129
the Spark service per request.
134130
135131
136-
Yields:
137-
Membership: The the next membership from the Cisco Spark query.
132+
Returns:
133+
GeneratorContainer: When iterated, the GeneratorContainer, yields
134+
the memberships returned from the Cisco Spark query.
138135
139136
Raises:
140137
AssertionError: If the parameter types are incorrect.
@@ -164,7 +161,7 @@ def list(self, roomId=None, personId=None, personEmail=None, max=None):
164161
if max:
165162
params['max'] = max
166163
# API request - get items
167-
items = self.session.get_items('memberships', params=params)
164+
items = self._session.get_items('memberships', params=params)
168165
# Yield Person objects created from the returned items JSON objects
169166
for item in items:
170167
yield Membership(item)
@@ -212,7 +209,7 @@ def create(self, roomId, personId=None, personEmail=None,
212209
raise ciscosparkapiException(error_message)
213210
post_data['isModerator'] = isModerator
214211
# API request
215-
json_obj = self.session.post('memberships', json=post_data)
212+
json_obj = self._session.post('memberships', json=post_data)
216213
# Return a Membership object created from the response JSON data
217214
return Membership(json_obj)
218215

@@ -233,7 +230,7 @@ def get(self, membershipId):
233230
# Process args
234231
assert isinstance(membershipId, string_types)
235232
# API request
236-
json_obj = self.session.get('memberships/'+membershipId)
233+
json_obj = self._session.get('memberships/' + membershipId)
237234
# Return a Membership object created from the response JSON data
238235
return Membership(json_obj)
239236

@@ -243,8 +240,6 @@ def update(self, membershipId, **update_attributes):
243240
Args:
244241
membershipId(string_types): The membershipId of the membership to
245242
be updated.
246-
247-
**update_attributes:
248243
isModerator(bool): If True, sets the person as a moderator for the
249244
room. If False, removes the person as a moderator for the room.
250245
@@ -265,8 +260,8 @@ def update(self, membershipId, **update_attributes):
265260
"argument must be specified."
266261
raise ciscosparkapiException(error_message)
267262
# API request
268-
json_obj = self.session.post('memberships/'+membershipId,
269-
json=update_attributes)
263+
json_obj = self._session.post('memberships/' + membershipId,
264+
json=update_attributes)
270265
# Return a Membership object created from the response JSON data
271266
return Membership(json_obj)
272267

@@ -285,4 +280,4 @@ def delete(self, membershipId):
285280
# Process args
286281
assert isinstance(membershipId, string_types)
287282
# API request
288-
self.session.delete('memberships/'+membershipId)
283+
self._session.delete('memberships/' + membershipId)

0 commit comments

Comments
 (0)