Coverage for src/mcp_atlassian/jira/comments.py: 91%
45 statements
« prev ^ index » next coverage.py v7.6.12, created at 2025-03-10 03:26 +0900
« prev ^ index » next coverage.py v7.6.12, created at 2025-03-10 03:26 +0900
1"""Module for Jira comment operations."""
3import logging
4from typing import Any, Dict, List, Optional
6import requests
8from ..document_types import Document
9from .client import JiraClient
11logger = logging.getLogger("mcp-jira")
14class CommentsMixin(JiraClient):
15 """Mixin for Jira comment operations."""
17 def get_issue_comments(self, issue_key: str, limit: int = 50) -> List[Dict[str, Any]]:
18 """
19 Get comments for a specific issue.
21 Args:
22 issue_key: The issue key (e.g. 'PROJ-123')
23 limit: Maximum number of comments to return
25 Returns:
26 List of comments with author, creation date, and content
28 Raises:
29 Exception: If there is an error getting comments
30 """
31 try:
32 comments = self.jira.issue_get_comments(issue_key)
33 processed_comments = []
35 for comment in comments.get("comments", [])[:limit]:
36 processed_comment = {
37 "id": comment.get("id"),
38 "body": self._clean_text(comment.get("body", "")),
39 "created": self._parse_date(comment.get("created")),
40 "updated": self._parse_date(comment.get("updated")),
41 "author": comment.get("author", {}).get("displayName", "Unknown"),
42 }
43 processed_comments.append(processed_comment)
45 return processed_comments
46 except Exception as e:
47 logger.error(f"Error getting comments for issue {issue_key}: {str(e)}")
48 raise Exception(f"Error getting comments: {str(e)}") from e
50 def add_comment(self, issue_key: str, comment: str) -> Dict[str, Any]:
51 """
52 Add a comment to an issue.
54 Args:
55 issue_key: The issue key (e.g. 'PROJ-123')
56 comment: Comment text to add (in Markdown format)
58 Returns:
59 The created comment details
61 Raises:
62 Exception: If there is an error adding the comment
63 """
64 try:
65 # Convert Markdown to Jira's markup format
66 jira_formatted_comment = self._markdown_to_jira(comment)
68 result = self.jira.issue_add_comment(issue_key, jira_formatted_comment)
69 return {
70 "id": result.get("id"),
71 "body": self._clean_text(result.get("body", "")),
72 "created": self._parse_date(result.get("created")),
73 "author": result.get("author", {}).get("displayName", "Unknown"),
74 }
75 except Exception as e:
76 logger.error(f"Error adding comment to issue {issue_key}: {str(e)}")
77 raise Exception(f"Error adding comment: {str(e)}") from e
79 def _markdown_to_jira(self, markdown_text: str) -> str:
80 """
81 Convert Markdown syntax to Jira markup syntax.
83 This method uses the TextPreprocessor implementation for consistent
84 conversion between Markdown and Jira markup.
86 Args:
87 markdown_text: Text in Markdown format
89 Returns:
90 Text in Jira markup format
91 """
92 if not markdown_text:
93 return ""
95 # Use the existing preprocessor
96 try:
97 return self.preprocessor.markdown_to_jira(markdown_text)
98 except Exception as e:
99 logger.warning(f"Error converting markdown to Jira format: {str(e)}")
100 # Return the original text if conversion fails
101 return markdown_text
103 def _parse_date(self, date_str: Optional[str]) -> str:
104 """
105 Parse a date string from ISO format to a more readable format.
107 This method is included for independence from other mixins,
108 but will use the implementation from other mixins if available.
110 Args:
111 date_str: Date string in ISO format or None
113 Returns:
114 Formatted date string or empty string if date_str is None
115 """
116 # If the date string is None, return empty string
117 if date_str is None:
118 return ""
120 # If another mixin has implemented this method, use that implementation
121 if hasattr(self, '_parse_date') and self.__class__._parse_date is not CommentsMixin._parse_date:
122 # This avoids infinite recursion by checking that the method is different
123 return super()._parse_date(date_str)
125 # Fallback implementation
126 try:
127 from datetime import datetime
128 date_obj = datetime.fromisoformat(date_str.replace("Z", "+00:00"))
129 return date_obj.strftime("%Y-%m-%d")
130 except (ValueError, TypeError):
131 return date_str