From 718ba36656ee5e8f32241a30aa0977777a1012f4 Mon Sep 17 00:00:00 2001 From: Evan Sangaline Date: Wed, 4 Dec 2019 11:13:05 -0800 Subject: [PATCH 1/8] Implement getters and setters for the oauth2 tokens. --- hubspot3/base.py | 47 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 44 insertions(+), 3 deletions(-) diff --git a/hubspot3/base.py b/hubspot3/base.py index 7f9f82f..fdae405 100644 --- a/hubspot3/base.py +++ b/hubspot3/base.py @@ -10,7 +10,8 @@ import urllib.parse import urllib.error import zlib -from typing import List, Union +from typing import Callable, List, Optional, Union +from typing_extensions import Literal from hubspot3 import utils from hubspot3.utils import force_utf8 from hubspot3.error import ( @@ -41,6 +42,12 @@ def __init__( refresh_token: str = None, client_id: str = None, client_secret: str = None, + oauth2_token_getter: Optional[Callable[ + [Literal['access_token', 'refresh_token']], str, + ]] = None, + oauth2_token_setter: Optional[Callable[ + [Literal['access_token', 'refresh_token'], str], str, + ]] = None, timeout: int = 10, mixins: List = None, api_base: str = "api.hubapi.com", @@ -58,10 +65,14 @@ def __init__( self.__class__.__bases__ = (mixin_class,) + self.__class__.__bases__ self.api_key = api_key - self.access_token = access_token - self.refresh_token = refresh_token + # These are used as fallbacks if there aren't setters/getters, or if no remote tokens can be + # found. The properties without `__` prefixes should generally be used instead of these. + self.__access_token = access_token + self.__refresh_token = refresh_token self.client_id = client_id self.client_secret = client_secret + self.oauth2_token_getter = oauth2_token_getter + self.oauth2_token_setter = oauth2_token_setter self.log = utils.get_log("hubspot3") if not disable_auth: if self.api_key and self.access_token: @@ -88,8 +99,38 @@ def credentials(self): "api_key": self.api_key, "access_token": self.access_token, "refresh_token": self.refresh_token, + "oauth2_token_getter": self.oauth2_token_getter, + "oauth2_token_setter": self.oauth2_token_setter, } + @property + def access_token(self): + if self.oauth2_token_getter: + return self.oauth2_token_getter('access_token', self.client_id) or self.__access_token + else: + return self.__access_token + + @access_token.setter + def access_token(self, access_token): + if self.oauth2_token_setter: + self.oauth2_token_setter('access_token', self.client_id, access_token) + else: + self.__access_token = access_token + + @property + def refresh_token(self): + if self.oauth2_token_getter: + return self.oauth2_token_getter('refresh_token', self.client_id) or self.__refresh_token + else: + return self.__refresh_token + + @refresh_token.setter + def refresh_token(self, refresh_token): + if self.oauth2_token_setter: + self.oauth2_token_setter('refresh_token', self.client_id, refresh_token) + else: + self.__refresh_token = refresh_token + def _prepare_connection_type(self): connection_types = { "http": http.client.HTTPConnection, From 539163339c3d6dcb5cba471fdf3d2bb4ff5eba1b Mon Sep 17 00:00:00 2001 From: Evan Sangaline Date: Wed, 4 Dec 2019 11:13:26 -0800 Subject: [PATCH 2/8] Update a test to pass with the new oauth2 getters and setters. --- hubspot3/test/test_lines.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hubspot3/test/test_lines.py b/hubspot3/test/test_lines.py index a606a5f..c5e727a 100644 --- a/hubspot3/test/test_lines.py +++ b/hubspot3/test/test_lines.py @@ -130,6 +130,7 @@ def test_link_line_item_to_deal(self, mock_associations_client, lines_client): mock_instance = mock_associations_client.return_value lines_client.link_line_item_to_deal(1, 1) mock_associations_client.assert_called_with( - access_token=None, api_key=None, refresh_token=None + access_token=None, api_key=None, refresh_token=None, + oauth2_token_getter=None, oauth2_token_setter=None, ) mock_instance.link_line_item_to_deal.assert_called_with(1, 1) From c0abf27538ed8ba9104d8d2d2733beda3bcef9b4 Mon Sep 17 00:00:00 2001 From: Evan Sangaline Date: Wed, 4 Dec 2019 11:31:42 -0800 Subject: [PATCH 3/8] Raise a configuration error if there's a getter without a setter. --- hubspot3/base.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/hubspot3/base.py b/hubspot3/base.py index fdae405..ab2fd85 100644 --- a/hubspot3/base.py +++ b/hubspot3/base.py @@ -71,6 +71,10 @@ def __init__( self.__refresh_token = refresh_token self.client_id = client_id self.client_secret = client_secret + if (oauth2_token_getter is None) != (oauth2_token_setter is None): + raise HubspotBadConfig( + "You must either specify both the oauth2 token setter and getter, or neither." + ) self.oauth2_token_getter = oauth2_token_getter self.oauth2_token_setter = oauth2_token_setter self.log = utils.get_log("hubspot3") From e67b8512127ede47f3746b85230eaa2b864d02e1 Mon Sep 17 00:00:00 2001 From: Evan Sangaline Date: Wed, 4 Dec 2019 11:36:39 -0800 Subject: [PATCH 4/8] Fix the typing on the getter/setter. --- hubspot3/base.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hubspot3/base.py b/hubspot3/base.py index ab2fd85..7a3b157 100644 --- a/hubspot3/base.py +++ b/hubspot3/base.py @@ -43,10 +43,10 @@ def __init__( client_id: str = None, client_secret: str = None, oauth2_token_getter: Optional[Callable[ - [Literal['access_token', 'refresh_token']], str, + [Literal['access_token', 'refresh_token'], str], str, ]] = None, oauth2_token_setter: Optional[Callable[ - [Literal['access_token', 'refresh_token'], str], str, + [Literal['access_token', 'refresh_token'], str, str], None, ]] = None, timeout: int = 10, mixins: List = None, From d968b675442b25cc025e2a0466b86066192cfa36 Mon Sep 17 00:00:00 2001 From: Evan Sangaline Date: Wed, 4 Dec 2019 11:50:20 -0800 Subject: [PATCH 5/8] Fix some of the linting issues. --- hubspot3/base.py | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/hubspot3/base.py b/hubspot3/base.py index 7a3b157..53bc318 100644 --- a/hubspot3/base.py +++ b/hubspot3/base.py @@ -42,12 +42,12 @@ def __init__( refresh_token: str = None, client_id: str = None, client_secret: str = None, - oauth2_token_getter: Optional[Callable[ - [Literal['access_token', 'refresh_token'], str], str, - ]] = None, - oauth2_token_setter: Optional[Callable[ - [Literal['access_token', 'refresh_token'], str, str], None, - ]] = None, + oauth2_token_getter: Optional[ + Callable[[Literal["access_token", "refresh_token"], str], str,] + ] = None, + oauth2_token_setter: Optional[ + Callable[[Literal["access_token", "refresh_token"], str, str], None,] + ] = None, timeout: int = 10, mixins: List = None, api_base: str = "api.hubapi.com", @@ -110,28 +110,32 @@ def credentials(self): @property def access_token(self): if self.oauth2_token_getter: - return self.oauth2_token_getter('access_token', self.client_id) or self.__access_token - else: - return self.__access_token + return ( + self.oauth2_token_getter("access_token", self.client_id) + or self.__access_token + ) + return self.__access_token @access_token.setter def access_token(self, access_token): if self.oauth2_token_setter: - self.oauth2_token_setter('access_token', self.client_id, access_token) - else: - self.__access_token = access_token + self.oauth2_token_setter("access_token", self.client_id, access_token) + self.__access_token = access_token @property def refresh_token(self): if self.oauth2_token_getter: - return self.oauth2_token_getter('refresh_token', self.client_id) or self.__refresh_token + return ( + self.oauth2_token_getter("refresh_token", self.client_id) + or self.__refresh_token + ) else: return self.__refresh_token @refresh_token.setter def refresh_token(self, refresh_token): if self.oauth2_token_setter: - self.oauth2_token_setter('refresh_token', self.client_id, refresh_token) + self.oauth2_token_setter("refresh_token", self.client_id, refresh_token) else: self.__refresh_token = refresh_token From abede40011dddc5f9728fdd343194b0cafdc05ac Mon Sep 17 00:00:00 2001 From: Evan Sangaline Date: Wed, 4 Dec 2019 11:52:30 -0800 Subject: [PATCH 6/8] Disable two pylint rules for the base client. --- hubspot3/base.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/hubspot3/base.py b/hubspot3/base.py index 53bc318..b566f8c 100644 --- a/hubspot3/base.py +++ b/hubspot3/base.py @@ -31,6 +31,9 @@ class BaseClient: """Base abstract object for interacting with the HubSpot APIs""" + # These rules are too restrictive for the `__init__()` method and attributes. + # pylint: disable=too-many-arguments,too-many-instance-attributes + # Controls how long we sleep for during retries, overridden by unittests # so tests run faster sleep_multiplier = 1 From 23875b3b1cd9c5cf7e6fc0082311aae31eb53fcd Mon Sep 17 00:00:00 2001 From: Evan Sangaline Date: Wed, 4 Dec 2019 11:55:15 -0800 Subject: [PATCH 7/8] More black fixes. --- hubspot3/base.py | 4 ++-- hubspot3/test/test_lines.py | 7 +++++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/hubspot3/base.py b/hubspot3/base.py index b566f8c..3a8dd58 100644 --- a/hubspot3/base.py +++ b/hubspot3/base.py @@ -46,10 +46,10 @@ def __init__( client_id: str = None, client_secret: str = None, oauth2_token_getter: Optional[ - Callable[[Literal["access_token", "refresh_token"], str], str,] + Callable[[Literal["access_token", "refresh_token"], str], str] ] = None, oauth2_token_setter: Optional[ - Callable[[Literal["access_token", "refresh_token"], str, str], None,] + Callable[[Literal["access_token", "refresh_token"], str, str], None] ] = None, timeout: int = 10, mixins: List = None, diff --git a/hubspot3/test/test_lines.py b/hubspot3/test/test_lines.py index c5e727a..35fab46 100644 --- a/hubspot3/test/test_lines.py +++ b/hubspot3/test/test_lines.py @@ -130,7 +130,10 @@ def test_link_line_item_to_deal(self, mock_associations_client, lines_client): mock_instance = mock_associations_client.return_value lines_client.link_line_item_to_deal(1, 1) mock_associations_client.assert_called_with( - access_token=None, api_key=None, refresh_token=None, - oauth2_token_getter=None, oauth2_token_setter=None, + access_token=None, + api_key=None, + refresh_token=None, + oauth2_token_getter=None, + oauth2_token_setter=None, ) mock_instance.link_line_item_to_deal.assert_called_with(1, 1) From 84377457788999bb705a938459960b2d5a9f17ae Mon Sep 17 00:00:00 2001 From: Evan Sangaline Date: Wed, 4 Dec 2019 11:57:26 -0800 Subject: [PATCH 8/8] Another linting fix. --- hubspot3/base.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/hubspot3/base.py b/hubspot3/base.py index 3a8dd58..95937e5 100644 --- a/hubspot3/base.py +++ b/hubspot3/base.py @@ -132,8 +132,7 @@ def refresh_token(self): self.oauth2_token_getter("refresh_token", self.client_id) or self.__refresh_token ) - else: - return self.__refresh_token + return self.__refresh_token @refresh_token.setter def refresh_token(self, refresh_token):