tableauserverclient 0.37__py3-none-any.whl → 0.38__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.
Files changed (36) hide show
  1. tableauserverclient/__init__.py +4 -0
  2. tableauserverclient/bin/_version.py +3 -3
  3. tableauserverclient/helpers/strings.py +25 -1
  4. tableauserverclient/models/__init__.py +6 -1
  5. tableauserverclient/models/datasource_item.py +110 -2
  6. tableauserverclient/models/extract_item.py +82 -0
  7. tableauserverclient/models/flow_item.py +2 -2
  8. tableauserverclient/models/group_item.py +11 -0
  9. tableauserverclient/models/interval_item.py +40 -0
  10. tableauserverclient/models/location_item.py +53 -0
  11. tableauserverclient/models/project_item.py +138 -27
  12. tableauserverclient/models/schedule_item.py +57 -0
  13. tableauserverclient/models/site_item.py +28 -0
  14. tableauserverclient/models/table_item.py +7 -3
  15. tableauserverclient/models/tableau_types.py +13 -1
  16. tableauserverclient/models/user_item.py +101 -1
  17. tableauserverclient/models/view_item.py +79 -5
  18. tableauserverclient/models/workbook_item.py +151 -1
  19. tableauserverclient/server/endpoint/databases_endpoint.py +101 -18
  20. tableauserverclient/server/endpoint/datasources_endpoint.py +3 -3
  21. tableauserverclient/server/endpoint/dqw_endpoint.py +16 -6
  22. tableauserverclient/server/endpoint/endpoint.py +39 -0
  23. tableauserverclient/server/endpoint/schedules_endpoint.py +132 -2
  24. tableauserverclient/server/endpoint/sites_endpoint.py +18 -1
  25. tableauserverclient/server/endpoint/tables_endpoint.py +140 -17
  26. tableauserverclient/server/endpoint/users_endpoint.py +22 -5
  27. tableauserverclient/server/query.py +36 -0
  28. tableauserverclient/server/request_factory.py +5 -0
  29. tableauserverclient/server/request_options.py +128 -2
  30. tableauserverclient/server/server.py +42 -0
  31. {tableauserverclient-0.37.dist-info → tableauserverclient-0.38.dist-info}/METADATA +1 -1
  32. {tableauserverclient-0.37.dist-info → tableauserverclient-0.38.dist-info}/RECORD +36 -34
  33. {tableauserverclient-0.37.dist-info → tableauserverclient-0.38.dist-info}/WHEEL +1 -1
  34. {tableauserverclient-0.37.dist-info → tableauserverclient-0.38.dist-info}/licenses/LICENSE +0 -0
  35. {tableauserverclient-0.37.dist-info → tableauserverclient-0.38.dist-info}/licenses/LICENSE.versioneer +0 -0
  36. {tableauserverclient-0.37.dist-info → tableauserverclient-0.38.dist-info}/top_level.txt +0 -0
@@ -1,15 +1,21 @@
1
1
  import copy
2
2
  from datetime import datetime
3
3
  from requests import Response
4
- from typing import Callable, Optional
4
+ from typing import TYPE_CHECKING, Callable, Optional, overload
5
5
  from collections.abc import Iterator
6
6
 
7
7
  from defusedxml.ElementTree import fromstring
8
8
 
9
9
  from tableauserverclient.datetime_helpers import parse_datetime
10
10
  from tableauserverclient.models.exceptions import UnpopulatedPropertyError
11
+ from tableauserverclient.models.location_item import LocationItem
11
12
  from tableauserverclient.models.permissions_item import PermissionsRule
13
+ from tableauserverclient.models.project_item import ProjectItem
12
14
  from tableauserverclient.models.tag_item import TagItem
15
+ from tableauserverclient.models.user_item import UserItem
16
+
17
+ if TYPE_CHECKING:
18
+ from tableauserverclient.models.workbook_item import WorkbookItem
13
19
 
14
20
 
15
21
  class ViewItem:
@@ -34,9 +40,16 @@ class ViewItem:
34
40
  The image of the view. You must first call the `views.populate_image`
35
41
  method to access the image.
36
42
 
43
+ location: Optional[LocationItem], default None
44
+ The location of the view. The location can be a personal space or a
45
+ project.
46
+
37
47
  name: Optional[str], default None
38
48
  The name of the view.
39
49
 
50
+ owner: Optional[UserItem], default None
51
+ The owner of the view.
52
+
40
53
  owner_id: Optional[str], default None
41
54
  The ID for the owner of the view.
42
55
 
@@ -48,6 +61,9 @@ class ViewItem:
48
61
  The preview image of the view. You must first call the
49
62
  `views.populate_preview_image` method to access the preview image.
50
63
 
64
+ project: Optional[ProjectItem], default None
65
+ The project that contains the view.
66
+
51
67
  project_id: Optional[str], default None
52
68
  The ID for the project that contains the view.
53
69
 
@@ -60,9 +76,11 @@ class ViewItem:
60
76
  updated_at: Optional[datetime], default None
61
77
  The date and time when the view was last updated.
62
78
 
79
+ workbook: Optional[WorkbookItem], default None
80
+ The workbook that contains the view.
81
+
63
82
  workbook_id: Optional[str], default None
64
83
  The ID for the workbook that contains the view.
65
-
66
84
  """
67
85
 
68
86
  def __init__(self) -> None:
@@ -84,11 +102,18 @@ class ViewItem:
84
102
  self._workbook_id: Optional[str] = None
85
103
  self._permissions: Optional[Callable[[], list[PermissionsRule]]] = None
86
104
  self.tags: set[str] = set()
105
+ self._favorites_total: Optional[int] = None
106
+ self._view_url_name: Optional[str] = None
87
107
  self._data_acceleration_config = {
88
108
  "acceleration_enabled": None,
89
109
  "acceleration_status": None,
90
110
  }
91
111
 
112
+ self._owner: Optional[UserItem] = None
113
+ self._project: Optional[ProjectItem] = None
114
+ self._workbook: Optional["WorkbookItem"] = None
115
+ self._location: Optional[LocationItem] = None
116
+
92
117
  def __str__(self):
93
118
  return "<ViewItem {} '{}' contentUrl='{}' project={}>".format(
94
119
  self._id, self.name, self.content_url, self.project_id
@@ -190,6 +215,14 @@ class ViewItem:
190
215
  def workbook_id(self) -> Optional[str]:
191
216
  return self._workbook_id
192
217
 
218
+ @property
219
+ def view_url_name(self) -> Optional[str]:
220
+ return self._view_url_name
221
+
222
+ @property
223
+ def favorites_total(self) -> Optional[int]:
224
+ return self._favorites_total
225
+
193
226
  @property
194
227
  def data_acceleration_config(self):
195
228
  return self._data_acceleration_config
@@ -198,6 +231,22 @@ class ViewItem:
198
231
  def data_acceleration_config(self, value):
199
232
  self._data_acceleration_config = value
200
233
 
234
+ @property
235
+ def project(self) -> Optional["ProjectItem"]:
236
+ return self._project
237
+
238
+ @property
239
+ def workbook(self) -> Optional["WorkbookItem"]:
240
+ return self._workbook
241
+
242
+ @property
243
+ def owner(self) -> Optional[UserItem]:
244
+ return self._owner
245
+
246
+ @property
247
+ def location(self) -> Optional[LocationItem]:
248
+ return self._location
249
+
201
250
  @property
202
251
  def permissions(self) -> list[PermissionsRule]:
203
252
  if self._permissions is None:
@@ -228,7 +277,7 @@ class ViewItem:
228
277
  workbook_elem = view_xml.find(".//t:workbook", namespaces=ns)
229
278
  owner_elem = view_xml.find(".//t:owner", namespaces=ns)
230
279
  project_elem = view_xml.find(".//t:project", namespaces=ns)
231
- tags_elem = view_xml.find(".//t:tags", namespaces=ns)
280
+ tags_elem = view_xml.find("./t:tags", namespaces=ns)
232
281
  data_acceleration_config_elem = view_xml.find(".//t:dataAccelerationConfig", namespaces=ns)
233
282
  view_item._created_at = parse_datetime(view_xml.get("createdAt", None))
234
283
  view_item._updated_at = parse_datetime(view_xml.get("updatedAt", None))
@@ -236,22 +285,35 @@ class ViewItem:
236
285
  view_item._name = view_xml.get("name", None)
237
286
  view_item._content_url = view_xml.get("contentUrl", None)
238
287
  view_item._sheet_type = view_xml.get("sheetType", None)
288
+ view_item._favorites_total = string_to_int(view_xml.get("favoritesTotal", None))
289
+ view_item._view_url_name = view_xml.get("viewUrlName", None)
239
290
  if usage_elem is not None:
240
291
  total_view = usage_elem.get("totalViewCount", None)
241
292
  if total_view:
242
293
  view_item._total_views = int(total_view)
243
294
  if owner_elem is not None:
295
+ user = UserItem.from_xml(owner_elem, ns)
296
+ view_item._owner = user
244
297
  view_item._owner_id = owner_elem.get("id", None)
245
298
  if project_elem is not None:
246
- view_item._project_id = project_elem.get("id", None)
299
+ project_item = ProjectItem.from_xml(project_elem, ns)
300
+ view_item._project = project_item
301
+ view_item._project_id = project_item.id
247
302
  if workbook_id:
248
303
  view_item._workbook_id = workbook_id
249
304
  elif workbook_elem is not None:
250
- view_item._workbook_id = workbook_elem.get("id", None)
305
+ from tableauserverclient.models.workbook_item import WorkbookItem
306
+
307
+ workbook_item = WorkbookItem.from_xml(workbook_elem, ns)
308
+ view_item._workbook = workbook_item
309
+ view_item._workbook_id = workbook_item.id
251
310
  if tags_elem is not None:
252
311
  tags = TagItem.from_xml_element(tags_elem, ns)
253
312
  view_item.tags = tags
254
313
  view_item._initial_tags = copy.copy(tags)
314
+ if (location_elem := view_xml.find(".//t:location", namespaces=ns)) is not None:
315
+ location = LocationItem.from_xml(location_elem, ns)
316
+ view_item._location = location
255
317
  if data_acceleration_config_elem is not None:
256
318
  data_acceleration_config = parse_data_acceleration_config(data_acceleration_config_elem)
257
319
  view_item.data_acceleration_config = data_acceleration_config
@@ -274,3 +336,15 @@ def parse_data_acceleration_config(data_acceleration_elem):
274
336
 
275
337
  def string_to_bool(s: str) -> bool:
276
338
  return s.lower() == "true"
339
+
340
+
341
+ @overload
342
+ def string_to_int(s: None) -> None: ...
343
+
344
+
345
+ @overload
346
+ def string_to_int(s: str) -> int: ...
347
+
348
+
349
+ def string_to_int(s):
350
+ return int(s) if s is not None else None
@@ -2,11 +2,14 @@ import copy
2
2
  import datetime
3
3
  import uuid
4
4
  import xml.etree.ElementTree as ET
5
- from typing import Callable, Optional
5
+ from typing import Callable, Optional, overload
6
6
 
7
7
  from defusedxml.ElementTree import fromstring
8
8
 
9
9
  from tableauserverclient.datetime_helpers import parse_datetime
10
+ from tableauserverclient.models.location_item import LocationItem
11
+ from tableauserverclient.models.project_item import ProjectItem
12
+ from tableauserverclient.models.user_item import UserItem
10
13
  from .connection_item import ConnectionItem
11
14
  from .exceptions import UnpopulatedPropertyError
12
15
  from .permissions_item import PermissionsRule
@@ -51,13 +54,31 @@ class WorkbookItem:
51
54
  created_at : Optional[datetime.datetime]
52
55
  The date and time the workbook was created.
53
56
 
57
+ default_view_id : Optional[str]
58
+ The identifier for the default view of the workbook.
59
+
54
60
  description : Optional[str]
55
61
  User-defined description of the workbook.
56
62
 
63
+ encrypt_extracts : Optional[bool]
64
+ Indicates whether extracts are encrypted.
65
+
66
+ has_extracts : Optional[bool]
67
+ Indicates whether the workbook has extracts.
68
+
57
69
  id : Optional[str]
58
70
  The identifier for the workbook. You need this value to query a specific
59
71
  workbook or to delete a workbook with the get_by_id and delete methods.
60
72
 
73
+ last_published_at : Optional[datetime.datetime]
74
+ The date and time the workbook was last published.
75
+
76
+ location : Optional[LocationItem]
77
+ The location of the workbook, such as a personal space or project.
78
+
79
+ owner : Optional[UserItem]
80
+ The owner of the workbook.
81
+
61
82
  owner_id : Optional[str]
62
83
  The identifier for the owner (UserItem) of the workbook.
63
84
 
@@ -65,6 +86,9 @@ class WorkbookItem:
65
86
  The thumbnail image for the view. You must first call the
66
87
  workbooks.populate_preview_image method to access this data.
67
88
 
89
+ project: Optional[ProjectItem]
90
+ The project that contains the workbook.
91
+
68
92
  project_name : Optional[str]
69
93
  The name of the project that contains the workbook.
70
94
 
@@ -139,6 +163,15 @@ class WorkbookItem:
139
163
  self._permissions = None
140
164
  self.thumbnails_user_id = thumbnails_user_id
141
165
  self.thumbnails_group_id = thumbnails_group_id
166
+ self._sheet_count: Optional[int] = None
167
+ self._has_extracts: Optional[bool] = None
168
+ self._project: Optional[ProjectItem] = None
169
+ self._owner: Optional[UserItem] = None
170
+ self._location: Optional[LocationItem] = None
171
+ self._encrypt_extracts: Optional[bool] = None
172
+ self._default_view_id: Optional[str] = None
173
+ self._share_description: Optional[str] = None
174
+ self._last_published_at: Optional[datetime.datetime] = None
142
175
 
143
176
  return None
144
177
 
@@ -234,6 +267,14 @@ class WorkbookItem:
234
267
  def size(self):
235
268
  return self._size
236
269
 
270
+ @property
271
+ def sheet_count(self) -> Optional[int]:
272
+ return self._sheet_count
273
+
274
+ @property
275
+ def has_extracts(self) -> Optional[bool]:
276
+ return self._has_extracts
277
+
237
278
  @property
238
279
  def updated_at(self) -> Optional[datetime.datetime]:
239
280
  return self._updated_at
@@ -300,6 +341,34 @@ class WorkbookItem:
300
341
  def thumbnails_group_id(self, value: str):
301
342
  self._thumbnails_group_id = value
302
343
 
344
+ @property
345
+ def project(self) -> Optional[ProjectItem]:
346
+ return self._project
347
+
348
+ @property
349
+ def owner(self) -> Optional[UserItem]:
350
+ return self._owner
351
+
352
+ @property
353
+ def location(self) -> Optional[LocationItem]:
354
+ return self._location
355
+
356
+ @property
357
+ def encrypt_extracts(self) -> Optional[bool]:
358
+ return self._encrypt_extracts
359
+
360
+ @property
361
+ def default_view_id(self) -> Optional[str]:
362
+ return self._default_view_id
363
+
364
+ @property
365
+ def share_description(self) -> Optional[str]:
366
+ return self._share_description
367
+
368
+ @property
369
+ def last_published_at(self) -> Optional[datetime.datetime]:
370
+ return self._last_published_at
371
+
303
372
  def _set_connections(self, connections):
304
373
  self._connections = connections
305
374
 
@@ -342,6 +411,15 @@ class WorkbookItem:
342
411
  views,
343
412
  data_acceleration_config,
344
413
  data_freshness_policy,
414
+ sheet_count,
415
+ has_extracts,
416
+ project,
417
+ owner,
418
+ location,
419
+ encrypt_extracts,
420
+ default_view_id,
421
+ share_description,
422
+ last_published_at,
345
423
  ) = self._parse_element(workbook_xml, ns)
346
424
 
347
425
  self._set_values(
@@ -361,6 +439,15 @@ class WorkbookItem:
361
439
  views,
362
440
  data_acceleration_config,
363
441
  data_freshness_policy,
442
+ sheet_count,
443
+ has_extracts,
444
+ project,
445
+ owner,
446
+ location,
447
+ encrypt_extracts,
448
+ default_view_id,
449
+ share_description,
450
+ last_published_at,
364
451
  )
365
452
 
366
453
  return self
@@ -383,6 +470,15 @@ class WorkbookItem:
383
470
  views,
384
471
  data_acceleration_config,
385
472
  data_freshness_policy,
473
+ sheet_count,
474
+ has_extracts,
475
+ project,
476
+ owner,
477
+ location,
478
+ encrypt_extracts,
479
+ default_view_id,
480
+ share_description,
481
+ last_published_at,
386
482
  ):
387
483
  if id is not None:
388
484
  self._id = id
@@ -417,6 +513,24 @@ class WorkbookItem:
417
513
  self.data_acceleration_config = data_acceleration_config
418
514
  if data_freshness_policy is not None:
419
515
  self.data_freshness_policy = data_freshness_policy
516
+ if sheet_count is not None:
517
+ self._sheet_count = sheet_count
518
+ if has_extracts is not None:
519
+ self._has_extracts = has_extracts
520
+ if project:
521
+ self._project = project
522
+ if owner:
523
+ self._owner = owner
524
+ if location:
525
+ self._location = location
526
+ if encrypt_extracts is not None:
527
+ self._encrypt_extracts = encrypt_extracts
528
+ if default_view_id is not None:
529
+ self._default_view_id = default_view_id
530
+ if share_description is not None:
531
+ self._share_description = share_description
532
+ if last_published_at is not None:
533
+ self._last_published_at = last_published_at
420
534
 
421
535
  @classmethod
422
536
  def from_response(cls, resp: str, ns: dict[str, str]) -> list["WorkbookItem"]:
@@ -443,6 +557,12 @@ class WorkbookItem:
443
557
  created_at = parse_datetime(workbook_xml.get("createdAt", None))
444
558
  description = workbook_xml.get("description", None)
445
559
  updated_at = parse_datetime(workbook_xml.get("updatedAt", None))
560
+ sheet_count = string_to_int(workbook_xml.get("sheetCount", None))
561
+ has_extracts = string_to_bool(workbook_xml.get("hasExtracts", ""))
562
+ encrypt_extracts = string_to_bool(e) if (e := workbook_xml.get("encryptExtracts", None)) is not None else None
563
+ default_view_id = workbook_xml.get("defaultViewId", None)
564
+ share_description = workbook_xml.get("shareDescription", None)
565
+ last_published_at = parse_datetime(workbook_xml.get("lastPublishedAt", None))
446
566
 
447
567
  size = workbook_xml.get("size", None)
448
568
  if size:
@@ -452,14 +572,18 @@ class WorkbookItem:
452
572
 
453
573
  project_id = None
454
574
  project_name = None
575
+ project = None
455
576
  project_tag = workbook_xml.find(".//t:project", namespaces=ns)
456
577
  if project_tag is not None:
578
+ project = ProjectItem.from_xml(project_tag, ns)
457
579
  project_id = project_tag.get("id", None)
458
580
  project_name = project_tag.get("name", None)
459
581
 
460
582
  owner_id = None
583
+ owner = None
461
584
  owner_tag = workbook_xml.find(".//t:owner", namespaces=ns)
462
585
  if owner_tag is not None:
586
+ owner = UserItem.from_xml(owner_tag, ns)
463
587
  owner_id = owner_tag.get("id", None)
464
588
 
465
589
  tags = None
@@ -473,6 +597,11 @@ class WorkbookItem:
473
597
  if views_elem is not None:
474
598
  views = ViewItem.from_xml_element(views_elem, ns)
475
599
 
600
+ location = None
601
+ location_elem = workbook_xml.find(".//t:location", namespaces=ns)
602
+ if location_elem is not None:
603
+ location = LocationItem.from_xml(location_elem, ns)
604
+
476
605
  data_acceleration_config = {
477
606
  "acceleration_enabled": None,
478
607
  "accelerate_now": None,
@@ -505,6 +634,15 @@ class WorkbookItem:
505
634
  views,
506
635
  data_acceleration_config,
507
636
  data_freshness_policy,
637
+ sheet_count,
638
+ has_extracts,
639
+ project,
640
+ owner,
641
+ location,
642
+ encrypt_extracts,
643
+ default_view_id,
644
+ share_description,
645
+ last_published_at,
508
646
  )
509
647
 
510
648
 
@@ -535,3 +673,15 @@ def parse_data_acceleration_config(data_acceleration_elem):
535
673
  # Used to convert string represented boolean to a boolean type
536
674
  def string_to_bool(s: str) -> bool:
537
675
  return s.lower() == "true"
676
+
677
+
678
+ @overload
679
+ def string_to_int(s: None) -> None: ...
680
+
681
+
682
+ @overload
683
+ def string_to_int(s: str) -> int: ...
684
+
685
+
686
+ def string_to_int(s):
687
+ return int(s) if s is not None else None
@@ -1,7 +1,8 @@
1
1
  import logging
2
- from typing import Union
2
+ from typing import TYPE_CHECKING, Optional, Union
3
3
  from collections.abc import Iterable
4
4
 
5
+ from tableauserverclient.models.permissions_item import PermissionsRule
5
6
  from tableauserverclient.server.endpoint.default_permissions_endpoint import _DefaultPermissionsEndpoint
6
7
  from tableauserverclient.server.endpoint.dqw_endpoint import _DataQualityWarningEndpoint
7
8
  from tableauserverclient.server.endpoint.endpoint import api, Endpoint
@@ -13,6 +14,10 @@ from tableauserverclient.models import DatabaseItem, TableItem, PaginationItem,
13
14
 
14
15
  from tableauserverclient.helpers.logging import logger
15
16
 
17
+ if TYPE_CHECKING:
18
+ from tableauserverclient.models.dqw_item import DQWItem
19
+ from tableauserverclient.server.request_options import RequestOptions
20
+
16
21
 
17
22
  class Databases(Endpoint, TaggingMixin):
18
23
  def __init__(self, parent_srv):
@@ -23,11 +28,29 @@ class Databases(Endpoint, TaggingMixin):
23
28
  self._data_quality_warnings = _DataQualityWarningEndpoint(parent_srv, Resource.Database)
24
29
 
25
30
  @property
26
- def baseurl(self):
31
+ def baseurl(self) -> str:
27
32
  return f"{self.parent_srv.baseurl}/sites/{self.parent_srv.site_id}/databases"
28
33
 
29
34
  @api(version="3.5")
30
- def get(self, req_options=None):
35
+ def get(self, req_options: Optional["RequestOptions"] = None) -> tuple[list[DatabaseItem], PaginationItem]:
36
+ """
37
+ Get information about all databases on the site. Endpoint is paginated,
38
+ and will return a default of 100 items per page. Use the `req_options`
39
+ parameter to customize the request.
40
+
41
+ REST API: https://help.tableau.com/current/api/rest_api/en-us/REST/rest_api_ref_metadata.htm#query_databases
42
+
43
+ Parameters
44
+ ----------
45
+ req_options : RequestOptions, optional
46
+ Options to customize the request. If not provided, defaults to None.
47
+
48
+ Returns
49
+ -------
50
+ tuple[list[DatabaseItem], PaginationItem]
51
+ A tuple containing a list of DatabaseItem objects and a
52
+ PaginationItem object.
53
+ """
31
54
  logger.info("Querying all databases on site")
32
55
  url = self.baseurl
33
56
  server_response = self.get_request(url, req_options)
@@ -37,7 +60,27 @@ class Databases(Endpoint, TaggingMixin):
37
60
 
38
61
  # Get 1 database
39
62
  @api(version="3.5")
40
- def get_by_id(self, database_id):
63
+ def get_by_id(self, database_id: str) -> DatabaseItem:
64
+ """
65
+ Get information about a single database asset on the site.
66
+
67
+ REST API: https://help.tableau.com/current/api/rest_api/en-us/REST/rest_api_ref_metadata.htm#query_database
68
+
69
+ Parameters
70
+ ----------
71
+ database_id : str
72
+ The ID of the database to retrieve.
73
+
74
+ Returns
75
+ -------
76
+ DatabaseItem
77
+ A DatabaseItem object representing the database.
78
+
79
+ Raises
80
+ ------
81
+ ValueError
82
+ If the database ID is undefined.
83
+ """
41
84
  if not database_id:
42
85
  error = "database ID undefined."
43
86
  raise ValueError(error)
@@ -47,7 +90,24 @@ class Databases(Endpoint, TaggingMixin):
47
90
  return DatabaseItem.from_response(server_response.content, self.parent_srv.namespace)[0]
48
91
 
49
92
  @api(version="3.5")
50
- def delete(self, database_id):
93
+ def delete(self, database_id: str) -> None:
94
+ """
95
+ Deletes a single database asset from the server.
96
+
97
+ Parameters
98
+ ----------
99
+ database_id : str
100
+ The ID of the database to delete.
101
+
102
+ Returns
103
+ -------
104
+ None
105
+
106
+ Raises
107
+ ------
108
+ ValueError
109
+ If the database ID is undefined.
110
+ """
51
111
  if not database_id:
52
112
  error = "Database ID undefined."
53
113
  raise ValueError(error)
@@ -56,7 +116,28 @@ class Databases(Endpoint, TaggingMixin):
56
116
  logger.info(f"Deleted single database (ID: {database_id})")
57
117
 
58
118
  @api(version="3.5")
59
- def update(self, database_item):
119
+ def update(self, database_item: DatabaseItem) -> DatabaseItem:
120
+ """
121
+ Update the database description, certify the database, set permissions,
122
+ or assign a User as the database contact.
123
+
124
+ REST API: https://help.tableau.com/current/api/rest_api/en-us/REST/rest_api_ref_metadata.htm#update_database
125
+
126
+ Parameters
127
+ ----------
128
+ database_item : DatabaseItem
129
+ The DatabaseItem object to update.
130
+
131
+ Returns
132
+ -------
133
+ DatabaseItem
134
+ The updated DatabaseItem object.
135
+
136
+ Raises
137
+ ------
138
+ MissingRequiredFieldError
139
+ If the database item is missing an ID.
140
+ """
60
141
  if not database_item.id:
61
142
  error = "Database item missing ID."
62
143
  raise MissingRequiredFieldError(error)
@@ -88,43 +169,45 @@ class Databases(Endpoint, TaggingMixin):
88
169
  return tables
89
170
 
90
171
  @api(version="3.5")
91
- def populate_permissions(self, item):
172
+ def populate_permissions(self, item: DatabaseItem) -> None:
92
173
  self._permissions.populate(item)
93
174
 
94
175
  @api(version="3.5")
95
- def update_permissions(self, item, rules):
176
+ def update_permissions(self, item: DatabaseItem, rules: list[PermissionsRule]) -> list[PermissionsRule]:
96
177
  return self._permissions.update(item, rules)
97
178
 
98
179
  @api(version="3.5")
99
- def delete_permission(self, item, rules):
180
+ def delete_permission(self, item: DatabaseItem, rules: list[PermissionsRule]) -> None:
100
181
  self._permissions.delete(item, rules)
101
182
 
102
183
  @api(version="3.5")
103
- def populate_table_default_permissions(self, item):
184
+ def populate_table_default_permissions(self, item: DatabaseItem):
104
185
  self._default_permissions.populate_default_permissions(item, Resource.Table)
105
186
 
106
187
  @api(version="3.5")
107
- def update_table_default_permissions(self, item):
108
- return self._default_permissions.update_default_permissions(item, Resource.Table)
188
+ def update_table_default_permissions(
189
+ self, item: DatabaseItem, rules: list[PermissionsRule]
190
+ ) -> list[PermissionsRule]:
191
+ return self._default_permissions.update_default_permissions(item, rules, Resource.Table)
109
192
 
110
193
  @api(version="3.5")
111
- def delete_table_default_permissions(self, item):
112
- self._default_permissions.delete_default_permission(item, Resource.Table)
194
+ def delete_table_default_permissions(self, rule: PermissionsRule, item: DatabaseItem) -> None:
195
+ self._default_permissions.delete_default_permission(item, rule, Resource.Table)
113
196
 
114
197
  @api(version="3.5")
115
- def populate_dqw(self, item):
198
+ def populate_dqw(self, item: DatabaseItem) -> None:
116
199
  self._data_quality_warnings.populate(item)
117
200
 
118
201
  @api(version="3.5")
119
- def update_dqw(self, item, warning):
202
+ def update_dqw(self, item: DatabaseItem, warning: "DQWItem") -> list["DQWItem"]:
120
203
  return self._data_quality_warnings.update(item, warning)
121
204
 
122
205
  @api(version="3.5")
123
- def add_dqw(self, item, warning):
206
+ def add_dqw(self, item: DatabaseItem, warning: "DQWItem") -> list["DQWItem"]:
124
207
  return self._data_quality_warnings.add(item, warning)
125
208
 
126
209
  @api(version="3.5")
127
- def delete_dqw(self, item):
210
+ def delete_dqw(self, item: DatabaseItem) -> None:
128
211
  self._data_quality_warnings.clear(item)
129
212
 
130
213
  @api(version="3.9")
@@ -733,7 +733,7 @@ class Datasources(QuerysetEndpoint[DatasourceItem], TaggingMixin[DatasourceItem]
733
733
  self._data_quality_warnings.populate(item)
734
734
 
735
735
  @api(version="3.5")
736
- def update_dqw(self, item, warning):
736
+ def update_dqw(self, item: DatasourceItem, warning: "DQWItem") -> list["DQWItem"]:
737
737
  """
738
738
  Update the warning type, status, and message of a data quality warning.
739
739
 
@@ -755,7 +755,7 @@ class Datasources(QuerysetEndpoint[DatasourceItem], TaggingMixin[DatasourceItem]
755
755
  return self._data_quality_warnings.update(item, warning)
756
756
 
757
757
  @api(version="3.5")
758
- def add_dqw(self, item, warning):
758
+ def add_dqw(self, item: DatasourceItem, warning: "DQWItem") -> list["DQWItem"]:
759
759
  """
760
760
  Add a data quality warning to a datasource.
761
761
 
@@ -786,7 +786,7 @@ class Datasources(QuerysetEndpoint[DatasourceItem], TaggingMixin[DatasourceItem]
786
786
  return self._data_quality_warnings.add(item, warning)
787
787
 
788
788
  @api(version="3.5")
789
- def delete_dqw(self, item):
789
+ def delete_dqw(self, item: DatasourceItem) -> None:
790
790
  """
791
791
  Delete a data quality warnings from an asset.
792
792