From b66212abd14e73ad9cef79c8c7aaab9a03c5d452 Mon Sep 17 00:00:00 2001 From: Roger Hoover Date: Wed, 1 Dec 2010 16:58:50 -0800 Subject: [PATCH 1/5] Fixed add_record, add_records, and delete_record methods to return results so that the twisted client can know when the request is finished and if an error occured --- setup.py | 2 +- simplegeo/__init__.py | 6 ++-- tests/twisted/test_client.py | 55 ++++++++++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+), 4 deletions(-) create mode 100644 tests/twisted/test_client.py diff --git a/setup.py b/setup.py index b4ff2f7..a83ef7b 100644 --- a/setup.py +++ b/setup.py @@ -30,4 +30,4 @@ install_requires=['httplib2>=0.6.0', 'oauth2>=1.1.3', 'simplejson>=2.0.9'], keywords="simplegeo", zip_safe = True, - tests_require=['nose', 'coverage', 'python-geohash>=0.2']) + tests_require=['nose', 'coverage', 'python-geohash>=0.2', 'mock']) diff --git a/simplegeo/__init__.py b/simplegeo/__init__.py index def129b..6719f7e 100644 --- a/simplegeo/__init__.py +++ b/simplegeo/__init__.py @@ -155,7 +155,7 @@ def add_record(self, record): raise Exception("Record has no layer.") endpoint = self.endpoint('record', layer=record.layer, id=record.id) - self._request(endpoint, "PUT", record.to_json()) + return self._request(endpoint, "PUT", record.to_json()) def add_records(self, layer, records): features = { @@ -163,11 +163,11 @@ def add_records(self, layer, records): 'features': [record.to_dict() for record in records], } endpoint = self.endpoint('add_records', layer=layer) - self._request(endpoint, "POST", json.dumps(features)) + return self._request(endpoint, "POST", json.dumps(features)) def delete_record(self, layer, id): endpoint = self.endpoint('record', layer=layer, id=id) - self._request(endpoint, "DELETE") + return self._request(endpoint, "DELETE") def get_record(self, layer, id): endpoint = self.endpoint('record', layer=layer, id=id) diff --git a/tests/twisted/test_client.py b/tests/twisted/test_client.py new file mode 100644 index 0000000..64e44bc --- /dev/null +++ b/tests/twisted/test_client.py @@ -0,0 +1,55 @@ +import mock +from twisted.trial import unittest +from twisted.internet import defer, reactor +from simplegeo import Record, APIError +from simplegeo.twisted import Client + +MY_OAUTH_KEY = 'MY_OAUTH_KEY' +MY_OAUTH_SECRET = 'MY_SECRET_KEY' +TESTING_LAYER = 'TESTING_LAYER' + +API_VERSION = '0.1' +API_HOST = 'api.simplegeo.com' +API_PORT = 80 + +class ClientTest(unittest.TestCase): + + def setUp(self): + self.client = Client(MY_OAUTH_KEY, MY_OAUTH_SECRET, API_VERSION, API_HOST, API_PORT) + + def fake_request(self, *args, **kwargs): + d = defer.Deferred() + reactor.callLater(0, d.callback, mock.sentinel.retval) + return d + + @defer.inlineCallbacks + def test_add_record_returns_deferred(self): + self.client._request = mock.Mock(wraps=self.fake_request) + record = Record(layer=TESTING_LAYER, id=69, lat=34.5, lon=-122.8) + deferred = self.client.add_record(record) + self.assertTrue(isinstance(deferred, defer.Deferred)) + retval = yield deferred + self.assertEquals(mock.sentinel.retval, retval) + + @defer.inlineCallbacks + def test_add_records_returns_deferred(self): + self.client._request = mock.Mock(wraps=self.fake_request) + records = [Record(layer=TESTING_LAYER, id=69, lat=34.5, lon=-122.8), Record(layer=TESTING_LAYER, id=70, lat=34.5, lon=-122.8)] + deferred = self.client.add_records(TESTING_LAYER, records) + self.assertTrue(isinstance(deferred, defer.Deferred)) + retval = yield deferred + self.assertEquals(mock.sentinel.retval, retval) + + @defer.inlineCallbacks + def test_delete_record_returns_deferred(self): + self.client._request = mock.Mock(wraps=self.fake_request) + deferred = self.client.delete_record(TESTING_LAYER, 4) + self.assertTrue(isinstance(deferred, defer.Deferred)) + retval = yield deferred + self.assertEquals(mock.sentinel.retval, retval) + +if __name__ == '__main__': + import sys + from twisted.scripts import trial + sys.argv.extend([sys.argv[0]]) + trial.run() From 9847eb7bda086838da482c84e34f9ae1a6f227fe Mon Sep 17 00:00:00 2001 From: Roger Hoover Date: Fri, 15 Apr 2011 14:24:52 -0700 Subject: [PATCH 2/5] Back ported API to create layer --- simplegeo/__init__.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/simplegeo/__init__.py b/simplegeo/__init__.py index 6719f7e..0484f69 100644 --- a/simplegeo/__init__.py +++ b/simplegeo/__init__.py @@ -4,6 +4,7 @@ import simplejson as json from httplib2 import Http from urlparse import urljoin +from simplegeo.models import Layer __version__ = "unknown" try: @@ -202,6 +203,10 @@ def get_layer(self, layer): endpoint = self.endpoint('layer', layer=layer) return self._request(endpoint, "GET") + def create_layer(self, layer): + endpoint = self.endpoint('layer', layer=layer.name) + return self._request(endpoint, "PUT", layer.to_json()) + def get_density(self, lat, lon, day, hour=None): if hour is not None: endpoint = self.endpoint('density_hour', lat=lat, lon=lon, day=day, hour=hour) From 0524c532bf515b464d016b1351bd00e940f6999b Mon Sep 17 00:00:00 2001 From: Roger Hoover Date: Fri, 15 Apr 2011 14:25:17 -0700 Subject: [PATCH 3/5] Back ported API to create layer --- simplegeo/__init__.py | 45 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/simplegeo/__init__.py b/simplegeo/__init__.py index 0484f69..9088dc3 100644 --- a/simplegeo/__init__.py +++ b/simplegeo/__init__.py @@ -4,7 +4,6 @@ import simplejson as json from httplib2 import Http from urlparse import urljoin -from simplegeo.models import Layer __version__ = "unknown" try: @@ -67,6 +66,47 @@ def __hash__(self): def __eq__(self, other): return isinstance(other, self.__class__) and self.id == other.id +class Layer(object): + def __init__(self, name, title='', description='', public=False, + callback_urls=[]): + self.name = name + self.title = title + self.description = description + self.public = public + self.callback_urls = callback_urls + + @classmethod + def from_dict(cls, data): + if not data: + return None + layer = cls(data.get('name'), data.get('title'), + data.get('description'), data.get('public'), + data.get('callback_urls', [])) + return layer + + def to_dict(self): + return { + 'name': self.name, + 'title': self.title, + 'description': self.description, + 'public': self.public, + 'callback_urls': self.callback_urls, + } + + def to_json(self): + return json.dumps(self.to_dict()) + + def __str__(self): + return self.to_json() + + def __repr__(self): + return "Layer(name=%s, public=%s)" % (self.name, self.public) + + def __hash__(self): + return hash((self.name)) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.name == other.name class APIError(Exception): """Base exception for all API errors.""" @@ -116,6 +156,7 @@ class Client(object): 'density_day': 'density/%(day)s/%(lat)s,%(lon)s.json', 'density_hour': 'density/%(day)s/%(hour)s/%(lat)s,%(lon)s.json', 'layer': 'layer/%(layer)s.json', + 'new_layer': 'layers/%(layer)s.json', 'contains' : 'contains/%(lat)s,%(lon)s.json', 'overlaps' : 'overlaps/%(south)s,%(west)s,%(north)s,%(east)s.json', 'boundary' : 'boundary/%(id)s.json', @@ -204,7 +245,7 @@ def get_layer(self, layer): return self._request(endpoint, "GET") def create_layer(self, layer): - endpoint = self.endpoint('layer', layer=layer.name) + endpoint = self.endpoint('new_layer', layer=layer.name) return self._request(endpoint, "PUT", layer.to_json()) def get_density(self, lat, lon, day, hour=None): From 748c4f340ed6b58438a35596d93e6b922b34babc Mon Sep 17 00:00:00 2001 From: Roger Hoover Date: Fri, 15 Apr 2011 15:12:14 -0700 Subject: [PATCH 4/5] Back ported get_layers API --- simplegeo/__init__.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/simplegeo/__init__.py b/simplegeo/__init__.py index 9088dc3..4b5b6ac 100644 --- a/simplegeo/__init__.py +++ b/simplegeo/__init__.py @@ -157,6 +157,7 @@ class Client(object): 'density_hour': 'density/%(day)s/%(hour)s/%(lat)s,%(lon)s.json', 'layer': 'layer/%(layer)s.json', 'new_layer': 'layers/%(layer)s.json', + 'layers': 'layers.json', 'contains' : 'contains/%(lat)s,%(lon)s.json', 'overlaps' : 'overlaps/%(south)s,%(west)s,%(north)s,%(east)s.json', 'boundary' : 'boundary/%(id)s.json', @@ -244,6 +245,10 @@ def get_layer(self, layer): endpoint = self.endpoint('layer', layer=layer) return self._request(endpoint, "GET") + def get_layers(self): + endpoint = self.endpoint('layers') + return self._request(endpoint, "GET") + def create_layer(self, layer): endpoint = self.endpoint('new_layer', layer=layer.name) return self._request(endpoint, "PUT", layer.to_json()) From 52818ed43ef054c08dbe16dbb2f335959d1b0a3b Mon Sep 17 00:00:00 2001 From: Roger Hoover Date: Tue, 10 May 2011 15:55:36 -0700 Subject: [PATCH 5/5] Better response checking on errors --- simplegeo/twisted/client.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/simplegeo/twisted/client.py b/simplegeo/twisted/client.py index 4ee5c7a..96b4321 100644 --- a/simplegeo/twisted/client.py +++ b/simplegeo/twisted/client.py @@ -57,8 +57,10 @@ def _request(self, endpoint, method, data=None): code = str(response.code) message = body if isinstance(body, dict): - code = body['code'] - message = body['message'] + if 'code' in body: + code = body['code'] + if 'message' in body: + message = body['message'] raise simplegeo.APIError(code, message, response.headers)