tableauserverclient 0.33__py3-none-any.whl → 0.35__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (94) hide show
  1. tableauserverclient/__init__.py +33 -23
  2. tableauserverclient/{_version.py → bin/_version.py} +3 -3
  3. tableauserverclient/config.py +5 -3
  4. tableauserverclient/models/column_item.py +1 -1
  5. tableauserverclient/models/connection_credentials.py +18 -2
  6. tableauserverclient/models/connection_item.py +44 -6
  7. tableauserverclient/models/custom_view_item.py +78 -11
  8. tableauserverclient/models/data_acceleration_report_item.py +2 -2
  9. tableauserverclient/models/data_alert_item.py +5 -5
  10. tableauserverclient/models/data_freshness_policy_item.py +6 -6
  11. tableauserverclient/models/database_item.py +3 -3
  12. tableauserverclient/models/datasource_item.py +10 -10
  13. tableauserverclient/models/dqw_item.py +1 -1
  14. tableauserverclient/models/favorites_item.py +5 -6
  15. tableauserverclient/models/fileupload_item.py +1 -1
  16. tableauserverclient/models/flow_item.py +54 -9
  17. tableauserverclient/models/flow_run_item.py +3 -3
  18. tableauserverclient/models/group_item.py +44 -4
  19. tableauserverclient/models/groupset_item.py +4 -4
  20. tableauserverclient/models/interval_item.py +9 -9
  21. tableauserverclient/models/job_item.py +73 -8
  22. tableauserverclient/models/linked_tasks_item.py +5 -5
  23. tableauserverclient/models/metric_item.py +5 -5
  24. tableauserverclient/models/pagination_item.py +1 -1
  25. tableauserverclient/models/permissions_item.py +12 -10
  26. tableauserverclient/models/project_item.py +73 -19
  27. tableauserverclient/models/property_decorators.py +12 -11
  28. tableauserverclient/models/reference_item.py +2 -2
  29. tableauserverclient/models/revision_item.py +3 -3
  30. tableauserverclient/models/schedule_item.py +2 -2
  31. tableauserverclient/models/server_info_item.py +26 -6
  32. tableauserverclient/models/site_item.py +69 -3
  33. tableauserverclient/models/subscription_item.py +3 -3
  34. tableauserverclient/models/table_item.py +1 -1
  35. tableauserverclient/models/tableau_auth.py +115 -5
  36. tableauserverclient/models/tableau_types.py +2 -2
  37. tableauserverclient/models/tag_item.py +3 -4
  38. tableauserverclient/models/task_item.py +34 -4
  39. tableauserverclient/models/user_item.py +47 -17
  40. tableauserverclient/models/view_item.py +66 -13
  41. tableauserverclient/models/virtual_connection_item.py +6 -5
  42. tableauserverclient/models/webhook_item.py +39 -6
  43. tableauserverclient/models/workbook_item.py +116 -13
  44. tableauserverclient/namespace.py +1 -1
  45. tableauserverclient/server/__init__.py +2 -1
  46. tableauserverclient/server/endpoint/auth_endpoint.py +69 -10
  47. tableauserverclient/server/endpoint/custom_views_endpoint.py +258 -29
  48. tableauserverclient/server/endpoint/data_acceleration_report_endpoint.py +2 -2
  49. tableauserverclient/server/endpoint/data_alert_endpoint.py +14 -14
  50. tableauserverclient/server/endpoint/databases_endpoint.py +13 -12
  51. tableauserverclient/server/endpoint/datasources_endpoint.py +61 -62
  52. tableauserverclient/server/endpoint/default_permissions_endpoint.py +19 -18
  53. tableauserverclient/server/endpoint/dqw_endpoint.py +9 -9
  54. tableauserverclient/server/endpoint/endpoint.py +19 -21
  55. tableauserverclient/server/endpoint/exceptions.py +23 -7
  56. tableauserverclient/server/endpoint/favorites_endpoint.py +31 -31
  57. tableauserverclient/server/endpoint/fileuploads_endpoint.py +9 -11
  58. tableauserverclient/server/endpoint/flow_runs_endpoint.py +15 -13
  59. tableauserverclient/server/endpoint/flow_task_endpoint.py +2 -2
  60. tableauserverclient/server/endpoint/flows_endpoint.py +344 -29
  61. tableauserverclient/server/endpoint/groups_endpoint.py +342 -27
  62. tableauserverclient/server/endpoint/groupsets_endpoint.py +2 -2
  63. tableauserverclient/server/endpoint/jobs_endpoint.py +116 -7
  64. tableauserverclient/server/endpoint/linked_tasks_endpoint.py +2 -2
  65. tableauserverclient/server/endpoint/metadata_endpoint.py +2 -2
  66. tableauserverclient/server/endpoint/metrics_endpoint.py +10 -10
  67. tableauserverclient/server/endpoint/permissions_endpoint.py +13 -15
  68. tableauserverclient/server/endpoint/projects_endpoint.py +681 -30
  69. tableauserverclient/server/endpoint/resource_tagger.py +14 -13
  70. tableauserverclient/server/endpoint/schedules_endpoint.py +17 -18
  71. tableauserverclient/server/endpoint/server_info_endpoint.py +40 -5
  72. tableauserverclient/server/endpoint/sites_endpoint.py +282 -17
  73. tableauserverclient/server/endpoint/subscriptions_endpoint.py +10 -10
  74. tableauserverclient/server/endpoint/tables_endpoint.py +15 -14
  75. tableauserverclient/server/endpoint/tasks_endpoint.py +86 -8
  76. tableauserverclient/server/endpoint/users_endpoint.py +366 -19
  77. tableauserverclient/server/endpoint/views_endpoint.py +262 -20
  78. tableauserverclient/server/endpoint/virtual_connections_endpoint.py +6 -5
  79. tableauserverclient/server/endpoint/webhooks_endpoint.py +88 -11
  80. tableauserverclient/server/endpoint/workbooks_endpoint.py +653 -65
  81. tableauserverclient/server/filter.py +2 -2
  82. tableauserverclient/server/pager.py +29 -6
  83. tableauserverclient/server/query.py +68 -19
  84. tableauserverclient/server/request_factory.py +57 -37
  85. tableauserverclient/server/request_options.py +243 -141
  86. tableauserverclient/server/server.py +76 -10
  87. tableauserverclient/server/sort.py +16 -2
  88. {tableauserverclient-0.33.dist-info → tableauserverclient-0.35.dist-info}/METADATA +7 -7
  89. tableauserverclient-0.35.dist-info/RECORD +106 -0
  90. {tableauserverclient-0.33.dist-info → tableauserverclient-0.35.dist-info}/WHEEL +1 -1
  91. tableauserverclient-0.33.dist-info/RECORD +0 -106
  92. {tableauserverclient-0.33.dist-info → tableauserverclient-0.35.dist-info}/LICENSE +0 -0
  93. {tableauserverclient-0.33.dist-info → tableauserverclient-0.35.dist-info}/LICENSE.versioneer +0 -0
  94. {tableauserverclient-0.33.dist-info → tableauserverclient-0.35.dist-info}/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  import logging
2
2
  import xml.etree.ElementTree as ET
3
- from typing import List, Optional
3
+ from typing import Optional
4
4
 
5
5
  from defusedxml.ElementTree import fromstring
6
6
 
@@ -8,14 +8,54 @@ from tableauserverclient.models.exceptions import UnpopulatedPropertyError
8
8
  from tableauserverclient.models.property_decorators import property_is_enum, property_not_empty
9
9
 
10
10
 
11
- class ProjectItem(object):
11
+ class ProjectItem:
12
+ """
13
+ The project resources for Tableau are defined in the ProjectItem class. The
14
+ class corresponds to the project resources you can access using the Tableau
15
+ Server REST API.
16
+
17
+ Parameters
18
+ ----------
19
+ name : str
20
+ Name of the project.
21
+
22
+ description : str
23
+ Description of the project.
24
+
25
+ content_permissions : str
26
+ Sets or shows the permissions for the content in the project. The
27
+ options are either LockedToProject, ManagedByOwner or
28
+ LockedToProjectWithoutNested.
29
+
30
+ parent_id : str
31
+ The id of the parent project. Use this option to create project
32
+ hierarchies. For information about managing projects, project
33
+ hierarchies, and permissions, see
34
+ https://help.tableau.com/current/server/en-us/projects.htm
35
+
36
+ samples : bool
37
+ Set to True to include sample workbooks and data sources in the
38
+ project. The default is False.
39
+
40
+ Attributes
41
+ ----------
42
+ id : str
43
+ The unique identifier for the project.
44
+
45
+ owner_id : str
46
+ The unique identifier for the UserItem owner of the project.
47
+
48
+ """
49
+
50
+ ERROR_MSG = "Project item must be populated with permissions first."
51
+
12
52
  class ContentPermissions:
13
53
  LockedToProject: str = "LockedToProject"
14
54
  ManagedByOwner: str = "ManagedByOwner"
15
55
  LockedToProjectWithoutNested: str = "LockedToProjectWithoutNested"
16
56
 
17
57
  def __repr__(self):
18
- return "<Project {0} {1} parent={2} permissions={3}>".format(
58
+ return "<Project {} {} parent={} permissions={}>".format(
19
59
  self._id, self.name, self.parent_id or "None (Top level)", self.content_permissions or "Not Set"
20
60
  )
21
61
 
@@ -43,6 +83,9 @@ class ProjectItem(object):
43
83
  self._default_lens_permissions = None
44
84
  self._default_datarole_permissions = None
45
85
  self._default_metric_permissions = None
86
+ self._default_virtualconnection_permissions = None
87
+ self._default_database_permissions = None
88
+ self._default_table_permissions = None
46
89
 
47
90
  @property
48
91
  def content_permissions(self):
@@ -56,52 +99,63 @@ class ProjectItem(object):
56
99
  @property
57
100
  def permissions(self):
58
101
  if self._permissions is None:
59
- error = "Project item must be populated with permissions first."
60
- raise UnpopulatedPropertyError(error)
102
+ raise UnpopulatedPropertyError(self.ERROR_MSG)
61
103
  return self._permissions()
62
104
 
63
105
  @property
64
106
  def default_datasource_permissions(self):
65
107
  if self._default_datasource_permissions is None:
66
- error = "Project item must be populated with permissions first."
67
- raise UnpopulatedPropertyError(error)
108
+ raise UnpopulatedPropertyError(self.ERROR_MSG)
68
109
  return self._default_datasource_permissions()
69
110
 
70
111
  @property
71
112
  def default_workbook_permissions(self):
72
113
  if self._default_workbook_permissions is None:
73
- error = "Project item must be populated with permissions first."
74
- raise UnpopulatedPropertyError(error)
114
+ raise UnpopulatedPropertyError(self.ERROR_MSG)
75
115
  return self._default_workbook_permissions()
76
116
 
77
117
  @property
78
118
  def default_flow_permissions(self):
79
119
  if self._default_flow_permissions is None:
80
- error = "Project item must be populated with permissions first."
81
- raise UnpopulatedPropertyError(error)
120
+ raise UnpopulatedPropertyError(self.ERROR_MSG)
82
121
  return self._default_flow_permissions()
83
122
 
84
123
  @property
85
124
  def default_lens_permissions(self):
86
125
  if self._default_lens_permissions is None:
87
- error = "Project item must be populated with permissions first."
88
- raise UnpopulatedPropertyError(error)
126
+ raise UnpopulatedPropertyError(self.ERROR_MSG)
89
127
  return self._default_lens_permissions()
90
128
 
91
129
  @property
92
130
  def default_datarole_permissions(self):
93
131
  if self._default_datarole_permissions is None:
94
- error = "Project item must be populated with permissions first."
95
- raise UnpopulatedPropertyError(error)
132
+ raise UnpopulatedPropertyError(self.ERROR_MSG)
96
133
  return self._default_datarole_permissions()
97
134
 
98
135
  @property
99
136
  def default_metric_permissions(self):
100
137
  if self._default_metric_permissions is None:
101
- error = "Project item must be populated with permissions first."
102
- raise UnpopulatedPropertyError(error)
138
+ raise UnpopulatedPropertyError(self.ERROR_MSG)
103
139
  return self._default_metric_permissions()
104
140
 
141
+ @property
142
+ def default_virtualconnection_permissions(self):
143
+ if self._default_virtualconnection_permissions is None:
144
+ raise UnpopulatedPropertyError(self.ERROR_MSG)
145
+ return self._default_virtualconnection_permissions()
146
+
147
+ @property
148
+ def default_database_permissions(self):
149
+ if self._default_database_permissions is None:
150
+ raise UnpopulatedPropertyError(self.ERROR_MSG)
151
+ return self._default_database_permissions()
152
+
153
+ @property
154
+ def default_table_permissions(self):
155
+ if self._default_table_permissions is None:
156
+ raise UnpopulatedPropertyError(self.ERROR_MSG)
157
+ return self._default_table_permissions()
158
+
105
159
  @property
106
160
  def id(self) -> Optional[str]:
107
161
  return self._id
@@ -158,7 +212,7 @@ class ProjectItem(object):
158
212
  self._permissions = permissions
159
213
 
160
214
  def _set_default_permissions(self, permissions, content_type):
161
- attr = "_default_{content}_permissions".format(content=content_type)
215
+ attr = f"_default_{content_type}_permissions".lower()
162
216
  setattr(
163
217
  self,
164
218
  attr,
@@ -166,7 +220,7 @@ class ProjectItem(object):
166
220
  )
167
221
 
168
222
  @classmethod
169
- def from_response(cls, resp, ns) -> List["ProjectItem"]:
223
+ def from_response(cls, resp, ns) -> list["ProjectItem"]:
170
224
  all_project_items = list()
171
225
  parsed_response = fromstring(resp)
172
226
  all_project_xml = parsed_response.findall(".//t:project", namespaces=ns)
@@ -1,7 +1,8 @@
1
1
  import datetime
2
2
  import re
3
3
  from functools import wraps
4
- from typing import Any, Container, Optional, Tuple
4
+ from typing import Any, Optional
5
+ from collections.abc import Container
5
6
 
6
7
  from tableauserverclient.datetime_helpers import parse_datetime
7
8
 
@@ -11,7 +12,7 @@ def property_is_enum(enum_type):
11
12
  @wraps(func)
12
13
  def wrapper(self, value):
13
14
  if value is not None and not hasattr(enum_type, value):
14
- error = "Invalid value: {0}. {1} must be of type {2}.".format(value, func.__name__, enum_type.__name__)
15
+ error = f"Invalid value: {value}. {func.__name__} must be of type {enum_type.__name__}."
15
16
  raise ValueError(error)
16
17
  return func(self, value)
17
18
 
@@ -24,7 +25,7 @@ def property_is_boolean(func):
24
25
  @wraps(func)
25
26
  def wrapper(self, value):
26
27
  if not isinstance(value, bool):
27
- error = "Boolean expected for {0} flag.".format(func.__name__)
28
+ error = f"Boolean expected for {func.__name__} flag."
28
29
  raise ValueError(error)
29
30
  return func(self, value)
30
31
 
@@ -35,7 +36,7 @@ def property_not_nullable(func):
35
36
  @wraps(func)
36
37
  def wrapper(self, value):
37
38
  if value is None:
38
- error = "{0} must be defined.".format(func.__name__)
39
+ error = f"{func.__name__} must be defined."
39
40
  raise ValueError(error)
40
41
  return func(self, value)
41
42
 
@@ -46,7 +47,7 @@ def property_not_empty(func):
46
47
  @wraps(func)
47
48
  def wrapper(self, value):
48
49
  if not value:
49
- error = "{0} must not be empty.".format(func.__name__)
50
+ error = f"{func.__name__} must not be empty."
50
51
  raise ValueError(error)
51
52
  return func(self, value)
52
53
 
@@ -66,7 +67,7 @@ def property_is_valid_time(func):
66
67
  return wrapper
67
68
 
68
69
 
69
- def property_is_int(range: Tuple[int, int], allowed: Optional[Container[Any]] = None):
70
+ def property_is_int(range: tuple[int, int], allowed: Optional[Container[Any]] = None):
70
71
  """Takes a range of ints and a list of exemptions to check against
71
72
  when setting a property on a model. The range is a tuple of (min, max) and the
72
73
  allowed list (empty by default) allows values outside that range.
@@ -81,7 +82,7 @@ def property_is_int(range: Tuple[int, int], allowed: Optional[Container[Any]] =
81
82
  def property_type_decorator(func):
82
83
  @wraps(func)
83
84
  def wrapper(self, value):
84
- error = "Invalid property defined: '{}'. Integer value expected.".format(value)
85
+ error = f"Invalid property defined: '{value}'. Integer value expected."
85
86
 
86
87
  if range is None:
87
88
  if isinstance(value, int):
@@ -133,7 +134,7 @@ def property_is_datetime(func):
133
134
  return func(self, value)
134
135
  if not isinstance(value, str):
135
136
  raise ValueError(
136
- "Cannot convert {} into a datetime, cannot update {}".format(value.__class__.__name__, func.__name__)
137
+ f"Cannot convert {value.__class__.__name__} into a datetime, cannot update {func.__name__}"
137
138
  )
138
139
 
139
140
  dt = parse_datetime(value)
@@ -146,11 +147,11 @@ def property_is_data_acceleration_config(func):
146
147
  @wraps(func)
147
148
  def wrapper(self, value):
148
149
  if not isinstance(value, dict):
149
- raise ValueError("{} is not type 'dict', cannot update {})".format(value.__class__.__name__, func.__name__))
150
+ raise ValueError(f"{value.__class__.__name__} is not type 'dict', cannot update {func.__name__})")
150
151
  if len(value) < 2 or not all(attr in value.keys() for attr in ("acceleration_enabled", "accelerate_now")):
151
- error = "{} should have 2 keys ".format(func.__name__)
152
+ error = f"{func.__name__} should have 2 keys "
152
153
  error += "'acceleration_enabled' and 'accelerate_now'"
153
- error += "instead you have {}".format(value.keys())
154
+ error += f"instead you have {value.keys()}"
154
155
  raise ValueError(error)
155
156
  return func(self, value)
156
157
 
@@ -1,10 +1,10 @@
1
- class ResourceReference(object):
1
+ class ResourceReference:
2
2
  def __init__(self, id_, tag_name):
3
3
  self.id = id_
4
4
  self.tag_name = tag_name
5
5
 
6
6
  def __str__(self):
7
- return "<ResourceReference id={} tag={}>".format(self._id, self._tag_name)
7
+ return f"<ResourceReference id={self._id} tag={self._tag_name}>"
8
8
 
9
9
  __repr__ = __str__
10
10
 
@@ -1,12 +1,12 @@
1
1
  from datetime import datetime
2
- from typing import List, Optional
2
+ from typing import Optional
3
3
 
4
4
  from defusedxml.ElementTree import fromstring
5
5
 
6
6
  from tableauserverclient.datetime_helpers import parse_datetime
7
7
 
8
8
 
9
- class RevisionItem(object):
9
+ class RevisionItem:
10
10
  def __init__(self):
11
11
  self._resource_id: Optional[str] = None
12
12
  self._resource_name: Optional[str] = None
@@ -56,7 +56,7 @@ class RevisionItem(object):
56
56
  )
57
57
 
58
58
  @classmethod
59
- def from_response(cls, resp: bytes, ns, resource_item) -> List["RevisionItem"]:
59
+ def from_response(cls, resp: bytes, ns, resource_item) -> list["RevisionItem"]:
60
60
  all_revision_items = list()
61
61
  parsed_response = fromstring(resp)
62
62
  all_revision_xml = parsed_response.findall(".//t:revision", namespaces=ns)
@@ -19,7 +19,7 @@ from .property_decorators import (
19
19
  Interval = Union[HourlyInterval, DailyInterval, WeeklyInterval, MonthlyInterval]
20
20
 
21
21
 
22
- class ScheduleItem(object):
22
+ class ScheduleItem:
23
23
  class Type:
24
24
  Extract = "Extract"
25
25
  Flow = "Flow"
@@ -336,7 +336,7 @@ class ScheduleItem(object):
336
336
  all_task_xml = parsed_response.findall(".//t:task", namespaces=ns)
337
337
 
338
338
  error = (
339
- "Status {}: {}".format(response.status_code, response.reason)
339
+ f"Status {response.status_code}: {response.reason}"
340
340
  if response.status_code < 200 or response.status_code >= 300
341
341
  else None
342
342
  )
@@ -6,7 +6,29 @@ from defusedxml.ElementTree import fromstring
6
6
  from tableauserverclient.helpers.logging import logger
7
7
 
8
8
 
9
- class ServerInfoItem(object):
9
+ class ServerInfoItem:
10
+ """
11
+ The ServerInfoItem class contains the build and version information for
12
+ Tableau Server. The server information is accessed with the
13
+ server_info.get() method, which returns an instance of the ServerInfo class.
14
+
15
+ Attributes
16
+ ----------
17
+ product_version : str
18
+ Shows the version of the Tableau Server or Tableau Cloud
19
+ (for example, 10.2.0).
20
+
21
+ build_number : str
22
+ Shows the specific build number (for example, 10200.17.0329.1446).
23
+
24
+ rest_api_version : str
25
+ Shows the supported REST API version number. Note that this might be
26
+ different from the default value specified for the server, with the
27
+ Server.version attribute. To take advantage of new features, you should
28
+ query the server and set the Server.version to match the supported REST
29
+ API version number.
30
+ """
31
+
10
32
  def __init__(self, product_version, build_number, rest_api_version):
11
33
  self._product_version = product_version
12
34
  self._build_number = build_number
@@ -40,13 +62,11 @@ class ServerInfoItem(object):
40
62
  try:
41
63
  parsed_response = fromstring(resp)
42
64
  except xml.etree.ElementTree.ParseError as error:
43
- logger.info("Unexpected response for ServerInfo: {}".format(resp))
44
- logger.info(error)
65
+ logger.exception(f"Unexpected response for ServerInfo: {resp}")
45
66
  return cls("Unknown", "Unknown", "Unknown")
46
67
  except Exception as error:
47
- logger.info("Unexpected response for ServerInfo: {}".format(resp))
48
- logger.info(error)
49
- return cls("Unknown", "Unknown", "Unknown")
68
+ logger.exception(f"Unexpected response for ServerInfo: {resp}")
69
+ raise error
50
70
 
51
71
  product_version_tag = parsed_response.find(".//t:productVersion", namespaces=ns)
52
72
  rest_api_version_tag = parsed_response.find(".//t:restApiVersion", namespaces=ns)
@@ -14,13 +14,79 @@ from .property_decorators import (
14
14
 
15
15
  VALID_CONTENT_URL_RE = r"^[a-zA-Z0-9_\-]*$"
16
16
 
17
- from typing import List, Optional, Union, TYPE_CHECKING
17
+ from typing import Optional, Union, TYPE_CHECKING
18
18
 
19
19
  if TYPE_CHECKING:
20
20
  from tableauserverclient.server import Server
21
21
 
22
22
 
23
- class SiteItem(object):
23
+ class SiteItem:
24
+ """
25
+ The SiteItem class contains the members or attributes for the site resources
26
+ on Tableau Server or Tableau Cloud. The SiteItem class defines the
27
+ information you can request or query from Tableau Server or Tableau Cloud.
28
+ The class members correspond to the attributes of a server request or
29
+ response payload.
30
+
31
+ Attributes
32
+ ----------
33
+ name: str
34
+ The name of the site. The name of the default site is "".
35
+
36
+ content_url: str
37
+ The path to the site.
38
+
39
+ admin_mode: str
40
+ (Optional) For Tableau Server only. Specify ContentAndUsers to allow
41
+ site administrators to use the server interface and tabcmd commands to
42
+ add and remove users. (Specifying this option does not give site
43
+ administrators permissions to manage users using the REST API.) Specify
44
+ ContentOnly to prevent site administrators from adding or removing
45
+ users. (Server administrators can always add or remove users.)
46
+
47
+ user_quota: int
48
+ (Optional) Specifies the total number of users for the site. The number
49
+ can't exceed the number of licenses activated for the site; and if
50
+ tiered capacity attributes are set, then user_quota will equal the sum
51
+ of the tiered capacity values, and attempting to set user_quota will
52
+ cause an error.
53
+
54
+ tier_explorer_capacity: int
55
+ tier_creator_capacity: int
56
+ tier_viewer_capacity: int
57
+ (Optional) The maximum number of licenses for users with the Creator,
58
+ Explorer, or Viewer role, respectively, allowed on a site.
59
+
60
+ storage_quota: int
61
+ (Optional) Specifies the maximum amount of space for the new site, in
62
+ megabytes. If you set a quota and the site exceeds it, publishers will
63
+ be prevented from uploading new content until the site is under the
64
+ limit again.
65
+
66
+ disable_subscriptions: bool
67
+ (Optional) Specify true to prevent users from being able to subscribe
68
+ to workbooks on the specified site. The default is False.
69
+
70
+ subscribe_others_enabled: bool
71
+ (Optional) Specify false to prevent server administrators, site
72
+ administrators, and project or content owners from being able to
73
+ subscribe other users to workbooks on the specified site. The default
74
+ is True.
75
+
76
+ revision_history_enabled: bool
77
+ (Optional) Specify true to enable revision history for content resources
78
+ (workbooks and datasources). The default is False.
79
+
80
+ revision_limit: int
81
+ (Optional) Specifies the number of revisions of a content source
82
+ (workbook or data source) to allow. On Tableau Server, the default is
83
+ 25.
84
+
85
+ state: str
86
+ Shows the current state of the site (Active or Suspended).
87
+
88
+ """
89
+
24
90
  _user_quota: Optional[int] = None
25
91
  _tier_creator_capacity: Optional[int] = None
26
92
  _tier_explorer_capacity: Optional[int] = None
@@ -873,7 +939,7 @@ class SiteItem(object):
873
939
  self.auto_suspend_refresh_inactivity_window = auto_suspend_refresh_inactivity_window
874
940
 
875
941
  @classmethod
876
- def from_response(cls, resp, ns) -> List["SiteItem"]:
942
+ def from_response(cls, resp, ns) -> list["SiteItem"]:
877
943
  all_site_items = list()
878
944
  parsed_response = fromstring(resp)
879
945
  all_site_xml = parsed_response.findall(".//t:site", namespaces=ns)
@@ -1,4 +1,4 @@
1
- from typing import List, Type, TYPE_CHECKING
1
+ from typing import TYPE_CHECKING
2
2
 
3
3
  from defusedxml.ElementTree import fromstring
4
4
 
@@ -10,7 +10,7 @@ if TYPE_CHECKING:
10
10
  from .target import Target
11
11
 
12
12
 
13
- class SubscriptionItem(object):
13
+ class SubscriptionItem:
14
14
  def __init__(self, subject: str, schedule_id: str, user_id: str, target: "Target") -> None:
15
15
  self._id = None
16
16
  self.attach_image = True
@@ -79,7 +79,7 @@ class SubscriptionItem(object):
79
79
  self._suspended = value
80
80
 
81
81
  @classmethod
82
- def from_response(cls: Type, xml: bytes, ns) -> List["SubscriptionItem"]:
82
+ def from_response(cls: type, xml: bytes, ns) -> list["SubscriptionItem"]:
83
83
  parsed_response = fromstring(xml)
84
84
  all_subscriptions_xml = parsed_response.findall(".//t:subscription", namespaces=ns)
85
85
 
@@ -4,7 +4,7 @@ from .exceptions import UnpopulatedPropertyError
4
4
  from .property_decorators import property_not_empty, property_is_boolean
5
5
 
6
6
 
7
- class TableItem(object):
7
+ class TableItem:
8
8
  def __init__(self, name, description=None):
9
9
  self._id = None
10
10
  self.description = description
@@ -1,5 +1,5 @@
1
1
  import abc
2
- from typing import Dict, Optional
2
+ from typing import Optional
3
3
 
4
4
 
5
5
  class Credentials(abc.ABC):
@@ -9,7 +9,7 @@ class Credentials(abc.ABC):
9
9
 
10
10
  @property
11
11
  @abc.abstractmethod
12
- def credentials(self) -> Dict[str, str]:
12
+ def credentials(self) -> dict[str, str]:
13
13
  credentials = (
14
14
  "Credentials can be username/password, Personal Access Token, or JWT"
15
15
  "This method returns values to set as an attribute on the credentials element of the request"
@@ -32,6 +32,43 @@ def deprecate_site_attribute():
32
32
 
33
33
  # The traditional auth type: username/password
34
34
  class TableauAuth(Credentials):
35
+ """
36
+ The TableauAuth class defines the information you can set in a sign-in
37
+ request. The class members correspond to the attributes of a server request
38
+ or response payload. To use this class, create a new instance, supplying
39
+ user name, password, and site information if necessary, and pass the
40
+ request object to the Auth.sign_in method.
41
+
42
+ Parameters
43
+ ----------
44
+ username : str
45
+ The user name for the sign-in request.
46
+
47
+ password : str
48
+ The password for the sign-in request.
49
+
50
+ site_id : str, optional
51
+ This corresponds to the contentUrl attribute in the Tableau REST API.
52
+ The site_id is the portion of the URL that follows the /site/ in the
53
+ URL. For example, "MarketingTeam" is the site_id in the following URL
54
+ MyServer/#/site/MarketingTeam/projects. To specify the default site on
55
+ Tableau Server, you can use an empty string '' (single quotes, no
56
+ space). For Tableau Cloud, you must provide a value for the site_id.
57
+
58
+ user_id_to_impersonate : str, optional
59
+ Specifies the id (not the name) of the user to sign in as. This is not
60
+ available for Tableau Online.
61
+
62
+ Examples
63
+ --------
64
+ >>> import tableauserverclient as TSC
65
+
66
+ >>> tableau_auth = TSC.TableauAuth('USERNAME', 'PASSWORD', site_id='CONTENTURL')
67
+ >>> server = TSC.Server('https://SERVER_URL', use_server_version=True)
68
+ >>> server.auth.sign_in(tableau_auth)
69
+
70
+ """
71
+
35
72
  def __init__(
36
73
  self, username: str, password: str, site_id: Optional[str] = None, user_id_to_impersonate: Optional[str] = None
37
74
  ) -> None:
@@ -42,7 +79,7 @@ class TableauAuth(Credentials):
42
79
  self.username = username
43
80
 
44
81
  @property
45
- def credentials(self) -> Dict[str, str]:
82
+ def credentials(self) -> dict[str, str]:
46
83
  return {"name": self.username, "password": self.password}
47
84
 
48
85
  def __repr__(self):
@@ -55,6 +92,43 @@ class TableauAuth(Credentials):
55
92
 
56
93
  # A Tableau-generated Personal Access Token
57
94
  class PersonalAccessTokenAuth(Credentials):
95
+ """
96
+ The PersonalAccessTokenAuth class defines the information you can set in a sign-in
97
+ request. The class members correspond to the attributes of a server request
98
+ or response payload. To use this class, create a new instance, supplying
99
+ token name, token secret, and site information if necessary, and pass the
100
+ request object to the Auth.sign_in method.
101
+
102
+ Parameters
103
+ ----------
104
+ token_name : str
105
+ The name of the personal access token.
106
+
107
+ personal_access_token : str
108
+ The personal access token secret for the sign in request.
109
+
110
+ site_id : str, optional
111
+ This corresponds to the contentUrl attribute in the Tableau REST API.
112
+ The site_id is the portion of the URL that follows the /site/ in the
113
+ URL. For example, "MarketingTeam" is the site_id in the following URL
114
+ MyServer/#/site/MarketingTeam/projects. To specify the default site on
115
+ Tableau Server, you can use an empty string '' (single quotes, no
116
+ space). For Tableau Cloud, you must provide a value for the site_id.
117
+
118
+ user_id_to_impersonate : str, optional
119
+ Specifies the id (not the name) of the user to sign in as. This is not
120
+ available for Tableau Online.
121
+
122
+ Examples
123
+ --------
124
+ >>> import tableauserverclient as TSC
125
+
126
+ >>> tableau_auth = TSC.PersonalAccessTokenAuth("token_name", "token_secret", site_id='CONTENTURL')
127
+ >>> server = TSC.Server('https://SERVER_URL', use_server_version=True)
128
+ >>> server.auth.sign_in(tableau_auth)
129
+
130
+ """
131
+
58
132
  def __init__(
59
133
  self,
60
134
  token_name: str,
@@ -69,7 +143,7 @@ class PersonalAccessTokenAuth(Credentials):
69
143
  self.personal_access_token = personal_access_token
70
144
 
71
145
  @property
72
- def credentials(self) -> Dict[str, str]:
146
+ def credentials(self) -> dict[str, str]:
73
147
  return {
74
148
  "personalAccessTokenName": self.token_name,
75
149
  "personalAccessTokenSecret": self.personal_access_token,
@@ -88,6 +162,42 @@ class PersonalAccessTokenAuth(Credentials):
88
162
 
89
163
  # A standard JWT generated specifically for Tableau
90
164
  class JWTAuth(Credentials):
165
+ """
166
+ The JWTAuth class defines the information you can set in a sign-in
167
+ request. The class members correspond to the attributes of a server request
168
+ or response payload. To use this class, create a new instance, supplying
169
+ an encoded JSON Web Token, and site information if necessary, and pass the
170
+ request object to the Auth.sign_in method.
171
+
172
+ Parameters
173
+ ----------
174
+ token : str
175
+ The encoded JSON Web Token.
176
+
177
+ site_id : str, optional
178
+ This corresponds to the contentUrl attribute in the Tableau REST API.
179
+ The site_id is the portion of the URL that follows the /site/ in the
180
+ URL. For example, "MarketingTeam" is the site_id in the following URL
181
+ MyServer/#/site/MarketingTeam/projects. To specify the default site on
182
+ Tableau Server, you can use an empty string '' (single quotes, no
183
+ space). For Tableau Cloud, you must provide a value for the site_id.
184
+
185
+ user_id_to_impersonate : str, optional
186
+ Specifies the id (not the name) of the user to sign in as. This is not
187
+ available for Tableau Online.
188
+
189
+ Examples
190
+ --------
191
+ >>> import jwt
192
+ >>> import tableauserverclient as TSC
193
+
194
+ >>> jwt_token = jwt.encode(...)
195
+ >>> tableau_auth = TSC.JWTAuth(token, site_id='CONTENTURL')
196
+ >>> server = TSC.Server('https://SERVER_URL', use_server_version=True)
197
+ >>> server.auth.sign_in(tableau_auth)
198
+
199
+ """
200
+
91
201
  def __init__(self, jwt: str, site_id: Optional[str] = None, user_id_to_impersonate: Optional[str] = None) -> None:
92
202
  if jwt is None:
93
203
  raise TabError("Must provide a JWT token when using JWT authentication")
@@ -95,7 +205,7 @@ class JWTAuth(Credentials):
95
205
  self.jwt = jwt
96
206
 
97
207
  @property
98
- def credentials(self) -> Dict[str, str]:
208
+ def credentials(self) -> dict[str, str]:
99
209
  return {"jwt": self.jwt}
100
210
 
101
211
  def __repr__(self):
@@ -28,8 +28,8 @@ class Resource:
28
28
  TableauItem = Union[DatasourceItem, FlowItem, MetricItem, ProjectItem, ViewItem, WorkbookItem, VirtualConnectionItem]
29
29
 
30
30
 
31
- def plural_type(content_type: Resource) -> str:
31
+ def plural_type(content_type: Union[Resource, str]) -> str:
32
32
  if content_type == Resource.Lens:
33
33
  return "lenses"
34
34
  else:
35
- return "{}s".format(content_type)
35
+ return f"{content_type}s"