11import json
22import os
3+ from urlparse import urlparse , parse_qs
4+ from urllib import quote
35
4- import dingus
6+ import mock
57
68from aweber_api import AWeberUser
79from aweber_api import OAuthAdapter
1517 '/accounts/1' : ({}, 'accounts/1' ),
1618 '/accounts/1?ws.op=findSubscribers&' \
1719 'email=joe%40example.com' : ({}, 'accounts/findSubscribers' ),
18- '/accounts/1?ws.op=findSubscribers&' \
19- 'email=joe%40example.com&' \
20- 'ws.show=total_size' : ({}, 'accounts/findSubscribers_ts' ),
20+ '/accounts/1?ws.show=total_size&ws.op=findSubscribers&' \
21+ 'email=joe%40example.com' : ({}, 'accounts/findSubscribers_ts' ),
2122 '/accounts/1?ws.op=getWebForms' : ({}, 'accounts/webForms' ),
2223 '/accounts/1?ws.op=getWebFormSplitTests' : ({}, 'accounts/webFormSplitTests' ),
2324 '/accounts/1/lists' : ({}, 'lists/page1' ),
3738 '/accounts/1/lists/505454/subscribers/3' : ({}, 'subscribers/3' ),
3839 '/accounts/1/lists/303449/subscribers/1?ws.op=getActivity' : (
3940 {}, 'subscribers/get_activity' ),
40- '/accounts/1/lists/303449/subscribers/1?ws.op=getActivity &ws.show=total_size ' : (
41+ '/accounts/1/lists/303449/subscribers/1?ws.show=total_size &ws.op=getActivity ' : (
4142 {}, 'subscribers/get_activity_ts' ),
4243 '/accounts/1/lists/303449/subscribers?ws.op=find&name=joe' : (
4344 {'status' : '400' }, 'error' ),
4445 '/accounts/1?ws.op=findSubscribers&name=bob' : (
4546 {'status' : '400' }, 'error' ),
4647 '/accounts/1/lists/303449/subscribers?ws.op=find&' \
4748 'email=joe%40example.com' : ({}, 'subscribers/find' ),
48- '/accounts/1/lists/303449/subscribers?ws.op=find&' \
49- 'email=joe%40example.com&' \
50- 'ws.show=total_size' : ({}, 'subscribers/find_ts' ),
49+ '/accounts/1/lists/303449/subscribers?ws.show=total_size&ws.op=find&' \
50+ 'email=joe%40example.com' : ({}, 'subscribers/find_ts' ),
5151 },
5252 'POST' : {
5353 '/accounts/1/lists/303449/any_collection' : ({
7272 }
7373}
7474
75+ def _sort_qs_for_url (url ):
76+ """Sort query string parameters in desending order."""
77+ parsed = urlparse (url )
78+
79+ if len (parsed .query ) == 0 :
80+ return parsed .path
81+
82+ qs = parse_qs (parsed .query )
83+ params = []
84+ for key in reversed (sorted (qs .keys ())):
85+ params .append ("{0}={1}" .format (key , quote (qs [key ][0 ])))
86+
87+ return "{0}?{1}" .format (parsed .path , "&" .join (params ))
88+
89+
7590def request (self , url , method , ** kwargs ):
7691 """Return a tuple to simulate calling oauth2.Client.request."""
92+ url = _sort_qs_for_url (url )
7793 (headers , file ) = responses [method ][url ]
7894 if 'status' not in headers :
7995 # assume 200 OK if not otherwise specified
@@ -90,9 +106,10 @@ class MockAdapter(OAuthAdapter):
90106 """Mocked OAuthAdapter."""
91107 requests = []
92108
93- @dingus .patch ('oauth2.Client.request' , request )
109+ @mock .patch ('oauth2.Client.request' , request )
94110 def request (self , method , url , data = {}, response = 'body' ):
95111 """Mock the oauth.Client.request method"""
112+ url = _sort_qs_for_url (url )
96113 req = super (MockAdapter , self ).request (method , url , data , response )
97114 self .requests .append ({'method' : method , 'url' : url , 'data' : data })
98115 return req
0 commit comments