8000 Jorwoods/type hint favorites by jorwoods · Pull Request #936 · tableau/server-client-python · GitHub
[go: up one dir, main page]

Skip to content

Jorwoods/type hint favorites #936

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 4 commits into from
Jan 28, 2022
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
35 changes: 29 additions & 6 deletions tableauserverclient/models/favorites_item.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,39 @@
from .view_item import ViewItem
from .project_item import ProjectItem
from .datasource_item import DatasourceItem
from .flow_item import FlowItem

logger = logging.getLogger("tableau.models.favorites_item")

from typing import Dict, List, Union

FavoriteType = Dict[
str,
List[
Union[
DatasourceItem,
ProjectItem,
FlowItem,
ViewItem,
WorkbookItem,
]
],
]


class FavoriteItem:
class Type:
Workbook = "workbook"
Datasource = "datasource"
View = "view"
Project = "project"
Workbook: str = "workbook"
Datasource: str = "datasource"
View: str = "view"
Project: str = "project"
Flow: str = "flow"

@classmethod
def from_response(cls, xml, namespace):
favorites = {
def from_response(cls, xml: str, namespace: Dict) -> FavoriteType:
favorites: FavoriteType = {
"datasources": [],
"flows": [],
"projects": [],
"views": [],
"workbooks": [],
Expand All @@ -45,5 +63,10 @@ def from_response(cls, xml, namespace):
fav_project._set_values(*fav_project._parse_element(project))
if fav_project:
favorites["projects"].append(fav_project)
for flow in parsed_response.findall(".//t:favorite/t:flow", namespace):
fav_flow = FlowItem("flows")
fav_flow._set_values(*fav_flow._parse_element(flow, namespace))
if fav_flow:
favorites["flows"].append(fav_flow)

return favorites
43 changes: 29 additions & 14 deletions tableauserverclient/server/endpoint/favorites_endpoint.py
Original file line number Diff line number Diff line change
@@ -1,77 +1,92 @@
from .endpoint import Endpoint, api
from .exceptions import MissingRequiredFieldError
from .. import RequestFactory
from ...models import FavoriteItem
from ..pager import Pager
import xml.etree.ElementTree as ET
import logging
import copy

logger = logging.getLogger("tableau.endpoint.favorites")

from typing import Optional, TYPE_CHECKING

if TYPE_CHECKING:
from ...models import DatasourceItem, FlowItem, ProjectItem, UserItem, ViewItem, WorkbookItem
from ..request_options import RequestOptions


class Favorites(Endpoint):
@property
def baseurl(self):
def baseurl(self) -> str:
return "{0}/sites/{1}/favorites".format(self.parent_srv.baseurl, self.parent_srv.site_id)

# Gets all favorites
@api(version="2.5")
def get(self, user_item, req_options=None):
def get(self, user_item: "UserItem", req_options: Optional["RequestOptions"] = None) -> None:
logger.info("Querying all favorites for user {0}".format(user_item.name))
url = "{0}/{1}".format(self.baseurl, user_item.id)
server_response = self.get_request(url, req_options)

user_item._favorites = FavoriteItem.from_response(server_response.content, self.parent_srv.namespace)

@api(version="2.0")
def add_favorite_workbook(self, user_item, workbook_item):
def add_favorite_workbook(self, user_item: "UserItem", workbook_item: "WorkbookItem") -> None:
url = "{0}/{1}".format(self.baseurl, user_item.id)
add_req = RequestFactory.Favorite.add_workbook_req(workbook_item.id, workbook_item.name)
server_response = self.put_request(url, add_req)
logger.info("Favorited {0} for user (ID: {1})".format(workbook_item.name, user_item.id))

@api(version="2.0")
def add_favorite_view(self, user_item, view_item):
def add_favorite_view(self, user_item: "UserItem", view_item: "ViewItem") -> None:
url = "{0}/{1}".format(self.baseurl, user_item.id)
add_req = RequestFactory.Favorite.add_view_req(view_item.id, view_item.name)
server_response = self.put_request(url, add_req)
logger.info("Favorited {0} for user (ID: {1})".format(view_item.name, user_item.id))

@api(version="2.3")
def add_favorite_datasource(self, user_item, datasource_item):
def add_favorite_datasource(self, user_item: "UserItem", datasource_item: "DatasourceItem") -> None:
url = "{0}/{1}".format(self.baseurl, user_item.id)
add_req = RequestFactory.Favorite.add_datasource_req(datasource_item.id, datasource_item.name)
server_response = self.put_request(url, add_req)
logger.info("Favorited {0} for user (ID: {1})".format(datasource_item.name, user_item.id))

@api(version="3.1")
def add_favorite_project(self, user_item, project_item):
def add_favorite_project(self, user_item: "UserItem", project_item: "ProjectItem") -> None:
url = "{0}/{1}".format(self.baseurl, user_item.id)
add_req = RequestFactory.Favorite.add_project_req(project_item.id, project_item.name)
server_response = self.put_request(url, add_req)
logger.info("Favorited {0} for user (ID: {1})".format(project_item.name, user_item.id))

@api(version="3.3")
def add_favorite_flow(self, user_item: "UserItem", flow_item: "FlowItem") -> None:
url = "{0}/{1}".format(self.baseurl, user_item.id)
add_req = RequestFactory.Favorite.add_flow_req(flow_item.id, flow_item.name)
server_response = self.put_request(url, add_req)
logger.info("Favorited {0} for user (ID: {1})".format(flow_item.name, user_item.id))

@api(version="2.0")
def delete_favorite_workbook(self, user_item, workbook_item):
def delete_favorite_workbook(self, user_item: "UserItem", workbook_item: "WorkbookItem") -> None:
url = "{0}/{1}/workbooks/{2}".format(self.baseurl, user_item.id, workbook_item.id)
logger.info("Removing favorite {0} for user (ID: {1})".format(workbook_item.id, user_item.id))
self.delete_request(url)

@api(version="2.0")
def delete_favorite_view(self, user_item, view_item):
def delete_favorite_view(self, user_item: "UserItem", view_item: "ViewItem") -> None:
url = "{0}/{1}/views/{2}".format(self.baseurl, user_item.id, view_item.id)
logger.info("Removing favorite {0} for user (ID: {1})".format(view_item.id, user_item.id))
self.delete_request(url)

@api(version="2.3")
def delete_favorite_datasource(self, user_item, datasource_item):
def delete_favorite_datasource(self, user_item: "UserItem", datasource_item: "DatasourceItem") -> None:
url = "{0}/{1}/datasources/{2}".format(self.baseurl, user_item.id, datasource_item.id)
logger.info("Removing favorite {0} for user (ID: {1})".format(datasource_item.id, user_item.id))
self.delete_request(url)

@api(version="3.1")
def delete_favorite_project(self, user_item, project_item):
def delete_favorite_project(self, user_item: "UserItem", project_item: "ProjectItem") -> None:
url = "{0}/{1}/projects/{2}".format(self.baseurl, user_item.id, project_item.id)
logger.info("Removing favorite {0} for user (ID: {1})".format(project_item.id, user_item.id))
self.delete_request(url)

@api(version="3.3")
def delete_favorite_flow(self, user_item: "UserItem", flow_item: "FlowItem") -> None:
url = "{0}/{1}/projects/{2}".format(self.baseurl, user_item.id, flow_item.id)
logger.info("Removing favorite {0} for user (ID: {1})".format(flow_item.id, user_item.id))
self.delete_request(url)
35 changes: 29 additions & 6 deletions tableauserverclient/server/request_factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

from ..models import TaskItem, UserItem, GroupItem, PermissionsRule, FavoriteItem

from typing import TYPE_CHECKING
from typing import Optional, TYPE_CHECKING

if TYPE_CHECKING:
from ..models import DataAlertItem
Expand Down Expand Up @@ -242,7 +242,7 @@ def update_req(self, database_item):


class FavoriteRequest(object):
def _add_to_req(self, id_, target_type, label):
def _add_to_req(self, id_: str, target_type: str, label: str) -> bytes:
"""
<favorite label="...">
<target_type id="..." />
Expand All @@ -256,16 +256,39 @@ def _add_to_req(self, id_, target_type, label):

return ET.tostring(xml_request)

def add_datasource_req(self, id_, name):
def add_datasource_req(self, id_: Optional[str], name: Optional[str]) -> bytes:
if id_ is None:
raise ValueError("id must exist to add to favorites")
if name is None:
raise ValueError("Name must exist to add to favorites.")
return self._add_to_req(id_, FavoriteItem.Type.Datasource, name)

def add_project_req(self, id_, name):
def add_flow_req(self, id_: Optional[str], name: Optional[str]) -> bytes:
if id_ is None:
raise ValueError("id must exist to add to favorites")
if name is None:
raise ValueError("Name must exist to add to favorites.")
return self._add_to_req(id_, FavoriteItem.Type.Flow, name)

def add_project_req(self, id_: Optional[str], name: Optional[str]) -> bytes:
if id_ is None:
raise ValueError("id must exist to add to favorites")
if name is None:
raise ValueError("Name must exist to add to favorites.")
return self._add_to_req(id_, FavoriteItem.Type.Project, name)

def add_view_req(self, id_, name):
def add_view_req(self, id_: Optional[str], name: Optional[str]) -> bytes:
if id_ is None:
raise ValueError("id must exist to add to favorites")
if name is None:
raise ValueError("Name must exist to add to favorites.")
return self._add_to_req(id_, FavoriteItem.Type.View, name)

def add_workbook_req(self, id_, name):
def add_workbook_req(self, id_: Optional[str], name: Optional[str]) -> bytes:
if id_ is None:
raise ValueError("id must exist to add to favorites")
if name is None:
raise ValueError("Name must exist to add to favorites.")
return self._add_to_req(id_, FavoriteItem.Type.Workbook, name)


Expand Down
18 changes: 9 additions & 9 deletions test/test_favorites.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ def setUp(self):
self.user = TSC.UserItem("alice", TSC.UserItem.Roles.Viewer)
self.user._id = "dd2239f6-ddf1-4107-981a-4cf94e415794"

def test_get(self):
def test_get(self) -> None:
response_xml = read_xml_asset(GET_FAVORITES_XML)
with requests_mock.mock() as m:
m.get("{0}/{1}".format(self.baseurl, self.user.id), text=response_xml)
Expand All @@ -49,7 +49,7 @@ def test_get(self):
self.assertEqual(datasource.id, "e76a1461-3b1d-4588-bf1b-17551a879ad9")
self.assertEqual(project.id, "1d0304cd-3796-429f-b815-7258370b9b74")

def test_add_favorite_workbook(self):
def test_add_favorite_workbook(self) -> None:
response_xml = read_xml_asset(ADD_FAVORITE_WORKBOOK_XML)
workbook = TSC.WorkbookItem("")
workbook._id = "6d13b0ca-043d-4d42-8c9d-3f3313ea3a00"
Expand All @@ -58,7 +58,7 @@ def test_add_favorite_workbook(self):
m.put("{0}/{1}".format(self.baseurl, self.user.id), text=response_xml)
self.server.favorites.add_favorite_workbook(self.user, workbook)

def test_add_favorite_view(self):
def test_add_favorite_view(self) -> None:
response_xml = read_xml_asset(ADD_FAVORITE_VIEW_XML)
view = TSC.ViewItem()
view._id = "d79634e1-6063-4ec9-95ff-50acbf609ff5"
Expand All @@ -67,7 +67,7 @@ def test_add_favorite_view(self):
m.put("{0}/{1}".format(self.baseurl, self.user.id), text=response_xml)
self.server.favorites.add_favorite_view(self.user, view)

def test_add_favorite_datasource(self):
def test_add_favorite_datasource(self) -> None:
response_xml = read_xml_asset(ADD_FAVORITE_DATASOURCE_XML)
datasource = TSC.DatasourceItem("ee8c6e70-43b6-11e6-af4f-f7b0d8e20760")
datasource._id = "e76a1461-3b1d-4588-bf1b-17551a879ad9"
Expand All @@ -76,7 +76,7 @@ def test_add_favorite_datasource(self):
m.put("{0}/{1}".format(self.baseurl, self.user.id), text=response_xml)
self.server.favorites.add_favorite_datasource(self.user, datasource)

def test_add_favorite_project(self):
def test_add_favorite_project(self) -> None:
self.server.version = "3.1"
baseurl = self.server.favorites.baseurl
response_xml = read_xml_asset(ADD_FAVORITE_PROJECT_XML)
Expand All @@ -86,31 +86,31 @@ def test_add_favorite_project(self):
m.put("{0}/{1}".format(baseurl, self.user.id), text=response_xml)
self.server.favorites.add_favorite_project(self.user, project)

def test_delete_favorite_workbook(self):
def test_delete_favorite_workbook(self) -> None:
workbook = TSC.WorkbookItem("")
workbook._id = "6d13b0ca-043d-4d42-8c9d-3f3313ea3a00"
workbook.name = "Superstore"
with requests_mock.mock() as m:
m.delete("{0}/{1}/workbooks/{2}".format(self.baseurl, self.user.id, workbook.id))
self.server.favorites.delete_favorite_workbook(self.user, workbook)

def test_delete_favorite_view(self):
def test_delete_favorite_view(self) -> None:
view = TSC.ViewItem()
view._id = "d79634e1-6063-4ec9-95ff-50acbf609ff5"
view._name = "ENDANGERED SAFARI"
with requests_mock.mock() as m:
m.delete("{0}/{1}/views/{2}".format(self.baseurl, self.user.id, view.id))
self.server.favorites.delete_favorite_view(self.user, view)

def test_delete_favorite_datasource(self):
def test_delete_favorite_datasource(self) -> None:
datasource = TSC.DatasourceItem("ee8c6e70-43b6-11e6-af4f-f7b0d8e20760")
datasource._id = "e76a1461-3b1d-4588-bf1b-17551a879ad9"
datasource.name = "SampleDS"
with requests_mock.mock() as m:
m.delete("{0}/{1}/datasources/{2}".format(self.baseurl, self.user.id, datasource.id))
self.server.favorites.delete_favorite_datasource(self.user, datasource)

def test_delete_favorite_project(self):
def test_delete_favorite_project(self) -> None:
self.server.version = "3.1"
baseurl = self.server.favorites.baseurl
project = TSC.ProjectItem("Tableau")
Expand Down
0