Skip to content

Commit 393ff34

Browse files
committed
Add a container class and function descriptor to wrap generator functions
Create a generator container and descriptor function to wrap the generator functions in the API package. Containerizing the generator functions makes the generators safe for reuse. A fresh iterator is returned every time a new iterator is requested from the container.
1 parent a0f1d69 commit 393ff34

File tree

2 files changed

+97
-7
lines changed

2 files changed

+97
-7
lines changed

ciscosparkapi/api/rooms.py

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010

1111
from ciscosparkapi.exceptions import ciscosparkapiException
12-
from ciscosparkapi.helperfunc import utf8
12+
from ciscosparkapi.helper import utf8, generator_container
1313
from ciscosparkapi.restsession import RestSession
1414
from ciscosparkapi.sparkdata import SparkData
1515

@@ -92,16 +92,20 @@ def __init__(self, session):
9292
super(RoomsAPI, self).__init__()
9393
self.session = session
9494

95+
@generator_container
9596
def list(self, max=None, **query_params):
9697
"""List rooms.
9798
9899
By default, lists rooms to which the authenticated user belongs.
99100
100101
This method supports Cisco Spark's implmentation of RFC5988 Web Linking
101-
to provide pagination support. It returns an iterator that
102-
incrementally yield all rooms returned by the query. It will
103-
automatically request additional 'pages' of responses from Spark as
104-
needed until all responses have been returned.
102+
to provide pagination support. It returns a generator container that
103+
incrementally yield all rooms returned by the query. The generator
104+
will automatically request additional 'pages' of responses from Spark
105+
as needed until all responses have been returned. The container makes
106+
the generator safe for reuse. A new API call will be made, using the
107+
same parameters that were specified when the generator was created,
108+
every time a new iterator is requested from the container.
105109
106110
Args:
107111
max(int): Limits the maximum number of rooms returned from the

ciscosparkapi/helper.py

Lines changed: 88 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,96 @@
1-
"""Package helper functions."""
1+
"""Package helper functions and classes.
2+
3+
Functions:
4+
utf8: Returns the input string as a UTF-8 unicode encoded string.
5+
generator_container: Function decorator that containerizes calls to
6+
generator functions.
7+
8+
Classes:
9+
GeneratorContainer: Container for storing a function call to a generator
10+
function.
11+
12+
"""
13+
14+
15+
import functools
216

317

418
def utf8(string):
5-
"""Return the 'string' as a UTF-8 unicode encoded string."""
19+
"""Return the 'string' as a UTF-8 unicode encoded string.
20+
21+
Ensure that 'string' is a unicode encoded string; converting if necessary.
22+
23+
Args:
24+
string(unicode, str): The input string.
25+
26+
Returns:
27+
unicode: The input string encoded as a unicode string.
28+
29+
Raises:
30+
AssertionError: If the parameter types are incorrect.
31+
32+
"""
633
assert isinstance(string, basestring)
734
if isinstance(string, unicode):
835
return string
936
elif isinstance(string, str):
1037
return unicode(string, encoding='utf-8')
38+
39+
40+
class GeneratorContainer(object):
41+
"""Container for storing a function call to a generator function.
42+
43+
Return a fresh iterator every time __iter__() is called on the container
44+
object.
45+
46+
Attributes:
47+
generator(func): The generator function.
48+
args(list): The arguments passed to the generator function.
49+
kwargs(dict): The keyword arguments passed to the generator function.
50+
51+
"""
52+
53+
def __init__(self, generator, *args, **kwargs):
54+
"""Inits a new GeneratorContainer.
55+
56+
Args:
57+
generator(func): The generator function.
58+
*args: The arguments passed to the generator function.
59+
**kwargs: The keyword arguments passed to the generator function.
60+
61+
"""
62+
self.generator = generator
63+
self.args = args
64+
self.kwargs = kwargs
65+
66+
def __iter__(self):
67+
"""Return a fresh iterator."""
68+
return self.generator(*self.args, **self.kwargs)
69+
70+
71+
def generator_container(generator):
72+
"""Function Decorator: Containerize calls to a generator function.
73+
74+
Args:
75+
generator(func): The generator function being containerized.
76+
77+
Returns:
78+
func: A wrapper function that containerizes the calls to the generator.
79+
80+
"""
81+
82+
@functools.wraps(generator)
83+
def generator_container_wrapper(*args, **kwargs):
84+
"""Store a generator call in a container and return the container.
85+
86+
Args:
87+
*args: The arguments passed to the generator function.
88+
**kwargs: The keyword arguments passed to the generator function.
89+
90+
Returns:
91+
GeneratorContainer: A container wrapping the call to the generator.
92+
93+
"""
94+
return GeneratorContainer(generator, *args, **kwargs)
95+
96+
return generator_container_wrapper

0 commit comments

Comments
 (0)