diff --git a/jira/client.py b/jira/client.py index 2915dd1ee..c48929ab9 100644 --- a/jira/client.py +++ b/jira/client.py @@ -16,6 +16,7 @@ import re import sys import time +import urllib import warnings from collections import OrderedDict from collections.abc import Iterable @@ -3280,6 +3281,36 @@ def delete_user_avatar(self, username: str, avatar: str): url = self._get_url("user/avatar/" + avatar) return self._session.delete(url, params=params) + @translate_resource_args + def delete_remote_link( + self, + issue: Union[str, Issue], + *, + internal_id: Optional[str] = None, + global_id: Optional[str] = None, + ) -> Response: + """Delete remote link from issue by internalId or globalId. + + Args: + issue (str): Key (or Issue) of Issue + internal_id (Optional[str]): InternalID of the remote link to delete + global_id (Optional[str]): GlobalID of the remote link to delete + + Returns: + Response + """ + if not ((internal_id is None) ^ (global_id is None)): + raise ValueError("Must supply either 'internal_id' XOR 'global_id'.") + + if internal_id is not None: + url = self._get_url(f"issue/{issue}/remotelink/{internal_id}") + elif global_id is not None: + # stop "&" and other special characters in global_id from messing around with the query + global_id = urllib.parse.quote(global_id, safe="") + url = self._get_url(f"issue/{issue}/remotelink?globalId={global_id}") + + return self._session.delete(url) + def search_users( self, user: Optional[str] = None, diff --git a/tests/tests.py b/tests/tests.py index 45c97a0ba..ee0b109f8 100755 --- a/tests/tests.py +++ b/tests/tests.py @@ -455,6 +455,39 @@ def _calculate_calls_for_fetch_pages( return call_list +DEFAULT_NEW_REMOTE_LINK_OBJECT = {"url": "http://google.com", "title": "googlicious!"} + + +class ClientRemoteLinkTests(JiraTestCase): + def setUp(self): + JiraTestCase.setUp(self) + self.issue_key = self.test_manager.project_b_issue1 + + def test_delete_remote_link_by_internal_id(self): + link = self.jira.add_remote_link( + self.issue_key, + destination=DEFAULT_NEW_REMOTE_LINK_OBJECT, + ) + _id = link.id + self.jira.delete_remote_link(self.issue_key, internal_id=_id) + self.assertRaises(JIRAError, self.jira.remote_link, self.issue_key, _id) + + def test_delete_remote_link_by_global_id(self): + link = self.jira.add_remote_link( + self.issue_key, + destination=DEFAULT_NEW_REMOTE_LINK_OBJECT, + globalId="python-test:story.of.sasquatch.riding", + ) + _id = link.id + self.jira.delete_remote_link( + self.issue_key, global_id="python-test:story.of.sasquatch.riding" + ) + self.assertRaises(JIRAError, self.jira.remote_link, self.issue_key, _id) + + def test_delete_remote_link_with_invalid_args(self): + self.assertRaises(ValueError, self.jira.delete_remote_link, self.issue_key) + + class WebsudoTests(JiraTestCase): def test_kill_websudo(self): self.jira.kill_websudo()