From e4554c153b851aa5cc7ed14bcbc994e0ca9f201c Mon Sep 17 00:00:00 2001 From: Klaus Zerwes Date: Sat, 25 Jan 2025 07:54:48 +0100 Subject: [PATCH 1/6] git: ignore vim swp files --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index bf044bd43..8b1a0ac46 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ .idea +*.swp *.bak *.egg *.egg-info/ From 2d121bcf9ac5eb90bc0cd3562fe4208066c37cdb Mon Sep 17 00:00:00 2001 From: Klaus Zerwes Date: Sat, 25 Jan 2025 20:39:02 +0100 Subject: [PATCH 2/6] implemented CommentProperty --- jira/client.py | 43 +++++++++++++++++++++++++++++++++++++++++++ jira/resources.py | 26 ++++++++++++++++++++++++++ 2 files changed, 69 insertions(+) diff --git a/jira/client.py b/jira/client.py index 36dc2fea9..d2ab389f5 100644 --- a/jira/client.py +++ b/jira/client.py @@ -55,6 +55,7 @@ Attachment, Board, Comment, + CommentProperty, Component, Customer, CustomFieldOption, @@ -2353,6 +2354,48 @@ def add_comment( return Comment(self._options, self._session, raw=json_loads(r)) + # Comment properties + + @translate_resource_args + def comment_properties(self, comment: str) -> list[CommentProperty]: + """Get a list of comment property Resource from the server for an issue. + + Args: + comment (str): ID of the comment to get properties from + + Returns: + List[CommentProperty] + """ + r_json = self._get_json(f"comment/{comment}/properties") + properties = [self.comment_property(comment, key["key"]) for key in r_json["keys"]] + return properties + + @translate_resource_args + def comment_property(self, comment: str, key: str) -> CommentProperty: + """Get a specific comment property Resource from the server. + + Args: + comment (str): ID of the comment to get the property from + key (str): Key of the property to get + Returns: + CommentProperty + """ + return self._find_for_resource(CommentProperty, (comment, key)) + + @translate_resource_args + def add_comment_property(self, comment: str, key: str, data) -> Response: + """Add or update a specific comment property Resource. + + Args: + issue (str): ID of the comment to set the property to + key (str): Key of the property to set + data: The data to set for the property + Returns: + Response + """ + url = self._get_url(f"comment/{comment}/properties/{key}") + return self._session.put(url, data=json.dumps(data)) + # non-resource @translate_resource_args def editmeta(self, issue: str | int): diff --git a/jira/resources.py b/jira/resources.py index 29c86e604..d0e3a621d 100644 --- a/jira/resources.py +++ b/jira/resources.py @@ -34,6 +34,7 @@ class AnyLike: "Resource", "Issue", "Comment", + "CommentProperty", "Project", "Attachment", "Component", @@ -971,6 +972,30 @@ def __init__( self.raw: dict[str, Any] = cast(dict[str, Any], self.raw) +class CommentProperty(Resource): + """Custom data against an comment.""" + + def __init__( + self, + options: dict[str, str], + session: ResilientSession, + raw: dict[str, Any] | None = None, + ): + Resource.__init__(self, "comment/{0}/properties/{1}", options, session) + if raw: + self._parse_raw(raw) + self.raw: dict[str, Any] = cast(dict[str, Any], self.raw) + + def _find_by_url( + self, + url: str, + params: dict[str, str] | None = None, + ): + super()._find_by_url(url, params) + # An CommentProperty never returns "self" identifier, set it + self.self = url + + class RemoteLink(Resource): """A link to a remote application from an issue.""" @@ -1675,6 +1700,7 @@ def dict2resource( r"filter/[^/]$": Filter, r"issue/[^/]+$": Issue, r"issue/[^/]+/comment/[^/]+$": Comment, + r"comment/[^/]+/properties/[^/]+$": CommentProperty, r"issue/[^/]+/pinned-comments$": PinnedComment, r"issue/[^/]+/votes$": Votes, r"issue/[^/]+/watchers$": Watchers, From 17ca52e8464c0f778c558bc3ecd68d9e9d92da4f Mon Sep 17 00:00:00 2001 From: Klaus Zerwes Date: Sat, 25 Jan 2025 20:59:21 +0100 Subject: [PATCH 3/6] fixed Args doc for add_comment_property --- jira/client.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jira/client.py b/jira/client.py index d2ab389f5..731041df8 100644 --- a/jira/client.py +++ b/jira/client.py @@ -2387,7 +2387,7 @@ def add_comment_property(self, comment: str, key: str, data) -> Response: """Add or update a specific comment property Resource. Args: - issue (str): ID of the comment to set the property to + comment (str): ID of the comment to set the property to key (str): Key of the property to set data: The data to set for the property Returns: From 37d7247c570ff48610dec6a7911ad61398558735 Mon Sep 17 00:00:00 2001 From: Klaus Zerwes Date: Thu, 17 Apr 2025 13:36:52 +0200 Subject: [PATCH 4/6] test for CommentProperty --- tests/resources/test_comment.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/tests/resources/test_comment.py b/tests/resources/test_comment.py index 1dafc84a8..b8d6e6848 100644 --- a/tests/resources/test_comment.py +++ b/tests/resources/test_comment.py @@ -9,9 +9,10 @@ def setUp(self): 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 + self.issue_4_key = self.test_manager.project_b_issue4 def tearDown(self) -> None: - for issue in [self.issue_1_key, self.issue_2_key, self.issue_3_key]: + for issue in [self.issue_1_key, self.issue_2_key, self.issue_3_key, self.issue_4_key]: for comment in self.jira.comments(issue): comment.delete() @@ -80,3 +81,12 @@ def test_update_comment_with_notify(self): comment.update(body="updated! without notification", notify=False) assert comment.body == "updated! without notification" comment.delete() + + def test_comment_property(self): + comment = self.jira.add_comment(self.issue_4_key, "comment for property test") + comment_prop_data = {'internal': 'true'} + self.jira.add_comment_property(comment, 'sd.public.comment', comment_prop_data) + commentproperty = self.jira.comment_property(comment, 'sd.public.comment') + assert isinstance(commentproperty, CommentProperty) + assert commentproperty.value.internal.lower() == 'true' + comment.delete() From 465cbc2a2b6f73ed54a12f708153742c1e92b1a6 Mon Sep 17 00:00:00 2001 From: Klaus Zerwes Date: Thu, 17 Apr 2025 14:06:22 +0200 Subject: [PATCH 5/6] test for CommentProperty: add missing resource import --- tests/resources/test_comment.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/resources/test_comment.py b/tests/resources/test_comment.py index b8d6e6848..ed2d05386 100644 --- a/tests/resources/test_comment.py +++ b/tests/resources/test_comment.py @@ -1,5 +1,6 @@ from __future__ import annotations +from jira.resources import CommentProperty from tests.conftest import JiraTestCase From f206010b839a0c3150045d1d8efe4d5b85a9d158 Mon Sep 17 00:00:00 2001 From: Klaus Zerwes Date: Fri, 25 Apr 2025 22:40:14 +0200 Subject: [PATCH 6/6] test_comment_property: use existing issue --- tests/resources/test_comment.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/resources/test_comment.py b/tests/resources/test_comment.py index ed2d05386..201860277 100644 --- a/tests/resources/test_comment.py +++ b/tests/resources/test_comment.py @@ -10,10 +10,9 @@ def setUp(self): 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 - self.issue_4_key = self.test_manager.project_b_issue4 def tearDown(self) -> None: - for issue in [self.issue_1_key, self.issue_2_key, self.issue_3_key, self.issue_4_key]: + for issue in [self.issue_1_key, self.issue_2_key, self.issue_3_key]: for comment in self.jira.comments(issue): comment.delete() @@ -84,7 +83,7 @@ def test_update_comment_with_notify(self): comment.delete() def test_comment_property(self): - comment = self.jira.add_comment(self.issue_4_key, "comment for property test") + comment = self.jira.add_comment(self.issue_1_key, "comment for property test") comment_prop_data = {'internal': 'true'} self.jira.add_comment_property(comment, 'sd.public.comment', comment_prop_data) commentproperty = self.jira.comment_property(comment, 'sd.public.comment')