Skip to content
10 changes: 5 additions & 5 deletions tableauserverclient/models/property_decorators.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ def wrapper(self, value):
return wrapper


def property_is_int(range, allowed=None):
def property_is_int(valid_int_range, allowed=None):
'''Takes a range of ints and a list of exemptions to check against
when setting a property on a model. The range is a tuple of (min, max) and the
allowed list (empty by default) allows values outside that range.
Expand All @@ -86,15 +86,15 @@ def property_type_decorator(func):
def wrapper(self, value):
error = "Invalid property defined: '{}'. Integer value expected.".format(value)

if range is None:
if value in allowed:
return func(self, value)
if valid_int_range is None:
if isinstance(value, int):
return func(self, value)
else:
raise ValueError(error)

min, max = range

if (value < min or value > max) and (value not in allowed):
if not (valid_int_range[0] < value < valid_int_range[1]):
raise ValueError(error)

return func(self, value)
Expand Down
2 changes: 1 addition & 1 deletion tableauserverclient/models/schedule_item.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ def priority(self):
return self._priority

@priority.setter
@property_is_int(range=(1, 100))
@property_is_int(valid_int_range=(1, 100))
def priority(self, value):
self._priority = value

Expand Down
38 changes: 38 additions & 0 deletions tableauserverclient/models/site_item.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import sys
import xml.etree.ElementTree as ET
from .property_decorators import (property_is_enum, property_is_boolean, property_matches,
property_not_empty, property_not_nullable, property_is_int)
Expand Down Expand Up @@ -197,6 +198,33 @@ def flows_enabled(self):
def flows_enabled(self, value):
self._flows_enabled = value

@property
def tier_creator_capacity(self):
return self._tier_creator_capacity

@tier_creator_capacity.setter
@property_is_int((0, sys.maxsize), allowed=(-1, None,))
def tier_creator_capacity(self, value):
self._tier_creator_capacity = value

@property
def tier_explorer_capacity(self):
return self._tier_explorer_capacity

@tier_explorer_capacity.setter
@property_is_int((0, sys.maxsize), allowed=(-1, None,))
def tier_explorer_capacity(self, value):
self._tier_explorer_capacity = value

@property
def tier_viewer_capacity(self):
return self._tier_viewer_capacity

@tier_viewer_capacity.setter
@property_is_int((0, sys.maxsize), allowed=(-1, None,))
def tier_viewer_capacity(self, value):
self._tier_viewer_capacity = value

def is_default(self):
return self.name.lower() == 'default'

Expand Down Expand Up @@ -761,6 +789,16 @@ def _parse_element(site_xml, ns):
flows_enabled = string_to_bool(site_xml.get('flowsEnabled', ''))
cataloging_enabled = string_to_bool(site_xml.get('catalogingEnabled', ''))

tier_creator_capacity = site_xml.get('tierCreatorCapacity', None)
tier_explorer_capacity = site_xml.get('tierExplorerCapacity', None)
tier_viewer_capacity = site_xml.get('tierViewerCapacity', None)
if tier_creator_capacity:
tier_creator_capacity = int(tier_creator_capacity)
if tier_explorer_capacity:
tier_explorer_capacity = int(tier_explorer_capacity)
if tier_viewer_capacity:
tier_viewer_capacity = int(tier_viewer_capacity)

return 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, data_acceleration_mode, flows_enabled, cataloging_enabled,\
Expand Down
8 changes: 8 additions & 0 deletions tableauserverclient/server/endpoint/sites_endpoint.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,14 @@ def update(self, site_item):
error = 'You cannot set admin_mode to ContentOnly and also set a user quota'
raise ValueError(error)

reset = (None, -1,)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this variable named "reset"? It could have always been empty, right?

if site_item.user_quota not in reset:
if any([site_item.tier_creator_capacity not in reset,
site_item.tier_explorer_capacity not in reset,
site_item.tier_viewer_capacity not in reset, ]):
error = 'You cannot set tiered capacity and a user quota.'
raise ValueError(error)

url = "{0}/{1}".format(self.baseurl, site_item.id)
update_req = RequestFactory.Site.update_req(site_item)
server_response = self.put_request(url, update_req)
Expand Down
6 changes: 3 additions & 3 deletions tableauserverclient/server/request_options.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ def max_age(self):
return self._max_age

@max_age.setter
@property_is_int(range=(0, 240), allowed=[-1])
@property_is_int(valid_int_range=(0, 240), allowed=[-1])
def max_age(self, value):
self._max_age = value

Expand Down Expand Up @@ -153,7 +153,7 @@ def max_age(self):
return self._max_age

@max_age.setter
@property_is_int(range=(0, 240), allowed=[-1])
@property_is_int(valid_int_range=(0, 240), allowed=[-1])
def max_age(self, value):
self._max_age = value

Expand Down Expand Up @@ -198,7 +198,7 @@ def max_age(self):
return self._max_age

@max_age.setter
@property_is_int(range=(0, 240), allowed=[-1])
@property_is_int(valid_int_range=(0, 240), allowed=[-1])
def max_age(self, value):
self._max_age = value

Expand Down
15 changes: 15 additions & 0 deletions test/test_site.py
Original file line number Diff line number Diff line change
Expand Up @@ -206,3 +206,18 @@ def test_decrypt(self):
with requests_mock.mock() as m:
m.post(self.baseurl + '/0626857c-1def-4503-a7d8-7907c3ff9d9f/decrypt-extracts', status_code=200)
self.server.sites.decrypt_extracts('0626857c-1def-4503-a7d8-7907c3ff9d9f')

def test_quota_and_tiers_error(self):
with open(UPDATE_XML, 'rb') as f:
response_xml = f.read().decode('utf-8')
with requests_mock.mock() as m:
m.put(self.baseurl + '/6b7179ba-b82b-4f0f-91ed-812074ac5da6', text=response_xml)
single_site = TSC.SiteItem(name='Tableau', content_url='tableau',
admin_mode=TSC.SiteItem.AdminMode.ContentAndUsers,
user_quota=15, storage_quota=1000,
disable_subscriptions=True, revision_history_enabled=False,
data_acceleration_mode='disable')
single_site.tier_creator_capacity = 11
single_site._id = '6b7179ba-b82b-4f0f-91ed-812074ac5da6'
with self.assertRaises(ValueError):
single_site = self.server.sites.update(single_site)