Skip to content

Commit

Permalink
refactor client to use multiple inheritance
Browse files Browse the repository at this point in the history
  • Loading branch information
dinahshi committed Jan 4, 2016
1 parent c95ab06 commit 98e34b5
Show file tree
Hide file tree
Showing 8 changed files with 20 additions and 57 deletions.
11 changes: 1 addition & 10 deletions tests/client_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,6 @@ def setup_class(cls):
auth = mock.Mock()
cls.client = Client(auth)

def test_add_instance_methods(self):
methods = [
('_private', 'private_method'),
('public', 'public_method')
]
self.client._add_instance_methods(methods)
assert self.client.public == 'public_method'
assert not hasattr(self.client, '_private')

def test_make_connection_closes(self):
mock_conn = mock.Mock()
mock_conn.read.return_value = b'{}'
Expand Down Expand Up @@ -49,5 +40,5 @@ def test_make_request_calls_raise_error_on_HTTPError(self):

with mock.patch('six.moves.urllib.request.urlopen', side_effect=error):
with mock.patch('yelp.errors.ErrorHandler.raise_error') as r:
self.client._make_request("")
self.client.make_request("")
r.assert_called_once_with(error)
4 changes: 2 additions & 2 deletions tests/endpoint/business_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,14 @@ def setup_class(cls):
cls.client = Client(auth)

def test_get_business_builds_correct_params(self):
with mock.patch('yelp.client.Client._make_request') as request:
with mock.patch('yelp.client.BaseClient.make_request') as request:
request.return_value = '{}'
response = self.client.get_business('test-id')
request.assert_called_once_with('/v2/business/test-id', {})
assert type(response) is BusinessResponse

def test_get_business_builds_correct_params_with_lang(self):
with mock.patch('yelp.client.Client._make_request') as request:
with mock.patch('yelp.client.BaseClient.make_request') as request:
params = {'lang': 'fr'}
self.client.get_business('test-id', **params)
request.assert_called_once_with('/v2/business/test-id', params)
2 changes: 1 addition & 1 deletion tests/endpoint/phone_search_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ def setup_class(cls):
cls.client = Client(auth)

def test_phone_search_builds_correct_params(self):
with mock.patch('yelp.client.Client._make_request') as request:
with mock.patch('yelp.client.BaseClient.make_request') as request:
request.return_value = '{}'
params = {
'category': 'fashion'
Expand Down
8 changes: 4 additions & 4 deletions tests/endpoint/search_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ def setup_class(cls):
cls.client = Client(auth)

def test_search_builds_correct_params(self):
with mock.patch('yelp.client.Client._make_request') as request:
with mock.patch('yelp.client.BaseClient.make_request') as request:
request.return_value = '{}'
params = {
'term': 'food',
Expand All @@ -28,7 +28,7 @@ def test_search_builds_correct_params(self):
assert type(response) is SearchResponse

def test_search_builds_correct_params_with_current_lat_long(self):
with mock.patch('yelp.client.Client._make_request') as request:
with mock.patch('yelp.client.BaseClient.make_request') as request:
params = {
'term': 'food',
}
Expand All @@ -40,7 +40,7 @@ def test_search_builds_correct_params_with_current_lat_long(self):
request.assert_called_once_with('/v2/search/', params)

def test_search_by_bounding_box_builds_correct_params(self):
with mock.patch('yelp.client.Client._make_request') as request:
with mock.patch('yelp.client.BaseClient.make_request') as request:
params = {
'term': 'food',
}
Expand All @@ -49,6 +49,6 @@ def test_search_by_bounding_box_builds_correct_params(self):
request.assert_called_once_with('/v2/search/', params)

def test_search_by_coordinates_builds_correct_params(self):
with mock.patch('yelp.client.Client._make_request') as request:
with mock.patch('yelp.client.BaseClient.make_request') as request:
self.client.search_by_coordinates(0, 0, 0, 0, 0)
request.assert_called_once_with('/v2/search/', {'ll': '0,0,0,0,0'})
33 changes: 7 additions & 26 deletions yelp/client.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
# -*- coding: UTF-8 -*-
import inspect
import json

import six
Expand All @@ -11,35 +10,13 @@
from yelp.errors import ErrorHandler


class Client(object):

_endpoints = [
Business,
PhoneSearch,
Search
]
class BaseClient(object):

def __init__(self, authenticator):
self.authenticator = authenticator
self._error_handler = ErrorHandler()
self._define_request_methods()

# Creates an instance of each endpoint class and adds the instances' public
# singleton methods to Client. We do this to promote modularity.
def _define_request_methods(self):
endpoint_instances = [end(self) for end in self._endpoints]
for endpoint in endpoint_instances:
instance_methods = inspect.getmembers(endpoint, inspect.ismethod)
self._add_instance_methods(instance_methods)

def _add_instance_methods(self, instance_methods):
# instance_methods is a list of (name, value) tuples where value is the
# instance of the bound method
for method in instance_methods:
if method[0][0] is not '_':
self.__setattr__(method[0], method[1])

def _make_request(self, path, url_params={}):

def make_request(self, path, url_params={}):
url = 'https://{0}{1}?'.format(
API_HOST,
six.moves.urllib.parse.quote(path.encode('utf-8'))
Expand All @@ -58,3 +35,7 @@ def _make_connection(self, signed_url):
finally:
conn.close()
return response


class Client(BaseClient, Business, PhoneSearch, Search):
pass
5 changes: 1 addition & 4 deletions yelp/endpoint/business.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,6 @@

class Business(object):

def __init__(self, client):
self.client = client

def get_business(self, business_id, **url_params):
"""Make a request to the business endpoint. More info at
https://www.yelp.com/developers/documentation/v2/business
Expand All @@ -23,5 +20,5 @@ def get_business(self, business_id, **url_params):
"""
business_path = BUSINESS_PATH + business_id
return BusinessResponse(
self.client._make_request(business_path, url_params)
self.make_request(business_path, url_params)
)
5 changes: 1 addition & 4 deletions yelp/endpoint/phone_search.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,6 @@

class PhoneSearch(object):

def __init__(self, client):
self.client = client

def phone_search(self, phone, **url_params):
"""Make a request to the phone search endpoint.More info at
https://www.yelp.com/developers/documentation/v2/phone_search
Expand All @@ -24,5 +21,5 @@ def phone_search(self, phone, **url_params):
url_params['phone'] = phone

return SearchResponse(
self.client._make_request(PHONE_SEARCH_PATH, url_params)
self.make_request(PHONE_SEARCH_PATH, url_params)
)
9 changes: 3 additions & 6 deletions yelp/endpoint/search.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,6 @@

class Search(object):

def __init__(self, client):
self.client = client

def search(
self,
location,
Expand Down Expand Up @@ -41,7 +38,7 @@ def search(
)

return SearchResponse(
self.client._make_request(SEARCH_PATH, url_params)
self.make_request(SEARCH_PATH, url_params)
)

def search_by_bounding_box(
Expand Down Expand Up @@ -76,7 +73,7 @@ def search_by_bounding_box(
)

return SearchResponse(
self.client._make_request(SEARCH_PATH, url_params)
self.make_request(SEARCH_PATH, url_params)
)

def search_by_coordinates(
Expand Down Expand Up @@ -115,7 +112,7 @@ def search_by_coordinates(
)

return SearchResponse(
self.client._make_request(SEARCH_PATH, url_params)
self.make_request(SEARCH_PATH, url_params)
)

def _format_current_lat_long(self, lat, long):
Expand Down

0 comments on commit 98e34b5

Please sign in to comment.