Skip to content

Commit

Permalink
Appease flake8
Browse files Browse the repository at this point in the history
  • Loading branch information
jhaigh0 committed Apr 26, 2024
1 parent 24fc693 commit 4dd35f9
Show file tree
Hide file tree
Showing 7 changed files with 95 additions and 60 deletions.
3 changes: 3 additions & 0 deletions web/.flake8
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,6 @@

exclude =
services/migrations,
services/github_issue_manager/test_search_for_matching_stacktrace.py,
services/github_issue_manager/test_trim_stacktrace.py,

80 changes: 51 additions & 29 deletions web/services/github_issue_manager/github_issue_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,15 @@
from github import Github, Auth

logger = logging.getLogger()
line_exp = re.compile(r"\s*File \".*(mantidqt|mantidqtinterfaces|workbench|scripts)(\/|\\)(.*)(\", line \d+, in \S+)")
line_exp = re.compile(r"\s*File \".*(mantidqt|mantidqtinterfaces|"
r"workbench|scripts)(\/|\\)(.*)(\", line \d+, in \S+)")
issue_text_template = Template("""
Name: $name
Email: $email
Mantid version: $version
OS: $os
**Additionl Information**
$info
Expand All @@ -30,35 +31,39 @@
OS: $os
**Additionl Information**
$info
$info
""")


def get_or_create_github_issue(report) -> GithubIssue | None:
"""
Given the stacktrace from the report, search for database entries with the same trace.
If found and there is a linked github issue, leave a comment with the report's key information.
If not, create a new issue.
Given the stacktrace from the report, search for database entries with the
same trace. If found and there is a linked github issue, leave a comment
with the report's key information. If not, create a new issue.
Return None in the following cases:
- There is no stack trace and no additional information in the report
- A GIT_AUTH_TOKEN has not been set
- The bug has already been submitted by the user (identified via the uid) and they have not left any additional information
- The bug has already been submitted by the user (identified via the uid)
and they have not left any additional information
Args:
report: The report recived by ErrorViewSet
Returns:
GithubIssue | None: A reference to a new or existing GithubIssue table entry, or None
GithubIssue | None: A reference to a new or existing GithubIssue table
entry, or None
"""
if not report.get('stacktrace') and not report.get('textBox'):
logger.info('No stacktrace or info in the report; skipping github issue interaction')
logger.info('No stacktrace or info in the report; skipping github'
' issue interaction')
return None

git_access_token = os.getenv('GIT_AUTH_TOKEN')
issue_repo = os.getenv('GIT_ISSUE_REPO')
if not git_access_token:
logger.info('No GIT_AUTH_TOKEN provided; skipping github issue interaction')
logger.info('No GIT_AUTH_TOKEN provided; skipping github issue'
' interaction')
return None

auth = Auth.Token(git_access_token)
Expand All @@ -68,50 +73,64 @@ def get_or_create_github_issue(report) -> GithubIssue | None:
github_issue = _search_for_matching_stacktrace(report["stacktrace"])
if github_issue and issue_repo == github_issue.repoName:
issue_number = github_issue.issueNumber
if _search_for_repeat_user(report['uid'], github_issue) and not report['textBox']:
if (_search_for_repeat_user(report['uid'], github_issue) and
not report['textBox']):
return github_issue

comment_text = comment_text_template.substitute(name=report['name'],
email=report['email'],
os=report['osReadable'],
version=report['mantidVersion'],
info=report['textBox'])

comment_text = comment_text_template.substitute(
name=report['name'],
email=report['email'],
os=report['osReadable'],
version=report['mantidVersion'],
info=report['textBox']
)
issue = repo.get_issue(number=int(issue_number))
issue.create_comment(comment_text)
logger.info(f'Added comment to issue {issue.url})')
return github_issue
else:
issue_text = issue_text_template.substitute(name=report['name'],
email=report['email'],
os=report['osReadable'],
version=report['mantidVersion'],
info=report['textBox'],
stacktrace=report['stacktrace'])
issue_text = issue_text_template.substitute(
name=report['name'],
email=report['email'],
os=report['osReadable'],
version=report['mantidVersion'],
info=report['textBox'],
stacktrace=report['stacktrace']
)
error_report_label = repo.get_label("Error Report")
issue = repo.create_issue(title="Automatic error report", labels=[error_report_label], body=issue_text)
issue = repo.create_issue(title="Automatic error report",
labels=[error_report_label],
body=issue_text)
logger.info(f'Created issue {issue.url})')
return GithubIssue.objects.create(repoName=issue_repo,
issueNumber=issue.number)


def _trim_stacktrace(stacktrace: str) -> str:
"""
Returns a rimmed and os non-specific version of the stacktrace given
"""
return '\n'.join([_stacktrace_line_trimer(line) for line in stacktrace.split('\n')])
return '\n'.join([_stacktrace_line_trimer(line) for line in
stacktrace.split('\n')])


def _stacktrace_line_trimer(line: str) -> str:
"""
Returns a trimmed and os non-specific version of the stacktrace line given
"""
match = line_exp.match(line)
if match:
path = pathlib.PureWindowsPath(os.path.normpath("".join(match.group(1,2,3))))
path = pathlib.PureWindowsPath(
os.path.normpath("".join(match.group(1, 2, 3)))
)
return path.as_posix() + match.group(4)
return line


def _search_for_matching_stacktrace(trace: str) -> GithubIssue | None:
"""
Search the database for a matching stack trace (irrespective of os, local install location etc.)
Search the database for a matching stack trace (irrespective of os, local
install location etc.)
Args:
trace (str): Raw stack trace from the report
Expand All @@ -122,16 +141,19 @@ def _search_for_matching_stacktrace(trace: str) -> GithubIssue | None:
if not trace:
return None
trimmed_trace = _trim_stacktrace(trace)
for raw_trace, github_issue in ErrorReport.objects.exclude(githubIssue__isnull=True).values_list('stacktrace', 'githubIssue'):
for raw_trace, github_issue in ErrorReport.objects.exclude(
githubIssue__isnull=True).values_list('stacktrace', 'githubIssue'):
if _trim_stacktrace(raw_trace) == trimmed_trace:
return GithubIssue.objects.get(id=github_issue)
return None


def _search_for_repeat_user(uid: str, github_issue: GithubIssue) -> bool:
"""
Return true if the user id has already submitted the same error
"""
for entry_uid in ErrorReport.objects.filter(githubIssue=github_issue).values_list('uid'):
for entry_uid in ErrorReport.objects.filter(
githubIssue=github_issue).values_list('uid'):
if uid == entry_uid:
return True
return False
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,26 @@

class MatchingStackTraceSearchTest(TestCase):
entries = [
(' File "/home/username/mantidworkbench/lib/python3.8/site-packages/mantidqt/widgets/memorywidget/memoryview.py", line 98, in _set_value'\
' @Slot(int, float, float)'\
(' File "/home/username/mantidworkbench/lib/python3.8/site-packages/mantidqt/widgets/memorywidget/memoryview.py", line 98, in _set_value'
' @Slot(int, float, float)'
'KeyboardInterrupt',
'1'),
(r' File "C:\MantidInstall\bin\mantidqt\widgets\workspacedisplay\matrix\table_view_model.py", line 172, in data'\
' return str(self.relevant_data(row)[index.column()])'\
(r' File "C:\MantidInstall\bin\mantidqt\widgets\workspacedisplay\matrix\table_view_model.py", line 172, in data'
' return str(self.relevant_data(row)[index.column()])'
'OverflowError: can\'t convert negative int to unsigned',
'2'),
(r' File "C:\MantidInstall\bin\mantidqt\widgets\codeeditor\interpreter.py", line 363, in _on_exec_error'\
' self.view.editor.updateProgressMarker(lineno, True)'\
(r' File "C:\MantidInstall\bin\mantidqt\widgets\codeeditor\interpreter.py", line 363, in _on_exec_error'
' self.view.editor.updateProgressMarker(lineno, True)'
'RuntimeError: wrapped C/C++ object of type ScriptEditor has been deleted',
'3'),
(r' File "C:\MantidInstall\bin\lib\site-packages\mantidqt\widgets\plotconfigdialog\curvestabwidget\presenter.py", line 367, in line_apply_to_all'\
' self.apply_properties()'\
r' File "C:\MantidInstall\bin\lib\site-packages\mantidqt\widgets\plotconfigdialog\curvestabwidget\presenter.py", line 69, in apply_properties'\
' FigureErrorsManager.toggle_errors(curve, view_props)'\
r' File "C:\MantidInstall\bin\lib\site-packages\workbench\plotting\figureerrorsmanager.py", line 108, in toggle_errors'\
' hide_errors = view_props.hide_errors or view_props.hide'\
r' File "C:\MantidInstall\bin\lib\site-packages\mantidqt\widgets\plotconfigdialog\curvestabwidget\__init__.py", line 137, in __getattr__'\
' return self[item]'\
(r' File "C:\MantidInstall\bin\lib\site-packages\mantidqt\widgets\plotconfigdialog\curvestabwidget\presenter.py", line 367, in line_apply_to_all'
' self.apply_properties()'
r' File "C:\MantidInstall\bin\lib\site-packages\mantidqt\widgets\plotconfigdialog\curvestabwidget\presenter.py", line 69, in apply_properties'
' FigureErrorsManager.toggle_errors(curve, view_props)'
r' File "C:\MantidInstall\bin\lib\site-packages\workbench\plotting\figureerrorsmanager.py", line 108, in toggle_errors'
' hide_errors = view_props.hide_errors or view_props.hide'
r' File "C:\MantidInstall\bin\lib\site-packages\mantidqt\widgets\plotconfigdialog\curvestabwidget\__init__.py", line 137, in __getattr__'
' return self[item]'
'KeyError: \'hide_errors\'',
'4'),
]
Expand All @@ -51,7 +51,7 @@ def test_retrieve_issue_number_with_identical_trace(self):

def test_retrieve_issue_number_with_different_path_seperators(self):
for trace, issue_number in self.entries:
altered_trace = trace.replace('/', '\\') if '/' in trace else trace.replace('\\','/')
altered_trace = trace.replace('/', '\\') if '/' in trace else trace.replace('\\', '/')
self.assertEqual(issue_number, _search_for_matching_stacktrace(altered_trace).issueNumber)

def test_different_user_name_yields_same_issue_number(self):
Expand All @@ -63,4 +63,4 @@ def test_different_install_location_yields_same_issue_number(self):
trace, issue_number = self.entries[1]
trace.replace('MantidInstall', 'my\\mantid\\install')
self.assertEqual(issue_number, _search_for_matching_stacktrace(trace).issueNumber)

2 changes: 2 additions & 0 deletions web/services/github_issue_manager/test_trim_stacktrace.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from services.github_issue_manager.github_issue_manager import _trim_stacktrace, _stacktrace_line_trimer
import unittest


class TrimStacktraceTest(unittest.TestCase):

def test_user_specific_dirs_are_removed(self):
Expand Down Expand Up @@ -38,5 +39,6 @@ def test_line_trimmer_other_lines(self):
for line in examples:
self.assertEqual(_stacktrace_line_trimer(line), line)


if __name__ == '__main__':
unittest.main()
11 changes: 7 additions & 4 deletions web/services/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,11 +76,13 @@ def clearOrphanedRecords():
num_refs=models.Count('errorreport')).filter(num_refs=0)
no_refs.delete()


class GithubIssue(models.Model):
repoName = models.CharField(max_length=200,
default="",
blank=True,
help_text="'user/repo_name': for example 'mantidproject/mantid'")
default="",
blank=True,
help_text="'user/repo_name': for example "
"'mantidproject/mantid'")
issueNumber = models.CharField(max_length=16, default="", blank=True)


Expand Down Expand Up @@ -119,7 +121,8 @@ def notify_report_received(sender, instance, signal, *args, **kwargs):
return

if instance.githubIssue:
issue_link = f"https://github.com/{instance.githubIssue.repoName}/issues/{instance.githubIssue.issueNumber}"
issue_link = (f"https://github.com/{instance.githubIssue.repoName}"
f"/issues/{instance.githubIssue.issueNumber}")

notification_thread = threading.Thread(
target=send_notification_to_slack, args=(name,
Expand Down
23 changes: 13 additions & 10 deletions web/services/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
$add_text
Stack Trace:
$stacktrace
Using: $application $version on $os
Using: $application $version on $os
$issue_link
""")

Expand All @@ -35,22 +35,25 @@ def send_notification_to_slack(name,
slack_webhook_url = settings.SLACK_WEBHOOK_URL
if not slack_webhook_url:
return
text = slack_message.substitute(name = _string_or_empty_field(name),
email = _string_or_empty_field(name),
add_text = _string_or_empty_field(additional_text),
stacktrace = _string_or_empty_field(stacktrace),
application = _string_or_empty_field(application),
version = _string_or_empty_field(version),
os = _string_or_empty_field(os),
issue_link = _string_or_empty_field(github_issue_link))
text = slack_message.substitute(
name=_string_or_empty_field(name),
email=_string_or_empty_field(name),
add_text=_string_or_empty_field(additional_text),
stacktrace=_string_or_empty_field(stacktrace),
application=_string_or_empty_field(application),
version=_string_or_empty_field(version),
os=_string_or_empty_field(os),
issue_link=_string_or_empty_field(github_issue_link)
)
requests.post(slack_webhook_url,
json={
'channel': settings.SLACK_ERROR_REPORTS_CHANNEL,
'username': settings.SLACK_ERROR_REPORTS_USERNAME,
'text': text,
'icon_emoji': settings.SLACK_ERROR_REPORTS_EMOJI
})



def _string_or_empty_field(value: str):
return value if value else settings.SLACK_ERROR_REPORTS_EMPTY_FIELD_TEXT

Expand Down
4 changes: 3 additions & 1 deletion web/services/views.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from services.models import ErrorReport, UserDetails
from services.github_issue_manager.github_issue_manager import get_or_create_github_issue
from services.github_issue_manager.github_issue_manager import (
get_or_create_github_issue
)
from services.constants import input_box_max_length
from rest_framework import response, viewsets, views
from rest_framework.decorators import api_view
Expand Down

0 comments on commit 4dd35f9

Please sign in to comment.