Skip to content

Commit

Permalink
Merge pull request #55 from gadventures/checkins
Browse files Browse the repository at this point in the history
Allow id and uri overrides for unconventional resources like auth tokens.
  • Loading branch information
bartek committed Oct 19, 2016
2 parents cb43160 + 3ddc431 commit 05aa5d7
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 29 deletions.
2 changes: 1 addition & 1 deletion gapipy/models/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ def _set_resource_collection_field(self, field, value):
# FIXME: variation_id is hardcoded all over the client. This should
# not be the case, but is a neccessity for now.
parent = (
self._resource_name,
self._uri,
self.id,
getattr(self, 'variation_id', None),
)
Expand Down
6 changes: 3 additions & 3 deletions gapipy/query.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ def get_resource_data(self, resource_id, variation_id=None, cached=True):
return resource_data

# Cache miss; get fresh data from the backend.
requestor = APIRequestor(self._client, self.resource._resource_name)
requestor = APIRequestor(self._client, self.resource)
out = requestor.get(resource_id, variation_id=variation_id)
self._filters = {}
return out
Expand Down Expand Up @@ -116,7 +116,7 @@ def all(self, limit=None):

requestor = APIRequestor(
self._client,
self.resource._resource_name,
self.resource,
params=self._filters,
parent=self.parent
)
Expand Down Expand Up @@ -147,7 +147,7 @@ def count(self):

requestor = APIRequestor(
self._client,
self.resource._resource_name,
self.resource,
params=self._filters,
parent=self.parent
)
Expand Down
34 changes: 20 additions & 14 deletions gapipy/request.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,11 @@ def _make_call(self, method, url, headers, data, params):
response.reason = response.text
return response.raise_for_status()

def _get_uri(self):
if self.resource._uri:
return self.resource._uri
return self.resource._resource_name

def get(self, resource_id=None, uri=None, variation_id=None):
"""
Get a single resource with the given resource_id or uri
Expand All @@ -95,10 +100,10 @@ def get(self, resource_id=None, uri=None, variation_id=None):
raise ValueError(
'Need to provide at least one of `resource_id` or `uri` as argument')
if not uri:
components = ['', self.resource, str(resource_id)]
if variation_id:
components.append(str(variation_id))
uri = '/'.join(components)
components = ['', self._get_uri(), str(resource_id)]
if variation_id:
components.append(str(variation_id))
uri = '/'.join(components)
return self._request(uri, 'GET')

def update(self, resource_id, data, partial=True, uri=None):
Expand All @@ -110,40 +115,41 @@ def update(self, resource_id, data, partial=True, uri=None):
"""
method = 'PATCH' if partial else 'PUT'
if not uri:
uri = '/{0}/{1}'.format(self.resource, resource_id)
uri = '/{0}/{1}'.format(self._get_uri(), resource_id)
return self._request(uri, method, data=data)

def create(self, data, uri=None):
"""
Create a single new resource with the given data.
"""
if not uri:
uri = '/{0}'.format(self.resource)
uri = '/{0}'.format(self._get_uri())
return self._request(uri, 'POST', data=data)

def list_raw(self, uri=None):
"""Return the raw response for listing resources.
If `uri` is given, make a GET request to it, otherwise build the uri
from `self.resource` and `self.parent`. Note that only the first page
of results will be returned. To get an iterator over all resources,
use `list`.
If `uri` is given, make a GET request to it; otherwise build the uri
from `self.resource._uri`(if present) and `self.parent`; else
`self.resource._resource_name` and `self.parent`. Note that only the
first page of results will be returned. To get an iterator over all
resources, use `list`.
"""
if not uri:
if self.parent:
parent_name, parent_id, parent_variation_id = self.parent
parent_uri, parent_id, parent_variation_id = self.parent

# First slash ensures leading slash.
parts = [parent_name, parent_id]
parts = [parent_uri, parent_id]
if parent_variation_id:
parts.append(parent_variation_id)

parts.append(self.resource)
parts.append(self._get_uri())

# Ensure leading slash.
uri = '/' + '/'.join(parts)
else:
uri = '/{0}'.format(self.resource)
uri = '/{0}'.format(self._get_uri())

return self._request(uri, 'GET', params=self.params)

Expand Down
10 changes: 6 additions & 4 deletions gapipy/resources/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,12 @@ class Resource(BaseModel):
_resource_name = None
_is_parent_resource = False
_is_listable = True # True if resource can be listed/queried (i.e /{resource_name} is an endpoint)
_uri = None

def __init__(self, data, stub=False, client=None):
self.is_stub = stub
if not self._uri:
self._uri = self._resource_name
super(Resource, self).__init__(data, client)

def fetch(self):
Expand All @@ -30,12 +33,11 @@ def fetch(self):
variation_id=getattr(self, 'variation_id', None))
if resource_obj:
self._fill_fields(resource_obj._raw_data)

return self

@classmethod
def create(cls, client, data_dict):
request = APIRequestor(client, cls._resource_name)
request = APIRequestor(client, cls)
response = request.create(json.dumps(data_dict))
return cls(response, client=client)

Expand Down Expand Up @@ -72,7 +74,7 @@ def to_json(self):
return json.dumps(self.to_dict())

def _update(self, partial=False):
request = APIRequestor(self._client, self._resource_name)
request = APIRequestor(self._client, self)

data = self.to_dict()
if partial:
Expand All @@ -81,7 +83,7 @@ def _update(self, partial=False):
return request.update(self.id, json.dumps(data), partial=partial)

def _create(self):
request = APIRequestor(self._client, self._resource_name)
request = APIRequestor(self._client, self)
return request.create(self.to_json())

def save(self, partial=False):
Expand Down
20 changes: 13 additions & 7 deletions tests/test_request.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,39 +8,45 @@
from .fixtures import FIRST_PAGE_LIST_DATA, SECOND_PAGE_LIST_DATA


class Resources(object):
def __init__(self, **kwArgs):
self.__dict__.update(kwArgs)


@patch('gapipy.request.APIRequestor._request')
class APIRequestorTestCase(unittest.TestCase):

def setUp(self):
self.client = Client()
self.resources = Resources(_resource_name='resources', _uri=None)

def test_get_resource_by_id(self, mock_request):
requestor = APIRequestor(self.client, 'resources')
requestor = APIRequestor(self.client, self.resources)
requestor.get(1234)
mock_request.assert_called_once_with('/resources/1234', 'GET')

def test_get_with_null_resource_id_and_uri_raises_error(self, mock_request):
requestor = APIRequestor(self.client, 'resources')
requestor = APIRequestor(self.client, self.resources)
error_msg = 'Need to provide at least one of `resource_id` or `uri` as argument'
with self.assertRaisesRegexp(ValueError, error_msg):
requestor.get()

def test_get_with_falsy_resource_id_does_not_raise_error(self, mock_request):
requestor = APIRequestor(self.client, 'resources')
requestor = APIRequestor(self.client, self.resources)
requestor.get(0)
mock_request.assert_called_once_with('/resources/0', 'GET')

def test_list_resource(self, mock_request):
requestor = APIRequestor(self.client, 'resources')
requestor = APIRequestor(self.client, self.resources)
requestor.list_raw()
mock_request.assert_called_once_with('/resources', 'GET', params=None)

def test_list_resource_with_parent(self, mock_request):
parent = ('parent', '1234', None)
requestor = APIRequestor(self.client, 'child', parent=parent)
requestor = APIRequestor(self.client, self.resources, parent=parent)
requestor.list_raw()
mock_request.assert_called_once_with(
'/parent/1234/child', 'GET', params=None)
'/parent/1234/resources', 'GET', params=None)

@patch('gapipy.request.APIRequestor.list_raw')
def test_list_generator(self, mock_list, mock_request):
Expand All @@ -50,7 +56,7 @@ def test_list_generator(self, mock_list, mock_request):
call('http://localhost:5000/resources/?page=2'),
]

requestor = APIRequestor(self.client, 'resources')
requestor = APIRequestor(self.client, self.resources)
resources = list(requestor.list())

self.assertEqual(mock_list.mock_calls, expected_calls)
Expand Down

0 comments on commit 05aa5d7

Please sign in to comment.