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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (94) hide show
  1. tableauserverclient/__init__.py +28 -22
  2. tableauserverclient/_version.py +3 -3
  3. tableauserverclient/config.py +5 -3
  4. tableauserverclient/models/column_item.py +1 -1
  5. tableauserverclient/models/connection_credentials.py +1 -1
  6. tableauserverclient/models/connection_item.py +6 -6
  7. tableauserverclient/models/custom_view_item.py +29 -6
  8. tableauserverclient/models/data_acceleration_report_item.py +2 -2
  9. tableauserverclient/models/data_alert_item.py +5 -5
  10. tableauserverclient/models/data_freshness_policy_item.py +6 -6
  11. tableauserverclient/models/database_item.py +3 -3
  12. tableauserverclient/models/datasource_item.py +10 -10
  13. tableauserverclient/models/dqw_item.py +1 -1
  14. tableauserverclient/models/favorites_item.py +5 -6
  15. tableauserverclient/models/fileupload_item.py +1 -1
  16. tableauserverclient/models/flow_item.py +6 -6
  17. tableauserverclient/models/flow_run_item.py +3 -3
  18. tableauserverclient/models/group_item.py +4 -4
  19. tableauserverclient/models/groupset_item.py +4 -4
  20. tableauserverclient/models/interval_item.py +9 -9
  21. tableauserverclient/models/job_item.py +8 -8
  22. tableauserverclient/models/linked_tasks_item.py +5 -5
  23. tableauserverclient/models/metric_item.py +5 -5
  24. tableauserverclient/models/pagination_item.py +1 -1
  25. tableauserverclient/models/permissions_item.py +12 -10
  26. tableauserverclient/models/project_item.py +35 -19
  27. tableauserverclient/models/property_decorators.py +12 -11
  28. tableauserverclient/models/reference_item.py +2 -2
  29. tableauserverclient/models/revision_item.py +3 -3
  30. tableauserverclient/models/schedule_item.py +2 -2
  31. tableauserverclient/models/server_info_item.py +26 -6
  32. tableauserverclient/models/site_item.py +69 -3
  33. tableauserverclient/models/subscription_item.py +3 -3
  34. tableauserverclient/models/table_item.py +1 -1
  35. tableauserverclient/models/tableau_auth.py +115 -5
  36. tableauserverclient/models/tableau_types.py +2 -2
  37. tableauserverclient/models/tag_item.py +3 -4
  38. tableauserverclient/models/task_item.py +4 -4
  39. tableauserverclient/models/user_item.py +47 -17
  40. tableauserverclient/models/view_item.py +11 -10
  41. tableauserverclient/models/virtual_connection_item.py +6 -5
  42. tableauserverclient/models/webhook_item.py +6 -6
  43. tableauserverclient/models/workbook_item.py +90 -12
  44. tableauserverclient/namespace.py +1 -1
  45. tableauserverclient/server/__init__.py +2 -1
  46. tableauserverclient/server/endpoint/auth_endpoint.py +65 -8
  47. tableauserverclient/server/endpoint/custom_views_endpoint.py +62 -18
  48. tableauserverclient/server/endpoint/data_acceleration_report_endpoint.py +2 -2
  49. tableauserverclient/server/endpoint/data_alert_endpoint.py +14 -14
  50. tableauserverclient/server/endpoint/databases_endpoint.py +13 -12
  51. tableauserverclient/server/endpoint/datasources_endpoint.py +49 -54
  52. tableauserverclient/server/endpoint/default_permissions_endpoint.py +19 -18
  53. tableauserverclient/server/endpoint/dqw_endpoint.py +9 -9
  54. tableauserverclient/server/endpoint/endpoint.py +19 -21
  55. tableauserverclient/server/endpoint/exceptions.py +23 -7
  56. tableauserverclient/server/endpoint/favorites_endpoint.py +31 -31
  57. tableauserverclient/server/endpoint/fileuploads_endpoint.py +9 -11
  58. tableauserverclient/server/endpoint/flow_runs_endpoint.py +15 -13
  59. tableauserverclient/server/endpoint/flow_task_endpoint.py +2 -2
  60. tableauserverclient/server/endpoint/flows_endpoint.py +30 -29
  61. tableauserverclient/server/endpoint/groups_endpoint.py +18 -17
  62. tableauserverclient/server/endpoint/groupsets_endpoint.py +2 -2
  63. tableauserverclient/server/endpoint/jobs_endpoint.py +7 -7
  64. tableauserverclient/server/endpoint/linked_tasks_endpoint.py +2 -2
  65. tableauserverclient/server/endpoint/metadata_endpoint.py +2 -2
  66. tableauserverclient/server/endpoint/metrics_endpoint.py +10 -10
  67. tableauserverclient/server/endpoint/permissions_endpoint.py +13 -15
  68. tableauserverclient/server/endpoint/projects_endpoint.py +81 -30
  69. tableauserverclient/server/endpoint/resource_tagger.py +14 -13
  70. tableauserverclient/server/endpoint/schedules_endpoint.py +17 -18
  71. tableauserverclient/server/endpoint/server_info_endpoint.py +40 -5
  72. tableauserverclient/server/endpoint/sites_endpoint.py +282 -17
  73. tableauserverclient/server/endpoint/subscriptions_endpoint.py +10 -10
  74. tableauserverclient/server/endpoint/tables_endpoint.py +15 -14
  75. tableauserverclient/server/endpoint/tasks_endpoint.py +8 -8
  76. tableauserverclient/server/endpoint/users_endpoint.py +366 -19
  77. tableauserverclient/server/endpoint/views_endpoint.py +19 -18
  78. tableauserverclient/server/endpoint/virtual_connections_endpoint.py +6 -5
  79. tableauserverclient/server/endpoint/webhooks_endpoint.py +11 -11
  80. tableauserverclient/server/endpoint/workbooks_endpoint.py +647 -61
  81. tableauserverclient/server/filter.py +2 -2
  82. tableauserverclient/server/pager.py +5 -6
  83. tableauserverclient/server/query.py +68 -19
  84. tableauserverclient/server/request_factory.py +37 -36
  85. tableauserverclient/server/request_options.py +123 -145
  86. tableauserverclient/server/server.py +65 -9
  87. tableauserverclient/server/sort.py +2 -2
  88. {tableauserverclient-0.33.dist-info → tableauserverclient-0.34.dist-info}/METADATA +6 -6
  89. tableauserverclient-0.34.dist-info/RECORD +106 -0
  90. {tableauserverclient-0.33.dist-info → tableauserverclient-0.34.dist-info}/WHEEL +1 -1
  91. tableauserverclient-0.33.dist-info/RECORD +0 -106
  92. {tableauserverclient-0.33.dist-info → tableauserverclient-0.34.dist-info}/LICENSE +0 -0
  93. {tableauserverclient-0.33.dist-info → tableauserverclient-0.34.dist-info}/LICENSE.versioneer +0 -0
  94. {tableauserverclient-0.33.dist-info → tableauserverclient-0.34.dist-info}/top_level.txt +0 -0
@@ -5,9 +5,10 @@ from tableauserverclient.server.endpoint.endpoint import QuerysetEndpoint, api,
5
5
  from tableauserverclient.server.endpoint.exceptions import MissingRequiredFieldError
6
6
  from tableauserverclient.server.endpoint.permissions_endpoint import _PermissionsEndpoint
7
7
  from tableauserverclient.server import RequestFactory, RequestOptions
8
+ from tableauserverclient.models.permissions_item import PermissionsRule
8
9
  from tableauserverclient.models import ProjectItem, PaginationItem, Resource
9
10
 
10
- from typing import List, Optional, Tuple, TYPE_CHECKING
11
+ from typing import Optional, TYPE_CHECKING
11
12
 
12
13
  from tableauserverclient.server.query import QuerySet
13
14
 
@@ -20,17 +21,17 @@ from tableauserverclient.helpers.logging import logger
20
21
 
21
22
  class Projects(QuerysetEndpoint[ProjectItem]):
22
23
  def __init__(self, parent_srv: "Server") -> None:
23
- super(Projects, self).__init__(parent_srv)
24
+ super().__init__(parent_srv)
24
25
 
25
26
  self._permissions = _PermissionsEndpoint(parent_srv, lambda: self.baseurl)
26
27
  self._default_permissions = _DefaultPermissionsEndpoint(parent_srv, lambda: self.baseurl)
27
28
 
28
29
  @property
29
30
  def baseurl(self) -> str:
30
- return "{0}/sites/{1}/projects".format(self.parent_srv.baseurl, self.parent_srv.site_id)
31
+ return f"{self.parent_srv.baseurl}/sites/{self.parent_srv.site_id}/projects"
31
32
 
32
33
  @api(version="2.0")
33
- def get(self, req_options: Optional["RequestOptions"] = None) -> Tuple[List[ProjectItem], PaginationItem]:
34
+ def get(self, req_options: Optional["RequestOptions"] = None) -> tuple[list[ProjectItem], PaginationItem]:
34
35
  logger.info("Querying all projects on site")
35
36
  url = self.baseurl
36
37
  server_response = self.get_request(url, req_options)
@@ -43,9 +44,9 @@ class Projects(QuerysetEndpoint[ProjectItem]):
43
44
  if not project_id:
44
45
  error = "Project ID undefined."
45
46
  raise ValueError(error)
46
- url = "{0}/{1}".format(self.baseurl, project_id)
47
+ url = f"{self.baseurl}/{project_id}"
47
48
  self.delete_request(url)
48
- logger.info("Deleted single project (ID: {0})".format(project_id))
49
+ logger.info(f"Deleted single project (ID: {project_id})")
49
50
 
50
51
  @api(version="2.0")
51
52
  def update(self, project_item: ProjectItem, samples: bool = False) -> ProjectItem:
@@ -54,10 +55,10 @@ class Projects(QuerysetEndpoint[ProjectItem]):
54
55
  raise MissingRequiredFieldError(error)
55
56
 
56
57
  params = {"params": {RequestOptions.Field.PublishSamples: samples}}
57
- url = "{0}/{1}".format(self.baseurl, project_item.id)
58
+ url = f"{self.baseurl}/{project_item.id}"
58
59
  update_req = RequestFactory.Project.update_req(project_item)
59
60
  server_response = self.put_request(url, update_req, XML_CONTENT_TYPE, params)
60
- logger.info("Updated project item (ID: {0})".format(project_item.id))
61
+ logger.info(f"Updated project item (ID: {project_item.id})")
61
62
  updated_project = ProjectItem.from_response(server_response.content, self.parent_srv.namespace)[0]
62
63
  return updated_project
63
64
 
@@ -66,11 +67,11 @@ class Projects(QuerysetEndpoint[ProjectItem]):
66
67
  params = {"params": {RequestOptions.Field.PublishSamples: samples}}
67
68
  url = self.baseurl
68
69
  if project_item._samples:
69
- url = "{0}?publishSamples={1}".format(self.baseurl, project_item._samples)
70
+ url = f"{self.baseurl}?publishSamples={project_item._samples}"
70
71
  create_req = RequestFactory.Project.create_req(project_item)
71
72
  server_response = self.post_request(url, create_req, XML_CONTENT_TYPE, params)
72
73
  new_project = ProjectItem.from_response(server_response.content, self.parent_srv.namespace)[0]
73
- logger.info("Created new project (ID: {0})".format(new_project.id))
74
+ logger.info(f"Created new project (ID: {new_project.id})")
74
75
  return new_project
75
76
 
76
77
  @api(version="2.0")
@@ -78,85 +79,135 @@ class Projects(QuerysetEndpoint[ProjectItem]):
78
79
  self._permissions.populate(item)
79
80
 
80
81
  @api(version="2.0")
81
- def update_permissions(self, item, rules):
82
+ def update_permissions(self, item: ProjectItem, rules: list[PermissionsRule]) -> list[PermissionsRule]:
82
83
  return self._permissions.update(item, rules)
83
84
 
84
85
  @api(version="2.0")
85
- def delete_permission(self, item, rules):
86
+ def delete_permission(self, item: ProjectItem, rules: list[PermissionsRule]) -> None:
86
87
  self._permissions.delete(item, rules)
87
88
 
88
89
  @api(version="2.1")
89
- def populate_workbook_default_permissions(self, item):
90
+ def populate_workbook_default_permissions(self, item: ProjectItem) -> None:
90
91
  self._default_permissions.populate_default_permissions(item, Resource.Workbook)
91
92
 
92
93
  @api(version="2.1")
93
- def populate_datasource_default_permissions(self, item):
94
+ def populate_datasource_default_permissions(self, item: ProjectItem) -> None:
94
95
  self._default_permissions.populate_default_permissions(item, Resource.Datasource)
95
96
 
96
97
  @api(version="3.2")
97
- def populate_metric_default_permissions(self, item):
98
+ def populate_metric_default_permissions(self, item: ProjectItem) -> None:
98
99
  self._default_permissions.populate_default_permissions(item, Resource.Metric)
99
100
 
100
101
  @api(version="3.4")
101
- def populate_datarole_default_permissions(self, item):
102
+ def populate_datarole_default_permissions(self, item: ProjectItem) -> None:
102
103
  self._default_permissions.populate_default_permissions(item, Resource.Datarole)
103
104
 
104
105
  @api(version="3.4")
105
- def populate_flow_default_permissions(self, item):
106
+ def populate_flow_default_permissions(self, item: ProjectItem) -> None:
106
107
  self._default_permissions.populate_default_permissions(item, Resource.Flow)
107
108
 
108
109
  @api(version="3.4")
109
- def populate_lens_default_permissions(self, item):
110
+ def populate_lens_default_permissions(self, item: ProjectItem) -> None:
110
111
  self._default_permissions.populate_default_permissions(item, Resource.Lens)
111
112
 
113
+ @api(version="3.23")
114
+ def populate_virtualconnection_default_permissions(self, item: ProjectItem) -> None:
115
+ self._default_permissions.populate_default_permissions(item, Resource.VirtualConnection)
116
+
117
+ @api(version="3.23")
118
+ def populate_database_default_permissions(self, item: ProjectItem) -> None:
119
+ self._default_permissions.populate_default_permissions(item, Resource.Database)
120
+
121
+ @api(version="3.23")
122
+ def populate_table_default_permissions(self, item: ProjectItem) -> None:
123
+ self._default_permissions.populate_default_permissions(item, Resource.Table)
124
+
112
125
  @api(version="2.1")
113
- def update_workbook_default_permissions(self, item, rules):
126
+ def update_workbook_default_permissions(
127
+ self, item: ProjectItem, rules: list[PermissionsRule]
128
+ ) -> list[PermissionsRule]:
114
129
  return self._default_permissions.update_default_permissions(item, rules, Resource.Workbook)
115
130
 
116
131
  @api(version="2.1")
117
- def update_datasource_default_permissions(self, item, rules):
132
+ def update_datasource_default_permissions(
133
+ self, item: ProjectItem, rules: list[PermissionsRule]
134
+ ) -> list[PermissionsRule]:
118
135
  return self._default_permissions.update_default_permissions(item, rules, Resource.Datasource)
119
136
 
120
137
  @api(version="3.2")
121
- def update_metric_default_permissions(self, item, rules):
138
+ def update_metric_default_permissions(
139
+ self, item: ProjectItem, rules: list[PermissionsRule]
140
+ ) -> list[PermissionsRule]:
122
141
  return self._default_permissions.update_default_permissions(item, rules, Resource.Metric)
123
142
 
124
143
  @api(version="3.4")
125
- def update_datarole_default_permissions(self, item, rules):
144
+ def update_datarole_default_permissions(
145
+ self, item: ProjectItem, rules: list[PermissionsRule]
146
+ ) -> list[PermissionsRule]:
126
147
  return self._default_permissions.update_default_permissions(item, rules, Resource.Datarole)
127
148
 
128
149
  @api(version="3.4")
129
- def update_flow_default_permissions(self, item, rules):
150
+ def update_flow_default_permissions(self, item: ProjectItem, rules: list[PermissionsRule]) -> list[PermissionsRule]:
130
151
  return self._default_permissions.update_default_permissions(item, rules, Resource.Flow)
131
152
 
132
153
  @api(version="3.4")
133
- def update_lens_default_permissions(self, item, rules):
154
+ def update_lens_default_permissions(self, item: ProjectItem, rules: list[PermissionsRule]) -> list[PermissionsRule]:
134
155
  return self._default_permissions.update_default_permissions(item, rules, Resource.Lens)
135
156
 
157
+ @api(version="3.23")
158
+ def update_virtualconnection_default_permissions(
159
+ self, item: ProjectItem, rules: list[PermissionsRule]
160
+ ) -> list[PermissionsRule]:
161
+ return self._default_permissions.update_default_permissions(item, rules, Resource.VirtualConnection)
162
+
163
+ @api(version="3.23")
164
+ def update_database_default_permissions(
165
+ self, item: ProjectItem, rules: list[PermissionsRule]
166
+ ) -> list[PermissionsRule]:
167
+ return self._default_permissions.update_default_permissions(item, rules, Resource.Database)
168
+
169
+ @api(version="3.23")
170
+ def update_table_default_permissions(
171
+ self, item: ProjectItem, rules: list[PermissionsRule]
172
+ ) -> list[PermissionsRule]:
173
+ return self._default_permissions.update_default_permissions(item, rules, Resource.Table)
174
+
136
175
  @api(version="2.1")
137
- def delete_workbook_default_permissions(self, item, rule):
176
+ def delete_workbook_default_permissions(self, item: ProjectItem, rule: PermissionsRule) -> None:
138
177
  self._default_permissions.delete_default_permission(item, rule, Resource.Workbook)
139
178
 
140
179
  @api(version="2.1")
141
- def delete_datasource_default_permissions(self, item, rule):
180
+ def delete_datasource_default_permissions(self, item: ProjectItem, rule: PermissionsRule) -> None:
142
181
  self._default_permissions.delete_default_permission(item, rule, Resource.Datasource)
143
182
 
144
183
  @api(version="3.2")
145
- def delete_metric_default_permissions(self, item, rule):
184
+ def delete_metric_default_permissions(self, item: ProjectItem, rule: PermissionsRule) -> None:
146
185
  self._default_permissions.delete_default_permission(item, rule, Resource.Metric)
147
186
 
148
187
  @api(version="3.4")
149
- def delete_datarole_default_permissions(self, item, rule):
188
+ def delete_datarole_default_permissions(self, item: ProjectItem, rule: PermissionsRule) -> None:
150
189
  self._default_permissions.delete_default_permission(item, rule, Resource.Datarole)
151
190
 
152
191
  @api(version="3.4")
153
- def delete_flow_default_permissions(self, item, rule):
192
+ def delete_flow_default_permissions(self, item: ProjectItem, rule: PermissionsRule) -> None:
154
193
  self._default_permissions.delete_default_permission(item, rule, Resource.Flow)
155
194
 
156
195
  @api(version="3.4")
157
- def delete_lens_default_permissions(self, item, rule):
196
+ def delete_lens_default_permissions(self, item: ProjectItem, rule: PermissionsRule) -> None:
158
197
  self._default_permissions.delete_default_permission(item, rule, Resource.Lens)
159
198
 
199
+ @api(version="3.23")
200
+ def delete_virtualconnection_default_permissions(self, item: ProjectItem, rule: PermissionsRule) -> None:
201
+ self._default_permissions.delete_default_permission(item, rule, Resource.VirtualConnection)
202
+
203
+ @api(version="3.23")
204
+ def delete_database_default_permissions(self, item: ProjectItem, rule: PermissionsRule) -> None:
205
+ self._default_permissions.delete_default_permission(item, rule, Resource.Database)
206
+
207
+ @api(version="3.23")
208
+ def delete_table_default_permissions(self, item: ProjectItem, rule: PermissionsRule) -> None:
209
+ self._default_permissions.delete_default_permission(item, rule, Resource.Table)
210
+
160
211
  def filter(self, *invalid, page_size: Optional[int] = None, **kwargs) -> QuerySet[ProjectItem]:
161
212
  """
162
213
  Queries the Tableau Server for items using the specified filters. Page
@@ -1,6 +1,7 @@
1
1
  import abc
2
2
  import copy
3
- from typing import Generic, Iterable, Optional, Protocol, Set, TypeVar, Union, TYPE_CHECKING, runtime_checkable
3
+ from typing import Generic, Optional, Protocol, TypeVar, Union, TYPE_CHECKING, runtime_checkable
4
+ from collections.abc import Iterable
4
5
  import urllib.parse
5
6
 
6
7
  from tableauserverclient.server.endpoint.endpoint import Endpoint, api
@@ -24,7 +25,7 @@ if TYPE_CHECKING:
24
25
  class _ResourceTagger(Endpoint):
25
26
  # Add new tags to resource
26
27
  def _add_tags(self, baseurl, resource_id, tag_set):
27
- url = "{0}/{1}/tags".format(baseurl, resource_id)
28
+ url = f"{baseurl}/{resource_id}/tags"
28
29
  add_req = RequestFactory.Tag.add_req(tag_set)
29
30
 
30
31
  try:
@@ -39,7 +40,7 @@ class _ResourceTagger(Endpoint):
39
40
  # Delete a resource's tag by name
40
41
  def _delete_tag(self, baseurl, resource_id, tag_name):
41
42
  encoded_tag_name = urllib.parse.quote(tag_name)
42
- url = "{0}/{1}/tags/{2}".format(baseurl, resource_id, encoded_tag_name)
43
+ url = f"{baseurl}/{resource_id}/tags/{encoded_tag_name}"
43
44
 
44
45
  try:
45
46
  self.delete_request(url)
@@ -59,7 +60,7 @@ class _ResourceTagger(Endpoint):
59
60
  if add_set:
60
61
  resource_item.tags = self._add_tags(baseurl, resource_item.id, add_set)
61
62
  resource_item._initial_tags = copy.copy(resource_item.tags)
62
- logger.info("Updated tags to {0}".format(resource_item.tags))
63
+ logger.info(f"Updated tags to {resource_item.tags}")
63
64
 
64
65
 
65
66
  class Response(Protocol):
@@ -68,8 +69,8 @@ class Response(Protocol):
68
69
 
69
70
  @runtime_checkable
70
71
  class Taggable(Protocol):
71
- tags: Set[str]
72
- _initial_tags: Set[str]
72
+ tags: set[str]
73
+ _initial_tags: set[str]
73
74
 
74
75
  @property
75
76
  def id(self) -> Optional[str]:
@@ -95,14 +96,14 @@ class TaggingMixin(abc.ABC, Generic[T]):
95
96
  def delete_request(self, url) -> None:
96
97
  pass
97
98
 
98
- def add_tags(self, item: Union[T, str], tags: Union[Iterable[str], str]) -> Set[str]:
99
+ def add_tags(self, item: Union[T, str], tags: Union[Iterable[str], str]) -> set[str]:
99
100
  item_id = getattr(item, "id", item)
100
101
 
101
102
  if not isinstance(item_id, str):
102
103
  raise ValueError("ID not found.")
103
104
 
104
105
  if isinstance(tags, str):
105
- tag_set = set([tags])
106
+ tag_set = {tags}
106
107
  else:
107
108
  tag_set = set(tags)
108
109
 
@@ -118,7 +119,7 @@ class TaggingMixin(abc.ABC, Generic[T]):
118
119
  raise ValueError("ID not found.")
119
120
 
120
121
  if isinstance(tags, str):
121
- tag_set = set([tags])
122
+ tag_set = {tags}
122
123
  else:
123
124
  tag_set = set(tags)
124
125
 
@@ -158,9 +159,9 @@ class Tags(Endpoint):
158
159
  return f"{self.parent_srv.baseurl}/tags"
159
160
 
160
161
  @api(version="3.9")
161
- def batch_add(self, tags: Union[Iterable[str], str], content: content) -> Set[str]:
162
+ def batch_add(self, tags: Union[Iterable[str], str], content: content) -> set[str]:
162
163
  if isinstance(tags, str):
163
- tag_set = set([tags])
164
+ tag_set = {tags}
164
165
  else:
165
166
  tag_set = set(tags)
166
167
 
@@ -170,9 +171,9 @@ class Tags(Endpoint):
170
171
  return TagItem.from_response(server_response.content, self.parent_srv.namespace)
171
172
 
172
173
  @api(version="3.9")
173
- def batch_delete(self, tags: Union[Iterable[str], str], content: content) -> Set[str]:
174
+ def batch_delete(self, tags: Union[Iterable[str], str], content: content) -> set[str]:
174
175
  if isinstance(tags, str):
175
- tag_set = set([tags])
176
+ tag_set = {tags}
176
177
  else:
177
178
  tag_set = set(tags)
178
179
 
@@ -2,7 +2,7 @@ import copy
2
2
  import logging
3
3
  import warnings
4
4
  from collections import namedtuple
5
- from typing import TYPE_CHECKING, Callable, List, Optional, Tuple, Union
5
+ from typing import TYPE_CHECKING, Callable, Optional, Union
6
6
 
7
7
  from .endpoint import Endpoint, api, parameter_added_in
8
8
  from .exceptions import MissingRequiredFieldError
@@ -22,14 +22,14 @@ if TYPE_CHECKING:
22
22
  class Schedules(Endpoint):
23
23
  @property
24
24
  def baseurl(self) -> str:
25
- return "{0}/schedules".format(self.parent_srv.baseurl)
25
+ return f"{self.parent_srv.baseurl}/schedules"
26
26
 
27
27
  @property
28
28
  def siteurl(self) -> str:
29
- return "{0}/sites/{1}/schedules".format(self.parent_srv.baseurl, self.parent_srv.site_id)
29
+ return f"{self.parent_srv.baseurl}/sites/{self.parent_srv.site_id}/schedules"
30
30
 
31
31
  @api(version="2.3")
32
- def get(self, req_options: Optional["RequestOptions"] = None) -> Tuple[List[ScheduleItem], PaginationItem]:
32
+ def get(self, req_options: Optional["RequestOptions"] = None) -> tuple[list[ScheduleItem], PaginationItem]:
33
33
  logger.info("Querying all schedules")
34
34
  url = self.baseurl
35
35
  server_response = self.get_request(url, req_options)
@@ -42,8 +42,8 @@ class Schedules(Endpoint):
42
42
  if not schedule_id:
43
43
  error = "No Schedule ID provided"
44
44
  raise ValueError(error)
45
- logger.info("Querying a single schedule by id ({})".format(schedule_id))
46
- url = "{0}/{1}".format(self.baseurl, schedule_id)
45
+ logger.info(f"Querying a single schedule by id ({schedule_id})")
46
+ url = f"{self.baseurl}/{schedule_id}"
47
47
  server_response = self.get_request(url)
48
48
  return ScheduleItem.from_response(server_response.content, self.parent_srv.namespace)[0]
49
49
 
@@ -52,9 +52,9 @@ class Schedules(Endpoint):
52
52
  if not schedule_id:
53
53
  error = "Schedule ID undefined"
54
54
  raise ValueError(error)
55
- url = "{0}/{1}".format(self.baseurl, schedule_id)
55
+ url = f"{self.baseurl}/{schedule_id}"
56
56
  self.delete_request(url)
57
- logger.info("Deleted single schedule (ID: {0})".format(schedule_id))
57
+ logger.info(f"Deleted single schedule (ID: {schedule_id})")
58
58
 
59
59
  @api(version="2.3")
60
60
  def update(self, schedule_item: ScheduleItem) -> ScheduleItem:
@@ -62,10 +62,10 @@ class Schedules(Endpoint):
62
62
  error = "Schedule item missing ID."
63
63
  raise MissingRequiredFieldError(error)
64
64
 
65
- url = "{0}/{1}".format(self.baseurl, schedule_item.id)
65
+ url = f"{self.baseurl}/{schedule_item.id}"
66
66
  update_req = RequestFactory.Schedule.update_req(schedule_item)
67
67
  server_response = self.put_request(url, update_req)
68
- logger.info("Updated schedule item (ID: {})".format(schedule_item.id))
68
+ logger.info(f"Updated schedule item (ID: {schedule_item.id})")
69
69
  updated_schedule = copy.copy(schedule_item)
70
70
  return updated_schedule._parse_common_tags(server_response.content, self.parent_srv.namespace)
71
71
 
@@ -79,7 +79,7 @@ class Schedules(Endpoint):
79
79
  create_req = RequestFactory.Schedule.create_req(schedule_item)
80
80
  server_response = self.post_request(url, create_req)
81
81
  new_schedule = ScheduleItem.from_response(server_response.content, self.parent_srv.namespace)[0]
82
- logger.info("Created new schedule (ID: {})".format(new_schedule.id))
82
+ logger.info(f"Created new schedule (ID: {new_schedule.id})")
83
83
  return new_schedule
84
84
 
85
85
  @api(version="2.8")
@@ -91,12 +91,12 @@ class Schedules(Endpoint):
91
91
  datasource: Optional["DatasourceItem"] = None,
92
92
  flow: Optional["FlowItem"] = None,
93
93
  task_type: Optional[str] = None,
94
- ) -> List[AddResponse]:
94
+ ) -> list[AddResponse]:
95
95
  # There doesn't seem to be a good reason to allow one item of each type?
96
96
  if workbook and datasource:
97
97
  warnings.warn("Passing in multiple items for add_to_schedule will be deprecated", PendingDeprecationWarning)
98
- items: List[
99
- Tuple[str, Union[WorkbookItem, FlowItem, DatasourceItem], str, Callable[[Optional[str], str], bytes], str]
98
+ items: list[
99
+ tuple[str, Union[WorkbookItem, FlowItem, DatasourceItem], str, Callable[[Optional[str], str], bytes], str]
100
100
  ] = []
101
101
 
102
102
  if workbook is not None:
@@ -115,8 +115,7 @@ class Schedules(Endpoint):
115
115
  ) # type:ignore[arg-type]
116
116
 
117
117
  results = (self._add_to(*x) for x in items)
118
- # list() is needed for python 3.x compatibility
119
- return list(filter(lambda x: not x.result, results)) # type:ignore[arg-type]
118
+ return [x for x in results if not x.result]
120
119
 
121
120
  def _add_to(
122
121
  self,
@@ -133,13 +132,13 @@ class Schedules(Endpoint):
133
132
  item_task_type,
134
133
  ) -> AddResponse:
135
134
  id_ = resource.id
136
- url = "{0}/{1}/{2}s".format(self.siteurl, schedule_id, type_)
135
+ url = f"{self.siteurl}/{schedule_id}/{type_}s"
137
136
  add_req = req_factory(id_, task_type=item_task_type) # type: ignore[call-arg, arg-type]
138
137
  response = self.put_request(url, add_req)
139
138
 
140
139
  error, warnings, task_created = ScheduleItem.parse_add_to_schedule_response(response, self.parent_srv.namespace)
141
140
  if task_created:
142
- logger.info("Added {} to {} to schedule {}".format(type_, id_, schedule_id))
141
+ logger.info(f"Added {type_} to {id_} to schedule {schedule_id}")
143
142
 
144
143
  if error is not None or warnings is not None:
145
144
  return AddResponse(
@@ -1,4 +1,5 @@
1
1
  import logging
2
+ from typing import Union
2
3
 
3
4
  from .endpoint import Endpoint, api
4
5
  from .exceptions import ServerResponseError
@@ -21,15 +22,49 @@ class ServerInfo(Endpoint):
21
22
  return self._info
22
23
 
23
24
  def __repr__(self):
24
- return "<Endpoint {}>".format(self.serverInfo)
25
+ return f"<Endpoint {self.serverInfo}>"
25
26
 
26
27
  @property
27
- def baseurl(self):
28
- return "{0}/serverInfo".format(self.parent_srv.baseurl)
28
+ def baseurl(self) -> str:
29
+ return f"{self.parent_srv.baseurl}/serverInfo"
29
30
 
30
31
  @api(version="2.4")
31
- def get(self):
32
- """Retrieve the server info for the server. This is an unauthenticated call"""
32
+ def get(self) -> Union[ServerInfoItem, None]:
33
+ """
34
+ Retrieve the build and version information for the server.
35
+
36
+ This method makes an unauthenticated call, so no sign in or
37
+ authentication token is required.
38
+
39
+ Returns
40
+ -------
41
+ :class:`~tableauserverclient.models.ServerInfoItem`
42
+
43
+ Raises
44
+ ------
45
+ :class:`~tableauserverclient.exceptions.ServerInfoEndpointNotFoundError`
46
+ Raised when the server info endpoint is not found.
47
+
48
+ :class:`~tableauserverclient.exceptions.EndpointUnavailableError`
49
+ Raised when the server info endpoint is not available.
50
+
51
+ Examples
52
+ --------
53
+ >>> import tableauserverclient as TSC
54
+
55
+ >>> # create a instance of server
56
+ >>> server = TSC.Server('https://MY-SERVER')
57
+
58
+ >>> # set the version number > 2.3
59
+ >>> # the server_info.get() method works in 2.4 and later
60
+ >>> server.version = '2.5'
61
+
62
+ >>> s_info = server.server_info.get()
63
+ >>> print("\nServer info:")
64
+ >>> print("\tProduct version: {0}".format(s_info.product_version))
65
+ >>> print("\tREST API version: {0}".format(s_info.rest_api_version))
66
+ >>> print("\tBuild number: {0}".format(s_info.build_number))
67
+ """
33
68
  try:
34
69
  server_response = self.get_unauthenticated_request(self.baseurl)
35
70
  except ServerResponseError as e: