8000 Merge pull request #46 from tableau/issue-38 · tableau/server-client-python@56af4af · GitHub
[go: up one dir, main page]

Skip to content

Commit 56af4af

Browse files
authored
Merge pull request #46 from tableau/issue-38
Added decorators for checking values of input to property setters (Issue-38)
2 parents 36d63c0 + a13d708 commit 56af4af

14 files changed

+229
-83
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,9 @@ docs/_build/
6666
# PyBuilder
6767
target/
6868

69+
# PyCharm stuff
70+
.idea/
71+
6972
# IPython Notebook
7073
.ipynb_checkpoints
7174

tableauserverclient/models/datasource_item.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import xml.etree.ElementTree as ET
22
from .exceptions import UnpopulatedPropertyError
3+
from .property_decorators import property_not_nullable
34
from .tag_item import TagItem
45
from .. import NAMESPACE
56

@@ -45,12 +46,9 @@ def project_id(self):
4546
return self._project_id
4647

4748
@project_id.setter
49+
@property_not_nullable
4850
def project_id(self, value):
49-
if value is None:
50-
error = 'Project ID must be defined.'
51-
raise ValueError(error)
52-
else:
53-
self._project_id = value
51+
self._project_id = value
5452

5553
@property
5654
def project_name(self):

tableauserverclient/models/group_item.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import xml.etree.ElementTree as ET
22
from .exceptions import UnpopulatedPropertyError
3+
from .property_decorators import property_not_empty
34
from .. import NAMESPACE
45

56

@@ -26,12 +27,9 @@ def name(self):
2627< 9E88 /code>
return self._name
2728

2829
@name.setter
30+
@property_not_empty
2931
def name(self, value):
30-
if not value:
31-
error = 'Name must be defined.'
32-
raise ValueError(error)
33-
else:
34-
self._name = value
32+
self._name = value
3533

3634
@property
3735
def users(self):

tableauserverclient/models/project_item.py

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import xml.etree.ElementTree as ET
2+
from .property_decorators import property_is_enum, property_not_empty
23
from .. import NAMESPACE
34

45

@@ -26,12 +27,9 @@ def content_permissions(self):
2627
return self._content_permissions
2728

2829
@content_permissions.setter
30+
@property_is_enum(ContentPermissions)
2931
def content_permissions(self, value):
30-
if value and not hasattr(ProjectItem.ContentPermissions, value):
31-
error = 'Invalid content permission defined.'
32-
raise ValueError(error)
33-
else:
34-
self._content_permissions = value
32+
self._content_permissions = value
3533

3634
@property
3735
def id(self):
@@ -42,12 +40,9 @@ def name(self):
4240
return self._name
4341

4442
@name.setter
43+
@property_not_empty
4544
def name(self, value):
46-
if not value:
47-
error = 'Name must be defined.'
48-
raise ValueError(error)
49-
else:
50-
self._name = value
45+
self._name = value
5146

5247
def is_default(self):
5348
return self.name.lower() == 'default'
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
from functools import wraps
2+
3+
4+
def property_is_enum(enum_type):
5+
def property_type_decorator(func):
6+
@wraps(func)
7+
def wrapper(self, value):
8+
if value is not None and not hasattr(enum_type, value):
9+
error = "Invalid value: {0}. {1} must be of type {2}.".format(value, func.__name__, enum_type.__name__)
10+
raise ValueError(error)
11+
return func(self, value)
12+
13+
return wrapper
14+
15+
return property_type_decorator
16+
17+
18+
def property_is_boolean(func):
19+
@wraps(func)
20+
def wrapper(self, value):
21+
if not isinstance(value, bool):
22+
error = "Boolean expected for {0} flag.".format(func.__name__)
23+
raise ValueError(error)
24+
return func(self, value)
25+
26+
return wrapper
27+
28+
29+
def property_not_nullable(func):
30+
@wraps(func)
31+
def wrapper(self, value):
32+
if value is None:
33+
error = "{0} must be defined.".format(func.__name__)
34+
raise ValueError(error)
35+
return func(self, value)
36+
37+
return wrapper
38+
39+
40+
def property_not_empty(func):
41+
@wraps(func)
42+
def wrapper(self, value):
43+
if not value:
44+
error = "{0} must not be empty.".format(func.__name__)
45+
raise ValueError(error)
46+
return func(self, value)
47+
48+
return wrapper

tableauserverclient/models/site_item.py

Lines changed: 15 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import xml.etree.ElementTree as ET
2+
from .property_decorators import property_is_enum, property_is_boolean, property_not_empty, property_not_nullable
23
from .. import NAMESPACE
34

45

@@ -45,36 +46,27 @@ def admin_mode(self):
4546
return self._admin_mode
4647

4748
@admin_mode.setter
49+
@property_is_enum(AdminMode)
4850
def admin_mode(self, value):
49-
if value and not hasattr(SiteItem.AdminMode, value):
50-
error = 'Invalid admin mode defined.'
51-
raise ValueError(error)
52-
else:
53-
self._admin_mode = value
51+
self._admin_mode = value
5452

5553
@property
5654
def content_url(self):
5755
return self._content_url
5856

5957
@content_url.setter
58+
@property_not_nullable
6059
def content_url(self, value):
61-
if value is None:
62-
error = 'Content URL must be defined.'
63-
raise ValueError(error)
64-
else:
65-
self._content_url = value
60+
self._content_url = value
6661

6762
@property
6863
def disable_subscriptions(self):
6964
return self._disable_subscriptions
7065

7166
@disable_subscriptions.setter
67+
@property_is_boolean
7268
def disable_subscriptions(self, value):
73-
if not isinstance(value, bool):
74-
error = 'Boolean expected for disable_subscriptions flag.'
75-
raise ValueError(error)
76-
else:
77-
self._disable_subscriptions = value
69+
self._disable_subscriptions = value
7870

7971
@property
8072
def id(self):
@@ -85,12 +77,9 @@ def name(self):
8577
return self._name
8678

8779
@name.setter
80+
@property_not_empty
8881
def name(self, value):
89-
if not value:
90-
error = 'Name must be defined.'
91-
raise ValueError(error)
92-
else:
93-
self._name = value
82+
self._name = value
9483

9584
@property
9685
def num_users(self):
@@ -101,24 +90,18 @@ def revision_history_enabled(self):
10190
return self._revision_history_enabled
10291

10392
@revision_history_enabled.setter
93+
@property_is_boolean
10494
def revision_history_enabled(self, value):
105-
if not isinstance(value, bool):
106-
error = 'Boolean expected for revision_history_enabled flag.'
107-
raise ValueError(error)
108-
else:
109-
self._revision_history_enabled = value
95+
self._revision_history_enabled = value
11096

11197
@property
11298
def state(self):
11399
return self._state
114100

115101
@state.setter
102+
@property_is_enum(State)
116103
def state(self, value):
117-
if not hasattr(SiteItem.State, value):
118-
error = 'Invalid state defined.'
119-
raise ValueError(error)
120-
else:
121-
self._state = value
104+
self._state = value
122105

123106
@property
124107
def status_reason(self):
@@ -133,12 +116,9 @@ def subscribe_others_enabled(self):
133116
return self._subscribe_others_enabled
134117

135118
@subscribe_others_enabled.setter
119+
@property_is_boolean
136120
def subscribe_others_enabled(self, value):
137-
if not isinstance(value, bool):
138-
error = 'Boolean expected for subscribe_others_enabled flag.'
139-
raise ValueError(error)
140-
else:
141-
self._subscribe_others_enabled = value
121+
self._subscribe_others_enabled = value
142122

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

tableauserverclient/models/user_item.py

Lines changed: 8 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import xml.etree.ElementTree as ET
22
from .exceptions import UnpopulatedPropertyError
3+
from .property_decorators import property_is_enum, property_not_empty, property_not_nullable
34
from .. import NAMESPACE
45

56

@@ -45,12 +46,9 @@ def auth_setting(self):
4546
return self._auth_setting
4647

4748
@auth_setting.setter
49+
@property_is_enum(Auth)
4850
def auth_setting(self, value):
49-
if not hasattr(UserItem.Auth, value):
50-
error = 'Invalid auth setting defined.'
51-
raise ValueError(error)
52-
else:
53-
self._auth_setting = value
51+
self._auth_setting = value
5452

5553
@property
5654
def domain_name(self):
@@ -73,27 +71,19 @@ def name(self):
7371
return self._name
7472

7573
@name.setter
74+
@property_not_empty
7675
def name(self, value):
77-
if not value:
78-
error = 'Name must be defined.'
79-
raise ValueError(error)
80-
else:
81-
self._name = value
76+
self._name = value
8277

8378
@property
8479
def site_role(self):
8580
return self._site_role
8681

8782
@site_role.setter
83+
@property_not_nullable
84+
@property_is_enum(Roles)
8885
def site_role(self, value):
89-
if not value:
90-
error = 'Site role must be defined.'
91-
raise ValueError(error)
92-
elif not hasattr(UserItem.Roles, value):
93-
error = 'Invalid site role defined.'
94-
raise ValueError(error)
95-
else:
96-
self._site_role = value
86+
self._site_role = value
9787

9888
@property
9989
def workbooks(self):

tableauserverclient/models/workbook_item.py

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import xml.etree.ElementTree as ET
22
from .exceptions import UnpopulatedPropertyError
3+
from .property_decorators import property_not_nullable, property_is_boolean
34
from .tag_item import TagItem
45
from .view_item import ViewItem
56
from .. import NAMESPACE
@@ -59,12 +60,9 @@ def project_id(self):
5960
return self._project_id
6061

6162
@project_id.setter
63+
@property_not_nullable
6264
def project_id(self, value):
63-
if value is None:
64-
error = 'Project ID must be defined.'
65-
raise ValueError(error)
66-
else:
67-
self._project_id = value
65+
self._project_id = value
6866

6967
@property
7068
def project_name(self):
@@ -75,12 +73,9 @@ def show_tabs(self):
7573
return self._show_tabs
7674

7775
@show_tabs.setter
76+
@property_is_boolean
7877
def show_tabs(self, value):
79-
if not isinstance(value, bool):
80-
error = 'Boolean expected for show tabs flag.'
81-
raise ValueError(error)
82-
else:
83-
self._show_tabs = value
78+
self._show_tabs = value
8479

8580
@property
8681
def size(self):

test/test_datasource_model.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import unittest
2+
import tableauserverclient as TSC
3+
4+
5+
class DatasourceModelTests(unittest.TestCase):
6+
def test_invalid_project_id(self):
7+
self.assertRaises(ValueError, TSC.DatasourceItem, None)
8+
datasource = TSC.DatasourceItem("10")
9+
with self.assertRaises(ValueError):
10+
datasource.project_id = None

test/test_group_model.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import unittest
2+
import tableauserverclient as TSC
3+
4+
5+
class GroupModelTests(unittest.TestCase):
6+
def test_invalid_name(self):
7+
self.assertRaises(ValueError, TSC.GroupItem, None)
8+
self.assertRaises(ValueError, TSC.GroupItem, "")
9+
group = TSC.GroupItem("grp")
10+
with self.assertRaises(ValueError):
11+
group.name = None
12+
13+
with self.assertRaises(ValueError):
14+
group.name = ""

test/test_project_model.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import unittest
2+
import tableauserverclient as TSC
3+
4+
5+
class ProjectModelTests(unittest.TestCase):
6+
def test_invalid_name(self):
7+
self.assertRaises(ValueError, TSC.ProjectItem, None)
8+
self.assertRaises(ValueError, TSC.ProjectItem, "")
9+
project = TSC.ProjectItem("proj")
10+
with self.assertRaises(ValueError):
11+
project.name = None
12+
13+
with self.assertRaises(ValueError):
14+
project.name = ""
15+
16+
def test_invalid_content_permissions(self):
17+
project = TSC.ProjectItem("proj")
18+
with self.assertRaises(ValueError):
19+
project.content_permissions = "Hello"

0 commit comments

Comments
 (0)
0