Conversation
Co-authored-by: Rushikesh Todkar <98420315+RushiT0122@users.noreply.github.com>
| with open(self.tmp_config_path, "w") as ff: | ||
| json.dump(self.base_config, ff) |
There was a problem hiding this comment.
I will strongly suggest deleting the temp config once the unit test is executed. If we don't delete it, I think it will keep on accumulating the temp configs (as the everyday job runs) within circleci server.
There was a problem hiding this comment.
agreed, but as the cci runner is temporary provisioned and the files created during testing are not preserved.
it will be autodeleted
tap_eloqua/client.py
Outdated
| Server5xxError, | ||
| max_tries=5, | ||
| factor=2) | ||
| @backoff.on_exception(backoff.expo,Server5xxError,5,factor=2) |
There was a problem hiding this comment.
| @backoff.on_exception(backoff.expo,Server5xxError,5,factor=2) | |
| @backoff.on_exception(backoff.expo, | |
| Server5xxError, | |
| max_tries=5, | |
| factor=2) |
tap_eloqua/client.py
Outdated
| except KeyError as err: | ||
| raise Exception("Unable to locate key in config") from err | ||
| if not self.__access_token or self.__expires < now(): | ||
| raise Exception("Access Token in config is expired, unable to authenticate in dev mode") |
There was a problem hiding this comment.
Use either ex or e as a convention for exception.
| except KeyError as err: | |
| raise Exception("Unable to locate key in config") from err | |
| if not self.__access_token or self.__expires < now(): | |
| raise Exception("Access Token in config is expired, unable to authenticate in dev mode") | |
| except KeyError as ex: | |
| raise Exception("Unable to locate key in config") from ex | |
| if not self.__access_token or self.__expires < now(): | |
| raise Exception("Access Token in config is expired, unable to authenticate in dev mode") |
tap_eloqua/client.py
Outdated
|
|
||
| def post(self, path, **kwargs): | ||
| return self.request('POST', path=path, **kwargs) | ||
|
|
tap_eloqua/client.py
Outdated
| expires_seconds = data['expires_in'] - 10 # pad by 10 seconds | ||
| self.__expires = datetime.utcnow() + timedelta(seconds=expires_seconds) | ||
| if not self.dev_mode: | ||
| update_config_keys = {"refresh_token":self.__refresh_token,"access_token":self.__access_token,"expires_in": strftime(self.__expires)} |
There was a problem hiding this comment.
| update_config_keys = {"refresh_token":self.__refresh_token,"access_token":self.__access_token,"expires_in": strftime(self.__expires)} | |
| update_config_keys = {"refresh_token": self.__refresh_token, | |
| "access_token": self.__access_token, | |
| "expires_in": strftime(self.__expires)} |
| finished = False | ||
| sync_start = pendulum.now('UTC') | ||
| end_date = sync_start | ||
| end_date, last_sync_date = sync_start, None |
There was a problem hiding this comment.
Are these changes in sync.py dev-mode related? If not can we keep it separate from dev-mode changes.
There was a problem hiding this comment.
And if these are required changes then update the description on this PR.
There was a problem hiding this comment.
@RushiT0122
These are not dev mode related changes, but if you see the code from Line:380 - Line:403
last_sync_date was declared on Line:385 in the try statement, but accessed outside its declared scope in the except block, hence it was introduced here.
There was a problem hiding this comment.
I'm pretty sure this is a problem in other languages, but not python
>>> for i in range(3):
... try:
... print("About to initialize `my_variable`")
... my_variable = i
... print(f"my_variable: {my_variable}")
... raise RuntimeError(f"Problem occured with {my_variable}")
... except Exception as err:
... print(f"Caught {type(err)} with message {str(err)}")
... print(f"Current value of my_variable {my_variable}")
...
About to initialize `my_variable`
my_variable: 0
Caught <class 'RuntimeError'> with message Problem occured with 0
Current value of my_variable 0
About to initialize `my_variable`
my_variable: 1
Caught <class 'RuntimeError'> with message Problem occured with 1
Current value of my_variable 1
About to initialize `my_variable`
my_variable: 2
Caught <class 'RuntimeError'> with message Problem occured with 2
Current value of my_variable 2
tap_eloqua/utils.py
Outdated
| LOGGER = get_logger() | ||
|
|
||
|
|
||
| def write_config(config_path,data :Dict) -> Dict: |
There was a problem hiding this comment.
Please check this comment on tap-deputy: singer-io/tap-deputy#3 (comment)
There was a problem hiding this comment.
made required changes
tests/unittests/test_devmode.py
Outdated
| try: | ||
| client = EloquaClient(config_path=self.tmp_config_path,dev_mode=True,config=self.base_config) | ||
|
|
||
| client.get_access_token() | ||
| except Exception as error: | ||
| self.assertEqual(str(error), "Unable to locate key in config") |
There was a problem hiding this comment.
Use with self.assertRaises() unittest construct here.
There was a problem hiding this comment.
I can't use assertRaises here, because we can only check the "type" of the exception with it.
But in this case, all exceptions are raised with "Exception" class and I want to validate the message-string that is raised with it.
| self.assertEqual(str(error), "Unable to locate key in config") | ||
|
|
||
| @patch("requests.Session.post", side_effect=mocked_auth_post) | ||
| def test_client_valid_token(self, mocked_auth_post): |
There was a problem hiding this comment.
| def test_client_valid_token(self, mocked_auth_post): | |
| def test_client_valid_access_token(self, mocked_auth_post): |
| client.get_access_token() | ||
|
|
||
| @patch("requests.Session.post", side_effect=mocked_auth_post) | ||
| def test_client_invalid_token(self, mocked_auth_post): |
There was a problem hiding this comment.
| def test_client_invalid_token(self, mocked_auth_post): | |
| def test_client_invalid_access_token(self, mocked_auth_post): |
tests/unittests/test_devmode.py
Outdated
| try: | ||
| client = EloquaClient(config_path=self.tmp_config_path,dev_mode=True,config=config_sample) | ||
| client.get_access_token() | ||
| except Exception as error: | ||
| self.assertEqual(str(error), "Access Token in config is expired, unable to authenticate in dev mode") |
There was a problem hiding this comment.
Use with self.assertRaises() unittest construct here.
There was a problem hiding this comment.
I can't use assertRaises here, because we can only check the "type" of the exception with it.
But in this case, all exceptions are raised with "Exception" class and I want to validate the message-string that is raised with it.
There was a problem hiding this comment.
Docs for assertRaises. These docs show how you can use a context manager with assertRaises. And they show that the exception object is a property on the manager, which means we can do exactly what you want to do
Here's how you use it
$ python3
Python 3.10.9 (main, Dec 15 2022, 18:25:35) [Clang 14.0.0 (clang-1400.0.29.202)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
# start setup
>>> import unittest
>>> class some_test(unittest.TestCase):
... pass
...
>>> my_test = some_test()
# Prove assertRaises works
>>> with my_test.assertRaises(Exception):
... 1+1
...
2
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/local/Cellar/python@3.10/3.10.9/Frameworks/Python.framework/Versions/3.10/lib/python3.10/unittest/case.py", line 226, in __exit__
self._raiseFailure("{} not raised".format(exc_name))
File "/usr/local/Cellar/python@3.10/3.10.9/Frameworks/Python.framework/Versions/3.10/lib/python3.10/unittest/case.py", line 163, in _raiseFailure
raise self.test_case.failureException(msg)
AssertionError: Exception not raised
# Prove the test can pass
>>> with my_test.assertRaises(Exception) as context_manager:
... raise Exception("this is a test")
...
# Show we have the exception
>>> actual_exception = context_manager.exception
>>> actual_exception
Exception('this is a test')
>>> str(actual_exception)
'this is a test'| self.assertEqual(True, "access_token" in config) | ||
| self.assertEqual(True, "refresh_token" in config) | ||
|
|
||
| def test_devmode_accesstoken_absent(self, *args, **kwargs): |
There was a problem hiding this comment.
It looks like *args and **kwargs is unused
luandy64
left a comment
There was a problem hiding this comment.
Overall, there are a lot of little changes to make. Functionally, the code seems fine and a lot like other dev-mode implementations.
But because code is written once and read over and over, I think it's very important that we think about cleaning up the style once the logic is complete. It's nice to reference any of the style guides out on the internet (they all basically say the same thing).
| name: 'pylint' | ||
| command: | | ||
| source /usr/local/share/virtualenvs/tap-eloqua/bin/activate | ||
| pylint tap_eloqua -d C,R,W |
There was a problem hiding this comment.
Should we use the standard list of disables?
| finished = False | ||
| sync_start = pendulum.now('UTC') | ||
| end_date = sync_start | ||
| end_date, last_sync_date = sync_start, None |
There was a problem hiding this comment.
I'm pretty sure this is a problem in other languages, but not python
>>> for i in range(3):
... try:
... print("About to initialize `my_variable`")
... my_variable = i
... print(f"my_variable: {my_variable}")
... raise RuntimeError(f"Problem occured with {my_variable}")
... except Exception as err:
... print(f"Caught {type(err)} with message {str(err)}")
... print(f"Current value of my_variable {my_variable}")
...
About to initialize `my_variable`
my_variable: 0
Caught <class 'RuntimeError'> with message Problem occured with 0
Current value of my_variable 0
About to initialize `my_variable`
my_variable: 1
Caught <class 'RuntimeError'> with message Problem occured with 1
Current value of my_variable 1
About to initialize `my_variable`
my_variable: 2
Caught <class 'RuntimeError'> with message Problem occured with 2
Current value of my_variable 2| @@ -0,0 +1,18 @@ | |||
| from typing import Dict | |||
| @patch("requests.Session.post", side_effect=mocked_auth_post) | ||
| def test_client_without_dev_mode(self, mocked_auth_post): | ||
| """checks if the client can write refresh token and expiry to | ||
| config.""" |
There was a problem hiding this comment.
Why is this line wrapped if line 23 isn't?
| self.assertEqual(True, "expires_in" in config) | ||
| self.assertEqual(True, "access_token" in config) | ||
| self.assertEqual(True, "refresh_token" in config) |
There was a problem hiding this comment.
I think there are 2 better options here:
"expires_in" in configis a boolean. So these are equivalent
self.assertEqual(True, "expires_in" in config)
self.assert("expires_in" in config)
| if self.dev_mode: | ||
| try: | ||
| self.__access_token = self.config['access_token'] | ||
| self.__expires=strptime_to_utc(self.config['expires_in']) |
There was a problem hiding this comment.
| self.__expires=strptime_to_utc(self.config['expires_in']) | |
| self.__expires = strptime_to_utc(self.config['expires_in']) |
| "refresh_token":self.__refresh_token, | ||
| "access_token":self.__access_token, | ||
| "expires_in": strftime(self.__expires) |
There was a problem hiding this comment.
| "refresh_token":self.__refresh_token, | |
| "access_token":self.__access_token, | |
| "expires_in": strftime(self.__expires) | |
| "refresh_token": self.__refresh_token, | |
| "access_token": self.__access_token, | |
| "expires_in": strftime(self.__expires) |
| "access_token":self.__access_token, | ||
| "expires_in": strftime(self.__expires) | ||
| } | ||
| self.config = write_config(self.__config_path,update_config_keys) |
There was a problem hiding this comment.
| self.config = write_config(self.__config_path,update_config_keys) | |
| self.config = write_config(self.__config_path, update_config_keys) |
| data = self.request('GET', | ||
| url='https://login.eloqua.com/id', | ||
| endpoint='base_url') | ||
| data = self.request('GET',url='https://login.eloqua.com/id',endpoint='base_url') |
There was a problem hiding this comment.
| data = self.request('GET',url='https://login.eloqua.com/id',endpoint='base_url') | |
| data = self.request('GET', url='https://login.eloqua.com/id', endpoint='base_url') |
| json.dump(self.base_config, ff) | ||
|
|
||
|
|
||
| client = EloquaClient(config_path=self.tmp_config_path,dev_mode=False,config=self.base_config) |
There was a problem hiding this comment.
| client = EloquaClient(config_path=self.tmp_config_path,dev_mode=False,config=self.base_config) | |
| client = EloquaClient(config_path=self.tmp_config_path, dev_mode=False, config=self.base_config) |
Description of change
Add support for
-dev/--devcli param,refresh_tokenexpiry while running in dev-modeaccess_tokenandexpiryin configaccess_tokenis not availableManual QA steps
access_token&expires_in--devor '-dev' paramRisks (Low)
P.R Dependant on #158
Rollback steps