Skip to content
This repository was archived by the owner on Aug 29, 2019. It is now read-only.

Commit c7fcbf2

Browse files
author
aweber
committed
Merge pull request #3 from borisvaweber/master
findSubscribers and get_parent_entry changes.
2 parents df9697d + 545fa2d commit c7fcbf2

File tree

8 files changed

+192
-2
lines changed

8 files changed

+192
-2
lines changed

aweber_api/collection.py

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from urlparse import parse_qs
33
from urllib import urlencode
44
from aweber_api.response import AWeberResponse
5+
from aweber_api.base import API_BASE
56

67
class AWeberCollection(AWeberResponse):
78
"""
@@ -42,7 +43,7 @@ def _load_page_for_offset(self, offset):
4243
self._key_entries(response)
4344

4445
def _get_page_params(self, offset):
45-
next_link = self._data['next_collection_link']
46+
next_link = self._data.get('next_collection_link', '')
4647
url, query = next_link.split('?')
4748
query_parts = parse_qs(query)
4849
self.page_size = int(query_parts['ws.size'][0])
@@ -83,10 +84,28 @@ def _get_total_size(self, uri, **kwargs):
8384
total_size_uri = '{0}&ws.show=total_size'.format(uri)
8485
return self.adapter.request('GET', total_size_uri)
8586

87+
# This method gets a collection's parent entry
88+
# Or returns None if no parent entry
89+
def get_parent_entry(self):
90+
from aweber_api.entry import AWeberEntry
91+
url_parts = self.url.split('/')
92+
#If top of tree - no parent entry
93+
if len(url_parts) <= 3:
94+
return None
95+
size = len(url_parts)
96+
#Remove collection id and slash from end of url
97+
url = self.url[:-len(url_parts[size-1])-1]
98+
data = self.adapter.request('GET', url)
99+
try:
100+
entry = AWeberEntry(url, data, self.adapter)
101+
except TypeError:
102+
return False
103+
return entry
104+
86105
def _create_entry(self, offset):
87106
from aweber_api.entry import AWeberEntry
88107
data = self._entry_data[offset]
89-
url = "{0}/{1}".format(self.url, data['id'])
108+
url = data['self_link'].replace(API_BASE, '')
90109
self._entries[offset] = AWeberEntry(url, data, self.adapter)
91110

92111
def __len__(self):

aweber_api/entry.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from aweber_api.response import AWeberResponse
22
from aweber_api.data_dict import DataDict
3+
from urllib import urlencode
34

45
class AWeberEntry(AWeberResponse):
56
"""
@@ -70,12 +71,60 @@ def save(self):
7071
return True
7172
return False
7273

74+
def findSubscribers(self, **kwargs):
75+
from aweber_api import AWeberCollection
76+
self._method_for('account')
77+
params = {'ws.op': 'findSubscribers'}
78+
params.update(kwargs)
79+
query_string = urlencode(params)
80+
url = '{0.url}?{1}'.format(self, query_string)
81+
data = self.adapter.request('GET', url)
82+
try:
83+
collection = AWeberCollection(url, data, self.adapter)
84+
except TypeError:
85+
print 'meow'
86+
return False
87+
88+
# collections return total_size_link
89+
collection._data['total_size'] = self._get_total_size(url)
90+
return collection
91+
92+
def _get_total_size(self, uri, **kwargs):
93+
"""Get actual total size number from total_size_link."""
94+
total_size_uri = '{0}&ws.show=total_size'.format(uri)
95+
return self.adapter.request('GET', total_size_uri)
96+
97+
# This method gets an entry's parent entry
98+
# Or returns None if no parent entry
99+
def get_parent_entry(self):
100+
url_parts = self.url.split('/')
101+
size = len(url_parts)
102+
#Remove entry id and slash from end of url
103+
url = self.url[:-len(url_parts[size-1])-1]
104+
#Remove collection name and slash from end of url
105+
url = url[:-len(url_parts[size-2])-1]
106+
data = self.adapter.request('GET', url)
107+
try:
108+
entry = AWeberEntry(url, data, self.adapter)
109+
#Top of tree
110+
except TypeError:
111+
return None
112+
return entry
113+
73114
def get_web_forms(self):
74115
self._method_for('account')
75116
data = self.adapter.request('GET',
76117
"{0}?ws.op=getWebForms".format(self.url))
77118
return self._parseNamedOperation(data)
78119

120+
def get_web_form_split_tests(self):
121+
self._method_for('account')
122+
data = self.adapter.request(
123+
'GET',
124+
"{0}?ws.op=getWebFormSplitTests".format(self.url),
125+
)
126+
return self._parseNamedOperation(data)
127+
79128
def _child_collection(self, attr):
80129
if not attr in self._child_collections:
81130
url = "{0}/{1}".format(self.url, attr)
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"start": 0, "total_size_link": "https://api.aweber.com/1.0/accounts/1?email=joe%40example.com&ws.op=findSubscribers&ws.show=total_size", "entries": [{"subscription_url": "https://www.aweber.com/users/leads/add", "postal_code": "14450", "id": 52629234, "custom_fields": {"NewCustomField": "really awesome", "YourCustomField": "NewValue"}, "last_followup_sent_link": "https://api.aweber.com/1.0/accounts/1/lists/496562/campaigns/f3548399", "city": "Fairport", "http_etag": "\"223a06015fdd0daaef1b561aee4f10176513e346-075619e34cfd24154382b5a53939132945e96ce3\"", "ad_tracking": "control panel", "dma_code": 538, "last_followup_message_number_sent": 3, "last_followup_sent_at": "2011-03-02 14:47:22.797206-05:00", "misc_notes": "", "self_link": "https://api.aweber.com/1.0/accounts/1/lists/303449/subscribers/1", "is_verified": true, "email": "joe@example.com", "status": "subscribed", "unsubscribed_at": null, "area_code": 585, "latitude": 43.100499999999997, "unsubscribe_method": null, "ip_address": "192.168.10.10", "name": "Joe User", "subscription_method": "signup form", "resource_type_link": "https://api.aweber.com/1.0/#subscriber", "region": "NY", "longitude": -77.426000000000002, "verified_at": "2011-02-15 13:37:23", "subscribed_at": "2011-02-15 13:27:28-05:00", "country": "United States"}]}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
1
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
[{"javascript_source_link": "http://forms.aweber.com/form/40/split_1855537940.js", "name": "Split test test", "components_collection_link": "https://api.aweber.com/1.0/accounts/1/lists/1115098/web_form_split_tests/1855537940/components", "is_active": true, "http_etag": "\"b233a000ec4c29e928c514a253a15684a410fa4e-ca5feee2b7fbb6febfca8af5541541ea960aaedb\"", "self_link": "https://api.aweber.com/1.0/accounts/1/lists/1115098/web_form_split_tests/1855537940", "resource_type_link": "https://api.aweber.com/1.0/#web_form_split_test", "id": 1855537940}, {"javascript_source_link": "http://forms.aweber.com/form/13/split_1532806713.js", "name": "boristest", "components_collection_link": "https://api.aweber.com/1.0/accounts/1/lists/1108070/web_form_split_tests/1532806713/components", "is_active": true, "http_etag": "\"84edfbf4844a7a322bc379038974c0ce9871c1cd-ca5feee2b7fbb6febfca8af5541541ea960aaedb\"", "self_link": "https://api.aweber.com/1.0/accounts/1/lists/1108070/web_form_split_tests/1532806713", "resource_type_link": "https://api.aweber.com/1.0/#web_form_split_test", "id": 1532806713}, {"javascript_source_link": "http://forms.aweber.com/form/77/split_534926677.js", "name": "dsdf", "components_collection_link": "https://api.aweber.com/1.0/accounts/1/lists/1108070/web_form_split_tests/534926677/components", "is_active": true, "http_etag": "\"3b72341343ae33364cbb88255b27faa0502eeaa4-ca5feee2b7fbb6febfca8af5541541ea960aaedb\"", "self_link": "https://api.aweber.com/1.0/accounts/1/lists/1108070/web_form_split_tests/534926677", "resource_type_link": "https://api.aweber.com/1.0/#web_form_split_test", "id": 534926677}, {"javascript_source_link": "http://forms.aweber.com/form/75/split_728276575.js", "name": "Split test 1", "components_collection_link": "https://api.aweber.com/1.0/accounts/1/lists/772516/web_form_split_tests/728276575/components", "is_active": true, "http_etag": "\"178f16c2c921b30ea27b1f367005873c6de01c3b-ca5feee2b7fbb6febfca8af5541541ea960aaedb\"", "self_link": "https://api.aweber.com/1.0/accounts/1/lists/772516/web_form_split_tests/728276575", "resource_type_link": "https://api.aweber.com/1.0/#web_form_split_test", "id": 728276575}, {"javascript_source_link": "http://forms.aweber.com/form/48/split_1607797548.js", "name": "Split Test", "components_collection_link": "https://api.aweber.com/1.0/accounts/1/lists/772516/web_form_split_tests/1607797548/components", "is_active": true, "http_etag": "\"67201f06d0d014c17dcde6b0a272535f6e569e79-ca5feee2b7fbb6febfca8af5541541ea960aaedb\"", "self_link": "https://api.aweber.com/1.0/accounts/1/lists/772516/web_form_split_tests/1607797548", "resource_type_link": "https://api.aweber.com/1.0/#web_form_split_test", "id": 1607797548}, {"javascript_source_link": "http://forms.aweber.com/form/26/split_1252500526.js", "name": "Default", "components_collection_link": "https://api.aweber.com/1.0/accounts/1/lists/226186/web_form_split_tests/1252500526/components", "is_active": true, "http_etag": "\"3516cfad8b8d86f837c3c96a80537437fd774423-ca5feee2b7fbb6febfca8af5541541ea960aaedb\"", "self_link": "https://api.aweber.com/1.0/accounts/1/lists/226186/web_form_split_tests/1252500526", "resource_type_link": "https://api.aweber.com/1.0/#web_form_split_test", "id": 1252500526}, {"javascript_source_link": "http://forms.aweber.com/form/35/split_917592535.js", "name": "sdfsdf", "components_collection_link": "https://api.aweber.com/1.0/accounts/1/lists/496562/web_form_split_tests/917592535/components", "is_active": true, "http_etag": "\"aa9292397447f3a0a75a377c258112d8c0533f2f-ca5feee2b7fbb6febfca8af5541541ea960aaedb\"", "self_link": "https://api.aweber.com/1.0/accounts/1/lists/496562/web_form_split_tests/917592535", "resource_type_link": "https://api.aweber.com/1.0/#web_form_split_test", "id": 917592535}, {"javascript_source_link": "http://forms.aweber.com/form/44/split_1012223044.js", "name": "My splittest", "components_collection_link": "https://api.aweber.com/1.0/accounts/1/lists/406860/web_form_split_tests/1012223044/components", "is_active": true, "http_etag": "\"a69aca22c1f557260d2e977974400ded9830d288-ca5feee2b7fbb6febfca8af5541541ea960aaedb\"", "self_link": "https://api.aweber.com/1.0/accounts/1/lists/406860/web_form_split_tests/1012223044", "resource_type_link": "https://api.aweber.com/1.0/#web_form_split_test", "id": 1012223044}, {"javascript_source_link": "http://forms.aweber.com/form/72/split_1470252472.js", "name": "Split Test", "components_collection_link": "https://api.aweber.com/1.0/accounts/1/lists/406860/web_form_split_tests/1470252472/components", "is_active": true, "http_etag": "\"32123e40a437467f56cbc2d937196af63521b106-ca5feee2b7fbb6febfca8af5541541ea960aaedb\"", "self_link": "https://api.aweber.com/1.0/accounts/1/lists/406860/web_form_split_tests/1470252472", "resource_type_link": "https://api.aweber.com/1.0/#web_form_split_test", "id": 1470252472}, {"javascript_source_link": "http://forms.aweber.com/form/63/split_612763163.js", "name": "Popover/Inline Split", "components_collection_link": "https://api.aweber.com/1.0/accounts/1/lists/406860/web_form_split_tests/612763163/components", "is_active": true, "http_etag": "\"527d810ab00669964ab634395cded77c12af7a9c-ca5feee2b7fbb6febfca8af5541541ea960aaedb\"", "self_link": "https://api.aweber.com/1.0/accounts/1/lists/406860/web_form_split_tests/612763163", "resource_type_link": "https://api.aweber.com/1.0/#web_form_split_test", "id": 612763163}]

tests/mock_adapter.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,13 @@
1313
'GET' : {
1414
'/accounts': ({}, 'accounts/page1'),
1515
'/accounts/1': ({}, 'accounts/1'),
16+
'/accounts/1?ws.op=findSubscribers&' \
17+
'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'),
1621
'/accounts/1?ws.op=getWebForms': ({}, 'accounts/webForms'),
22+
'/accounts/1?ws.op=getWebFormSplitTests': ({}, 'accounts/webFormSplitTests'),
1723
'/accounts/1/lists': ({}, 'lists/page1'),
1824
'/accounts/1/lists?ws.start=20&ws.size=20': ({}, 'lists/page2'),
1925
'/accounts/1/lists/303449': ({}, 'lists/303449'),

tests/test_aweber_collection.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from unittest import TestCase
22
from aweber_api import AWeberAPI, AWeberCollection, AWeberEntry
3+
from aweber_api.base import API_BASE
34
from mock_adapter import MockAdapter
45

56

@@ -63,6 +64,13 @@ def test_find_should_handle_errors(self):
6364
assert request['url'] == \
6465
'{0}?ws.op=find&name=joe'.format(base_url)
6566

67+
def test_should_create_entries_with_correct_url(self):
68+
base_url = '/accounts/1'
69+
account = self.aweber.load_from_url(base_url)
70+
subscribers = account.findSubscribers(email='joe@example.com')
71+
for subscriber in subscribers:
72+
assert subscriber.url == subscriber.self_link.replace(API_BASE, '')
73+
6674

6775
class TestCreatingCustomFields(TestCase):
6876

@@ -97,3 +105,30 @@ def test_should_refresh_cf_resource(self):
97105
self.assertEqual(self.get_req['method'], 'GET')
98106
self.assertEqual(self.get_req['url'] ,
99107
'/accounts/1/lists/303449/custom_fields/2')
108+
109+
110+
class TestGettingParentEntry(TestCase):
111+
112+
def setUp(self):
113+
self.aweber = AWeberAPI('1', '2')
114+
self.aweber.adapter = MockAdapter()
115+
self.lists = self.aweber.load_from_url('/accounts/1/lists')
116+
self.accounts = self.aweber.load_from_url('/accounts')
117+
self.custom_fields = self.aweber.load_from_url('/accounts/1/lists/303449/custom_fields')
118+
119+
def test_should_be_able_get_parent_entry(self):
120+
entry = self.lists.get_parent_entry()
121+
122+
def test_lists_parent_should_be_account(self):
123+
entry = self.lists.get_parent_entry()
124+
self.assertEqual(type(entry), AWeberEntry)
125+
self.assertEqual(entry.type, 'account')
126+
127+
def test_custom_fields_parent_should_be_list(self):
128+
entry = self.custom_fields.get_parent_entry()
129+
self.assertEqual(type(entry), AWeberEntry)
130+
self.assertEqual(entry.type, 'list')
131+
132+
def test_accounts_parent_should_be_none(self):
133+
entry = self.accounts.get_parent_entry()
134+
self.assertEqual(entry, None)

tests/test_aweber_entry.py

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,17 @@ def test_should_have_child_collections(self):
2727
campaigns = self.list.campaigns
2828
self.assertEqual(type(campaigns), AWeberCollection)
2929

30+
def test_findSubscribers_should_handle_errors(self):
31+
base_url = '/accounts/1'
32+
account = self.aweber.load_from_url(base_url)
33+
self.aweber.adapter.requests = []
34+
subscribers = account.findSubscribers(name='bob')
35+
request = self.aweber.adapter.requests[0]
36+
37+
assert subscribers == False
38+
assert request['url'] == \
39+
'{0}?ws.op=findSubscribers&name=bob'.format(base_url)
40+
3041
class TestAWeberAccountEntry(TestCase):
3142

3243
def setUp(self):
@@ -41,6 +52,9 @@ def test_should_be_an_entry(self):
4152
def test_should_be_able_get_web_forms(self):
4253
forms = self.account.get_web_forms()
4354

55+
def test_should_be_able_get_web_form_split_tests(self):
56+
forms = self.account.get_web_form_split_tests()
57+
4458
class TestAccountGetWebForms(TestAWeberAccountEntry):
4559

4660
def setUp(self):
@@ -63,6 +77,43 @@ def test_each_should_have_correct_url(self):
6377
for entry in self.forms:
6478
self.assertTrue(re.match(url_regex, entry.url))
6579

80+
class TestAccountGetWebFormSplitTests(TestAWeberAccountEntry):
81+
82+
def setUp(self):
83+
TestAWeberAccountEntry.setUp(self)
84+
self.forms = self.account.get_web_form_split_tests()
85+
86+
def test_should_be_a_list(self):
87+
self.assertEqual(type(self.forms), list)
88+
89+
def test_should_have_10_split_tests(self):
90+
self.assertEqual(len(self.forms), 10)
91+
92+
def test_each_should_be_entry(self):
93+
for entry in self.forms:
94+
self.assertEqual(type(entry), AWeberEntry)
95+
self.assertEqual(entry.type, 'web_form_split_test')
96+
97+
def test_each_should_have_correct_url(self):
98+
url_regex = '/accounts\/1\/lists\/\d*/web_form_split_tests/\d*'
99+
for entry in self.forms:
100+
self.assertTrue(re.match(url_regex, entry.url))
101+
102+
class TestAccountFindSubscribers(TestAWeberAccountEntry):
103+
104+
def test_should_support_find_method(self):
105+
base_url = '/accounts/1'
106+
account = self.aweber.load_from_url(base_url)
107+
self.aweber.adapter.requests = []
108+
subscribers = account.findSubscribers(email='joe@example.com')
109+
request = self.aweber.adapter.requests[0]
110+
111+
assert subscribers != False
112+
assert isinstance(subscribers, AWeberCollection)
113+
assert len(subscribers) == 1
114+
assert subscribers[0].self_link == \
115+
'https://api.aweber.com/1.0/accounts/1/lists/303449/subscribers/1'
116+
66117
class TestSubscriber(TestCase):
67118

68119
def setUp(self):
@@ -210,3 +261,30 @@ def setUp(self):
210261

211262
def test_should_have_failed(self):
212263
self.assertFalse(self.response)
264+
265+
class TestGettingParentEntry(TestCase):
266+
267+
def setUp(self):
268+
self.aweber = AWeberAPI('1', '2')
269+
self.aweber.adapter = MockAdapter()
270+
self.list = self.aweber.load_from_url('/accounts/1/lists/303449')
271+
self.account = self.aweber.load_from_url('/accounts/1')
272+
self.custom_field = self.aweber.load_from_url('/accounts/1/lists/303449/custom_fields/1')
273+
274+
def test_should_be_able_get_parent_entry(self):
275+
entry = self.list.get_parent_entry()
276+
277+
def test_list_parent_should_be_account(self):
278+
entry = self.list.get_parent_entry()
279+
self.assertEqual(type(entry), AWeberEntry)
280+
self.assertEqual(entry.type, 'account')
281+
282+
def test_custom_field_parent_should_be_list(self):
283+
entry = self.custom_field.get_parent_entry()
284+
self.assertEqual(type(entry), AWeberEntry)
285+
self.assertEqual(entry.type, 'list')
286+
287+
def test_account_parent_should_be_none(self):
288+
entry = self.account.get_parent_entry()
289+
self.assertEqual(entry, None)
290+

0 commit comments

Comments
 (0)