Skip to content

Commit c9bf9af

Browse files
authored
Merge branch 'development' into patch-1
2 parents bae9dd0 + 7a8e54e commit c9bf9af

37 files changed

+742
-455
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -156,3 +156,4 @@ docs/_site/
156156
docs/.jekyll-metadata
157157
docs/Gemfile.lock
158158
samples/credentials
159+
.venv/

pyproject.toml

+3-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ classifiers = [
3232
repository = "https://github.com/tableau/server-client-python"
3333

3434
[project.optional-dependencies]
35-
test = ["argparse", "black==23.7", "mock", "mypy==1.4", "pytest>=7.0", "pytest-cov", "pytest-subtests",
35+
test = ["black==23.7", "build", "mypy==1.4", "pytest>=7.0", "pytest-cov", "pytest-subtests",
3636
"requests-mock>=1.0,<2.0"]
3737

3838
[tool.black]
@@ -49,6 +49,8 @@ disable_error_code = [
4949
files = ["tableauserverclient", "test"]
5050
show_error_codes = true
5151
ignore_missing_imports = true # defusedxml library has no types
52+
no_implicit_reexport = true
53+
5254
[tool.pytest.ini_options]
5355
testpaths = ["test"]
5456
addopts = "--junitxml=./test.junit.xml"

tableauserverclient/__init__.py

+64-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
from ._version import get_versions
2-
from .namespace import NEW_NAMESPACE as DEFAULT_NAMESPACE
3-
from .models import (
1+
from tableauserverclient._version import get_versions
2+
from tableauserverclient.namespace import NEW_NAMESPACE as DEFAULT_NAMESPACE
3+
from tableauserverclient.models import (
44
BackgroundJobItem,
55
ColumnItem,
66
ConnectionCredentials,
@@ -43,7 +43,8 @@
4343
WeeklyInterval,
4444
WorkbookItem,
4545
)
46-
from .server import (
46+
47+
from tableauserverclient.server import (
4748
CSVRequestOptions,
4849
ExcelRequestOptions,
4950
ImageRequestOptions,
@@ -57,3 +58,62 @@
5758
Server,
5859
Sort,
5960
)
61+
62+
__all__ = [
63+
"get_versions",
64+
"DEFAULT_NAMESPACE",
65+
"BackgroundJobItem",
66+
"BackgroundJobItem",
67+
"ColumnItem",
68+
"ConnectionCredentials",
69+
"ConnectionItem",
70+
"CustomViewItem",
71+
"DQWItem",
72+
"DailyInterval",
73+
"DataAlertItem",
74+
"DatabaseItem",
75+
"DataFreshnessPolicyItem",
76+
"DatasourceItem",
77+
"FavoriteItem",
78+
"FlowItem",
79+
"FlowRunItem",
80+
"FileuploadItem",
81+
"GroupItem",
82+
"HourlyInterval",
83+
"IntervalItem",
84+
"JobItem",
85+
"JWTAuth",
86+
"MetricItem",
87+
"MonthlyInterval",
88+
"PaginationItem",
89+
"Permission",
90+
"PermissionsRule",
91+
"PersonalAccessTokenAuth",
92+
"ProjectItem",
93+
"RevisionItem",
94+
"ScheduleItem",
95+
"SiteItem",
96+
"ServerInfoItem",
97+
"SubscriptionItem",
98+
"TableItem",
99+
"TableauAuth",
100+
"Target",
101+
"TaskItem",
102+
"UserItem",
103+
"ViewItem",
104+
"WebhookItem",
105+
"WeeklyInterval",
106+
"WorkbookItem",
107+
"CSVRequestOptions",
108+
"ExcelRequestOptions",
109+
"ImageRequestOptions",
110+
"PDFRequestOptions",
111+
"RequestOptions",
112+
"MissingRequiredFieldError",
113+
"NotSignedInError",
114+
"ServerResponseError",
115+
"Filter",
116+
"Pager",
117+
"Server",
118+
"Sort",
119+
]
+88-37
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,94 @@
1-
from .column_item import ColumnItem
2-
from .connection_credentials import ConnectionCredentials
3-
from .connection_item import ConnectionItem
4-
from .custom_view_item import CustomViewItem
5-
from .data_acceleration_report_item import DataAccelerationReportItem
6-
from .data_alert_item import DataAlertItem
7-
from .database_item import DatabaseItem
8-
from .data_freshness_policy_item import DataFreshnessPolicyItem
9-
from .datasource_item import DatasourceItem
10-
from .dqw_item import DQWItem
11-
from .exceptions import UnpopulatedPropertyError
12-
from .favorites_item import FavoriteItem
13-
from .fileupload_item import FileuploadItem
14-
from .flow_item import FlowItem
15-
from .flow_run_item import FlowRunItem
16-
from .group_item import GroupItem
17-
from .interval_item import (
1+
from tableauserverclient.models.column_item import ColumnItem
2+
from tableauserverclient.models.connection_credentials import ConnectionCredentials
3+
from tableauserverclient.models.connection_item import ConnectionItem
4+
from tableauserverclient.models.custom_view_item import CustomViewItem
5+
from tableauserverclient.models.data_acceleration_report_item import DataAccelerationReportItem
6+
from tableauserverclient.models.data_alert_item import DataAlertItem
7+
from tableauserverclient.models.database_item import DatabaseItem
8+
from tableauserverclient.models.data_freshness_policy_item import DataFreshnessPolicyItem
9+
from tableauserverclient.models.datasource_item import DatasourceItem
10+
from tableauserverclient.models.dqw_item import DQWItem
11+
from tableauserverclient.models.exceptions import UnpopulatedPropertyError
12+
from tableauserverclient.models.favorites_item import FavoriteItem
13+
from tableauserverclient.models.fileupload_item import FileuploadItem
14+
from tableauserverclient.models.flow_item import FlowItem
15+
from tableauserverclient.models.flow_run_item import FlowRunItem
16+
from tableauserverclient.models.group_item import GroupItem
17+
from tableauserverclient.models.interval_item import (
1818
IntervalItem,
1919
DailyInterval,
2020
WeeklyInterval,
2121
MonthlyInterval,
2222
HourlyInterval,
2323
)
24-
from .job_item import JobItem, BackgroundJobItem
25-
from .metric_item import MetricItem
26-
from .pagination_item import PaginationItem
27-
from .permissions_item import PermissionsRule, Permission
28-
from .project_item import ProjectItem
29-
from .revision_item import RevisionItem
30-
from .schedule_item import ScheduleItem
31-
from .server_info_item import ServerInfoItem
32-
from .site_item import SiteItem
33-
from .subscription_item import SubscriptionItem
34-
from .table_item import TableItem
35-
from .tableau_auth import Credentials, TableauAuth, PersonalAccessTokenAuth, JWTAuth
36-
from .tableau_types import Resource, TableauItem, plural_type
37-
from .tag_item import TagItem
38-
from .target import Target
39-
from .task_item import TaskItem
40-
from .user_item import UserItem
41-
from .view_item import ViewItem
42-
from .webhook_item import WebhookItem
43-
from .workbook_item import WorkbookItem
24+
from tableauserverclient.models.job_item import JobItem, BackgroundJobItem
25+
from tableauserverclient.models.metric_item import MetricItem
26+
from tableauserverclient.models.pagination_item import PaginationItem
27+
from tableauserverclient.models.permissions_item import PermissionsRule, Permission
28+
from tableauserverclient.models.project_item import ProjectItem
29+
from tableauserverclient.models.revision_item import RevisionItem
30+
from tableauserverclient.models.schedule_item import ScheduleItem
31+
from tableauserverclient.models.server_info_item import ServerInfoItem
32+
from tableauserverclient.models.site_item import SiteItem
33+
from tableauserverclient.models.subscription_item import SubscriptionItem
34+
from tableauserverclient.models.table_item import TableItem
35+
from tableauserverclient.models.tableau_auth import Credentials, TableauAuth, PersonalAccessTokenAuth, JWTAuth
36+
from tableauserverclient.models.tableau_types import Resource, TableauItem, plural_type
37+
from tableauserverclient.models.tag_item import TagItem
38+
from tableauserverclient.models.target import Target
39+
from tableauserverclient.models.task_item import TaskItem
40+
from tableauserverclient.models.user_item import UserItem
41+
from tableauserverclient.models.view_item import ViewItem
42+
from tableauserverclient.models.webhook_item import WebhookItem
43+
from tableauserverclient.models.workbook_item import WorkbookItem
44+
45+
__all__ = [
46+
"ColumnItem",
47+
"ConnectionCredentials",
48+
"ConnectionItem",
49+
"Credentials",
50+
"CustomViewItem",
51+
"DataAccelerationReportItem",
52+
"DataAlertItem",
53+
"DatabaseItem",
54+
"DataFreshnessPolicyItem",
55+
"DatasourceItem",
56+
"DQWItem",
57+
"UnpopulatedPropertyError",
58+
"FavoriteItem",
59+
"FileuploadItem",
60+
"FlowItem",
61+
"FlowRunItem",
62+
"GroupItem",
63+
"IntervalItem",
64+
"JobItem",
65+
"DailyInterval",
66+
"WeeklyInterval",
67+
"MonthlyInterval",
68+
"HourlyInterval",
69+
"BackgroundJobItem",
70+
"MetricItem",
71+
"PaginationItem",
72+
"Permission",
73+
"PermissionsRule",
74+
"ProjectItem",
75+
"RevisionItem",
76+
"ScheduleItem",
77+
"ServerInfoItem",
78+
"SiteItem",
79+
"SubscriptionItem",
80+
"TableItem",
81+
"TableauAuth",
82+
"PersonalAccessTokenAuth",
83+
"JWTAuth",
84+
"Resource",
85+
"TableauItem",
86+
"plural_type",
87+
"TagItem",
88+
"Target",
89+
"TaskItem",
90+
"UserItem",
91+
"ViewItem",
92+
"WebhookItem",
93+
"WorkbookItem",
94+
]

tableauserverclient/models/datasource_item.py

+12
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ def __init__(self, project_id: Optional[str] = None, name: Optional[str] = None)
4747
self._initial_tags: Set = set()
4848
self._project_name: Optional[str] = None
4949
self._revisions = None
50+
self._size: Optional[int] = None
5051
self._updated_at = None
5152
self._use_remote_query_agent = None
5253
self._webpage_url = None
@@ -182,6 +183,10 @@ def revisions(self) -> List[RevisionItem]:
182183
raise UnpopulatedPropertyError(error)
183184
return self._revisions()
184185

186+
@property
187+
def size(self) -> Optional[int]:
188+
return self._size
189+
185190
def _set_connections(self, connections):
186191
self._connections = connections
187192

@@ -217,6 +222,7 @@ def _parse_common_elements(self, datasource_xml, ns):
217222
updated_at,
218223
use_remote_query_agent,
219224
webpage_url,
225+
size,
220226
) = self._parse_element(datasource_xml, ns)
221227
self._set_values(
222228
ask_data_enablement,
@@ -237,6 +243,7 @@ def _parse_common_elements(self, datasource_xml, ns):
237243
updated_at,
238244
use_remote_query_agent,
239245
webpage_url,
246+
size,
240247
)
241248
return self
242249

@@ -260,6 +267,7 @@ def _set_values(
260267
updated_at,
261268
use_remote_query_agent,
262269
webpage_url,
270+
size,
263271
):
264272
if ask_data_enablement is not None:
265273
self._ask_data_enablement = ask_data_enablement
@@ -297,6 +305,8 @@ def _set_values(
297305
self._use_remote_query_agent = str(use_remote_query_agent).lower() == "true"
298306
if webpage_url:
299307
self._webpage_url = webpage_url
308+
if size is not None:
309+
self._size = int(size)
300310

301311
@classmethod
302312
def from_response(cls, resp: str, ns: Dict) -> List["DatasourceItem"]:
@@ -330,6 +340,7 @@ def _parse_element(datasource_xml: ET.Element, ns: Dict) -> Tuple:
330340
has_extracts = datasource_xml.get("hasExtracts", None)
331341
use_remote_query_agent = datasource_xml.get("useRemoteQueryAgent", None)
332342
webpage_url = datasource_xml.get("webpageUrl", None)
343+
size = datasource_xml.get("size", None)
333344

334345
tags = None
335346
tags_elem = datasource_xml.find(".//t:tags", namespaces=ns)
@@ -372,4 +383,5 @@ def _parse_element(datasource_xml: ET.Element, ns: Dict) -> Tuple:
372383
updated_at,
373384
use_remote_query_agent,
374385
webpage_url,
386+
size,
375387
)

tableauserverclient/models/permissions_item.py

+46-1
Original file line numberDiff line numberDiff line change
@@ -45,14 +45,59 @@ def __repr__(self):
4545
return "<Enum Capability: AddComment | ChangeHierarchy | ChangePermission ... (17 more) >"
4646

4747

48-
class PermissionsRule(object):
48+
class PermissionsRule:
4949
def __init__(self, grantee: ResourceReference, capabilities: Dict[str, str]) -> None:
5050
self.grantee = grantee
5151
self.capabilities = capabilities
5252

5353
def __repr__(self):
5454
return "<PermissionsRule grantee={}, capabilities={}>".format(self.grantee, self.capabilities)
5555

56+
def __eq__(self, other: object) -> bool:
57+
if not hasattr(other, "grantee") or not hasattr(other, "capabilities"):
58+
return False
59+
return self.grantee == other.grantee and self.capabilities == other.capabilities
60+
61+
def __and__(self, other: "PermissionsRule") -> "PermissionsRule":
62+
if self.grantee != other.grantee:
63+
raise ValueError("Cannot AND two permissions rules with different grantees")
64+
65+
if self.capabilities == other.capabilities:
66+
return self
67+
68+
capabilities = set((*self.capabilities.keys(), *other.capabilities.keys()))
69+
new_capabilities = {}
70+
for capability in capabilities:
71+
if (self.capabilities.get(capability), other.capabilities.get(capability)) == (
72+
Permission.Mode.Allow,
73+
Permission.Mode.Allow,
74+
):
75+
new_capabilities[capability] = Permission.Mode.Allow
76+
elif Permission.Mode.Deny in (self.capabilities.get(capability), other.capabilities.get(capability)):
77+
new_capabilities[capability] = Permission.Mode.Deny
78+
79+
return PermissionsRule(self.grantee, new_capabilities)
80+
81+
def __or__(self, other: "PermissionsRule") -> "PermissionsRule":
82+
if self.grantee != other.grantee:
83+
raise ValueError("Cannot OR two permissions rules with different grantees")
84+
85+
if self.capabilities == other.capabilities:
86+
return self
87+
88+
capabilities = set((*self.capabilities.keys(), *other.capabilities.keys()))
89+
new_capabilities = {}
90+
for capability in capabilities:
91+
if Permission.Mode.Allow in (self.capabilities.get(capability), other.capabilities.get(capability)):
92+
new_capabilities[capability] = Permission.Mode.Allow
93+
elif (self.capabilities.get(capability), other.capabilities.get(capability)) == (
94+
Permission.Mode.Deny,
95+
Permission.Mode.Deny,
96+
):
97+
new_capabilities[capability] = Permission.Mode.Deny
98+
99+
return PermissionsRule(self.grantee, new_capabilities)
100+
56101
@classmethod
57102
def from_response(cls, resp, ns=None) -> List["PermissionsRule"]:
58103
parsed_response = fromstring(resp)

tableauserverclient/models/reference_item.py

+5
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@ def __str__(self):
88

99
__repr__ = __str__
1010

11+
def __eq__(self, other: object) -> bool:
12+
if not hasattr(other, "id") or not hasattr(other, "tag_name"):
13+
return False
14+
return (self.id == other.id) and (self.tag_name == other.tag_name)
15+
1116
@property
1217
def id(self):
1318
return self._id

0 commit comments

Comments
 (0)