Fixed bugs and added last comment auto completion
This commit is contained in:
parent
0a01146227
commit
3189d9a7a5
@ -96,7 +96,8 @@ class WorklogDialog(QtWidgets.QDialog):
|
||||
def __init__(self, config: Config, worklog: Worklog, parent, *args, **kwargs):
|
||||
super().__init__(parent, *args, **kwargs)
|
||||
|
||||
self.rest = WorklogRest(config)
|
||||
self.config = config
|
||||
self.rest = WorklogRest(self.config)
|
||||
|
||||
self._changing_items = False
|
||||
self._worklog = worklog
|
||||
@ -172,8 +173,10 @@ class WorklogDialog(QtWidgets.QDialog):
|
||||
self.update_timer.timeout.connect(self.update_statuses)
|
||||
|
||||
def showEvent(self, _):
|
||||
self.rest.purge_cache()
|
||||
# reinitialize to purge caches
|
||||
self.rest = WorklogRest(self.config)
|
||||
self.update_all()
|
||||
self.upload_button.setEnabled(False)
|
||||
|
||||
def update_all(self):
|
||||
self.refresh_table()
|
||||
@ -187,10 +190,13 @@ class WorklogDialog(QtWidgets.QDialog):
|
||||
for row in self._worklog_data[:-1]:
|
||||
issue_keys.append(row[0].split()[0])
|
||||
old_statuses = self._statuses
|
||||
self._statuses = self.rest.get_issues_state(issue_keys)
|
||||
self._statuses = self.rest.get_issues_state(issue_keys, self._worklog.date)
|
||||
for row, status in enumerate(self._statuses):
|
||||
if len(old_statuses) != len(self._statuses) or old_statuses[row][0] != status[0]:
|
||||
self.update_status_view(row)
|
||||
if not self._worklog_data[row][1] and status[2]:
|
||||
self._worklog_data[row][1] = status[2]
|
||||
self.tableWidget.cellWidget(row, 1).setPlainText(status[2])
|
||||
all_ok = reduce(lambda acc, it: acc and it[0] is Status.OK, self._statuses, True)
|
||||
if all_ok:
|
||||
self.upload_button.setEnabled(True)
|
||||
|
@ -6,7 +6,7 @@ from datetime import date, datetime, timedelta, time
|
||||
from functools import partial
|
||||
from textwrap import dedent
|
||||
from threading import Lock
|
||||
from typing import List, Dict, Tuple
|
||||
from typing import List, Dict, Tuple, Optional
|
||||
|
||||
import requests
|
||||
from requests_futures.sessions import FuturesSession
|
||||
@ -25,9 +25,11 @@ class WorklogRest:
|
||||
self.worklog_update_url = os.path.join(config.jira_url, "rest/api/2/issue/{issue_key}/worklog/{worklog_id}")
|
||||
self.session = FuturesSession()
|
||||
self._user = None
|
||||
self._user_future = self._req_user()
|
||||
self._issue_state: Dict[str, Tuple[Status, str]] = dict()
|
||||
self._issue_state_lock = Lock()
|
||||
self._req_user()
|
||||
self._issue_previous_comments: Dict[str, str] = dict()
|
||||
self._issue_worklog_id: Dict[str, str] = dict()
|
||||
self._issues_lock = Lock()
|
||||
|
||||
def _req_user(self):
|
||||
future = self.session.get(
|
||||
@ -38,6 +40,7 @@ class WorklogRest:
|
||||
},
|
||||
)
|
||||
future.add_done_callback(self._resp_user)
|
||||
return future
|
||||
|
||||
def _resp_user(self, future):
|
||||
try:
|
||||
@ -46,20 +49,21 @@ class WorklogRest:
|
||||
print("Could not get user key:\n", file=sys.stderr)
|
||||
print(traceback.format_exc(), file=sys.stderr)
|
||||
|
||||
def get_issues_state(self, issue_keys: List[str]):
|
||||
def get_issues_state(self, issue_keys: List[str], pdate: date) -> List[Tuple[Status, str, Optional[str]]]:
|
||||
ret = []
|
||||
with self._issue_state_lock:
|
||||
with self._issues_lock:
|
||||
for issue_key in issue_keys:
|
||||
if issue_key not in self._issue_state:
|
||||
self._issue_state[issue_key] = (Status.PROGRESS, "Working")
|
||||
self._req_issue(issue_key)
|
||||
ret.append(self._issue_state[issue_key])
|
||||
self._req_issue(issue_key, pdate)
|
||||
if issue_key in self._issue_previous_comments:
|
||||
prev_comment = self._issue_previous_comments[issue_key]
|
||||
else:
|
||||
prev_comment = None
|
||||
ret.append((*self._issue_state[issue_key], prev_comment))
|
||||
return ret
|
||||
|
||||
def purge_cache(self):
|
||||
self._issue_state = dict()
|
||||
|
||||
def _req_issue(self, issue_key: str):
|
||||
def _req_issue(self, issue_key: str, pdate :date):
|
||||
future = self.session.get(
|
||||
self.issue_url.format(issue_key),
|
||||
headers={
|
||||
@ -67,22 +71,60 @@ class WorklogRest:
|
||||
"Accept": "application/json",
|
||||
},
|
||||
)
|
||||
future.add_done_callback(partial(self._resp_issue, issue_key))
|
||||
future.add_done_callback(partial(self._resp_issue, issue_key, pdate))
|
||||
|
||||
def _resp_issue(self, issue_key: str, future: Future):
|
||||
def _resp_issue(self, issue_key: str, pdate: date, future: Future):
|
||||
resp: requests.Response = future.result()
|
||||
with self._issue_state_lock:
|
||||
with self._issues_lock:
|
||||
if resp.status_code == 200:
|
||||
hint = f'{issue_key} {resp.json()["fields"]["summary"]}'
|
||||
self._issue_state[issue_key] = (Status.OK, hint)
|
||||
issue_title = f'{issue_key} {resp.json()["fields"]["summary"]}'
|
||||
self._req_worklog_check(issue_key, issue_title, pdate)
|
||||
else:
|
||||
self._issue_state[issue_key] = (Status.ERROR, "Could not find specified issue")
|
||||
|
||||
def _req_worklog_check(self, issue_key: str, issue_title: str, pdate: date):
|
||||
future = self.session.get(
|
||||
self.worklog_url.format(issue_key),
|
||||
headers={
|
||||
"Authorization": f"Bearer {self.config.jira_token}",
|
||||
"Accept": "application/json",
|
||||
},
|
||||
)
|
||||
future.add_done_callback(partial(self._resp_worklog_check, issue_key, issue_title, pdate))
|
||||
|
||||
def _resp_worklog_check(self, issue_key: str, issue_title: str, pdate: date, future: Future):
|
||||
resp = future.result()
|
||||
worklogs = resp.json()["worklogs"]
|
||||
worklogs = sorted(
|
||||
worklogs, key=lambda x: datetime.strptime(x["started"], "%Y-%m-%dT%H:%M:%S.%f%z"), reverse=True)
|
||||
self._user_future.result()
|
||||
if not self._user:
|
||||
with self._issues_lock:
|
||||
self._issue_state[issue_key] = (Status.OK, issue_title)
|
||||
return
|
||||
worklog_found = False
|
||||
with self._issues_lock:
|
||||
for log in worklogs:
|
||||
if log["author"]["key"] == self._user:
|
||||
if datetime.strptime(log["started"], "%Y-%m-%dT%H:%M:%S.%f%z").date() == pdate:
|
||||
self._issue_worklog_id[issue_key] = log["id"]
|
||||
worklog_found = True
|
||||
else:
|
||||
self._issue_previous_comments[issue_key] = log["comment"].strip()
|
||||
worklog_found = True
|
||||
break
|
||||
if worklog_found:
|
||||
print(f"Found existing worklog for issue {issue_key}")
|
||||
else:
|
||||
print(f"Did not find existing worklog for issue {issue_key}")
|
||||
self._issue_state[issue_key] = (Status.OK, issue_title)
|
||||
|
||||
def _upload_sanity_check(self, issue_keys: List[str]):
|
||||
if not self._user:
|
||||
raise FimeException("Could not get user key")
|
||||
# lock is held by caller
|
||||
for issue_key in issue_keys:
|
||||
if issue_key not in self._issue_state or self._issue_state[issue_key] is not Status.OK:
|
||||
if issue_key not in self._issue_state or self._issue_state[issue_key][0] is not Status.OK:
|
||||
raise FimeException(f"Issue with key {issue_key} in unexpected state")
|
||||
|
||||
def upload(self, issues: List[Tuple[str, str, timedelta]], pdate: date):
|
||||
@ -92,33 +134,15 @@ class WorklogRest:
|
||||
timedelta(seconds=300),
|
||||
), ... ]
|
||||
"""
|
||||
with self._issues_lock:
|
||||
self._upload_sanity_check(list(map(lambda x: x[0], issues)))
|
||||
for issue in issues:
|
||||
future = self.session.get(
|
||||
self.worklog_url.format(issue[0]),
|
||||
headers={
|
||||
"Authorization": f"Bearer {self.config.jira_token}",
|
||||
"Accept": "application/json",
|
||||
}
|
||||
)
|
||||
future.add_done_callback(partial(self._worklog_check_resp, issue[0], issue[1], issue[2], pdate))
|
||||
self._issue_state[issue[0]] = (Status.PROGRESS, "Working")
|
||||
|
||||
def _worklog_check_resp(self, issue_key: str, comment: str, time_spent: timedelta, pdate: date, future: Future):
|
||||
resp = future.result()
|
||||
worklogs = resp.json()["worklogs"]
|
||||
worklog_id = None
|
||||
for log in worklogs:
|
||||
if log["author"]["key"] == self._user \
|
||||
and datetime.strptime(log["started"], "%Y-%m-%dT%H:%M:%S.%f%z").date() == pdate:
|
||||
worklog_id = log["id"]
|
||||
break
|
||||
if worklog_id:
|
||||
print(f"Found existing worklog for issue {issue_key} with id {worklog_id}")
|
||||
self._worklog_update(issue_key, worklog_id, comment, time_spent, pdate)
|
||||
issue_key, comment, time_spent = issue
|
||||
if issue_key in self._issue_worklog_id:
|
||||
self._worklog_update(issue_key, self._issue_worklog_id[issue_key], comment, time_spent, pdate)
|
||||
else:
|
||||
print(f"Did not find existing worklog for issue {issue_key}")
|
||||
self._worklog_create(issue_key, comment, time_spent, pdate)
|
||||
self._issue_state[issue[0]] = (Status.PROGRESS, "Working")
|
||||
|
||||
def _worklog_create(self, issue_key: str, comment: str, time_spent: timedelta, pdate: date):
|
||||
future = self.session.post(
|
||||
@ -156,8 +180,8 @@ class WorklogRest:
|
||||
|
||||
def _worklog_resp(self, issue_key: str, future: Future):
|
||||
resp: requests.Response = future.result()
|
||||
with self._issue_state_lock:
|
||||
if resp.status_code == 200:
|
||||
with self._issues_lock:
|
||||
if resp.status_code in (200, 201):
|
||||
self._issue_state[issue_key] = (Status.OK, "Successfully uploaded")
|
||||
print(f"Successfully uploaded issue {issue_key}")
|
||||
else:
|
||||
|
Loading…
Reference in New Issue
Block a user