tableauserverclient 0.33__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.
Files changed (94) hide show
  1. tableauserverclient/__init__.py +28 -22
  2. tableauserverclient/_version.py +3 -3
  3. tableauserverclient/config.py +5 -3
  4. tableauserverclient/models/column_item.py +1 -1
  5. tableauserverclient/models/connection_credentials.py +1 -1
  6. tableauserverclient/models/connection_item.py +6 -6
  7. tableauserverclient/models/custom_view_item.py +29 -6
  8. tableauserverclient/models/data_acceleration_report_item.py +2 -2
  9. tableauserverclient/models/data_alert_item.py +5 -5
  10. tableauserverclient/models/data_freshness_policy_item.py +6 -6
  11. tableauserverclient/models/database_item.py +3 -3
  12. tableauserverclient/models/datasource_item.py +10 -10
  13. tableauserverclient/models/dqw_item.py +1 -1
  14. tableauserverclient/models/favorites_item.py +5 -6
  15. tableauserverclient/models/fileupload_item.py +1 -1
  16. tableauserverclient/models/flow_item.py +6 -6
  17. tableauserverclient/models/flow_run_item.py +3 -3
  18. tableauserverclient/models/group_item.py +4 -4
  19. tableauserverclient/models/groupset_item.py +4 -4
  20. tableauserverclient/models/interval_item.py +9 -9
  21. tableauserverclient/models/job_item.py +8 -8
  22. tableauserverclient/models/linked_tasks_item.py +5 -5
  23. tableauserverclient/models/metric_item.py +5 -5
  24. tableauserverclient/models/pagination_item.py +1 -1
  25. tableauserverclient/models/permissions_item.py +12 -10
  26. tableauserverclient/models/project_item.py +35 -19
  27. tableauserverclient/models/property_decorators.py +12 -11
  28. tableauserverclient/models/reference_item.py +2 -2
  29. tableauserverclient/models/revision_item.py +3 -3
  30. tableauserverclient/models/schedule_item.py +2 -2
  31. tableauserverclient/models/server_info_item.py +26 -6
  32. tableauserverclient/models/site_item.py +69 -3
  33. tableauserverclient/models/subscription_item.py +3 -3
  34. tableauserverclient/models/table_item.py +1 -1
  35. tableauserverclient/models/tableau_auth.py +115 -5
  36. tableauserverclient/models/tableau_types.py +2 -2
  37. tableauserverclient/models/tag_item.py +3 -4
  38. tableauserverclient/models/task_item.py +4 -4
  39. tableauserverclient/models/user_item.py +47 -17
  40. tableauserverclient/models/view_item.py +11 -10
  41. tableauserverclient/models/virtual_connection_item.py +6 -5
  42. tableauserverclient/models/webhook_item.py +6 -6
  43. tableauserverclient/models/workbook_item.py +90 -12
  44. tableauserverclient/namespace.py +1 -1
  45. tableauserverclient/server/__init__.py +2 -1
  46. tableauserverclient/server/endpoint/auth_endpoint.py +65 -8
  47. tableauserverclient/server/endpoint/custom_views_endpoint.py +62 -18
  48. tableauserverclient/server/endpoint/data_acceleration_report_endpoint.py +2 -2
  49. tableauserverclient/server/endpoint/data_alert_endpoint.py +14 -14
  50. tableauserverclient/server/endpoint/databases_endpoint.py +13 -12
  51. tableauserverclient/server/endpoint/datasources_endpoint.py +49 -54
  52. tableauserverclient/server/endpoint/default_permissions_endpoint.py +19 -18
  53. tableauserverclient/server/endpoint/dqw_endpoint.py +9 -9
  54. tableauserverclient/server/endpoint/endpoint.py +19 -21
  55. tableauserverclient/server/endpoint/exceptions.py +23 -7
  56. tableauserverclient/server/endpoint/favorites_endpoint.py +31 -31
  57. tableauserverclient/server/endpoint/fileuploads_endpoint.py +9 -11
  58. tableauserverclient/server/endpoint/flow_runs_endpoint.py +15 -13
  59. tableauserverclient/server/endpoint/flow_task_endpoint.py +2 -2
  60. tableauserverclient/server/endpoint/flows_endpoint.py +30 -29
  61. tableauserverclient/server/endpoint/groups_endpoint.py +18 -17
  62. tableauserverclient/server/endpoint/groupsets_endpoint.py +2 -2
  63. tableauserverclient/server/endpoint/jobs_endpoint.py +7 -7
  64. tableauserverclient/server/endpoint/linked_tasks_endpoint.py +2 -2
  65. tableauserverclient/server/endpoint/metadata_endpoint.py +2 -2
  66. tableauserverclient/server/endpoint/metrics_endpoint.py +10 -10
  67. tableauserverclient/server/endpoint/permissions_endpoint.py +13 -15
  68. tableauserverclient/server/endpoint/projects_endpoint.py +81 -30
  69. tableauserverclient/server/endpoint/resource_tagger.py +14 -13
  70. tableauserverclient/server/endpoint/schedules_endpoint.py +17 -18
  71. tableauserverclient/server/endpoint/server_info_endpoint.py +40 -5
  72. tableauserverclient/server/endpoint/sites_endpoint.py +282 -17
  73. tableauserverclient/server/endpoint/subscriptions_endpoint.py +10 -10
  74. tableauserverclient/server/endpoint/tables_endpoint.py +15 -14
  75. tableauserverclient/server/endpoint/tasks_endpoint.py +8 -8
  76. tableauserverclient/server/endpoint/users_endpoint.py +366 -19
  77. tableauserverclient/server/endpoint/views_endpoint.py +19 -18
  78. tableauserverclient/server/endpoint/virtual_connections_endpoint.py +6 -5
  79. tableauserverclient/server/endpoint/webhooks_endpoint.py +11 -11
  80. tableauserverclient/server/endpoint/workbooks_endpoint.py +647 -61
  81. tableauserverclient/server/filter.py +2 -2
  82. tableauserverclient/server/pager.py +5 -6
  83. tableauserverclient/server/query.py +68 -19
  84. tableauserverclient/server/request_factory.py +37 -36
  85. tableauserverclient/server/request_options.py +123 -145
  86. tableauserverclient/server/server.py +65 -9
  87. tableauserverclient/server/sort.py +2 -2
  88. {tableauserverclient-0.33.dist-info → tableauserverclient-0.34.dist-info}/METADATA +6 -6
  89. tableauserverclient-0.34.dist-info/RECORD +106 -0
  90. {tableauserverclient-0.33.dist-info → tableauserverclient-0.34.dist-info}/WHEEL +1 -1
  91. tableauserverclient-0.33.dist-info/RECORD +0 -106
  92. {tableauserverclient-0.33.dist-info → tableauserverclient-0.34.dist-info}/LICENSE +0 -0
  93. {tableauserverclient-0.33.dist-info → tableauserverclient-0.34.dist-info}/LICENSE.versioneer +0 -0
  94. {tableauserverclient-0.33.dist-info → tableauserverclient-0.34.dist-info}/top_level.txt +0 -0
@@ -32,11 +32,13 @@ from tableauserverclient.models import (
32
32
  PermissionsRule,
33
33
  PersonalAccessTokenAuth,
34
34
  ProjectItem,
35
+ Resource,
35
36
  RevisionItem,
36
37
  ScheduleItem,
37
38
  SiteItem,
38
39
  ServerInfoItem,
39
40
  SubscriptionItem,
41
+ TableauItem,
40
42
  TableItem,
41
43
  TableauAuth,
42
44
  Target,
@@ -56,6 +58,7 @@ from tableauserverclient.server import (
56
58
  PDFRequestOptions,
57
59
  RequestOptions,
58
60
  MissingRequiredFieldError,
61
+ FailedSignInError,
59
62
  NotSignedInError,
60
63
  ServerResponseError,
61
64
  Filter,
@@ -65,65 +68,68 @@ from tableauserverclient.server import (
65
68
  )
66
69
 
67
70
  __all__ = [
68
- "get_versions",
69
- "DEFAULT_NAMESPACE",
70
71
  "BackgroundJobItem",
71
72
  "BackgroundJobItem",
72
73
  "ColumnItem",
73
74
  "ConnectionCredentials",
74
75
  "ConnectionItem",
76
+ "CSVRequestOptions",
75
77
  "CustomViewItem",
76
- "DQWItem",
77
78
  "DailyInterval",
78
79
  "DataAlertItem",
79
80
  "DatabaseItem",
80
81
  "DataFreshnessPolicyItem",
81
82
  "DatasourceItem",
83
+ "DEFAULT_NAMESPACE",
84
+ "DQWItem",
85
+ "ExcelRequestOptions",
86
+ "FailedSignInError",
82
87
  "FavoriteItem",
88
+ "FileuploadItem",
89
+ "Filter",
83
90
  "FlowItem",
84
91
  "FlowRunItem",
85
- "FileuploadItem",
92
+ "get_versions",
86
93
  "GroupItem",
87
94
  "GroupSetItem",
88
95
  "HourlyInterval",
96
+ "ImageRequestOptions",
89
97
  "IntervalItem",
90
98
  "JobItem",
91
99
  "JWTAuth",
100
+ "LinkedTaskFlowRunItem",
101
+ "LinkedTaskItem",
102
+ "LinkedTaskStepItem",
92
103
  "MetricItem",
104
+ "MissingRequiredFieldError",
93
105
  "MonthlyInterval",
106
+ "NotSignedInError",
107
+ "Pager",
94
108
  "PaginationItem",
109
+ "PDFRequestOptions",
95
110
  "Permission",
96
111
  "PermissionsRule",
97
112
  "PersonalAccessTokenAuth",
98
113
  "ProjectItem",
114
+ "RequestOptions",
115
+ "Resource",
99
116
  "RevisionItem",
100
117
  "ScheduleItem",
101
- "SiteItem",
118
+ "Server",
102
119
  "ServerInfoItem",
120
+ "ServerResponseError",
121
+ "SiteItem",
122
+ "Sort",
103
123
  "SubscriptionItem",
104
- "TableItem",
105
124
  "TableauAuth",
125
+ "TableauItem",
126
+ "TableItem",
106
127
  "Target",
107
128
  "TaskItem",
108
129
  "UserItem",
109
130
  "ViewItem",
131
+ "VirtualConnectionItem",
110
132
  "WebhookItem",
111
133
  "WeeklyInterval",
112
134
  "WorkbookItem",
113
- "CSVRequestOptions",
114
- "ExcelRequestOptions",
115
- "ImageRequestOptions",
116
- "PDFRequestOptions",
117
- "RequestOptions",
118
- "MissingRequiredFieldError",
119
- "NotSignedInError",
120
- "ServerResponseError",
121
- "Filter",
122
- "Pager",
123
- "Server",
124
- "Sort",
125
- "LinkedTaskItem",
126
- "LinkedTaskStepItem",
127
- "LinkedTaskFlowRunItem",
128
- "VirtualConnectionItem",
129
135
  ]
@@ -8,11 +8,11 @@ import json
8
8
 
9
9
  version_json = '''
10
10
  {
11
- "date": "2024-09-17T16:51:07-0700",
11
+ "date": "2024-10-25T16:34:58-0700",
12
12
  "dirty": false,
13
13
  "error": null,
14
- "full-revisionid": "4259316ef2e2656531b0c65c71d043708b37b4a9",
15
- "version": "0.33"
14
+ "full-revisionid": "1d98fdad189ebed130fb904e8fa5dca2207f9011",
15
+ "version": "0.34"
16
16
  }
17
17
  ''' # END VERSION_JSON
18
18
 
@@ -6,11 +6,13 @@ BYTES_PER_MB = 1024 * 1024
6
6
 
7
7
  DELAY_SLEEP_SECONDS = 0.1
8
8
 
9
- # The maximum size of a file that can be published in a single request is 64MB
10
- FILESIZE_LIMIT_MB = 64
11
-
12
9
 
13
10
  class Config:
11
+ # The maximum size of a file that can be published in a single request is 64MB
12
+ @property
13
+ def FILESIZE_LIMIT_MB(self):
14
+ return min(int(os.getenv("TSC_FILESIZE_LIMIT_MB", 64)), 64)
15
+
14
16
  # For when a datasource is over 64MB, break it into 5MB(standard chunk size) chunks
15
17
  @property
16
18
  def CHUNK_SIZE_MB(self):
@@ -3,7 +3,7 @@ from defusedxml.ElementTree import fromstring
3
3
  from .property_decorators import property_not_empty
4
4
 
5
5
 
6
- class ColumnItem(object):
6
+ class ColumnItem:
7
7
  def __init__(self, name, description=None):
8
8
  self._id = None
9
9
  self.description = description
@@ -1,7 +1,7 @@
1
1
  from .property_decorators import property_is_boolean
2
2
 
3
3
 
4
- class ConnectionCredentials(object):
4
+ class ConnectionCredentials:
5
5
  """Connection Credentials for Workbooks and Datasources publish request.
6
6
 
7
7
  Consider removing this object and other variables holding secrets
@@ -1,5 +1,5 @@
1
1
  import logging
2
- from typing import List, Optional
2
+ from typing import Optional
3
3
 
4
4
  from defusedxml.ElementTree import fromstring
5
5
 
@@ -8,7 +8,7 @@ from .property_decorators import property_is_boolean
8
8
  from tableauserverclient.helpers.logging import logger
9
9
 
10
10
 
11
- class ConnectionItem(object):
11
+ class ConnectionItem:
12
12
  def __init__(self):
13
13
  self._datasource_id: Optional[str] = None
14
14
  self._datasource_name: Optional[str] = None
@@ -48,7 +48,7 @@ class ConnectionItem(object):
48
48
  # if connection type = hyper, Snowflake, or Teradata, we can't change this value: it is always true
49
49
  if self._connection_type in ["hyper", "snowflake", "teradata"]:
50
50
  logger.debug(
51
- "Cannot update value: Query tagging is always enabled for {} connections".format(self._connection_type)
51
+ f"Cannot update value: Query tagging is always enabled for {self._connection_type} connections"
52
52
  )
53
53
  return
54
54
  self._query_tagging = value
@@ -59,7 +59,7 @@ class ConnectionItem(object):
59
59
  )
60
60
 
61
61
  @classmethod
62
- def from_response(cls, resp, ns) -> List["ConnectionItem"]:
62
+ def from_response(cls, resp, ns) -> list["ConnectionItem"]:
63
63
  all_connection_items = list()
64
64
  parsed_response = fromstring(resp)
65
65
  all_connection_xml = parsed_response.findall(".//t:connection", namespaces=ns)
@@ -82,7 +82,7 @@ class ConnectionItem(object):
82
82
  return all_connection_items
83
83
 
84
84
  @classmethod
85
- def from_xml_element(cls, parsed_response, ns) -> List["ConnectionItem"]:
85
+ def from_xml_element(cls, parsed_response, ns) -> list["ConnectionItem"]:
86
86
  """
87
87
  <connections>
88
88
  <connection serverAddress="mysql.test.com">
@@ -93,7 +93,7 @@ class ConnectionItem(object):
93
93
  </connection>
94
94
  </connections>
95
95
  """
96
- all_connection_items: List["ConnectionItem"] = list()
96
+ all_connection_items: list["ConnectionItem"] = list()
97
97
  all_connection_xml = parsed_response.findall(".//t:connection", namespaces=ns)
98
98
 
99
99
  for connection_xml in all_connection_xml:
@@ -2,7 +2,8 @@ from datetime import datetime
2
2
 
3
3
  from defusedxml import ElementTree
4
4
  from defusedxml.ElementTree import fromstring, tostring
5
- from typing import Callable, List, Optional
5
+ from typing import Callable, Optional
6
+ from collections.abc import Iterator
6
7
 
7
8
  from .exceptions import UnpopulatedPropertyError
8
9
  from .user_item import UserItem
@@ -11,12 +12,14 @@ from .workbook_item import WorkbookItem
11
12
  from ..datetime_helpers import parse_datetime
12
13
 
13
14
 
14
- class CustomViewItem(object):
15
+ class CustomViewItem:
15
16
  def __init__(self, id: Optional[str] = None, name: Optional[str] = None) -> None:
16
17
  self._content_url: Optional[str] = None # ?
17
18
  self._created_at: Optional["datetime"] = None
18
19
  self._id: Optional[str] = id
19
20
  self._image: Optional[Callable[[], bytes]] = None
21
+ self._pdf: Optional[Callable[[], bytes]] = None
22
+ self._csv: Optional[Callable[[], Iterator[bytes]]] = None
20
23
  self._name: Optional[str] = name
21
24
  self._shared: Optional[bool] = False
22
25
  self._updated_at: Optional["datetime"] = None
@@ -35,11 +38,17 @@ class CustomViewItem(object):
35
38
  owner_info = ""
36
39
  if self._owner:
37
40
  owner_info = " owner='{}'".format(self._owner.name or self._owner.id or "unknown")
38
- return "<CustomViewItem id={} name=`{}`{}{}{}>".format(self.id, self.name, view_info, wb_info, owner_info)
41
+ return f"<CustomViewItem id={self.id} name=`{self.name}`{view_info}{wb_info}{owner_info}>"
39
42
 
40
43
  def _set_image(self, image):
41
44
  self._image = image
42
45
 
46
+ def _set_pdf(self, pdf):
47
+ self._pdf = pdf
48
+
49
+ def _set_csv(self, csv):
50
+ self._csv = csv
51
+
43
52
  @property
44
53
  def content_url(self) -> Optional[str]:
45
54
  return self._content_url
@@ -55,10 +64,24 @@ class CustomViewItem(object):
55
64
  @property
56
65
  def image(self) -> bytes:
57
66
  if self._image is None:
58
- error = "View item must be populated with its png image first."
67
+ error = "Custom View item must be populated with its png image first."
59
68
  raise UnpopulatedPropertyError(error)
60
69
  return self._image()
61
70
 
71
+ @property
72
+ def pdf(self) -> bytes:
73
+ if self._pdf is None:
74
+ error = "Custom View item must be populated with its pdf first."
75
+ raise UnpopulatedPropertyError(error)
76
+ return self._pdf()
77
+
78
+ @property
79
+ def csv(self) -> Iterator[bytes]:
80
+ if self._csv is None:
81
+ error = "Custom View item must be populated with its csv first."
82
+ raise UnpopulatedPropertyError(error)
83
+ return self._csv()
84
+
62
85
  @property
63
86
  def name(self) -> Optional[str]:
64
87
  return self._name
@@ -104,7 +127,7 @@ class CustomViewItem(object):
104
127
  return item[0]
105
128
 
106
129
  @classmethod
107
- def list_from_response(cls, resp, ns, workbook_id="") -> List["CustomViewItem"]:
130
+ def list_from_response(cls, resp, ns, workbook_id="") -> list["CustomViewItem"]:
108
131
  return cls.from_xml_element(fromstring(resp), ns, workbook_id)
109
132
 
110
133
  """
@@ -121,7 +144,7 @@ class CustomViewItem(object):
121
144
  """
122
145
 
123
146
  @classmethod
124
- def from_xml_element(cls, parsed_response, ns, workbook_id="") -> List["CustomViewItem"]:
147
+ def from_xml_element(cls, parsed_response, ns, workbook_id="") -> list["CustomViewItem"]:
125
148
  all_view_items = list()
126
149
  all_view_xml = parsed_response.findall(".//t:customView", namespaces=ns)
127
150
  for custom_view_xml in all_view_xml:
@@ -1,8 +1,8 @@
1
1
  from defusedxml.ElementTree import fromstring
2
2
 
3
3
 
4
- class DataAccelerationReportItem(object):
5
- class ComparisonRecord(object):
4
+ class DataAccelerationReportItem:
5
+ class ComparisonRecord:
6
6
  def __init__(
7
7
  self,
8
8
  site,
@@ -1,5 +1,5 @@
1
1
  from datetime import datetime
2
- from typing import List, Optional
2
+ from typing import Optional
3
3
 
4
4
  from defusedxml.ElementTree import fromstring
5
5
 
@@ -10,7 +10,7 @@ from .property_decorators import (
10
10
  )
11
11
 
12
12
 
13
- class DataAlertItem(object):
13
+ class DataAlertItem:
14
14
  class Frequency:
15
15
  Once = "Once"
16
16
  Frequently = "Frequently"
@@ -34,7 +34,7 @@ class DataAlertItem(object):
34
34
  self._workbook_name: Optional[str] = None
35
35
  self._project_id: Optional[str] = None
36
36
  self._project_name: Optional[str] = None
37
- self._recipients: Optional[List[str]] = None
37
+ self._recipients: Optional[list[str]] = None
38
38
 
39
39
  def __repr__(self) -> str:
40
40
  return "<Data Alert {_id} subject={_subject} frequency={_frequency} \
@@ -78,7 +78,7 @@ class DataAlertItem(object):
78
78
  return self._creatorId
79
79
 
80
80
  @property
81
- def recipients(self) -> List[str]:
81
+ def recipients(self) -> list[str]:
82
82
  return self._recipients or list()
83
83
 
84
84
  @property
@@ -174,7 +174,7 @@ class DataAlertItem(object):
174
174
  self._recipients = recipients
175
175
 
176
176
  @classmethod
177
- def from_response(cls, resp, ns) -> List["DataAlertItem"]:
177
+ def from_response(cls, resp, ns) -> list["DataAlertItem"]:
178
178
  all_alert_items = list()
179
179
  parsed_response = fromstring(resp)
180
180
  all_alert_xml = parsed_response.findall(".//t:dataAlert", namespaces=ns)
@@ -1,6 +1,6 @@
1
1
  import xml.etree.ElementTree as ET
2
2
 
3
- from typing import Optional, Union, List
3
+ from typing import Optional
4
4
  from tableauserverclient.models.property_decorators import property_is_enum, property_not_nullable
5
5
  from .interval_item import IntervalItem
6
6
 
@@ -50,11 +50,11 @@ class DataFreshnessPolicyItem:
50
50
  Week = "Week"
51
51
  Month = "Month"
52
52
 
53
- def __init__(self, frequency: str, time: str, timezone, interval_item: Optional[List[str]] = None):
53
+ def __init__(self, frequency: str, time: str, timezone, interval_item: Optional[list[str]] = None):
54
54
  self.frequency = frequency
55
55
  self.time = time
56
56
  self.timezone = timezone
57
- self.interval_item: Optional[List[str]] = interval_item
57
+ self.interval_item: Optional[list[str]] = interval_item
58
58
 
59
59
  def __repr__(self):
60
60
  return (
@@ -62,11 +62,11 @@ class DataFreshnessPolicyItem:
62
62
  ).format(**vars(self))
63
63
 
64
64
  @property
65
- def interval_item(self) -> Optional[List[str]]:
65
+ def interval_item(self) -> Optional[list[str]]:
66
66
  return self._interval_item
67
67
 
68
68
  @interval_item.setter
69
- def interval_item(self, value: List[str]):
69
+ def interval_item(self, value: list[str]):
70
70
  self._interval_item = value
71
71
 
72
72
  @property
@@ -186,7 +186,7 @@ def parse_week_intervals(interval_values):
186
186
 
187
187
 
188
188
  def parse_month_intervals(interval_values):
189
- error = "Invalid interval value for a monthly frequency: {}.".format(interval_values)
189
+ error = f"Invalid interval value for a monthly frequency: {interval_values}."
190
190
 
191
191
  # Month interval can have value either only ['LastDay'] or list of dates e.g. ["1", 20", "30"]
192
192
  # First check if the list only have LastDay value. When using LastDay, there shouldn't be
@@ -10,7 +10,7 @@ from .property_decorators import (
10
10
  )
11
11
 
12
12
 
13
- class DatabaseItem(object):
13
+ class DatabaseItem:
14
14
  class ContentPermissions:
15
15
  LockedToProject = "LockedToDatabase"
16
16
  ManagedByOwner = "ManagedByOwner"
@@ -45,7 +45,7 @@ class DatabaseItem(object):
45
45
  self._tables = None # Not implemented yet
46
46
 
47
47
  def __str__(self):
48
- return "<Database {0} '{1}'>".format(self._id, self.name)
48
+ return f"<Database {self._id} '{self.name}'>"
49
49
 
50
50
  def __repr__(self):
51
51
  return self.__str__() + " { " + ", ".join(" % s: % s" % item for item in vars(self).items()) + "}"
@@ -250,7 +250,7 @@ class DatabaseItem(object):
250
250
  self._tables = tables
251
251
 
252
252
  def _set_default_permissions(self, permissions, content_type):
253
- attr = "_default_{content}_permissions".format(content=content_type)
253
+ attr = f"_default_{content_type}_permissions"
254
254
  setattr(
255
255
  self,
256
256
  attr,
@@ -1,7 +1,7 @@
1
1
  import copy
2
2
  import datetime
3
3
  import xml.etree.ElementTree as ET
4
- from typing import Dict, List, Optional, Set, Tuple
4
+ from typing import Optional
5
5
 
6
6
  from defusedxml.ElementTree import fromstring
7
7
 
@@ -18,14 +18,14 @@ from tableauserverclient.models.revision_item import RevisionItem
18
18
  from tableauserverclient.models.tag_item import TagItem
19
19
 
20
20
 
21
- class DatasourceItem(object):
21
+ class DatasourceItem:
22
22
  class AskDataEnablement:
23
23
  Enabled = "Enabled"
24
24
  Disabled = "Disabled"
25
25
  SiteDefault = "SiteDefault"
26
26
 
27
27
  def __repr__(self):
28
- return "<Datasource {0} '{1}' ({2} parent={3} >".format(
28
+ return "<Datasource {} '{}' ({} parent={} >".format(
29
29
  self._id,
30
30
  self.name,
31
31
  self.description or "No Description",
@@ -44,7 +44,7 @@ class DatasourceItem(object):
44
44
  self._encrypt_extracts = None
45
45
  self._has_extracts = None
46
46
  self._id: Optional[str] = None
47
- self._initial_tags: Set = set()
47
+ self._initial_tags: set = set()
48
48
  self._project_name: Optional[str] = None
49
49
  self._revisions = None
50
50
  self._size: Optional[int] = None
@@ -55,7 +55,7 @@ class DatasourceItem(object):
55
55
  self.name = name
56
56
  self.owner_id: Optional[str] = None
57
57
  self.project_id = project_id
58
- self.tags: Set[str] = set()
58
+ self.tags: set[str] = set()
59
59
 
60
60
  self._permissions = None
61
61
  self._data_quality_warnings = None
@@ -72,14 +72,14 @@ class DatasourceItem(object):
72
72
  self._ask_data_enablement = value
73
73
 
74
74
  @property
75
- def connections(self) -> Optional[List[ConnectionItem]]:
75
+ def connections(self) -> Optional[list[ConnectionItem]]:
76
76
  if self._connections is None:
77
77
  error = "Datasource item must be populated with connections first."
78
78
  raise UnpopulatedPropertyError(error)
79
79
  return self._connections()
80
80
 
81
81
  @property
82
- def permissions(self) -> Optional[List[PermissionsRule]]:
82
+ def permissions(self) -> Optional[list[PermissionsRule]]:
83
83
  if self._permissions is None:
84
84
  error = "Project item must be populated with permissions first."
85
85
  raise UnpopulatedPropertyError(error)
@@ -177,7 +177,7 @@ class DatasourceItem(object):
177
177
  return self._webpage_url
178
178
 
179
179
  @property
180
- def revisions(self) -> List[RevisionItem]:
180
+ def revisions(self) -> list[RevisionItem]:
181
181
  if self._revisions is None:
182
182
  error = "Datasource item must be populated with revisions first."
183
183
  raise UnpopulatedPropertyError(error)
@@ -309,7 +309,7 @@ class DatasourceItem(object):
309
309
  self._size = int(size)
310
310
 
311
311
  @classmethod
312
- def from_response(cls, resp: str, ns: Dict) -> List["DatasourceItem"]:
312
+ def from_response(cls, resp: str, ns: dict) -> list["DatasourceItem"]:
313
313
  all_datasource_items = list()
314
314
  parsed_response = fromstring(resp)
315
315
  all_datasource_xml = parsed_response.findall(".//t:datasource", namespaces=ns)
@@ -326,7 +326,7 @@ class DatasourceItem(object):
326
326
  return datasource_item
327
327
 
328
328
  @staticmethod
329
- def _parse_element(datasource_xml: ET.Element, ns: Dict) -> Tuple:
329
+ def _parse_element(datasource_xml: ET.Element, ns: dict) -> tuple:
330
330
  id_ = datasource_xml.get("id", None)
331
331
  name = datasource_xml.get("name", None)
332
332
  datasource_type = datasource_xml.get("type", None)
@@ -3,7 +3,7 @@ from defusedxml.ElementTree import fromstring
3
3
  from tableauserverclient.datetime_helpers import parse_datetime
4
4
 
5
5
 
6
- class DQWItem(object):
6
+ class DQWItem:
7
7
  class WarningType:
8
8
  WARNING = "WARNING"
9
9
  DEPRECATED = "DEPRECATED"
@@ -1,28 +1,27 @@
1
1
  import logging
2
2
 
3
+ from typing import Union
3
4
  from defusedxml.ElementTree import fromstring
4
- from tableauserverclient.models.tableau_types import TableauItem
5
5
 
6
+ from tableauserverclient.models.tableau_types import TableauItem
6
7
  from tableauserverclient.models.datasource_item import DatasourceItem
7
8
  from tableauserverclient.models.flow_item import FlowItem
8
9
  from tableauserverclient.models.project_item import ProjectItem
9
10
  from tableauserverclient.models.metric_item import MetricItem
10
11
  from tableauserverclient.models.view_item import ViewItem
11
12
  from tableauserverclient.models.workbook_item import WorkbookItem
12
- from typing import Dict, List
13
13
 
14
14
  from tableauserverclient.helpers.logging import logger
15
- from typing import Dict, List, Union
16
15
 
17
- FavoriteType = Dict[
16
+ FavoriteType = dict[
18
17
  str,
19
- List[TableauItem],
18
+ list[TableauItem],
20
19
  ]
21
20
 
22
21
 
23
22
  class FavoriteItem:
24
23
  @classmethod
25
- def from_response(cls, xml: str, namespace: Dict) -> FavoriteType:
24
+ def from_response(cls, xml: Union[str, bytes], namespace: dict) -> FavoriteType:
26
25
  favorites: FavoriteType = {
27
26
  "datasources": [],
28
27
  "flows": [],
@@ -1,7 +1,7 @@
1
1
  from defusedxml.ElementTree import fromstring
2
2
 
3
3
 
4
- class FileuploadItem(object):
4
+ class FileuploadItem:
5
5
  def __init__(self):
6
6
  self._file_size = None
7
7
  self._upload_session_id = None
@@ -1,7 +1,7 @@
1
1
  import copy
2
2
  import datetime
3
3
  import xml.etree.ElementTree as ET
4
- from typing import List, Optional, Set
4
+ from typing import Optional
5
5
 
6
6
  from defusedxml.ElementTree import fromstring
7
7
 
@@ -14,9 +14,9 @@ from tableauserverclient.models.property_decorators import property_not_nullable
14
14
  from tableauserverclient.models.tag_item import TagItem
15
15
 
16
16
 
17
- class FlowItem(object):
17
+ class FlowItem:
18
18
  def __repr__(self):
19
- return "<Flow {0} '{1}' ({2}) Project={3} createdAt={4}".format(
19
+ return "<Flow {} '{}' ({}) Project={} createdAt={}".format(
20
20
  self._id, self.name, self.description, self.project_id, self.created_at
21
21
  )
22
22
 
@@ -24,13 +24,13 @@ class FlowItem(object):
24
24
  self._webpage_url: Optional[str] = None
25
25
  self._created_at: Optional[datetime.datetime] = None
26
26
  self._id: Optional[str] = None
27
- self._initial_tags: Set[str] = set()
27
+ self._initial_tags: set[str] = set()
28
28
  self._project_name: Optional[str] = None
29
29
  self._updated_at: Optional[datetime.datetime] = None
30
30
  self.name: Optional[str] = name
31
31
  self.owner_id: Optional[str] = None
32
32
  self.project_id: str = project_id
33
- self.tags: Set[str] = set()
33
+ self.tags: set[str] = set()
34
34
  self.description: Optional[str] = None
35
35
 
36
36
  self._connections: Optional[ConnectionItem] = None
@@ -170,7 +170,7 @@ class FlowItem(object):
170
170
  self.owner_id = owner_id
171
171
 
172
172
  @classmethod
173
- def from_response(cls, resp, ns) -> List["FlowItem"]:
173
+ def from_response(cls, resp, ns) -> list["FlowItem"]:
174
174
  all_flow_items = list()
175
175
  parsed_response = fromstring(resp)
176
176
  all_flow_xml = parsed_response.findall(".//t:flow", namespaces=ns)
@@ -1,13 +1,13 @@
1
1
  import itertools
2
2
  from datetime import datetime
3
- from typing import Dict, List, Optional, Type
3
+ from typing import Optional
4
4
 
5
5
  from defusedxml.ElementTree import fromstring
6
6
 
7
7
  from tableauserverclient.datetime_helpers import parse_datetime
8
8
 
9
9
 
10
- class FlowRunItem(object):
10
+ class FlowRunItem:
11
11
  def __init__(self) -> None:
12
12
  self._id: str = ""
13
13
  self._flow_id: Optional[str] = None
@@ -71,7 +71,7 @@ class FlowRunItem(object):
71
71
  self._background_job_id = background_job_id
72
72
 
73
73
  @classmethod
74
- def from_response(cls: Type["FlowRunItem"], resp: bytes, ns: Optional[Dict]) -> List["FlowRunItem"]:
74
+ def from_response(cls: type["FlowRunItem"], resp: bytes, ns: Optional[dict]) -> list["FlowRunItem"]:
75
75
  all_flowrun_items = list()
76
76
  parsed_response = fromstring(resp)
77
77
  all_flowrun_xml = itertools.chain(
@@ -1,4 +1,4 @@
1
- from typing import Callable, List, Optional, TYPE_CHECKING
1
+ from typing import Callable, Optional, TYPE_CHECKING
2
2
 
3
3
  from defusedxml.ElementTree import fromstring
4
4
 
@@ -11,7 +11,7 @@ if TYPE_CHECKING:
11
11
  from tableauserverclient.server import Pager
12
12
 
13
13
 
14
- class GroupItem(object):
14
+ class GroupItem:
15
15
  tag_name: str = "group"
16
16
 
17
17
  class LicenseMode:
@@ -27,7 +27,7 @@ class GroupItem(object):
27
27
  self.domain_name: Optional[str] = domain_name
28
28
 
29
29
  def __repr__(self):
30
- return "{}({!r})".format(self.__class__.__name__, self.__dict__)
30
+ return f"{self.__class__.__name__}({self.__dict__!r})"
31
31
 
32
32
  @property
33
33
  def domain_name(self) -> Optional[str]:
@@ -79,7 +79,7 @@ class GroupItem(object):
79
79
  self._users = users
80
80
 
81
81
  @classmethod
82
- def from_response(cls, resp, ns) -> List["GroupItem"]:
82
+ def from_response(cls, resp, ns) -> list["GroupItem"]:
83
83
  all_group_items = list()
84
84
  parsed_response = fromstring(resp)
85
85
  all_group_xml = parsed_response.findall(".//t:group", namespaces=ns)