from typing import List from llama_index.readers.base import BaseReader from llama_index.readers.schema.base import Document def safe_value_dict(dict_obj): for key, value in dict_obj.items(): if isinstance(value, (str, int, float)): dict_obj[key] = value elif isinstance(value, list): # Convert lists to strings dict_obj[key] = ', '.join(map(str, value)) elif value is None: # Replace None with a default string dict_obj[key] = '' else: # Convert other types to strings dict_obj[key] = str(value) return dict_obj class JiraReader(BaseReader): """Jira reader. Reads data from Jira issues from passed query. Args: email (str): Jira email. api_token (str): Jira API token. server_url (str): Jira server url. """ def __init__(self, email: str, api_token: str, server_url: str) -> None: from jira import JIRA self.jira = JIRA( basic_auth=(email, api_token), server=f'https://{server_url}' ) def load_data(self, query: str) -> List[Document]: relevant_issues = self.jira.search_issues(query) issues = [] for issue in relevant_issues: # Iterates through only issues and not epics if 'parent' in (issue.raw['fields']): assignee = '' reporter = '' epic_key = '' epic_summary = '' epic_descripton = '' if issue.fields.assignee: assignee = issue.fields.assignee.displayName if issue.fields.reporter: reporter = issue.fields.reporter.displayName if issue.raw['fields']['parent']['key']: epic_key = issue.raw['fields']['parent']['key'] if issue.raw['fields']['parent']['fields']['summary']: epic_summary = issue.raw['fields']['parent']['fields']['summary'] if issue.raw['fields']['parent']['fields']['status']['description']: epic_descripton = issue.raw['fields']['parent']['fields']['status']['description'] issues.append( Document( f"{issue.fields.summary} \n {issue.fields.description}", extra_info = safe_value_dict({ 'id': issue.id, 'title': issue.fields.summary, 'url': issue.permalink(), 'created_at': issue.fields.created, 'updated_at': issue.fields.updated, 'labels': issue.fields.labels, 'status': issue.fields.status.name, 'assignee': assignee, 'reporter': reporter, 'project': issue.fields.project.name, 'issue_type': issue.fields.issuetype.name, 'priority': issue.fields.priority.name, 'epic_key': epic_key, 'epic_summary': epic_summary, 'epic_description': epic_descripton}) ) ) return issues