From 6c8e3c2dc7b58c80bf413634042b583348ec8ed3 Mon Sep 17 00:00:00 2001 From: Daniel Pham Date: Sun, 2 Apr 2023 00:13:29 -0700 Subject: [PATCH 1/4] Minor update --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3d75ae9..995a0ef 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # 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 From a0e87f423358a8a020b40bea808f08156bef7df8 Mon Sep 17 00:00:00 2001 From: Daniel Pham Date: Sun, 2 Apr 2023 01:32:58 -0700 Subject: [PATCH 2/4] Working tests --- setup.cfg | 2 +- setup.py | 2 +- src/examplepy/__init__.py | 3 -- src/examplepy/module1.py | 22 --------------- src/exchangerate/__init__.py | 4 +++ src/exchangerate/client.py | 51 ++++++++++++++++++++++++++++++++++ src/exchangerate/config.py | 5 ++++ src/exchangerate/exceptions.py | 5 ++++ tests/test_client.py | 9 ++++++ tests/test_module1.py | 13 --------- 10 files changed, 76 insertions(+), 40 deletions(-) delete mode 100644 src/examplepy/__init__.py delete mode 100644 src/examplepy/module1.py create mode 100644 src/exchangerate/__init__.py create mode 100644 src/exchangerate/client.py create mode 100644 src/exchangerate/config.py create mode 100644 src/exchangerate/exceptions.py create mode 100644 tests/test_client.py delete mode 100644 tests/test_module1.py 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..126e6fa 100644 --- a/setup.py +++ b/setup.py @@ -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..36b41eb --- /dev/null +++ b/src/exchangerate/client.py @@ -0,0 +1,51 @@ +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() + + 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() From a04f4c551837bdec0e9f31e814fb832fac5b1307 Mon Sep 17 00:00:00 2001 From: Daniel Pham Date: Sun, 2 Apr 2023 08:25:16 -0700 Subject: [PATCH 3/4] Add symbol doc --- README.md | 25 +++++++++++++++++++++++-- setup.py | 2 +- src/exchangerate/client.py | 5 +++++ 3 files changed, 29 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 995a0ef..caba993 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,28 @@ This is unofficial https://exchangerate.host (https://github.com/Formicka/exchan # 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.py b/setup.py index 126e6fa..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', diff --git a/src/exchangerate/client.py b/src/exchangerate/client.py index 36b41eb..411c721 100644 --- a/src/exchangerate/client.py +++ b/src/exchangerate/client.py @@ -14,11 +14,16 @@ def __init__(self, base_currency="USD", region=Region.AMERICA): 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: From 8c7f210805e6067c5e17d5a5ff114715e7082d74 Mon Sep 17 00:00:00 2001 From: Daniel Pham Date: Sun, 2 Apr 2023 08:28:05 -0700 Subject: [PATCH 4/4] Fix missing python 3.6 in action --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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]