8000 v0.38 - IDP configuration by jacalata · Pull Request #1606 · tableau/server-client-python · GitHub
[go: up one dir, main page]

Skip to content

v0.38 - IDP configuration #1606
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
May 15, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/slack.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ on: [push, pull_request, issues]
jobs:
slack-notifications:
continue-on-error: true
runs-on: ubuntu-20.04
runs-on: ubuntu-latest
name: Sends a message to Slack when a push, a pull request or an issue is made
steps:
- name: Send message to Slack API
Expand Down
1 change: 0 additions & 1 deletion samples/extracts.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ def main():
server.add_http_options({"verify": False})
server.use_server_version()
with server.auth.sign_in(tableau_auth):

wb = None
ds = None
if args.workbook:
Expand Down
4 changes: 4 additions & 0 deletions tableauserverclient/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
LinkedTaskItem,
LinkedTaskStepItem,
LinkedTaskFlowRunItem,
LocationItem,
MetricItem,
MonthlyInterval,
PaginationItem,
Expand All @@ -35,6 +36,7 @@
Resource,
RevisionItem,
ScheduleItem,
SiteAuthConfiguration,
SiteItem,
ServerInfoItem,
SubscriptionItem,
Expand Down Expand Up @@ -101,6 +103,7 @@
"LinkedTaskFlowRunItem",
"LinkedTaskItem",
"LinkedTaskStepItem",
"LocationItem",
"MetricItem",
"MissingRequiredFieldError",
"MonthlyInterval",
Expand All @@ -121,6 +124,7 @@
"ServerInfoItem",
"ServerResponseError",
"SiteItem",
"SiteAuthConfiguration",
"Sort",
"SubscriptionItem",
"TableauAuth",
Expand Down
26 changes: 25 additions & 1 deletion tableauserverclient/helpers/strings.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from defusedxml.ElementTree import fromstring, tostring
from functools import singledispatch
from typing import TypeVar
from typing import TypeVar, overload


# the redact method can handle either strings or bytes, but it can't mix them.
Expand Down Expand Up @@ -41,3 +41,27 @@ def _(xml: str) -> str:
@redact_xml.register # type: ignore[no-redef]
def _(xml: bytes) -> bytes:
return _redact_any_type(bytearray(xml), b"password", b"..[redacted]")


@overload
def nullable_str_to_int(value: None) -> None: ...


@overload
def nullable_str_to_int(value: str) -> int: ...


def nullable_str_to_int(value):
return int(value) if value is not None else None


@overload
def nullable_str_to_bool(value: None) -> None: ...


@overload
def nullable_str_to_bool(value: str) -> bool: ...


def nullable_str_to_bool(value):
return str(value).lower() == "true" if value is not None else None
7 changes: 6 additions & 1 deletion tableauserverclient/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,15 @@
LinkedTaskStepItem,
LinkedTaskFlowRunItem,
)
from tableauserverclient.models.location_item import LocationItem
from tableauserverclient.models.metric_item import MetricItem
from tableauserverclient.models.pagination_item import PaginationItem
from tableauserverclient.models.permissions_item import PermissionsRule, Permission
from tableauserverclient.models.project_item import ProjectItem
from tableauserverclient.models.revision_item import RevisionItem
from tableauserverclient.models.schedule_item import ScheduleItem
from tableauserverclient.models.server_info_item import ServerInfoItem
from tableauserverclient.models.site_item import SiteItem
from tableauserverclient.models.site_item import SiteItem, SiteAuthConfiguration
from tableauserverclient.models.subscription_item import SubscriptionItem
from tableauserverclient.models.table_item import TableItem
from tableauserverclient.models.tableau_auth import Credentials, TableauAuth, PersonalAccessTokenAuth, JWTAuth
Expand All @@ -48,6 +49,7 @@
from tableauserverclient.models.virtual_connection_item import VirtualConnectionItem
from tableauserverclient.models.webhook_item import WebhookItem
from tableauserverclient.models.workbook_item import WorkbookItem
from tableauserverclient.models.extract_item import ExtractItem

__all__ = [
"ColumnItem",
Expand Down Expand Up @@ -75,6 +77,7 @@
"MonthlyInterval",
"HourlyInterval",
"BackgroundJobItem",
"LocationItem",
"MetricItem",
"PaginationItem",
"Permission",
Expand All @@ -83,6 +86,7 @@
"RevisionItem",
"ScheduleItem",
"ServerInfoItem",
"SiteAuthConfiguration",
"SiteItem",
"SubscriptionItem",
"TableItem",
Expand All @@ -103,4 +107,5 @@
"LinkedTaskItem",
"LinkedTaskStepItem",
"LinkedTaskFlowRunItem",
"ExtractItem",
]
112 changes: 110 additions & 2 deletions tableauserverclient/models/datasource_item.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,19 @@
from defusedxml.ElementTree import fromstring

from tableauserverclient.datetime_helpers import parse_datetime
from tableauserverclient.helpers.strings import nullable_str_to_bool, nullable_str_to_int
from tableauserverclient.models.connection_item import ConnectionItem
from tableauserverclient.models.exceptions import UnpopulatedPropertyError
from tableauserverclient.models.permissions_item import PermissionsRule
from tableauserverclient.models.project_item import ProjectItem
from tableauserverclient.models.property_decorators import (
property_not_nullable,
property_is_boolean,
property_is_enum,
)
from tableauserverclient.models.revision_item import RevisionItem
from tableauserverclient.models.tag_item import TagItem
from tableauserverclient.models.user_item import UserItem


class DatasourceItem:
Expand All @@ -40,6 +43,9 @@ class DatasourceItem:
specified, it will default to SiteDefault. See REST API Publish
Datasource for more information about ask_data_enablement.

connected_workbooks_count : Optional[int]
The number of workbooks connected to the datasource.

connections : list[ConnectionItem]
The list of data connections (ConnectionItem) for the specified data
source. You must first call the populate_connections method to access
Expand Down Expand Up @@ -67,6 +73,12 @@ class DatasourceItem:
A Boolean value to determine if a datasource should be encrypted or not.
See Extract and Encryption Methods for more information.

favorites_total : Optional[int]
The number of users who have marked the data source as a favorite.

has_alert : Optional[bool]
A Boolean value that indicates whether the data source has an alert.

has_extracts : Optional[bool]
A Boolean value that indicates whether the datasource has extracts.

Expand All @@ -75,20 +87,32 @@ class DatasourceItem:
specific data source or to delete a data source with the get_by_id and
delete methods.

is_published : Optional[bool]
A Boolean value that indicates whether the data source is published.

name : Optional[str]
The name of the data source. If not specified, the name of the published
data source file is used.

owner: Optional[UserItem]
The owner of the data source.

owner_id : Optional[str]
The identifier of the owner of the data source.

project : Optional[ProjectItem]
The project that the data source belongs to.

project_id : Optional[str]
The identifier of the project associated with the data source. You must
provide this identifier when you create an instance of a DatasourceItem.

project_name : Optional[str]
The name of the project associated with the data source.

server_name : Optional[str]
The name of the server where the data source is published.

tags : Optional[set[str]]
The tags (list of strings) that have been added to the data source.

Expand Down Expand Up @@ -143,6 +167,13 @@ def __init__(self, project_id: Optional[str] = None, name: Optional[str] = None)
self.owner_id: Optional[str] = None
self.project_id: Optional[str] = project_id
self.tags: set[str] = set()
self._connected_workbooks_count: Optional[int] = None
self._favorites_total: Optional[int] = None
self._has_alert: Optional[bool] = None
self._is_published: Optional[bool] = None
self._server_name: Optional[str] = None
self._project: Optional[ProjectItem] = None
self._owner: Optional[UserItem] = None

self._permissions = None
self._data_quality_warnings = None
Expand Down Expand Up @@ -274,14 +305,42 @@ def revisions(self) -> list[RevisionItem]:
def size(self) -> Optional[int]:
return self._size

@property
def connected_workbooks_count(self) -> Optional[int]:
return self._connected_workbooks_count

@property
def favorites_total(self) -> Optional[int]:
return self._favorites_total

@property
def has_alert(self) -> Optional[bool]:
return self._has_alert

@property
def is_published(self) -> Optional[bool]:
return self._is_published

@property
def server_name(self) -> Optional[str]:
return self._server_name

@property
def project(self) -> Optional[ProjectItem]:
return self._project

@property
def owner(self) -> Optional[UserItem]:
return self._owner

def _set_connections(self, connections) -> None:
self._connections = connections

def _set_permissions(self, permissions):
self._permissions = permissions

def _set_data_quality_warnings(self, dqws):
self._data_quality_warnings = dqws
def _set_data_quality_warnings(self, dqw):
self._data_quality_warnings = dqw

def _set_revisions(self, revisions):
self._revisions = revisions
Expand Down Expand Up @@ -310,6 +369,13 @@ def _parse_common_elements(self, datasource_xml, ns):
use_remote_query_agent,
webpage_url,
size,
connected_workbooks_count,
favorites_total,
has_alert,
is_published,
server_name,
project,
owner,
) = self._parse_element(datasource_xml, ns)
self._set_values(
ask_data_enablement,
Expand All @@ -331,6 +397,13 @@ def _parse_common_elements(self, datasource_xml, ns):
use_remote_query_agent,
webpage_url,
size,
connected_workbooks_count,
favorites_total,
has_alert,
is_published,
server_name,
project,
owner,
)
return self

Expand All @@ -355,6 +428,13 @@ def _set_values(
use_remote_query_agent,
webpage_url,
size,
connected_workbooks_count,
favorites_total,
has_alert,
is_published,
server_name,
project,
owner,
):
if ask_data_enablement is not None:
self._ask_data_enablement = ask_data_enablement
Expand Down Expand Up @@ -394,6 +474,20 @@ def _set_values(
self._webpage_url = webpage_url
if size is not None:
self._size = int(size)
if connected_workbooks_count is not None:
self._connected_workbooks_count = connected_workbooks_count
if favorites_total is not None:
self._favorites_total = favorites_total
if has_alert is not None:
self._has_alert = has_alert
if is_published is not None:
self._is_published = is_published
if server_name is not None:
self._server_name = server_name
if project is not None:
self._project = project
if owner is not None:
self._owner = owner

@classmethod
def from_response(cls, resp: str, ns: dict) -> list["DatasourceItem"]:
Expand Down Expand Up @@ -428,6 +522,11 @@ def _parse_element(datasource_xml: ET.Element, ns: dict) -> tuple:
use_remote_query_agent = datasource_xml.get("useRemoteQueryAgent", None)
webpage_url = datasource_xml.get("webpageUrl", None)
size = datasource_xml.get("size", None)
connected_workbooks_count = nullable_str_to_int(datasource_xml.get("connectedWorkbooksCount", None))
favorites_total = nullable_str_to_int(datasource_xml.get("favoritesTotal", None))
has_alert = nullable_str_to_bool(datasource_xml.get("hasAlert", None))
is_published = nullable_str_to_bool(datasource_xml.get("isPublished", None))
server_name = datasource_xml.get("serverName", None)

tags = None
tags_elem = datasource_xml.find(".//t:tags", namespaces=ns)
Expand All @@ -438,12 +537,14 @@ def _parse_element(datasource_xml: ET.Element, ns: dict) -> tuple:
project_name = None
project_elem = datasource_xml.find(".//t:project", namespaces=ns)
if project_elem is not None:
project = ProjectItem.from_xml(project_elem, ns)
project_id = project_elem.get("id", None)
project_name = project_elem.get("name", None)

owner_id = None
owner_elem = datasource_xml.find(".//t:owner", namespaces=ns)
if owner_elem is not None:
owner = UserItem.from_xml(owner_elem, ns)
owner_id = owner_elem.get("id", None)

ask_data_enablement = None
Expand Down Expand Up @@ -471,4 +572,11 @@ def _parse_element(datasource_xml: ET.Element, ns: dict) -> tuple:
use_remote_query_agent,
webpage_url,
size,
connected_workbooks_count,
favorites_total,
has_alert,
is_published,
server_name,
project,
owner,
)
Loading
Loading
0