diff --git a/.circleci/config.yml b/.circleci/config.yml index e7df668..f78282d 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -2,7 +2,7 @@ version: 2 jobs: build: docker: - - image: 218546966473.dkr.ecr.us-east-1.amazonaws.com/circle-ci:tap-tester + - image: 218546966473.dkr.ecr.us-east-1.amazonaws.com/circle-ci:stitch-tap-tester steps: - checkout - run: @@ -16,12 +16,12 @@ jobs: name: 'Pylint' command: | source ~/.virtualenvs/tap-marketo/bin/activate - pylint tap_marketo -d C,R + pylint tap_marketo -d C,R,W - run: name: 'JSON Validator' command: | source /usr/local/share/virtualenvs/tap-tester/bin/activate - stitch-validate-json ~/.virtualenvs/tap-marketo/lib/python3.5/site-packages/tap_marketo/schemas/*.json + stitch-validate-json tap_marketo/schemas/*.json - run: name: 'Unit Tests' command: | diff --git a/CHANGELOG.md b/CHANGELOG.md index 69b1b5f..f9a8632 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ # Changelog +## 2.5.1 + * Fixed Validation Error for `max_daily_calls` [#84](https://github.com/singer-io/tap-marketo/pull/84) + ## 2.5.0 * Add campaignId field to activities streams [#82](https://github.com/singer-io/tap-marketo/pull/82) diff --git a/setup.py b/setup.py index 6914127..1870f19 100644 --- a/setup.py +++ b/setup.py @@ -3,7 +3,7 @@ from setuptools import setup setup(name='tap-marketo', - version='2.5.0', + version='2.5.1', description='Singer.io tap for extracting data from the Marketo API', author='Stitch', url='http://singer.io', diff --git a/tap_marketo/client.py b/tap_marketo/client.py index 49f268f..de0291d 100644 --- a/tap_marketo/client.py +++ b/tap_marketo/client.py @@ -26,7 +26,7 @@ # Marketo limits REST requests to 50000 per day with a rate limit of 100 # calls per 20 seconds. # http://developers.marketo.com/rest-api/ -MAX_DAILY_CALLS = int(50000 * 0.8) +MAX_DAILY_CALLS = 50000 * 0.8 RATE_LIMIT_CALLS = 100 RATE_LIMIT_SECONDS = 20 @@ -80,7 +80,7 @@ def raise_for_rate_limit(data): class Client: # pylint: disable=unused-argument def __init__(self, endpoint, client_id, client_secret, - max_daily_calls=MAX_DAILY_CALLS, + max_daily_calls=None, user_agent=DEFAULT_USER_AGENT, job_timeout=JOB_TIMEOUT, poll_interval=POLL_INTERVAL, @@ -89,7 +89,14 @@ def __init__(self, endpoint, client_id, client_secret, self.domain = extract_domain(endpoint) self.client_id = client_id self.client_secret = client_secret - self.max_daily_calls = int(max_daily_calls) + try: + self.max_daily_calls = int(max_daily_calls or MAX_DAILY_CALLS) + if self.max_daily_calls <= 1: + raise ValueError("Limit Cannot be Negative or Zero") + except (ValueError, TypeError) as err: + singer.log_critical(f"Invalid Value passed for max_daily_calls: {max_daily_calls}") + raise err + self.user_agent = user_agent self.job_timeout = job_timeout self.poll_interval = poll_interval diff --git a/tests/test_client_max_api_limit.py b/tests/test_client_max_api_limit.py new file mode 100644 index 0000000..51ac50d --- /dev/null +++ b/tests/test_client_max_api_limit.py @@ -0,0 +1,113 @@ +import unittest +from tap_marketo.client import Client, MAX_DAILY_CALLS + +class TestmaxdailycallsConfig(unittest.TestCase): + + def test_maxdailycalls_default_no_val(self): + """ + Verify that max_daily_calls is default if no value is passed + """ + # Initialize Client object + client = Client(**{'endpoint': '123-ABC-789','client_id':'ABC-123','client_secret':'123-QRT'}) + + self.assertEqual(client.max_daily_calls, MAX_DAILY_CALLS) + + def test_maxdailycalls_default_empty_str(self): + """ + Verify that max_daily_calls is default if empty string value is passed + Verify no Exception is raised for typecasting error between str to num + """ + # Initialize Client object + client = Client(**{'endpoint': '123-ABC-789','client_id':'ABC-123','client_secret':'123-QRT','max_daily_calls':''}) + + self.assertEqual(client.max_daily_calls, MAX_DAILY_CALLS) + + def test_maxdailycalls_default_bool_false_val(self): + """ + Verify that max_daily_calls is default if bool value is passed + """ + # Initialize Client object + client = Client(**{'endpoint': '123-ABC-789','client_id':'ABC-123','client_secret':'123-QRT','max_daily_calls':False}) + self.assertEqual(client.max_daily_calls ,MAX_DAILY_CALLS) + + def test_maxdailycalls_bool_true_val(self): + """ + Verify that max_daily_calls is default if bool value is passed + """ + # Initialize Client object + params = {'endpoint': '123-ABC-789','client_id':'ABC-123','client_secret':'123-QRT','max_daily_calls':True} + with self.assertRaises(ValueError): + try: + Client(**params) + except Exception as err: + self.assertEqual(str(err),"Limit Cannot be Negative or Zero") + raise err + + def test_maxdailycalls_default_zero_val(self): + """ + Verify that api_limit is default if 0 value is passed + """ + # Initialize Client object + client = Client(**{'endpoint': '123-ABC-789','client_id':'ABC-123','client_secret':'123-QRT','max_daily_calls':0}) + self.assertEqual(client.max_daily_calls, MAX_DAILY_CALLS) + + def test_maxdailycalls_default_none_val(self): + """ + Verify that api_limit is default if None value is passed + """ + # Initialize Client object + client = Client(**{'endpoint': '123-ABC-789','client_id':'ABC-123','client_secret':'123-QRT','max_daily_calls':None}) + self.assertEqual(client.max_daily_calls, MAX_DAILY_CALLS) + + def test_maxdailycalls_enabled_num_val(self): + """ + Verify that api_limit is set appropriately if num value is passed + """ + # Initialize Client object + client = Client(**{'endpoint': '123-ABC-789','client_id':'ABC-123','client_secret':'123-QRT','max_daily_calls':3}) + + self.assertEqual(client.max_daily_calls, 3) + + def test_maxdailycalls_failed_comma_val(self): + """ + Verify that exception is raised if invalid input value is passed + """ + params = {'endpoint': '123-ABC-789','client_id':'ABC-123','client_secret':'123-QRT','max_daily_calls':'30,000'} + # Initialize Client object + with self.assertRaises(ValueError): + Client(**params) + + def test_maxdailycalls_failed_decimal_val(self): + """ + Verify that api_limit is set appropriately if num value is passed + """ + # Initialize Client object + params = {'endpoint': '123-ABC-789','client_id':'ABC-123','client_secret':'123-QRT','max_daily_calls':'3700.15'} + with self.assertRaises(ValueError): + Client(**params) + + def test_maxdailycalls_failed_negative_val(self): + """ + Verify that api_limit is set appropriately if num value is passed + """ + # Initialize Client object + params = {'endpoint': '123-ABC-789','client_id':'ABC-123','client_secret':'123-QRT','max_daily_calls':'-522'} + with self.assertRaises(ValueError): + try: + Client(**params) + except Exception as err: + self.assertEqual(str(err),"Limit Cannot be Negative or Zero") + raise err + + def test_maxdailycalls_default_str_zero_val(self): + """ + Verify that api_limit is default if "0" value is passed + """ + # Initialize Client object + params = {'endpoint': '123-ABC-789','client_id':'ABC-123','client_secret':'123-QRT','max_daily_calls':'0'} + with self.assertRaises(ValueError): + try: + Client(**params) + except Exception as err: + self.assertEqual(str(err),"Limit Cannot be Negative or Zero") + raise err