diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 7be9344..f5fedbf 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -12,7 +12,7 @@ on: jobs: build: - runs-on: ubuntu-latest + runs-on: ubuntu-20.04 strategy: matrix: python: [3.6, 3.7, 3.8, 3.9] diff --git a/README.md b/README.md index 3d75ae9..caba993 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,31 @@ # Introduction -This is unofficial https://exchangerate.host python client library +This is unofficial https://exchangerate.host (https://github.com/Formicka/exchangerate.host) python client library # Getting started ## Installation +- Using pip `pip install exchangerate-client -## Sample usage +## Usage +- Get all currency symbols +``` +import exchangerate +client = exchangerate.ExchangerateClient() +print(client.symbols()) +``` -# Development guide \ No newline at end of file +## Configuration +- + +# Development guide +## Testing +This package uses `tox` to run testing automation against multiple python versions, to install and run tox, use + +``` +pip install tox +tox +``` + +## Local development +- Install to local env with `pip install --editable .` +- Then this will work `python -c "import exchangerate"` diff --git a/setup.cfg b/setup.cfg index 040b134..e99dc46 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,3 +1,3 @@ [metadata] -version = attr: examplepy.__version__ +version = attr: exchangerate.__version__ license_files = LICENSE diff --git a/setup.py b/setup.py index 819bc7c..8d2857b 100644 --- a/setup.py +++ b/setup.py @@ -4,7 +4,7 @@ long_description = fh.read() setuptools.setup( - name='exchangerate-python', + name='exchangerate-client', author='Daniel Pham', author_email='tdpham1105@yahoo.com', description='Unofficial exchangerate.host python client library', @@ -39,7 +39,7 @@ 'Operating System :: OS Independent', ], python_requires='>=3.6', - # install_requires=['Pillow'], + install_requires=['requests'], extras_require={ 'dev': ['check-manifest'], # 'test': ['coverage'], diff --git a/src/examplepy/__init__.py b/src/examplepy/__init__.py deleted file mode 100644 index ae6f1d7..0000000 --- a/src/examplepy/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -__version__ = "0.1.0" - -from .module1 import * diff --git a/src/examplepy/module1.py b/src/examplepy/module1.py deleted file mode 100644 index f85a53b..0000000 --- a/src/examplepy/module1.py +++ /dev/null @@ -1,22 +0,0 @@ -# Example PyPI (Python Package Index) Package - -class Number(object): - - def __init__(self, n): - self.value = n - - def val(self): - return self.value - - def add(self, n2): - self.value += n2.val() - - def __add__(self, n2): - return self.__class__(self.value + n2.val()) - - def __str__(self): - return str(self.val()) - - @classmethod - def addall(cls, number_obj_iter): - cls(sum(n.val() for n in number_obj_iter)) diff --git a/src/exchangerate/__init__.py b/src/exchangerate/__init__.py new file mode 100644 index 0000000..bd93acb --- /dev/null +++ b/src/exchangerate/__init__.py @@ -0,0 +1,4 @@ +__version__ = "0.1.0" + +from .config import Region +from .client import ExchangerateClient diff --git a/src/exchangerate/client.py b/src/exchangerate/client.py new file mode 100644 index 0000000..411c721 --- /dev/null +++ b/src/exchangerate/client.py @@ -0,0 +1,56 @@ +import requests +from collections import namedtuple +from urllib.parse import urlencode, urlunparse + +from .config import Region +from .exceptions import * + +class ExchangerateClient: + """ + Primary client class + """ + def __init__(self, base_currency="USD", region=Region.AMERICA): + self.base_currency = base_currency + self.region = region + self.session = requests.Session() + + # ------------------------------------------------------------------- + # Public methods + # ------------------------------------------------------------------- + + def symbols(self): + url = self._build_url(path="symbols") + resp_json = self._validate_and_get_json(url) + return resp_json.get("rates") + + # ------------------------------------------------------------------- + def _validate_and_get_json(self, url): + resp = self.session.get(url) + if resp.status_code != 200: + raise ResponseErrorException("Status code=%d calling url=%s" % (resp.status_code, url)) + + resp_json = resp.json() + if not resp_json.get("success", False): + raise ResponseErrorException("No success field calling url=%s" % (url)) + + return resp_json + + def _build_url(self, path="", params=None): + Components = namedtuple( + typename='Components', + field_names=['scheme', 'netloc', 'url', 'path', 'query', 'fragment'] + ) + + if not params: + params = {} + + return urlunparse( + Components( + scheme='https', + netloc=self.region.value, + query=urlencode(params), + path=path, + url="/", + fragment="" + ) + ) diff --git a/src/exchangerate/config.py b/src/exchangerate/config.py new file mode 100644 index 0000000..ea87128 --- /dev/null +++ b/src/exchangerate/config.py @@ -0,0 +1,5 @@ +from enum import Enum + +class Region(Enum): + EUROPE = "api.exchangerate.host" + AMERICA = "api-us.exchangerate.host" diff --git a/src/exchangerate/exceptions.py b/src/exchangerate/exceptions.py new file mode 100644 index 0000000..227c78d --- /dev/null +++ b/src/exchangerate/exceptions.py @@ -0,0 +1,5 @@ +class ExchangerateException(Exception): + pass + +class ResponseErrorException(ExchangerateException): + pass diff --git a/tests/test_client.py b/tests/test_client.py new file mode 100644 index 0000000..5bc2cc2 --- /dev/null +++ b/tests/test_client.py @@ -0,0 +1,9 @@ +from exchangerate.client import ExchangerateClient + +def test_get_symbols(): + client = ExchangerateClient() + all_symbols = client.symbols() + + assert "USD" in all_symbols + assert "CAD" in all_symbols + assert "AUD" in all_symbols diff --git a/tests/test_module1.py b/tests/test_module1.py deleted file mode 100644 index d3aeede..0000000 --- a/tests/test_module1.py +++ /dev/null @@ -1,13 +0,0 @@ -import unittest - -from examplepy.module1 import Number - - -class TestSimple(unittest.TestCase): - - def test_add(self): - self.assertEqual((Number(5) + Number(6)).value, 11) - - -if __name__ == '__main__': - unittest.main()