tableauserverclient 0.26__py3-none-any.whl → 0.28__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 (39) hide show
  1. tableauserverclient/__init__.py +42 -1
  2. tableauserverclient/_version.py +4 -4
  3. tableauserverclient/helpers/logging.py +0 -2
  4. tableauserverclient/models/__init__.py +1 -1
  5. tableauserverclient/models/column_item.py +3 -0
  6. tableauserverclient/models/connection_credentials.py +7 -0
  7. tableauserverclient/models/custom_view_item.py +5 -0
  8. tableauserverclient/models/data_acceleration_report_item.py +3 -0
  9. tableauserverclient/models/datasource_item.py +0 -9
  10. tableauserverclient/models/group_item.py +1 -4
  11. tableauserverclient/models/interval_item.py +12 -0
  12. tableauserverclient/models/job_item.py +10 -1
  13. tableauserverclient/models/metric_item.py +4 -1
  14. tableauserverclient/models/pagination_item.py +3 -0
  15. tableauserverclient/models/permissions_item.py +7 -4
  16. tableauserverclient/models/project_item.py +2 -0
  17. tableauserverclient/models/schedule_item.py +6 -7
  18. tableauserverclient/models/server_info_item.py +1 -1
  19. tableauserverclient/models/site_item.py +3 -0
  20. tableauserverclient/models/subscription_item.py +8 -0
  21. tableauserverclient/models/table_item.py +6 -0
  22. tableauserverclient/models/tableau_auth.py +41 -6
  23. tableauserverclient/models/user_item.py +4 -1
  24. tableauserverclient/models/view_item.py +4 -1
  25. tableauserverclient/models/workbook_item.py +4 -1
  26. tableauserverclient/server/endpoint/auth_endpoint.py +28 -7
  27. tableauserverclient/server/endpoint/favorites_endpoint.py +0 -1
  28. tableauserverclient/server/endpoint/groups_endpoint.py +4 -1
  29. tableauserverclient/server/endpoint/projects_endpoint.py +2 -0
  30. tableauserverclient/server/endpoint/tasks_endpoint.py +11 -0
  31. tableauserverclient/server/filter.py +5 -1
  32. tableauserverclient/server/request_factory.py +28 -0
  33. tableauserverclient/server/request_options.py +1 -0
  34. {tableauserverclient-0.26.dist-info → tableauserverclient-0.28.dist-info}/METADATA +12 -10
  35. {tableauserverclient-0.26.dist-info → tableauserverclient-0.28.dist-info}/RECORD +39 -39
  36. {tableauserverclient-0.26.dist-info → tableauserverclient-0.28.dist-info}/WHEEL +1 -1
  37. {tableauserverclient-0.26.dist-info → tableauserverclient-0.28.dist-info}/LICENSE +0 -0
  38. {tableauserverclient-0.26.dist-info → tableauserverclient-0.28.dist-info}/LICENSE.versioneer +0 -0
  39. {tableauserverclient-0.26.dist-info → tableauserverclient-0.28.dist-info}/top_level.txt +0 -0
@@ -1,6 +1,47 @@
1
1
  from ._version import get_versions
2
2
  from .namespace import NEW_NAMESPACE as DEFAULT_NAMESPACE
3
- from .models import *
3
+ from .models import (
4
+ BackgroundJobItem,
5
+ ColumnItem,
6
+ ConnectionCredentials,
7
+ ConnectionItem,
8
+ CustomViewItem,
9
+ DQWItem,
10
+ DailyInterval,
11
+ DataAlertItem,
12
+ DatabaseItem,
13
+ DatasourceItem,
14
+ FavoriteItem,
15
+ FlowItem,
16
+ FlowRunItem,
17
+ FileuploadItem,
18
+ GroupItem,
19
+ HourlyInterval,
20
+ IntervalItem,
21
+ JobItem,
22
+ JWTAuth,
23
+ MetricItem,
24
+ MonthlyInterval,
25
+ PaginationItem,
26
+ Permission,
27
+ PermissionsRule,
28
+ PersonalAccessTokenAuth,
29
+ ProjectItem,
30
+ RevisionItem,
31
+ ScheduleItem,
32
+ SiteItem,
33
+ ServerInfoItem,
34
+ SubscriptionItem,
35
+ TableItem,
36
+ TableauAuth,
37
+ Target,
38
+ TaskItem,
39
+ UserItem,
40
+ ViewItem,
41
+ WebhookItem,
42
+ WeeklyInterval,
43
+ WorkbookItem,
44
+ )
4
45
  from .server import (
5
46
  CSVRequestOptions,
6
47
  ExcelRequestOptions,
@@ -1,5 +1,5 @@
1
1
 
2
- # This file was generated by 'versioneer.py' (0.28) from
2
+ # This file was generated by 'versioneer.py' (0.29) from
3
3
  # revision-control system data, or from the parent directory name of an
4
4
  # unpacked source archive. Distribution tarballs contain a pre-generated copy
5
5
  # of this file.
@@ -8,11 +8,11 @@ import json
8
8
 
9
9
  version_json = '''
10
10
  {
11
- "date": "2023-04-24T13:08:23-0700",
11
+ "date": "2023-10-04T00:33:03-0700",
12
12
  "dirty": false,
13
13
  "error": null,
14
- "full-revisionid": "307d8a20a30f32c1ce615cca7c6a78b9b9bff081",
15
- "version": "0.26"
14
+ "full-revisionid": "72eb3c8500193e4f20defa20c8a6f8bbf34b2f43",
15
+ "version": "0.28"
16
16
  }
17
17
  ''' # END VERSION_JSON
18
18
 
@@ -2,5 +2,3 @@ import logging
2
2
 
3
3
  # TODO change: this defaults to logging *everything* to stdout
4
4
  logger = logging.getLogger("TSC")
5
- logger.setLevel(logging.DEBUG)
6
- logger.addHandler(logging.StreamHandler())
@@ -31,7 +31,7 @@ from .server_info_item import ServerInfoItem
31
31
  from .site_item import SiteItem
32
32
  from .subscription_item import SubscriptionItem
33
33
  from .table_item import TableItem
34
- from .tableau_auth import Credentials, TableauAuth, PersonalAccessTokenAuth
34
+ from .tableau_auth import Credentials, TableauAuth, PersonalAccessTokenAuth, JWTAuth
35
35
  from .tableau_types import Resource, TableauItem, plural_type
36
36
  from .tag_item import TagItem
37
37
  from .target import Target
@@ -9,6 +9,9 @@ class ColumnItem(object):
9
9
  self.description = description
10
10
  self.name = name
11
11
 
12
+ def __repr__(self):
13
+ return f"<{self.__class__.__name__} {self._id} {self.name} {self.description}>"
14
+
12
15
  @property
13
16
  def id(self):
14
17
  return self._id
@@ -15,6 +15,13 @@ class ConnectionCredentials(object):
15
15
  self.embed = embed
16
16
  self.oauth = oauth
17
17
 
18
+ def __repr__(self):
19
+ if self.password:
20
+ print = "redacted"
21
+ else:
22
+ print = "None"
23
+ return f"<{self.__class__.__name__} name={self.name} password={print} embed={self.embed} oauth={self.oauth} >"
24
+
18
25
  @property
19
26
  def embed(self):
20
27
  return self._embed
@@ -134,6 +134,7 @@ class CustomViewItem(object):
134
134
  cv_item._content_url = custom_view_xml.get("contentUrl", None)
135
135
  cv_item._id = custom_view_xml.get("id", None)
136
136
  cv_item._name = custom_view_xml.get("name", None)
137
+ cv_item._shared = string_to_bool(custom_view_xml.get("shared", None))
137
138
 
138
139
  if owner_elem is not None:
139
140
  parsed_owners = UserItem.from_response_as_owner(tostring(custom_view_xml), ns)
@@ -154,3 +155,7 @@ class CustomViewItem(object):
154
155
 
155
156
  all_view_items.append(cv_item)
156
157
  return all_view_items
158
+
159
+
160
+ def string_to_bool(s: Optional[str]) -> bool:
161
+ return (s or "").lower() == "true"
@@ -46,6 +46,9 @@ class DataAccelerationReportItem(object):
46
46
  def __init__(self, comparison_records):
47
47
  self._comparison_records = comparison_records
48
48
 
49
+ def __repr__(self):
50
+ return f"<(deprecated)DataAccelerationReportItem site={self.site} sheet={sheet_uri}>"
51
+
49
52
  @property
50
53
  def comparison_records(self):
51
54
  return self._comparison_records
@@ -326,17 +326,8 @@ class DatasourceItem(object):
326
326
  updated_at = parse_datetime(datasource_xml.get("updatedAt", None))
327
327
  certification_note = datasource_xml.get("certificationNote", None)
328
328
  certified = str(datasource_xml.get("isCertified", None)).lower() == "true"
329
- certification_note = datasource_xml.get("certificationNote", None)
330
- certified = str(datasource_xml.get("isCertified", None)).lower() == "true"
331
- content_url = datasource_xml.get("contentUrl", None)
332
- created_at = parse_datetime(datasource_xml.get("createdAt", None))
333
- datasource_type = datasource_xml.get("type", None)
334
- description = datasource_xml.get("description", None)
335
329
  encrypt_extracts = datasource_xml.get("encryptExtracts", None)
336
330
  has_extracts = datasource_xml.get("hasExtracts", None)
337
- id_ = datasource_xml.get("id", None)
338
- name = datasource_xml.get("name", None)
339
- updated_at = parse_datetime(datasource_xml.get("updatedAt", None))
340
331
  use_remote_query_agent = datasource_xml.get("useRemoteQueryAgent", None)
341
332
  webpage_url = datasource_xml.get("webpageUrl", None)
342
333
 
@@ -26,11 +26,9 @@ class GroupItem(object):
26
26
  self.name: Optional[str] = name
27
27
  self.domain_name: Optional[str] = domain_name
28
28
 
29
- def __str__(self):
29
+ def __repr__(self):
30
30
  return "{}({!r})".format(self.__class__.__name__, self.__dict__)
31
31
 
32
- __repr__ = __str__
33
-
34
32
  @property
35
33
  def domain_name(self) -> Optional[str]:
36
34
  return self._domain_name
@@ -48,7 +46,6 @@ class GroupItem(object):
48
46
  return self._name
49
47
 
50
48
  @name.setter
51
- @property_not_empty
52
49
  def name(self, value: str) -> None:
53
50
  self._name = value
54
51
 
@@ -31,6 +31,9 @@ class HourlyInterval(object):
31
31
  self.end_time = end_time
32
32
  self.interval = interval_value
33
33
 
34
+ def __repr__(self):
35
+ return f"<{self.__class__.__name__} start={self.start_time} end={self.end_time} interval={self.interval}>"
36
+
34
37
  @property
35
38
  def _frequency(self):
36
39
  return IntervalItem.Frequency.Hourly
@@ -86,6 +89,9 @@ class DailyInterval(object):
86
89
  self.start_time = start_time
87
90
  self.interval = interval_values
88
91
 
92
+ def __repr__(self):
93
+ return f"<{self.__class__.__name__} start={self.start_time} interval={self.interval}>"
94
+
89
95
  @property
90
96
  def _frequency(self):
91
97
  return IntervalItem.Frequency.Daily
@@ -114,6 +120,9 @@ class WeeklyInterval(object):
114
120
  self.start_time = start_time
115
121
  self.interval = interval_values
116
122
 
123
+ def __repr__(self):
124
+ return f"<{self.__class__.__name__} start={self.start_time} interval={self.interval}>"
125
+
117
126
  @property
118
127
  def _frequency(self):
119
128
  return IntervalItem.Frequency.Weekly
@@ -148,6 +157,9 @@ class MonthlyInterval(object):
148
157
  self.start_time = start_time
149
158
  self.interval = str(interval_value)
150
159
 
160
+ def __repr__(self):
161
+ return f"<{self.__class__.__name__} start={self.start_time} interval={self.interval}>"
162
+
151
163
  @property
152
164
  def _frequency(self):
153
165
  return IntervalItem.Frequency.Monthly
@@ -117,12 +117,15 @@ class JobItem(object):
117
117
  def updated_at(self) -> Optional[datetime.datetime]:
118
118
  return self._updated_at
119
119
 
120
- def __repr__(self):
120
+ def __str__(self):
121
121
  return (
122
122
  "<Job#{_id} {_type} created_at({_created_at}) started_at({_started_at}) updated_at({_updated_at}) completed_at({_completed_at})"
123
123
  " progress ({_progress}) finish_code({_finish_code})>".format(**self.__dict__)
124
124
  )
125
125
 
126
+ def __repr__(self):
127
+ return self.__str__() + " { " + ", ".join(" % s: % s" % item for item in vars(self).items()) + "}"
128
+
126
129
  @classmethod
127
130
  def from_response(cls, xml, ns) -> List["JobItem"]:
128
131
  parsed_response = fromstring(xml)
@@ -202,6 +205,12 @@ class BackgroundJobItem(object):
202
205
  self._title = title
203
206
  self._subtitle = subtitle
204
207
 
208
+ def __str__(self):
209
+ return f"<{self.__class__.name} {self._id} {self._type}>"
210
+
211
+ def __repr__(self):
212
+ return self.__str__() + " { " + ", ".join(" % s: % s" % item for item in vars(self).items()) + "}"
213
+
205
214
  @property
206
215
  def id(self) -> str:
207
216
  return self._id
@@ -115,9 +115,12 @@ class MetricItem(object):
115
115
  def _set_permissions(self, permissions):
116
116
  self._permissions = permissions
117
117
 
118
- def __repr__(self):
118
+ def __str__(self):
119
119
  return "<MetricItem# name={_name} id={_id} owner_id={_owner_id}>".format(**vars(self))
120
120
 
121
+ def __repr__(self):
122
+ return self.__str__() + " { " + ", ".join(" % s: % s" % item for item in vars(self).items()) + "}"
123
+
121
124
  @classmethod
122
125
  def from_response(
123
126
  cls,
@@ -7,6 +7,9 @@ class PaginationItem(object):
7
7
  self._page_size = None
8
8
  self._total_available = None
9
9
 
10
+ def __repr__(self):
11
+ return f"<PaginationItem page_number={self._page_number} page_size={self._page_size} total={self._total_available}>"
12
+
10
13
  @property
11
14
  def page_number(self) -> int:
12
15
  return self._page_number
@@ -1,4 +1,3 @@
1
- import logging
2
1
  import xml.etree.ElementTree as ET
3
2
  from typing import Dict, List, Optional
4
3
 
@@ -17,6 +16,9 @@ class Permission:
17
16
  Allow = "Allow"
18
17
  Deny = "Deny"
19
18
 
19
+ def __repr__(self):
20
+ return "<Enum Mode: Allow | Deny>"
21
+
20
22
  class Capability:
21
23
  AddComment = "AddComment"
22
24
  ChangeHierarchy = "ChangeHierarchy"
@@ -39,17 +41,18 @@ class Permission:
39
41
  CreateRefreshMetrics = "CreateRefreshMetrics"
40
42
  SaveAs = "SaveAs"
41
43
 
44
+ def __repr__(self):
45
+ return "<Enum Capability: AddComment | ChangeHierarchy | ChangePermission ... (17 more) >"
46
+
42
47
 
43
48
  class PermissionsRule(object):
44
49
  def __init__(self, grantee: ResourceReference, capabilities: Dict[str, str]) -> None:
45
50
  self.grantee = grantee
46
51
  self.capabilities = capabilities
47
52
 
48
- def __str__(self):
53
+ def __repr__(self):
49
54
  return "<PermissionsRule grantee={}, capabilities={}>".format(self.grantee, self.capabilities)
50
55
 
51
- __repr__ = __str__
52
-
53
56
  @classmethod
54
57
  def from_response(cls, resp, ns=None) -> List["PermissionsRule"]:
55
58
  parsed_response = fromstring(resp)
@@ -25,6 +25,7 @@ class ProjectItem(object):
25
25
  description: Optional[str] = None,
26
26
  content_permissions: Optional[str] = None,
27
27
  parent_id: Optional[str] = None,
28
+ samples: Optional[bool] = None,
28
29
  ) -> None:
29
30
  self._content_permissions = None
30
31
  self._id: Optional[str] = None
@@ -32,6 +33,7 @@ class ProjectItem(object):
32
33
  self.name: str = name
33
34
  self.content_permissions: Optional[str] = content_permissions
34
35
  self.parent_id: Optional[str] = parent_id
36
+ self._samples: Optional[bool] = samples
35
37
 
36
38
  self._permissions = None
37
39
  self._default_workbook_permissions = None
@@ -14,8 +14,6 @@ from .interval_item import (
14
14
  )
15
15
  from .property_decorators import (
16
16
  property_is_enum,
17
- property_not_nullable,
18
- property_is_int,
19
17
  )
20
18
 
21
19
  Interval = Union[HourlyInterval, DailyInterval, WeeklyInterval, MonthlyInterval]
@@ -27,6 +25,7 @@ class ScheduleItem(object):
27
25
  Flow = "Flow"
28
26
  Subscription = "Subscription"
29
27
  DataAcceleration = "DataAcceleration"
28
+ ActiveDirectorySync = "ActiveDirectorySync"
30
29
 
31
30
  class ExecutionOrder:
32
31
  Parallel = "Parallel"
@@ -49,9 +48,12 @@ class ScheduleItem(object):
49
48
  self.priority: int = priority
50
49
  self.schedule_type: str = schedule_type
51
50
 
52
- def __repr__(self):
51
+ def __str__(self):
53
52
  return '<Schedule#{_id} "{_name}" {interval_item}>'.format(**vars(self))
54
53
 
54
+ def __repr__(self):
55
+ return self.__str__() + " { " + ", ".join(" % s: % s" % item for item in vars(self).items()) + "}"
56
+
55
57
  @property
56
58
  def created_at(self) -> Optional[datetime]:
57
59
  return self._created_at
@@ -74,11 +76,10 @@ class ScheduleItem(object):
74
76
  return self._id
75
77
 
76
78
  @property
77
- def name(self) -> str:
79
+ def name(self) -> Optional[str]:
78
80
  return self._name
79
81
 
80
82
  @name.setter
81
- @property_not_nullable
82
83
  def name(self, value: str):
83
84
  self._name = value
84
85
 
@@ -91,7 +92,6 @@ class ScheduleItem(object):
91
92
  return self._priority
92
93
 
93
94
  @priority.setter
94
- @property_is_int(range=(1, 100))
95
95
  def priority(self, value: int):
96
96
  self._priority = value
97
97
 
@@ -101,7 +101,6 @@ class ScheduleItem(object):
101
101
 
102
102
  @schedule_type.setter
103
103
  @property_is_enum(Type)
104
- @property_not_nullable
105
104
  def schedule_type(self, value: str):
106
105
  self._schedule_type = value
107
106
 
@@ -12,7 +12,7 @@ class ServerInfoItem(object):
12
12
  self._build_number = build_number
13
13
  self._rest_api_version = rest_api_version
14
14
 
15
- def __str__(self):
15
+ def __repr__(self):
16
16
  return (
17
17
  "ServerInfoItem: [product version: "
18
18
  + self._product_version
@@ -39,6 +39,9 @@ class SiteItem(object):
39
39
  + ">"
40
40
  )
41
41
 
42
+ def __repr__(self):
43
+ return self.__str__() + " { " + ", ".join(" % s: % s" % item for item in vars(self).items()) + "}"
44
+
42
45
  class AdminMode:
43
46
  ContentAndUsers: str = "ContentAndUsers"
44
47
  ContentOnly: str = "ContentOnly"
@@ -4,6 +4,7 @@ from defusedxml.ElementTree import fromstring
4
4
 
5
5
  from .property_decorators import property_is_boolean
6
6
  from .target import Target
7
+ from tableauserverclient.models import ScheduleItem
7
8
 
8
9
  if TYPE_CHECKING:
9
10
  from .target import Target
@@ -23,6 +24,7 @@ class SubscriptionItem(object):
23
24
  self.suspended = False
24
25
  self.target = target
25
26
  self.user_id = user_id
27
+ self.schedule = None
26
28
 
27
29
  def __repr__(self) -> str:
28
30
  if self.id is not None:
@@ -92,9 +94,14 @@ class SubscriptionItem(object):
92
94
 
93
95
  # Schedule element
94
96
  schedule_id = None
97
+ schedule = None
95
98
  if schedule_element is not None:
96
99
  schedule_id = schedule_element.get("id", None)
97
100
 
101
+ # If schedule id is not provided, then TOL with full schedule provided
102
+ if schedule_id is None:
103
+ schedule = ScheduleItem.from_element(element, ns)
104
+
98
105
  # Content element
99
106
  target = None
100
107
  send_if_view_empty = None
@@ -127,6 +134,7 @@ class SubscriptionItem(object):
127
134
  sub.page_size_option = page_size_option
128
135
  sub.send_if_view_empty = send_if_view_empty
129
136
  sub.suspended = suspended
137
+ sub.schedule = schedule
130
138
 
131
139
  return sub
132
140
 
@@ -19,6 +19,12 @@ class TableItem(object):
19
19
  self._columns = None
20
20
  self._data_quality_warnings = None
21
21
 
22
+ def __str__(self):
23
+ return f"<{self.__class__.__name__} {self._id} {self._name} >"
24
+
25
+ def __repr__(self):
26
+ return self.__str__() + " { " + ", ".join(" % s: % s" % item for item in vars(self).items()) + "}"
27
+
22
28
  @property
23
29
  def permissions(self):
24
30
  if self._permissions is None:
@@ -1,13 +1,18 @@
1
- class Credentials:
1
+ import abc
2
+
3
+
4
+ class Credentials(abc.ABC):
2
5
  def __init__(self, site_id=None, user_id_to_impersonate=None):
3
6
  self.site_id = site_id or ""
4
7
  self.user_id_to_impersonate = user_id_to_impersonate or None
5
8
 
6
9
  @property
10
+ @abc.abstractmethod
7
11
  def credentials(self):
8
12
  credentials = "Credentials can be username/password, Personal Access Token, or JWT"
9
13
  +"This method returns values to set as an attribute on the credentials element of the request"
10
14
 
15
+ @abc.abstractmethod
11
16
  def __repr__(self):
12
17
  return "All Credentials types must have a debug display that does not print secrets"
13
18
 
@@ -38,7 +43,11 @@ class TableauAuth(Credentials):
38
43
  return {"name": self.username, "password": self.password}
39
44
 
40
45
  def __repr__(self):
41
- return "<Credentials username={} password={}>".format(self.username, "<redacted>")
46
+ if self.user_id_to_impersonate:
47
+ uid = f", user_id_to_impersonate=f{self.user_id_to_impersonate}"
48
+ else:
49
+ uid = ""
50
+ return f"<Credentials username={self.username} password=redacted (site={self.site_id}{uid})>"
42
51
 
43
52
  @property
44
53
  def site(self):
@@ -51,11 +60,12 @@ class TableauAuth(Credentials):
51
60
  self.site_id = value
52
61
 
53
62
 
63
+ # A Tableau-generated Personal Access Token
54
64
  class PersonalAccessTokenAuth(Credentials):
55
- def __init__(self, token_name, personal_access_token, site_id=None):
65
+ def __init__(self, token_name, personal_access_token, site_id=None, user_id_to_impersonate=None):
56
66
  if personal_access_token is None or token_name is None:
57
67
  raise TabError("Must provide a token and token name when using PAT authentication")
58
- super().__init__(site_id=site_id)
68
+ super().__init__(site_id=site_id, user_id_to_impersonate=user_id_to_impersonate)
59
69
  self.token_name = token_name
60
70
  self.personal_access_token = personal_access_token
61
71
 
@@ -67,6 +77,31 @@ class PersonalAccessTokenAuth(Credentials):
67
77
  }
68
78
 
69
79
  def __repr__(self):
70
- return "<PersonalAccessToken name={} token={}>(site={})".format(
71
- self.token_name, self.personal_access_token[:2] + "...", self.site_id
80
+ if self.user_id_to_impersonate:
81
+ uid = f", user_id_to_impersonate=f{self.user_id_to_impersonate}"
82
+ else:
83
+ uid = ""
84
+ return (
85
+ f"<PersonalAccessToken name={self.token_name} token={self.personal_access_token[:2]}..."
86
+ f"(site={self.site_id}{uid} >"
72
87
  )
88
+
89
+
90
+ # A standard JWT generated specifically for Tableau
91
+ class JWTAuth(Credentials):
92
+ def __init__(self, jwt: str, site_id=None, user_id_to_impersonate=None):
93
+ if jwt is None:
94
+ raise TabError("Must provide a JWT token when using JWT authentication")
95
+ super().__init__(site_id, user_id_to_impersonate)
96
+ self.jwt = jwt
97
+
98
+ @property
99
+ def credentials(self):
100
+ return {"jwt": self.jwt}
101
+
102
+ def __repr__(self):
103
+ if self.user_id_to_impersonate:
104
+ uid = f", user_id_to_impersonate=f{self.user_id_to_impersonate}"
105
+ else:
106
+ uid = ""
107
+ return f"<{self.__class__.__qualname__} jwt={self.jwt[:5]}... (site={self.site_id}{uid})>"
@@ -67,10 +67,13 @@ class UserItem(object):
67
67
 
68
68
  return None
69
69
 
70
- def __repr__(self) -> str:
70
+ def __str__(self) -> str:
71
71
  str_site_role = self.site_role or "None"
72
72
  return "<User {} name={} role={}>".format(self.id, self.name, str_site_role)
73
73
 
74
+ def __repr__(self):
75
+ return self.__str__() + " { " + ", ".join(" % s: % s" % item for item in vars(self).items()) + "}"
76
+
74
77
  @property
75
78
  def auth_setting(self) -> Optional[str]:
76
79
  return self._auth_setting
@@ -32,11 +32,14 @@ class ViewItem(object):
32
32
  self._permissions: Optional[Callable[[], List[PermissionsRule]]] = None
33
33
  self.tags: Set[str] = set()
34
34
 
35
- def __repr__(self):
35
+ def __str__(self):
36
36
  return "<ViewItem {0} '{1}' contentUrl='{2}' project={3}>".format(
37
37
  self._id, self.name, self.content_url, self.project_id
38
38
  )
39
39
 
40
+ def __repr__(self):
41
+ return self.__str__() + " { " + ", ".join(" % s: % s" % item for item in vars(self).items()) + "}"
42
+
40
43
  def _set_preview_image(self, preview_image):
41
44
  self._preview_image = preview_image
42
45
 
@@ -53,11 +53,14 @@ class WorkbookItem(object):
53
53
 
54
54
  return None
55
55
 
56
- def __repr__(self):
56
+ def __str__(self):
57
57
  return "<WorkbookItem {0} '{1}' contentUrl='{2}' project={3}>".format(
58
58
  self._id, self.name, self.content_url, self.project_id
59
59
  )
60
60
 
61
+ def __repr__(self):
62
+ return self.__str__() + " { " + ", ".join(" % s: % s" % item for item in vars(self).items()) + "}"
63
+
61
64
  @property
62
65
  def connections(self) -> List[ConnectionItem]:
63
66
  if self._connections is None:
@@ -1,4 +1,6 @@
1
1
  import logging
2
+ from typing import TYPE_CHECKING
3
+ import warnings
2
4
 
3
5
  from defusedxml.ElementTree import fromstring
4
6
 
@@ -8,6 +10,10 @@ from ..request_factory import RequestFactory
8
10
 
9
11
  from tableauserverclient.helpers.logging import logger
10
12
 
13
+ if TYPE_CHECKING:
14
+ from tableauserverclient.models.site_item import SiteItem
15
+ from tableauserverclient.models.tableau_auth import Credentials
16
+
11
17
 
12
18
  class Auth(Endpoint):
13
19
  class contextmgr(object):
@@ -21,11 +27,21 @@ class Auth(Endpoint):
21
27
  self._callback()
22
28
 
23
29
  @property
24
- def baseurl(self):
30
+ def baseurl(self) -> str:
25
31
  return "{0}/auth".format(self.parent_srv.baseurl)
26
32
 
27
33
  @api(version="2.0")
28
- def sign_in(self, auth_req):
34
+ def sign_in(self, auth_req: "Credentials") -> contextmgr:
35
+ """
36
+ Sign in to a Tableau Server or Tableau Online using a credentials object.
37
+
38
+ The credentials object can either be a TableauAuth object, a
39
+ PersonalAccessTokenAuth object, or a JWTAuth object. This method now
40
+ accepts them all. The object should be populated with the site_id and
41
+ optionally a user_id to impersonate.
42
+
43
+ Creates a context manager that will sign out of the server upon exit.
44
+ """
29
45
  url = "{0}/{1}".format(self.baseurl, "signin")
30
46
  signin_req = RequestFactory.Auth.signin_req(auth_req)
31
47
  server_response = self.parent_srv.session.post(
@@ -50,13 +66,18 @@ class Auth(Endpoint):
50
66
  logger.info("Signed into {0} as user with id {1}".format(self.parent_srv.server_address, user_id))
51
67
  return Auth.contextmgr(self.sign_out)
52
68
 
69
+ # We use the same request that username/password login uses for all auth types.
70
+ # The distinct methods are mostly useful for explicitly showing api version support for each auth type
53
71
  @api(version="3.6")
54
- def sign_in_with_personal_access_token(self, auth_req):
55
- # We use the same request that username/password login uses.
72
+ def sign_in_with_personal_access_token(self, auth_req: "Credentials") -> contextmgr:
73
+ return self.sign_in(auth_req)
74
+
75
+ @api(version="3.17")
76
+ def sign_in_with_json_web_token(self, auth_req: "Credentials") -> contextmgr:
56
77
  return self.sign_in(auth_req)
57
78
 
58
79
  @api(version="2.0")
59
- def sign_out(self):
80
+ def sign_out(self) -> None:
60
81
  url = "{0}/{1}".format(self.baseurl, "signout")
61
82
  # If there are no auth tokens you're already signed out. No-op
62
83
  if not self.parent_srv.is_signed_in():
@@ -66,7 +87,7 @@ class Auth(Endpoint):
66
87
  logger.info("Signed out")
67
88
 
68
89
  @api(version="2.6")
69
- def switch_site(self, site_item):
90
+ def switch_site(self, site_item: "SiteItem") -> contextmgr:
70
91
  url = "{0}/{1}".format(self.baseurl, "switchSite")
71
92
  switch_req = RequestFactory.Auth.switch_req(site_item.content_url)
72
93
  try:
@@ -87,7 +108,7 @@ class Auth(Endpoint):
87
108
  return Auth.contextmgr(self.sign_out)
88
109
 
89
110
  @api(version="3.10")
90
- def revoke_all_server_admin_tokens(self):
111
+ def revoke_all_server_admin_tokens(self) -> None:
91
112
  url = "{0}/{1}".format(self.baseurl, "revokeAllServerAdminTokens")
92
113
  self.post_request(url, "")
93
114
  logger.info("Revoked all tokens for all server admins")
@@ -1,6 +1,5 @@
1
1
  from .endpoint import Endpoint, api
2
2
  from requests import Response
3
-
4
3
  from tableauserverclient.helpers.logging import logger
5
4
  from tableauserverclient.models import (
6
5
  DatasourceItem,
@@ -82,14 +82,17 @@ class Groups(QuerysetEndpoint):
82
82
  )
83
83
  group_item.minimum_site_role = default_site_role
84
84
 
85
+ url = "{0}/{1}".format(self.baseurl, group_item.id)
86
+
85
87
  if not group_item.id:
86
88
  error = "Group item missing ID."
87
89
  raise MissingRequiredFieldError(error)
88
90
  if as_job and (group_item.domain_name is None or group_item.domain_name == "local"):
89
91
  error = "Local groups cannot be updated asynchronously."
90
92
  raise ValueError(error)
93
+ elif as_job:
94
+ url = "?".join([url, "asJob=True"])
91
95
 
92
- url = "{0}/{1}".format(self.baseurl, group_item.id)
93
96
  update_req = RequestFactory.Group.update_req(group_item, None)
94
97
  server_response = self.put_request(url, update_req)
95
98
  logger.info("Updated group item (ID: {0})".format(group_item.id))
@@ -63,6 +63,8 @@ class Projects(QuerysetEndpoint):
63
63
  def create(self, project_item: ProjectItem, samples: bool = False) -> ProjectItem:
64
64
  params = {"params": {RequestOptions.Field.PublishSamples: samples}}
65
65
  url = self.baseurl
66
+ if project_item._samples:
67
+ url = "{0}?publishSamples={1}".format(self.baseurl, project_item._samples)
66
68
  create_req = RequestFactory.Project.create_req(project_item)
67
69
  server_response = self.post_request(url, create_req, XML_CONTENT_TYPE, params)
68
70
  new_project = ProjectItem.from_response(server_response.content, self.parent_srv.namespace)[0]
@@ -51,6 +51,17 @@ class Tasks(Endpoint):
51
51
  server_response = self.get_request(url)
52
52
  return TaskItem.from_response(server_response.content, self.parent_srv.namespace)[0]
53
53
 
54
+ @api(version="3.19")
55
+ def create(self, extract_item: TaskItem) -> TaskItem:
56
+ if not extract_item:
57
+ error = "No extract refresh provided"
58
+ raise ValueError(error)
59
+ logger.info("Creating an extract refresh ({})".format(extract_item))
60
+ url = "{0}/{1}".format(self.baseurl, self.__normalize_task_type(TaskItem.Type.ExtractRefresh))
61
+ create_req = RequestFactory.Task.create_extract_req(extract_item)
62
+ server_response = self.post_request(url, create_req)
63
+ return server_response.content
64
+
54
65
  @api(version="2.6")
55
66
  def run(self, task_item):
56
67
  if not task_item.id:
@@ -11,7 +11,11 @@ class Filter(object):
11
11
  def __str__(self):
12
12
  value_string = str(self._value)
13
13
  if isinstance(self._value, list):
14
- value_string = value_string.replace(" ", "").replace("'", "")
14
+ # this should turn the string representation of the list
15
+ # from ['<string1>', '<string2>', ...]
16
+ # to [<string1>,<string2>]
17
+ # so effectively, remove any spaces between "," and "'" and then remove all "'"
18
+ value_string = value_string.replace(", '", ",'").replace("'", "")
15
19
  return "{0}:{1}:{2}".format(self.field, self.operator, value_string)
16
20
 
17
21
  @property
@@ -1028,6 +1028,34 @@ class TaskRequest(object):
1028
1028
  # Send an empty tsRequest
1029
1029
  pass
1030
1030
 
1031
+ @_tsrequest_wrapped
1032
+ def create_extract_req(self, xml_request: ET.Element, extract_item: "TaskItem") -> bytes:
1033
+ extract_element = ET.SubElement(xml_request, "extractRefresh")
1034
+
1035
+ # Schedule attributes
1036
+ schedule_element = ET.SubElement(xml_request, "schedule")
1037
+
1038
+ interval_item = extract_item.schedule_item.interval_item
1039
+ schedule_element.attrib["frequency"] = interval_item._frequency
1040
+ frequency_element = ET.SubElement(schedule_element, "frequencyDetails")
1041
+ frequency_element.attrib["start"] = str(interval_item.start_time)
1042
+ if hasattr(interval_item, "end_time") and interval_item.end_time is not None:
1043
+ frequency_element.attrib["end"] = str(interval_item.end_time)
1044
+ if hasattr(interval_item, "interval") and interval_item.interval:
1045
+ intervals_element = ET.SubElement(frequency_element, "intervals")
1046
+ for interval in interval_item._interval_type_pairs():
1047
+ expression, value = interval
1048
+ single_interval_element = ET.SubElement(intervals_element, "interval")
1049
+ single_interval_element.attrib[expression] = value
1050
+
1051
+ # Main attributes
1052
+ extract_element.attrib["type"] = extract_item.task_type
1053
+
1054
+ target_element = ET.SubElement(extract_element, extract_item.target.type)
1055
+ target_element.attrib["id"] = extract_item.target.id
1056
+
1057
+ return ET.tostring(xml_request)
1058
+
1031
1059
 
1032
1060
  class SubscriptionRequest(object):
1033
1061
  @_tsrequest_wrapped
@@ -167,6 +167,7 @@ class ExcelRequestOptions(_FilterOptionsBase):
167
167
  if self.max_age != -1:
168
168
  params["maxAge"] = self.max_age
169
169
 
170
+ self._append_view_filters(params)
170
171
  return params
171
172
 
172
173
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: tableauserverclient
3
- Version: 0.26
3
+ Version: 0.28
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,26 +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.7
32
31
  Classifier: Programming Language :: Python :: 3.8
33
32
  Classifier: Programming Language :: Python :: 3.9
34
33
  Classifier: Programming Language :: Python :: 3.10
34
+ Classifier: Programming Language :: Python :: 3.11
35
+ Classifier: Programming Language :: Python :: 3.12
35
36
  Requires-Python: >=3.7
36
37
  Description-Content-Type: text/markdown
37
38
  License-File: LICENSE
38
39
  License-File: LICENSE.versioneer
39
- Requires-Dist: defusedxml (>=0.7.1)
40
- Requires-Dist: packaging (>=22.0)
41
- Requires-Dist: requests (>=2.28)
42
- Requires-Dist: urllib3 (~=1.26.8)
40
+ Requires-Dist: defusedxml >=0.7.1
41
+ Requires-Dist: packaging >=23.1
42
+ Requires-Dist: requests >=2.31
43
+ Requires-Dist: urllib3 ==2.0.6
43
44
  Provides-Extra: test
44
45
  Requires-Dist: argparse ; extra == 'test'
45
- Requires-Dist: black ; extra == 'test'
46
+ Requires-Dist: black ==23.7 ; extra == 'test'
46
47
  Requires-Dist: mock ; extra == 'test'
47
- Requires-Dist: mypy ; extra == 'test'
48
- Requires-Dist: pytest (>=7.0) ; 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'
49
51
  Requires-Dist: pytest-subtests ; extra == 'test'
50
- Requires-Dist: requests-mock (<2.0,>=1.0) ; extra == 'test'
52
+ Requires-Dist: requests-mock <2.0,>=1.0 ; extra == 'test'
51
53
 
52
54
  # Tableau Server Client (Python)
53
55
 
@@ -1,5 +1,5 @@
1
- tableauserverclient/__init__.py,sha256=ftQXEg_7wXOMqiUdFG14rOgMoKELODvkszHmsQELU4w,378
2
- tableauserverclient/_version.py,sha256=Po29xYWGqun8nkQ1K3B4jzZk6ukpZ5RtnhCf9PJ_ESc,496
1
+ tableauserverclient/__init__.py,sha256=hDjLTdwXPmQj4BQBRdUcnP7XdhT7apJ_c7JAPyyYZ7Y,1096
2
+ tableauserverclient/_version.py,sha256=77BR3Uhg7xOImjTULb4qcvv7VjeMtNO9xpnQ-eW_gLU,496
3
3
  tableauserverclient/config.py,sha256=u9YnTDv0XnFR0sUY6AdeSuP5Zi2WKmcgJGGdehuaoO0,429
4
4
  tableauserverclient/datetime_helpers.py,sha256=_-gWz5I2_KHT5AzW_boD8meH6loTTKdK-_62h1MA6ko,884
5
5
  tableauserverclient/exponential_backoff.py,sha256=HtAfbbVnYtiOe2_ZzKqZmsml40EDZBaC3bttif5qeG8,1474
@@ -7,58 +7,58 @@ tableauserverclient/filesys_helpers.py,sha256=hosTm9fpc9B9_VCDcAuyHA0A-f-MWs9_2u
7
7
  tableauserverclient/namespace.py,sha256=i0o0T0xO0vd1RX98o54xmIrqCkeVfhtQOGDMGRx_F_o,971
8
8
  tableauserverclient/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
9
  tableauserverclient/helpers/__init__.py,sha256=llpqF9zV5dsP5hQt8dyop33Op5OzGmxW0BZibaSlCcM,23
10
- tableauserverclient/helpers/logging.py,sha256=kDXxtuU8TFOtvSQnErAsEckT5Mmiftx48x7L1Nos25w,187
10
+ tableauserverclient/helpers/logging.py,sha256=5q_oR3wERHVXFXY6XDnLYML5-HdAPJTmqhH9IZg4VfY,113
11
11
  tableauserverclient/helpers/strings.py,sha256=dnfm_2s75WvXnkcU8JFGRlLbSZdarRPyHpRYOi19APs,1682
12
- tableauserverclient/models/__init__.py,sha256=jAjXNMIPLV9gZho5LRT1BzKmR3IMnGz8-bnj5CWEW9Q,1611
13
- tableauserverclient/models/column_item.py,sha256=H-SaHQuSgW4VQmB2IYlJbG-uHGXIoCykBLkNfytRbTM,1859
14
- tableauserverclient/models/connection_credentials.py,sha256=hMrlfInBu35t5IMZMXiLjSvJIAPZKB8BS7XuzdVClzk,1317
12
+ tableauserverclient/models/__init__.py,sha256=NfVfRDeU8b6zTQ7wzkorhvuGIPabym8lXvNiyEX_AVg,1620
13
+ tableauserverclient/models/column_item.py,sha256=gV2r7xOVmcn9UnMXFOe9_ORZ85oha1KtIH-crKUhgN4,1972
14
+ tableauserverclient/models/connection_credentials.py,sha256=8Wa8B_-cB3INFUup-Pyd5znsUD5opgYYH5TfipCzKTU,1559
15
15
  tableauserverclient/models/connection_item.py,sha256=BiLrjWY42EtkAyh2_3juo31rYW9YZN1e3uOXMXIaslY,4743
16
- tableauserverclient/models/custom_view_item.py,sha256=GpCWN87-9S6c2Tpg5JYCL7ZU2DvsOOFL3WMw6gh_0no,5613
17
- tableauserverclient/models/data_acceleration_report_item.py,sha256=QKdxbTla8FudecIX7w74bV9QyEDc-L1F5YkUk2-DopQ,3283
16
+ tableauserverclient/models/custom_view_item.py,sha256=Gr2lYgBU1zUfCoaXHhqTzWDspmL33UqOxlt48Y8yaGg,5782
17
+ tableauserverclient/models/data_acceleration_report_item.py,sha256=5Z18-fppR_lnAyPKHwxi4gOP6kqcYX3Q3RdwiD4Zy94,3402
18
18
  tableauserverclient/models/data_alert_item.py,sha256=sJpncsKY1BY-tFJKDpX7xaHy6aGvELWrorsILJxr3lI,6458
19
19
  tableauserverclient/models/database_item.py,sha256=SAwoxsgeowwFN20zGt3-226kJabk0M2tqbVLQthvmRs,8043
20
- tableauserverclient/models/datasource_item.py,sha256=JYx4BYVhFAgZtVlfU5L-c2UGXOE7IqshEnD48intvgs,12527
20
+ tableauserverclient/models/datasource_item.py,sha256=ZZZvYfzg6gD7DlZWzfEJ3VBQBMYADJ9GeoWV02F7Z8E,11944
21
21
  tableauserverclient/models/dqw_item.py,sha256=MFpxSP6vSzpjh5GLNrom--Sbi8iLwuGLuAda8KHiIa8,3718
22
22
  tableauserverclient/models/exceptions.py,sha256=pQu5DS4jNMT9A0wEBWv2vANAQU1vgNpFatVr8sGE4zk,105
23
23
  tableauserverclient/models/favorites_item.py,sha256=AfQOraRaZ_c2lY9XzxOeeg0N89WHOOYW3CREsCuACNs,3140
24
24
  tableauserverclient/models/fileupload_item.py,sha256=tx3LfgRxVqeHGpCN6kTDPkdBY5i1H-u1RVaPf0hQx_4,750
25
25
  tableauserverclient/models/flow_item.py,sha256=rPIVDe8_tHied8TDRiGpg2gyTyQWlNiGb3vGhqF9YJw,7320
26
26
  tableauserverclient/models/flow_run_item.py,sha256=pwJNz0m7l--Sb6z0o83ebWfAmTVFYSr-0apMxHWt0Vs,3139
27
- tableauserverclient/models/group_item.py,sha256=pILM_5gFQL_KNu4eIc-pHaYkVC967usdltBm9nyLvjQ,3668
28
- tableauserverclient/models/interval_item.py,sha256=uXIQX8xzjvsdoKneW1Az2KurLPx1BoRmSR-yh5wg3Vg,5247
29
- tableauserverclient/models/job_item.py,sha256=oDQQwNezb7AnzisaGYi0kcGNtsuq1_6Nh4IbUrsb91U,8264
30
- tableauserverclient/models/metric_item.py,sha256=PsY3-Tl31x-i0hh-eacfBbJjkAdmZKe28ZGLoMQfY1w,5265
31
- tableauserverclient/models/pagination_item.py,sha256=Uo2fem9I_yvyTWWMZy9UYQWyhKX5pGxAp3C2ghmDSVo,1282
32
- tableauserverclient/models/permissions_item.py,sha256=NVG8f_osa4Dy58J2VK2jJvneb1F6BLhLf7j0ULu2Iao,3561
33
- tableauserverclient/models/project_item.py,sha256=ctrHEqRqSBJivudh_mrFzqcwevWHCgBOWkcVbjqIMLU,6968
27
+ tableauserverclient/models/group_item.py,sha256=1KP_KmIG1veJJGyte82aFvMAiU_tvzYtaP2vLEReLoo,3621
28
+ tableauserverclient/models/interval_item.py,sha256=h0mAFnR3rOj9nNOT237sPHQrdkN3NyonnGX10Chbx9k,5747
29
+ tableauserverclient/models/job_item.py,sha256=PMt7G2qu8WAxe-b3f_0BtQ9JcCSvk-g5L5EcOUpYFCY,8619
30
+ tableauserverclient/models/metric_item.py,sha256=Zrzi_Un43p2jzE_4OhetxhjfeSUYzotMfm8Hjd5WOhI,5397
31
+ tableauserverclient/models/pagination_item.py,sha256=Hdr2EIKWkXfrjWOr-Ao_vzQTWB2akUfxxtaupFKLrlQ,1432
32
+ tableauserverclient/models/permissions_item.py,sha256=2WlJOc1Vxkxl-WnAkFaacWsGxUXU9_d85AetSKrKwP0,3731
33
+ tableauserverclient/models/project_item.py,sha256=Mf5maEdKJqk5ojhT_DNmLqL50Ib6u1OKYEDq0oJpeGs,7056
34
34
  tableauserverclient/models/property_decorators.py,sha256=eXaYxzXYuHdftlcnqSQOzHYM7OAilETWK8Td2Dtmmuc,4726
35
35
  tableauserverclient/models/reference_item.py,sha256=HddG1loGNJU7gB7hBccCjnhagnSEbk4_wY2kuPbNhRQ,534
36
36
  tableauserverclient/models/revision_item.py,sha256=fLkcScAgBBiVMCyDPk4aboyZNxrykIavzJP2vkn6Rq0,2787
37
- tableauserverclient/models/schedule_item.py,sha256=irbbUm41mB2hAYJWU0YjdXLEXQWtbDUSHQ_d8nR-qw4,10514
38
- tableauserverclient/models/server_info_item.py,sha256=cCLzndio9si_FIv-0ujvVQjsMLhBbf6G3Nt_rZAHTFA,1879
39
- tableauserverclient/models/site_item.py,sha256=-b5o40xBSeY7pRQ3ANkpCex8SFBa0oYDkr6bDzFRfxk,42123
40
- tableauserverclient/models/subscription_item.py,sha256=E0jHnaRe9GG_a5Gcaq7ATuZJlM5C5h_-rhVaL9HbE_0,4421
41
- tableauserverclient/models/table_item.py,sha256=YWnjMOMLOCsi_BnCQfJLTkPmA5TfracWkGjpvWhLPzE,4355
42
- tableauserverclient/models/tableau_auth.py,sha256=t-Ocn3R8azPlrBVPYmG-5VTlC1qODMd1KUpWgGLwtLs,2512
37
+ tableauserverclient/models/schedule_item.py,sha256=AmodNmh9iKdlGzyEm0pRjdy8-yFSXsIe7xf0Y6oVFVc,10569
38
+ tableauserverclient/models/server_info_item.py,sha256=pR_fqqPuiBwpLn0wr4rQ4vxK7gxGJVTtaswzwjslheE,1880
39
+ tableauserverclient/models/site_item.py,sha256=xvXpsR0eEz2ypS-94KJTMS-gusHV1bLomKIhWX7GXrU,42256
40
+ tableauserverclient/models/subscription_item.py,sha256=XkQiAi_gWPBnxtTaB8TgrFa-IDVDtai9H00Ilay0T64,4744
41
+ tableauserverclient/models/table_item.py,sha256=WgXrHCgmA5djpA7k2tNuZ8A3PPK6GEKfj9RQZ27RsNk,4583
42
+ tableauserverclient/models/tableau_auth.py,sha256=TdkOtRnNRi4p0w_WhBsWqUunNVG9nxKl6NPO2AQ08zU,3723
43
43
  tableauserverclient/models/tableau_types.py,sha256=1iq1034K1W9ugLAxON_t8n2UxSouiWV_ZEwoHiNM94c,918
44
44
  tableauserverclient/models/tag_item.py,sha256=mVfJGZG8PspPM8hBxX38heEQ_Rnp5sSwfwWdLNA-UV0,619
45
45
  tableauserverclient/models/target.py,sha256=dVc1SHwo9ZASR8250MhAPODXX_G5UqA4BnK8hykRE6E,263
46
46
  tableauserverclient/models/task_item.py,sha256=0DSOZ3aQ6nppD-zVeeK-GKdAxLE0-d-sSazXs7ybH6Q,3466
47
- tableauserverclient/models/user_item.py,sha256=3XJwoRPTTiuJnU7XeaFiUumURWByLBxdGaLeBLKSnjY,15644
48
- tableauserverclient/models/view_item.py,sha256=Q9j8AW_1SlCrMGOs6-H5zwMDrjqSdQlVj7s36AhaxwE,6645
47
+ tableauserverclient/models/user_item.py,sha256=vaQD3nvU7bJVD6t0nkWQFse8UDz8HTp8wh_6WmCjKtM,15776
48
+ tableauserverclient/models/view_item.py,sha256=7OLTLpLXDiYAWi7Tc6vSCkh2Krl7-cvKUwA7iMWZspQ,6777
49
49
  tableauserverclient/models/webhook_item.py,sha256=LLf2HQ2Y50Rw-c4dSYyv6MXLbXdij9Iyy261gu9zpv4,2650
50
- tableauserverclient/models/workbook_item.py,sha256=aZKl4pgVYA9A7JCyagfYxgLx0HLe0VcohkaXMbBVmXQ,12842
50
+ tableauserverclient/models/workbook_item.py,sha256=x-qRFLAkVKQzd-PFYTkfuzYBkMcW3EOvc6Zx-iVWa3U,12974
51
51
  tableauserverclient/server/__init__.py,sha256=ZyvucBvBQMPyTVW7oDHl4W9NWuaSVSMfN9cTcSQRmKw,406
52
52
  tableauserverclient/server/exceptions.py,sha256=l-O4lcoEeXJC7fLWUanIcZM_Mf8m54uK3NQuKNj3RCg,183
53
- tableauserverclient/server/filter.py,sha256=A1qPQwLPt-Ehq7I5jDIQHJMqf3_dKn_wJg5qhMkCQIQ,864
53
+ tableauserverclient/server/filter.py,sha256=WZ_dIBuADRZf8VTYcRgn1rulSGUOJq8_uUltq05KkRI,1119
54
54
  tableauserverclient/server/pager.py,sha256=rd6rKkoTxP0u3RiOZ3HY9oWKyOcf8aowbHPcs-Ul4D0,2725
55
55
  tableauserverclient/server/query.py,sha256=qMweo-N5P_V9z2Or4u_QrStaBbGL6HOg4Y4EDg8uh44,5735
56
- tableauserverclient/server/request_factory.py,sha256=W-gMLN715lb0BE_2bPrdcd4ASrCXPVVPum30BHmVAJg,57758
57
- tableauserverclient/server/request_options.py,sha256=d4yTM-KU3wY2AbAgZLUTlBJpLtJklACT8oO8u-hpcsE,7063
56
+ tableauserverclient/server/request_factory.py,sha256=u8h2EtGKBAN5ELR9Cg_v3bSKvRsMmy4IXVkYp4OZqzQ,59190
57
+ tableauserverclient/server/request_options.py,sha256=xilsnYTsNObCZfwB5ydfzYq7XBkhpvIMWHM67yWQSKY,7105
58
58
  tableauserverclient/server/server.py,sha256=LhbQOk-lvIBAOF5tTAghYNPFsKJN4Z95SJbuHLAxdKo,8401
59
59
  tableauserverclient/server/sort.py,sha256=ikndqXW2r2FeacJzybC2TVcJGn4ktviWgXwPyK-AX-0,208
60
60
  tableauserverclient/server/endpoint/__init__.py,sha256=9KGDtgBWlWsWbBQvQV2cbIU-VmHmMqcgtSM7PonpIzg,1141
61
- tableauserverclient/server/endpoint/auth_endpoint.py,sha256=sCHXvlHzvGMSzILxzGZH62Ihnoh5sa8cIM8CcAU9ZBY,4111
61
+ tableauserverclient/server/endpoint/auth_endpoint.py,sha256=EOGGlGHWUZRN0SFBlYnEWUSwCH1lrB0Zfv4VWdd7HQs,5139
62
62
  tableauserverclient/server/endpoint/custom_views_endpoint.py,sha256=SShsI8TnDe3tPXCrCsjs3Oy5Ym4j-QrcDXUfZ7rF9Y4,4542
63
63
  tableauserverclient/server/endpoint/data_acceleration_report_endpoint.py,sha256=nfC2gXoCke-YXGTiMWGDRBK_lDlLa9Y6hts7w3Zs8cI,1170
64
64
  tableauserverclient/server/endpoint/data_alert_endpoint.py,sha256=c6-ICGRVDRQN7ClAgCeJsk6JK4HyBvtQGQVLOzNc4eo,5358
@@ -68,30 +68,30 @@ tableauserverclient/server/endpoint/default_permissions_endpoint.py,sha256=HQSYP
68
68
  tableauserverclient/server/endpoint/dqw_endpoint.py,sha256=TvzjonvIiGtp4EisoBKms1lHOkVTjagQACw6unyY9_8,2418
69
69
  tableauserverclient/server/endpoint/endpoint.py,sha256=IZtHZia7aSr2sc1iV8bdtg39kX-IBDsXLoAxKa3y5v8,14425
70
70
  tableauserverclient/server/endpoint/exceptions.py,sha256=fh4fFYasqiKd3EPTxriVsmLkRL24wz9UvX94BMRfyLY,2534
71
- tableauserverclient/server/endpoint/favorites_endpoint.py,sha256=Yujl6f3jvYRlTc5-kvU37JQDEH6gvXWZ116PmDqmpWg,6702
71
+ tableauserverclient/server/endpoint/favorites_endpoint.py,sha256=D0MCco9kxaeCShfWOnVt3UpttJRgczJmJKXb3w0jpw4,6701
72
72
  tableauserverclient/server/endpoint/fileuploads_endpoint.py,sha256=fh2xH6a8mMcBI14QzodWPBMabK1_9SMDbzZbawz-ZJc,2553
73
73
  tableauserverclient/server/endpoint/flow_runs_endpoint.py,sha256=1vwkOrb574natWl-njFOij8xaV32e9RU3-rFbu4bML0,3338
74
74
  tableauserverclient/server/endpoint/flows_endpoint.py,sha256=97S15UatgSzdw22Q5ZfhtlVVTvahp7fAtrXt7L28OWg,12898
75
- tableauserverclient/server/endpoint/groups_endpoint.py,sha256=aKKb3cNmbZcvGdrYw2ZdwrkuNud0C2v5DBeRXc-E-uY,6570
75
+ tableauserverclient/server/endpoint/groups_endpoint.py,sha256=_aSTVy7m3NXSEqgC0cPfJt6KOaPoWprxzz0MD8CsiiY,6640
76
76
  tableauserverclient/server/endpoint/jobs_endpoint.py,sha256=P5Hdv1hsNVxd5KdrcNCfR9ZtJ7v3UgrfATCBItVdAxY,3239
77
77
  tableauserverclient/server/endpoint/metadata_endpoint.py,sha256=AKnmRNj9U85p__igiuY_vhhipsxNXpQ_9zzNUtTuU9o,5203
78
78
  tableauserverclient/server/endpoint/metrics_endpoint.py,sha256=pW7ZOmRrsk_d1afITrQKhYdDDo3zqw1Vq-FnhBnSM24,3264
79
79
  tableauserverclient/server/endpoint/permissions_endpoint.py,sha256=K-AZ1VPTHfiuyEwLo4qQLVTacwYFgNEGrYpCtgO9nmY,3879
80
- tableauserverclient/server/endpoint/projects_endpoint.py,sha256=92bFqlsCgUkqcR6PaMszIhFdflNDnHnj_1JbN7fIg60,7202
80
+ tableauserverclient/server/endpoint/projects_endpoint.py,sha256=cbW-VTtrG1dt2kQy5vGCmurB8w3ethuNQvyaWViSpIE,7323
81
81
  tableauserverclient/server/endpoint/resource_tagger.py,sha256=NJ64WySE7RWIR3JNltyWbErwwdaw9L_Wi7TLWdNas_4,2248
82
82
  tableauserverclient/server/endpoint/schedules_endpoint.py,sha256=VKlAqTqMtxkvkG2UgZQ6VrBkiAgpjgffRZFzdzV9LtM,6462
83
83
  tableauserverclient/server/endpoint/server_info_endpoint.py,sha256=4TtCc7oIp6iEuiZYGC_1NDIBsWetKk7b0rNemoA2VXI,1453
84
84
  tableauserverclient/server/endpoint/sites_endpoint.py,sha256=lMeVXxm1k32HZK84u7aTys9hUQekb4PE1hlhKFxaZ8c,6694
85
85
  tableauserverclient/server/endpoint/subscriptions_endpoint.py,sha256=mMo9M6DF6tAZIab6UY8f_duETezELl9VXEYs5ocAcGY,3280
86
86
  tableauserverclient/server/endpoint/tables_endpoint.py,sha256=OJQIarL-IC9mjeu1jfNh9B3UEkB41O51Q53TQNeSJ78,5376
87
- tableauserverclient/server/endpoint/tasks_endpoint.py,sha256=D4USE9nwhCqYZnCIiaQp_8yrXUf3Enl-qJd8I_yNsUk,3154
87
+ tableauserverclient/server/endpoint/tasks_endpoint.py,sha256=jHz-d3q-hoxmv9Xg2qPAOzAz9mv0ahHtPSW8IXon0sw,3707
88
88
  tableauserverclient/server/endpoint/users_endpoint.py,sha256=QRoApMyP53nF-AqvC7oLHNcT4VJE8s5ykjUnI5ojmPY,7274
89
89
  tableauserverclient/server/endpoint/views_endpoint.py,sha256=GIYPftL5B0YUOb_SisFtfLP0LPIAbbUv24XCi15UH_M,7118
90
90
  tableauserverclient/server/endpoint/webhooks_endpoint.py,sha256=-HsbAuKECNcx5EZkqp097PfGHLCNwPRnxbrdzreTpnM,2835
91
91
  tableauserverclient/server/endpoint/workbooks_endpoint.py,sha256=65Zv-b0yd4yuh1JAoqbhNlEJM6k2LD6nh1nPQGTdKRc,21734
92
- tableauserverclient-0.26.dist-info/LICENSE,sha256=MMkY7MguOb4L-WCmmqrVcwg2iwSGaz-RfAMFvXRXwsQ,1074
93
- tableauserverclient-0.26.dist-info/LICENSE.versioneer,sha256=OYaGozOXk7bUNSm1z577iDYpti8a40XIqqR4lyQ47D8,334
94
- tableauserverclient-0.26.dist-info/METADATA,sha256=rl61Tr4pdH6vV2GmpvYvAV-H9ENbfcVrUqQF-56F8aM,3977
95
- tableauserverclient-0.26.dist-info/WHEEL,sha256=pkctZYzUS4AYVn6dJ-7367OJZivF2e8RA9b_ZBjif18,92
96
- tableauserverclient-0.26.dist-info/top_level.txt,sha256=kBnL39G2RlGqxJSsShDBWG4WZ3NFcWJkv1EGiOfZh4Q,20
97
- tableauserverclient-0.26.dist-info/RECORD,,
92
+ tableauserverclient-0.28.dist-info/LICENSE,sha256=MMkY7MguOb4L-WCmmqrVcwg2iwSGaz-RfAMFvXRXwsQ,1074
93
+ tableauserverclient-0.28.dist-info/LICENSE.versioneer,sha256=OYaGozOXk7bUNSm1z577iDYpti8a40XIqqR4lyQ47D8,334
94
+ tableauserverclient-0.28.dist-info/METADATA,sha256=0oM0-poO__vHSlu02Lfa93Lv8lRqYsNn5RI5B6UIRvI,4073
95
+ tableauserverclient-0.28.dist-info/WHEEL,sha256=yQN5g4mg4AybRjkgi-9yy4iQEFibGQmlz78Pik5Or-A,92
96
+ tableauserverclient-0.28.dist-info/top_level.txt,sha256=kBnL39G2RlGqxJSsShDBWG4WZ3NFcWJkv1EGiOfZh4Q,20
97
+ tableauserverclient-0.28.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.40.0)
2
+ Generator: bdist_wheel (0.41.2)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5