Skip to content
This repository was archived by the owner on Aug 29, 2019. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
*.pyc
*.svn
Binary file removed aweber_api/__init__.pyc
Binary file not shown.
Binary file removed aweber_api/base.pyc
Binary file not shown.
Binary file removed aweber_api/collection.pyc
Binary file not shown.
19 changes: 19 additions & 0 deletions aweber_api/data_dict.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
"""
This class is used to propagate changes to a parent item. This is
used for when an AWeberEntry has a dict item as on of the attributes
in _data. When changes are made to an item in this data dict, __setattr__
gets called on the parent with the new state of the dict.
"""
class DataDict(object):

def __init__(self, data, name, parent):
self.parent = parent
self.data = data
self.name = name

def __getitem__(self, key):
return self.data[key]

def __setitem__(self, key, value):
self.data[key] = value
self.parent.__setattr__(self.name, self.data)
25 changes: 25 additions & 0 deletions aweber_api/entry.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from aweber_api.response import AWeberResponse
from aweber_api.data_dict import DataDict

class AWeberEntry(AWeberResponse):
"""
Expand All @@ -15,9 +16,31 @@ class AWeberEntry(AWeberResponse):
"""

def __init__(self, url, data, adapter):
self._data = {}
self._diff = {}
AWeberResponse.__init__(self, url, data, adapter)
self._child_collections = {}

def __setattr__(self, key, value):
if not key == '_data' and key in self._data:
self._data[key] = value
self._diff[key] = value
return value
return AWeberResponse.__setattr__(self, key, value)

def delete(self):
status = self.adapter.request('DELETE', self.url, response='status')
if str(status)[:2] == '20':
return True
return False

def save(self):
response = self.adapter.request('PATCH', self.url, self._diff,
response='status')
self._diff = {}
if str(response)[:2] == '20':
return True
return False

def get_web_forms(self):
self._method_for('account')
Expand All @@ -33,6 +56,8 @@ def _child_collection(self, attr):

def __getattr__(self, attr):
if attr in self._data:
if isinstance(self._data[attr], dict):
return DataDict(self._data[attr], attr, self)
return self._data[attr]
elif attr in self.collections_map[self.type]:
return self._child_collection(attr)
Expand Down
Binary file removed aweber_api/entry.pyc
Binary file not shown.
51 changes: 32 additions & 19 deletions aweber_api/oauth.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,27 +19,40 @@ def _parse(self, response):
pass
return response

def request(self, method, url, data={}):
token = self.user.get_highest_priority_token()
if token:
token = oauth.Token(token, self.user.token_secret)
client = oauth.Client(self.consumer, token=token)
else:
client = oauth.Client(self.consumer)

if not url[:4] == 'http':
url = '%s%s' % (self.api_base, url)

if len(data.keys()) == 0:
body = None
else:
body = '&'.join(map(lambda x: "{0}={1}".format(x, data[x]),
data.keys()))

def request(self, method, url, data={}, response='body'):
client = self._get_client()
url = self._expand_url(url)
body = self._prepare_request_body(method, url, data)
try:
resp, content = client.request(url, method, body=body)
if type(content) == str:
headers = {'Content-Type' : 'application/json'}
resp, content = client.request(url, method, body=body,
headers=headers)
if response == 'body' and isinstance(content, str):
return self._parse(content)
if response == 'status':
return resp['status']
except e:
pass
return None

def _expand_url(self, url):
if not url[:4] == 'http':
return '%s%s' % (self.api_base, url)
return url

def _get_client(self):
token = self.user.get_highest_priority_token()
if token:
token = oauth.Token(token, self.user.token_secret)
return oauth.Client(self.consumer, token=token)
return oauth.Client(self.consumer)

def _prepare_request_body(self, method, url, data):
if len(data.keys()) == 0 or method not in ['GET', 'PATCH']:
return None

if method == 'GET':
return '&'.join(map(lambda x: "{0}={1}".format(x, data[x]),
data.keys()))
if method == 'PATCH':
return json.dumps(data)
Binary file removed aweber_api/oauth.pyc
Binary file not shown.
Binary file removed aweber_api/response.pyc
Binary file not shown.
1 change: 1 addition & 0 deletions tests/data/subscribers/1.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"subscription_url": null, "postal_code": "19006", "id": 1, "custom_fields": {"Trim": "EX", "Make": "Honda", "Model": "Civic", "Year": "2007"}, "last_followup_sent_link": "http://api.aweber.com/1.0/accounts/1/lists/1/campaigns/f2", "city": "Huntingdon Valley", "http_etag": "\"f3cd054da8ee5fcc8fd62765f1248a3e286a1e98-5452a183e6c35a9d38607ef778eba4fbf56db21e\"", "ad_tracking": "asasdffasdfasff", "dma_code": 143, "last_followup_message_number_sent": 1, "last_followup_sent_at": null, "misc_notes": null, "latitude": 23.23, "is_verified": false, "email": "joe@example.com", "status": "unsubscribed", "area_code": 267, "unsubscribed_at": "2010-12-16 20:57:51.178863-05:00", "self_link": "http://api.aweber.com/1.0/accounts/1/lists/1/subscribers/1", "ip_address": null, "name": "Joe Jones", "subscription_method": "email", "resource_type_link": "http://api.aweber.com/1.0/#subscriber", "region": "North America", "longitude": 70.340000000000003, "verified_at": "2010-12-17 01:57:51.178816", "subscribed_at": "2010-12-16 20:57:51.178856-05:00", "country": "USA"}
1 change: 1 addition & 0 deletions tests/data/subscribers/2.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"subscription_url": null, "postal_code": "19006", "id": 1, "custom_fields": {"Trim": "EX", "Make": "Honda", "Model": "Civic", "Year": "2007"}, "last_followup_sent_link": "http://api.aweber.com/1.0/accounts/1/lists/1/campaigns/f2", "city": "Huntingdon Valley", "http_etag": "\"f3cd054da8ee5fcc8fd62765f1248a3e286a1e98-5452a183e6c35a9d38607ef778eba4fbf56db21e\"", "ad_tracking": "asasdffasdfasff", "dma_code": 143, "last_followup_message_number_sent": 1, "last_followup_sent_at": null, "misc_notes": null, "latitude": 23.23, "is_verified": false, "email": "joe@example.com", "status": "unsubscribed", "area_code": 267, "unsubscribed_at": "2010-12-16 20:57:51.178863-05:00", "self_link": "http://api.aweber.com/1.0/accounts/1/lists/1/subscribers/1", "ip_address": null, "name": "Joe Jones", "subscription_method": "email", "resource_type_link": "http://api.aweber.com/1.0/#subscriber", "region": "North America", "longitude": 70.340000000000003, "verified_at": "2010-12-17 01:57:51.178816", "subscribed_at": "2010-12-16 20:57:51.178856-05:00", "country": "USA"}
43 changes: 30 additions & 13 deletions tests/mock_adapter.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,31 @@ def __init__(self):
self.user = AWeberUser()

request_paths = {
'/accounts' : 'accounts',
'/accounts/1' : 'account',
'/accounts/1/lists' : 'lists',
'/accounts/1?ws.op=getWebForms' : 'web_forms',
'/accounts/1/lists?ws.start=20&ws.size=20' : 'lists_page2',
'/accounts/1/lists/303449' : 'lists/303449',
'/accounts/1/lists/303449/campaigns' : 'lists/303449/campaigns'
'GET' : {
'/accounts' : 'accounts',
'/accounts/1' : 'account',
'/accounts/1/lists' : 'lists',
'/accounts/1?ws.op=getWebForms' : 'web_forms',
'/accounts/1/lists?ws.start=20&ws.size=20' : 'lists_page2',
'/accounts/1/lists/303449' : 'lists/303449',
'/accounts/1/lists/303449/campaigns' : 'lists/303449/campaigns',
'/accounts/1/lists/303449/subscribers/1' : 'subscribers/1',
'/accounts/1/lists/303449/subscribers/2' : 'subscribers/2'
},
'PATCH' : {
'/accounts/1/lists/303449/subscribers/1' : '200',
'/accounts/1/lists/303449/subscribers/2' : '403'
},
'DELETE' : {
'/accounts/1/lists/303449/subscribers/1' : '200',
'/accounts/1/lists/303449/subscribers/2' : '403'
}
}

requests = []

def request(self, method, url, data={}):
if not (len(data.keys()) == 0):
def request(self, method, url, data={}, response=False):
if method == 'GET' and not (len(data.keys()) == 0):
first = True
for key in data.keys():
if first:
Expand All @@ -30,12 +42,17 @@ def request(self, method, url, data={}):
first = False
url += key+'='+str(data[key])

if not url in self.request_paths:
if not url in self.request_paths[method]:
return ''
self.requests.append({'method' : method, 'url' : url, 'data' : data})

path = "{0}{1}.json".format(self.data_dir,
self.request_paths[url])
return json.load(open(path))
if not response:
path = "{0}{1}.json".format(self.data_dir,
self.request_paths[method][url])

return json.load(open(path))
if response == 'status':
return self.request_paths[method][url]

@property
def data_dir(self):
Expand Down
Binary file removed tests/mock_adapter.pyc
Binary file not shown.
Binary file removed tests/test_aweber_api.pyc
Binary file not shown.
Binary file removed tests/test_aweber_collection.pyc
Binary file not shown.
105 changes: 105 additions & 0 deletions tests/test_aweber_entry.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,4 +60,109 @@ def test_each_should_have_correct_url(self):
for entry in self.forms:
self.assertTrue(re.match(url_regex, entry.url))

class TestSubscriber(TestCase):

def setUp(self):
self.aweber = AWeberAPI('1', '2')
self.aweber.adapter = MockAdapter()
sub_url = '/accounts/1/lists/303449/subscribers/1'
self.subscriber = self.aweber.load_from_url(sub_url)

class TestGetAndSetData(TestSubscriber):

def test_get_name(self):
self.assertEqual(self.subscriber.name, 'Joe Jones')

def test_set_name(self):
self.subscriber.name = 'Randy Rhodes'
self.assertEqual(self.subscriber.name, 'Randy Rhodes')

def test_get_custom_fields(self):
fields = self.subscriber.custom_fields
self.assertEqual(fields['Make'], 'Honda')

def test_set_custom_fields(self):
self.subscriber.custom_fields['Make'] = 'Jeep'
self.assertEqual(self.subscriber._data['custom_fields']['Make'], 'Jeep')
fields = self.subscriber.custom_fields
self.assertEqual(fields['Make'], 'Jeep')


class TestSavingSubscriberData(TestSubscriber):

def setUp(self):
TestSubscriber.setUp(self)
self.aweber.adapter.requests = []
self.subscriber.name = 'Gary Oldman'
self.subscriber.custom_fields['Make'] = 'Jeep'
self.resp = self.subscriber.save()
self.req = self.aweber.adapter.requests[0]

def test_returned_true(self):
self.assertTrue(self.resp)

def test_should_make_request(self):
self.assertEqual(len(self.aweber.adapter.requests), 1)

def test_should_have_requested_resource_url(self):
self.assertEqual(self.req['url'] , self.subscriber.url)

def test_should_have_requested_with_patch(self):
self.assertEqual(self.req['method'], 'PATCH')

def test_should_have_supplied_data(self):
self.assertEqual(self.req['data']['name'], 'Gary Oldman')

def test_should_not_include_unchanged_data(self):
self.assertFalse('email' in self.req['data'])

def test_should_given_all_custom_fields(self):
# Make changed, Model did not
self.assertEqual(self.req['data']['custom_fields']['Make'], 'Jeep')
self.assertEqual(self.req['data']['custom_fields']['Model'], 'Civic')

class TestSavingInvalidSubscriberData(TestCase):

def setUp(self):
self.aweber = AWeberAPI('1', '2')
self.aweber.adapter = MockAdapter()
sub_url = '/accounts/1/lists/303449/subscribers/2'
self.subscriber = self.aweber.load_from_url(sub_url)
self.subscriber.name = 'Gary Oldman'
self.subscriber.custom_fields['New Custom Field'] = 'Cookies'
self.resp = self.subscriber.save()
self.req = self.aweber.adapter.requests[0]

def test_save_failed(self):
self.assertFalse(self.resp)

class TestDeletingSubscriberData(TestSubscriber):

def setUp(self):
TestSubscriber.setUp(self)
self.aweber.adapter.requests = []
self.response = self.subscriber.delete()
self.req = self.aweber.adapter.requests[0]

def test_should_be_deleted(self):
self.assertTrue(self.response)

def test_should_have_made_request(self):
self.assertEqual(len(self.aweber.adapter.requests), 1)

def test_should_have_made_delete(self):
self.assertEqual(self.req['method'], 'DELETE')

class TestFailedSubscriberDelete(TestCase):

def setUp(self):
self.aweber = AWeberAPI('1', '2')
self.aweber.adapter = MockAdapter()
sub_url = '/accounts/1/lists/303449/subscribers/2'
self.subscriber = self.aweber.load_from_url(sub_url)
self.aweber.adapter.requests = []
self.response = self.subscriber.delete()
self.req = self.aweber.adapter.requests[0]

def test_should_have_failed(self):
self.assertFalse(self.response)
Binary file removed tests/test_aweber_entry.pyc
Binary file not shown.
25 changes: 25 additions & 0 deletions tests/test_data_dict.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
from unittest import TestCase
from aweber_api.data_dict import DataDict
from dingus import Dingus

class TestDataDict(TestCase):

def setUp(self):
self.obj = Dingus()
self.obj.data = {}
self.data = {
'favorite food' : 'Tacos',
'favorite drink' : 'Beer'
}
self.dict = DataDict(self.data, 'data', self.obj)

def test_exists(self):
self.assertTrue(self.dict)

def test_get_data(self):
self.assertEqual(self.dict['favorite drink'], 'Beer')

def test_set_data(self):
self.dict['favorite food'] = 'Pizza'
self.assertEqual(self.obj.data['favorite food'], 'Pizza')