From bb6d5040245d047ceecd91b397082f3376e0a47e Mon Sep 17 00:00:00 2001 From: Joe Norton Date: Tue, 30 Mar 2021 09:10:20 -0700 Subject: [PATCH 01/12] Create webhooks.py rough first draft, not tested yet --- typeform/webhooks.py | 45 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 typeform/webhooks.py diff --git a/typeform/webhooks.py b/typeform/webhooks.py new file mode 100644 index 0000000..1b0b6ad --- /dev/null +++ b/typeform/webhooks.py @@ -0,0 +1,45 @@ +import typing +from .client import Client + + +class Webhooks: + """Typeform Webhooks API client""" + + def __init__(self, client: Client): + """Constructor for Typeform Webhooks class""" + self.__client = client + + def list(self, uid: str): + """ + Returns form webhooks and date and time of form landing and submission. + """ + return self.__client.request('get', '/forms/%s/webhooks' % uid) + + + def get(self, uid: str, tag: str): + """ + Returns form webhooks and date and time of form landing and submission. + """ + return self.__client.request('get', '/forms/%s/webhooks/%s' % uid, tag) + + def create_update(self, uid: str, tag: str, url: str, enabled: bool, secret: str, verify_ssl: bool): + """ + Create or update a webhook. + """ + return self.__client.request( + 'put', '/forms/%s/webhooks/%s' % (uid,tag), params={ + 'url': url, + 'enabled': enabled, + 'secret': secret, + 'verify_ssl': verify_ssl + } + ) + + def delete(self, uid: str, tag: str, includedTokens: typing.Union[str, typing.List[str]]) -> str: + """ + Delete webhooks to a form. You must specify the `included_tokens`/`includedTokens` parameter. + Return a `str` based on success of deletion, `OK` on success, otherwise an error message. + """ + return self.__client.request('delete', '/forms/%s/webhooks/%s' % (uid,tag), params={ + 'included_tokens': includedTokens + }) From 2e7e9d507a9f143c1fdbdc26582c55e992613aa3 Mon Sep 17 00:00:00 2001 From: Joe Norton Date: Tue, 30 Mar 2021 09:15:51 -0700 Subject: [PATCH 02/12] Update __init__.py --- typeform/__init__.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/typeform/__init__.py b/typeform/__init__.py index 27afd66..34fe264 100644 --- a/typeform/__init__.py +++ b/typeform/__init__.py @@ -1,5 +1,6 @@ from .forms import Forms from .responses import Responses +from .webhooks import Webhooks from .client import Client __all__ = ['Typeform'] @@ -13,6 +14,7 @@ def __init__(self, token: str, headers: dict = {}): client = Client(token, headers=headers) self.__forms = Forms(client) self.__responses = Responses(client) + self.__webhooks = Webhooks(client) @property def forms(self) -> Forms: @@ -21,3 +23,7 @@ def forms(self) -> Forms: @property def responses(self) -> Responses: return self.__responses + + @property + def webhooks(self) -> Webhooks: + return self.__webhooks From dad7625e3e7f40c0082822e570f3a2109c00527c Mon Sep 17 00:00:00 2001 From: Joe Norton Date: Tue, 30 Mar 2021 09:37:10 -0700 Subject: [PATCH 03/12] Update webhooks.py --- typeform/webhooks.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/typeform/webhooks.py b/typeform/webhooks.py index 1b0b6ad..2d3af80 100644 --- a/typeform/webhooks.py +++ b/typeform/webhooks.py @@ -20,19 +20,20 @@ def get(self, uid: str, tag: str): """ Returns form webhooks and date and time of form landing and submission. """ - return self.__client.request('get', '/forms/%s/webhooks/%s' % uid, tag) + return self.__client.request('get', '/forms/%s/webhooks/%s' % (uid,tag)) - def create_update(self, uid: str, tag: str, url: str, enabled: bool, secret: str, verify_ssl: bool): + def create_update(self, uid: str, tag: str, data={}): """ Create or update a webhook. + { + 'url': url, str + 'enabled': enabled, bool + 'secret': secret, str + 'verify_ssl': verify_ssl bool + } """ return self.__client.request( - 'put', '/forms/%s/webhooks/%s' % (uid,tag), params={ - 'url': url, - 'enabled': enabled, - 'secret': secret, - 'verify_ssl': verify_ssl - } + 'put', '/forms/%s/webhooks/%s' % (uid,tag), data=data ) def delete(self, uid: str, tag: str, includedTokens: typing.Union[str, typing.List[str]]) -> str: From 6546870a95b8ecc1035a11a60282dde1bc4b6d41 Mon Sep 17 00:00:00 2001 From: Joe Norton Date: Tue, 30 Mar 2021 11:29:01 -0700 Subject: [PATCH 04/12] Update webhooks.py --- typeform/webhooks.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/typeform/webhooks.py b/typeform/webhooks.py index 2d3af80..1802c9a 100644 --- a/typeform/webhooks.py +++ b/typeform/webhooks.py @@ -41,6 +41,4 @@ def delete(self, uid: str, tag: str, includedTokens: typing.Union[str, typing.Li Delete webhooks to a form. You must specify the `included_tokens`/`includedTokens` parameter. Return a `str` based on success of deletion, `OK` on success, otherwise an error message. """ - return self.__client.request('delete', '/forms/%s/webhooks/%s' % (uid,tag), params={ - 'included_tokens': includedTokens - }) + return self.__client.request('delete', '/forms/%s/webhooks/%s' % (uid,tag)) From 52542911812c87e26acb5ed7f7224e3dd7d03325 Mon Sep 17 00:00:00 2001 From: Joe Norton Date: Tue, 30 Mar 2021 11:29:10 -0700 Subject: [PATCH 05/12] Update webhooks.py --- typeform/webhooks.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/typeform/webhooks.py b/typeform/webhooks.py index 1802c9a..2275e0d 100644 --- a/typeform/webhooks.py +++ b/typeform/webhooks.py @@ -42,3 +42,5 @@ def delete(self, uid: str, tag: str, includedTokens: typing.Union[str, typing.Li Return a `str` based on success of deletion, `OK` on success, otherwise an error message. """ return self.__client.request('delete', '/forms/%s/webhooks/%s' % (uid,tag)) + + From eaf40a488498f660f494081f234a107b8a923351 Mon Sep 17 00:00:00 2001 From: Joe Norton Date: Tue, 30 Mar 2021 11:29:29 -0700 Subject: [PATCH 06/12] Update webhooks.py --- typeform/webhooks.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/typeform/webhooks.py b/typeform/webhooks.py index 2275e0d..1802c9a 100644 --- a/typeform/webhooks.py +++ b/typeform/webhooks.py @@ -42,5 +42,3 @@ def delete(self, uid: str, tag: str, includedTokens: typing.Union[str, typing.Li Return a `str` based on success of deletion, `OK` on success, otherwise an error message. """ return self.__client.request('delete', '/forms/%s/webhooks/%s' % (uid,tag)) - - From 9c495527ca192146c0446a3df5bbdc75f9799a35 Mon Sep 17 00:00:00 2001 From: Joe Norton Date: Tue, 30 Mar 2021 11:39:08 -0700 Subject: [PATCH 07/12] Update webhooks.py --- typeform/webhooks.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/typeform/webhooks.py b/typeform/webhooks.py index 1802c9a..3373780 100644 --- a/typeform/webhooks.py +++ b/typeform/webhooks.py @@ -38,7 +38,7 @@ def create_update(self, uid: str, tag: str, data={}): def delete(self, uid: str, tag: str, includedTokens: typing.Union[str, typing.List[str]]) -> str: """ - Delete webhooks to a form. You must specify the `included_tokens`/`includedTokens` parameter. + Delete webhooks to a form. Return a `str` based on success of deletion, `OK` on success, otherwise an error message. """ return self.__client.request('delete', '/forms/%s/webhooks/%s' % (uid,tag)) From f915a5004a54db657c81e2dc8c0c7bba754b565b Mon Sep 17 00:00:00 2001 From: Joe Norton Date: Tue, 30 Mar 2021 11:45:56 -0700 Subject: [PATCH 08/12] Update webhooks.py --- typeform/webhooks.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/typeform/webhooks.py b/typeform/webhooks.py index 3373780..5a8150b 100644 --- a/typeform/webhooks.py +++ b/typeform/webhooks.py @@ -36,7 +36,7 @@ def create_update(self, uid: str, tag: str, data={}): 'put', '/forms/%s/webhooks/%s' % (uid,tag), data=data ) - def delete(self, uid: str, tag: str, includedTokens: typing.Union[str, typing.List[str]]) -> str: + def delete(self, uid: str, tag: str) -> str: """ Delete webhooks to a form. Return a `str` based on success of deletion, `OK` on success, otherwise an error message. From 876c36f666a567c7df1832e816533de79c08e2a5 Mon Sep 17 00:00:00 2001 From: Joe Norton Date: Tue, 30 Mar 2021 11:47:47 -0700 Subject: [PATCH 09/12] Update webhooks.py --- typeform/webhooks.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/typeform/webhooks.py b/typeform/webhooks.py index 5a8150b..b6ffb77 100644 --- a/typeform/webhooks.py +++ b/typeform/webhooks.py @@ -9,20 +9,20 @@ def __init__(self, client: Client): """Constructor for Typeform Webhooks class""" self.__client = client - def list(self, uid: str): + def list(self, uid: str) -> dict: """ Returns form webhooks and date and time of form landing and submission. """ return self.__client.request('get', '/forms/%s/webhooks' % uid) - def get(self, uid: str, tag: str): + def get(self, uid: str, tag: str) -> dict: """ Returns form webhooks and date and time of form landing and submission. """ return self.__client.request('get', '/forms/%s/webhooks/%s' % (uid,tag)) - def create_update(self, uid: str, tag: str, data={}): + def create_update(self, uid: str, tag: str, data={}) -> dict: """ Create or update a webhook. { From cd148a5866b17f0e4d3173571e3929f615a2aa6e Mon Sep 17 00:00:00 2001 From: Craig Anderson Date: Mon, 19 Jul 2021 11:46:54 +0100 Subject: [PATCH 10/12] Fix flake8 errors. --- typeform/client.py | 2 +- typeform/test/fixtures.py | 2 +- typeform/test/test_forms.py | 11 +++++++---- typeform/test/test_responses.py | 2 +- typeform/webhooks.py | 8 +++----- 5 files changed, 13 insertions(+), 12 deletions(-) diff --git a/typeform/client.py b/typeform/client.py index 53d284c..5f7bd0a 100644 --- a/typeform/client.py +++ b/typeform/client.py @@ -39,7 +39,7 @@ def __validator(self, result: requests.Response) -> typing.Union[str, dict]: if type(body) is dict and body.get('code', None) is not None: raise Exception(body.get('description')) elif result.status_code >= 400: - raise Exception(' '.join([str(result.status_code),result.reason])) + raise Exception(' '.join([str(result.status_code), result.reason])) elif len(result.text) == 0: return 'OK' else: diff --git a/typeform/test/fixtures.py b/typeform/test/fixtures.py index 0a3f003..38c46f2 100644 --- a/typeform/test/fixtures.py +++ b/typeform/test/fixtures.py @@ -11,4 +11,4 @@ WORKSPACE_ID = WORKSPACE.split('/')[-1] if MOCK and (not TOKEN or '[YOUR WORKSPACE ID]' in WORKSPACE): - raise Exception("You need to setup TOKEN and WORKSPACE in fixtures.py") \ No newline at end of file + raise Exception('You need to setup TOKEN and WORKSPACE in fixtures.py') diff --git a/typeform/test/test_forms.py b/typeform/test/test_forms.py index 68af9d2..ceb26d6 100644 --- a/typeform/test/test_forms.py +++ b/typeform/test/test_forms.py @@ -15,7 +15,7 @@ def setUp(self): form = self.forms.create(dict(title="Form's test form", workspace={'href': WORKSPACE})) self.formID = form.get('id') else: - self.formID = "MOCK-FORM-ID" + self.formID = 'MOCK-FORM-ID' def tearDown(self): if not MOCK: @@ -93,7 +93,7 @@ def test_forms_update_as_patch_updates_a_form(self): update as patch updates a form """ with requests_mock.mock(real_http=not MOCK) as m: - m.patch(API_BASE_URL+'/forms/'+self.formID, json="OK") + m.patch(API_BASE_URL+'/forms/'+self.formID, json='OK') result = self.forms.update(self.formID, patch=True, data=[ dict(op='replace', path='/title', value='forms_update_as_patch_updates_a_form')]) @@ -125,7 +125,7 @@ def test_forms_delete_removes_the_correct_uid_form(self): self.assertEqual(get_one_result.get('id'), self.formID) self.forms.delete(self.formID) m.get(API_BASE_URL + '/forms/{}'.format(self.formID), - json=dict(code="FORM_NOT_FOUND", description="Non existing form with uid {}".format(self.formID))) + json=dict(code='FORM_NOT_FOUND', description='Non existing form with uid {}'.format(self.formID))) try: self.forms.get(self.formID) except Exception as err: @@ -153,7 +153,10 @@ def test_forms_create_creates_a_new_form(self): m.post(API_BASE_URL + '/forms', json=dict(id=str(self.formID))) m.get(API_BASE_URL + '/forms/{}'.format(self.formID), json=dict(id=str(self.formID))) - create_result = self.forms.create(dict(title='forms_create_creates_a_new_form', workspace={'href': WORKSPACE})) + create_result = self.forms.create(dict( + title='forms_create_creates_a_new_form', + workspace={'href': WORKSPACE}, + )) formID = create_result.get('id') diff --git a/typeform/test/test_responses.py b/typeform/test/test_responses.py index c86b8cd..154b4f4 100644 --- a/typeform/test/test_responses.py +++ b/typeform/test/test_responses.py @@ -16,7 +16,7 @@ def setUp(self): form = self.forms.create((dict(title="Responses's test form", workspace={'href': WORKSPACE}))) self.formID = form.get('id') else: - self.formID = "MOCK-FORM-ID" + self.formID = 'MOCK-FORM-ID' def tearDown(self): if not MOCK: diff --git a/typeform/webhooks.py b/typeform/webhooks.py index b6ffb77..6a5055c 100644 --- a/typeform/webhooks.py +++ b/typeform/webhooks.py @@ -1,4 +1,3 @@ -import typing from .client import Client @@ -15,12 +14,11 @@ def list(self, uid: str) -> dict: """ return self.__client.request('get', '/forms/%s/webhooks' % uid) - def get(self, uid: str, tag: str) -> dict: """ Returns form webhooks and date and time of form landing and submission. """ - return self.__client.request('get', '/forms/%s/webhooks/%s' % (uid,tag)) + return self.__client.request('get', '/forms/%s/webhooks/%s' % (uid, tag)) def create_update(self, uid: str, tag: str, data={}) -> dict: """ @@ -33,7 +31,7 @@ def create_update(self, uid: str, tag: str, data={}) -> dict: } """ return self.__client.request( - 'put', '/forms/%s/webhooks/%s' % (uid,tag), data=data + 'put', '/forms/%s/webhooks/%s' % (uid, tag), data=data ) def delete(self, uid: str, tag: str) -> str: @@ -41,4 +39,4 @@ def delete(self, uid: str, tag: str) -> str: Delete webhooks to a form. Return a `str` based on success of deletion, `OK` on success, otherwise an error message. """ - return self.__client.request('delete', '/forms/%s/webhooks/%s' % (uid,tag)) + return self.__client.request('delete', '/forms/%s/webhooks/%s' % (uid, tag)) From 6698b329cdd979686a3707b69d8b93c64508553c Mon Sep 17 00:00:00 2001 From: Craig Anderson Date: Mon, 19 Jul 2021 11:53:42 +0100 Subject: [PATCH 11/12] Get tests to pass --- typeform/test/fixtures.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/typeform/test/fixtures.py b/typeform/test/fixtures.py index 38c46f2..95b9af1 100644 --- a/typeform/test/fixtures.py +++ b/typeform/test/fixtures.py @@ -10,5 +10,5 @@ WORKSPACE = 'https://api.typeform.com/workspaces/hn3dNa' WORKSPACE_ID = WORKSPACE.split('/')[-1] -if MOCK and (not TOKEN or '[YOUR WORKSPACE ID]' in WORKSPACE): +if (not MOCK) and (not TOKEN or '[YOUR WORKSPACE ID]' in WORKSPACE): raise Exception('You need to setup TOKEN and WORKSPACE in fixtures.py') From cedfdbe5511269dc88e7f9739531a3858c5dccb0 Mon Sep 17 00:00:00 2001 From: Craig Anderson Date: Mon, 19 Jul 2021 12:03:28 +0100 Subject: [PATCH 12/12] Update Python versions. 3.5 reached its end of life and requests no longer supports it. --- .travis.yml | 11 +++++++---- setup.py | 3 ++- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index ff43d00..bdc42f1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,15 +1,18 @@ language: python matrix: include: - - python: 3.5 - dist: trusty - sudo: false - python: 3.6 dist: trusty sudo: false - python: 3.7 dist: xenial - sudo: true + sudo: false + - python: 3.8 + dist: xenial + sudo: false + - python: 3.9 + dist: xenial + sudo: false install: - python setup.py develop diff --git a/setup.py b/setup.py index e2c3351..ccd2f39 100644 --- a/setup.py +++ b/setup.py @@ -29,9 +29,10 @@ 'License :: OSI Approved :: MIT License', 'Operating System :: OS Independent', 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.7', + 'Programming Language :: Python :: 3.8', + 'Programming Language :: Python :: 3.9', 'Programming Language :: Python', ] )