From ae04984fee09f1f60a1ed5859eb5cd446a7fea69 Mon Sep 17 00:00:00 2001 From: Oli Girling Date: Thu, 28 Sep 2023 11:00:38 +0100 Subject: [PATCH] Update tests, makefile, readme --- .gitignore | 1 + Dockerfile | 4 +++- Makefile | 9 ++++++--- README.md | 8 ++++---- currencyapi/__init__.py | 2 +- currencyapi/client.py | 8 -------- currencyapi/currency.py | 24 ++++++++++++++++++++++++ currencyapi/endpoints/currencies.py | 5 ----- currencyapi/endpoints/endpoint.py | 6 +++++- index.py | 4 ---- run.py | 4 ++++ setup.py | 4 ++-- tests/endpoints/test_convert.py | 20 +++++++++++++++++++- tests/endpoints/test_currencies.py | 18 ++++++++++++------ tests/endpoints/test_endpoint.py | 16 ++++++++++++++++ tests/endpoints/test_history.py | 23 ++++++++++++++++++++++- tests/endpoints/test_rates.py | 20 ++++++++++++++++++-- tests/endpoints/test_timeframe.py | 24 +++++++++++++++++++++++- tests/test_client.py | 10 ---------- tests/test_currency.py | 28 ++++++++++++++++++++++++++++ 20 files changed, 188 insertions(+), 50 deletions(-) delete mode 100644 currencyapi/client.py create mode 100644 currencyapi/currency.py delete mode 100644 index.py create mode 100644 run.py delete mode 100644 tests/test_client.py create mode 100644 tests/test_currency.py diff --git a/.gitignore b/.gitignore index 8300b6c..6749d7b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ .DS_Store +.env # Byte-compiled / optimized / DLL files __pycache__/ diff --git a/Dockerfile b/Dockerfile index f8b152e..9108dfc 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,6 +3,8 @@ FROM python:3-alpine WORKDIR /app RUN pip install requests \ - coverage + coverage \ + twine \ + wheel COPY . . \ No newline at end of file diff --git a/Makefile b/Makefile index 838551f..2ea6442 100644 --- a/Makefile +++ b/Makefile @@ -13,7 +13,7 @@ test: ## Run the tests ${DOCKER_COMMAND} python -m coverage run -m unittest discover run: ## Run the sample testing file - ${DOCKER_COMMAND} python index.py + ${DOCKER_COMMAND} python run.py test-coverage: ## Show test coverage ${DOCKER_COMMAND} python -m coverage report @@ -24,8 +24,11 @@ setup: ## Setup exec: ## Run test file ${DOCKER_COMMAND} sh -publish: ## Publish version - ${DOCKER_COMMAND} npm publish +build-package: ## Build pip package + ${DOCKER_COMMAND} python setup.py sdist bdist_wheel + +upload-package: ## Upload pip package + ${DOCKER_COMMAND} python -m twine upload dist/* help: @grep -h -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}' diff --git a/README.md b/README.md index b3e95e4..3a849ea 100644 --- a/README.md +++ b/README.md @@ -23,8 +23,8 @@ Python wrapper for Currenc #### Prerequisites -- Minimum NodeJs v8 (npm v5 and above) -- Working on Python 3.x +- Minimum Python version 3.5 +- Last tested and working on Python 3.11.5 - Free or Paid account with CurrencyApi.net #### Test Coverage @@ -41,7 +41,7 @@ pip install currencyapi then import the package with: ```python -from currencyapi.client import Client +from currencyapi.currency import Currency ``` ## Usage @@ -49,7 +49,7 @@ from currencyapi.client import Client ### Instantiating ```python -currency = Client('API_KEY') +currency = Currency('API_KEY') ``` ### Live rates: diff --git a/currencyapi/__init__.py b/currencyapi/__init__.py index cfae4d3..7a43320 100644 --- a/currencyapi/__init__.py +++ b/currencyapi/__init__.py @@ -1 +1 @@ -from currencyapi.client import Client \ No newline at end of file +from currencyapi.currency import Currency \ No newline at end of file diff --git a/currencyapi/client.py b/currencyapi/client.py deleted file mode 100644 index 036cae8..0000000 --- a/currencyapi/client.py +++ /dev/null @@ -1,8 +0,0 @@ -from currencyapi.endpoints.rates import Rates - -class Client(object): - def __init__(self, api_key: str): - self._api_key = api_key - - def rates(self) -> Rates: - return Rates(self._api_key) diff --git a/currencyapi/currency.py b/currencyapi/currency.py new file mode 100644 index 0000000..45dcc0e --- /dev/null +++ b/currencyapi/currency.py @@ -0,0 +1,24 @@ +from currencyapi.endpoints.rates import Rates +from currencyapi.endpoints.convert import Convert +from currencyapi.endpoints.history import History +from currencyapi.endpoints.timeframe import Timeframe +from currencyapi.endpoints.currencies import Currencies + +class Currency(object): + def __init__(self, api_key: str): + self._api_key = api_key + + def rates(self) -> Rates: + return Rates(self._api_key) + + def convert(self) -> Convert: + return Convert(self._api_key) + + def history(self) -> History: + return History(self._api_key) + + def timeframe(self) -> Timeframe: + return Timeframe(self._api_key) + + def currencies(self) -> Currencies: + return Currencies(self._api_key) diff --git a/currencyapi/endpoints/currencies.py b/currencyapi/endpoints/currencies.py index 6e5e0b1..9e9a8f5 100644 --- a/currencyapi/endpoints/currencies.py +++ b/currencyapi/endpoints/currencies.py @@ -5,9 +5,4 @@ class Currencies(Endpoint): def __init__(self, api_key: str): super().__init__(api_key, CURRENCIES_ENDPOINT) - self._base() - - def base(self, currency: str): - self._base(currency) - return self diff --git a/currencyapi/endpoints/endpoint.py b/currencyapi/endpoints/endpoint.py index 501bfdd..f09c37c 100644 --- a/currencyapi/endpoints/endpoint.py +++ b/currencyapi/endpoints/endpoint.py @@ -36,10 +36,14 @@ def _headers(self): headers['X-Sdk'] = 'python' headers['Content-Type'] = content_type return headers + + def _build_url_params(self): + url_params = {'key': self.api_key} + return url_params | self.param def get(self): url = BASE_URL + self.endpoint - r = requests.get(url, params=self.param, headers=self._headers()) + r = requests.get(url, params=self._build_url_params(), headers=self._headers()) if self._isXml(): return r.text diff --git a/index.py b/index.py deleted file mode 100644 index 65a7c75..0000000 --- a/index.py +++ /dev/null @@ -1,4 +0,0 @@ -from currencyapi.client import Client - -c = Client('fake_api_key') -r = c.rates().get() \ No newline at end of file diff --git a/run.py b/run.py new file mode 100644 index 0000000..e8072ce --- /dev/null +++ b/run.py @@ -0,0 +1,4 @@ +from currencyapi.currency import Currency + +currency = Currency('') +print(currency.history().output('JSON').date('2013-01-02').get()) \ No newline at end of file diff --git a/setup.py b/setup.py index ec483a1..06e940a 100644 --- a/setup.py +++ b/setup.py @@ -7,7 +7,7 @@ name="currencyapi", version="1.0.0", packages=find_packages(exclude="tests"), - description="Python Client for CurrencyApi.net", + description="Python wrapper for CurrencyApi.net", long_description=README_MD, long_description_content_type="text/markdown", url="https://github.com/houseofapis/currencyapi-python", @@ -16,7 +16,7 @@ classifiers=[ "License :: OSI Approved :: MIT License", "Intended Audience :: Developers", - "Programming Language :: Python :: 3 :: Only" + "Programming Language :: Python :: 3 :: Only", "Topic :: Software Development :: Libraries :: Python Modules", ], install_requires=[ diff --git a/tests/endpoints/test_convert.py b/tests/endpoints/test_convert.py index 01a7f63..faf8f16 100644 --- a/tests/endpoints/test_convert.py +++ b/tests/endpoints/test_convert.py @@ -23,4 +23,22 @@ def test_convert_amount(self): self.assertIsInstance(self.class_under_test.amount(10), Convert) def test_history_endpoint_set(self): - self.assertEqual('convert', self.class_under_test.endpoint) \ No newline at end of file + self.assertEqual('convert', self.class_under_test.endpoint) + + def test_convert__build_url_params(self): + self.assertDictEqual( + {'key': 'fakekey', 'output': 'JSON'}, + self.class_under_test._build_url_params() + ) + self.class_under_test.output('xMl') + self.assertDictEqual( + {'key': 'fakekey', 'output': 'XML'}, + self.class_under_test._build_url_params() + ) + self.class_under_test.from_currency('gbP') + self.class_under_test.to_currency('uSd') + self.class_under_test.amount(10) + self.assertDictEqual( + {'key': 'fakekey', 'output': 'XML', 'from': 'GBP', 'to': 'USD', 'amount': 10}, + self.class_under_test._build_url_params() + ) \ No newline at end of file diff --git a/tests/endpoints/test_currencies.py b/tests/endpoints/test_currencies.py index 7cb15bc..e25f282 100644 --- a/tests/endpoints/test_currencies.py +++ b/tests/endpoints/test_currencies.py @@ -7,10 +7,16 @@ class Test(TestCase): def setUp(self): self.class_under_test = Currencies('fakekey') - def test_currencies_base(self): - self.class_under_test.base('gBp') - self.assertEqual('GBP', self.class_under_test.param.get('base')) - self.assertIsInstance(self.class_under_test.base('uSD'), Currencies) + def test_currencies_endpoint_set(self): + self.assertEqual('currencies', self.class_under_test.endpoint) - def test_rates_endpoint_set(self): - self.assertEqual('currencies', self.class_under_test.endpoint) \ No newline at end of file + def test_currencies__build_url_params(self): + self.assertDictEqual( + {'key': 'fakekey', 'output': 'JSON'}, + self.class_under_test._build_url_params() + ) + self.class_under_test.output('xMl') + self.assertDictEqual( + {'key': 'fakekey', 'output': 'XML'}, + self.class_under_test._build_url_params() + ) \ No newline at end of file diff --git a/tests/endpoints/test_endpoint.py b/tests/endpoints/test_endpoint.py index 585eded..61b6c90 100644 --- a/tests/endpoints/test_endpoint.py +++ b/tests/endpoints/test_endpoint.py @@ -64,4 +64,20 @@ def test_endpoint_get_xml(self, mock_requests_get): mock_data, self.class_under_test.get() ) + + def test_endpoint__build_url_params(self): + self.assertDictEqual( + {'key': 'fakekey', 'output': 'JSON'}, + self.class_under_test._build_url_params() + ) + self.class_under_test.output('xMl') + self.assertDictEqual( + {'key': 'fakekey', 'output': 'XML'}, + self.class_under_test._build_url_params() + ) + self.class_under_test._base('gbP') + self.assertDictEqual( + {'base': 'GBP', 'key': 'fakekey', 'output': 'XML'}, + self.class_under_test._build_url_params() + ) \ No newline at end of file diff --git a/tests/endpoints/test_history.py b/tests/endpoints/test_history.py index 9bdc9d9..5a98346 100644 --- a/tests/endpoints/test_history.py +++ b/tests/endpoints/test_history.py @@ -18,4 +18,25 @@ def test_history_date(self): self.assertIsInstance(self.class_under_test.date('2023-01-01'), History) def test_history_endpoint_set(self): - self.assertEqual('history', self.class_under_test.endpoint) \ No newline at end of file + self.assertEqual('history', self.class_under_test.endpoint) + + def test_history__build_url_params(self): + self.assertDictEqual( + {'key': 'fakekey', 'base': 'USD', 'output': 'JSON'}, + self.class_under_test._build_url_params() + ) + self.class_under_test.output('xMl') + self.assertDictEqual( + {'key': 'fakekey', 'base': 'USD', 'output': 'XML'}, + self.class_under_test._build_url_params() + ) + self.class_under_test.base('gbP') + self.assertDictEqual( + {'key': 'fakekey', 'base': 'GBP', 'output': 'XML'}, + self.class_under_test._build_url_params() + ) + self.class_under_test.date('2023-01-01') + self.assertDictEqual( + {'key': 'fakekey', 'base': 'GBP', 'date': '2023-01-01', 'output': 'XML'}, + self.class_under_test._build_url_params() + ) \ No newline at end of file diff --git a/tests/endpoints/test_rates.py b/tests/endpoints/test_rates.py index b8f5297..2529056 100644 --- a/tests/endpoints/test_rates.py +++ b/tests/endpoints/test_rates.py @@ -17,7 +17,7 @@ def test_rates_endpoint_set(self): self.assertEqual('rates', self.class_under_test.endpoint) @patch.object(requests, 'get') - def test_endpoint_get(self, mock_requests_get): + def test_rates_get(self, mock_requests_get): mock_data = [{"id": 1}, {"id": 2}] response_mock = Mock(return_value=mock_data) mock_requests_get.return_value.json = response_mock @@ -27,11 +27,27 @@ def test_endpoint_get(self, mock_requests_get): ) @patch.object(requests, 'get') - def test_endpoint_get_xml(self, mock_requests_get): + def test_rates_get_xml(self, mock_requests_get): self.class_under_test.output('xMl') mock_data = [{"id": 1}, {"id": 2}] mock_requests_get.return_value.text = mock_data self.assertEqual( mock_data, self.class_under_test.get() + ) + + def test_rates__build_url_params(self): + self.assertDictEqual( + {'base': 'USD', 'key': 'fakekey', 'output': 'JSON'}, + self.class_under_test._build_url_params() + ) + self.class_under_test.output('xMl') + self.assertDictEqual( + {'base': 'USD', 'key': 'fakekey', 'output': 'XML'}, + self.class_under_test._build_url_params() + ) + self.class_under_test.base('gbP') + self.assertDictEqual( + {'base': 'GBP', 'key': 'fakekey', 'output': 'XML'}, + self.class_under_test._build_url_params() ) \ No newline at end of file diff --git a/tests/endpoints/test_timeframe.py b/tests/endpoints/test_timeframe.py index ff56332..0bc129b 100644 --- a/tests/endpoints/test_timeframe.py +++ b/tests/endpoints/test_timeframe.py @@ -23,4 +23,26 @@ def test_timeframe_end_date(self): self.assertIsInstance(self.class_under_test.end_date('2023-01-02'), Timeframe) def test_history_endpoint_set(self): - self.assertEqual('timeframe', self.class_under_test.endpoint) \ No newline at end of file + self.assertEqual('timeframe', self.class_under_test.endpoint) + + def test_timeframe__build_url_params(self): + self.assertDictEqual( + {'base': 'USD', 'key': 'fakekey', 'output': 'JSON'}, + self.class_under_test._build_url_params() + ) + self.class_under_test.output('xMl') + self.assertDictEqual( + {'base': 'USD', 'key': 'fakekey', 'output': 'XML'}, + self.class_under_test._build_url_params() + ) + self.class_under_test.base('gbP') + self.assertDictEqual( + {'base': 'GBP', 'key': 'fakekey', 'output': 'XML'}, + self.class_under_test._build_url_params() + ) + self.class_under_test.start_date('2023-01-01') + self.class_under_test.end_date('2023-01-02') + self.assertDictEqual( + {'base': 'GBP', 'start_date': '2023-01-01', 'end_date': '2023-01-02', 'key': 'fakekey', 'output': 'XML'}, + self.class_under_test._build_url_params() + ) \ No newline at end of file diff --git a/tests/test_client.py b/tests/test_client.py deleted file mode 100644 index a8ea192..0000000 --- a/tests/test_client.py +++ /dev/null @@ -1,10 +0,0 @@ -import unittest - -from currencyapi import Client -from currencyapi.endpoints.rates import Rates - -class Test(unittest.TestCase): - def test_rates_method(self): - errorMessage = "Rates method does not return rates object" - class_under_test = Client('fakeKey') - self.assertIsInstance(class_under_test.rates(), Rates, errorMessage) \ No newline at end of file diff --git a/tests/test_currency.py b/tests/test_currency.py new file mode 100644 index 0000000..ea87225 --- /dev/null +++ b/tests/test_currency.py @@ -0,0 +1,28 @@ +from currencyapi import Currency +from currencyapi.endpoints.rates import Rates +from currencyapi.endpoints.history import History +from currencyapi.endpoints.timeframe import Timeframe +from currencyapi.endpoints.convert import Convert +from currencyapi.endpoints.currencies import Currencies +from unittest import TestCase + +class Test(TestCase): + def test_rates_method(self): + class_under_test = Currency('fakeKey') + self.assertIsInstance(class_under_test.rates(), Rates) + + def test_history_method(self): + class_under_test = Currency('fakeKey') + self.assertIsInstance(class_under_test.history(), History) + + def test_timeframe_method(self): + class_under_test = Currency('fakeKey') + self.assertIsInstance(class_under_test.timeframe(), Timeframe) + + def test_convert_method(self): + class_under_test = Currency('fakeKey') + self.assertIsInstance(class_under_test.convert(), Convert) + + def test_currencies_method(self): + class_under_test = Currency('fakeKey') + self.assertIsInstance(class_under_test.currencies(), Currencies) \ No newline at end of file