tableauserverclient 0.32__py3-none-any.whl → 0.34__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- tableauserverclient/__init__.py +34 -18
- tableauserverclient/_version.py +3 -3
- tableauserverclient/config.py +20 -6
- tableauserverclient/models/__init__.py +12 -0
- tableauserverclient/models/column_item.py +1 -1
- tableauserverclient/models/connection_credentials.py +1 -1
- tableauserverclient/models/connection_item.py +10 -8
- tableauserverclient/models/custom_view_item.py +29 -6
- tableauserverclient/models/data_acceleration_report_item.py +2 -2
- tableauserverclient/models/data_alert_item.py +5 -5
- tableauserverclient/models/data_freshness_policy_item.py +6 -6
- tableauserverclient/models/database_item.py +8 -2
- tableauserverclient/models/datasource_item.py +10 -10
- tableauserverclient/models/dqw_item.py +1 -1
- tableauserverclient/models/favorites_item.py +5 -6
- tableauserverclient/models/fileupload_item.py +1 -1
- tableauserverclient/models/flow_item.py +12 -12
- tableauserverclient/models/flow_run_item.py +3 -3
- tableauserverclient/models/group_item.py +4 -4
- tableauserverclient/models/groupset_item.py +53 -0
- tableauserverclient/models/interval_item.py +36 -23
- tableauserverclient/models/job_item.py +26 -10
- tableauserverclient/models/linked_tasks_item.py +102 -0
- tableauserverclient/models/metric_item.py +5 -5
- tableauserverclient/models/pagination_item.py +1 -1
- tableauserverclient/models/permissions_item.py +19 -14
- tableauserverclient/models/project_item.py +35 -19
- tableauserverclient/models/property_decorators.py +12 -11
- tableauserverclient/models/reference_item.py +2 -2
- tableauserverclient/models/revision_item.py +3 -3
- tableauserverclient/models/schedule_item.py +2 -2
- tableauserverclient/models/server_info_item.py +26 -6
- tableauserverclient/models/site_item.py +69 -3
- tableauserverclient/models/subscription_item.py +3 -3
- tableauserverclient/models/table_item.py +1 -1
- tableauserverclient/models/tableau_auth.py +115 -5
- tableauserverclient/models/tableau_types.py +11 -9
- tableauserverclient/models/tag_item.py +3 -4
- tableauserverclient/models/task_item.py +4 -4
- tableauserverclient/models/user_item.py +47 -17
- tableauserverclient/models/view_item.py +11 -10
- tableauserverclient/models/virtual_connection_item.py +78 -0
- tableauserverclient/models/webhook_item.py +6 -6
- tableauserverclient/models/workbook_item.py +90 -12
- tableauserverclient/namespace.py +1 -1
- tableauserverclient/server/__init__.py +2 -1
- tableauserverclient/server/endpoint/__init__.py +8 -0
- tableauserverclient/server/endpoint/auth_endpoint.py +68 -11
- tableauserverclient/server/endpoint/custom_views_endpoint.py +124 -19
- tableauserverclient/server/endpoint/data_acceleration_report_endpoint.py +2 -2
- tableauserverclient/server/endpoint/data_alert_endpoint.py +14 -14
- tableauserverclient/server/endpoint/databases_endpoint.py +32 -17
- tableauserverclient/server/endpoint/datasources_endpoint.py +150 -59
- tableauserverclient/server/endpoint/default_permissions_endpoint.py +19 -18
- tableauserverclient/server/endpoint/dqw_endpoint.py +9 -9
- tableauserverclient/server/endpoint/endpoint.py +47 -31
- tableauserverclient/server/endpoint/exceptions.py +23 -7
- tableauserverclient/server/endpoint/favorites_endpoint.py +31 -31
- tableauserverclient/server/endpoint/fileuploads_endpoint.py +11 -13
- tableauserverclient/server/endpoint/flow_runs_endpoint.py +59 -17
- tableauserverclient/server/endpoint/flow_task_endpoint.py +2 -2
- tableauserverclient/server/endpoint/flows_endpoint.py +73 -35
- tableauserverclient/server/endpoint/groups_endpoint.py +96 -27
- tableauserverclient/server/endpoint/groupsets_endpoint.py +127 -0
- tableauserverclient/server/endpoint/jobs_endpoint.py +79 -12
- tableauserverclient/server/endpoint/linked_tasks_endpoint.py +45 -0
- tableauserverclient/server/endpoint/metadata_endpoint.py +2 -2
- tableauserverclient/server/endpoint/metrics_endpoint.py +10 -10
- tableauserverclient/server/endpoint/permissions_endpoint.py +13 -15
- tableauserverclient/server/endpoint/projects_endpoint.py +124 -30
- tableauserverclient/server/endpoint/resource_tagger.py +139 -6
- tableauserverclient/server/endpoint/schedules_endpoint.py +17 -18
- tableauserverclient/server/endpoint/server_info_endpoint.py +40 -5
- tableauserverclient/server/endpoint/sites_endpoint.py +282 -17
- tableauserverclient/server/endpoint/subscriptions_endpoint.py +10 -10
- tableauserverclient/server/endpoint/tables_endpoint.py +33 -19
- tableauserverclient/server/endpoint/tasks_endpoint.py +8 -8
- tableauserverclient/server/endpoint/users_endpoint.py +405 -19
- tableauserverclient/server/endpoint/views_endpoint.py +111 -25
- tableauserverclient/server/endpoint/virtual_connections_endpoint.py +174 -0
- tableauserverclient/server/endpoint/webhooks_endpoint.py +11 -11
- tableauserverclient/server/endpoint/workbooks_endpoint.py +735 -68
- tableauserverclient/server/filter.py +2 -2
- tableauserverclient/server/pager.py +8 -10
- tableauserverclient/server/query.py +70 -20
- tableauserverclient/server/request_factory.py +213 -41
- tableauserverclient/server/request_options.py +125 -145
- tableauserverclient/server/server.py +73 -9
- tableauserverclient/server/sort.py +2 -2
- {tableauserverclient-0.32.dist-info → tableauserverclient-0.34.dist-info}/METADATA +17 -17
- tableauserverclient-0.34.dist-info/RECORD +106 -0
- {tableauserverclient-0.32.dist-info → tableauserverclient-0.34.dist-info}/WHEEL +1 -1
- tableauserverclient-0.32.dist-info/RECORD +0 -100
- {tableauserverclient-0.32.dist-info → tableauserverclient-0.34.dist-info}/LICENSE +0 -0
- {tableauserverclient-0.32.dist-info → tableauserverclient-0.34.dist-info}/LICENSE.versioneer +0 -0
- {tableauserverclient-0.32.dist-info → tableauserverclient-0.34.dist-info}/top_level.txt +0 -0
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import copy
|
|
2
2
|
import logging
|
|
3
|
-
from typing import
|
|
3
|
+
from typing import Optional
|
|
4
|
+
|
|
5
|
+
from tableauserverclient.server.query import QuerySet
|
|
4
6
|
|
|
5
7
|
from .endpoint import QuerysetEndpoint, api
|
|
6
8
|
from .exceptions import MissingRequiredFieldError, ServerResponseError
|
|
@@ -12,13 +14,75 @@ from tableauserverclient.helpers.logging import logger
|
|
|
12
14
|
|
|
13
15
|
|
|
14
16
|
class Users(QuerysetEndpoint[UserItem]):
|
|
17
|
+
"""
|
|
18
|
+
The user resources for Tableau Server are defined in the UserItem class.
|
|
19
|
+
The class corresponds to the user resources you can access using the
|
|
20
|
+
Tableau Server REST API. The user methods are based upon the endpoints for
|
|
21
|
+
users in the REST API and operate on the UserItem class. Only server and
|
|
22
|
+
site administrators can access the user resources.
|
|
23
|
+
"""
|
|
24
|
+
|
|
15
25
|
@property
|
|
16
26
|
def baseurl(self) -> str:
|
|
17
|
-
return "{
|
|
27
|
+
return f"{self.parent_srv.baseurl}/sites/{self.parent_srv.site_id}/users"
|
|
18
28
|
|
|
19
29
|
# Gets all users
|
|
20
30
|
@api(version="2.0")
|
|
21
|
-
def get(self, req_options: Optional[RequestOptions] = None) ->
|
|
31
|
+
def get(self, req_options: Optional[RequestOptions] = None) -> tuple[list[UserItem], PaginationItem]:
|
|
32
|
+
"""
|
|
33
|
+
Query all users on the site. Request is paginated and returns a subset of users.
|
|
34
|
+
By default, the request returns the first 100 users on the site.
|
|
35
|
+
|
|
36
|
+
Parameters
|
|
37
|
+
----------
|
|
38
|
+
req_options : Optional[RequestOptions]
|
|
39
|
+
Optional request options to filter and sort the results.
|
|
40
|
+
|
|
41
|
+
Returns
|
|
42
|
+
-------
|
|
43
|
+
tuple[list[UserItem], PaginationItem]
|
|
44
|
+
Returns a tuple with a list of UserItem objects and a PaginationItem object.
|
|
45
|
+
|
|
46
|
+
Raises
|
|
47
|
+
------
|
|
48
|
+
ServerResponseError
|
|
49
|
+
code: 400006
|
|
50
|
+
summary: Invalid page number
|
|
51
|
+
detail: The page number is not an integer, is less than one, or is
|
|
52
|
+
greater than the final page number for users at the requested
|
|
53
|
+
page size.
|
|
54
|
+
|
|
55
|
+
ServerResponseError
|
|
56
|
+
code: 400007
|
|
57
|
+
summary: Invalid page size
|
|
58
|
+
detail: The page size parameter is not an integer, is less than one.
|
|
59
|
+
|
|
60
|
+
ServerResponseError
|
|
61
|
+
code: 403014
|
|
62
|
+
summary: Page size limit exceeded
|
|
63
|
+
detail: The specified page size is larger than the maximum page size
|
|
64
|
+
|
|
65
|
+
ServerResponseError
|
|
66
|
+
code: 404000
|
|
67
|
+
summary: Site not found
|
|
68
|
+
detail: The site ID in the URI doesn't correspond to an existing site.
|
|
69
|
+
|
|
70
|
+
ServerResponseError
|
|
71
|
+
code: 405000
|
|
72
|
+
summary: Invalid request method
|
|
73
|
+
detail: Request type was not GET.
|
|
74
|
+
|
|
75
|
+
Examples
|
|
76
|
+
--------
|
|
77
|
+
>>> import tableauserverclient as TSC
|
|
78
|
+
>>> tableau_auth = TSC.TableauAuth('USERNAME', 'PASSWORD')
|
|
79
|
+
>>> server = TSC.Server('https://SERVERURL')
|
|
80
|
+
|
|
81
|
+
>>> with server.auth.sign_in(tableau_auth):
|
|
82
|
+
>>> users_page, pagination_item = server.users.get()
|
|
83
|
+
>>> print("\nThere are {} user on site: ".format(pagination_item.total_available))
|
|
84
|
+
>>> print([user.name for user in users_page])
|
|
85
|
+
"""
|
|
22
86
|
logger.info("Querying all users on site")
|
|
23
87
|
|
|
24
88
|
if req_options is None:
|
|
@@ -34,55 +98,253 @@ class Users(QuerysetEndpoint[UserItem]):
|
|
|
34
98
|
# Gets 1 user by id
|
|
35
99
|
@api(version="2.0")
|
|
36
100
|
def get_by_id(self, user_id: str) -> UserItem:
|
|
101
|
+
"""
|
|
102
|
+
Query a single user by ID.
|
|
103
|
+
|
|
104
|
+
Parameters
|
|
105
|
+
----------
|
|
106
|
+
user_id : str
|
|
107
|
+
The ID of the user to query.
|
|
108
|
+
|
|
109
|
+
Returns
|
|
110
|
+
-------
|
|
111
|
+
UserItem
|
|
112
|
+
The user item that was queried.
|
|
113
|
+
|
|
114
|
+
Raises
|
|
115
|
+
------
|
|
116
|
+
ValueError
|
|
117
|
+
If the user ID is not specified.
|
|
118
|
+
|
|
119
|
+
ServerResponseError
|
|
120
|
+
code: 404000
|
|
121
|
+
summary: Site not found
|
|
122
|
+
detail: The site ID in the URI doesn't correspond to an existing site.
|
|
123
|
+
|
|
124
|
+
ServerResponseError
|
|
125
|
+
code: 403133
|
|
126
|
+
summary: Query user permissions forbidden
|
|
127
|
+
detail: The user does not have permissions to query user information
|
|
128
|
+
for other users
|
|
129
|
+
|
|
130
|
+
ServerResponseError
|
|
131
|
+
code: 404002
|
|
132
|
+
summary: User not found
|
|
133
|
+
detail: The user ID in the URI doesn't correspond to an existing user.
|
|
134
|
+
|
|
135
|
+
ServerResponseError
|
|
136
|
+
code: 405000
|
|
137
|
+
summary: Invalid request method
|
|
138
|
+
detail: Request type was not GET.
|
|
139
|
+
|
|
140
|
+
Examples
|
|
141
|
+
--------
|
|
142
|
+
>>> user1 = server.users.get_by_id('9f9e9d9c-8b8a-8f8e-7d7c-7b7a6f6d6e6d')
|
|
143
|
+
"""
|
|
37
144
|
if not user_id:
|
|
38
145
|
error = "User ID undefined."
|
|
39
146
|
raise ValueError(error)
|
|
40
|
-
logger.info("Querying single user (ID: {
|
|
41
|
-
url = "{
|
|
147
|
+
logger.info(f"Querying single user (ID: {user_id})")
|
|
148
|
+
url = f"{self.baseurl}/{user_id}"
|
|
42
149
|
server_response = self.get_request(url)
|
|
43
150
|
return UserItem.from_response(server_response.content, self.parent_srv.namespace).pop()
|
|
44
151
|
|
|
45
152
|
# Update user
|
|
46
153
|
@api(version="2.0")
|
|
47
154
|
def update(self, user_item: UserItem, password: Optional[str] = None) -> UserItem:
|
|
155
|
+
"""
|
|
156
|
+
Modifies information about the specified user.
|
|
157
|
+
|
|
158
|
+
If Tableau Server is configured to use local authentication, you can
|
|
159
|
+
update the user's name, email address, password, or site role.
|
|
160
|
+
|
|
161
|
+
If Tableau Server is configured to use Active Directory
|
|
162
|
+
authentication, you can change the user's display name (full name),
|
|
163
|
+
email address, and site role. However, if you synchronize the user with
|
|
164
|
+
Active Directory, the display name and email address will be
|
|
165
|
+
overwritten with the information that's in Active Directory.
|
|
166
|
+
|
|
167
|
+
For Tableau Cloud, you can update the site role for a user, but you
|
|
168
|
+
cannot update or change a user's password, user name (email address),
|
|
169
|
+
or full name.
|
|
170
|
+
|
|
171
|
+
Parameters
|
|
172
|
+
----------
|
|
173
|
+
user_item : UserItem
|
|
174
|
+
The user item to update.
|
|
175
|
+
|
|
176
|
+
password : Optional[str]
|
|
177
|
+
The new password for the user.
|
|
178
|
+
|
|
179
|
+
Returns
|
|
180
|
+
-------
|
|
181
|
+
UserItem
|
|
182
|
+
The user item that was updated.
|
|
183
|
+
|
|
184
|
+
Raises
|
|
185
|
+
------
|
|
186
|
+
MissingRequiredFieldError
|
|
187
|
+
If the user item is missing an ID.
|
|
188
|
+
|
|
189
|
+
Examples
|
|
190
|
+
--------
|
|
191
|
+
>>> user = server.users.get_by_id('9f9e9d9c-8b8a-8f8e-7d7c-7b7a6f6d6e6d')
|
|
192
|
+
>>> user.fullname = 'New Full Name'
|
|
193
|
+
>>> updated_user = server.users.update(user)
|
|
194
|
+
|
|
195
|
+
"""
|
|
48
196
|
if not user_item.id:
|
|
49
197
|
error = "User item missing ID."
|
|
50
198
|
raise MissingRequiredFieldError(error)
|
|
51
199
|
|
|
52
|
-
url = "{
|
|
200
|
+
url = f"{self.baseurl}/{user_item.id}"
|
|
53
201
|
update_req = RequestFactory.User.update_req(user_item, password)
|
|
54
202
|
server_response = self.put_request(url, update_req)
|
|
55
|
-
logger.info("Updated user item (ID: {
|
|
203
|
+
logger.info(f"Updated user item (ID: {user_item.id})")
|
|
56
204
|
updated_item = copy.copy(user_item)
|
|
57
205
|
return updated_item._parse_common_tags(server_response.content, self.parent_srv.namespace)
|
|
58
206
|
|
|
59
207
|
# Delete 1 user by id
|
|
60
208
|
@api(version="2.0")
|
|
61
209
|
def remove(self, user_id: str, map_assets_to: Optional[str] = None) -> None:
|
|
210
|
+
"""
|
|
211
|
+
Removes a user from the site. You can also specify a user to map the
|
|
212
|
+
assets to when you remove the user.
|
|
213
|
+
|
|
214
|
+
Parameters
|
|
215
|
+
----------
|
|
216
|
+
user_id : str
|
|
217
|
+
The ID of the user to remove.
|
|
218
|
+
|
|
219
|
+
map_assets_to : Optional[str]
|
|
220
|
+
The ID of the user to map the assets to when you remove the user.
|
|
221
|
+
|
|
222
|
+
Returns
|
|
223
|
+
-------
|
|
224
|
+
None
|
|
225
|
+
|
|
226
|
+
Raises
|
|
227
|
+
------
|
|
228
|
+
ValueError
|
|
229
|
+
If the user ID is not specified.
|
|
230
|
+
|
|
231
|
+
Examples
|
|
232
|
+
--------
|
|
233
|
+
>>> server.users.remove('9f9e9d9c-8b8a-8f8e-7d7c-7b7a6f6d6e6d')
|
|
234
|
+
"""
|
|
62
235
|
if not user_id:
|
|
63
236
|
error = "User ID undefined."
|
|
64
237
|
raise ValueError(error)
|
|
65
|
-
url = "{
|
|
238
|
+
url = f"{self.baseurl}/{user_id}"
|
|
66
239
|
if map_assets_to is not None:
|
|
67
240
|
url += f"?mapAssetsTo={map_assets_to}"
|
|
68
241
|
self.delete_request(url)
|
|
69
|
-
logger.info("Removed single user (ID: {
|
|
242
|
+
logger.info(f"Removed single user (ID: {user_id})")
|
|
70
243
|
|
|
71
244
|
# Add new user to site
|
|
72
245
|
@api(version="2.0")
|
|
73
246
|
def add(self, user_item: UserItem) -> UserItem:
|
|
247
|
+
"""
|
|
248
|
+
Adds the user to the site.
|
|
249
|
+
|
|
250
|
+
To add a new user to the site you need to first create a new user_item
|
|
251
|
+
(from UserItem class). When you create a new user, you specify the name
|
|
252
|
+
of the user and their site role. For Tableau Cloud, you also specify
|
|
253
|
+
the auth_setting attribute in your request. When you add user to
|
|
254
|
+
Tableau Cloud, the name of the user must be the email address that is
|
|
255
|
+
used to sign in to Tableau Cloud. After you add a user, Tableau Cloud
|
|
256
|
+
sends the user an email invitation. The user can click the link in the
|
|
257
|
+
invitation to sign in and update their full name and password.
|
|
258
|
+
|
|
259
|
+
Parameters
|
|
260
|
+
----------
|
|
261
|
+
user_item : UserItem
|
|
262
|
+
The user item to add to the site.
|
|
263
|
+
|
|
264
|
+
Returns
|
|
265
|
+
-------
|
|
266
|
+
UserItem
|
|
267
|
+
The user item that was added to the site with attributes from the
|
|
268
|
+
site populated.
|
|
269
|
+
|
|
270
|
+
Raises
|
|
271
|
+
------
|
|
272
|
+
ValueError
|
|
273
|
+
If the user item is missing a name
|
|
274
|
+
|
|
275
|
+
ValueError
|
|
276
|
+
If the user item is missing a site role
|
|
277
|
+
|
|
278
|
+
ServerResponseError
|
|
279
|
+
code: 400000
|
|
280
|
+
summary: Bad Request
|
|
281
|
+
detail: The content of the request body is missing or incomplete, or
|
|
282
|
+
contains malformed XML.
|
|
283
|
+
|
|
284
|
+
ServerResponseError
|
|
285
|
+
code: 400003
|
|
286
|
+
summary: Bad Request
|
|
287
|
+
detail: The user authentication setting ServerDefault is not
|
|
288
|
+
supported for you site. Try again using TableauIDWithMFA instead.
|
|
289
|
+
|
|
290
|
+
ServerResponseError
|
|
291
|
+
code: 400013
|
|
292
|
+
summary: Invalid site role
|
|
293
|
+
detail: The value of the siteRole attribute must be Explorer,
|
|
294
|
+
ExplorerCanPublish, SiteAdministratorCreator,
|
|
295
|
+
SiteAdministratorExplorer, Unlicensed, or Viewer.
|
|
296
|
+
|
|
297
|
+
ServerResponseError
|
|
298
|
+
code: 404000
|
|
299
|
+
summary: Site not found
|
|
300
|
+
detail: The site ID in the URI doesn't correspond to an existing site.
|
|
301
|
+
|
|
302
|
+
ServerResponseError
|
|
303
|
+
code: 404002
|
|
304
|
+
summary: User not found
|
|
305
|
+
detail: The server is configured to use Active Directory for
|
|
306
|
+
authentication, and the username specified in the request body
|
|
307
|
+
doesn't match an existing user in Active Directory.
|
|
308
|
+
|
|
309
|
+
ServerResponseError
|
|
310
|
+
code: 405000
|
|
311
|
+
summary: Invalid request method
|
|
312
|
+
detail: Request type was not POST.
|
|
313
|
+
|
|
314
|
+
ServerResponseError
|
|
315
|
+
code: 409000
|
|
316
|
+
summary: User conflict
|
|
317
|
+
detail: The specified user already exists on the site.
|
|
318
|
+
|
|
319
|
+
ServerResponseError
|
|
320
|
+
code: 409005
|
|
321
|
+
summary: Guest user conflict
|
|
322
|
+
detail: The Tableau Server API doesn't allow adding a user with the
|
|
323
|
+
guest role to a site.
|
|
324
|
+
|
|
325
|
+
|
|
326
|
+
Examples
|
|
327
|
+
--------
|
|
328
|
+
>>> import tableauserverclient as TSC
|
|
329
|
+
>>> server = TSC.Server('https://SERVERURL')
|
|
330
|
+
>>> # Login to the server
|
|
331
|
+
|
|
332
|
+
>>> new_user = TSC.UserItem(name='new_user', site_role=TSC.UserItem.Role.Unlicensed)
|
|
333
|
+
>>> new_user = server.users.add(new_user)
|
|
334
|
+
|
|
335
|
+
"""
|
|
74
336
|
url = self.baseurl
|
|
75
|
-
logger.info("Add user {
|
|
337
|
+
logger.info(f"Add user {user_item.name}")
|
|
76
338
|
add_req = RequestFactory.User.add_req(user_item)
|
|
77
339
|
server_response = self.post_request(url, add_req)
|
|
78
340
|
logger.info(server_response)
|
|
79
341
|
new_user = UserItem.from_response(server_response.content, self.parent_srv.namespace).pop()
|
|
80
|
-
logger.info("Added new user (ID: {
|
|
342
|
+
logger.info(f"Added new user (ID: {new_user.id})")
|
|
81
343
|
return new_user
|
|
82
344
|
|
|
83
345
|
# Add new users to site. This does not actually perform a bulk action, it's syntactic sugar
|
|
84
346
|
@api(version="2.0")
|
|
85
|
-
def add_all(self, users:
|
|
347
|
+
def add_all(self, users: list[UserItem]):
|
|
86
348
|
created = []
|
|
87
349
|
failed = []
|
|
88
350
|
for user in users:
|
|
@@ -96,7 +358,7 @@ class Users(QuerysetEndpoint[UserItem]):
|
|
|
96
358
|
# helping the user by parsing a file they could have used to add users through the UI
|
|
97
359
|
# line format: Username [required], password, display name, license, admin, publish
|
|
98
360
|
@api(version="2.0")
|
|
99
|
-
def create_from_file(self, filepath: str) ->
|
|
361
|
+
def create_from_file(self, filepath: str) -> tuple[list[UserItem], list[tuple[UserItem, ServerResponseError]]]:
|
|
100
362
|
created = []
|
|
101
363
|
failed = []
|
|
102
364
|
if not filepath.find("csv"):
|
|
@@ -120,6 +382,42 @@ class Users(QuerysetEndpoint[UserItem]):
|
|
|
120
382
|
# Get workbooks for user
|
|
121
383
|
@api(version="2.0")
|
|
122
384
|
def populate_workbooks(self, user_item: UserItem, req_options: Optional[RequestOptions] = None) -> None:
|
|
385
|
+
"""
|
|
386
|
+
Returns information about the workbooks that the specified user owns
|
|
387
|
+
and has Read (view) permissions for.
|
|
388
|
+
|
|
389
|
+
This method retrieves the workbook information for the specified user.
|
|
390
|
+
The REST API is designed to return only the information you ask for
|
|
391
|
+
explicitly. When you query for all the users, the workbook information
|
|
392
|
+
for each user is not included. Use this method to retrieve information
|
|
393
|
+
about the workbooks that the user owns or has Read (view) permissions.
|
|
394
|
+
The method adds the list of workbooks to the user item object
|
|
395
|
+
(user_item.workbooks).
|
|
396
|
+
|
|
397
|
+
Parameters
|
|
398
|
+
----------
|
|
399
|
+
user_item : UserItem
|
|
400
|
+
The user item to populate workbooks for.
|
|
401
|
+
|
|
402
|
+
req_options : Optional[RequestOptions]
|
|
403
|
+
Optional request options to filter and sort the results.
|
|
404
|
+
|
|
405
|
+
Returns
|
|
406
|
+
-------
|
|
407
|
+
None
|
|
408
|
+
|
|
409
|
+
Raises
|
|
410
|
+
------
|
|
411
|
+
MissingRequiredFieldError
|
|
412
|
+
If the user item is missing an ID.
|
|
413
|
+
|
|
414
|
+
Examples
|
|
415
|
+
--------
|
|
416
|
+
>>> user = server.users.get_by_id('9f9e9d9c-8b8a-8f8e-7d7c-7b7a6f6d6e6d')
|
|
417
|
+
>>> server.users.populate_workbooks(user)
|
|
418
|
+
>>> for wb in user.workbooks:
|
|
419
|
+
>>> print(wb.name)
|
|
420
|
+
"""
|
|
123
421
|
if not user_item.id:
|
|
124
422
|
error = "User item missing ID."
|
|
125
423
|
raise MissingRequiredFieldError(error)
|
|
@@ -131,20 +429,71 @@ class Users(QuerysetEndpoint[UserItem]):
|
|
|
131
429
|
|
|
132
430
|
def _get_wbs_for_user(
|
|
133
431
|
self, user_item: UserItem, req_options: Optional[RequestOptions] = None
|
|
134
|
-
) ->
|
|
135
|
-
url = "{
|
|
432
|
+
) -> tuple[list[WorkbookItem], PaginationItem]:
|
|
433
|
+
url = f"{self.baseurl}/{user_item.id}/workbooks"
|
|
136
434
|
server_response = self.get_request(url, req_options)
|
|
137
|
-
logger.info("Populated workbooks for user (ID: {
|
|
435
|
+
logger.info(f"Populated workbooks for user (ID: {user_item.id})")
|
|
138
436
|
workbook_item = WorkbookItem.from_response(server_response.content, self.parent_srv.namespace)
|
|
139
437
|
pagination_item = PaginationItem.from_response(server_response.content, self.parent_srv.namespace)
|
|
140
438
|
return workbook_item, pagination_item
|
|
141
439
|
|
|
142
440
|
def populate_favorites(self, user_item: UserItem) -> None:
|
|
441
|
+
"""
|
|
442
|
+
Populate the favorites for the user.
|
|
443
|
+
|
|
444
|
+
Parameters
|
|
445
|
+
----------
|
|
446
|
+
user_item : UserItem
|
|
447
|
+
The user item to populate favorites for.
|
|
448
|
+
|
|
449
|
+
Returns
|
|
450
|
+
-------
|
|
451
|
+
None
|
|
452
|
+
|
|
453
|
+
Examples
|
|
454
|
+
--------
|
|
455
|
+
>>> import tableauserverclient as TSC
|
|
456
|
+
>>> server = TSC.Server('https://SERVERURL')
|
|
457
|
+
>>> # Login to the server
|
|
458
|
+
|
|
459
|
+
>>> user = server.users.get_by_id('9f9e9d9c-8b8a-8f8e-7d7c-7b7a6f6d6e6d')
|
|
460
|
+
>>> server.users.populate_favorites(user)
|
|
461
|
+
>>> for obj_type, items in user.favorites.items():
|
|
462
|
+
>>> print(f"Favorites for {obj_type}:")
|
|
463
|
+
>>> for item in items:
|
|
464
|
+
>>> print(item.name)
|
|
465
|
+
"""
|
|
143
466
|
self.parent_srv.favorites.get(user_item)
|
|
144
467
|
|
|
145
468
|
# Get groups for user
|
|
146
469
|
@api(version="3.7")
|
|
147
470
|
def populate_groups(self, user_item: UserItem, req_options: Optional[RequestOptions] = None) -> None:
|
|
471
|
+
"""
|
|
472
|
+
Populate the groups for the user.
|
|
473
|
+
|
|
474
|
+
Parameters
|
|
475
|
+
----------
|
|
476
|
+
user_item : UserItem
|
|
477
|
+
The user item to populate groups for.
|
|
478
|
+
|
|
479
|
+
req_options : Optional[RequestOptions]
|
|
480
|
+
Optional request options to filter and sort the results.
|
|
481
|
+
|
|
482
|
+
Returns
|
|
483
|
+
-------
|
|
484
|
+
None
|
|
485
|
+
|
|
486
|
+
Raises
|
|
487
|
+
------
|
|
488
|
+
MissingRequiredFieldError
|
|
489
|
+
If the user item is missing an ID.
|
|
490
|
+
|
|
491
|
+
Examples
|
|
492
|
+
--------
|
|
493
|
+
>>> server.users.populate_groups(user)
|
|
494
|
+
>>> for group in user.groups:
|
|
495
|
+
>>> print(group.name)
|
|
496
|
+
"""
|
|
148
497
|
if not user_item.id:
|
|
149
498
|
error = "User item missing ID."
|
|
150
499
|
raise MissingRequiredFieldError(error)
|
|
@@ -159,10 +508,47 @@ class Users(QuerysetEndpoint[UserItem]):
|
|
|
159
508
|
|
|
160
509
|
def _get_groups_for_user(
|
|
161
510
|
self, user_item: UserItem, req_options: Optional[RequestOptions] = None
|
|
162
|
-
) ->
|
|
163
|
-
url = "{
|
|
511
|
+
) -> tuple[list[GroupItem], PaginationItem]:
|
|
512
|
+
url = f"{self.baseurl}/{user_item.id}/groups"
|
|
164
513
|
server_response = self.get_request(url, req_options)
|
|
165
|
-
logger.info("Populated groups for user (ID: {
|
|
514
|
+
logger.info(f"Populated groups for user (ID: {user_item.id})")
|
|
166
515
|
group_item = GroupItem.from_response(server_response.content, self.parent_srv.namespace)
|
|
167
516
|
pagination_item = PaginationItem.from_response(server_response.content, self.parent_srv.namespace)
|
|
168
517
|
return group_item, pagination_item
|
|
518
|
+
|
|
519
|
+
def filter(self, *invalid, page_size: Optional[int] = None, **kwargs) -> QuerySet[UserItem]:
|
|
520
|
+
"""
|
|
521
|
+
Queries the Tableau Server for items using the specified filters. Page
|
|
522
|
+
size can be specified to limit the number of items returned in a single
|
|
523
|
+
request. If not specified, the default page size is 100. Page size can
|
|
524
|
+
be an integer between 1 and 1000.
|
|
525
|
+
|
|
526
|
+
No positional arguments are allowed. All filters must be specified as
|
|
527
|
+
keyword arguments. If you use the equality operator, you can specify it
|
|
528
|
+
through <field_name>=<value>. If you want to use a different operator,
|
|
529
|
+
you can specify it through <field_name>__<operator>=<value>. Field
|
|
530
|
+
names can either be in snake_case or camelCase.
|
|
531
|
+
|
|
532
|
+
This endpoint supports the following fields and operators:
|
|
533
|
+
|
|
534
|
+
|
|
535
|
+
domain_name=...
|
|
536
|
+
domain_name__in=...
|
|
537
|
+
friendly_name=...
|
|
538
|
+
friendly_name__in=...
|
|
539
|
+
is_local=...
|
|
540
|
+
last_login=...
|
|
541
|
+
last_login__gt=...
|
|
542
|
+
last_login__gte=...
|
|
543
|
+
last_login__lt=...
|
|
544
|
+
last_login__lte=...
|
|
545
|
+
luid=...
|
|
546
|
+
luid__in=...
|
|
547
|
+
name__cieq=...
|
|
548
|
+
name=...
|
|
549
|
+
name__in=...
|
|
550
|
+
site_role=...
|
|
551
|
+
site_role__in=...
|
|
552
|
+
"""
|
|
553
|
+
|
|
554
|
+
return super().filter(*invalid, page_size=page_size, **kwargs)
|