Skip to content

Commit

Permalink
Merge branch 'development' into jorwoods/deprecated_cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
jacalata committed Jun 15, 2024
2 parents daace10 + 2f8fd5d commit 16262e9
Show file tree
Hide file tree
Showing 8 changed files with 174 additions and 5 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -156,3 +156,4 @@ docs/_site/
docs/.jekyll-metadata
docs/Gemfile.lock
samples/credentials
.venv/
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ classifiers = [
repository = "https://github.com/tableau/server-client-python"

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

[tool.black]
Expand Down
12 changes: 12 additions & 0 deletions tableauserverclient/models/datasource_item.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ def __init__(self, project_id: Optional[str] = None, name: Optional[str] = None)
self._initial_tags: Set = set()
self._project_name: Optional[str] = None
self._revisions = None
self._size: Optional[int] = None
self._updated_at = None
self._use_remote_query_agent = None
self._webpage_url = None
Expand Down Expand Up @@ -182,6 +183,10 @@ def revisions(self) -> List[RevisionItem]:
raise UnpopulatedPropertyError(error)
return self._revisions()

@property
def size(self) -> Optional[int]:
return self._size

def _set_connections(self, connections):
self._connections = connections

Expand Down Expand Up @@ -217,6 +222,7 @@ def _parse_common_elements(self, datasource_xml, ns):
updated_at,
use_remote_query_agent,
webpage_url,
size,
) = self._parse_element(datasource_xml, ns)
self._set_values(
ask_data_enablement,
Expand All @@ -237,6 +243,7 @@ def _parse_common_elements(self, datasource_xml, ns):
updated_at,
use_remote_query_agent,
webpage_url,
size,
)
return self

Expand All @@ -260,6 +267,7 @@ def _set_values(
updated_at,
use_remote_query_agent,
webpage_url,
size,
):
if ask_data_enablement is not None:
self._ask_data_enablement = ask_data_enablement
Expand Down Expand Up @@ -297,6 +305,8 @@ def _set_values(
self._use_remote_query_agent = str(use_remote_query_agent).lower() == "true"
if webpage_url:
self._webpage_url = webpage_url
if size is not None:
self._size = int(size)

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

tags = None
tags_elem = datasource_xml.find(".//t:tags", namespaces=ns)
Expand Down Expand Up @@ -372,4 +383,5 @@ def _parse_element(datasource_xml: ET.Element, ns: Dict) -> Tuple:
updated_at,
use_remote_query_agent,
webpage_url,
size,
)
47 changes: 46 additions & 1 deletion tableauserverclient/models/permissions_item.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,14 +45,59 @@ def __repr__(self):
return "<Enum Capability: AddComment | ChangeHierarchy | ChangePermission ... (17 more) >"


class PermissionsRule(object):
class PermissionsRule:
def __init__(self, grantee: ResourceReference, capabilities: Dict[str, str]) -> None:
self.grantee = grantee
self.capabilities = capabilities

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

def __eq__(self, other: object) -> bool:
if not hasattr(other, "grantee") or not hasattr(other, "capabilities"):
return False
return self.grantee == other.grantee and self.capabilities == other.capabilities

def __and__(self, other: "PermissionsRule") -> "PermissionsRule":
if self.grantee != other.grantee:
raise ValueError("Cannot AND two permissions rules with different grantees")

if self.capabilities == other.capabilities:
return self

capabilities = set((*self.capabilities.keys(), *other.capabilities.keys()))
new_capabilities = {}
for capability in capabilities:
if (self.capabilities.get(capability), other.capabilities.get(capability)) == (
Permission.Mode.Allow,
Permission.Mode.Allow,
):
new_capabilities[capability] = Permission.Mode.Allow
elif Permission.Mode.Deny in (self.capabilities.get(capability), other.capabilities.get(capability)):
new_capabilities[capability] = Permission.Mode.Deny

return PermissionsRule(self.grantee, new_capabilities)

def __or__(self, other: "PermissionsRule") -> "PermissionsRule":
if self.grantee != other.grantee:
raise ValueError("Cannot OR two permissions rules with different grantees")

if self.capabilities == other.capabilities:
return self

capabilities = set((*self.capabilities.keys(), *other.capabilities.keys()))
new_capabilities = {}
for capability in capabilities:
if Permission.Mode.Allow in (self.capabilities.get(capability), other.capabilities.get(capability)):
new_capabilities[capability] = Permission.Mode.Allow
elif (self.capabilities.get(capability), other.capabilities.get(capability)) == (
Permission.Mode.Deny,
Permission.Mode.Deny,
):
new_capabilities[capability] = Permission.Mode.Deny

return PermissionsRule(self.grantee, new_capabilities)

@classmethod
def from_response(cls, resp, ns=None) -> List["PermissionsRule"]:
parsed_response = fromstring(resp)
Expand Down
5 changes: 5 additions & 0 deletions tableauserverclient/models/reference_item.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ def __str__(self):

__repr__ = __str__

def __eq__(self, other: object) -> bool:
if not hasattr(other, "id") or not hasattr(other, "tag_name"):
return False
return (self.id == other.id) and (self.tag_name == other.tag_name)

@property
def id(self):
return self._id
Expand Down
6 changes: 3 additions & 3 deletions test/assets/datasource_get.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
<tsResponse xmlns="http://tableau.com/api" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://tableau.com/api http://tableau.com/api/ts-api-2.3.xsd">
<pagination pageNumber="1" pageSize="100" totalAvailable="2" />
<datasources>
<datasource id="e76a1461-3b1d-4588-bf1b-17551a879ad9" name="SampleDS" contentUrl="SampleDS" description="SampleDsDescription" type="dataengine" createdAt="2016-08-11T21:22:40Z" updatedAt="2016-08-11T21:34:17Z" encryptExtracts="false" hasExtracts="true" useRemoteQueryAgent="false" webpageUrl="https://web.com">
<datasource id="e76a1461-3b1d-4588-bf1b-17551a879ad9" name="SampleDS" size="4096" contentUrl="SampleDS" description="SampleDsDescription" type="dataengine" createdAt="2016-08-11T21:22:40Z" updatedAt="2016-08-11T21:34:17Z" encryptExtracts="false" hasExtracts="true" useRemoteQueryAgent="false" webpageUrl="https://web.com">
<project id="ee8c6e70-43b6-11e6-af4f-f7b0d8e20760" name="default" />
<owner id="5de011f8-5aa9-4d5b-b991-f462c8dd6bb7" />
<tags />
</datasource>
<datasource id="9dbd2263-16b5-46e1-9c43-a76bb8ab65fb" name="Sample datasource" description="description Sample" contentUrl="Sampledatasource" type="dataengine" createdAt="2016-08-04T21:31:55Z" updatedAt="2016-08-04T21:31:55Z" encryptExtracts="true" hasExtracts="false" useRemoteQueryAgent="true" webpageUrl="https://page.com">
<datasource id="9dbd2263-16b5-46e1-9c43-a76bb8ab65fb" name="Sample datasource" description="description Sample" size="10240" contentUrl="Sampledatasource" type="dataengine" createdAt="2016-08-04T21:31:55Z" updatedAt="2016-08-04T21:31:55Z" encryptExtracts="true" hasExtracts="false" useRemoteQueryAgent="true" webpageUrl="https://page.com">
<project id="ee8c6e70-43b6-11e6-af4f-f7b0d8e20760" name="default" />
<owner id="5de011f8-5aa9-4d5b-b991-f462c8dd6bb7" />
<tags>
Expand All @@ -17,4 +17,4 @@
</tags>
</datasource>
</datasources>
</tsResponse>
</tsResponse>
2 changes: 2 additions & 0 deletions test/test_datasource.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ def test_get(self) -> None:
self.assertEqual("dataengine", all_datasources[0].datasource_type)
self.assertEqual("SampleDsDescription", all_datasources[0].description)
self.assertEqual("SampleDS", all_datasources[0].content_url)
self.assertEqual(4096, all_datasources[0].size)
self.assertEqual("2016-08-11T21:22:40Z", format_datetime(all_datasources[0].created_at))
self.assertEqual("2016-08-11T21:34:17Z", format_datetime(all_datasources[0].updated_at))
self.assertEqual("default", all_datasources[0].project_name)
Expand All @@ -67,6 +68,7 @@ def test_get(self) -> None:
self.assertEqual("dataengine", all_datasources[1].datasource_type)
self.assertEqual("description Sample", all_datasources[1].description)
self.assertEqual("Sampledatasource", all_datasources[1].content_url)
self.assertEqual(10240, all_datasources[1].size)
self.assertEqual("2016-08-04T21:31:55Z", format_datetime(all_datasources[1].created_at))
self.assertEqual("2016-08-04T21:31:55Z", format_datetime(all_datasources[1].updated_at))
self.assertEqual("default", all_datasources[1].project_name)
Expand Down
104 changes: 104 additions & 0 deletions test/test_permissionsrule.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import unittest

import tableauserverclient as TSC
from tableauserverclient.models.reference_item import ResourceReference


class TestPermissionsRules(unittest.TestCase):
def test_and(self):
grantee = ResourceReference("a", "user")
rule1 = TSC.PermissionsRule(
grantee,
{
TSC.Permission.Capability.ExportData: TSC.Permission.Mode.Allow,
TSC.Permission.Capability.Delete: TSC.Permission.Mode.Deny,
TSC.Permission.Capability.ViewComments: TSC.Permission.Mode.Allow,
TSC.Permission.Capability.ExportXml: TSC.Permission.Mode.Deny,
},
)
rule2 = TSC.PermissionsRule(
grantee,
{
TSC.Permission.Capability.ExportData: TSC.Permission.Mode.Allow,
TSC.Permission.Capability.Delete: TSC.Permission.Mode.Allow,
TSC.Permission.Capability.ExportXml: TSC.Permission.Mode.Deny,
},
)

composite = rule1 & rule2

self.assertEqual(composite.capabilities.get(TSC.Permission.Capability.ExportData), TSC.Permission.Mode.Allow)
self.assertEqual(composite.capabilities.get(TSC.Permission.Capability.Delete), TSC.Permission.Mode.Deny)
self.assertEqual(composite.capabilities.get(TSC.Permission.Capability.ViewComments), None)
self.assertEqual(composite.capabilities.get(TSC.Permission.Capability.ExportXml), TSC.Permission.Mode.Deny)

def test_or(self):
grantee = ResourceReference("a", "user")
rule1 = TSC.PermissionsRule(
grantee,
{
TSC.Permission.Capability.ExportData: TSC.Permission.Mode.Allow,
TSC.Permission.Capability.Delete: TSC.Permission.Mode.Deny,
TSC.Permission.Capability.ViewComments: TSC.Permission.Mode.Allow,
TSC.Permission.Capability.ExportXml: TSC.Permission.Mode.Deny,
},
)
rule2 = TSC.PermissionsRule(
grantee,
{
TSC.Permission.Capability.ExportData: TSC.Permission.Mode.Allow,
TSC.Permission.Capability.Delete: TSC.Permission.Mode.Allow,
TSC.Permission.Capability.ExportXml: TSC.Permission.Mode.Deny,
},
)

composite = rule1 | rule2

self.assertEqual(composite.capabilities.get(TSC.Permission.Capability.ExportData), TSC.Permission.Mode.Allow)
self.assertEqual(composite.capabilities.get(TSC.Permission.Capability.Delete), TSC.Permission.Mode.Allow)
self.assertEqual(composite.capabilities.get(TSC.Permission.Capability.ViewComments), TSC.Permission.Mode.Allow)
self.assertEqual(composite.capabilities.get(TSC.Permission.Capability.ExportXml), TSC.Permission.Mode.Deny)

def test_eq_false(self):
grantee = ResourceReference("a", "user")
rule1 = TSC.PermissionsRule(
grantee,
{
TSC.Permission.Capability.ExportData: TSC.Permission.Mode.Allow,
TSC.Permission.Capability.Delete: TSC.Permission.Mode.Deny,
TSC.Permission.Capability.ViewComments: TSC.Permission.Mode.Allow,
TSC.Permission.Capability.ExportXml: TSC.Permission.Mode.Deny,
},
)
rule2 = TSC.PermissionsRule(
grantee,
{
TSC.Permission.Capability.ExportData: TSC.Permission.Mode.Allow,
TSC.Permission.Capability.Delete: TSC.Permission.Mode.Allow,
TSC.Permission.Capability.ExportXml: TSC.Permission.Mode.Deny,
},
)

self.assertNotEqual(rule1, rule2)

def test_eq_true(self):
grantee = ResourceReference("a", "user")
rule1 = TSC.PermissionsRule(
grantee,
{
TSC.Permission.Capability.ExportData: TSC.Permission.Mode.Allow,
TSC.Permission.Capability.Delete: TSC.Permission.Mode.Deny,
TSC.Permission.Capability.ViewComments: TSC.Permission.Mode.Allow,
TSC.Permission.Capability.ExportXml: TSC.Permission.Mode.Deny,
},
)
rule2 = TSC.PermissionsRule(
grantee,
{
TSC.Permission.Capability.ExportData: TSC.Permission.Mode.Allow,
TSC.Permission.Capability.Delete: TSC.Permission.Mode.Deny,
TSC.Permission.Capability.ViewComments: TSC.Permission.Mode.Allow,
TSC.Permission.Capability.ExportXml: TSC.Permission.Mode.Deny,
},
)
self.assertEqual(rule1, rule2)

0 comments on commit 16262e9

Please sign in to comment.