Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion docs/examples.rst
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,8 @@ Adding, editing and deleting comments is similarly straightforward::
comment = jira.add_comment('JRA-1330', 'new comment') # no Issue object required
comment = jira.add_comment(issue, 'new comment', visibility={'type': 'role', 'value': 'Administrators'}) # for admins only

comment.update(body = 'updated comment body')
comment.update(body='updated comment body')
comment.update(body='updated comment body but no mail notification', notify=False)
comment.delete()

Transitions
Expand Down
24 changes: 9 additions & 15 deletions jira/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -1852,22 +1852,16 @@ def add_comment(
data: Dict[str, Any] = {"body": body}

if is_internal:
data.update(
{
"properties": [
{"key": "sd.public.comment", "value": {"internal": is_internal}}
]
}
)

data["properties"] = [
{"key": "sd.public.comment", "value": {"internal": is_internal}}
]
if visibility is not None:
data["visibility"] = visibility

url = self._get_url("issue/" + str(issue) + "/comment")
r = self._session.post(url, data=json.dumps(data))

comment = Comment(self._options, self._session, raw=json_loads(r))
return comment
return Comment(self._options, self._session, raw=json_loads(r))

# non-resource
@translate_resource_args
Expand Down Expand Up @@ -4330,16 +4324,16 @@ def add_user(
directoryId (int): The directory ID the new user should be a part of (Default: 1)
password (Optional[str]): Optional, the password for the new user
fullname (Optional[str]): Optional, the full name of the new user
notify (bool): Whether or not to send a notification to the new user. (Default: False)
active (bool): Whether or not to make the new user active upon creation. (Default: True)
ignore_existing (bool): Whether or not to ignore and existing user. (Default: False)
applicationKeys (Optional[list]): Keys of products user should have access to
notify (bool): Whether to send a notification to the new user. (Default: False)
active (bool): Whether to make the new user active upon creation. (Default: True)
ignore_existing (bool): Whether to ignore and existing user. (Default: False)
application_keys (Optional[list]): Keys of products user should have access to

Raises:
JIRAError: If username already exists and `ignore_existing` has not been set to `True`.

Returns:
bool: Whether or not the user creation was successful.
bool: Whether the user creation was successful.


"""
Expand Down
39 changes: 35 additions & 4 deletions jira/resources.py
Original file line number Diff line number Diff line change
Expand Up @@ -763,14 +763,45 @@ def __init__(
self._parse_raw(raw)
self.raw: Dict[str, Any] = cast(Dict[str, Any], self.raw)

def update(self, fields=None, async_=None, jira=None, body="", visibility=None):
"""Update a comment"""
data = {}
def update( # type: ignore[override]
# The above ignore is added because we've added new parameters and order of parameters is different.
# Will need to be solved in a major version bump.
self,
fields: Optional[Dict[str, Any]] = None,
async_: Optional[bool] = None,
jira: "JIRA" = None,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

more for myself, but why the quotes around JIRA?
I didn't see such a variant on https://docs.python.org/3/library/typing.html

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is because we only import the JIRA class when type checking, and current Python versions actually try to evaluate the type hint.

Some more reading here: https://mypy.readthedocs.io/en/stable/runtime_troubles.html#annotation-issues-at-runtime

body: str = "",
visibility: Optional[Dict[str, str]] = None,
is_internal: bool = False,
notify: bool = True,
):
"""Update a comment

Keyword arguments are marshalled into a dict before being sent.

Args:
fields (Optional[Dict[str, Any]]): DEPRECATED => a comment doesn't have fields
async_ (Optional[bool]): If True the request will be added to the queue, so it can be executed later using async_run()
jira (jira.client.JIRA): Instance of Jira Client
visibility (Optional[Dict[str, str]]): a dict containing two entries: "type" and "value".
"type" is 'role' (or 'group' if the Jira server has configured
comment visibility for groups) and 'value' is the name of the role
(or group) to which viewing of this comment will be restricted.
body (str): New text of the comment
is_internal (bool): Defines whether a comment has to be marked as 'Internal' in Jira Service Desk (Default: False)
notify (bool): Whether to notify users about the update. (Default: True)
"""
data: Dict[str, Any] = {}
if body:
data["body"] = body
if visibility:
data["visibility"] = visibility
super().update(data)
if is_internal:
data["properties"] = [
{"key": "sd.public.comment", "value": {"internal": is_internal}}
]

super().update(async_=async_, jira=jira, notify=notify, fields=data)


class RemoteLink(Resource):
Expand Down
3 changes: 2 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@ requires = [
"setuptools_scm_git_archive >= 1.0",
"wheel",
]
requires-python = ">=3.8"
build-backend = "setuptools.build_meta"
[project]
requires-python = ">=3.8"
39 changes: 25 additions & 14 deletions tests/resources/test_comment.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,17 @@
class CommentTests(JiraTestCase):
def setUp(self):
JiraTestCase.setUp(self)
self.issue_1 = self.test_manager.project_b_issue1
self.issue_2 = self.test_manager.project_b_issue2
self.issue_3 = self.test_manager.project_b_issue3
self.issue_1_key = self.test_manager.project_b_issue1
self.issue_2_key = self.test_manager.project_b_issue2
self.issue_3_key = self.test_manager.project_b_issue3

def tearDown(self) -> None:
for issue in [self.issue_1_key, self.issue_2_key, self.issue_3_key]:
for comment in self.jira.comments(issue):
comment.delete()

def test_comments(self):
for issue in [self.issue_1, self.jira.issue(self.issue_2)]:
for issue in [self.issue_1_key, self.jira.issue(self.issue_2_key)]:
self.jira.issue(issue)
comment1 = self.jira.add_comment(issue, "First comment")
comment2 = self.jira.add_comment(issue, "Second comment")
Expand All @@ -22,24 +27,24 @@ def test_comments(self):
assert len(comments) == 0

def test_expanded_comments(self):
comment1 = self.jira.add_comment(self.issue_1, "First comment")
comment2 = self.jira.add_comment(self.issue_1, "Second comment")
comments = self.jira.comments(self.issue_1, expand="renderedBody")
comment1 = self.jira.add_comment(self.issue_1_key, "First comment")
comment2 = self.jira.add_comment(self.issue_1_key, "Second comment")
comments = self.jira.comments(self.issue_1_key, expand="renderedBody")
self.assertTrue(hasattr(comments[0], "renderedBody"))
ret_comment1 = self.jira.comment(
self.issue_1, comment1.id, expand="renderedBody"
self.issue_1_key, comment1.id, expand="renderedBody"
)
ret_comment2 = self.jira.comment(self.issue_1, comment2.id)
ret_comment2 = self.jira.comment(self.issue_1_key, comment2.id)
comment1.delete()
comment2.delete()
self.assertTrue(hasattr(ret_comment1, "renderedBody"))
self.assertFalse(hasattr(ret_comment2, "renderedBody"))
comments = self.jira.comments(self.issue_1)
comments = self.jira.comments(self.issue_1_key)
assert len(comments) == 0

def test_add_comment(self):
comment = self.jira.add_comment(
self.issue_3,
self.issue_3_key,
"a test comment!",
visibility={"type": "role", "value": "Administrators"},
)
Expand All @@ -49,7 +54,7 @@ def test_add_comment(self):
comment.delete()

def test_add_comment_with_issue_obj(self):
issue = self.jira.issue(self.issue_3)
issue = self.jira.issue(self.issue_3_key)
comment = self.jira.add_comment(
issue,
"a new test comment!",
Expand All @@ -61,9 +66,15 @@ def test_add_comment_with_issue_obj(self):
comment.delete()

def test_update_comment(self):
comment = self.jira.add_comment(self.issue_3, "updating soon!")
comment = self.jira.add_comment(self.issue_3_key, "updating soon!")
comment.update(body="updated!")
self.assertEqual(comment.body, "updated!")
assert comment.body == "updated!"
# self.assertEqual(comment.visibility.type, 'role')
# self.assertEqual(comment.visibility.value, 'Administrators')
comment.delete()

def test_update_comment_with_notify(self):
comment = self.jira.add_comment(self.issue_3_key, "updating soon!")
comment.update(body="updated! without notification", notify=False)
assert comment.body == "updated! without notification"
comment.delete()