loaders: Add LoaderChain.

This commit is contained in:
Brett Smith 2017-05-12 07:40:27 -04:00
parent 10b0a818d7
commit 1927a18120
4 changed files with 115 additions and 5 deletions

View file

@ -1,4 +1,5 @@
import cgi
import functools
import io
import urllib.request
import urllib.parse
@ -19,6 +20,10 @@ class LoaderSourceError(LoaderError):
pass
class NoLoadersError(Exception):
pass
class FileCache:
def __init__(self, dir_path, filename_pattern):
self.dir_path = dir_path
@ -75,3 +80,32 @@ class OXRAPIRequest:
'historical/{}.json'.format(date.isoformat()),
{'app_id': self.app_id, 'base': base},
)
class LoaderChain:
def __init__(self):
self.loaders = []
def add_loader(self, loader):
self.loaders.append(loader)
def _wrap_load_method(orig_func):
@functools.wraps(orig_func)
def load_wrapper(self, *args, **kwargs):
self.used_loader = None
error = None
for loader in self.loaders:
try:
response = getattr(loader, orig_func.__name__)(*args, **kwargs)
except LoaderError as this_error:
error = this_error
else:
self.used_loader = loader
return response
else:
raise NoLoadersError() if error is None else error
return load_wrapper
@_wrap_load_method
def historical(self, date, base):
pass

View file

@ -1,6 +1,14 @@
import datetime
import pathlib
import random
import pytest
TEST_DIR = pathlib.Path(__file__).parent
def relpath(*parts):
return TEST_DIR / pathlib.Path(*parts)
@pytest.fixture
def any_date():
return datetime.date.today() - datetime.timedelta(days=730 - random.randint(0, 365))

71
tests/test_LoaderChain.py Normal file
View file

@ -0,0 +1,71 @@
import io
import pytest
import oxrlib.loaders
from . import any_date
SUCCESS_S = '"success"\n'
ERROR = oxrlib.loaders.LoaderNoDataError("test")
class FakeLoader:
def __init__(self, result):
self.result = result
def _respond(self, *args, **kwargs):
return io.StringIO(self.result)
def __getattr__(self, name):
return self._respond
class FakeErrorLoader(FakeLoader):
def __init__(self, error):
self.error = error
def _respond(self, *args, **kwargs):
raise self.error
@pytest.fixture
def lchain():
return oxrlib.loaders.LoaderChain()
@pytest.fixture
def good_loader():
return FakeLoader(SUCCESS_S)
@pytest.fixture
def error_loader():
return FakeErrorLoader(ERROR)
def test_no_loaders(lchain, any_date):
try:
lchain.historical(any_date, 'USD')
except oxrlib.loaders.NoLoadersError:
pass
else:
assert False, "expected NoLoadersError not raised"
def test_one_with_success(lchain, any_date, good_loader):
lchain.add_loader(good_loader)
response = lchain.historical(any_date, 'USD')
assert response.read(32) == SUCCESS_S
def test_two_with_success(lchain, any_date, good_loader, error_loader):
lchain.add_loader(error_loader)
lchain.add_loader(good_loader)
response = lchain.historical(any_date, 'USD')
assert response.read(32) == SUCCESS_S
@pytest.mark.parametrize('count', [1, 2])
def test_no_success(lchain, any_date, error_loader, count):
for _ in range(count):
lchain.add_loader(error_loader)
try:
lchain.historical(any_date, 'USD')
except type(ERROR) as error:
assert error is ERROR
else:
assert False, "{} not raised".format(type(ERROR).__name__)

View file

@ -1,4 +1,3 @@
import datetime
import http.client
import io
import json
@ -10,6 +9,8 @@ import urllib.parse
import pytest
import oxrlib.loaders
from . import any_date
APPID_CHARS = string.ascii_letters + string.digits
RANDOM_APPID = ''.join(random.choice(APPID_CHARS) for _ in range(32))
API_ROOT = 'http://[100::]/oxrlibtest/'
@ -67,10 +68,6 @@ class FakeOpener:
def api_client():
return oxrlib.loaders.OXRAPIRequest(RANDOM_APPID, API_ROOT)
@pytest.fixture
def any_date():
return datetime.date.today() - datetime.timedelta(days=730 - random.randint(0, 365))
@pytest.mark.parametrize('base', ['USD', 'JPY'])
def test_success(api_client, any_date, base):
body = "Good Test"