Skip to content

Commit

Permalink
subresource testing
Browse files Browse the repository at this point in the history
  • Loading branch information
GregHilmes committed Jul 23, 2018
1 parent 5752b67 commit 71aac46
Show file tree
Hide file tree
Showing 8 changed files with 95 additions and 89 deletions.
38 changes: 9 additions & 29 deletions pokebase/api.py
Expand Up @@ -2,13 +2,13 @@

import requests

from .common import BASE_URL, ENDPOINTS, api_url_build, sprite_url_build, subresource_url_build
from .cache import save, load, save_sprite, load_sprite, get_sprite_path, save_subresource, load_subresource
from .common import BASE_URL, ENDPOINTS, api_url_build, sprite_url_build
from .cache import save, load, save_sprite, load_sprite, get_sprite_path


def _call_api(endpoint, resource_id=None):
def _call_api(endpoint, resource_id=None, subresource=None):

url = api_url_build(endpoint, resource_id)
url = api_url_build(endpoint, resource_id, subresource)

# Get a list of resources at the endpoint, if no resource_id is given.
get_endpoint_list = resource_id is None
Expand All @@ -31,17 +31,17 @@ def _call_api(endpoint, resource_id=None):
return data


def get_data(endpoint, resource_id=None, force_lookup=False):
def get_data(endpoint, resource_id=None, subresource=None, **kwargs):

if not force_lookup:
if not kwargs.get('force_lookup', False):
try:
data = load(endpoint, resource_id)
data = load(endpoint, resource_id, subresource)
return data
except KeyError:
pass

data = _call_api(endpoint, resource_id)
save(data, endpoint, resource_id)
data = _call_api(endpoint, resource_id, subresource)
save(data, endpoint, resource_id, subresource)

return data

Expand Down Expand Up @@ -72,23 +72,3 @@ def get_sprite(sprite_type, sprite_id, **kwargs):
save_sprite(data, sprite_type, sprite_id, **kwargs)

return data


def get_encounters(endpoint, resource_id, subresource, **kwargs):

if not kwargs.get('force_lookup', False):
try:
data = load_subresource(endpoint, resource_id, subresource)
return data
except KeyError:
pass

url = subresource_url_build(endpoint, resource_id, subresource)

response = requests.get(url)
response.raise_for_status()

data = response.json()
save_subresource(data, endpoint, resource_id, subresource)

return data
42 changes: 6 additions & 36 deletions pokebase/cache.py
Expand Up @@ -3,23 +3,23 @@
import os
import shelve

from .common import cache_uri_build, sprite_filepath_build, subresource_cache_uri_build
from .common import cache_uri_build, sprite_filepath_build

# Cache locations will be set at the end of this file.
CACHE_DIR = None
API_CACHE = None
SPRITE_CACHE = None


def save(data, endpoint, resource_id=None):
def save(data, endpoint, resource_id=None, subresource=None):

if data == dict(): # No point in saving empty data.
return None

if not isinstance(data, dict):
if not isinstance(data, (dict, list)):
raise ValueError('Could not save non-dict data')

uri = cache_uri_build(endpoint, resource_id)
uri = cache_uri_build(endpoint, resource_id, subresource)

try:
with shelve.open(API_CACHE) as cache:
Expand Down Expand Up @@ -48,9 +48,9 @@ def save_sprite(data, sprite_type, sprite_id, **kwargs):
return None


def load(endpoint, resource_id=None):
def load(endpoint, resource_id=None, subresource=None):

uri = cache_uri_build(endpoint, resource_id)
uri = cache_uri_build(endpoint, resource_id, subresource)

try:
with shelve.open(API_CACHE) as cache:
Expand Down Expand Up @@ -143,33 +143,3 @@ def set_cache(new_path=None):


CACHE_DIR, API_CACHE, SPRITE_CACHE = set_cache()


def save_subresource(data, endpoint, resource_id, subresource):

uri = subresource_cache_uri_build(endpoint, resource_id, subresource)

with shelve.open(API_CACHE) as cache:
cache[uri] = data

return None


def load_subresource(endpoint, resource_id, subresource):

uri = subresource_cache_uri_build(endpoint, resource_id, subresource)

print('getting cached')

try:
with shelve.open(API_CACHE) as cache:
data = cache[uri]
except OSError as error:
if error.errno == 11:
# Cache open by another person/program
# print('Cache unavailable, skipping load')
raise KeyError('Cache could not be opened.')
else:
raise

return data
32 changes: 12 additions & 20 deletions pokebase/common.py
Expand Up @@ -33,26 +33,30 @@ def validate(endpoint, resource_id=None):
return None


def api_url_build(endpoint, resource_id=None):
def api_url_build(endpoint, resource_id=None, subresource=None):

validate(endpoint, resource_id)

if resource_id is not None:
url = '/'.join([BASE_URL, endpoint,str(resource_id), ''])
else:
url = '/'.join([BASE_URL, endpoint, ''])
if subresource is not None:
return '/'.join([BASE_URL, endpoint, str(resource_id), subresource, ''])

return url
return '/'.join([BASE_URL, endpoint, str(resource_id), ''])

return '/'.join([BASE_URL, endpoint, ''])


def cache_uri_build(endpoint, resource_id):
def cache_uri_build(endpoint, resource_id=None, subresource=None):

validate(endpoint, resource_id)

if resource_id is not None:
if subresource is not None:
return '/'.join([endpoint, str(resource_id), subresource, ''])

return '/'.join([endpoint, str(resource_id), ''])
else:
return '/'.join([endpoint, ''])

return '/'.join([endpoint, ''])


def sprite_url_build(sprite_type, sprite_id, **kwargs):
Expand All @@ -65,18 +69,6 @@ def sprite_url_build(sprite_type, sprite_id, **kwargs):
return url


def subresource_url_build(endpoint, resource_id, subresource):

url = '/'.join([BASE_URL, endpoint, resource_id, subresource])
return url


def subresource_cache_uri_build(endpoint, resource_id, subresource):

uri = '/'.join([endpoint, resource_id, subresource])
return uri


def sprite_filepath_build(sprite_type, sprite_id, **kwargs):
"""returns the filepath of the sprite *relative to SPRITE_CACHE*"""

Expand Down
9 changes: 5 additions & 4 deletions pokebase/interface.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-

from .api import get_data, get_sprite, get_encounters
from .api import get_data, get_sprite
from .common import BASE_URL, api_url_build, sprite_url_build


Expand Down Expand Up @@ -133,16 +133,17 @@ def _load(self):
:return None
"""

data = get_data(self.endpoint, self.id_, self.__force_lookup)
data = get_data(self.endpoint, self.id_, force_lookup=self.__force_lookup)

# Make our custom objects from the data.
for key, val in data.items():

if key == 'location_area_encounters' \
and self.endpoint == 'pokemon':

params = val.split('/')[-3:len(val)]
encounters = get_encounters(*params)
params = val.split('/')[-3:]
ep, id_, subr = params
encounters = get_data(ep, int(id_), subr)
data[key] = [_make_obj(enc) for enc in encounters]
continue

Expand Down
18 changes: 18 additions & 0 deletions tests/test_module_api.py
Expand Up @@ -46,6 +46,15 @@ def testArg_resource_id_None(self, mock_get, endpoint, resource_id):

self.assertIsNotNone(api._call_api(endpoint, resource_id).get('count'))

@given(endpoint=sampled_from(ENDPOINTS),
resource_id=integers(min_value=1),
subresource=text())
@patch('pokebase.api.requests.get')
def testArg_subresource_Text(self, mock_get, endpoint, resource_id, subresource):
mock_get.return_value.json.return_value = {'version_details': 'foo'}

self.assertIsNotNone(api._call_api(endpoint, resource_id, subresource).get('version_details'))

@given(endpoint=sampled_from(ENDPOINTS),
resource_id=(integers(min_value=1)))
@patch('pokebase.api.requests.get')
Expand Down Expand Up @@ -88,6 +97,15 @@ def testArgs_GettingNoncachedData(self, mock_get, data, endpoint, resource_id):

self.assertEqual(data, api.get_data(endpoint, resource_id))

@given(endpoint=sampled_from(ENDPOINTS),
resource_id=integers(min_value=1),
subresource=text())
@patch('pokebase.api.requests.get')
def testArg_subresource_Text(self, mock_get, endpoint, resource_id, subresource):
mock_get.return_value.json.return_value = {'version_details': 'foo'}

self.assertIsNotNone(api.get_data(endpoint, resource_id, subresource).get('version_details'))

@given(endpoint=text(),
resource_id=integers(min_value=1))
def testArg_endpoint_Text(self, endpoint, resource_id):
Expand Down
16 changes: 16 additions & 0 deletions tests/test_module_cache.py
Expand Up @@ -48,6 +48,13 @@ def testArg_resource_id_Text(self, data, endpoint, resource_id):
with self.assertRaises(ValueError):
cache.save(data, endpoint, resource_id)

@given(data=dictionaries(text(), text()),
endpoint=sampled_from(ENDPOINTS),
resource_id=integers(min_value=1),
subresource=text())
def testArg_subresource_Text(self, data, endpoint, resource_id, subresource):
self.assertIsNone(cache.save(data, endpoint, resource_id, subresource))

@given(data=dictionaries(text(), text()),
endpoint=sampled_from(ENDPOINTS),
resource_id=integers(min_value=1))
Expand Down Expand Up @@ -92,6 +99,15 @@ def testArg_resource_id_Text(self, endpoint, resource_id):
with self.assertRaises(ValueError):
cache.load(endpoint, resource_id)

@given(data=dictionaries(text(), text()),
endpoint=sampled_from(ENDPOINTS),
resource_id=integers(min_value=1),
subresource=text())
def testArg_subresource_Text(self, data, endpoint, resource_id, subresource):
assume(data != dict())
cache.save(data, endpoint, resource_id, subresource)
self.assertEqual(data, cache.load(endpoint, resource_id, subresource))

@given(endpoint=sampled_from(ENDPOINTS),
resource_id=integers(min_value=1))
def testEnv_CacheFileNotFound(self, endpoint, resource_id):
Expand Down
15 changes: 15 additions & 0 deletions tests/test_module_common.py
Expand Up @@ -55,6 +55,14 @@ def testArg_endpoint_Text(self, endpoint, resource_id):
with self.assertRaises(ValueError):
common.api_url_build(endpoint, resource_id)

@given(endpoint=sampled_from(common.ENDPOINTS),
resource_id=integers(min_value=1),
subresource=text())
def testArg_subresource_Text(self, endpoint, resource_id, subresource):
self.assertEqual(common.api_url_build(endpoint, resource_id, subresource),
'http://pokeapi.co/api/v2/{}/{}/{}/'
.format(endpoint, resource_id, subresource))


class TestFunction_cache_uri_build(unittest.TestCase):

Expand All @@ -75,3 +83,10 @@ def testArg_resource_id_None(self, endpoint, resource_id):
def testArg_endpoint_Text(self, endpoint, resource_id):
with self.assertRaises(ValueError):
common.cache_uri_build(endpoint, resource_id)

@given(endpoint=sampled_from(common.ENDPOINTS),
resource_id=integers(min_value=1),
subresource=text())
def testArg_subresource_Text(self, endpoint, resource_id, subresource):
self.assertEqual(common.cache_uri_build(endpoint, resource_id, subresource),
'/'.join([endpoint, str(resource_id), subresource, '']))
14 changes: 14 additions & 0 deletions tests/test_module_interface.py
Expand Up @@ -224,6 +224,20 @@ def testArg_endpoint_Text(self, mock_get_data, endpoint, id_):
with self.assertRaises(ValueError):
interface.APIResource(endpoint, id_)

@given(id_=integers(min_value=1))
@patch('pokebase.interface.get_data')
def testHasLocationAreaEncounters(self, mock_get_data, id_):

mock_get_data.side_effect = [{'count': 1, 'results': [{'url': 'mocked.url/api/v2/pokemon/{}/'.format(id_), 'name': 'mocked name'}]},
{'location_area_encounters': '/api/v2/pokemon/{}/encounters'.format(id_)},
[{'version_details': [], 'location_area': {'url': 'mocked.url/api/v2/location-area/1/', 'name': 'mocked location_area'}}],
{'count': 1, 'results': [{'url': 'mocked.url/api/v2/location-area/1/', 'name': 'mocked name'}]}]
pkmn = interface.APIResource('pokemon', id_)
# Should be list or empty list
self.assertIsInstance(pkmn.location_area_encounters, list)
# would be str if it was not handled
self.assertNotIsInstance(pkmn.location_area_encounters, str)


class TestClass_APIResourceList(unittest.TestCase):

Expand Down

0 comments on commit 71aac46

Please sign in to comment.