Skip to content

Commit c2fc32a

Browse files
committed
Make it run on 3.5 as well as 2.7.
* use six to smooth over unicode/string and module layout differences * make sure the action construction is immune to implementation differences in hash order * make sure the tests of action construction are immune to implementation differences in hash order
1 parent ae93773 commit c2fc32a

File tree

5 files changed

+23
-17
lines changed

5 files changed

+23
-17
lines changed

adobe_umapi/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
from api import UMAPI, Action
1+
from .api import UMAPI, Action

adobe_umapi/api.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import requests
22
import json
3-
from error import UMAPIError, UMAPIRetryError, UMAPIRequestError, ActionFormatError
3+
import six
4+
from .error import UMAPIError, UMAPIRetryError, UMAPIRequestError, ActionFormatError
45

56

67
class UMAPI(object):
@@ -17,7 +18,7 @@ def groups(self, org_id, page=0):
1718

1819
def action(self, org_id, action):
1920
if not isinstance(action, Action):
20-
if not isinstance(action, str) and hasattr(action, "__getitem__") or hasattr(action, "__iter__"):
21+
if not isinstance(action, str) and (hasattr(action, "__getitem__") or hasattr(action, "__iter__")):
2122
actions = [a.data for a in action]
2223
else:
2324
raise ActionFormatError("action must be iterable, indexable or Action object")
@@ -51,19 +52,19 @@ def _call(self, method, call, params=None):
5152
class Action(object):
5253
def __init__(self, user_key, **kwargs):
5354
self.data = {"user": user_key, "do": []} # empty actions upon creation
54-
for k, v in kwargs.items():
55+
for k, v in six.iteritems(kwargs):
5556
self.data[k] = v
5657

5758
# do adds to any existing actions, so can you Action(...).do(...).do(...)
5859
def do(self, **kwargs):
5960
# add "create" / "add" / "removeFrom" first
60-
for k, v in kwargs.items():
61+
for k, v in list(six.iteritems(kwargs)):
6162
if k.startswith("create") or k.startswith("addAdobe") or k.startswith("removeFrom"):
6263
self.data["do"].append({k: v})
6364
del kwargs[k]
6465

65-
# now do the other actions
66-
for k, v in kwargs.items():
66+
# now do the other actions, in a canonical order (to avoid implementation variations)
67+
for k, v in sorted(six.iteritems(kwargs)):
6768
if k in ['add', 'remove']:
6869
self.data["do"].append({k: {"product": v}})
6970
else:

adobe_umapi/auth.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import time
2-
# noinspection PyPackageRequirements
2+
# noinspection PyPackageRequirements,PyUnresolvedReferences
33
import jwt # package name is PyJWT in setup
44
import requests
55
import datetime as dt
6-
from urllib import urlencode
6+
from six.moves.urllib.parse import urlencode
77

88

99
class JWT(object):

adobe_umapi/helper.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from random import randint
55
from sys import maxsize
66
from time import time, sleep
7-
from error import UMAPIError, UMAPIRetryError, UMAPIRequestError
7+
from .error import UMAPIError, UMAPIRetryError, UMAPIRequestError
88

99
# make the retry options module-global so they can be set by clients
1010
retry_max_attempts = 4

tests/test_actions.py

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99

1010
# This method will be used by the mock to replace requests.get / requests.post
11-
def mocked_requests_call(target):
11+
def mocked_requests_call(target, **kwargs):
1212
class MockResponse:
1313
def __init__(self, status_code, data):
1414
self.status_code = status_code
@@ -87,7 +87,7 @@ def test_user_create_error(_):
8787

8888

8989
@mock.patch('adobe_umapi.api.requests.post', side_effect=mocked_requests_call)
90-
def test_user_create_success(_):
90+
def test_user_create_failure(_):
9191
"""Test User Creation - FAILURE"""
9292
auth = mock.create_autospec(Auth)
9393

@@ -128,23 +128,26 @@ def test_action_obj_create():
128128
action = Action(user_key="[email protected]").do(
129129
addAdobeID={"email": "[email protected]"}
130130
)
131-
assert json.dumps(action.data) == '{"do": [{"addAdobeID": {"email": "[email protected]"}}], "user": "[email protected]"}'
131+
assert json.dumps(action.data, sort_keys=True) ==\
132+
'{"do": [{"addAdobeID": {"email": "[email protected]"}}], "user": "[email protected]"}'
132133

133134

134135
def test_action_obj_remove():
135136
""""Create a user removal action object"""
136137
action = Action(user_key="[email protected]").do(
137138
removeFromOrg={}
138139
)
139-
assert json.dumps(action.data) == '{"do": [{"removeFromOrg": {}}], "user": "[email protected]"}'
140+
assert json.dumps(action.data, sort_keys=True) ==\
141+
'{"do": [{"removeFromOrg": {}}], "user": "[email protected]"}'
140142

141143

142144
def test_action_obj_update():
143145
"""Create a user update action object"""
144146
action = Action(user_key="[email protected]").do(
145147
update={"firstname": "example", "lastname": "user"}
146148
)
147-
assert json.dumps(action.data) == '{"do": [{"update": {"lastname": "user", "firstname": "example"}}], "user": "[email protected]"}'
149+
assert json.dumps(action.data, sort_keys=True) ==\
150+
'{"do": [{"update": {"firstname": "example", "lastname": "user"}}], "user": "[email protected]"}'
148151

149152

150153
def test_action_obj_multi():
@@ -154,12 +157,14 @@ def test_action_obj_multi():
154157
add=["product1", "product2"],
155158
remove=["product3"]
156159
)
157-
assert json.dumps(action.data) == '{"do": [{"addAdobeID": {"email": "[email protected]"}}, {"add": {"product": ["product1", "product2"]}}, {"remove": {"product": ["product3"]}}], "user": "[email protected]"}'
160+
assert json.dumps(action.data, sort_keys=True) ==\
161+
'{"do": [{"addAdobeID": {"email": "[email protected]"}}, {"add": {"product": ["product1", "product2"]}}, {"remove": {"product": ["product3"]}}], "user": "[email protected]"}'
158162

159163

160164
def test_action_obj_requestid():
161165
"""Include a request ID in action object"""
162166
action = Action(user_key="[email protected]", requestID="abc123").do(
163167
add=["product1"]
164168
)
165-
assert json.dumps(action.data) == '{"do": [{"add": {"product": ["product1"]}}], "user": "[email protected]", "requestID": "abc123"}'
169+
assert json.dumps(action.data, sort_keys=True) ==\
170+
'{"do": [{"add": {"product": ["product1"]}}], "requestID": "abc123", "user": "[email protected]"}'

0 commit comments

Comments
 (0)