Commit ef1e42c6 authored by Joshua Roesslein's avatar Joshua Roesslein
Browse files

Merge pull request #220 from inactivist/geo-models

Place model support and geo API mods to support Places
parents 517031b2 5f4c71fb
......@@ -294,9 +294,19 @@ class TweepyAPITests(unittest.TestCase):
self.api.trends_weekly()
def testgeoapis(self):
self.api.geo_id(id='c3f37afa9efcf94b') # Austin, TX, USA
self.api.nearby_places(lat=30.267370168467806, long=-97.74261474609375) # Austin, TX, USA
self.api.reverse_geocode(lat=30.267370168467806, long=-97.74261474609375) # Austin, TX, USA
def place_name_in_list(place_name, place_list):
"""Return True if a given place_name is in place_list."""
return any([x.full_name.lower() == place_name.lower() for x in place_list])
twitter_hq = self.api.geo_similar_places(lat=37, long= -122, name='Twitter HQ')
# Assumes that twitter_hq is first Place returned...
self.assertEqual(twitter_hq[0].id, '3bdf30ed8b201f31')
# Test various API functions using Austin, TX, USA
self.assertEqual(self.api.geo_id(id='c3f37afa9efcf94b').full_name, 'Austin, TX')
self.assertTrue(place_name_in_list('Austin, TX',
self.api.nearby_places(lat=30.267370168467806, long= -97.74261474609375))) # Austin, TX, USA
self.assertTrue(place_name_in_list('Austin, TX',
self.api.reverse_geocode(lat=30.267370168467806, long= -97.74261474609375))) # Austin, TX, USA
class TweepyCursorTests(unittest.TestCase):
......
......@@ -702,7 +702,7 @@ class API(object):
""" geo/reverse_geocode """
reverse_geocode = bind_api(
path = '/geo/reverse_geocode.json',
payload_type = 'json',
payload_type = 'place', payload_list = True,
allowed_param = ['lat', 'long', 'accuracy', 'granularity', 'max_results']
)
......@@ -710,24 +710,31 @@ class API(object):
# listed as deprecated on twitter's API documents
nearby_places = bind_api(
path = '/geo/nearby_places.json',
payload_type = 'json',
payload_type = 'place', payload_list = True,
allowed_param = ['lat', 'long', 'ip', 'accuracy', 'granularity', 'max_results']
)
""" geo/id """
geo_id = bind_api(
path = '/geo/id/{id}.json',
payload_type = 'json',
payload_type = 'place',
allowed_param = ['id']
)
""" geo/search """
geo_search = bind_api(
path = '/geo/search.json',
payload_type = 'json',
payload_type = 'place', payload_list = True,
allowed_param = ['lat', 'long', 'query', 'ip', 'granularity', 'accuracy', 'max_results', 'contained_within']
)
""" geo/similar_places """
geo_similar_places = bind_api(
path = '/geo/similar_places.json',
payload_type = 'place', payload_list = True,
allowed_param = ['lat', 'long', 'name', 'contained_within']
)
""" Internal use only """
@staticmethod
def _pack_image(filename, max_size):
......
......@@ -62,6 +62,11 @@ class Status(Model):
setattr(status, 'source_url', None)
elif k == 'retweeted_status':
setattr(status, k, Status.parse(api, v))
elif k == 'place':
if v is not None:
setattr(status, k, Place.parse(api, v))
else:
setattr(status, k, None)
else:
setattr(status, k, v)
return status
......@@ -321,6 +326,70 @@ class IDModel(Model):
return json['ids']
class BoundingBox(Model):
@classmethod
def parse(cls, api, json):
result = cls(api)
if json is not None:
for k, v in json.items():
setattr(result, k, v)
return result
def origin(self):
"""
Return longitude, latitude of southwest (bottom, left) corner of
bounding box, as a tuple.
This assumes that bounding box is always a rectangle, which
appears to be the case at present.
"""
return tuple(self.coordinates[0][0])
def corner(self):
"""
Return longitude, latitude of northeast (top, right) corner of
bounding box, as a tuple.
This assumes that bounding box is always a rectangle, which
appears to be the case at present.
"""
return tuple(self.coordinates[0][2])
class Place(Model):
@classmethod
def parse(cls, api, json):
place = cls(api)
for k, v in json.items():
if k == 'bounding_box':
# bounding_box value may be null (None.)
# Example: "United States" (id=96683cc9126741d1)
if v is not None:
t = BoundingBox.parse(api, v)
else:
t = v
setattr(place, k, t)
elif k == 'contained_within':
# contained_within is a list of Places.
setattr(place, k, Place.parse_list(api, v))
else:
setattr(place, k, v)
return place
@classmethod
def parse_list(cls, api, json_list):
if isinstance(json_list, list):
item_list = json_list
else:
item_list = json_list['result']['places']
results = ResultSet()
for obj in item_list:
results.append(cls.parse(api, obj))
return results
class ModelFactory(object):
"""
Used by parsers for creating instances
......@@ -340,4 +409,6 @@ class ModelFactory(object):
json = JSONModel
ids = IDModel
place = Place
bounding_box = BoundingBox
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment