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,7 +1,7 @@
1
1
  from .request_options import RequestOptions
2
2
 
3
3
 
4
- class Filter(object):
4
+ class Filter:
5
5
  def __init__(self, field, operator, value):
6
6
  self.field = field
7
7
  self.operator = operator
@@ -16,7 +16,7 @@ class Filter(object):
16
16
  # to [<string1>,<string2>]
17
17
  # so effectively, remove any spaces between "," and "'" and then remove all "'"
18
18
  value_string = value_string.replace(", '", ",'").replace("'", "")
19
- return "{0}:{1}:{2}".format(self.field, self.operator, value_string)
19
+ return f"{self.field}:{self.operator}:{value_string}"
20
20
 
21
21
  @property
22
22
  def value(self):
@@ -1,25 +1,23 @@
1
1
  import copy
2
2
  from functools import partial
3
- from typing import Generic, Iterable, Iterator, List, Optional, Protocol, Tuple, TypeVar, Union, runtime_checkable
3
+ from typing import Optional, Protocol, TypeVar, Union, runtime_checkable
4
+ from collections.abc import Iterable, Iterator
4
5
 
5
6
  from tableauserverclient.models.pagination_item import PaginationItem
6
7
  from tableauserverclient.server.request_options import RequestOptions
7
8
 
8
9
 
9
10
  T = TypeVar("T")
10
- ReturnType = Tuple[List[T], PaginationItem]
11
11
 
12
12
 
13
13
  @runtime_checkable
14
- class Endpoint(Protocol):
15
- def get(self, req_options: Optional[RequestOptions], **kwargs) -> ReturnType:
16
- ...
14
+ class Endpoint(Protocol[T]):
15
+ def get(self, req_options: Optional[RequestOptions]) -> tuple[list[T], PaginationItem]: ...
17
16
 
18
17
 
19
18
  @runtime_checkable
20
- class CallableEndpoint(Protocol):
21
- def __call__(self, __req_options: Optional[RequestOptions], **kwargs) -> ReturnType:
22
- ...
19
+ class CallableEndpoint(Protocol[T]):
20
+ def __call__(self, __req_options: Optional[RequestOptions], **kwargs) -> tuple[list[T], PaginationItem]: ...
23
21
 
24
22
 
25
23
  class Pager(Iterable[T]):
@@ -28,12 +26,12 @@ class Pager(Iterable[T]):
28
26
  Supports all `RequestOptions` including starting on any page. Also used by models to load sub-models
29
27
  (users in a group, views in a workbook, etc) by passing a different endpoint.
30
28
 
31
- Will loop over anything that returns (List[ModelItem], PaginationItem).
29
+ Will loop over anything that returns (list[ModelItem], PaginationItem).
32
30
  """
33
31
 
34
32
  def __init__(
35
33
  self,
36
- endpoint: Union[CallableEndpoint, Endpoint],
34
+ endpoint: Union[CallableEndpoint[T], Endpoint[T]],
37
35
  request_opts: Optional[RequestOptions] = None,
38
36
  **kwargs,
39
37
  ) -> None:
@@ -1,7 +1,10 @@
1
- from collections.abc import Sized
1
+ from collections.abc import Iterable, Iterator, Sized
2
2
  from itertools import count
3
- from typing import Iterable, Iterator, List, Optional, Protocol, Tuple, TYPE_CHECKING, TypeVar, overload
3
+ from typing import Optional, Protocol, TYPE_CHECKING, TypeVar, overload
4
+ import sys
5
+ from tableauserverclient.config import config
4
6
  from tableauserverclient.models.pagination_item import PaginationItem
7
+ from tableauserverclient.server.endpoint.exceptions import ServerResponseError
5
8
  from tableauserverclient.server.filter import Filter
6
9
  from tableauserverclient.server.request_options import RequestOptions
7
10
  from tableauserverclient.server.sort import Sort
@@ -33,10 +36,36 @@ see pagination_sample
33
36
 
34
37
 
35
38
  class QuerySet(Iterable[T], Sized):
39
+ """
40
+ QuerySet is a class that allows easy filtering, sorting, and iterating over
41
+ many endpoints in TableauServerClient. It is designed to be used in a similar
42
+ way to Django QuerySets, but with a more limited feature set.
43
+
44
+ QuerySet is an iterable, and can be used in for loops, list comprehensions,
45
+ and other places where iterables are expected.
46
+
47
+ QuerySet is also Sized, and can be used in places where the length of the
48
+ QuerySet is needed. The length of the QuerySet is the total number of items
49
+ available in the QuerySet, not just the number of items that have been
50
+ fetched. If the endpoint does not return a total count of items, the length
51
+ of the QuerySet will be sys.maxsize. If there is no total count, the
52
+ QuerySet will continue to fetch items until there are no more items to
53
+ fetch.
54
+
55
+ QuerySet is not re-entrant. It is not designed to be used in multiple places
56
+ at the same time. If you need to use a QuerySet in multiple places, you
57
+ should create a new QuerySet for each place you need to use it, convert it
58
+ to a list, or create a deep copy of the QuerySet.
59
+
60
+ QuerySets are also indexable, and can be sliced. If you try to access an
61
+ index that has not been fetched, the QuerySet will fetch the page that
62
+ contains the item you are looking for.
63
+ """
64
+
36
65
  def __init__(self, model: "QuerysetEndpoint[T]", page_size: Optional[int] = None) -> None:
37
66
  self.model = model
38
- self.request_options = RequestOptions(pagesize=page_size or 100)
39
- self._result_cache: List[T] = []
67
+ self.request_options = RequestOptions(pagesize=page_size or config.PAGE_SIZE)
68
+ self._result_cache: list[T] = []
40
69
  self._pagination_item = PaginationItem()
41
70
 
42
71
  def __iter__(self: Self) -> Iterator[T]:
@@ -48,19 +77,30 @@ class QuerySet(Iterable[T], Sized):
48
77
  for page in count(1):
49
78
  self.request_options.pagenumber = page
50
79
  self._result_cache = []
51
- self._fetch_all()
80
+ self._pagination_item._page_number = None
81
+ try:
82
+ self._fetch_all()
83
+ except ServerResponseError as e:
84
+ if e.code == "400006":
85
+ # If the endpoint does not support pagination, it will end
86
+ # up overrunning the total number of pages. Catch the
87
+ # error and break out of the loop.
88
+ raise StopIteration
89
+ if len(self._result_cache) == 0:
90
+ return
52
91
  yield from self._result_cache
53
- # Set result_cache to empty so the fetch will populate
54
- if (page * self.page_size) >= len(self):
92
+ # If the length of the QuerySet is unknown, continue fetching until
93
+ # the result cache is empty.
94
+ if (size := len(self)) == 0:
95
+ continue
96
+ if (page * self.page_size) >= size:
55
97
  return
56
98
 
57
99
  @overload
58
- def __getitem__(self: Self, k: Slice) -> List[T]:
59
- ...
100
+ def __getitem__(self: Self, k: Slice) -> list[T]: ...
60
101
 
61
102
  @overload
62
- def __getitem__(self: Self, k: int) -> T:
63
- ...
103
+ def __getitem__(self: Self, k: int) -> T: ...
64
104
 
65
105
  def __getitem__(self, k):
66
106
  page = self.page_number
@@ -102,6 +142,7 @@ class QuerySet(Iterable[T], Sized):
102
142
  elif k in range(self.total_available):
103
143
  # Otherwise, check if k is even sensible to return
104
144
  self._result_cache = []
145
+ self._pagination_item._page_number = None
105
146
  # Add one to k, otherwise it gets stuck at page boundaries, e.g. 100
106
147
  self.request_options.pagenumber = max(1, math.ceil((k + 1) / size))
107
148
  return self[k]
@@ -113,11 +154,16 @@ class QuerySet(Iterable[T], Sized):
113
154
  """
114
155
  Retrieve the data and store result and pagination item in cache
115
156
  """
116
- if not self._result_cache:
117
- self._result_cache, self._pagination_item = self.model.get(self.request_options)
157
+ if not self._result_cache and self._pagination_item._page_number is None:
158
+ response = self.model.get(self.request_options)
159
+ if isinstance(response, tuple):
160
+ self._result_cache, self._pagination_item = response
161
+ else:
162
+ self._result_cache = response
163
+ self._pagination_item = PaginationItem()
118
164
 
119
165
  def __len__(self: Self) -> int:
120
- return self.total_available
166
+ return sys.maxsize if self.total_available is None else self.total_available
121
167
 
122
168
  @property
123
169
  def total_available(self: Self) -> int:
@@ -127,12 +173,16 @@ class QuerySet(Iterable[T], Sized):
127
173
  @property
128
174
  def page_number(self: Self) -> int:
129
175
  self._fetch_all()
130
- return self._pagination_item.page_number
176
+ # If the PaginationItem is not returned from the endpoint, use the
177
+ # pagenumber from the RequestOptions.
178
+ return self._pagination_item.page_number or self.request_options.pagenumber
131
179
 
132
180
  @property
133
181
  def page_size(self: Self) -> int:
134
182
  self._fetch_all()
135
- return self._pagination_item.page_size
183
+ # If the PaginationItem is not returned from the endpoint, use the
184
+ # pagesize from the RequestOptions.
185
+ return self._pagination_item.page_size or self.request_options.pagesize
136
186
 
137
187
  def filter(self: Self, *invalid, page_size: Optional[int] = None, **kwargs) -> Self:
138
188
  if invalid:
@@ -159,22 +209,22 @@ class QuerySet(Iterable[T], Sized):
159
209
  return self
160
210
 
161
211
  @staticmethod
162
- def _parse_shorthand_filter(key: str) -> Tuple[str, str]:
212
+ def _parse_shorthand_filter(key: str) -> tuple[str, str]:
163
213
  tokens = key.split("__", 1)
164
214
  if len(tokens) == 1:
165
215
  operator = RequestOptions.Operator.Equals
166
216
  else:
167
217
  operator = tokens[1]
168
218
  if operator not in RequestOptions.Operator.__dict__.values():
169
- raise ValueError("Operator `{}` is not valid.".format(operator))
219
+ raise ValueError(f"Operator `{operator}` is not valid.")
170
220
 
171
221
  field = to_camel_case(tokens[0])
172
222
  if field not in RequestOptions.Field.__dict__.values():
173
- raise ValueError("Field name `{}` is not valid.".format(field))
223
+ raise ValueError(f"Field name `{field}` is not valid.")
174
224
  return (field, operator)
175
225
 
176
226
  @staticmethod
177
- def _parse_shorthand_sort(key: str) -> Tuple[str, str]:
227
+ def _parse_shorthand_sort(key: str) -> tuple[str, str]:
178
228
  direction = RequestOptions.Direction.Asc
179
229
  if key.startswith("-"):
180
230
  direction = RequestOptions.Direction.Desc