From 8e1040b51addeee50769997b4b737ff8afe4c258 Mon Sep 17 00:00:00 2001 From: Russell Hay Date: Fri, 2 Sep 2016 15:47:46 -0700 Subject: [PATCH 1/3] Add automated test runs via travis (#8) --- .travis.yml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 000000000..656e169f7 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,17 @@ +language: python +python: + - "2.7" + - "3.3" + - "3.4" + - "3.5" + - "pypy" +# command to install dependencies +install: + - "pip install -e ." + # - "pip install pep8" +# command to run tests +script: + # Tests + - python setup.py test + # pep8 - disabled for now until we can scrub the files to make sure we pass before turning it on + # - pep8 . From 78f041b79097cdd36f1efa9906223133ee9844e4 Mon Sep 17 00:00:00 2001 From: shinchris Date: Tue, 6 Sep 2016 13:19:54 -0700 Subject: [PATCH 2/3] renamed keywords 'file' and 'input' --- tableauserverapi/server/filter.py | 6 ++-- test/test_auth.py | 20 ++++++------- test/test_datasource.py | 24 ++++++++-------- test/test_group.py | 24 ++++++++-------- test/test_project.py | 16 +++++------ test/test_request_option.py | 20 ++++++------- test/test_site.py | 16 +++++------ test/test_user.py | 24 ++++++++-------- test/test_view.py | 8 +++--- test/test_workbook.py | 48 +++++++++++++++---------------- 10 files changed, 103 insertions(+), 103 deletions(-) diff --git a/tableauserverapi/server/filter.py b/tableauserverapi/server/filter.py index fdb473c03..c02b66925 100644 --- a/tableauserverapi/server/filter.py +++ b/tableauserverapi/server/filter.py @@ -19,9 +19,9 @@ def value(self): return self._value @value.setter - def value(self, input): - if isinstance(input, list) and self.operator != RequestOptions.Operator.In: + def value(self, filter_value): + if isinstance(filter_value, list) and self.operator != RequestOptions.Operator.In: error = "Filter values can only be a list if the operator is 'in'." raise ValueError(error) else: - self._value = input + self._value = filter_value diff --git a/test/test_auth.py b/test/test_auth.py index 2efcb688d..8716ad110 100644 --- a/test/test_auth.py +++ b/test/test_auth.py @@ -16,8 +16,8 @@ def setUp(self): self.baseurl = self.server.auth.baseurl def test_sign_in(self): - with open(SIGN_IN_XML, 'rb') as file: - response_xml = file.read() + with open(SIGN_IN_XML, 'rb') as f: + response_xml = f.read() with requests_mock.mock() as m: m.post(self.baseurl + '/signin', text=response_xml) tableau_auth = TSA.TableauAuth('testuser', 'password', site='Samples') @@ -28,8 +28,8 @@ def test_sign_in(self): self.assertEqual('1a96d216-e9b8-497b-a82a-0b899a965e01', self.server.user_id) def test_sign_in_impersonate(self): - with open(SIGN_IN_IMPERSONATE_XML, 'rb') as file: - response_xml = file.read() + with open(SIGN_IN_IMPERSONATE_XML, 'rb') as f: + response_xml = f.read() with requests_mock.mock() as m: m.post(self.baseurl + '/signin', text=response_xml) tableau_auth = TSA.TableauAuth('testuser', @@ -42,24 +42,24 @@ def test_sign_in_impersonate(self): self.assertEqual('dd2239f6-ddf1-4107-981a-4cf94e415794', self.server.user_id) def test_sign_in_error(self): - with open(SIGN_IN_ERROR_XML, 'rb') as file: - response_xml = file.read() + with open(SIGN_IN_ERROR_XML, 'rb') as f: + response_xml = f.read() with requests_mock.mock() as m: m.post(self.baseurl + '/signin', text=response_xml, status_code=401) tableau_auth = TSA.TableauAuth('testuser', 'wrongpassword') self.assertRaises(TSA.ServerResponseError, self.server.auth.sign_in, tableau_auth) def test_sign_in_without_auth(self): - with open(SIGN_IN_ERROR_XML, 'rb') as file: - response_xml = file.read() + with open(SIGN_IN_ERROR_XML, 'rb') as f: + response_xml = f.read() with requests_mock.mock() as m: m.post(self.baseurl + '/signin', text=response_xml, status_code=401) tableau_auth = TSA.TableauAuth('', '') self.assertRaises(TSA.ServerResponseError, self.server.auth.sign_in, tableau_auth) def test_sign_out(self): - with open(SIGN_IN_XML, 'rb') as file: - response_xml = file.read() + with open(SIGN_IN_XML, 'rb') as f: + response_xml = f.read() with requests_mock.mock() as m: m.post(self.baseurl + '/signin', text=response_xml) m.post(self.baseurl + '/signout', text='') diff --git a/test/test_datasource.py b/test/test_datasource.py index 0224a7e2e..65f6472bf 100644 --- a/test/test_datasource.py +++ b/test/test_datasource.py @@ -23,8 +23,8 @@ def setUp(self): self.baseurl = self.server.datasources._construct_url() def test_get(self): - with open(GET_XML, 'rb') as file: - response_xml = file.read() + with open(GET_XML, 'rb') as f: + response_xml = f.read() with requests_mock.mock() as m: m.get(self.baseurl, text=response_xml) pagination_item, all_datasources = self.server.datasources.get() @@ -56,8 +56,8 @@ def test_get_before_signin(self): self.assertRaises(TSA.NotSignedInError, self.server.datasources.get) def test_get_empty(self): - with open(GET_EMPTY_XML, 'rb') as file: - response_xml = file.read() + with open(GET_EMPTY_XML, 'rb') as f: + response_xml = f.read() with requests_mock.mock() as m: m.get(self.baseurl, text=response_xml) pagination_item, all_datasources = self.server.datasources.get() @@ -66,8 +66,8 @@ def test_get_empty(self): self.assertEqual([], all_datasources) def test_get_by_id(self): - with open(GET_BY_ID_XML, 'rb') as file: - response_xml = file.read() + with open(GET_BY_ID_XML, 'rb') as f: + response_xml = f.read() with requests_mock.mock() as m: m.get(self.baseurl + '/9dbd2263-16b5-46e1-9c43-a76bb8ab65fb', text=response_xml) single_datasource = self.server.datasources.get_by_id('9dbd2263-16b5-46e1-9c43-a76bb8ab65fb') @@ -84,8 +84,8 @@ def test_get_by_id(self): self.assertEqual(set(['world', 'indicators', 'sample']), single_datasource.tags) def test_update(self): - with open(UPDATE_XML, 'rb') as file: - response_xml = file.read() + with open(UPDATE_XML, 'rb') as f: + response_xml = f.read() with requests_mock.mock() as m: m.put(self.baseurl + '/9dbd2263-16b5-46e1-9c43-a76bb8ab65fb', text=response_xml) single_datasource = TSA.DatasourceItem('test', '1d0304cd-3796-429f-b815-7258370b9b74') @@ -98,8 +98,8 @@ def test_update(self): self.assertEqual('dd2239f6-ddf1-4107-981a-4cf94e415794', single_datasource.owner_id) def test_update_copy_fields(self): - with open(UPDATE_XML, 'rb') as file: - response_xml = file.read() + with open(UPDATE_XML, 'rb') as f: + response_xml = f.read() with requests_mock.mock() as m: m.put(self.baseurl + '/9dbd2263-16b5-46e1-9c43-a76bb8ab65fb', text=response_xml) single_datasource = TSA.DatasourceItem('test', '1d0304cd-3796-429f-b815-7258370b9b74') @@ -112,8 +112,8 @@ def test_update_copy_fields(self): self.assertEqual(single_datasource._project_name, updated_datasource._project_name) def test_publish(self): - with open(PUBLISH_XML, 'rb') as file: - response_xml = file.read() + with open(PUBLISH_XML, 'rb') as f: + response_xml = f.read() with requests_mock.mock() as m: m.post(self.baseurl, text=response_xml) new_datasource = TSA.DatasourceItem('SampleDS', 'ee8c6e70-43b6-11e6-af4f-f7b0d8e20760') diff --git a/test/test_group.py b/test/test_group.py index 1c36a0d57..bc8f5dbb7 100644 --- a/test/test_group.py +++ b/test/test_group.py @@ -21,8 +21,8 @@ def setUp(self): self.baseurl = self.server.groups._construct_url() def test_get(self): - with open(GET_XML, 'rb') as file: - response_xml = file.read() + with open(GET_XML, 'rb') as f: + response_xml = f.read() with requests_mock.mock() as m: m.get(self.baseurl, text=response_xml) pagination_item, all_groups = self.server.groups.get() @@ -45,8 +45,8 @@ def test_get_before_signin(self): self.assertRaises(TSA.NotSignedInError, self.server.groups.get) def test_populate_users(self): - with open(POPULATE_USERS, 'rb') as file: - response_xml = file.read() + with open(POPULATE_USERS, 'rb') as f: + response_xml = f.read() with requests_mock.mock() as m: m.get(self.baseurl + '/e7833b48-c6f7-47b5-a2a7-36e7dd232758/users', text=response_xml) single_group = TSA.GroupItem(name='Test Group') @@ -66,8 +66,8 @@ def test_delete(self): self.server.groups.delete('e7833b48-c6f7-47b5-a2a7-36e7dd232758') def test_remove_user(self): - with open(POPULATE_USERS, 'rb') as file: - response_xml = file.read() + with open(POPULATE_USERS, 'rb') as f: + response_xml = f.read() with requests_mock.mock() as m: url = self.baseurl + '/e7833b48-c6f7-47b5-a2a7-36e7dd232758/users' \ '/dd2239f6-ddf1-4107-981a-4cf94e415794' @@ -82,8 +82,8 @@ def test_remove_user(self): self.assertEqual(0, len(single_group.users)) def test_add_user(self): - with open(ADD_USER, 'rb') as file: - response_xml = file.read() + with open(ADD_USER, 'rb') as f: + response_xml = f.read() with requests_mock.mock() as m: m.post(self.baseurl + '/e7833b48-c6f7-47b5-a2a7-36e7dd232758/users', text=response_xml) single_group = TSA.GroupItem('test') @@ -103,8 +103,8 @@ def test_add_user_before_populating(self): '5de011f8-5aa9-4d5b-b991-f462c8dd6bb7') def test_add_user_missing_user_id(self): - with open(POPULATE_USERS, 'rb') as file: - response_xml = file.read() + with open(POPULATE_USERS, 'rb') as f: + response_xml = f.read() with requests_mock.mock() as m: m.get(self.baseurl + '/e7833b48-c6f7-47b5-a2a7-36e7dd232758/users', text=response_xml) single_group = TSA.GroupItem(name='Test Group') @@ -125,8 +125,8 @@ def test_remove_user_before_populating(self): '5de011f8-5aa9-4d5b-b991-f462c8dd6bb7') def test_remove_user_missing_user_id(self): - with open(POPULATE_USERS, 'rb') as file: - response_xml = file.read() + with open(POPULATE_USERS, 'rb') as f: + response_xml = f.read() with requests_mock.mock() as m: m.get(self.baseurl + '/e7833b48-c6f7-47b5-a2a7-36e7dd232758/users', text=response_xml) single_group = TSA.GroupItem(name='Test Group') diff --git a/test/test_project.py b/test/test_project.py index 360c02f8d..4e53dae46 100644 --- a/test/test_project.py +++ b/test/test_project.py @@ -21,8 +21,8 @@ def setUp(self): self.baseurl = self.server.projects._construct_url() def test_get(self): - with open(GET_XML, 'rb') as file: - response_xml = file.read() + with open(GET_XML, 'rb') as f: + response_xml = f.read() with requests_mock.mock() as m: m.get(self.baseurl, text=response_xml) pagination_item, all_projects = self.server.projects.get() @@ -51,8 +51,8 @@ def test_delete_missing_id(self): self.assertRaises(ValueError, self.server.projects.delete, '') def test_update(self): - with open(UPDATE_XML, 'rb') as file: - response_xml = file.read() + with open(UPDATE_XML, 'rb') as f: + response_xml = f.read() with requests_mock.mock() as m: m.put(self.baseurl + '/1d0304cd-3796-429f-b815-7258370b9b74', text=response_xml) single_project = TSA.ProjectItem(name='Test Project', content_permissions='LockedToProject', @@ -66,8 +66,8 @@ def test_update(self): self.assertEqual('LockedToProject', single_project.content_permissions) def test_update_copy_fields(self): - with open(UPDATE_XML, 'rb') as file: - response_xml = file.read() + with open(UPDATE_XML, 'rb') as f: + response_xml = f.read() with requests_mock.mock() as m: m.put(self.baseurl + '/1d0304cd-3796-429f-b815-7258370b9b74', text=response_xml) single_project = TSA.ProjectItem('test') @@ -82,8 +82,8 @@ def test_update_missing_id(self): self.assertRaises(TSA.MissingRequiredFieldError, self.server.projects.update, single_project) def test_create(self): - with open(CREATE_XML, 'rb') as file: - response_xml = file.read() + with open(CREATE_XML, 'rb') as f: + response_xml = f.read() with requests_mock.mock() as m: m.post(self.baseurl, text=response_xml) new_project = TSA.ProjectItem(name='Test Project', description='Project created for testing') diff --git a/test/test_request_option.py b/test/test_request_option.py index a3d9ed276..6d22be958 100644 --- a/test/test_request_option.py +++ b/test/test_request_option.py @@ -23,8 +23,8 @@ def setUp(self): self.baseurl = '{0}/{1}'.format(self.server.sites._construct_url(), self.server._site_id) def test_pagination(self): - with open(PAGINATION_XML, 'rb') as file: - response_xml = file.read() + with open(PAGINATION_XML, 'rb') as f: + response_xml = f.read() with requests_mock.mock() as m: m.get(self.baseurl + '/views?pageNumber=1&pageSize=10', text=response_xml) req_option = TSA.RequestOptions().page_size(10) @@ -36,8 +36,8 @@ def test_pagination(self): self.assertEqual(10, len(all_views)) def test_page_number(self): - with open(PAGE_NUMBER_XML, 'rb') as file: - response_xml = file.read() + with open(PAGE_NUMBER_XML, 'rb') as f: + response_xml = f.read() with requests_mock.mock() as m: m.get(self.baseurl + '/views?pageNumber=3', text=response_xml) req_option = TSA.RequestOptions().page_number(3) @@ -49,8 +49,8 @@ def test_page_number(self): self.assertEqual(10, len(all_views)) def test_page_size(self): - with open(PAGE_SIZE_XML, 'rb') as file: - response_xml = file.read() + with open(PAGE_SIZE_XML, 'rb') as f: + response_xml = f.read() with requests_mock.mock() as m: m.get(self.baseurl + '/views?pageSize=5', text=response_xml) req_option = TSA.RequestOptions().page_size(5) @@ -62,8 +62,8 @@ def test_page_size(self): self.assertEqual(5, len(all_views)) def test_filter_equals(self): - with open(FILTER_EQUALS, 'rb') as file: - response_xml = file.read() + with open(FILTER_EQUALS, 'rb') as f: + response_xml = f.read() with requests_mock.mock() as m: m.get(self.baseurl + '/workbooks?filter=name:eq:RESTAPISample', text=response_xml) req_option = TSA.RequestOptions() @@ -76,8 +76,8 @@ def test_filter_equals(self): self.assertEqual('RESTAPISample', matching_workbooks[1].name) def test_filter_tags_in(self): - with open(FILTER_TAGS_IN, 'rb') as file: - response_xml = file.read() + with open(FILTER_TAGS_IN, 'rb') as f: + response_xml = f.read() with requests_mock.mock() as m: m.get(self.baseurl + '/workbooks?filter=tags:in:[sample,safari,weather]', text=response_xml) req_option = TSA.RequestOptions() diff --git a/test/test_site.py b/test/test_site.py index acbcffe56..becb3e2bb 100644 --- a/test/test_site.py +++ b/test/test_site.py @@ -21,8 +21,8 @@ def setUp(self): self.baseurl = self.server.sites._construct_url() def test_get(self): - with open(GET_XML, 'rb') as file: - response_xml = file.read() + with open(GET_XML, 'rb') as f: + response_xml = f.read() with requests_mock.mock() as m: m.get(self.baseurl, text=response_xml) pagination_item, all_sites = self.server.sites.get() @@ -47,8 +47,8 @@ def test_get_before_signin(self): self.assertRaises(TSA.NotSignedInError, self.server.sites.get) def test_get_by_id(self): - with open(GET_BY_ID_XML, 'rb') as file: - response_xml = file.read() + with open(GET_BY_ID_XML, 'rb') as f: + response_xml = f.read() with requests_mock.mock() as m: m.get(self.baseurl + '/dad65087-b08b-4603-af4e-2887b8aafc67', text=response_xml) single_site = self.server.sites.get_by_id('dad65087-b08b-4603-af4e-2887b8aafc67') @@ -65,8 +65,8 @@ def test_get_by_id_missing_id(self): self.assertRaises(ValueError, self.server.sites.get_by_id, '') def test_update(self): - with open(UPDATE_XML, 'rb') as file: - response_xml = file.read() + with open(UPDATE_XML, 'rb') as f: + response_xml = f.read() with requests_mock.mock() as m: m.put(self.baseurl + '/6b7179ba-b82b-4f0f-91ed-812074ac5da6', text=response_xml) single_site = TSA.SiteItem(name='Tableau', content_url='tableau', @@ -89,8 +89,8 @@ def test_update_missing_id(self): self.assertRaises(TSA.MissingRequiredFieldError, self.server.sites.update, single_site) def test_create(self): - with open(CREATE_XML, 'rb') as file: - response_xml = file.read() + with open(CREATE_XML, 'rb') as f: + response_xml = f.read() with requests_mock.mock() as m: m.post(self.baseurl, text=response_xml) new_site = TSA.SiteItem(name='Tableau', content_url='tableau', diff --git a/test/test_user.py b/test/test_user.py index 4d214c856..3dd7ec971 100644 --- a/test/test_user.py +++ b/test/test_user.py @@ -25,8 +25,8 @@ def setUp(self): self.baseurl = self.server.users._construct_url() def test_get(self): - with open(GET_XML, 'rb') as file: - response_xml = file.read() + with open(GET_XML, 'rb') as f: + response_xml = f.read() with requests_mock.mock() as m: m.get(self.baseurl, text=response_xml) pagination_item, all_users = self.server.users.get() @@ -42,8 +42,8 @@ def test_get(self): self.assertEqual('Interactor', all_users[1].site_role) def test_get_empty(self): - with open(GET_EMPTY_XML, 'rb') as file: - response_xml = file.read() + with open(GET_EMPTY_XML, 'rb') as f: + response_xml = f.read() with requests_mock.mock() as m: m.get(self.baseurl, text=response_xml) pagination_item, all_users = self.server.users.get() @@ -56,8 +56,8 @@ def test_get_before_signin(self): self.assertRaises(TSA.NotSignedInError, self.server.users.get) def test_get_by_id(self): - with open(GET_BY_ID_XML, 'rb') as file: - response_xml = file.read() + with open(GET_BY_ID_XML, 'rb') as f: + response_xml = f.read() with requests_mock.mock() as m: m.get(self.baseurl + '/dd2239f6-ddf1-4107-981a-4cf94e415794', text=response_xml) single_user = self.server.users.get_by_id('dd2239f6-ddf1-4107-981a-4cf94e415794') @@ -74,8 +74,8 @@ def test_get_by_id_missing_id(self): self.assertRaises(ValueError, self.server.users.get_by_id, '') def test_update(self): - with open(UPDATE_XML, 'rb') as file: - response_xml = file.read() + with open(UPDATE_XML, 'rb') as f: + response_xml = f.read() with requests_mock.mock() as m: m.put(self.baseurl + '/dd2239f6-ddf1-4107-981a-4cf94e415794', text=response_xml) single_user = TSA.UserItem('test', 'Viewer') @@ -104,8 +104,8 @@ def test_remove_missing_id(self): self.assertRaises(ValueError, self.server.users.remove, '') def test_add(self): - with open(ADD_XML, 'rb') as file: - response_xml = file.read() + with open(ADD_XML, 'rb') as f: + response_xml = f.read() with requests_mock.mock() as m: m.post(self.baseurl + '', text=response_xml) new_user = TSA.UserItem(name='Cassie', site_role='Viewer', auth_setting='ServerDefault') @@ -117,8 +117,8 @@ def test_add(self): self.assertEqual('ServerDefault', new_user.auth_setting) def test_populate_workbooks(self): - with open(POPULATE_WORKBOOKS_XML, 'rb') as file: - response_xml = file.read() + with open(POPULATE_WORKBOOKS_XML, 'rb') as f: + response_xml = f.read() with requests_mock.mock() as m: m.get(self.baseurl + '/dd2239f6-ddf1-4107-981a-4cf94e415794/workbooks', text=response_xml) diff --git a/test/test_view.py b/test/test_view.py index 3b8bbee8c..ea807f536 100644 --- a/test/test_view.py +++ b/test/test_view.py @@ -20,8 +20,8 @@ def setUp(self): self.baseurl = self.server.views._construct_url() def test_get(self): - with open(GET_XML, 'rb') as file: - response_xml = file.read() + with open(GET_XML, 'rb') as f: + response_xml = f.read() with requests_mock.mock() as m: m.get(self.baseurl + '/views', text=response_xml) pagination_item, all_views = self.server.views.get() @@ -44,8 +44,8 @@ def test_get_before_signin(self): self.assertRaises(TSA.NotSignedInError, self.server.views.get) def test_populate_preview_image(self): - with open(POPULATE_PREVIEW_IMAGE, 'rb') as file: - response = file.read() + with open(POPULATE_PREVIEW_IMAGE, 'rb') as f: + response = f.read() with requests_mock.mock() as m: m.get(self.baseurl + '/workbooks/3cc6cd06-89ce-4fdc-b935-5294135d6d42/' 'views/d79634e1-6063-4ec9-95ff-50acbf609ff5/previewImage', content=response) diff --git a/test/test_workbook.py b/test/test_workbook.py index 963e89e2b..81ad17ad0 100644 --- a/test/test_workbook.py +++ b/test/test_workbook.py @@ -27,8 +27,8 @@ def setUp(self): self.baseurl = self.server.workbooks._construct_url() def test_get(self): - with open(GET_XML, 'rb') as file: - response_xml = file.read() + with open(GET_XML, 'rb') as f: + response_xml = f.read() with requests_mock.mock() as m: m.get(self.baseurl, text=response_xml) pagination_item, all_workbooks = self.server.workbooks.get() @@ -62,8 +62,8 @@ def test_get_before_signin(self): self.assertRaises(TSA.NotSignedInError, self.server.workbooks.get) def test_get_empty(self): - with open(GET_EMPTY_XML, 'rb') as file: - response_xml = file.read() + with open(GET_EMPTY_XML, 'rb') as f: + response_xml = f.read() with requests_mock.mock() as m: m.get(self.baseurl, text=response_xml) pagination_item, all_workbooks = self.server.workbooks.get() @@ -72,8 +72,8 @@ def test_get_empty(self): self.assertEqual([], all_workbooks) def test_get_by_id(self): - with open(GET_BY_ID_XML, 'rb') as file: - response_xml = file.read() + with open(GET_BY_ID_XML, 'rb') as f: + response_xml = f.read() with requests_mock.mock() as m: m.get(self.baseurl + '/3cc6cd06-89ce-4fdc-b935-5294135d6d42', text=response_xml) single_workbook = self.server.workbooks.get_by_id('3cc6cd06-89ce-4fdc-b935-5294135d6d42') @@ -105,8 +105,8 @@ def test_delete_missing_id(self): self.assertRaises(ValueError, self.server.workbooks.delete, '') def test_update(self): - with open(UPDATE_XML, 'rb') as file: - response_xml = file.read() + with open(UPDATE_XML, 'rb') as f: + response_xml = f.read() with requests_mock.mock() as m: m.put(self.baseurl + '/1f951daf-4061-451a-9df1-69a8062664f2', text=response_xml) single_workbook = TSA.WorkbookItem('1d0304cd-3796-429f-b815-7258370b9b74', show_tabs=True) @@ -124,10 +124,10 @@ def test_update_missing_id(self): self.assertRaises(TSA.MissingRequiredFieldError, self.server.workbooks.update, single_workbook) def test_update_copy_fields(self): - with open(POPULATE_CONNECTIONS_XML, 'rb') as file: - connection_xml = file.read() - with open(UPDATE_XML, 'rb') as file: - update_xml = file.read() + with open(POPULATE_CONNECTIONS_XML, 'rb') as f: + connection_xml = f.read() + with open(UPDATE_XML, 'rb') as f: + update_xml = f.read() with requests_mock.mock() as m: m.get(self.baseurl + '/1f951daf-4061-451a-9df1-69a8062664f2/connections', text=connection_xml) m.put(self.baseurl + '/1f951daf-4061-451a-9df1-69a8062664f2', text=update_xml) @@ -143,10 +143,10 @@ def test_update_copy_fields(self): self.assertEqual(single_workbook._preview_image, updated_workbook._preview_image) def test_update_tags(self): - with open(ADD_TAGS_XML, 'rb') as file: - add_tags_xml = file.read() - with open(UPDATE_XML, 'rb') as file: - update_xml = file.read() + with open(ADD_TAGS_XML, 'rb') as f: + add_tags_xml = f.read() + with open(UPDATE_XML, 'rb') as f: + update_xml = f.read() with requests_mock.mock() as m: m.put(self.baseurl + '/1f951daf-4061-451a-9df1-69a8062664f2/tags', text=add_tags_xml) m.delete(self.baseurl + '/1f951daf-4061-451a-9df1-69a8062664f2/tags/b', status_code=204) @@ -173,8 +173,8 @@ def test_download_missing_id(self): self.assertRaises(ValueError, self.server.workbooks.download, '') def test_populate_views(self): - with open(POPULATE_VIEWS_XML, 'rb') as file: - response_xml = file.read() + with open(POPULATE_VIEWS_XML, 'rb') as f: + response_xml = f.read() with requests_mock.mock() as m: m.get(self.baseurl + '/1f951daf-4061-451a-9df1-69a8062664f2/views', text=response_xml) single_workbook = TSA.WorkbookItem('test') @@ -199,8 +199,8 @@ def test_populate_views_missing_id(self): self.assertRaises(TSA.MissingRequiredFieldError, self.server.workbooks.populate_views, single_workbook) def test_populate_connections(self): - with open(POPULATE_CONNECTIONS_XML, 'rb') as file: - response_xml = file.read() + with open(POPULATE_CONNECTIONS_XML, 'rb') as f: + response_xml = f.read() with requests_mock.mock() as m: m.get(self.baseurl + '/1f951daf-4061-451a-9df1-69a8062664f2/connections', text=response_xml) single_workbook = TSA.WorkbookItem('test') @@ -219,8 +219,8 @@ def test_populate_connections_missing_id(self): single_workbook) def test_populate_preview_image(self): - with open(POPULATE_PREVIEW_IMAGE, 'rb') as file: - response = file.read() + with open(POPULATE_PREVIEW_IMAGE, 'rb') as f: + response = f.read() with requests_mock.mock() as m: m.get(self.baseurl + '/1f951daf-4061-451a-9df1-69a8062664f2/previewImage', content=response) single_workbook = TSA.WorkbookItem('test') @@ -236,8 +236,8 @@ def test_populate_preview_image_missing_id(self): single_workbook) def test_publish(self): - with open(PUBLISH_XML, 'rb') as file: - response_xml = file.read() + with open(PUBLISH_XML, 'rb') as f: + response_xml = f.read() with requests_mock.mock() as m: m.post(self.baseurl, text=response_xml) new_workbook = TSA.WorkbookItem(name='Sample', show_tabs=False, From 026724abecae12f9b9b1ac63a2b34a74bf38218c Mon Sep 17 00:00:00 2001 From: shinchris Date: Tue, 6 Sep 2016 13:54:12 -0700 Subject: [PATCH 3/3] reorganized properties and added checks for preview images --- tableauserverapi/models/connection_item.py | 24 ++-- tableauserverapi/models/datasource_item.py | 90 ++++++------ tableauserverapi/models/fileupload_item.py | 2 +- tableauserverapi/models/group_item.py | 22 +-- tableauserverapi/models/pagination_item.py | 8 +- tableauserverapi/models/project_item.py | 56 ++++---- tableauserverapi/models/site_item.py | 157 +++++++++++---------- tableauserverapi/models/user_item.py | 94 ++++++------ tableauserverapi/models/view_item.py | 30 ++-- tableauserverapi/models/workbook_item.py | 100 +++++++------ 10 files changed, 302 insertions(+), 281 deletions(-) diff --git a/tableauserverapi/models/connection_item.py b/tableauserverapi/models/connection_item.py index f3ab7ff18..507b3a580 100644 --- a/tableauserverapi/models/connection_item.py +++ b/tableauserverapi/models/connection_item.py @@ -4,23 +4,15 @@ class ConnectionItem(object): def __init__(self): - self._id = None - self._type = None self._datasource_id = None self._datasource_name = None + self._id = None + self._type = None + self.embed_password = None + self.password = None self.server_address = None self.server_port = None self.username = None - self.password = None - self.embed_password = None - - @property - def id(self): - return self._id - - @property - def type(self): - return self._type @property def datasource_id(self): @@ -30,6 +22,14 @@ def datasource_id(self): def datasource_name(self): return self._datasource_name + @property + def id(self): + return self._id + + @property + def type(self): + return self._type + @classmethod def from_response(cls, resp): all_connection_items = list() diff --git a/tableauserverapi/models/datasource_item.py b/tableauserverapi/models/datasource_item.py index 783df53f8..82ecf32aa 100644 --- a/tableauserverapi/models/datasource_item.py +++ b/tableauserverapi/models/datasource_item.py @@ -6,38 +6,27 @@ class DatasourceItem(object): def __init__(self, project_id, name=None): + self._connections = None self._content_url = None self._created_at = None self._id = None + self._project_id = None self._project_name = None self._tags = set() self._type = None self._updated_at = None - self._connections = None - self._project_id = None - self.owner_id = None - self.project_id = project_id self.name = name + self.owner_id = None - @property - def project_id(self): - return self._project_id - - @project_id.setter - def project_id(self, value): - if value is None: - error = 'Project ID must be defined.' - raise ValueError(error) - else: - self._project_id = value - - @property - def id(self): - return self._id + # Invoke setter + self.project_id = project_id @property - def type(self): - return self._type + def connections(self): + if self._connections is None: + error = 'Datasource item must be populated with connections first.' + raise UnpopulatedPropertyError(error) + return self._connections @property def content_url(self): @@ -48,8 +37,20 @@ def created_at(self): return self._created_at @property - def updated_at(self): - return self._updated_at + def id(self): + return self._id + + @property + def project_id(self): + return self._project_id + + @project_id.setter + def project_id(self, value): + if value is None: + error = 'Project ID must be defined.' + raise ValueError(error) + else: + self._project_id = value @property def project_name(self): @@ -60,30 +61,16 @@ def tags(self): return self._tags @property - def connections(self): - if self._connections is None: - error = 'Datasource item must be populated with connections first.' - raise UnpopulatedPropertyError(error) - return self._connections + def type(self): + return self._type + + @property + def updated_at(self): + return self._updated_at def _set_connections(self, connections): self._connections = connections - @classmethod - def from_response(cls, resp): - all_datasource_items = list() - parsed_response = ET.fromstring(resp) - all_datasource_xml = parsed_response.findall('.//t:datasource', namespaces=NAMESPACE) - - for datasource_xml in all_datasource_xml: - (id, name, type, content_url, created_at, updated_at, - tags, project_id, project_name, owner_id) = cls._parse_element(datasource_xml) - datasource_item = cls(project_id) - datasource_item._set_values(id, name, type, content_url, created_at, updated_at, - tags, None, project_name, owner_id) - all_datasource_items.append(datasource_item) - return all_datasource_items - def _parse_common_tags(self, datasource_xml): if not isinstance(datasource_xml, ET.Element): datasource_xml = ET.fromstring(datasource_xml).find('.//t:datasource', namespaces=NAMESPACE) @@ -115,6 +102,21 @@ def _set_values(self, id, name, type, content_url, created_at, if owner_id: self.owner_id = owner_id + @classmethod + def from_response(cls, resp): + all_datasource_items = list() + parsed_response = ET.fromstring(resp) + all_datasource_xml = parsed_response.findall('.//t:datasource', namespaces=NAMESPACE) + + for datasource_xml in all_datasource_xml: + (id, name, type, content_url, created_at, updated_at, + tags, project_id, project_name, owner_id) = cls._parse_element(datasource_xml) + datasource_item = cls(project_id) + datasource_item._set_values(id, name, type, content_url, created_at, updated_at, + tags, None, project_name, owner_id) + all_datasource_items.append(datasource_item) + return all_datasource_items + @staticmethod def _parse_element(datasource_xml): id = datasource_xml.get('id', None) @@ -141,4 +143,4 @@ def _parse_element(datasource_xml): if owner_elem is not None: owner_id = owner_elem.get('id', None) - return id, name, type, content_url, created_at, updated_at, tags, project_id, project_name, owner_id \ No newline at end of file + return id, name, type, content_url, created_at, updated_at, tags, project_id, project_name, owner_id diff --git a/tableauserverapi/models/fileupload_item.py b/tableauserverapi/models/fileupload_item.py index 685fd8555..329f04caa 100644 --- a/tableauserverapi/models/fileupload_item.py +++ b/tableauserverapi/models/fileupload_item.py @@ -4,8 +4,8 @@ class FileuploadItem(object): def __init__(self): - self._upload_session_id = None self._file_size = None + self._upload_session_id = None @property def upload_session_id(self): diff --git a/tableauserverapi/models/group_item.py b/tableauserverapi/models/group_item.py index 095d734d6..adb54d9db 100644 --- a/tableauserverapi/models/group_item.py +++ b/tableauserverapi/models/group_item.py @@ -5,12 +5,22 @@ class GroupItem(object): def __init__(self, name): - self._id = None self._domain_name = None - self._users = None + self._id = None self._name = None + self._users = None + + # Invoke setter self.name = name + @property + def domain_name(self): + return self._domain_name + + @property + def id(self): + return self._id + @property def name(self): return self._name @@ -23,14 +33,6 @@ def name(self, value): else: self._name = value - @property - def id(self): - return self._id - - @property - def domain_name(self): - return self._domain_name - @property def users(self): if self._users is None: diff --git a/tableauserverapi/models/pagination_item.py b/tableauserverapi/models/pagination_item.py index 5ff896922..4fffe1bae 100644 --- a/tableauserverapi/models/pagination_item.py +++ b/tableauserverapi/models/pagination_item.py @@ -8,10 +8,6 @@ def __init__(self): self._page_size = None self._total_available = None - @property - def total_available(self): - return self._total_available - @property def page_number(self): return self._page_number @@ -20,6 +16,10 @@ def page_number(self): def page_size(self): return self._page_size + @property + def total_available(self): + return self._total_available + @classmethod def from_response(cls, resp): parsed_response = ET.fromstring(resp) diff --git a/tableauserverapi/models/project_item.py b/tableauserverapi/models/project_item.py index 7dc983fc9..768d5f16e 100644 --- a/tableauserverapi/models/project_item.py +++ b/tableauserverapi/models/project_item.py @@ -8,10 +8,12 @@ class ContentPermissions: ManagedByOwner = 'ManagedByOwner' def __init__(self, name, description=None, content_permissions=None): - self._id = None self._content_permissions = None + self._id = None self._name = None self.description = description + + # Invoke setter self.name = name if content_permissions: @@ -19,21 +21,6 @@ def __init__(self, name, description=None, content_permissions=None): # _content_permissions must be initialized first. self.content_permissions = content_permissions - def is_default(self): - return self.name.lower() == 'default' - - @property - def name(self): - return self._name - - @name.setter - def name(self, value): - if not value: - error = 'Name must be defined.' - raise ValueError(error) - else: - self._name = value - @property def content_permissions(self): return self._content_permissions @@ -50,18 +37,20 @@ def content_permissions(self, value): def id(self): return self._id - @classmethod - def from_response(cls, resp): - all_project_items = list() - parsed_response = ET.fromstring(resp) - all_project_xml = parsed_response.findall('.//t:project', namespaces=NAMESPACE) + @property + def name(self): + return self._name - for project_xml in all_project_xml: - (id, name, description, content_permissions) = cls._parse_element(project_xml) - project_item = cls(name) - project_item._set_values(id, name, description, content_permissions) - all_project_items.append(project_item) - return all_project_items + @name.setter + def name(self, value): + if not value: + error = 'Name must be defined.' + raise ValueError(error) + else: + self._name = value + + def is_default(self): + return self.name.lower() == 'default' def _parse_common_tags(self, project_xml): if not isinstance(project_xml, ET.Element): @@ -82,6 +71,19 @@ def _set_values(self, project_id, name, description, content_permissions): if content_permissions: self._content_permissions = content_permissions + @classmethod + def from_response(cls, resp): + all_project_items = list() + parsed_response = ET.fromstring(resp) + all_project_xml = parsed_response.findall('.//t:project', namespaces=NAMESPACE) + + for project_xml in all_project_xml: + (id, name, description, content_permissions) = cls._parse_element(project_xml) + project_item = cls(name) + project_item._set_values(id, name, description, content_permissions) + all_project_items.append(project_item) + return all_project_items + @staticmethod def _parse_element(project_xml): id = project_xml.get('id', None) diff --git a/tableauserverapi/models/site_item.py b/tableauserverapi/models/site_item.py index 75c5555ea..f2791ed6a 100644 --- a/tableauserverapi/models/site_item.py +++ b/tableauserverapi/models/site_item.py @@ -13,25 +13,27 @@ class State: def __init__(self, name, content_url, admin_mode=None, user_quota=None, storage_quota=None, disable_subscriptions=False, subscribe_others_enabled=True, revision_history_enabled=False): + self._admin_mode = None + self._content_url = None + self._disable_subscriptions = None self._id = None - self._status_reason = None + self._name = None self._num_users = None - self._storage = None - self._admin_mode = None + self._revision_history_enabled = None self._state = None - self._name = None - self._content_url = None + self._status_reason = None + self._storage = None self._subscribe_others_enabled = None - self._revision_history_enabled = None - self._disable_subscriptions = None - self.subscribe_others_enabled = subscribe_others_enabled - self.revision_history_enabled = revision_history_enabled - self.disable_subscriptions = disable_subscriptions self.revision_limit = None self.user_quota = user_quota self.storage_quota = storage_quota - self.name = name + + # Invoke setter self.content_url = content_url + self.disable_subscriptions = disable_subscriptions + self.name = name + self.revision_history_enabled = revision_history_enabled + self.subscribe_others_enabled = subscribe_others_enabled if admin_mode: # In order to invoke the setter method to validate admin_mode, @@ -39,28 +41,28 @@ def __init__(self, name, content_url, admin_mode=None, user_quota=None, storage_ self.admin_mode = admin_mode @property - def subscribe_others_enabled(self): - return self._subscribe_others_enabled + def admin_mode(self): + return self._admin_mode - @subscribe_others_enabled.setter - def subscribe_others_enabled(self, value): - if not isinstance(value, bool): - error = 'Boolean expected for subscribe_others_enabled flag.' + @admin_mode.setter + def admin_mode(self, value): + if value and not hasattr(SiteItem.AdminMode, value): + error = 'Invalid admin mode defined.' raise ValueError(error) else: - self._subscribe_others_enabled = value + self._admin_mode = value @property - def revision_history_enabled(self): - return self._revision_history_enabled + def content_url(self): + return self._content_url - @revision_history_enabled.setter - def revision_history_enabled(self, value): - if not isinstance(value, bool): - error = 'Boolean expected for revision_history_enabled flag.' + @content_url.setter + def content_url(self, value): + if value is None: + error = 'Content URL must be defined.' raise ValueError(error) else: - self._revision_history_enabled = value + self._content_url = value @property def disable_subscriptions(self): @@ -75,28 +77,8 @@ def disable_subscriptions(self, value): self._disable_subscriptions = value @property - def admin_mode(self): - return self._admin_mode - - @admin_mode.setter - def admin_mode(self, value): - if value and not hasattr(SiteItem.AdminMode, value): - error = 'Invalid admin mode defined.' - raise ValueError(error) - else: - self._admin_mode = value - - @property - def state(self): - return self._state - - @state.setter - def state(self, value): - if not hasattr(SiteItem.State, value): - error = 'Invalid state defined.' - raise ValueError(error) - else: - self._state = value + def id(self): + return self._id @property def name(self): @@ -111,52 +93,55 @@ def name(self, value): self._name = value @property - def content_url(self): - return self._content_url + def num_users(self): + return self._num_users - @content_url.setter - def content_url(self, value): - if value is None: - error = 'Content URL must be defined.' + @property + def revision_history_enabled(self): + return self._revision_history_enabled + + @revision_history_enabled.setter + def revision_history_enabled(self, value): + if not isinstance(value, bool): + error = 'Boolean expected for revision_history_enabled flag.' raise ValueError(error) else: - self._content_url = value + self._revision_history_enabled = value @property - def id(self): - return self._id + def state(self): + return self._state + + @state.setter + def state(self, value): + if not hasattr(SiteItem.State, value): + error = 'Invalid state defined.' + raise ValueError(error) + else: + self._state = value @property def status_reason(self): return self._status_reason - @property - def num_users(self): - return self._num_users - @property def storage(self): return self._storage - def is_default(self): - return self.name.lower() == 'default' + @property + def subscribe_others_enabled(self): + return self._subscribe_others_enabled - @classmethod - def from_response(cls, resp): - all_site_items = list() - parsed_response = ET.fromstring(resp) - all_site_xml = parsed_response.findall('.//t:site', namespaces=NAMESPACE) - for site_xml in all_site_xml: - (id, name, content_url, status_reason, admin_mode, state, subscribe_others_enabled, - disable_subscriptions, revision_history_enabled, user_quota, storage_quota, - revision_limit, num_users, storage) = cls._parse_element(site_xml) + @subscribe_others_enabled.setter + def subscribe_others_enabled(self, value): + if not isinstance(value, bool): + error = 'Boolean expected for subscribe_others_enabled flag.' + raise ValueError(error) + else: + self._subscribe_others_enabled = value - site_item = cls(name, content_url) - site_item._set_values(id, name, content_url, status_reason, admin_mode, state, - subscribe_others_enabled, disable_subscriptions, revision_history_enabled, - user_quota, storage_quota, revision_limit, num_users, storage) - all_site_items.append(site_item) - return all_site_items + def is_default(self): + return self.name.lower() == 'default' def _parse_common_tags(self, site_xml): if not isinstance(site_xml, ET.Element): @@ -203,6 +188,23 @@ def _set_values(self, id, name, content_url, status_reason, admin_mode, state, if storage: self._storage = storage + @classmethod + def from_response(cls, resp): + all_site_items = list() + parsed_response = ET.fromstring(resp) + all_site_xml = parsed_response.findall('.//t:site', namespaces=NAMESPACE) + for site_xml in all_site_xml: + (id, name, content_url, status_reason, admin_mode, state, subscribe_others_enabled, + disable_subscriptions, revision_history_enabled, user_quota, storage_quota, + revision_limit, num_users, storage) = cls._parse_element(site_xml) + + site_item = cls(name, content_url) + site_item._set_values(id, name, content_url, status_reason, admin_mode, state, + subscribe_others_enabled, disable_subscriptions, revision_history_enabled, + user_quota, storage_quota, revision_limit, num_users, storage) + all_site_items.append(site_item) + return all_site_items + @staticmethod def _parse_element(site_xml): id = site_xml.get('id', None) @@ -239,5 +241,6 @@ def _parse_element(site_xml): revision_limit, num_users, storage +# Used to convert string represented boolean to a boolean type def string_to_bool(s): return s.lower() == 'true' diff --git a/tableauserverapi/models/user_item.py b/tableauserverapi/models/user_item.py index 49e4aacc0..961dfe3ab 100644 --- a/tableauserverapi/models/user_item.py +++ b/tableauserverapi/models/user_item.py @@ -19,17 +19,19 @@ class Auth: ServerDefault = 'ServerDefault' def __init__(self, name, site_role, auth_setting=None): + self._auth_setting = None + self._domain_name = None + self._external_auth_user_id = None self._id = None self._last_login = None - self._external_auth_user_id = None - self._domain_name = None - self._workbooks = None self._name = None self._site_role = None - self._auth_setting = None + self._workbooks = None self.email = None self.fullname = None self.password = None + + # Invoke setter self.name = name self.site_role = site_role @@ -38,6 +40,34 @@ def __init__(self, name, site_role, auth_setting=None): # _auth_setting must be initialized first self.auth_setting = auth_setting + @property + def auth_setting(self): + return self._auth_setting + + @auth_setting.setter + def auth_setting(self, value): + if not hasattr(UserItem.Auth, value): + error = 'Invalid auth setting defined.' + raise ValueError(error) + else: + self._auth_setting = value + + @property + def domain_name(self): + return self._domain_name + + @property + def external_auth_user_id(self): + return self._external_auth_user_id + + @property + def id(self): + return self._id + + @property + def last_login(self): + return self._last_login + @property def name(self): return self._name @@ -65,34 +95,6 @@ def site_role(self, value): else: self._site_role = value - @property - def auth_setting(self): - return self._auth_setting - - @auth_setting.setter - def auth_setting(self, value): - if not hasattr(UserItem.Auth, value): - error = 'Invalid auth setting defined.' - raise ValueError(error) - else: - self._auth_setting = value - - @property - def id(self): - return self._id - - @property - def last_login(self): - return self._last_login - - @property - def external_auth_user_id(self): - return self._external_auth_user_id - - @property - def domain_name(self): - return self._domain_name - @property def workbooks(self): if self._workbooks is None: @@ -103,20 +105,6 @@ def workbooks(self): def _set_workbooks(self, workbooks): self._workbooks = workbooks - @classmethod - def from_response(cls, resp): - all_user_items = set() - parsed_response = ET.fromstring(resp) - all_user_xml = parsed_response.findall('.//t:user', namespaces=NAMESPACE) - for user_xml in all_user_xml: - (id, name, site_role, last_login, external_auth_user_id, - fullname, email, auth_setting, domain_name) = cls._parse_element(user_xml) - user_item = cls(name, site_role) - user_item._set_values(id, name, site_role, last_login, external_auth_user_id, - fullname, email, auth_setting, domain_name) - all_user_items.add(user_item) - return all_user_items - def _parse_common_tags(self, user_xml): if not isinstance(user_xml, ET.Element): user_xml = ET.fromstring(user_xml).find('.//t:user', namespaces=NAMESPACE) @@ -146,6 +134,20 @@ def _set_values(self, id, name, site_role, last_login, if domain_name: self._domain_name = domain_name + @classmethod + def from_response(cls, resp): + all_user_items = set() + parsed_response = ET.fromstring(resp) + all_user_xml = parsed_response.findall('.//t:user', namespaces=NAMESPACE) + for user_xml in all_user_xml: + (id, name, site_role, last_login, external_auth_user_id, + fullname, email, auth_setting, domain_name) = cls._parse_element(user_xml) + user_item = cls(name, site_role) + user_item._set_values(id, name, site_role, last_login, external_auth_user_id, + fullname, email, auth_setting, domain_name) + all_user_items.add(user_item) + return all_user_items + @staticmethod def _parse_element(user_xml): id = user_xml.get('id', None) diff --git a/tableauserverapi/models/view_item.py b/tableauserverapi/models/view_item.py index 4f9d7d4b3..9df61bc1a 100644 --- a/tableauserverapi/models/view_item.py +++ b/tableauserverapi/models/view_item.py @@ -1,16 +1,21 @@ import xml.etree.ElementTree as ET +from exceptions import UnpopulatedPropertyError from .. import NAMESPACE class ViewItem(object): def __init__(self): + self._content_url = None self._id = None self._name = None - self._content_url = None - self._total_views = None - self._workbook_id = None self._owner_id = None self._preview_image = None + self._total_views = None + self._workbook_id = None + + @property + def content_url(self): + return self._content_url @property def id(self): @@ -21,8 +26,15 @@ def name(self): return self._name @property - def content_url(self): - return self._content_url + def owner_id(self): + return self._owner_id + + @property + def preview_image(self): + if self._preview_image is None: + error = "View item must be populated with its preview image first." + raise UnpopulatedPropertyError(error) + return self._preview_image @property def total_views(self): @@ -32,14 +44,6 @@ def total_views(self): def workbook_id(self): return self._workbook_id - @property - def owner_id(self): - return self._owner_id - - @property - def preview_image(self): - return self._preview_image - @classmethod def from_response(cls, resp, workbook_id=''): return cls.from_xml_element(ET.fromstring(resp), workbook_id) diff --git a/tableauserverapi/models/workbook_item.py b/tableauserverapi/models/workbook_item.py index 8b45628ad..f53cea95e 100644 --- a/tableauserverapi/models/workbook_item.py +++ b/tableauserverapi/models/workbook_item.py @@ -13,19 +13,47 @@ def __init__(self, project_id, name=None, show_tabs=False): self._created_at = None self._id = None self._initial_tags = set() - self._project_name = None self._preview_image = None + self._project_id = None + self._project_name = None + self._show_tabs = None self._size = None self._updated_at = None self._views = None - self._show_tabs = None - self._project_id = None - self.show_tabs = show_tabs self.name = name - self.project_id = project_id self.owner_id = None self.tags = set() + # Invoke setter + self.project_id = project_id + self.show_tabs = show_tabs + + @property + def connections(self): + if self._connections is None: + error = "Workbook item must be populated with connections first." + raise UnpopulatedPropertyError(error) + return self._connections + + @property + def content_url(self): + return self._content_url + + @property + def created_at(self): + return self._created_at + + @property + def id(self): + return self._id + + @property + def preview_image(self): + if self._preview_image is None: + error = "Workbook item must be populated with its preview image first." + raise UnpopulatedPropertyError(error) + return self._preview_image + @property def project_id(self): return self._project_id @@ -38,6 +66,10 @@ def project_id(self, value): else: self._project_id = value + @property + def project_name(self): + return self._project_name + @property def show_tabs(self): return self._show_tabs @@ -50,30 +82,14 @@ def show_tabs(self, value): else: self._show_tabs = value - @property - def id(self): - return self._id - - @property - def content_url(self): - return self._content_url - @property def size(self): return self._size - @property - def created_at(self): - return self._created_at - @property def updated_at(self): return self._updated_at - @property - def project_name(self): - return self._project_name - @property def views(self): if self._views is None: @@ -81,17 +97,6 @@ def views(self): raise UnpopulatedPropertyError(error) return self._views - @property - def connections(self): - if self._connections is None: - error = "Workbook item must be populated with connections first." - raise UnpopulatedPropertyError(error) - return self._connections - - @property - def preview_image(self): - return self._preview_image - def _set_connections(self, connections): self._connections = connections @@ -107,21 +112,6 @@ def _set_initial_tags(self, initial_tags): def _get_initial_tags(self): return self._initial_tags - @classmethod - def from_response(cls, resp): - all_workbook_items = list() - parsed_response = ET.fromstring(resp) - all_workbook_xml = parsed_response.findall('.//t:workbook', namespaces=NAMESPACE) - for workbook_xml in all_workbook_xml: - (id, name, content_url, created_at, updated_at, size, show_tabs, - project_id, project_name, owner_id, tags, views) = cls._parse_element(workbook_xml) - - workbook_item = cls(project_id) - workbook_item._set_values(id, name, content_url, created_at, updated_at, - size, show_tabs, None, project_name, owner_id, tags, views) - all_workbook_items.append(workbook_item) - return all_workbook_items - def _parse_common_tags(self, workbook_xml): if not isinstance(workbook_xml, ET.Element): workbook_xml = ET.fromstring(workbook_xml).find('.//t:workbook', namespaces=NAMESPACE) @@ -162,6 +152,21 @@ def _set_values(self, id, name, content_url, created_at, updated_at, if views: self._views = views + @classmethod + def from_response(cls, resp): + all_workbook_items = list() + parsed_response = ET.fromstring(resp) + all_workbook_xml = parsed_response.findall('.//t:workbook', namespaces=NAMESPACE) + for workbook_xml in all_workbook_xml: + (id, name, content_url, created_at, updated_at, size, show_tabs, + project_id, project_name, owner_id, tags, views) = cls._parse_element(workbook_xml) + + workbook_item = cls(project_id) + workbook_item._set_values(id, name, content_url, created_at, updated_at, + size, show_tabs, None, project_name, owner_id, tags, views) + all_workbook_items.append(workbook_item) + return all_workbook_items + @staticmethod def _parse_element(workbook_xml): id = workbook_xml.get('id', None) @@ -203,5 +208,6 @@ def _parse_element(workbook_xml): project_id, project_name, owner_id, tags, views +# Used to convert string represented boolean to a boolean type def string_to_bool(s): return s.lower() == 'true'