Add get_issues, logging
This commit is contained in:
		
							
								
								
									
										21
									
								
								cli/get_issues.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								cli/get_issues.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | |||||||
|  | from jira import JIRA | ||||||
|  | from rich.console import Console | ||||||
|  |  | ||||||
|  | from jql_utils import JQLPrompt, load_config | ||||||
|  |  | ||||||
|  | config = load_config() | ||||||
|  | console = Console(color_system="truecolor") | ||||||
|  | jira = JIRA(server=config["server"], basic_auth=(config["username"], config["token"])) | ||||||
|  | jql_prompt = JQLPrompt(jira) | ||||||
|  |  | ||||||
|  | issues = jql_prompt.prompt() | ||||||
|  |  | ||||||
|  | console.print("[ℹ] Getting more issues... 🚀", style="#A3BE8C bold") | ||||||
|  |  | ||||||
|  | more_issues = jql_prompt.multi_prompt() | ||||||
|  |  | ||||||
|  | if issues or more_issues: | ||||||
|  |     console.print("[ℹ] Saving logs... 🚀", style="#A3BE8C bold") | ||||||
|  |     jql_prompt.save_log() | ||||||
|  |  | ||||||
|  | console.print("Exiting... 🚀", style="bold green") | ||||||
| @@ -1,70 +0,0 @@ | |||||||
| from prompt_toolkit.lexers import Lexer |  | ||||||
| from prompt_toolkit.styles import Style |  | ||||||
| from prompt_toolkit.document import Document |  | ||||||
| from prompt_toolkit.formatted_text import StyleAndTextTuples |  | ||||||
| from typing import Callable |  | ||||||
|  |  | ||||||
| class JQLLexer(Lexer): |  | ||||||
|     def lex_document(self, document: Document) -> Callable[[int], StyleAndTextTuples]: |  | ||||||
|         text = document.text |  | ||||||
|         tokens = [] |  | ||||||
|  |  | ||||||
|         keywords = { |  | ||||||
|             "AND", "OR", "NOT", "IN", "ORDER BY", "ASC", "DESC", |  | ||||||
|             "IS", "NULL", "TRUE", "FALSE", "EMPTY" |  | ||||||
|         } |  | ||||||
|         operators = { |  | ||||||
|             "=", "!", ">", "<", ">=", "<=", "~", "!~", "!=" |  | ||||||
|         } |  | ||||||
|         punctuations = {"(", ")", ",", ":", " "} |  | ||||||
|  |  | ||||||
|         pos = 0 |  | ||||||
|         word = '' |  | ||||||
|  |  | ||||||
|         while pos < len(text): |  | ||||||
|             char = text[pos] |  | ||||||
|  |  | ||||||
|             if char.isalpha(): |  | ||||||
|                 word += char |  | ||||||
|             else: |  | ||||||
|                 if word: |  | ||||||
|                     if word.upper() in keywords: |  | ||||||
|                         tokens.append(('class:keyword', word)) |  | ||||||
|                     else: |  | ||||||
|                         tokens.append(('class:name', word)) |  | ||||||
|                     word = '' |  | ||||||
|  |  | ||||||
|                 if char in operators: |  | ||||||
|                     tokens.append(('class:operator', char)) |  | ||||||
|                 elif char in punctuations: |  | ||||||
|                     tokens.append(('class:punctuation', char)) |  | ||||||
|                 elif char.isspace(): |  | ||||||
|                     tokens.append(('class:text', char)) |  | ||||||
|                 else: |  | ||||||
|                     tokens.append(('class:error', char)) |  | ||||||
|             pos += 1 |  | ||||||
|  |  | ||||||
|         if word: |  | ||||||
|             if word.upper() in keywords: |  | ||||||
|                 tokens.append(('class:keyword', word)) |  | ||||||
|             else: |  | ||||||
|                 tokens.append(('class:name', word)) |  | ||||||
|  |  | ||||||
|         return lambda i: tokens |  | ||||||
|  |  | ||||||
| # Example usage |  | ||||||
| from prompt_toolkit import PromptSession |  | ||||||
|  |  | ||||||
| custom_style = Style.from_dict({ |  | ||||||
|     'keyword': '#ff0066 bold', |  | ||||||
|     'operator': '#00ff00', |  | ||||||
|     'name': '#0000ff', |  | ||||||
|     'punctuation': '#00ffff', |  | ||||||
|     'text': '#ffffff', |  | ||||||
|     'error': '#ff0000 bold', |  | ||||||
| }) |  | ||||||
|  |  | ||||||
| session = PromptSession(lexer=JQLLexer(), style=custom_style) |  | ||||||
|  |  | ||||||
| text = session.prompt('Enter JQL: ') |  | ||||||
| print(f'You entered: {text}') |  | ||||||
| @@ -1,17 +1,19 @@ | |||||||
| import json | import json | ||||||
| from typing import Dict, List | from datetime import datetime | ||||||
|  | from typing import Dict, List, Optional | ||||||
| 
 | 
 | ||||||
| from jira import JIRA | from jira import JIRA | ||||||
| from jira.exceptions import JIRAError | from jira.exceptions import JIRAError | ||||||
|  | from jira.resources import Issue | ||||||
| from prompt_toolkit import PromptSession | from prompt_toolkit import PromptSession | ||||||
| from prompt_toolkit.completion import Completer, Completion | from prompt_toolkit.completion import Completer, Completion | ||||||
| from prompt_toolkit.lexers import PygmentsLexer | from prompt_toolkit.lexers import PygmentsLexer | ||||||
|  | from prompt_toolkit.shortcuts import confirm | ||||||
| from prompt_toolkit.styles import Style | from prompt_toolkit.styles import Style | ||||||
| from prompt_toolkit.validation import ValidationError, Validator | from prompt_toolkit.validation import ValidationError, Validator | ||||||
| from prompt_toolkit.shortcuts import confirm |  | ||||||
| from pygments.lexer import RegexLexer | from pygments.lexer import RegexLexer | ||||||
| from pygments.token import Error, Keyword, Name, Operator, Punctuation, String, Text, Whitespace, _TokenType | from pygments.token import (Error, Keyword, Name, Operator, Punctuation, | ||||||
| 
 |                             String, Text, Whitespace, _TokenType) | ||||||
| from rich.console import Console | from rich.console import Console | ||||||
| from rich.text import Text as RichText | from rich.text import Text as RichText | ||||||
| 
 | 
 | ||||||
| @@ -38,10 +40,10 @@ class JQLLexer(RegexLexer): | |||||||
|                 Keyword, |                 Keyword, | ||||||
|             ), |             ), | ||||||
|             ( |             ( | ||||||
|                 r"(?i)\b(?:Assignee|affectedVersion|Attachments|Category|Comment|Component|Created|createdDate|" |                 r"(?i)\b(?:assignee|affectedVersion|attachments|category|comment|component|created|createdDate|" | ||||||
|                 r"Creator|Description|Due|duedate|Filter|fixVersion|issuekey|issuetype|issueLinkType|Labels|" |                 r"creator|cescription|due|duedate|filter|fixVersion|issuekey|issuetype|issueLinkType|labels|" | ||||||
|                 r"lastViewed|Priority|Project|Reporter|Resolved|Sprint|Status|statusCategory|Summary|Text|" |                 r"lastViewed|priority|project|reporter|resolved|Sprint|status|statusCategory|summary|text|" | ||||||
|                 r"timespent|Voter|Watcher)\b", |                 r"timespent|updated|updatedDate|voter|watcher|watchers)\b", | ||||||
|                 Name.Attribute, |                 Name.Attribute, | ||||||
|             ), |             ), | ||||||
|             (r"(?i)(=|!=|<|>|<=|>=|~|!~|IN|NOT IN|IS|IS NOT|WAS|WAS IN|WAS NOT IN|WAS NOT)", Operator), |             (r"(?i)(=|!=|<|>|<=|>=|~|!~|IN|NOT IN|IS|IS NOT|WAS|WAS IN|WAS NOT IN|WAS NOT)", Operator), | ||||||
| @@ -178,6 +180,7 @@ completions: Dict[str, List[str]] = { | |||||||
|         "summary", |         "summary", | ||||||
|         "text", |         "text", | ||||||
|         "timespent", |         "timespent", | ||||||
|  |         "updated", | ||||||
|         "voter", |         "voter", | ||||||
|         "watcher", |         "watcher", | ||||||
|     ], |     ], | ||||||
| @@ -281,21 +284,26 @@ def load_config(): | |||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class JQLPrompt: | class JQLPrompt: | ||||||
|     def __init__(self, jira, console): |     def __init__(self, jira): | ||||||
|         self.jira = jira |         self.jira: JIRA = jira | ||||||
|         self.console = console |         self.console: Console = Console(color_system="truecolor", record=True) | ||||||
|         self.session = self.create_jql_prompt_session() |         self.session: PromptSession = self.create_jql_prompt_session() | ||||||
|         self.jql = JQLPrinter(console) |         self.jql: JQLPrinter = JQLPrinter(self.console) | ||||||
|         self.query_count = 0 |         self.query_count: int = 0 | ||||||
|  |         self.issue_count: int = 0 | ||||||
|  |         self.total_issue_count: int = 0 | ||||||
|  |         self.issues: List[Issue] = [] | ||||||
| 
 | 
 | ||||||
|     def get_query_count(self): |     def get_query_count(self): | ||||||
|         space = self.console.width // 4 |         space = self.console.width // 3 | ||||||
|         query_count_str = f"Query count: {self.query_count}" |         query_count_str = f"Query Count: {self.query_count}" if self.query_count else "" | ||||||
|         plain_text = f"{query_count_str:^{space}}{query_count_str:^{space}}{query_count_str:^{space}}{query_count_str:^{space}}" |         issue_count_str = f"Issues Added: {self.issue_count}" if self.issue_count else "" | ||||||
|  |         total_issue_count_str = f"Total Issues: {self.total_issue_count}" if self.total_issue_count else "" | ||||||
|  |         plain_text = f"{query_count_str:^{space}}{issue_count_str:^{space}}{total_issue_count_str:^{space}}" | ||||||
|         return [("bg:#2E3440 #D8DEE9", plain_text)] |         return [("bg:#2E3440 #D8DEE9", plain_text)] | ||||||
| 
 | 
 | ||||||
|     def create_jql_prompt_session(self): |     def create_jql_prompt_session(self): | ||||||
|         completer = JQLCompleter(completions) |         completer: JQLCompleter = JQLCompleter(completions) | ||||||
|         return PromptSession( |         return PromptSession( | ||||||
|             message=[("#B48EAD", "JQL \u276f ")], |             message=[("#B48EAD", "JQL \u276f ")], | ||||||
|             lexer=PygmentsLexer(JQLLexer), |             lexer=PygmentsLexer(JQLLexer), | ||||||
| @@ -310,8 +318,9 @@ class JQLPrompt: | |||||||
|             validate_while_typing=False, |             validate_while_typing=False, | ||||||
|         ) |         ) | ||||||
| 
 | 
 | ||||||
|     def get_input(self): |     def prompt(self) -> Optional[List[Issue]]: | ||||||
|         user_input = self.session.prompt() |         user_input: str = self.session.prompt() | ||||||
|  |         self.issue_count = 0 | ||||||
|         if not user_input: |         if not user_input: | ||||||
|             do_empty_query = confirm( |             do_empty_query = confirm( | ||||||
|                 [("#EBCB8B bold", "[?] "), ("#D8DEE9 bold", "Do you want to perform an empty query?")], |                 [("#EBCB8B bold", "[?] "), ("#D8DEE9 bold", "Do you want to perform an empty query?")], | ||||||
| @@ -328,21 +337,39 @@ class JQLPrompt: | |||||||
|             self.query_count += 1 |             self.query_count += 1 | ||||||
|             self.console.print( |             self.console.print( | ||||||
|                 RichText.assemble( |                 RichText.assemble( | ||||||
|                     (f"[+] Found {len(issues)} issues from JQL query: ", "green bold"), |                     (f"[+] Found {len(issues)} issues from JQL query: ", "#A3BE8C bold"), | ||||||
|                     self.jql.pygments_to_rich(user_input), |                     self.jql.pygments_to_rich(user_input), | ||||||
|                 ), |                 ), | ||||||
|                 end="", |                 end="", | ||||||
|             ) |             ) | ||||||
|             for issue in issues: |             return issues | ||||||
|                 self.console.print(f"{issue.key}: {issue.fields.summary}") |         self.console.print("[!] No issues found.", style="#BF616A bold") | ||||||
| 
 | 
 | ||||||
|     def run(self): |     def multi_prompt(self) -> Optional[List[Issue]]: | ||||||
|  |         self.issues = [] | ||||||
|         while True: |         while True: | ||||||
|             try: |             try: | ||||||
|                 self.get_input() |                 issues = self.prompt() | ||||||
|  |                 if issues: | ||||||
|  |                     issues = [issue for issue in issues if issue not in self.issues] | ||||||
|  |                     self.issues.extend(issues) | ||||||
|  |                     self.issue_count += len(issues) | ||||||
|  |                     self.total_issue_count += len(issues) | ||||||
|  |                 self.console.print(f"[ℹ] Total issues: {len(self.issues)}", style="#D8DEE9") | ||||||
|  |                 get_more = confirm([("#A3BE8C", "[?] Get more issues?")], suffix=[("#81A1C1 bold", " (Y/n) ")]) | ||||||
|  |                 if not get_more: | ||||||
|  |                     break | ||||||
|             except (EOFError, KeyboardInterrupt): |             except (EOFError, KeyboardInterrupt): | ||||||
|                 break |                 break | ||||||
|         self.console.print("Goodbye!", style="#BF616A bold") |         if self.issues: | ||||||
|  |             self.console.print(f"[+] {self.total_issue_count} Issues added:", style="#A3BE8C bold") | ||||||
|  |             return self.issues | ||||||
|  |         self.console.print("[!] No issues added.", style="#BF616A bold") | ||||||
|  | 
 | ||||||
|  |     def save_log(self): | ||||||
|  |         log_time = datetime.now().strftime("%Y-%m-%d_%H-%M-%S") | ||||||
|  |         with open(f"jql_{log_time}.txt", "w") as log_file: | ||||||
|  |             log_file.write(self.console.export_text()) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| """ | """ | ||||||
| @@ -362,10 +389,9 @@ class JQLPrompt: | |||||||
| 
 | 
 | ||||||
| def main(): | def main(): | ||||||
|     config = load_config() |     config = load_config() | ||||||
|     console = Console(color_system="truecolor") |  | ||||||
|     jira = JIRA(server=config["server"], basic_auth=(config["username"], config["token"])) |     jira = JIRA(server=config["server"], basic_auth=(config["username"], config["token"])) | ||||||
|     prompt = JQLPrompt(jira, console) |     prompt = JQLPrompt(jira) | ||||||
|     prompt.run() |     prompt.multi_prompt() | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| if __name__ == "__main__": | if __name__ == "__main__": | ||||||
		Reference in New Issue
	
	Block a user