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
@@ -1,4 +1,5 @@
1
1
  import sys
2
+ from typing import Optional
2
3
 
3
4
  from typing_extensions import Self
4
5
 
@@ -9,12 +10,12 @@ import logging
9
10
  from tableauserverclient.helpers.logging import logger
10
11
 
11
12
 
12
- class RequestOptionsBase(object):
13
+ class RequestOptionsBase:
13
14
  # This method is used if server api version is below 3.7 (2020.1)
14
15
  def apply_query_params(self, url):
15
16
  try:
16
17
  params = self.get_query_params()
17
- params_list = ["{}={}".format(k, v) for (k, v) in params.items()]
18
+ params_list = [f"{k}={v}" for (k, v) in params.items()]
18
19
 
19
20
  logger.debug("Applying options to request: <%s(%s)>", self.__class__.__name__, ",".join(params_list))
20
21
 
@@ -22,15 +23,52 @@ class RequestOptionsBase(object):
22
23
  url, existing_params = url.split("?")
23
24
  params_list.append(existing_params)
24
25
 
25
- return "{0}?{1}".format(url, "&".join(params_list))
26
+ return "{}?{}".format(url, "&".join(params_list))
26
27
  except NotImplementedError:
27
28
  raise
28
29
 
29
- def get_query_params(self):
30
- raise NotImplementedError()
30
+
31
+ # If it wasn't a breaking change, I'd rename it to QueryOptions
32
+ """
33
+ This class manages options can be used when querying content on the server
34
+ """
31
35
 
32
36
 
33
37
  class RequestOptions(RequestOptionsBase):
38
+ def __init__(self, pagenumber=1, pagesize=None):
39
+ self.pagenumber = pagenumber
40
+ self.pagesize = pagesize or config.PAGE_SIZE
41
+ self.sort = set()
42
+ self.filter = set()
43
+ # This is private until we expand all of our parsers to handle the extra fields
44
+ self._all_fields = False
45
+
46
+ def get_query_params(self) -> dict:
47
+ params = {}
48
+ if self.sort and len(self.sort) > 0:
49
+ sort_options = (str(sort_item) for sort_item in self.sort)
50
+ ordered_sort_options = sorted(sort_options)
51
+ params["sort"] = ",".join(ordered_sort_options)
52
+ if len(self.filter) > 0:
53
+ filter_options = (str(filter_item) for filter_item in self.filter)
54
+ ordered_filter_options = sorted(filter_options)
55
+ params["filter"] = ",".join(ordered_filter_options)
56
+ if self._all_fields:
57
+ params["fields"] = "_all_"
58
+ if self.pagenumber:
59
+ params["pageNumber"] = self.pagenumber
60
+ if self.pagesize:
61
+ params["pageSize"] = self.pagesize
62
+ return params
63
+
64
+ def page_size(self, page_size):
65
+ self.pagesize = page_size
66
+ return self
67
+
68
+ def page_number(self, page_number):
69
+ self.pagenumber = page_number
70
+ return self
71
+
34
72
  class Operator:
35
73
  Equals = "eq"
36
74
  GreaterThan = "gt"
@@ -41,6 +79,7 @@ class RequestOptions(RequestOptionsBase):
41
79
  Has = "has"
42
80
  CaseInsensitiveEquals = "cieq"
43
81
 
82
+ # These are fields in the REST API
44
83
  class Field:
45
84
  Args = "args"
46
85
  AuthenticationType = "authenticationType"
@@ -117,60 +156,53 @@ class RequestOptions(RequestOptionsBase):
117
156
  Desc = "desc"
118
157
  Asc = "asc"
119
158
 
120
- def __init__(self, pagenumber=1, pagesize=None):
121
- self.pagenumber = pagenumber
122
- self.pagesize = pagesize or config.PAGE_SIZE
123
- self.sort = set()
124
- self.filter = set()
125
-
126
- # This is private until we expand all of our parsers to handle the extra fields
127
- self._all_fields = False
128
159
 
129
- def page_size(self, page_size):
130
- self.pagesize = page_size
131
- return self
132
-
133
- def page_number(self, page_number):
134
- self.pagenumber = page_number
135
- return self
160
+ """
161
+ These options can be used by methods that are fetching data exported from a specific content item
162
+ """
136
163
 
137
- def get_query_params(self):
138
- params = {}
139
- if self.pagenumber:
140
- params["pageNumber"] = self.pagenumber
141
- if self.pagesize:
142
- params["pageSize"] = self.pagesize
143
- if len(self.sort) > 0:
144
- sort_options = (str(sort_item) for sort_item in self.sort)
145
- ordered_sort_options = sorted(sort_options)
146
- params["sort"] = ",".join(ordered_sort_options)
147
- if len(self.filter) > 0:
148
- filter_options = (str(filter_item) for filter_item in self.filter)
149
- ordered_filter_options = sorted(filter_options)
150
- params["filter"] = ",".join(ordered_filter_options)
151
- if self._all_fields:
152
- params["fields"] = "_all_"
153
- return params
154
164
 
165
+ class _DataExportOptions(RequestOptionsBase):
166
+ def __init__(self, maxage: int = -1):
167
+ super().__init__()
168
+ self.view_filters: list[tuple[str, str]] = []
169
+ self.view_parameters: list[tuple[str, str]] = []
170
+ self.max_age: Optional[int] = maxage
171
+ """
172
+ This setting will affect the contents of the workbook as they are exported.
173
+ Valid language values are tableau-supported languages like de, es, en
174
+ If no locale is specified, the default locale for that language will be used
175
+ """
176
+ self.language: Optional[str] = None
155
177
 
156
- class _FilterOptionsBase(RequestOptionsBase):
157
- """Provide a basic implementation of adding view filters to the url"""
178
+ @property
179
+ def max_age(self) -> int:
180
+ return self._max_age
158
181
 
159
- def __init__(self):
160
- self.view_filters = []
161
- self.view_parameters = []
182
+ @max_age.setter
183
+ @property_is_int(range=(0, 240), allowed=[-1])
184
+ def max_age(self, value):
185
+ self._max_age = value
162
186
 
163
187
  def get_query_params(self):
164
- raise NotImplementedError()
188
+ params = {}
189
+ if self.max_age != -1:
190
+ params["maxAge"] = self.max_age
191
+ if self.language:
192
+ params["language"] = self.language
193
+
194
+ self._append_view_filters(params)
195
+ return params
165
196
 
166
197
  def vf(self, name: str, value: str) -> Self:
167
- """Apply a filter to the view for a filter that is a normal column
168
- within the view."""
198
+ """Apply a filter based on a column within the view.
199
+ Note that when filtering on a boolean type field, the only valid values are 'true' and 'false'"""
169
200
  self.view_filters.append((name, value))
170
201
  return self
171
202
 
172
203
  def parameter(self, name: str, value: str) -> Self:
173
- """Apply a filter based on a parameter within the workbook."""
204
+ """Apply a filter based on a parameter within the workbook.
205
+ Note that when filtering on a boolean type field, the only valid values are 'true' and 'false'"""
174
206
  self.view_parameters.append((name, value))
175
207
  return self
176
208
 
@@ -181,82 +213,73 @@ class _FilterOptionsBase(RequestOptionsBase):
181
213
  params[name] = value
182
214
 
183
215
 
184
- class CSVRequestOptions(_FilterOptionsBase):
185
- def __init__(self, maxage=-1):
186
- super(CSVRequestOptions, self).__init__()
187
- self.max_age = maxage
216
+ class _ImagePDFCommonExportOptions(_DataExportOptions):
217
+ def __init__(self, maxage=-1, viz_height=None, viz_width=None):
218
+ super().__init__(maxage=maxage)
219
+ self.viz_height = viz_height
220
+ self.viz_width = viz_width
188
221
 
189
222
  @property
190
- def max_age(self):
191
- return self._max_age
192
-
193
- @max_age.setter
194
- @property_is_int(range=(0, 240), allowed=[-1])
195
- def max_age(self, value):
196
- self._max_age = value
223
+ def viz_height(self):
224
+ return self._viz_height
197
225
 
198
- def get_query_params(self):
199
- params = {}
200
- if self.max_age != -1:
201
- params["maxAge"] = self.max_age
226
+ @viz_height.setter
227
+ @property_is_int(range=(0, sys.maxsize), allowed=(None,))
228
+ def viz_height(self, value):
229
+ self._viz_height = value
202
230
 
203
- self._append_view_filters(params)
204
- return params
231
+ @property
232
+ def viz_width(self):
233
+ return self._viz_width
205
234
 
235
+ @viz_width.setter
236
+ @property_is_int(range=(0, sys.maxsize), allowed=(None,))
237
+ def viz_width(self, value):
238
+ self._viz_width = value
206
239
 
207
- class ExcelRequestOptions(_FilterOptionsBase):
208
- def __init__(self, maxage: int = -1) -> None:
209
- super().__init__()
210
- self.max_age = maxage
240
+ def get_query_params(self) -> dict:
241
+ params = super().get_query_params()
211
242
 
212
- @property
213
- def max_age(self) -> int:
214
- return self._max_age
243
+ # XOR. Either both are None or both are not None.
244
+ if (self.viz_height is None) ^ (self.viz_width is None):
245
+ raise ValueError("viz_height and viz_width must be specified together")
215
246
 
216
- @max_age.setter
217
- @property_is_int(range=(0, 240), allowed=[-1])
218
- def max_age(self, value: int) -> None:
219
- self._max_age = value
247
+ if self.viz_height is not None:
248
+ params["vizHeight"] = self.viz_height
220
249
 
221
- def get_query_params(self):
222
- params = {}
223
- if self.max_age != -1:
224
- params["maxAge"] = self.max_age
250
+ if self.viz_width is not None:
251
+ params["vizWidth"] = self.viz_width
225
252
 
226
- self._append_view_filters(params)
227
253
  return params
228
254
 
229
255
 
230
- class ImageRequestOptions(_FilterOptionsBase):
256
+ class CSVRequestOptions(_DataExportOptions):
257
+ extension = "csv"
258
+
259
+
260
+ class ExcelRequestOptions(_DataExportOptions):
261
+ extension = "xlsx"
262
+
263
+
264
+ class ImageRequestOptions(_ImagePDFCommonExportOptions):
265
+ extension = "png"
266
+
231
267
  # if 'high' isn't specified, the REST API endpoint returns an image with standard resolution
232
268
  class Resolution:
233
269
  High = "high"
234
270
 
235
- def __init__(self, imageresolution=None, maxage=-1):
236
- super(ImageRequestOptions, self).__init__()
271
+ def __init__(self, imageresolution=None, maxage=-1, viz_height=None, viz_width=None):
272
+ super().__init__(maxage=maxage, viz_height=viz_height, viz_width=viz_width)
237
273
  self.image_resolution = imageresolution
238
- self.max_age = maxage
239
-
240
- @property
241
- def max_age(self):
242
- return self._max_age
243
-
244
- @max_age.setter
245
- @property_is_int(range=(0, 240), allowed=[-1])
246
- def max_age(self, value):
247
- self._max_age = value
248
274
 
249
275
  def get_query_params(self):
250
- params = {}
276
+ params = super().get_query_params()
251
277
  if self.image_resolution:
252
278
  params["resolution"] = self.image_resolution
253
- if self.max_age != -1:
254
- params["maxAge"] = self.max_age
255
- self._append_view_filters(params)
256
279
  return params
257
280
 
258
281
 
259
- class PDFRequestOptions(_FilterOptionsBase):
282
+ class PDFRequestOptions(_ImagePDFCommonExportOptions):
260
283
  class PageType:
261
284
  A3 = "a3"
262
285
  A4 = "a4"
@@ -278,61 +301,16 @@ class PDFRequestOptions(_FilterOptionsBase):
278
301
  Landscape = "landscape"
279
302
 
280
303
  def __init__(self, page_type=None, orientation=None, maxage=-1, viz_height=None, viz_width=None):
281
- super(PDFRequestOptions, self).__init__()
304
+ super().__init__(maxage=maxage, viz_height=viz_height, viz_width=viz_width)
282
305
  self.page_type = page_type
283
306
  self.orientation = orientation
284
- self.max_age = maxage
285
- self.viz_height = viz_height
286
- self.viz_width = viz_width
287
-
288
- @property
289
- def max_age(self):
290
- return self._max_age
291
-
292
- @max_age.setter
293
- @property_is_int(range=(0, 240), allowed=[-1])
294
- def max_age(self, value):
295
- self._max_age = value
296
-
297
- @property
298
- def viz_height(self):
299
- return self._viz_height
300
-
301
- @viz_height.setter
302
- @property_is_int(range=(0, sys.maxsize), allowed=(None,))
303
- def viz_height(self, value):
304
- self._viz_height = value
305
-
306
- @property
307
- def viz_width(self):
308
- return self._viz_width
309
-
310
- @viz_width.setter
311
- @property_is_int(range=(0, sys.maxsize), allowed=(None,))
312
- def viz_width(self, value):
313
- self._viz_width = value
314
307
 
315
- def get_query_params(self):
316
- params = {}
308
+ def get_query_params(self) -> dict:
309
+ params = super().get_query_params()
317
310
  if self.page_type:
318
311
  params["type"] = self.page_type
319
312
 
320
313
  if self.orientation:
321
314
  params["orientation"] = self.orientation
322
315
 
323
- if self.max_age != -1:
324
- params["maxAge"] = self.max_age
325
-
326
- # XOR. Either both are None or both are not None.
327
- if (self.viz_height is None) ^ (self.viz_width is None):
328
- raise ValueError("viz_height and viz_width must be specified together")
329
-
330
- if self.viz_height is not None:
331
- params["vizHeight"] = self.viz_height
332
-
333
- if self.viz_width is not None:
334
- params["vizWidth"] = self.viz_width
335
-
336
- self._append_view_filters(params)
337
-
338
316
  return params
@@ -58,8 +58,64 @@ minimum_supported_server_version = "2.3"
58
58
  default_server_version = "2.4" # first version that dropped the legacy auth endpoint
59
59
 
60
60
 
61
- class Server(object):
61
+ class Server:
62
+ """
63
+ In the Tableau REST API, the server (https://MY-SERVER/) is the base or core
64
+ of the URI that makes up the various endpoints or methods for accessing
65
+ resources on the server (views, workbooks, sites, users, data sources, etc.)
66
+ The TSC library provides a Server class that represents the server. You
67
+ create a server instance to sign in to the server and to call the various
68
+ methods for accessing resources.
69
+
70
+ The Server class contains the attributes that represent the server on
71
+ Tableau Server. After you create an instance of the Server class, you can
72
+ sign in to the server and call methods to access all of the resources on the
73
+ server.
74
+
75
+ Parameters
76
+ ----------
77
+ server_address : str
78
+ Specifies the address of the Tableau Server or Tableau Cloud (for
79
+ example, https://MY-SERVER/).
80
+
81
+ use_server_version : bool
82
+ Specifies the version of the REST API to use (for example, '2.5'). When
83
+ you use the TSC library to call methods that access Tableau Server, the
84
+ version is passed to the endpoint as part of the URI
85
+ (https://MY-SERVER/api/2.5/). Each release of Tableau Server supports
86
+ specific versions of the REST API. New versions of the REST API are
87
+ released with Tableau Server. By default, the value of version is set to
88
+ '2.3', which corresponds to Tableau Server 10.0. You can view or set
89
+ this value. You might need to set this to a different value, for
90
+ example, if you want to access features that are supported by the server
91
+ and a later version of the REST API. For more information, see REST API
92
+ Versions.
93
+
94
+ Examples
95
+ --------
96
+ >>> import tableauserverclient as TSC
97
+
98
+ >>> # create a instance of server
99
+ >>> server = TSC.Server('https://MY-SERVER')
100
+
101
+ >>> # sign in, etc.
102
+
103
+ >>> # change the REST API version to match the server
104
+ >>> server.use_server_version()
105
+
106
+ >>> # or change the REST API version to match a specific version
107
+ >>> # for example, 2.8
108
+ >>> # server.version = '2.8'
109
+
110
+ """
111
+
62
112
  class PublishMode:
113
+ """
114
+ Enumerates the options that specify what happens when you publish a
115
+ workbook or data source. The options are Overwrite, Append, or
116
+ CreateNew.
117
+ """
118
+
63
119
  Append = "Append"
64
120
  Overwrite = "Overwrite"
65
121
  CreateNew = "CreateNew"
@@ -130,7 +186,7 @@ class Server(object):
130
186
  raise ValueError("Server connection settings not valid", req_ex)
131
187
 
132
188
  def __repr__(self):
133
- return "<TableauServerClient [Connection: {}, {}]>".format(self.baseurl, self.server_info.serverInfo)
189
+ return f"<TableauServerClient [Connection: {self.baseurl}, {self.server_info.serverInfo}]>"
134
190
 
135
191
  def add_http_options(self, options_dict: dict):
136
192
  try:
@@ -142,7 +198,7 @@ class Server(object):
142
198
  # expected errors on invalid input:
143
199
  # 'set' object has no attribute 'keys', 'list' object has no attribute 'keys'
144
200
  # TypeError: cannot convert dictionary update sequence element #0 to a sequence (input is a tuple)
145
- raise ValueError("Invalid http options given: {}".format(options_dict))
201
+ raise ValueError(f"Invalid http options given: {options_dict}")
146
202
 
147
203
  def clear_http_options(self):
148
204
  self._http_options = dict()
@@ -176,15 +232,15 @@ class Server(object):
176
232
  old_version = self.version
177
233
  version = self.server_info.get().rest_api_version
178
234
  except ServerInfoEndpointNotFoundError as e:
179
- logger.info("Could not get version info from server: {}{}".format(e.__class__, e))
235
+ logger.info(f"Could not get version info from server: {e.__class__}{e}")
180
236
  version = self._get_legacy_version()
181
237
  except EndpointUnavailableError as e:
182
- logger.info("Could not get version info from server: {}{}".format(e.__class__, e))
238
+ logger.info(f"Could not get version info from server: {e.__class__}{e}")
183
239
  version = self._get_legacy_version()
184
240
  except Exception as e:
185
- logger.info("Could not get version info from server: {}{}".format(e.__class__, e))
241
+ logger.info(f"Could not get version info from server: {e.__class__}{e}")
186
242
  version = None
187
- logger.info("versions: {}, {}".format(version, old_version))
243
+ logger.info(f"versions: {version}, {old_version}")
188
244
  return version or old_version
189
245
 
190
246
  def use_server_version(self):
@@ -201,12 +257,12 @@ class Server(object):
201
257
 
202
258
  def assert_at_least_version(self, comparison: str, reason: str):
203
259
  if not self.check_at_least_version(comparison):
204
- error = "{} is not available in API version {}. Requires {}".format(reason, self.version, comparison)
260
+ error = f"{reason} is not available in API version {self.version}. Requires {comparison}"
205
261
  raise EndpointUnavailableError(error)
206
262
 
207
263
  @property
208
264
  def baseurl(self):
209
- return "{0}/api/{1}".format(self._server_address, str(self.version))
265
+ return f"{self._server_address}/api/{str(self.version)}"
210
266
 
211
267
  @property
212
268
  def namespace(self):
@@ -1,7 +1,7 @@
1
- class Sort(object):
1
+ class Sort:
2
2
  def __init__(self, field, direction):
3
3
  self.field = field
4
4
  self.direction = direction
5
5
 
6
6
  def __str__(self):
7
- return "{0}:{1}".format(self.field, self.direction)
7
+ return f"{self.field}:{self.direction}"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: tableauserverclient
3
- Version: 0.33
3
+ Version: 0.34
4
4
  Summary: A Python module for working with the Tableau Server REST API.
5
5
  Author-email: Tableau <github@tableau.com>
6
6
  License: The MIT License (MIT)
@@ -28,22 +28,22 @@ License: The MIT License (MIT)
28
28
  Project-URL: repository, https://github.com/tableau/server-client-python
29
29
  Classifier: Programming Language :: Python
30
30
  Classifier: Programming Language :: Python :: 3
31
- Classifier: Programming Language :: Python :: 3.8
32
31
  Classifier: Programming Language :: Python :: 3.9
33
32
  Classifier: Programming Language :: Python :: 3.10
34
33
  Classifier: Programming Language :: Python :: 3.11
35
34
  Classifier: Programming Language :: Python :: 3.12
36
- Requires-Python: >=3.7
35
+ Classifier: Programming Language :: Python :: 3.13
36
+ Requires-Python: >=3.9
37
37
  Description-Content-Type: text/markdown
38
38
  License-File: LICENSE
39
39
  License-File: LICENSE.versioneer
40
40
  Requires-Dist: defusedxml>=0.7.1
41
41
  Requires-Dist: packaging>=23.1
42
- Requires-Dist: requests>=2.31
43
- Requires-Dist: urllib3==2.2.2
42
+ Requires-Dist: requests>=2.32
43
+ Requires-Dist: urllib3<3,>=2.2.2
44
44
  Requires-Dist: typing-extensions>=4.0.1
45
45
  Provides-Extra: test
46
- Requires-Dist: black==23.7; extra == "test"
46
+ Requires-Dist: black==24.8; extra == "test"
47
47
  Requires-Dist: build; extra == "test"
48
48
  Requires-Dist: mypy==1.4; extra == "test"
49
49
  Requires-Dist: pytest>=7.0; extra == "test"
@@ -0,0 +1,106 @@
1
+ tableauserverclient/__init__.py,sha256=fC2e9i-0apUVZ5-KMv5yqCwNHpHLKMZzH9iKr3MhFQk,2733
2
+ tableauserverclient/_version.py,sha256=avYqaqs6dEYkBErJoo8H4QwrWV-YA20Dq1QvilajM4c,496
3
+ tableauserverclient/config.py,sha256=LcWVmZjkYMh1cKCKZm3VZItgKOoSLz1ai4PnVgbAtDA,713
4
+ tableauserverclient/datetime_helpers.py,sha256=_-gWz5I2_KHT5AzW_boD8meH6loTTKdK-_62h1MA6ko,884
5
+ tableauserverclient/exponential_backoff.py,sha256=HtAfbbVnYtiOe2_ZzKqZmsml40EDZBaC3bttif5qeG8,1474
6
+ tableauserverclient/filesys_helpers.py,sha256=hosTm9fpc9B9_VCDcAuyHA0A-f-MWs9_2utyRweuZ5I,1667
7
+ tableauserverclient/namespace.py,sha256=Zh6QtxNmqPkjRMsefHHX-ycS4r-egnrJ4-hdHvldBHw,963
8
+ tableauserverclient/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
+ tableauserverclient/helpers/__init__.py,sha256=llpqF9zV5dsP5hQt8dyop33Op5OzGmxW0BZibaSlCcM,23
10
+ tableauserverclient/helpers/headers.py,sha256=Pg-ZWSgV2Yp813BV1Tzo8F2Hn4P01zscla2RRM4yqNk,411
11
+ tableauserverclient/helpers/logging.py,sha256=5q_oR3wERHVXFXY6XDnLYML5-HdAPJTmqhH9IZg4VfY,113
12
+ tableauserverclient/helpers/strings.py,sha256=HRTP31HIdD3gFxDDHuBsmOl_8cLdh8fa3xLALgYsUAQ,1563
13
+ tableauserverclient/models/__init__.py,sha256=bU4eaOQ4I9h_JYn7IbhCZhHbMVvxdSUhMJeHg80apYA,4051
14
+ tableauserverclient/models/column_item.py,sha256=yUFzXNcnUPVo2imrhEBS4fMVAR5j2ZzksOk5t9XYW5s,1964
15
+ tableauserverclient/models/connection_credentials.py,sha256=MBsXL5bT0iBfrKUequ-TdfS2wxn9VYCeWEMgE5kJ_WM,1551
16
+ tableauserverclient/models/connection_item.py,sha256=LkepJbkuNmOYrPVPUSv7y4NTTUpIY9I0RTy2IjSeRS4,4799
17
+ tableauserverclient/models/custom_view_item.py,sha256=sbXVMCqWu9PlP5jFmYMFshaMkoU93GArx4KcoHOOPiM,6490
18
+ tableauserverclient/models/data_acceleration_report_item.py,sha256=HFZROetfOWh-hMS48xBEHqYOViINHZR-EpcrP45_8AI,3386
19
+ tableauserverclient/models/data_alert_item.py,sha256=VZtRR-kqojq-mkrTgvay4WkPawj3-4jbSc0wBijmJhk,6444
20
+ tableauserverclient/models/data_freshness_policy_item.py,sha256=UdaEmwVL_q364Do_2dOnkCSX-oKnvjKfsYzGSaJIQFs,7618
21
+ tableauserverclient/models/database_item.py,sha256=lWxmmMpPeVxzizVAsVkc6Ps2I-j-0KJAJZto8qShrYU,8223
22
+ tableauserverclient/models/datasource_item.py,sha256=PVXcopBZFunLc3SAtti0HQd5xJ93ANc8dZYJihvtyzA,12371
23
+ tableauserverclient/models/dqw_item.py,sha256=87oTc7icrQst_DSaTqoVR965YEckg5dk6osa51BrCAk,3710
24
+ tableauserverclient/models/exceptions.py,sha256=pQu5DS4jNMT9A0wEBWv2vANAQU1vgNpFatVr8sGE4zk,105
25
+ tableauserverclient/models/favorites_item.py,sha256=JxHfy38xdRYol2KM_8_A7Ng59cZunkhTNcpxO670k08,3294
26
+ tableauserverclient/models/fileupload_item.py,sha256=N5M0jtlFj_PFh3jlp2AbcYOwCwdnBCk_L64xe3Z4ves,742
27
+ tableauserverclient/models/flow_item.py,sha256=pKEx4CNZYFgK2lT2TcQjrGBGqv0kZh-0xEWL7EfxRPQ,7452
28
+ tableauserverclient/models/flow_run_item.py,sha256=nf_b6KRwNevwZRsPoMh8dLzdONUMWY2wipWEMdY9SN4,3113
29
+ tableauserverclient/models/group_item.py,sha256=MU3lPkPbRlzEFElPiU30jnnMb6CrIdTh4ttlx4Qh5zc,3597
30
+ tableauserverclient/models/groupset_item.py,sha256=gxxyzviE5B8zr2sKJteIDKtYTPYKsGd-qMcrjEY2uVU,1885
31
+ tableauserverclient/models/interval_item.py,sha256=_ZHQtzQWxwdd_sScziqhrK54k7W_ZgrMfP2PhlIhTRQ,9101
32
+ tableauserverclient/models/job_item.py,sha256=4jKpekVJoI4rJyNjnaPMPag_6-MLzogEtbPPrp10598,9231
33
+ tableauserverclient/models/linked_tasks_item.py,sha256=TYkNvmJfKlZ30OST8w9GUobboFAH5ftFKjXdWWAtR24,3806
34
+ tableauserverclient/models/metric_item.py,sha256=D3atzbr3jtQUsVsqYHfz-v3yRP3qruRN5jRsv_-yRQ0,5378
35
+ tableauserverclient/models/pagination_item.py,sha256=55Ap_9pJxq8plWQO1Js3Jp6KFidN3TQsL5LM2-yZGDo,1424
36
+ tableauserverclient/models/permissions_item.py,sha256=CWf1Q4x7U4QQWQ1VUWgDzaE7mhriHblG1MJAc6EKJHM,6149
37
+ tableauserverclient/models/project_item.py,sha256=B2P3dk8VfxPWfPFOVdlkn_Y5UeqZ5dw75tAKm-k2v8M,7352
38
+ tableauserverclient/models/property_decorators.py,sha256=v2cTqiW5iZXoOyu6RYg3X6Ly--8sozjWOcKCTLi99Nc,4645
39
+ tableauserverclient/models/reference_item.py,sha256=R4Tr7qfVdnGcq_ac4hr0yhAjBOkqFZEW-4NGMUYaf9w,733
40
+ tableauserverclient/models/revision_item.py,sha256=5ghmnwhUcCOWwZdApzgV_uM3sqdoG_gtsJwUQwfKITo,2773
41
+ tableauserverclient/models/schedule_item.py,sha256=40Py-mpwK3GDZbfAuD6UjDz52NyVce5i8XjuneTarp4,11332
42
+ tableauserverclient/models/server_info_item.py,sha256=55wTG_31o-WwqgBrbwpgMpq_by10iM6BXpmdAZ3TO90,2631
43
+ tableauserverclient/models/site_item.py,sha256=Y0uWYfTzk4Utfl44V1_v0wH4VJmWg4Wq5o1EPTWVs8U,44999
44
+ tableauserverclient/models/subscription_item.py,sha256=ujaQQIo_ln3pnm0Th2IdcGCp_cl6WxvEMPgeZbwZtFc,4724
45
+ tableauserverclient/models/table_item.py,sha256=C_oseSV4PnkVkzIt8V_NkiT138vLmrGxzsr3Rn37png,4575
46
+ tableauserverclient/models/tableau_auth.py,sha256=atmXdAsA5LrrLHEzrHJQPLYETC1iKyxFqPSwIk-vacI,8218
47
+ tableauserverclient/models/tableau_types.py,sha256=ybXO_O7ni-WjKUJ5zVEoEgEnatsDtfXTeT0rpiq7Jxs,1230
48
+ tableauserverclient/models/tag_item.py,sha256=K2EVEy1EDdr0yLr4wBvGr-p9gIAFVsOCv80b-AFPFLk,588
49
+ tableauserverclient/models/target.py,sha256=dVc1SHwo9ZASR8250MhAPODXX_G5UqA4BnK8hykRE6E,263
50
+ tableauserverclient/models/task_item.py,sha256=I-2up8F2g5XA53Py24uDdtZ1JYu6wv9f3VwQqqkYNi8,3753
51
+ tableauserverclient/models/user_item.py,sha256=otfavMznvkqUwxRlh1wW0Y_eTw3gaVNJKlWeecKy5j0,16494
52
+ tableauserverclient/models/view_item.py,sha256=HoqVzuiVOSj2w_n7VjHIpPevYQt58ZZoz13cTY7ojtY,8110
53
+ tableauserverclient/models/virtual_connection_item.py,sha256=TvX7MId7WSg4IZE41XAMl1l3Ibu8kTUR1xr26Cqtyeo,3357
54
+ tableauserverclient/models/webhook_item.py,sha256=i2Flue9TEv89xs5SogmkG3jjDmtYYXhbW20kaV07xaY,2601
55
+ tableauserverclient/models/workbook_item.py,sha256=Jl0ofGP5lO7W0sh-T-bwGdxZ_rBILZSc3c3Qs_LP68M,16765
56
+ tableauserverclient/server/__init__.py,sha256=Ahk3Zh1F2e-rNPtlC7k51Lp8R_2q2obIuolln7bllTM,1890
57
+ tableauserverclient/server/exceptions.py,sha256=l-O4lcoEeXJC7fLWUanIcZM_Mf8m54uK3NQuKNj3RCg,183
58
+ tableauserverclient/server/filter.py,sha256=Z7O6A175bBSmcponLs0Enh5R5Gp2puVRGfOMk-V395w,1096
59
+ tableauserverclient/server/pager.py,sha256=KsQAtBclJfGSS16jFvhGTeQaK-Dto2sxjZreaQ2PIeA,2682
60
+ tableauserverclient/server/query.py,sha256=dxl0dOBd_Rx8BIS0ocMd-RhO5yb1KXnu2OacrQzQGPY,9461
61
+ tableauserverclient/server/request_factory.py,sha256=hS3StOUzi-C7WF2slL7q7HQ4LKGO3EeMryWfiUK6pnI,71531
62
+ tableauserverclient/server/request_options.py,sha256=VTBl4rVo0lmD-DT47qtzxSxtUrSFYwXJCi6H0sSfp2w,10086
63
+ tableauserverclient/server/server.py,sha256=HuClS7_UHkvighWxVHZKF9LdVO-T0dJZ7LHtoYobHv4,10974
64
+ tableauserverclient/server/sort.py,sha256=-vPtU-ZczVqlkQEMBb4DCXDQ1b2KQ2PGt6dTVIP7i4A,188
65
+ tableauserverclient/server/endpoint/__init__.py,sha256=MpttkNENWAiXS2QigwZMfWG6PnsB05QSFK4-OIR3CaQ,3101
66
+ tableauserverclient/server/endpoint/auth_endpoint.py,sha256=FgOhry6cv1FrlFP7s4iaFTsbCCtPeRqdhiXHxxuBwmg,6927
67
+ tableauserverclient/server/endpoint/custom_views_endpoint.py,sha256=XBInsWEqsIVvfyUHb0x3P7WmWCvLdIfgP-uh8wSuOPc,8906
68
+ tableauserverclient/server/endpoint/data_acceleration_report_endpoint.py,sha256=he-MVqCvAQo8--icEKFoIV2KUP6Z1s_PJ2uZ8Xpj2f8,1130
69
+ tableauserverclient/server/endpoint/data_alert_endpoint.py,sha256=ZNotgG3hBpR7fo8eDTXx_gSppF2n25GQ3udwF3MKFLk,5203
70
+ tableauserverclient/server/endpoint/databases_endpoint.py,sha256=3kl7YCCJB_DY88QiJxKvtarDV7kPApGYtIcr7d7l8k0,5705
71
+ tableauserverclient/server/endpoint/datasources_endpoint.py,sha256=IeNsTfrYCpW9UXz72H7M2R0DnI2Dzn47Z8GWBoF35r4,22676
72
+ tableauserverclient/server/endpoint/default_permissions_endpoint.py,sha256=bZlhDqu6jFyC4vbrdC3Nn1cWRJWRz0mhxco9hRUouJA,4327
73
+ tableauserverclient/server/endpoint/dqw_endpoint.py,sha256=hN2UsyM3hrUsIK9CudSBB-WXNa0TeUU7Zjeol0njIXI,2155
74
+ tableauserverclient/server/endpoint/endpoint.py,sha256=pYr-l3GLK8Fvh46U_VdaJLLerd2GBJXJk_x94RQ-ZeE,14113
75
+ tableauserverclient/server/endpoint/exceptions.py,sha256=4fN-kI9Hg3QaSOAJ1xLN56sCjTH9d470jWkYurZvTrM,2861
76
+ tableauserverclient/server/endpoint/favorites_endpoint.py,sha256=ZMui0KQCSGRBlUrem519Y5_gBpngN7wtDWo_EvEUMEk,6340
77
+ tableauserverclient/server/endpoint/fileuploads_endpoint.py,sha256=OnjAoHJyMsOnCVauAyOnKEdUqw9elpQ5O5cBnM0T1bQ,2427
78
+ tableauserverclient/server/endpoint/flow_runs_endpoint.py,sha256=HIVuTi4pXIqog16K_3Zzu1LC96TR_pZlAjxRKoJrJ_g,4957
79
+ tableauserverclient/server/endpoint/flow_task_endpoint.py,sha256=4D7tEYow7lqkCuazXUrUyIH_y_PQMTehmeIi-zSIMXo,1078
80
+ tableauserverclient/server/endpoint/flows_endpoint.py,sha256=spDO5AjgfgEe8QmrhnxuEWhBIzbgzzyim3TjDB33sdA,14087
81
+ tableauserverclient/server/endpoint/groups_endpoint.py,sha256=fOBkKoizvUo556rdtL-aWGKWUoR4DcNQuFfrPrmzm_I,9004
82
+ tableauserverclient/server/endpoint/groupsets_endpoint.py,sha256=-nsl2LCixvMhho3KKSWDpHLfNahTBue76L3i8RjTqyc,5585
83
+ tableauserverclient/server/endpoint/jobs_endpoint.py,sha256=ZtzpQ7uJT1uu-gjkU8pX3h9QWyZAnAR0hRlbDkuq4QA,5644
84
+ tableauserverclient/server/endpoint/linked_tasks_endpoint.py,sha256=tMZqVPWPZvYawaXLJGVV9scmWPu1rdCxz-eWZv1WbPk,2262
85
+ tableauserverclient/server/endpoint/metadata_endpoint.py,sha256=sg0Yehj2f0wlrJMkVjzNdNxNEhSeNbZIkio3eQamOVk,5228
86
+ tableauserverclient/server/endpoint/metrics_endpoint.py,sha256=p9F_tbUela1sb3i9n67Tr9zsPRmsjSAigC6EqLwZHqE,3175
87
+ tableauserverclient/server/endpoint/permissions_endpoint.py,sha256=tXX_KSanbxUeR-L4UdI_jphko8dD_fZsXVhQayQL3JA,3719
88
+ tableauserverclient/server/endpoint/projects_endpoint.py,sha256=Q5plk2iPbCV2Ld0d0LuKBxfiENtoP8gu0CQj1lby2mA,11621
89
+ tableauserverclient/server/endpoint/resource_tagger.py,sha256=eKekflXzLjx_zDOLgYkTIusRO8vsFus1LvLIf0LOwtQ,6661
90
+ tableauserverclient/server/endpoint/schedules_endpoint.py,sha256=eUyNCqx7alQTPTCX-KYGk7zFd7EtAJxYatfa9D6NCc0,6242
91
+ tableauserverclient/server/endpoint/server_info_endpoint.py,sha256=9UcYP3td22S_Kwabu-RWc-Pn3lFrIERVlzVpl4ErP_I,2649
92
+ tableauserverclient/server/endpoint/sites_endpoint.py,sha256=H_bq6hU-zsGJ2sNr2jqQ5YGajQ310WvjJgpiDBREfiY,14001
93
+ tableauserverclient/server/endpoint/subscriptions_endpoint.py,sha256=21oZ6Q14AL8p2ZHyfREpbnPU6Vj4Xh97o1K9hmKRJ-I,3187
94
+ tableauserverclient/server/endpoint/tables_endpoint.py,sha256=7HCOheWJd8VAEz1TACbWnLFxfYiKcPB40XpxtT5Qbj0,5725
95
+ tableauserverclient/server/endpoint/tasks_endpoint.py,sha256=6HfKdEXMy-xYiAtpL2aRIsRlSR50hx2jvaNU3d3dKPw,3985
96
+ tableauserverclient/server/endpoint/users_endpoint.py,sha256=yLDzGy9K9ecY8uO8Tww1fp3hwrs_WMbMYtgMRRa7Hho,19788
97
+ tableauserverclient/server/endpoint/views_endpoint.py,sha256=VyLx7SU7i90oYrfkSuItS_fqb6iDE5nqD3kGE1IXkY8,9970
98
+ tableauserverclient/server/endpoint/virtual_connections_endpoint.py,sha256=K5R86aIm4hZeYw3OUOlKv-zTmsWa3np1iuV_h5iPvt0,8458
99
+ tableauserverclient/server/endpoint/webhooks_endpoint.py,sha256=1rgjDHfpXAneEAMfkrVuK8yW26rF-3kdAB42OSPTf-s,2721
100
+ tableauserverclient/server/endpoint/workbooks_endpoint.py,sha256=X6UriJnyWP1OsYlPwMij4vKrHZ5EEMmQaxLr9XwkN-M,43153
101
+ tableauserverclient-0.34.dist-info/LICENSE,sha256=MMkY7MguOb4L-WCmmqrVcwg2iwSGaz-RfAMFvXRXwsQ,1074
102
+ tableauserverclient-0.34.dist-info/LICENSE.versioneer,sha256=OYaGozOXk7bUNSm1z577iDYpti8a40XIqqR4lyQ47D8,334
103
+ tableauserverclient-0.34.dist-info/METADATA,sha256=_LjVhIb5VIxqO7dAcTvqnw43AloAy23Eak_dteZzg3Q,4331
104
+ tableauserverclient-0.34.dist-info/WHEEL,sha256=OVMc5UfuAQiSplgO0_WdW7vXVGAt9Hdd6qtN4HotdyA,91
105
+ tableauserverclient-0.34.dist-info/top_level.txt,sha256=kBnL39G2RlGqxJSsShDBWG4WZ3NFcWJkv1EGiOfZh4Q,20
106
+ tableauserverclient-0.34.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.1.0)
2
+ Generator: setuptools (75.2.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5