8000 added ability to get usage statistics for views (#242) · sbttc/server-client-python@fa7e568 · GitHub
[go: up one dir, main page]

Skip to content

Commit fa7e568

Browse files
authored
added ability to get usage statistics for views (tableau#242)
* added ability to get usage statistics for views
1 parent 262d32f commit fa7e568

File tree

8 files changed

+97
-5
lines changed

8 files changed

+97
-5
lines changed

tableauserverclient/models/view_item.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,9 @@ def csv(self):
7575

7676
@property
7777
def total_views(self):
78+
if self._total_views is None:
79+
error = "Usage statistics must be requested when querying for view."
80+
raise UnpopulatedPropertyError(error)
7881
return self._total_views
7982

8083
@property

tableauserverclient/server/endpoint/views_endpoint.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,12 @@ def baseurl(self):
2424
return "{0}/views".format(self.siteurl)
2525

2626
@api(version="2.2")
27-
def get(self, req_options=None):
27+
def get(self, req_options=None, usage=False):
2828
logger.info('Querying all views on site')
29-
server_response = self.get_request(self.baseurl, req_options)
29+
url = self.baseurl
30+
if usage:
31+
url += "?includeUsageStatistics=true"
32+
server_response = self.get_request(url, req_options)
3033
pagination_item = PaginationItem.from_response(server_response.content, self.parent_srv.namespace)
3134
all_view_items = ViewItem.from_response(server_response.content, self.parent_srv.namespace)
3235
return all_view_items, pagination_item

tableauserverclient/server/endpoint/workbooks_endpoint.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -118,19 +118,21 @@ def download(self, workbook_id, filepath=None, include_extract=True, no_extract=
118118

119119
# Get all views of workbook
120120
@api(version="2.0")
121-
def populate_views(self, workbook_item):
121+
def populate_views(self, workbook_item, usage=False):
122122
if not workbook_item.id:
123123
error = "Workbook item missing ID. Workbook must be retrieved from server first."
124124
raise MissingRequiredFieldError(error)
125125

126126
def view_fetcher():
127-
return self._get_views_for_workbook(workbook_item)
127+
return self._get_views_for_workbook(workbook_item, usage)
128128

129129
workbook_item._set_views(view_fetcher)
130130
logger.info('Populated views for workbook (ID: {0}'.format(workbook_item.id))
131131

132-
def _get_views_for_workbook(self, workbook_item):
132+
def _get_views_for_workbook(self, workbook_item, usage):
133133
url = "{0}/{1}/views".format(self.baseurl, workbook_item.id)
134+
if usage:
135+
url += "?includeUsageStatistics=true"
134136
server_response = self.get_request(url)
135137
views = ViewItem.from_response(server_response.content,
136138
self.parent_srv.namespace,

tableauserverclient/server/request_options.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,11 @@ def page_number(self, page_number):
4141

4242
def apply_query_params(self, url):
4343
params = []
44+
45+
if '?' in url:
46+
url, existing_params = url.split('?')
47+
params.append(existing_params)
48+
4449
if self.page_number:
4550
params.append('pageNumber={0}'.format(self.pagenumber))
4651
if self.page_size:

test/assets/view_get_usage.xml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?xml version='1.0' encoding='UTF-8'?>
2+
<tsResponse xmlns="http://tableau.com/api" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://tableau.com/api http://tableau.com/api/ts-api-2.3.xsd">
3+
<pagination pageNumber="1" pageSize="100" totalAvailable="2" />
4+
<views>
5+
<view id="d79634e1-6063-4ec9-95ff-50acbf609ff5" name="ENDANGERED SAFARI" contentUrl="SafariSample/sheets/ENDANGEREDSAFARI">
6+
<workbook id="3cc6cd06-89ce-4fdc-b935-5294135d6d42" />
7+
<owner id="5de011f8-5aa9-4d5b-b991-f462c8dd6bb7" />
8+
<tags />
9+
<usage totalViewCount="7" />
10+
</view>
11+
<view id="fd252f73-593c-4c4e-8584-c032b8022adc" name="Overview" contentUrl="Superstore/sheets/Overview">
12+
<workbook id="6d13b0ca-043d-4d42-8c9d-3f3313ea3a00" />
13+
<owner id="5de011f8-5aa9-4d5b-b991-f462c8dd6bb7" />
14+
<tags />
15+
<usage totalViewCount="13" />
16+
</view>
17+
</views>
18+
</tsResponse>
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?xml version='1.0' encoding='UTF-8'?>
2+
<tsResponse xmlns="http://tableau.com/api" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://tableau.com/api http://tableau.com/api/ts-api-2.3.xsd">
3+
<views>
4+
<view id="097dbe13 37BC -de89-445f-b2c3-02f28bd010c1" name="GDP per capita" contentUrl="RESTAPISample/sheets/GDPpercapita">
5+
<usage totalViewCount="2" />
6+
</view>
7+
<view id="2c1ab9d7-8d64-4cc6-b495-52e40c60c330" name="Country ranks" contentUrl="RESTAPISample/sheets/Countryranks">
8+
<usage totalViewCount="37" />
9+
</view>
10+
<view id="0599c28c-6d82-457e-a453-e52c1bdb00f5" name="Interest rates" contentUrl="RESTAPISample/sheets/Interestrates">
11+
<usage totalViewCount="0" />
12+
</view>
13+
</views>
14+
</tsResponse>

test/test_view.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
ADD_TAGS_XML = os.path.join(TEST_ASSET_DIR, 'view_add_tags.xml')
99
GET_XML = os.path.join(TEST_ASSET_DIR, 'view_get.xml')
10+
GET_XML_USAGE = os.path.join(TEST_ASSET_DIR, 'view_get_usage.xml')
1011
POPULATE_PREVIEW_IMAGE = os.path.join(TEST_ASSET_DIR, 'Sample View Image.png')
1112
POPULATE_PDF = os.path.join(TEST_ASSET_DIR, 'populate_pdf.pdf')
1213
POPULATE_CSV = os.path.join(TEST_ASSET_DIR, 'populate_csv.csv')
@@ -45,6 +46,33 @@ def test_get(self):
4546
self.assertEqual('6d13b0ca-043d-4d42-8c9d-3f3313ea3a00', all_views[1].workbook_id)
4647
self.assertEqual('5de011f8-5aa9-4d5b-b991-f462c8dd6bb7', all_views[1].owner_id)
4748

49+
def test_get_with_usage(self):
50+
with open(GET_XML_USAGE, 'rb') as f:
51+
response_xml = f.read().decode('utf-8')
52+
with requests_mock.mock() as m:
53+
m.get(self.baseurl + "?includeUsageStatistics=true", text=response_xml)
54+
all_views, pagination_item = self.server.views.get(usage=True)
55+
56+
self.assertEqual('d79634e1-6063-4ec9-95ff-50acbf609ff5', all_views[0].id)
57+
self.assertEqual(7, all_views[0].total_views)
58+
self.assertEqual('fd252f73-593c-4c4e-8584-c032b8022adc', all_views[1].id)
59+
self.assertEqual(13, all_views[1].total_views)
60+
61+
def test_get_with_usage_and_filter(self):
62+
with open(GET_XML_USAGE, 'rb') as f:
63+
response_xml = f.read().decode('utf-8')
64+
with requests_mock.mock() as m:
65+
m.get(self.baseurl + "?includeUsageStatistics=true&filter=name:in:[foo,bar]", text=response_xml)
66+
options = TSC.RequestOptions()
67+
options.filter.add(TSC.Filter(TSC.RequestOptions.Field.Name, TSC.RequestOptions.Operator.In,
68+
["foo", "bar"]))
69+
all_views, pagination_item = self.server.views.get(req_options=options, usage=True)
70+
71+
self.assertEqual("ENDANGERED SAFARI", all_views[0].name)
72+
self.assertEqual(7, all_views[0].total_views)
73+
self.assertEqual("Overview", all_views[1].name)
74+
self.assertEqual(13, all_views[1].total_views)
75+
4876
def test_get_before_signin(self):
4977
self.server._auth_token = None
5078
self.assertRaises(TSC.NotSignedInError, self.server.views.get)

test/test_workbook.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
POPULATE_CONNECTIONS_XML = os.path.join(TEST_ASSET_DIR, 'workbook_populate_connections.xml')
1414
POPULATE_PREVIEW_IMAGE = os.path.join(TEST_ASSET_DIR, 'RESTAPISample Image.png')
1515
POPULATE_VIEWS_XML = os.path.join(TEST_ASSET_DIR, 'workbook_populate_views.xml')
16+
POPULATE_VIEWS_USAGE_XML = os.path.join(TEST_ASSET_DIR, 'workbook_populate_views_usage.xml')
1617
PUBLISH_XML = os.path.join(TEST_ASSET_DIR, 'workbook_publish.xml')
1718
UPDATE_XML = os.path.join(TEST_ASSET_DIR, 'workbook_update.xml')
1819

@@ -220,6 +221,24 @@ def test_populate_views(self):
220221
self.assertEqual('Interest rates', views_list[2].name)
221222
self.assertEqual('RESTAPISample/sheets/Interestrates', views_list[2].content_url)
222223

224+
def test_populate_views_with_usage(self):
225+
with open(POPULATE_VIEWS_USAGE_XML, 'rb') as f:
226+
response_xml = f.read().decode('utf-8')
227+
with requests_mock.mock() as m:
228+
m.get(self.baseurl + '/1f951daf-4061-451a-9df1-69a8062664f2/views?includeUsageStatistics=true',
229+
text=response_xml)
230+
single_workbook = TSC.WorkbookItem('test')
231+
single_workbook._id = '1f951daf-4061-451a-9df1-69a8062664f2'
232+
self.server.workbooks.populate_views(single_workbook, usage=True)
233+
234+
views_list = single_workbook.views
235+
self.assertEqual('097dbe13-de89-445f-b2c3-02f28bd010c1', views_list[0].id)
236+
self.assertEqual(2, views_list[0].total_views)
237+
self.assertEqual('2c1ab9d7-8d64-4cc6-b495-52e40c60c330', views_list[1].id)
238+
self.assertEqual(37, views_list[1].total_views)
239+
self.assertEqual('0599c28c-6d82-457e-a453-e52c1bdb00f5', views_list[2].id)
240+
self.assertEqual(0, views_list[2].total_views)
241+
223242
def test_populate_views_missing_id(self):
224243
single_workbook = TSC.WorkbookItem('test')
225244
self.assertRaises(TSC.MissingRequiredFieldError, self.server.workbooks.populate_views, single_workbook)

0 commit comments

Comments
 (0)
0