t-bug-catcher 0.6.6__tar.gz → 0.6.9__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.6.6 → t_bug_catcher-0.6.9}/PKG-INFO +2 -2
- {t_bug_catcher-0.6.6 → t_bug_catcher-0.6.9}/setup.cfg +1 -1
- {t_bug_catcher-0.6.6 → t_bug_catcher-0.6.9}/setup.py +1 -1
- {t_bug_catcher-0.6.6 → t_bug_catcher-0.6.9}/t_bug_catcher/__init__.py +1 -1
- {t_bug_catcher-0.6.6 → t_bug_catcher-0.6.9}/t_bug_catcher/config.py +1 -1
- {t_bug_catcher-0.6.6 → t_bug_catcher-0.6.9}/t_bug_catcher/jira.py +23 -8
- {t_bug_catcher-0.6.6 → t_bug_catcher-0.6.9}/t_bug_catcher/utils/common.py +17 -0
- {t_bug_catcher-0.6.6 → t_bug_catcher-0.6.9}/t_bug_catcher.egg-info/PKG-INFO +2 -2
- {t_bug_catcher-0.6.6 → t_bug_catcher-0.6.9}/MANIFEST.in +0 -0
- {t_bug_catcher-0.6.6 → t_bug_catcher-0.6.9}/README.rst +0 -0
- {t_bug_catcher-0.6.6 → t_bug_catcher-0.6.9}/pyproject.toml +0 -0
- {t_bug_catcher-0.6.6 → t_bug_catcher-0.6.9}/requirements.txt +0 -0
- {t_bug_catcher-0.6.6 → t_bug_catcher-0.6.9}/t_bug_catcher/bug_catcher.py +0 -0
- {t_bug_catcher-0.6.6 → t_bug_catcher-0.6.9}/t_bug_catcher/bug_snag.py +0 -0
- {t_bug_catcher-0.6.6 → t_bug_catcher-0.6.9}/t_bug_catcher/exceptions.py +0 -0
- {t_bug_catcher-0.6.6 → t_bug_catcher-0.6.9}/t_bug_catcher/resources/whispers_config.yml +0 -0
- {t_bug_catcher-0.6.6 → t_bug_catcher-0.6.9}/t_bug_catcher/stack_saver.py +0 -0
- {t_bug_catcher-0.6.6 → t_bug_catcher-0.6.9}/t_bug_catcher/utils/__init__.py +0 -0
- {t_bug_catcher-0.6.6 → t_bug_catcher-0.6.9}/t_bug_catcher/utils/logger.py +0 -0
- {t_bug_catcher-0.6.6 → t_bug_catcher-0.6.9}/t_bug_catcher/workitems.py +0 -0
- {t_bug_catcher-0.6.6 → t_bug_catcher-0.6.9}/t_bug_catcher.egg-info/SOURCES.txt +0 -0
- {t_bug_catcher-0.6.6 → t_bug_catcher-0.6.9}/t_bug_catcher.egg-info/dependency_links.txt +0 -0
- {t_bug_catcher-0.6.6 → t_bug_catcher-0.6.9}/t_bug_catcher.egg-info/not-zip-safe +0 -0
- {t_bug_catcher-0.6.6 → t_bug_catcher-0.6.9}/t_bug_catcher.egg-info/requires.txt +0 -0
- {t_bug_catcher-0.6.6 → t_bug_catcher-0.6.9}/t_bug_catcher.egg-info/top_level.txt +0 -0
- {t_bug_catcher-0.6.6 → t_bug_catcher-0.6.9}/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.6.
|
|
29
|
+
version="0.6.9",
|
|
30
30
|
zip_safe=False,
|
|
31
31
|
install_requires=install_requirements,
|
|
32
32
|
include_package_data=True,
|
|
@@ -22,7 +22,7 @@ from retry import retry
|
|
|
22
22
|
from .config import CONFIG
|
|
23
23
|
from .exceptions import BadRequestError
|
|
24
24
|
from .utils import logger
|
|
25
|
-
from .utils.common import Encoder, get_frames, remove_holotree_id, retrieve_build_info
|
|
25
|
+
from .utils.common import Encoder, clean_nested_data, get_frames, remove_holotree_id, retrieve_build_info
|
|
26
26
|
from .workitems import variables
|
|
27
27
|
|
|
28
28
|
|
|
@@ -856,8 +856,7 @@ class Jira:
|
|
|
856
856
|
exc_traceback_info: str = (
|
|
857
857
|
f"Traceback (most recent call last):\n{''.join(traceback.format_tb(exc_traceback)[-1])}{exc_info}"
|
|
858
858
|
)
|
|
859
|
-
|
|
860
|
-
return {
|
|
859
|
+
description = {
|
|
861
860
|
"version": 1,
|
|
862
861
|
"type": "doc",
|
|
863
862
|
"content": []
|
|
@@ -873,6 +872,7 @@ class Jira:
|
|
|
873
872
|
+ (self.__metadata_markup(metadata) if metadata else [])
|
|
874
873
|
+ self.__error_markup(error_id),
|
|
875
874
|
}
|
|
875
|
+
return clean_nested_data(description)
|
|
876
876
|
|
|
877
877
|
def __create_warning_description_markup(
|
|
878
878
|
self,
|
|
@@ -1501,7 +1501,9 @@ class Jira:
|
|
|
1501
1501
|
return response
|
|
1502
1502
|
except Exception as ex:
|
|
1503
1503
|
logger.warning(f"Failed to create Jira issue due to: {type(ex)}: {ex}")
|
|
1504
|
-
self.report_internal_error(
|
|
1504
|
+
self.report_internal_error(
|
|
1505
|
+
exception=ex, metadata=variables, additional_info="Failed to report unhandled error."
|
|
1506
|
+
)
|
|
1505
1507
|
return False
|
|
1506
1508
|
|
|
1507
1509
|
def report_internal_error(self, exception: Exception, metadata: dict = None, additional_info: str = None):
|
|
@@ -1768,19 +1770,32 @@ class Jira:
|
|
|
1768
1770
|
return response[0]["accountId"]
|
|
1769
1771
|
|
|
1770
1772
|
@staticmethod
|
|
1771
|
-
def sanitize_summary(exception:
|
|
1773
|
+
def sanitize_summary(exception: Exception) -> str:
|
|
1772
1774
|
"""Remove locators from the exception.
|
|
1773
1775
|
|
|
1774
1776
|
Args:
|
|
1775
|
-
exception (
|
|
1777
|
+
exception (Exception): The exception to be cleaned.
|
|
1776
1778
|
|
|
1777
1779
|
Returns:
|
|
1778
1780
|
str: The cleaned exception string.
|
|
1779
1781
|
"""
|
|
1780
|
-
|
|
1782
|
+
try:
|
|
1783
|
+
exception_str = str(exception)
|
|
1784
|
+
except Exception as e:
|
|
1785
|
+
logger.warning(f"Failed to convert exception to string due to: {e}")
|
|
1786
|
+
try:
|
|
1787
|
+
tb_lines = traceback.format_exception(type(exception), exception, exception.__traceback__)
|
|
1788
|
+
exception_str = tb_lines[-1].strip()
|
|
1789
|
+
except Exception as e:
|
|
1790
|
+
logger.warning(f"Failed to convert exception to string due to: {e}")
|
|
1791
|
+
return exception.__class__.__name__
|
|
1792
|
+
|
|
1793
|
+
message = re.sub("<([a-z]+)(?![^>]*\/>)[^>]*>", r"<\1>", exception_str)
|
|
1781
1794
|
message = re.sub(">([^<]+)<\/", ">...</", message)
|
|
1795
|
+
|
|
1782
1796
|
if "selenium" not in exception.__class__.__name__.lower() and not isinstance(exception, AssertionError):
|
|
1783
|
-
return
|
|
1797
|
+
return message
|
|
1798
|
+
|
|
1784
1799
|
return re.sub(r"\'(.+)\'", "'...'", message)
|
|
1785
1800
|
|
|
1786
1801
|
def __create_summary(
|
|
@@ -115,6 +115,23 @@ def remove_holotree_id(path: str) -> str:
|
|
|
115
115
|
return re.sub(pattern, r"\1", path)
|
|
116
116
|
|
|
117
117
|
|
|
118
|
+
def clean_nested_data(data):
|
|
119
|
+
"""Recursively replaces None values with empty strings in nested dictionaries and lists.
|
|
120
|
+
|
|
121
|
+
Args:
|
|
122
|
+
data: Input data structure (dict, list, or other type)
|
|
123
|
+
|
|
124
|
+
Returns:
|
|
125
|
+
Cleaned data structure with None values replaced by empty strings
|
|
126
|
+
"""
|
|
127
|
+
if isinstance(data, dict):
|
|
128
|
+
return {key: clean_nested_data(value) for key, value in data.items()}
|
|
129
|
+
elif isinstance(data, (list, tuple)):
|
|
130
|
+
return [clean_nested_data(item) for item in data]
|
|
131
|
+
else:
|
|
132
|
+
return "" if data is None else data
|
|
133
|
+
|
|
134
|
+
|
|
118
135
|
def retrieve_build_info():
|
|
119
136
|
"""Logs build information."""
|
|
120
137
|
if not os.path.exists(CONFIG.BUILD_INFO_FILE):
|
|
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
|