diff --git a/tableauserverclient/models/project_item.py b/tableauserverclient/models/project_item.py index 0e4e5af56..dd90f8bfb 100644 --- a/tableauserverclient/models/project_item.py +++ b/tableauserverclient/models/project_item.py @@ -86,9 +86,10 @@ def __init__( content_permissions: Optional[str] = None, parent_id: Optional[str] = None, samples: Optional[bool] = None, + id: Optional[str] = None, ) -> None: self._content_permissions = None - self._id: Optional[str] = None + self._id: Optional[str] = id self.description: Optional[str] = description self.name: str = name self.content_permissions: Optional[str] = content_permissions diff --git a/tableauserverclient/server/endpoint/projects_endpoint.py b/tableauserverclient/server/endpoint/projects_endpoint.py index 68eb573cc..c7a834802 100644 --- a/tableauserverclient/server/endpoint/projects_endpoint.py +++ b/tableauserverclient/server/endpoint/projects_endpoint.py @@ -89,6 +89,18 @@ def delete(self, project_id: str) -> None: self.delete_request(url) logger.info(f"Deleted single project (ID: {project_id})") + @api(version="2.0") + def get_by_id(self, project_id: str) -> ProjectItem: + """ + Fetch a project by ID. This is a convenience method making up for a gap in the server API. + It uses the same endpoint as the update method, but without the ability to update the project. + """ + if not project_id: + error = "Project ID undefined." + raise ValueError(error) + project = ProjectItem(id=project_id) + return self.update(project, samples=False) + @api(version="2.0") def update(self, project_item: ProjectItem, samples: bool = False) -> ProjectItem: """ diff --git a/test/test_project.py b/test/test_project.py index f2cfab5d1..eb33f6732 100644 --- a/test/test_project.py +++ b/test/test_project.py @@ -80,6 +80,25 @@ def test_delete_missing_id(server: TSC.Server) -> None: server.projects.delete("") +def test_get_by_id(server: TSC.Server) -> None: + response_xml = UPDATE_XML.read_text() + with requests_mock.mock() as m: + m.put(server.projects.baseurl + "/1d0304cd-3796-429f-b815-7258370b9b74", text=response_xml) + project = server.projects.get_by_id("1d0304cd-3796-429f-b815-7258370b9b74") + assert "1d0304cd-3796-429f-b815-7258370b9b74" == project.id + assert "Test Project" == project.name + assert "Project created for testing" == project.description + assert "LockedToProject" == project.content_permissions + assert "9a8f2265-70f3-4494-96c5-e5949d7a1120" == project.parent_id + assert "dd2239f6-ddf1-4107-981a-4cf94e415794" == project.owner_id + assert "LockedToProject" == project.content_permissions + + +def test_get_by_id_missing_id(server: TSC.Server) -> None: + with pytest.raises(ValueError): + server.projects.get_by_id("") + + def test_update(server: TSC.Server) -> None: response_xml = UPDATE_XML.read_text() with requests_mock.mock() as m: