Skip to content

Commit 86ddb6a

Browse files
committed
Add flexible models and factory functions
Add examples for flexible data models: * `simple_data_factory` (`SimpleDataModel`) - A simple data model that assigns all of the top-level JSON attributes to Python object attributes. * `dict_data_factory` - An object factory that returns the Spark data objects as parsed ordered dictionaries.
1 parent 0b314df commit 86ddb6a

File tree

5 files changed

+134
-33
lines changed

5 files changed

+134
-33
lines changed

ciscosparkapi/__init__.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@
3333
)
3434
from .models import (
3535
AccessToken, Event, License, Membership, Message, Organization, Person,
36-
Role, Room, Team, TeamMembership, Webhook, WebhookEvent, sparkdata_factory,
36+
Role, Room, Team, TeamMembership, Webhook, WebhookEvent, dict_data_factory,
37+
simple_data_factory, spark_data_factory,
3738
)
3839
from .restsession import (
3940
DEFAULT_SINGLE_REQUEST_TIMEOUT,
@@ -106,7 +107,7 @@ def __init__(self, access_token=None, base_url=DEFAULT_BASE_URL,
106107
timeout=None,
107108
single_request_timeout=DEFAULT_SINGLE_REQUEST_TIMEOUT,
108109
wait_on_rate_limit=DEFAULT_WAIT_ON_RATE_LIMIT,
109-
object_factory=sparkdata_factory):
110+
object_factory=spark_data_factory):
110111
"""Create a new CiscoSparkAPI object.
111112
112113
An access token must be used when interacting with the Cisco Spark API.

ciscosparkapi/models/__init__.py

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,13 @@
2020
from .person import PersonBasicPropertiesMixin
2121
from .role import RoleBasicPropertiesMixin
2222
from .room import RoomBasicPropertiesMixin
23+
from .simple import SimpleDataModel
2324
from .sparkdata import SparkData
2425
from .team import TeamBasicPropertiesMixin
2526
from .team_membership import TeamMembershipBasicPropertiesMixin
2627
from .webhook import WebhookBasicPropertiesMixin
2728
from .webhook_event import WebhookEventBasicPropertiesMixin
29+
from ..utils import json_dict
2830

2931

3032
__author__ = "Chris Lunsford"
@@ -85,7 +87,7 @@ class WebhookEvent(SparkData, WebhookEventBasicPropertiesMixin):
8587
"""Cisco Spark Webhook-Events data model."""
8688

8789

88-
sparkdata_models = defaultdict(
90+
spark_data_models = defaultdict(
8991
lambda: SparkData,
9092
access_token=AccessToken,
9193
event=Event,
@@ -103,7 +105,7 @@ class WebhookEvent(SparkData, WebhookEventBasicPropertiesMixin):
103105
)
104106

105107

106-
def sparkdata_factory(model, json_data):
108+
def spark_data_factory(model, json_data):
107109
"""Factory function for creating SparkData objects.
108110
109111
Args:
@@ -120,4 +122,45 @@ def sparkdata_factory(model, json_data):
120122
dictionary.
121123
122124
"""
123-
return sparkdata_models[model](json_data)
125+
return spark_data_models[model](json_data)
126+
127+
128+
def simple_data_factory(model, json_data):
129+
"""Factory function for creating SimpleDataModel objects.
130+
131+
Args:
132+
model(basestring): The data model to use when creating the SparkData
133+
object (message, room, membership, etc.).
134+
json_data(basestring, dict): The JSON string or dictionary data with
135+
which to initialize the object.
136+
137+
Returns:
138+
SimpleDataModel: The created SimpleDataModel object.
139+
140+
Raises:
141+
TypeError: If the json_data parameter is not a JSON string or
142+
dictionary.
143+
144+
"""
145+
return SimpleDataModel(json_data)
146+
147+
148+
def dict_data_factory(model, json_data):
149+
"""Factory function for creating SimpleDataModel objects.
150+
151+
Args:
152+
model(basestring): The data model to use when creating the SparkData
153+
object (message, room, membership, etc.).
154+
json_data(basestring, dict): The JSON string or dictionary data with
155+
which to initialize the object.
156+
157+
Returns:
158+
OrderedDict: An ordered dictionary with the contents of the Spark JSON
159+
object.
160+
161+
Raises:
162+
TypeError: If the json_data parameter is not a JSON string or
163+
dictionary.
164+
165+
"""
166+
return json_dict(json_data)

ciscosparkapi/models/simple.py

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
# -*- coding: utf-8 -*-
2+
"""Simple data model; models Spark JSON objects as simple Python objects.
3+
4+
Classes:
5+
SimpleDataModel: Models Spark JSON objects as simple Python objects.
6+
7+
The SimpleDataModel class models any JSON object passed to it as a string or
8+
Python dictionary as a native Python object; providing attribute access using
9+
native dot-syntax.
10+
11+
"""
12+
13+
14+
from __future__ import (
15+
absolute_import,
16+
division,
17+
print_function,
18+
unicode_literals,
19+
)
20+
21+
from builtins import *
22+
import json
23+
24+
from ..utils import json_dict
25+
26+
27+
__author__ = "Chris Lunsford"
28+
__author_email__ = "[email protected]"
29+
__copyright__ = "Copyright (c) 2016-2018 Cisco and/or its affiliates."
30+
__license__ = "MIT"
31+
32+
33+
class SimpleDataModel(object):
34+
"""Model a Spark JSON object as a simple Python object."""
35+
36+
def __init__(self, json_data):
37+
"""Init a new SparkData object from a dictionary or JSON string.
38+
39+
Args:
40+
json_data(dict, basestring): Input JSON string or dictionary.
41+
42+
Raises:
43+
TypeError: If the input object is not a dictionary or string.
44+
45+
"""
46+
super(SimpleDataModel, self).__init__()
47+
for attribute, value in json_dict(json_data).items():
48+
setattr(self, attribute, value)
49+
50+
def __str__(self):
51+
"""A human-readable string representation of this object."""
52+
return json.dumps(self.__dict__, ensure_ascii=False, indent=4)
53+
54+
def __repr__(self):
55+
"""A string representing this object as valid Python expression."""
56+
class_str = self.__class__.__name__
57+
json_str = json.dumps(self.__dict__, ensure_ascii=False)
58+
return "{}({})".format(class_str, repr(json_str))

ciscosparkapi/models/sparkdata.py

Lines changed: 3 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,9 @@
1919
)
2020

2121
from builtins import *
22-
from collections import OrderedDict
2322
import json
2423

25-
from past.builtins import basestring
24+
from ..utils import json_dict
2625

2726

2827
__author__ = "Chris Lunsford"
@@ -31,30 +30,6 @@
3130
__license__ = "MIT"
3231

3332

34-
def _json_dict(json_data):
35-
"""Given a dictionary or JSON string; return a dictionary.
36-
37-
Args:
38-
json_data(dict, str): Input JSON object.
39-
40-
Returns:
41-
A Python dictionary with the contents of the JSON object.
42-
43-
Raises:
44-
TypeError: If the input object is not a dictionary or string.
45-
46-
"""
47-
if isinstance(json_data, dict):
48-
return json_data
49-
elif isinstance(json_data, basestring):
50-
return json.loads(json_data, object_hook=OrderedDict)
51-
else:
52-
raise TypeError(
53-
"'json_data' must be a dictionary or valid JSON string; "
54-
"received: {!r}".format(json_data)
55-
)
56-
57-
5833
class SparkData(object):
5934
"""Model a Spark JSON object as a native Python object."""
6035

@@ -69,7 +44,7 @@ def __init__(self, json_data):
6944
7045
"""
7146
super(SparkData, self).__init__()
72-
self._json_data = _json_dict(json_data)
47+
self._json_data = json_dict(json_data)
7348

7449
def __getattr__(self, item):
7550
"""Provide native attribute access to the JSON object attributes.
@@ -113,7 +88,7 @@ def __repr__(self):
11388
"""A string representing this object as valid Python expression."""
11489
class_str = self.__class__.__name__
11590
json_str = json.dumps(self._json_data, ensure_ascii=False)
116-
return "{}({})".format(class_str, json_str)
91+
return "{}({})".format(class_str, repr(json_str))
11792

11893
@property
11994
def json_data(self):

ciscosparkapi/utils.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,3 +204,27 @@ def extract_and_parse_json(response):
204204
205205
"""
206206
return json.loads(response.text, object_hook=OrderedDict)
207+
208+
209+
def json_dict(json_data):
210+
"""Given a dictionary or JSON string; return a dictionary.
211+
212+
Args:
213+
json_data(dict, str): Input JSON object.
214+
215+
Returns:
216+
A Python dictionary with the contents of the JSON object.
217+
218+
Raises:
219+
TypeError: If the input object is not a dictionary or string.
220+
221+
"""
222+
if isinstance(json_data, dict):
223+
return json_data
224+
elif isinstance(json_data, basestring):
225+
return json.loads(json_data, object_hook=OrderedDict)
226+
else:
227+
raise TypeError(
228+
"'json_data' must be a dictionary or valid JSON string; "
229+
"received: {!r}".format(json_data)
230+
)

0 commit comments

Comments
 (0)