tableauserverclient 0.32__py3-none-any.whl → 0.34__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (96) hide show
  1. tableauserverclient/__init__.py +34 -18
  2. tableauserverclient/_version.py +3 -3
  3. tableauserverclient/config.py +20 -6
  4. tableauserverclient/models/__init__.py +12 -0
  5. tableauserverclient/models/column_item.py +1 -1
  6. tableauserverclient/models/connection_credentials.py +1 -1
  7. tableauserverclient/models/connection_item.py +10 -8
  8. tableauserverclient/models/custom_view_item.py +29 -6
  9. tableauserverclient/models/data_acceleration_report_item.py +2 -2
  10. tableauserverclient/models/data_alert_item.py +5 -5
  11. tableauserverclient/models/data_freshness_policy_item.py +6 -6
  12. tableauserverclient/models/database_item.py +8 -2
  13. tableauserverclient/models/datasource_item.py +10 -10
  14. tableauserverclient/models/dqw_item.py +1 -1
  15. tableauserverclient/models/favorites_item.py +5 -6
  16. tableauserverclient/models/fileupload_item.py +1 -1
  17. tableauserverclient/models/flow_item.py +12 -12
  18. tableauserverclient/models/flow_run_item.py +3 -3
  19. tableauserverclient/models/group_item.py +4 -4
  20. tableauserverclient/models/groupset_item.py +53 -0
  21. tableauserverclient/models/interval_item.py +36 -23
  22. tableauserverclient/models/job_item.py +26 -10
  23. tableauserverclient/models/linked_tasks_item.py +102 -0
  24. tableauserverclient/models/metric_item.py +5 -5
  25. tableauserverclient/models/pagination_item.py +1 -1
  26. tableauserverclient/models/permissions_item.py +19 -14
  27. tableauserverclient/models/project_item.py +35 -19
  28. tableauserverclient/models/property_decorators.py +12 -11
  29. tableauserverclient/models/reference_item.py +2 -2
  30. tableauserverclient/models/revision_item.py +3 -3
  31. tableauserverclient/models/schedule_item.py +2 -2
  32. tableauserverclient/models/server_info_item.py +26 -6
  33. tableauserverclient/models/site_item.py +69 -3
  34. tableauserverclient/models/subscription_item.py +3 -3
  35. tableauserverclient/models/table_item.py +1 -1
  36. tableauserverclient/models/tableau_auth.py +115 -5
  37. tableauserverclient/models/tableau_types.py +11 -9
  38. tableauserverclient/models/tag_item.py +3 -4
  39. tableauserverclient/models/task_item.py +4 -4
  40. tableauserverclient/models/user_item.py +47 -17
  41. tableauserverclient/models/view_item.py +11 -10
  42. tableauserverclient/models/virtual_connection_item.py +78 -0
  43. tableauserverclient/models/webhook_item.py +6 -6
  44. tableauserverclient/models/workbook_item.py +90 -12
  45. tableauserverclient/namespace.py +1 -1
  46. tableauserverclient/server/__init__.py +2 -1
  47. tableauserverclient/server/endpoint/__init__.py +8 -0
  48. tableauserverclient/server/endpoint/auth_endpoint.py +68 -11
  49. tableauserverclient/server/endpoint/custom_views_endpoint.py +124 -19
  50. tableauserverclient/server/endpoint/data_acceleration_report_endpoint.py +2 -2
  51. tableauserverclient/server/endpoint/data_alert_endpoint.py +14 -14
  52. tableauserverclient/server/endpoint/databases_endpoint.py +32 -17
  53. tableauserverclient/server/endpoint/datasources_endpoint.py +150 -59
  54. tableauserverclient/server/endpoint/default_permissions_endpoint.py +19 -18
  55. tableauserverclient/server/endpoint/dqw_endpoint.py +9 -9
  56. tableauserverclient/server/endpoint/endpoint.py +47 -31
  57. tableauserverclient/server/endpoint/exceptions.py +23 -7
  58. tableauserverclient/server/endpoint/favorites_endpoint.py +31 -31
  59. tableauserverclient/server/endpoint/fileuploads_endpoint.py +11 -13
  60. tableauserverclient/server/endpoint/flow_runs_endpoint.py +59 -17
  61. tableauserverclient/server/endpoint/flow_task_endpoint.py +2 -2
  62. tableauserverclient/server/endpoint/flows_endpoint.py +73 -35
  63. tableauserverclient/server/endpoint/groups_endpoint.py +96 -27
  64. tableauserverclient/server/endpoint/groupsets_endpoint.py +127 -0
  65. tableauserverclient/server/endpoint/jobs_endpoint.py +79 -12
  66. tableauserverclient/server/endpoint/linked_tasks_endpoint.py +45 -0
  67. tableauserverclient/server/endpoint/metadata_endpoint.py +2 -2
  68. tableauserverclient/server/endpoint/metrics_endpoint.py +10 -10
  69. tableauserverclient/server/endpoint/permissions_endpoint.py +13 -15
  70. tableauserverclient/server/endpoint/projects_endpoint.py +124 -30
  71. tableauserverclient/server/endpoint/resource_tagger.py +139 -6
  72. tableauserverclient/server/endpoint/schedules_endpoint.py +17 -18
  73. tableauserverclient/server/endpoint/server_info_endpoint.py +40 -5
  74. tableauserverclient/server/endpoint/sites_endpoint.py +282 -17
  75. tableauserverclient/server/endpoint/subscriptions_endpoint.py +10 -10
  76. tableauserverclient/server/endpoint/tables_endpoint.py +33 -19
  77. tableauserverclient/server/endpoint/tasks_endpoint.py +8 -8
  78. tableauserverclient/server/endpoint/users_endpoint.py +405 -19
  79. tableauserverclient/server/endpoint/views_endpoint.py +111 -25
  80. tableauserverclient/server/endpoint/virtual_connections_endpoint.py +174 -0
  81. tableauserverclient/server/endpoint/webhooks_endpoint.py +11 -11
  82. tableauserverclient/server/endpoint/workbooks_endpoint.py +735 -68
  83. tableauserverclient/server/filter.py +2 -2
  84. tableauserverclient/server/pager.py +8 -10
  85. tableauserverclient/server/query.py +70 -20
  86. tableauserverclient/server/request_factory.py +213 -41
  87. tableauserverclient/server/request_options.py +125 -145
  88. tableauserverclient/server/server.py +73 -9
  89. tableauserverclient/server/sort.py +2 -2
  90. {tableauserverclient-0.32.dist-info → tableauserverclient-0.34.dist-info}/METADATA +17 -17
  91. tableauserverclient-0.34.dist-info/RECORD +106 -0
  92. {tableauserverclient-0.32.dist-info → tableauserverclient-0.34.dist-info}/WHEEL +1 -1
  93. tableauserverclient-0.32.dist-info/RECORD +0 -100
  94. {tableauserverclient-0.32.dist-info → tableauserverclient-0.34.dist-info}/LICENSE +0 -0
  95. {tableauserverclient-0.32.dist-info → tableauserverclient-0.34.dist-info}/LICENSE.versioneer +0 -0
  96. {tableauserverclient-0.32.dist-info → tableauserverclient-0.34.dist-info}/top_level.txt +0 -0
@@ -1,19 +1,21 @@
1
1
  import sys
2
+ from typing import Optional
2
3
 
3
4
  from typing_extensions import Self
4
5
 
6
+ from tableauserverclient.config import config
5
7
  from tableauserverclient.models.property_decorators import property_is_int
6
8
  import logging
7
9
 
8
10
  from tableauserverclient.helpers.logging import logger
9
11
 
10
12
 
11
- class RequestOptionsBase(object):
13
+ class RequestOptionsBase:
12
14
  # This method is used if server api version is below 3.7 (2020.1)
13
15
  def apply_query_params(self, url):
14
16
  try:
15
17
  params = self.get_query_params()
16
- params_list = ["{}={}".format(k, v) for (k, v) in params.items()]
18
+ params_list = [f"{k}={v}" for (k, v) in params.items()]
17
19
 
18
20
  logger.debug("Applying options to request: <%s(%s)>", self.__class__.__name__, ",".join(params_list))
19
21
 
@@ -21,15 +23,52 @@ class RequestOptionsBase(object):
21
23
  url, existing_params = url.split("?")
22
24
  params_list.append(existing_params)
23
25
 
24
- return "{0}?{1}".format(url, "&".join(params_list))
26
+ return "{}?{}".format(url, "&".join(params_list))
25
27
  except NotImplementedError:
26
28
  raise
27
29
 
28
- def get_query_params(self):
29
- 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
+ """
30
35
 
31
36
 
32
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
+
33
72
  class Operator:
34
73
  Equals = "eq"
35
74
  GreaterThan = "gt"
@@ -38,7 +77,9 @@ class RequestOptions(RequestOptionsBase):
38
77
  LessThanOrEqual = "lte"
39
78
  In = "in"
40
79
  Has = "has"
80
+ CaseInsensitiveEquals = "cieq"
41
81
 
82
+ # These are fields in the REST API
42
83
  class Field:
43
84
  Args = "args"
44
85
  AuthenticationType = "authenticationType"
@@ -115,60 +156,53 @@ class RequestOptions(RequestOptionsBase):
115
156
  Desc = "desc"
116
157
  Asc = "asc"
117
158
 
118
- def __init__(self, pagenumber=1, pagesize=100):
119
- self.pagenumber = pagenumber
120
- self.pagesize = pagesize
121
- self.sort = set()
122
- self.filter = set()
123
159
 
124
- # This is private until we expand all of our parsers to handle the extra fields
125
- self._all_fields = False
126
-
127
- def page_size(self, page_size):
128
- self.pagesize = page_size
129
- return self
160
+ """
161
+ These options can be used by methods that are fetching data exported from a specific content item
162
+ """
130
163
 
131
- def page_number(self, page_number):
132
- self.pagenumber = page_number
133
- return self
134
-
135
- def get_query_params(self):
136
- params = {}
137
- if self.pagenumber:
138
- params["pageNumber"] = self.pagenumber
139
- if self.pagesize:
140
- params["pageSize"] = self.pagesize
141
- if len(self.sort) > 0:
142
- sort_options = (str(sort_item) for sort_item in self.sort)
143
- ordered_sort_options = sorted(sort_options)
144
- params["sort"] = ",".join(ordered_sort_options)
145
- if len(self.filter) > 0:
146
- filter_options = (str(filter_item) for filter_item in self.filter)
147
- ordered_filter_options = sorted(filter_options)
148
- params["filter"] = ",".join(ordered_filter_options)
149
- if self._all_fields:
150
- params["fields"] = "_all_"
151
- return params
152
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
153
177
 
154
- class _FilterOptionsBase(RequestOptionsBase):
155
- """Provide a basic implementation of adding view filters to the url"""
178
+ @property
179
+ def max_age(self) -> int:
180
+ return self._max_age
156
181
 
157
- def __init__(self):
158
- self.view_filters = []
159
- 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
160
186
 
161
187
  def get_query_params(self):
162
- 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
163
196
 
164
197
  def vf(self, name: str, value: str) -> Self:
165
- """Apply a filter to the view for a filter that is a normal column
166
- 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'"""
167
200
  self.view_filters.append((name, value))
168
201
  return self
169
202
 
170
203
  def parameter(self, name: str, value: str) -> Self:
171
- """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'"""
172
206
  self.view_parameters.append((name, value))
173
207
  return self
174
208
 
@@ -179,82 +213,73 @@ class _FilterOptionsBase(RequestOptionsBase):
179
213
  params[name] = value
180
214
 
181
215
 
182
- class CSVRequestOptions(_FilterOptionsBase):
183
- def __init__(self, maxage=-1):
184
- super(CSVRequestOptions, self).__init__()
185
- 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
186
221
 
187
222
  @property
188
- def max_age(self):
189
- return self._max_age
190
-
191
- @max_age.setter
192
- @property_is_int(range=(0, 240), allowed=[-1])
193
- def max_age(self, value):
194
- self._max_age = value
223
+ def viz_height(self):
224
+ return self._viz_height
195
225
 
196
- def get_query_params(self):
197
- params = {}
198
- if self.max_age != -1:
199
- 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
200
230
 
201
- self._append_view_filters(params)
202
- return params
231
+ @property
232
+ def viz_width(self):
233
+ return self._viz_width
203
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
204
239
 
205
- class ExcelRequestOptions(_FilterOptionsBase):
206
- def __init__(self, maxage: int = -1) -> None:
207
- super().__init__()
208
- self.max_age = maxage
240
+ def get_query_params(self) -> dict:
241
+ params = super().get_query_params()
209
242
 
210
- @property
211
- def max_age(self) -> int:
212
- 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")
213
246
 
214
- @max_age.setter
215
- @property_is_int(range=(0, 240), allowed=[-1])
216
- def max_age(self, value: int) -> None:
217
- self._max_age = value
247
+ if self.viz_height is not None:
248
+ params["vizHeight"] = self.viz_height
218
249
 
219
- def get_query_params(self):
220
- params = {}
221
- if self.max_age != -1:
222
- params["maxAge"] = self.max_age
250
+ if self.viz_width is not None:
251
+ params["vizWidth"] = self.viz_width
223
252
 
224
- self._append_view_filters(params)
225
253
  return params
226
254
 
227
255
 
228
- 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
+
229
267
  # if 'high' isn't specified, the REST API endpoint returns an image with standard resolution
230
268
  class Resolution:
231
269
  High = "high"
232
270
 
233
- def __init__(self, imageresolution=None, maxage=-1):
234
- 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)
235
273
  self.image_resolution = imageresolution
236
- self.max_age = maxage
237
-
238
- @property
239
- def max_age(self):
240
- return self._max_age
241
-
242
- @max_age.setter
243
- @property_is_int(range=(0, 240), allowed=[-1])
244
- def max_age(self, value):
245
- self._max_age = value
246
274
 
247
275
  def get_query_params(self):
248
- params = {}
276
+ params = super().get_query_params()
249
277
  if self.image_resolution:
250
278
  params["resolution"] = self.image_resolution
251
- if self.max_age != -1:
252
- params["maxAge"] = self.max_age
253
- self._append_view_filters(params)
254
279
  return params
255
280
 
256
281
 
257
- class PDFRequestOptions(_FilterOptionsBase):
282
+ class PDFRequestOptions(_ImagePDFCommonExportOptions):
258
283
  class PageType:
259
284
  A3 = "a3"
260
285
  A4 = "a4"
@@ -276,61 +301,16 @@ class PDFRequestOptions(_FilterOptionsBase):
276
301
  Landscape = "landscape"
277
302
 
278
303
  def __init__(self, page_type=None, orientation=None, maxage=-1, viz_height=None, viz_width=None):
279
- super(PDFRequestOptions, self).__init__()
304
+ super().__init__(maxage=maxage, viz_height=viz_height, viz_width=viz_width)
280
305
  self.page_type = page_type
281
306
  self.orientation = orientation
282
- self.max_age = maxage
283
- self.viz_height = viz_height
284
- self.viz_width = viz_width
285
-
286
- @property
287
- def max_age(self):
288
- return self._max_age
289
-
290
- @max_age.setter
291
- @property_is_int(range=(0, 240), allowed=[-1])
292
- def max_age(self, value):
293
- self._max_age = value
294
-
295
- @property
296
- def viz_height(self):
297
- return self._viz_height
298
-
299
- @viz_height.setter
300
- @property_is_int(range=(0, sys.maxsize), allowed=(None,))
301
- def viz_height(self, value):
302
- self._viz_height = value
303
-
304
- @property
305
- def viz_width(self):
306
- return self._viz_width
307
307
 
308
- @viz_width.setter
309
- @property_is_int(range=(0, sys.maxsize), allowed=(None,))
310
- def viz_width(self, value):
311
- self._viz_width = value
312
-
313
- def get_query_params(self):
314
- params = {}
308
+ def get_query_params(self) -> dict:
309
+ params = super().get_query_params()
315
310
  if self.page_type:
316
311
  params["type"] = self.page_type
317
312
 
318
313
  if self.orientation:
319
314
  params["orientation"] = self.orientation
320
315
 
321
- if self.max_age != -1:
322
- params["maxAge"] = self.max_age
323
-
324
- # XOR. Either both are None or both are not None.
325
- if (self.viz_height is None) ^ (self.viz_width is None):
326
- raise ValueError("viz_height and viz_width must be specified together")
327
-
328
- if self.viz_height is not None:
329
- params["vizHeight"] = self.viz_height
330
-
331
- if self.viz_width is not None:
332
- params["vizWidth"] = self.viz_width
333
-
334
- self._append_view_filters(params)
335
-
336
316
  return params
@@ -33,6 +33,10 @@ from tableauserverclient.server.endpoint import (
33
33
  Metrics,
34
34
  Endpoint,
35
35
  CustomViews,
36
+ LinkedTasks,
37
+ GroupSets,
38
+ Tags,
39
+ VirtualConnections,
36
40
  )
37
41
  from tableauserverclient.server.exceptions import (
38
42
  ServerInfoEndpointNotFoundError,
@@ -54,8 +58,64 @@ minimum_supported_server_version = "2.3"
54
58
  default_server_version = "2.4" # first version that dropped the legacy auth endpoint
55
59
 
56
60
 
57
- 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
+
58
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
+
59
119
  Append = "Append"
60
120
  Overwrite = "Overwrite"
61
121
  CreateNew = "CreateNew"
@@ -99,6 +159,10 @@ class Server(object):
99
159
  self.flow_runs = FlowRuns(self)
100
160
  self.metrics = Metrics(self)
101
161
  self.custom_views = CustomViews(self)
162
+ self.linked_tasks = LinkedTasks(self)
163
+ self.group_sets = GroupSets(self)
164
+ self.tags = Tags(self)
165
+ self.virtual_connections = VirtualConnections(self)
102
166
 
103
167
  self._session = self._session_factory()
104
168
  self._http_options = dict() # must set this before making a server call
@@ -122,7 +186,7 @@ class Server(object):
122
186
  raise ValueError("Server connection settings not valid", req_ex)
123
187
 
124
188
  def __repr__(self):
125
- return "<TableauServerClient [Connection: {}, {}]>".format(self.baseurl, self.server_info.serverInfo)
189
+ return f"<TableauServerClient [Connection: {self.baseurl}, {self.server_info.serverInfo}]>"
126
190
 
127
191
  def add_http_options(self, options_dict: dict):
128
192
  try:
@@ -134,7 +198,7 @@ class Server(object):
134
198
  # expected errors on invalid input:
135
199
  # 'set' object has no attribute 'keys', 'list' object has no attribute 'keys'
136
200
  # TypeError: cannot convert dictionary update sequence element #0 to a sequence (input is a tuple)
137
- raise ValueError("Invalid http options given: {}".format(options_dict))
201
+ raise ValueError(f"Invalid http options given: {options_dict}")
138
202
 
139
203
  def clear_http_options(self):
140
204
  self._http_options = dict()
@@ -168,15 +232,15 @@ class Server(object):
168
232
  old_version = self.version
169
233
  version = self.server_info.get().rest_api_version
170
234
  except ServerInfoEndpointNotFoundError as e:
171
- 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}")
172
236
  version = self._get_legacy_version()
173
237
  except EndpointUnavailableError as e:
174
- 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}")
175
239
  version = self._get_legacy_version()
176
240
  except Exception as e:
177
- 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}")
178
242
  version = None
179
- logger.info("versions: {}, {}".format(version, old_version))
243
+ logger.info(f"versions: {version}, {old_version}")
180
244
  return version or old_version
181
245
 
182
246
  def use_server_version(self):
@@ -193,12 +257,12 @@ class Server(object):
193
257
 
194
258
  def assert_at_least_version(self, comparison: str, reason: str):
195
259
  if not self.check_at_least_version(comparison):
196
- 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}"
197
261
  raise EndpointUnavailableError(error)
198
262
 
199
263
  @property
200
264
  def baseurl(self):
201
- return "{0}/api/{1}".format(self._server_address, str(self.version))
265
+ return f"{self._server_address}/api/{str(self.version)}"
202
266
 
203
267
  @property
204
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.32
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,28 +28,28 @@ 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
- Requires-Dist: defusedxml >=0.7.1
41
- Requires-Dist: packaging >=23.1
42
- Requires-Dist: requests >=2.31
43
- Requires-Dist: urllib3 ==2.2.2
44
- Requires-Dist: typing-extensions >=4.0.1
40
+ Requires-Dist: defusedxml>=0.7.1
41
+ Requires-Dist: packaging>=23.1
42
+ Requires-Dist: requests>=2.32
43
+ Requires-Dist: urllib3<3,>=2.2.2
44
+ Requires-Dist: typing-extensions>=4.0.1
45
45
  Provides-Extra: test
46
- Requires-Dist: black ==23.7 ; extra == 'test'
47
- Requires-Dist: build ; extra == 'test'
48
- Requires-Dist: mypy ==1.4 ; extra == 'test'
49
- Requires-Dist: pytest >=7.0 ; extra == 'test'
50
- Requires-Dist: pytest-cov ; extra == 'test'
51
- Requires-Dist: pytest-subtests ; extra == 'test'
52
- Requires-Dist: requests-mock <2.0,>=1.0 ; extra == 'test'
46
+ Requires-Dist: black==24.8; extra == "test"
47
+ Requires-Dist: build; extra == "test"
48
+ Requires-Dist: mypy==1.4; extra == "test"
49
+ Requires-Dist: pytest>=7.0; extra == "test"
50
+ Requires-Dist: pytest-cov; extra == "test"
51
+ Requires-Dist: pytest-subtests; extra == "test"
52
+ Requires-Dist: requests-mock<2.0,>=1.0; extra == "test"
53
53
 
54
54
  # Tableau Server Client (Python)
55
55
 
@@ -62,14 +62,14 @@ Use the Tableau Server Client (TSC) library to increase your productivity as you
62
62
  * Create users and groups.
63
63
  * Query projects, sites, and more.
64
64
 
65
- This repository contains Python source code for the library and sample files showing how to use it. As of May 2022, Python versions 3.7 and up are supported.
65
+ This repository contains Python source code for the library and sample files showing how to use it. As of September 2024, support for Python 3.7 and 3.8 will be dropped - support for older versions of Python aims to match https://devguide.python.org/versions/
66
66
 
67
67
  To see sample code that works directly with the REST API (in Java, Python, or Postman), visit the [REST API Samples](https://github.com/tableau/rest-api-samples) repo.
68
68
 
69
69
  For more information on installing and using TSC, see the documentation:
70
70
  <https://tableau.github.io/server-client-python/docs/>
71
71
 
72
-
72
+ To contribute, see our [Developer Guide](https://tableau.github.io/server-client-python/docs/dev-guide). A list of all our contributors to date is in [CONTRIBUTORS.md].
73
73
 
74
74
  ## License
75
75
  [![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Ftableau%2Fserver-client-python.svg?type=large)](https://app.fossa.com/projects/git%2Bgithub.com%2Ftableau%2Fserver-client-python?ref=badge_large)