Skip to content

Commit

Permalink
Merge branch 'development' into jacalata-patch-2
Browse files Browse the repository at this point in the history
  • Loading branch information
jacalata authored Sep 28, 2023
2 parents 674495b + 2f6a343 commit cd543a9
Show file tree
Hide file tree
Showing 26 changed files with 205 additions and 88 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/code-coverage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ jobs:
# https://github.com/marketplace/actions/pytest-coverage-comment
- name: Generate coverage report
run: pytest --junitxml=pytest.xml --cov=tableauserverclient tests/ | tee pytest-coverage.txt
run: pytest --junitxml=pytest.xml --cov=tableauserverclient test/ | tee pytest-coverage.txt

- name: Comment on pull request with coverage
uses: MishaKav/pytest-coverage-comment@main
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,4 @@ For more information on installing and using TSC, see the documentation:


## License
[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Ftableau%2Fserver-client-python.svg?type=large)](https://app.fossa.com/projects/git%2Bgithub.com%2Ftableau%2Fserver-client-python?ref=badge_large)
[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Ftableau%2Fserver-client-python.svg?type=large)](https://app.fossa.com/projects/git%2Bgithub.com%2Ftableau%2Fserver-client-python?ref=badge_large)
3 changes: 2 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ 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-subtests", "requests-mock>=1.0,<2.0"]
test = ["argparse", "black==23.7", "mock", "mypy==1.4", "pytest>=7.0", "pytest-cov", "pytest-subtests",
"requests-mock>=1.0,<2.0"]

[tool.black]
line-length = 120
Expand Down
43 changes: 42 additions & 1 deletion tableauserverclient/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,47 @@
from ._version import get_versions
from .namespace import NEW_NAMESPACE as DEFAULT_NAMESPACE
from .models import *
from .models import (
BackgroundJobItem,
ColumnItem,
ConnectionCredentials,
ConnectionItem,
CustomViewItem,
DQWItem,
DailyInterval,
DataAlertItem,
DatabaseItem,
DatasourceItem,
FavoriteItem,
FlowItem,
FlowRunItem,
FileuploadItem,
GroupItem,
HourlyInterval,
IntervalItem,
JobItem,
JWTAuth,
MetricItem,
MonthlyInterval,
PaginationItem,
Permission,
PermissionsRule,
PersonalAccessTokenAuth,
ProjectItem,
RevisionItem,
ScheduleItem,
SiteItem,
ServerInfoItem,
SubscriptionItem,
TableItem,
TableauAuth,
Target,
TaskItem,
UserItem,
ViewItem,
WebhookItem,
WeeklyInterval,
WorkbookItem,
)
from .server import (
CSVRequestOptions,
ExcelRequestOptions,
Expand Down
2 changes: 1 addition & 1 deletion tableauserverclient/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
from .site_item import SiteItem
from .subscription_item import SubscriptionItem
from .table_item import TableItem
from .tableau_auth import Credentials, TableauAuth, PersonalAccessTokenAuth
from .tableau_auth import Credentials, TableauAuth, PersonalAccessTokenAuth, JWTAuth
from .tableau_types import Resource, TableauItem, plural_type
from .tag_item import TagItem
from .target import Target
Expand Down
3 changes: 3 additions & 0 deletions tableauserverclient/models/column_item.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ def __init__(self, name, description=None):
self.description = description
self.name = name

def __repr__(self):
return f"<{self.__class__.__name__} {self._id} {self.name} {self.description}>"

@property
def id(self):
return self._id
Expand Down
7 changes: 7 additions & 0 deletions tableauserverclient/models/connection_credentials.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,13 @@ def __init__(self, name, password, embed=True, oauth=False):
self.embed = embed
self.oauth = oauth

def __repr__(self):
if self.password:
print = "redacted"
else:
print = "None"
return f"<{self.__class__.__name__} name={self.name} password={print} embed={self.embed} oauth={self.oauth} >"

@property
def embed(self):
return self._embed
Expand Down
3 changes: 3 additions & 0 deletions tableauserverclient/models/data_acceleration_report_item.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ def avg_non_accelerated_plt(self):
def __init__(self, comparison_records):
self._comparison_records = comparison_records

def __repr__(self):
return f"<(deprecated)DataAccelerationReportItem site={self.site} sheet={sheet_uri}>"

@property
def comparison_records(self):
return self._comparison_records
Expand Down
5 changes: 1 addition & 4 deletions tableauserverclient/models/group_item.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,9 @@ def __init__(self, name=None, domain_name=None) -> None:
self.name: Optional[str] = name
self.domain_name: Optional[str] = domain_name

def __str__(self):
def __repr__(self):
return "{}({!r})".format(self.__class__.__name__, self.__dict__)

__repr__ = __str__

@property
def domain_name(self) -> Optional[str]:
return self._domain_name
Expand All @@ -48,7 +46,6 @@ def name(self) -> Optional[str]:
return self._name

@name.setter
@property_not_empty
def name(self, value: str) -> None:
self._name = value

Expand Down
12 changes: 12 additions & 0 deletions tableauserverclient/models/interval_item.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ def __init__(self, start_time, end_time, interval_value):
self.end_time = end_time
self.interval = interval_value

def __repr__(self):
return f"<{self.__class__.__name__} start={self.start_time} end={self.end_time} interval={self.interval}>"

@property
def _frequency(self):
return IntervalItem.Frequency.Hourly
Expand Down Expand Up @@ -86,6 +89,9 @@ def __init__(self, start_time, *interval_values):
self.start_time = start_time
self.interval = interval_values

def __repr__(self):
return f"<{self.__class__.__name__} start={self.start_time} interval={self.interval}>"

@property
def _frequency(self):
return IntervalItem.Frequency.Daily
Expand Down Expand Up @@ -114,6 +120,9 @@ def __init__(self, start_time, *interval_values):
self.start_time = start_time
self.interval = interval_values

def __repr__(self):
return f"<{self.__class__.__name__} start={self.start_time} interval={self.interval}>"

@property
def _frequency(self):
return IntervalItem.Frequency.Weekly
Expand Down Expand Up @@ -148,6 +157,9 @@ def __init__(self, start_time, interval_value):
self.start_time = start_time
self.interval = str(interval_value)

def __repr__(self):
return f"<{self.__class__.__name__} start={self.start_time} interval={self.interval}>"

@property
def _frequency(self):
return IntervalItem.Frequency.Monthly
Expand Down
11 changes: 10 additions & 1 deletion tableauserverclient/models/job_item.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,12 +117,15 @@ def flow_run(self, value):
def updated_at(self) -> Optional[datetime.datetime]:
return self._updated_at

def __repr__(self):
def __str__(self):
return (
"<Job#{_id} {_type} created_at({_created_at}) started_at({_started_at}) updated_at({_updated_at}) completed_at({_completed_at})"
" progress ({_progress}) finish_code({_finish_code})>".format(**self.__dict__)
)

def __repr__(self):
return self.__str__() + " { " + ", ".join(" % s: % s" % item for item in vars(self).items()) + "}"

@classmethod
def from_response(cls, xml, ns) -> List["JobItem"]:
parsed_response = fromstring(xml)
Expand Down Expand Up @@ -202,6 +205,12 @@ def __init__(
self._title = title
self._subtitle = subtitle

def __str__(self):
return f"<{self.__class__.name} {self._id} {self._type}>"

def __repr__(self):
return self.__str__() + " { " + ", ".join(" % s: % s" % item for item in vars(self).items()) + "}"

@property
def id(self) -> str:
return self._id
Expand Down
5 changes: 4 additions & 1 deletion tableauserverclient/models/metric_item.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,9 +115,12 @@ def view_id(self, value: Optional[str]) -> None:
def _set_permissions(self, permissions):
self._permissions = permissions

def __repr__(self):
def __str__(self):
return "<MetricItem# name={_name} id={_id} owner_id={_owner_id}>".format(**vars(self))

def __repr__(self):
return self.__str__() + " { " + ", ".join(" % s: % s" % item for item in vars(self).items()) + "}"

@classmethod
def from_response(
cls,
Expand Down
3 changes: 3 additions & 0 deletions tableauserverclient/models/pagination_item.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ def __init__(self):
self._page_size = None
self._total_available = None

def __repr__(self):
return f"<PaginationItem page_number={self._page_number} page_size={self._page_size} total={self._total_available}>"

@property
def page_number(self) -> int:
return self._page_number
Expand Down
11 changes: 7 additions & 4 deletions tableauserverclient/models/permissions_item.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import logging
import xml.etree.ElementTree as ET
from typing import Dict, List, Optional

Expand All @@ -17,6 +16,9 @@ class Mode:
Allow = "Allow"
Deny = "Deny"

def __repr__(self):
return "<Enum Mode: Allow | Deny>"

class Capability:
AddComment = "AddComment"
ChangeHierarchy = "ChangeHierarchy"
Expand All @@ -39,17 +41,18 @@ class Capability:
CreateRefreshMetrics = "CreateRefreshMetrics"
SaveAs = "SaveAs"

def __repr__(self):
return "<Enum Capability: AddComment | ChangeHierarchy | ChangePermission ... (17 more) >"


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

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

__repr__ = __str__

@classmethod
def from_response(cls, resp, ns=None) -> List["PermissionsRule"]:
parsed_response = fromstring(resp)
Expand Down
5 changes: 4 additions & 1 deletion tableauserverclient/models/schedule_item.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,12 @@ def __init__(self, name: str, priority: int, schedule_type: str, execution_order
self.priority: int = priority
self.schedule_type: str = schedule_type

def __repr__(self):
def __str__(self):
return '<Schedule#{_id} "{_name}" {interval_item}>'.format(**vars(self))

def __repr__(self):
return self.__str__() + " { " + ", ".join(" % s: % s" % item for item in vars(self).items()) + "}"

@property
def created_at(self) -> Optional[datetime]:
return self._created_at
Expand Down
2 changes: 1 addition & 1 deletion tableauserverclient/models/server_info_item.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ def __init__(self, product_version, build_number, rest_api_version):
self._build_number = build_number
self._rest_api_version = rest_api_version

def __str__(self):
def __repr__(self):
return (
"ServerInfoItem: [product version: "
+ self._product_version
Expand Down
3 changes: 3 additions & 0 deletions tableauserverclient/models/site_item.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ def __str__(self):
+ ">"
)

def __repr__(self):
return self.__str__() + " { " + ", ".join(" % s: % s" % item for item in vars(self).items()) + "}"

class AdminMode:
ContentAndUsers: str = "ContentAndUsers"
ContentOnly: str = "ContentOnly"
Expand Down
6 changes: 6 additions & 0 deletions tableauserverclient/models/table_item.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@ def __init__(self, name, description=None):
self._columns = None
self._data_quality_warnings = None

def __str__(self):
return f"<{self.__class__.__name__} {self._id} {self._name} >"

def __repr__(self):
return self.__str__() + " { " + ", ".join(" % s: % s" % item for item in vars(self).items()) + "}"

@property
def permissions(self):
if self._permissions is None:
Expand Down
21 changes: 16 additions & 5 deletions tableauserverclient/models/tableau_auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,11 @@ def credentials(self):
return {"name": self.username, "password": self.password}

def __repr__(self):
return "<Credentials username={} password={}>".format(self.username, "<redacted>")
if self.user_id_to_impersonate:
uid = f", user_id_to_impersonate=f{self.user_id_to_impersonate}"
else:
uid = ""
return f"<Credentials username={self.username} password=redacted (site={self.site_id}{uid})>"

@property
def site(self):
Expand All @@ -56,6 +60,7 @@ def site(self, value):
self.site_id = value


# A Tableau-generated Personal Access Token
class PersonalAccessTokenAuth(Credentials):
def __init__(self, token_name, personal_access_token, site_id=None, user_id_to_impersonate=None):
if personal_access_token is None or token_name is None:
Expand All @@ -72,13 +77,19 @@ def credentials(self):
}

def __repr__(self):
return "<PersonalAccessToken name={} token={}>(site={})".format(
self.token_name, self.personal_access_token[:2] + "...", self.site_id
if self.user_id_to_impersonate:
uid = f", user_id_to_impersonate=f{self.user_id_to_impersonate}"
else:
uid = ""
return (
f"<PersonalAccessToken name={self.token_name} token={self.personal_access_token[:2]}..."
f"(site={self.site_id}{uid} >"
)


# A standard JWT generated specifically for Tableau
class JWTAuth(Credentials):
def __init__(self, jwt=None, site_id=None, user_id_to_impersonate=None):
def __init__(self, jwt: str, site_id=None, user_id_to_impersonate=None):
if jwt is None:
raise TabError("Must provide a JWT token when using JWT authentication")
super().__init__(site_id, user_id_to_impersonate)
Expand All @@ -93,4 +104,4 @@ def __repr__(self):
uid = f", user_id_to_impersonate=f{self.user_id_to_impersonate}"
else:
uid = ""
return f"<{self.__class__.__qualname__}(jwt={self.jwt[:5]}..., site_id={self.site_id}{uid})>"
return f"<{self.__class__.__qualname__} jwt={self.jwt[:5]}... (site={self.site_id}{uid})>"
5 changes: 4 additions & 1 deletion tableauserverclient/models/user_item.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,13 @@ def __init__(

return None

def __repr__(self) -> str:
def __str__(self) -> str:
str_site_role = self.site_role or "None"
return "<User {} name={} role={}>".format(self.id, self.name, str_site_role)

def __repr__(self):
return self.__str__() + " { " + ", ".join(" % s: % s" % item for item in vars(self).items()) + "}"

@property
def auth_setting(self) -> Optional[str]:
return self._auth_setting
Expand Down
5 changes: 4 additions & 1 deletion tableauserverclient/models/view_item.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,14 @@ def __init__(self) -> None:
self._permissions: Optional[Callable[[], List[PermissionsRule]]] = None
self.tags: Set[str] = set()

def __repr__(self):
def __str__(self):
return "<ViewItem {0} '{1}' contentUrl='{2}' project={3}>".format(
self._id, self.name, self.content_url, self.project_id
)

def __repr__(self):
return self.__str__() + " { " + ", ".join(" % s: % s" % item for item in vars(self).items()) + "}"

def _set_preview_image(self, preview_image):
self._preview_image = preview_image

Expand Down
Loading

0 comments on commit cd543a9

Please sign in to comment.