t-bug-catcher 0.4.4__tar.gz → 0.4.5__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {t_bug_catcher-0.4.4 → t_bug_catcher-0.4.5}/PKG-INFO +1 -1
- {t_bug_catcher-0.4.4 → t_bug_catcher-0.4.5}/setup.cfg +1 -1
- {t_bug_catcher-0.4.4 → t_bug_catcher-0.4.5}/setup.py +1 -1
- {t_bug_catcher-0.4.4 → t_bug_catcher-0.4.5}/t_bug_catcher/__init__.py +1 -1
- {t_bug_catcher-0.4.4 → t_bug_catcher-0.4.5}/t_bug_catcher/bug_catcher.py +25 -2
- {t_bug_catcher-0.4.4 → t_bug_catcher-0.4.5}/t_bug_catcher/jira.py +133 -0
- {t_bug_catcher-0.4.4 → t_bug_catcher-0.4.5}/t_bug_catcher.egg-info/PKG-INFO +1 -1
- {t_bug_catcher-0.4.4 → t_bug_catcher-0.4.5}/MANIFEST.in +0 -0
- {t_bug_catcher-0.4.4 → t_bug_catcher-0.4.5}/README.rst +0 -0
- {t_bug_catcher-0.4.4 → t_bug_catcher-0.4.5}/pyproject.toml +0 -0
- {t_bug_catcher-0.4.4 → t_bug_catcher-0.4.5}/requirements.txt +0 -0
- {t_bug_catcher-0.4.4 → t_bug_catcher-0.4.5}/t_bug_catcher/bug_snag.py +0 -0
- {t_bug_catcher-0.4.4 → t_bug_catcher-0.4.5}/t_bug_catcher/config.py +0 -0
- {t_bug_catcher-0.4.4 → t_bug_catcher-0.4.5}/t_bug_catcher/exceptions.py +0 -0
- {t_bug_catcher-0.4.4 → t_bug_catcher-0.4.5}/t_bug_catcher/resources/whispers_config.yml +0 -0
- {t_bug_catcher-0.4.4 → t_bug_catcher-0.4.5}/t_bug_catcher/stack_saver.py +0 -0
- {t_bug_catcher-0.4.4 → t_bug_catcher-0.4.5}/t_bug_catcher/utils/__init__.py +0 -0
- {t_bug_catcher-0.4.4 → t_bug_catcher-0.4.5}/t_bug_catcher/utils/common.py +0 -0
- {t_bug_catcher-0.4.4 → t_bug_catcher-0.4.5}/t_bug_catcher/utils/logger.py +0 -0
- {t_bug_catcher-0.4.4 → t_bug_catcher-0.4.5}/t_bug_catcher/workitems.py +0 -0
- {t_bug_catcher-0.4.4 → t_bug_catcher-0.4.5}/t_bug_catcher.egg-info/SOURCES.txt +0 -0
- {t_bug_catcher-0.4.4 → t_bug_catcher-0.4.5}/t_bug_catcher.egg-info/dependency_links.txt +0 -0
- {t_bug_catcher-0.4.4 → t_bug_catcher-0.4.5}/t_bug_catcher.egg-info/not-zip-safe +0 -0
- {t_bug_catcher-0.4.4 → t_bug_catcher-0.4.5}/t_bug_catcher.egg-info/requires.txt +0 -0
- {t_bug_catcher-0.4.4 → t_bug_catcher-0.4.5}/t_bug_catcher.egg-info/top_level.txt +0 -0
- {t_bug_catcher-0.4.4 → t_bug_catcher-0.4.5}/tests/test_t_bug_catcher.py +0 -0
|
@@ -26,7 +26,7 @@ setup(
|
|
|
26
26
|
packages=find_packages(include=["t_bug_catcher", "t_bug_catcher.*"]),
|
|
27
27
|
test_suite="tests",
|
|
28
28
|
url="https://www.thoughtful.ai/",
|
|
29
|
-
version="0.4.
|
|
29
|
+
version="0.4.5",
|
|
30
30
|
zip_safe=False,
|
|
31
31
|
install_requires=install_requirements,
|
|
32
32
|
include_package_data=True,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"""JiraPoster class for interacting with the Jira API."""
|
|
2
2
|
|
|
3
|
+
import inspect
|
|
3
4
|
import os
|
|
4
5
|
import sys
|
|
5
6
|
from types import TracebackType
|
|
@@ -129,11 +130,33 @@ class BugCatcher:
|
|
|
129
130
|
_, exception, _ = sys.exc_info()
|
|
130
131
|
|
|
131
132
|
if not isinstance(exception, Exception):
|
|
132
|
-
logger.warning("
|
|
133
|
+
logger.warning("Implementation error. Incorrect exception type.")
|
|
134
|
+
inspected_frame = inspect.currentframe().f_back
|
|
135
|
+
if self.__configurator.is_jira_configured:
|
|
136
|
+
self.__jira.warning_message(
|
|
137
|
+
summary="bug_catcher implementation warning ⚠️",
|
|
138
|
+
inspected_frame=inspected_frame,
|
|
139
|
+
message=(
|
|
140
|
+
"Incorrect exception type. Check the variable that holds the exception "
|
|
141
|
+
"and make sure that report_error() in the try/except block is called."
|
|
142
|
+
),
|
|
143
|
+
assignee=assignee,
|
|
144
|
+
)
|
|
133
145
|
return
|
|
134
146
|
|
|
135
147
|
if not getattr(exception, "__traceback__", None):
|
|
136
|
-
logger.warning("No traceback available.
|
|
148
|
+
logger.warning("Implementation error. No traceback available.")
|
|
149
|
+
inspected_frame = inspect.currentframe().f_back
|
|
150
|
+
if self.__configurator.is_jira_configured:
|
|
151
|
+
self.__jira.warning_message(
|
|
152
|
+
summary="bug_catcher implementation warning ⚠️",
|
|
153
|
+
inspected_frame=inspected_frame,
|
|
154
|
+
message=(
|
|
155
|
+
"No traceback is available. Please, use an exception with a traceback in the try/except block. "
|
|
156
|
+
"Not just called exceptions."
|
|
157
|
+
),
|
|
158
|
+
assignee=assignee,
|
|
159
|
+
)
|
|
137
160
|
return
|
|
138
161
|
|
|
139
162
|
handled_error = getattr(exception, "handled_error", None)
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import hashlib
|
|
4
4
|
import json
|
|
5
|
+
import linecache
|
|
5
6
|
import os
|
|
6
7
|
import re
|
|
7
8
|
import sys
|
|
@@ -375,6 +376,42 @@ class Jira:
|
|
|
375
376
|
}
|
|
376
377
|
]
|
|
377
378
|
|
|
379
|
+
@staticmethod
|
|
380
|
+
def __warning_markup(warning_message: str, message: str) -> List[dict]:
|
|
381
|
+
"""Create the error string markup.
|
|
382
|
+
|
|
383
|
+
Args:
|
|
384
|
+
warning_message (str): The warning message.
|
|
385
|
+
|
|
386
|
+
Returns:
|
|
387
|
+
dict: The error string markup.
|
|
388
|
+
"""
|
|
389
|
+
return [
|
|
390
|
+
{
|
|
391
|
+
"type": "panel",
|
|
392
|
+
"attrs": {"panelType": "warning"},
|
|
393
|
+
"content": [
|
|
394
|
+
{
|
|
395
|
+
"type": "paragraph",
|
|
396
|
+
"content": [
|
|
397
|
+
{
|
|
398
|
+
"type": "text",
|
|
399
|
+
"text": warning_message,
|
|
400
|
+
"marks": [{"type": "code"}],
|
|
401
|
+
},
|
|
402
|
+
],
|
|
403
|
+
},
|
|
404
|
+
{
|
|
405
|
+
"type": "paragraph",
|
|
406
|
+
"content": [
|
|
407
|
+
{"type": "text", "text": "Message: ", "marks": [{"type": "strong"}]},
|
|
408
|
+
{"type": "text", "text": message},
|
|
409
|
+
],
|
|
410
|
+
},
|
|
411
|
+
],
|
|
412
|
+
}
|
|
413
|
+
]
|
|
414
|
+
|
|
378
415
|
@staticmethod
|
|
379
416
|
def __date_markup() -> List[dict]:
|
|
380
417
|
"""Create the date markup.
|
|
@@ -671,6 +708,33 @@ class Jira:
|
|
|
671
708
|
+ self.__error_markup(error_id),
|
|
672
709
|
}
|
|
673
710
|
|
|
711
|
+
def __create_warning_description_markup(
|
|
712
|
+
self,
|
|
713
|
+
warning_message: str,
|
|
714
|
+
message: str,
|
|
715
|
+
warning_id: str,
|
|
716
|
+
) -> dict:
|
|
717
|
+
"""Create a warning description.
|
|
718
|
+
|
|
719
|
+
Args:
|
|
720
|
+
warning_message (str): The warning message.
|
|
721
|
+
warning_id (str): The warning ID.
|
|
722
|
+
|
|
723
|
+
Returns:
|
|
724
|
+
dict: A dictionary containing the version, type, and content.
|
|
725
|
+
"""
|
|
726
|
+
return {
|
|
727
|
+
"version": 1,
|
|
728
|
+
"type": "doc",
|
|
729
|
+
"content": []
|
|
730
|
+
+ self.__warning_markup(warning_message, message)
|
|
731
|
+
+ self.__bot_name_markup()
|
|
732
|
+
+ self.__date_markup()
|
|
733
|
+
+ self.__runlink_markup()
|
|
734
|
+
+ self.__environment_markup()
|
|
735
|
+
+ self.__error_markup(warning_id),
|
|
736
|
+
}
|
|
737
|
+
|
|
674
738
|
def __create_transtion_markup(self, issue_status: str) -> dict:
|
|
675
739
|
"""Create a transition markup.
|
|
676
740
|
|
|
@@ -962,6 +1026,55 @@ class Jira:
|
|
|
962
1026
|
self.move_ticket_to_board(ticket_id)
|
|
963
1027
|
return response
|
|
964
1028
|
|
|
1029
|
+
def warning_message(self, summary: str, inspected_frame, message: str, assignee: Optional[str] = None) -> None:
|
|
1030
|
+
"""Create a new ticket with warning message.
|
|
1031
|
+
|
|
1032
|
+
Args:
|
|
1033
|
+
summary (str): The summary of the ticket.
|
|
1034
|
+
inspected_frame (frame): The frame of the warning.
|
|
1035
|
+
assignee (str, optional): The assignee of the ticket. Defaults to None.
|
|
1036
|
+
|
|
1037
|
+
Returns:
|
|
1038
|
+
The response from creating the ticket.
|
|
1039
|
+
"""
|
|
1040
|
+
if self._project_key == CONFIG.SUPPORT_BOARD and CONFIG.ADMIN_CODE:
|
|
1041
|
+
summary = CONFIG.ADMIN_CODE + " - " + summary
|
|
1042
|
+
|
|
1043
|
+
warning_id, warning_message = self.__generate_warning_id(inspected_frame)
|
|
1044
|
+
|
|
1045
|
+
existing_ticket = self.filter_tickets(
|
|
1046
|
+
all_tickets=self.get_issues()["issues"],
|
|
1047
|
+
error_id=warning_id,
|
|
1048
|
+
)
|
|
1049
|
+
if existing_ticket:
|
|
1050
|
+
self.__update_existing_ticket(
|
|
1051
|
+
existing_ticket=existing_ticket,
|
|
1052
|
+
summary=summary,
|
|
1053
|
+
)
|
|
1054
|
+
return existing_ticket
|
|
1055
|
+
|
|
1056
|
+
assignee_id = None
|
|
1057
|
+
assignee = assignee if assignee else self._default_assignee
|
|
1058
|
+
if assignee:
|
|
1059
|
+
try:
|
|
1060
|
+
assignee_id = self.__get_assignee(assignee)
|
|
1061
|
+
except Exception as ex:
|
|
1062
|
+
logger.info(f"Failed to get assignee {assignee} due to: {ex}")
|
|
1063
|
+
|
|
1064
|
+
description = self.__create_warning_description_markup(
|
|
1065
|
+
warning_message=warning_message,
|
|
1066
|
+
message=message,
|
|
1067
|
+
warning_id=warning_id,
|
|
1068
|
+
)
|
|
1069
|
+
response = self.__create_new_ticket(
|
|
1070
|
+
summary=summary,
|
|
1071
|
+
description=description,
|
|
1072
|
+
assignee_id=assignee_id,
|
|
1073
|
+
labels=["bug_catcher_warning"],
|
|
1074
|
+
)
|
|
1075
|
+
|
|
1076
|
+
return response
|
|
1077
|
+
|
|
965
1078
|
def report_error(
|
|
966
1079
|
self,
|
|
967
1080
|
exception: Optional[Exception] = None,
|
|
@@ -1271,6 +1384,26 @@ class Jira:
|
|
|
1271
1384
|
error_id = f"{path}-{exception_chain}-{frames[-1].line}-" f"{exc_type.__module__}-{exc_type.__name__}"
|
|
1272
1385
|
return hashlib.md5(error_id.encode()).hexdigest()
|
|
1273
1386
|
|
|
1387
|
+
@staticmethod
|
|
1388
|
+
def __generate_warning_id(inspected_frame) -> tuple:
|
|
1389
|
+
"""Generates an error string ID using the exception, function name, and error string.
|
|
1390
|
+
|
|
1391
|
+
Args:
|
|
1392
|
+
inspected_frame (frame): The frame of the warning.
|
|
1393
|
+
|
|
1394
|
+
Returns:
|
|
1395
|
+
tuple: The generated error string ID and the warning message.
|
|
1396
|
+
"""
|
|
1397
|
+
lineno = inspected_frame.f_lineno
|
|
1398
|
+
filename = inspected_frame.f_code.co_filename
|
|
1399
|
+
func = inspected_frame.f_code.co_name
|
|
1400
|
+
line = linecache.getline(filename, lineno).strip()
|
|
1401
|
+
rel_path = os.path.relpath(filename, os.getcwd())
|
|
1402
|
+
|
|
1403
|
+
warning_message = f"{line}\n{rel_path}:{func}:{lineno}"
|
|
1404
|
+
warning_id = hashlib.md5(f"{filename}-{lineno}-{func}-{line}".encode()).hexdigest()
|
|
1405
|
+
return warning_id, warning_message
|
|
1406
|
+
|
|
1274
1407
|
def __get_assignee(self, assignee: str) -> str:
|
|
1275
1408
|
"""Get assignee Jira user by ID.
|
|
1276
1409
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|