126 lines
4.7 KiB
Python
126 lines
4.7 KiB
Python
|
import os
|
||
|
import sys
|
||
|
import traceback
|
||
|
from functools import reduce
|
||
|
from queue import Queue, Empty
|
||
|
from urllib.parse import urlparse, parse_qs
|
||
|
|
||
|
from PySide2 import QtCore
|
||
|
from PySide2.QtCore import QTimer
|
||
|
from PySide2.QtWidgets import QCompleter
|
||
|
from requests_futures.sessions import FuturesSession
|
||
|
|
||
|
from config import Config
|
||
|
|
||
|
|
||
|
class TaskCompleter(QCompleter):
|
||
|
def __init__(self, parent=None, *args, **kwargs):
|
||
|
super().__init__([], parent, *args, **kwargs)
|
||
|
self.setFilterMode(QtCore.Qt.MatchFlag.MatchContains)
|
||
|
self.setCaseSensitivity(QtCore.Qt.CaseInsensitive)
|
||
|
self.session = FuturesSession()
|
||
|
self.config = Config()
|
||
|
self.picker_url = os.path.join(self.config.jira_url, "rest/api/2/issue/picker")
|
||
|
self.search_url = os.path.join(self.config.jira_url, "rest/api/2/search")
|
||
|
self.text = ""
|
||
|
self.response_text = ""
|
||
|
self.model_string_list = []
|
||
|
self.escalate = False
|
||
|
self.update_timer = QTimer(self)
|
||
|
self.update_timer.timeout.connect(self.process_response)
|
||
|
self.update_timer.setInterval(250)
|
||
|
self.queue = Queue()
|
||
|
|
||
|
@QtCore.Slot()
|
||
|
def process_response(self):
|
||
|
try:
|
||
|
while not self.queue.empty():
|
||
|
result_dict = self.queue.get_nowait()
|
||
|
if result_dict["response_text"] == self.text:
|
||
|
if self.text == self.response_text:
|
||
|
self.response_text = result_dict["response_text"]
|
||
|
self.model_string_list = result_dict["result"]
|
||
|
else:
|
||
|
self.model_string_list += result_dict["result"]
|
||
|
self.model().setStringList(self.model_string_list)
|
||
|
self.complete()
|
||
|
except Empty:
|
||
|
return
|
||
|
|
||
|
@QtCore.Slot(str)
|
||
|
def update_picker(self, text):
|
||
|
self.text = text
|
||
|
if self.text == self.currentCompletion():
|
||
|
# do not update, after auto completion was used
|
||
|
return
|
||
|
if self.escalate:
|
||
|
self.update_search()
|
||
|
if not self.update_timer.isActive():
|
||
|
self.update_timer.start()
|
||
|
future = self.session.get(
|
||
|
url=self.picker_url,
|
||
|
params={
|
||
|
"query": self.text
|
||
|
},
|
||
|
headers={
|
||
|
"Authorization": f"Bearer {self.config.jira_token}",
|
||
|
"Accept": "application/json",
|
||
|
},
|
||
|
)
|
||
|
future.add_done_callback(self.picker_response_callback)
|
||
|
|
||
|
def picker_response_callback(self, future):
|
||
|
try:
|
||
|
result = future.result()
|
||
|
parsed = urlparse(result.request.url)
|
||
|
response_text = parse_qs(parsed.query)["query"][0]
|
||
|
issues = reduce(lambda x, y: x + (y["issues"]), result.json()["sections"], [])
|
||
|
extracted = list(map(lambda x: f"{x['key']} {x['summaryText']}", issues))
|
||
|
if extracted:
|
||
|
self.queue.put({
|
||
|
"response_text": response_text,
|
||
|
"result": extracted,
|
||
|
})
|
||
|
else:
|
||
|
if not self.escalate:
|
||
|
print("No picker results. Escalating")
|
||
|
self.escalate = True
|
||
|
self.update_search()
|
||
|
except Exception:
|
||
|
print("Ignoring exception, as it only breaks autocompletion:", file=sys.stderr)
|
||
|
print(traceback.format_exc(), file=sys.stderr)
|
||
|
return
|
||
|
|
||
|
def update_search(self):
|
||
|
for jql in [f"text = {self.text}", f"key = {self.text}"]:
|
||
|
future = self.session.get(
|
||
|
url=self.search_url,
|
||
|
params={
|
||
|
"jql": jql,
|
||
|
"maxResults": 10,
|
||
|
"fields": "key,summary",
|
||
|
},
|
||
|
headers={
|
||
|
"Authorization": f"Bearer {self.config.jira_token}",
|
||
|
"Accept": "application/json",
|
||
|
},
|
||
|
)
|
||
|
future.add_done_callback(self.search_response_callback)
|
||
|
|
||
|
def search_response_callback(self, future):
|
||
|
try:
|
||
|
result = future.result()
|
||
|
json_result = result.json()
|
||
|
parsed = urlparse(result.request.url)
|
||
|
response_text = parse_qs(parsed.query)["jql"][0].split()[2]
|
||
|
if "issues" in json_result:
|
||
|
extracted = list(map(lambda x: f"{x['key']} {x['fields']['summary']}", json_result["issues"]))
|
||
|
self.queue.put({
|
||
|
"response_text": response_text,
|
||
|
"result": extracted,
|
||
|
})
|
||
|
except Exception:
|
||
|
print("Ignoring exception, as it only breaks autocompletion:", file=sys.stderr)
|
||
|
print(traceback.format_exc(), file=sys.stderr)
|
||
|
return
|