Skip to content

Commit 42d83bf

Browse files
jorwoodsjacalata
andauthored
Jorwoods/type hint user (#944)
* Type hint Users * Type hint UserRequest * Remove type hints from Roles and Auth namespaces * Update user_item.py Co-authored-by: Jac <jacalata@users.noreply.github.com>
1 parent b54759b commit 42d83bf

File tree

4 files changed

+83
-61
lines changed

4 files changed

+83
-61
lines changed

tableauserverclient/models/user_item.py

Lines changed: 41 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from datetime import datetime
12
import xml.etree.ElementTree as ET
23
from .exceptions import UnpopulatedPropertyError
34
from .property_decorators import (
@@ -8,10 +9,15 @@
89
from ..datetime_helpers import parse_datetime
910
from .reference_item import ResourceReference
1011

12+
from typing import Dict, List, Optional, TYPE_CHECKING
13+
14+
if TYPE_CHECKING:
15+
from ..server.pager import Pager
16+
1117

1218
class UserItem(object):
1319

14-
tag_name = "user"
20+
tag_name: str = "user"
1521

1622
class Roles:
1723
Interactor = "Interactor"
@@ -39,23 +45,27 @@ class Auth:
3945
SAML = "SAML"
4046
ServerDefault = "ServerDefault"
4147

42-
def __init__(self, name=None, site_role=None, auth_setting=None):
43-
self._auth_setting = None
44-
self._domain_name = None
45-
self._external_auth_user_id = None
46-
self._id = None
47-
self._last_login = None
48+
def __init__(
49+
self, name: Optional[str] = None, site_role: Optional[str] = None, auth_setting: Optional[str] = None
50+
) -> None:
51+
self._auth_setting: Optional[str] = None
52+
self._domain_name: Optional[str] = None
53+
self._external_auth_user_id: Optional[str] = None
54+
self._id: Optional[str] = None
55+
self._last_login: Optional[datetime] = None
4856
self._workbooks = None
49-
self._favorites = None
57+
self._favorites: Optional[Dict[str, List]] = None
5058
self._groups = None
51-
self.email = None
52-
self.fullname = None
53-
self.name = name
54-
self.site_role = site_role
55-
self.auth_setting = auth_setting
59+
self.email: Optional[str] = None
60+
self.fullname: Optional[str] = None
61+
self.name: Optional[str] = name
62+
self.site_role: Optional[str] = site_role
63+
self.auth_setting: Optional[str] = auth_setting
64+
65+
return None
5666

5767
@property
58-
def auth_setting(self):
68+
def auth_setting(self) -> Optional[str]:
5969
return self._auth_setting
6070

6171
@auth_setting.setter
@@ -64,32 +74,32 @@ def auth_setting(self, value):
6474
self._auth_setting = value
6575

6676
@property
67-
def domain_name(self):
77+
def domain_name(self) -> Optional[str]:
6878
return self._domain_name
6979

7080
@property
71-
def external_auth_user_id(self):
81+
def external_auth_user_id(self) -> Optional[str]:
7282
return self._external_auth_user_id
7383

7484
@property
75-
def id(self):
85+
def id(self) -> Optional[str]:
7686
return self._id
7787

7888
@property
79-
def last_login(self):
89+
def last_login(self) -> Optional[datetime]:
8090
return self._last_login
8191

8292
@property
83-
def name(self):
93+
def name(self) -> Optional[str]:
8494
return self._name
8595

8696
@name.setter
8797
@property_not_empty
88-
def name(self, value):
98+
def name(self, value: str):
8999
self._name = value
90100

91101
@property
92-
def site_role(self):
102+
def site_role(self) -> Optional[str]:
93103
return self._site_role
94104

95105
@site_role.setter
@@ -99,36 +109,36 @@ def site_role(self, value):
99109
self._site_role = value
100110

101111
@property
102-
def workbooks(self):
112+
def workbooks(self) -> "Pager":
103113
if self._workbooks is None:
104114
error = "User item must be populated with workbooks first."
105115
raise UnpopulatedPropertyError(error)
106116
return self._workbooks()
107117

108118
@property
109-
def favorites(self):
119+
def favorites(self) -> Dict[str, List]:
110120
if self._favorites is None:
111121
error = "User item must be populated with favorites first."
112122
raise UnpopulatedPropertyError(error)
113123
return self._favorites
114124

115125
@property
116-
def groups(self):
126+
def groups(self) -> "Pager":
117127
if self._groups is None:
118128
error = "User item must be populated with groups first."
119129
raise UnpopulatedPropertyError(error)
120130
return self._groups()
121131

122-
def to_reference(self):
132+
def to_reference(self) -> ResourceReference:
123133
return ResourceReference(id_=self.id, tag_name=self.tag_name)
124134

125-
def _set_workbooks(self, workbooks):
135+
def _set_workbooks(self, workbooks) -> None:
126136
self._workbooks = workbooks
127137

128-
def _set_groups(self, groups):
138+
def _set_groups(self, groups) -> None:
129139
self._groups = groups
130140

131-
def _parse_common_tags(self, user_xml, ns):
141+
def _parse_common_tags(self, user_xml, ns) -> "UserItem":
132142
if not isinstance(user_xml, ET.Element):
133143
user_xml = ET.fromstring(user_xml).find(".//t:user", namespaces=ns)
134144
if user_xml is not None:
@@ -178,7 +188,7 @@ def _set_values(
178188
self._domain_name = domain_name
179189

180190
@classmethod
181-
def from_response(cls, resp, ns):
191+
def from_response(cls, resp, ns) -> List["UserItem"]:
182192
all_user_items = []
183193
parsed_response = ET.fromstring(resp)
184194
all_user_xml = parsed_response.findall(".//t:user", namespaces=ns)
@@ -210,7 +220,7 @@ def from_response(cls, resp, ns):
210220
return all_user_items
211221

212222
@staticmethod
213-
def as_reference(id_):
223+
def as_reference(id_) -> ResourceReference:
214224
return ResourceReference(id_, UserItem.tag_name)
215225

216226
@staticmethod
@@ -241,5 +251,5 @@ def _parse_element(user_xml, ns):
241251
domain_name,
242252
)
243253

244-
def __repr__(self):
254+
def __repr__(self) -> str:
245255
return "<User {} name={} role={}>".format(self.id, self.name, self.site_role)

tableauserverclient/server/endpoint/users_endpoint.py

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from typing import List, Tuple
12
from .endpoint import QuerysetEndpoint, api
23
from .exceptions import MissingRequiredFieldError
34
from .. import (
@@ -18,12 +19,12 @@
1819

1920
class Users(QuerysetEndpoint):
2021
@property
21-
def baseurl(self):
22+
def baseurl(self) -> str:
2223
return "{0}/sites/{1}/users".format(self.parent_srv.baseurl, self.parent_srv.site_id)
2324

2425
# Gets all users
2526
@api(version="2.0")
26-
def get(self, req_options=None):
27+
def get(self, req_options: RequestOptions = None) -> Tuple[List[UserItem], PaginationItem]:
2728
logger.info("Querying all users on site")
2829

2930
if req_options is None:
@@ -38,7 +39,7 @@ def get(self, req_options=None):
3839

3940
# Gets 1 user by id
4041
@api(version="2.0")
41-
def get_by_id(self, user_id):
42+
def get_by_id(self, user_id: str) -> UserItem:
4243
if not user_id:
4344
error = "User ID undefined."
4445
raise ValueError(error)
@@ -49,7 +50,7 @@ def get_by_id(self, user_id):
4950

5051
# Update user
5152
@api(version="2.0")
52-
def update(self, user_item, password=None):
53+
def update(self, user_item: UserItem, password: str = None) -> UserItem:
5354
if not user_item.id:
5455
error = "User item missing ID."
5556
raise MissingRequiredFieldError(error)
@@ -63,7 +64,7 @@ def update(self, user_item, password=None):
6364

6465
# Delete 1 user by id
6566
@api(version="2.0")
66-
def remove(self, user_id):
67+
def remove(self, user_id: str) -> None:
6768
if not user_id:
6869
error = "User ID undefined."
6970
raise ValueError(error)
@@ -73,7 +74,7 @@ def remove(self, user_id):
7374

7475
# Add new user to site
7576
@api(version="2.0")
76-
def add(self, user_item):
77+
def add(self, user_item: UserItem) -> UserItem:
7778
url = self.baseurl
7879
add_req = RequestFactory.User.add_req(user_item)
7980
server_response = self.post_request(url, add_req)
@@ -83,7 +84,7 @@ def add(self, user_item):
8384

8485
# Get workbooks for user
8586
@api(version="2.0")
86-
def populate_workbooks(self, user_item, req_options=None):
87+
def populate_workbooks(self, user_item: UserItem, req_options: RequestOptions = None) -> None:
8788
if not user_item.id:
8889
error = "User item missing ID."
8990
raise MissingRequiredFieldError(error)
@@ -93,20 +94,22 @@ def wb_pager():
9394

9495
user_item._set_workbooks(wb_pager)
9596

96-
def _get_wbs_for_user(self, user_item, req_options=None):
97+
def _get_wbs_for_user(
98+
self, user_item: UserItem, req_options: RequestOptions = None
99+
) -> Tuple[List[WorkbookItem], PaginationItem]:
97100
url = "{0}/{1}/workbooks".format(self.baseurl, user_item.id)
98101
server_response = self.get_request(url, req_options)
99102
logger.info("Populated workbooks for user (ID: {0})".format(user_item.id))
100103
workbook_item = WorkbookItem.from_response(server_response.content, self.parent_srv.namespace)
101104
pagination_item = PaginationItem.from_response(server_response.content, self.parent_srv.namespace)
102105
return workbook_item, pagination_item
103106

104-
def populate_favorites(self, user_item):
107+
def populate_favorites(self, user_item: UserItem) -> None:
105108
self.parent_srv.favorites.get(user_item)
106109

107110
# Get groups for user
108111
@api(version="3.7")
109-
def populate_groups(self, user_item, req_options=None):
112+
def populate_groups(self, user_item: UserItem, req_options: RequestOptions = None) -> None:
110113
if not user_item.id:
111114
error = "User item missing ID."
112115
raise MissingRequiredFieldError(error)
@@ -119,7 +122,9 @@ def groups_for_user_pager():
119122

120123
user_item._set_groups(groups_for_user_pager)
121124

122-
def _get_groups_for_user(self, user_item, req_options=None):
125+
def _get_groups_for_user(
126+
self, user_item: UserItem, req_options: RequestOptions = None
127+
) -> Tuple[List[GroupItem], PaginationItem]:
123128
url = "{0}/{1}/groups".format(self.baseurl, user_item.id)
124129
server_response = self.get_request(url, req_options)
125130
logger.info("Populated groups for user (ID: {0})".format(user_item.id))

tableauserverclient/server/request_factory.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -798,7 +798,7 @@ def add_req(self, tag_set):
798798

799799

800800
class UserRequest(object):
801-
def update_req(self, user_item, password):
801+
def update_req(self, user_item: UserItem, password: Optional[str]) -> bytes:
802802
xml_request = ET.Element("tsRequest")
803803
user_element = ET.SubElement(xml_request, "user")
804804
if user_item.fullname:
@@ -814,11 +814,18 @@ def update_req(self, user_item, password):
814814
user_element.attrib["password"] = password
815815
return ET.tostring(xml_request)
816816

817-
def add_req(self, user_item):
817+
def add_req(self, user_item: UserItem) -> bytes:
818818
xml_request = ET.Element("tsRequest")
819819
user_element = ET.SubElement(xml_request, "user")
820-
user_element.attrib["name"] = user_item.name
821-
user_element.attrib["siteRole"] = user_item.site_role
820+
if isinstance(user_item.name, str):
821+
user_element.attrib["name"] = user_item.name
822+
else:
823+
raise ValueError(f"{user_item} missing name.")
824+
if isinstance(user_item.site_role, str):
825+
user_element.attrib["siteRole"] = user_item.site_role
826+
else:
827+
raise ValueError(f"{user_item} must have site role populated.")
828+
822829
if user_item.auth_setting:
823830
user_element.attrib["authSetting"] = user_item.auth_setting
824831
return ET.tostring(xml_request)

0 commit comments

Comments
 (0)