t-bug-catcher 0.4.1__tar.gz → 0.4.2__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.1 → t_bug_catcher-0.4.2}/PKG-INFO +1 -1
- {t_bug_catcher-0.4.1 → t_bug_catcher-0.4.2}/setup.cfg +1 -1
- {t_bug_catcher-0.4.1 → t_bug_catcher-0.4.2}/setup.py +1 -1
- {t_bug_catcher-0.4.1 → t_bug_catcher-0.4.2}/t_bug_catcher/__init__.py +1 -1
- {t_bug_catcher-0.4.1 → t_bug_catcher-0.4.2}/t_bug_catcher/config.py +2 -0
- {t_bug_catcher-0.4.1 → t_bug_catcher-0.4.2}/t_bug_catcher/stack_saver.py +10 -33
- t_bug_catcher-0.4.2/t_bug_catcher/utils/common.py +69 -0
- {t_bug_catcher-0.4.1 → t_bug_catcher-0.4.2}/t_bug_catcher.egg-info/PKG-INFO +1 -1
- t_bug_catcher-0.4.1/t_bug_catcher/utils/common.py +0 -41
- {t_bug_catcher-0.4.1 → t_bug_catcher-0.4.2}/MANIFEST.in +0 -0
- {t_bug_catcher-0.4.1 → t_bug_catcher-0.4.2}/README.rst +0 -0
- {t_bug_catcher-0.4.1 → t_bug_catcher-0.4.2}/pyproject.toml +0 -0
- {t_bug_catcher-0.4.1 → t_bug_catcher-0.4.2}/requirements.txt +0 -0
- {t_bug_catcher-0.4.1 → t_bug_catcher-0.4.2}/t_bug_catcher/bug_catcher.py +0 -0
- {t_bug_catcher-0.4.1 → t_bug_catcher-0.4.2}/t_bug_catcher/bug_snag.py +0 -0
- {t_bug_catcher-0.4.1 → t_bug_catcher-0.4.2}/t_bug_catcher/exceptions.py +0 -0
- {t_bug_catcher-0.4.1 → t_bug_catcher-0.4.2}/t_bug_catcher/jira.py +0 -0
- {t_bug_catcher-0.4.1 → t_bug_catcher-0.4.2}/t_bug_catcher/resources/whispers_config.yml +0 -0
- {t_bug_catcher-0.4.1 → t_bug_catcher-0.4.2}/t_bug_catcher/utils/__init__.py +0 -0
- {t_bug_catcher-0.4.1 → t_bug_catcher-0.4.2}/t_bug_catcher/utils/logger.py +0 -0
- {t_bug_catcher-0.4.1 → t_bug_catcher-0.4.2}/t_bug_catcher/workitems.py +0 -0
- {t_bug_catcher-0.4.1 → t_bug_catcher-0.4.2}/t_bug_catcher.egg-info/SOURCES.txt +0 -0
- {t_bug_catcher-0.4.1 → t_bug_catcher-0.4.2}/t_bug_catcher.egg-info/dependency_links.txt +0 -0
- {t_bug_catcher-0.4.1 → t_bug_catcher-0.4.2}/t_bug_catcher.egg-info/not-zip-safe +0 -0
- {t_bug_catcher-0.4.1 → t_bug_catcher-0.4.2}/t_bug_catcher.egg-info/requires.txt +0 -0
- {t_bug_catcher-0.4.1 → t_bug_catcher-0.4.2}/t_bug_catcher.egg-info/top_level.txt +0 -0
- {t_bug_catcher-0.4.1 → t_bug_catcher-0.4.2}/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.2",
|
|
30
30
|
zip_safe=False,
|
|
31
31
|
install_requires=install_requirements,
|
|
32
32
|
include_package_data=True,
|
|
@@ -17,6 +17,8 @@ class Config:
|
|
|
17
17
|
|
|
18
18
|
SUPPORT_BOARD = "AB"
|
|
19
19
|
|
|
20
|
+
KEYS_TO_REMOVE = ["credential", "password"]
|
|
21
|
+
|
|
20
22
|
RC_RUN_LINK = (
|
|
21
23
|
f"https://cloud.robocorp.com/organizations/{os.environ.get('RC_ORGANIZATION_ID')}"
|
|
22
24
|
f"/workspaces/{os.environ.get('RC_WORKSPACE_ID')}/processes"
|
|
@@ -12,7 +12,7 @@ import whispers
|
|
|
12
12
|
|
|
13
13
|
from .config import CONFIG
|
|
14
14
|
from .utils import logger
|
|
15
|
-
from .utils.common import Encoder
|
|
15
|
+
from .utils.common import Encoder, convert_keys_to_primitives
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
class StackSaver:
|
|
@@ -34,8 +34,7 @@ class StackSaver:
|
|
|
34
34
|
"""
|
|
35
35
|
return path.replace(os.getcwd(), "").strip(os.sep)
|
|
36
36
|
|
|
37
|
-
|
|
38
|
-
def serialize_frame_info(frame_info: dict) -> dict:
|
|
37
|
+
def serialize_frame_info(self, frame_info: dict) -> dict:
|
|
39
38
|
"""A static method to serialize the frame info.
|
|
40
39
|
|
|
41
40
|
Args:
|
|
@@ -44,23 +43,8 @@ class StackSaver:
|
|
|
44
43
|
Returns:
|
|
45
44
|
dict: The serialized frame info.
|
|
46
45
|
"""
|
|
47
|
-
run_locals = {}
|
|
48
|
-
run_args = {}
|
|
49
|
-
if frame_info["locals"]:
|
|
50
|
-
for key, value in frame_info["locals"].items():
|
|
51
|
-
if str(key).lower() == "credentials":
|
|
52
|
-
continue
|
|
53
|
-
if isinstance(value, dict):
|
|
54
|
-
run_locals[str(key)] = value
|
|
55
|
-
else:
|
|
56
|
-
run_locals[str(key)] = str(value)
|
|
57
|
-
for key, value in frame_info["args"].items():
|
|
58
|
-
if str(key).lower() == "credentials":
|
|
59
|
-
continue
|
|
60
|
-
if isinstance(value, dict):
|
|
61
|
-
run_args[str(key)] = value
|
|
62
|
-
else:
|
|
63
|
-
run_args[str(key)] = str(value)
|
|
46
|
+
run_locals = convert_keys_to_primitives(frame_info["locals"]) if frame_info["locals"] else {}
|
|
47
|
+
run_args = convert_keys_to_primitives(frame_info["args"]) if frame_info["args"] else {}
|
|
64
48
|
serializable_frame_info = {
|
|
65
49
|
"filename": frame_info["filename"],
|
|
66
50
|
"function_name": frame_info["function_name"],
|
|
@@ -88,7 +72,7 @@ class StackSaver:
|
|
|
88
72
|
continue
|
|
89
73
|
if isinstance(var, (ModuleType, FunctionType)):
|
|
90
74
|
continue
|
|
91
|
-
local_variables[var_name] = var
|
|
75
|
+
local_variables[str(var_name)] = var
|
|
92
76
|
return local_variables
|
|
93
77
|
|
|
94
78
|
def mask_credentials(self, file_path: str) -> None:
|
|
@@ -111,25 +95,18 @@ class StackSaver:
|
|
|
111
95
|
args = f"-c {config_path} {file_path}"
|
|
112
96
|
|
|
113
97
|
secrets = [secret for secret in whispers.secrets(args)]
|
|
114
|
-
unique_secrets = []
|
|
115
|
-
seen = set()
|
|
116
|
-
for secret in secrets:
|
|
117
|
-
item = (secret.key, secret.value, secret.line)
|
|
118
|
-
if item not in seen:
|
|
119
|
-
seen.add(item)
|
|
120
|
-
unique_secrets.append(secret)
|
|
121
98
|
|
|
122
99
|
for index, line in enumerate(filedata):
|
|
123
|
-
if not
|
|
100
|
+
if not secrets:
|
|
124
101
|
break
|
|
125
102
|
|
|
126
|
-
for secret in
|
|
103
|
+
for secret in secrets:
|
|
127
104
|
if secret.key in line and secret.value in line:
|
|
128
105
|
filedata[index] = line.replace(secret.value, secret.value[:1] + "***")
|
|
129
|
-
|
|
106
|
+
secrets.pop(secrets.index(secret))
|
|
130
107
|
break
|
|
131
108
|
|
|
132
|
-
if
|
|
109
|
+
if secrets:
|
|
133
110
|
logger.warning("Failed to mask credentials")
|
|
134
111
|
os.remove(file_path)
|
|
135
112
|
raise Exception("Failed to mask credentials")
|
|
@@ -157,7 +134,7 @@ class StackSaver:
|
|
|
157
134
|
continue
|
|
158
135
|
frames.append(frame)
|
|
159
136
|
tb = tb.tb_next
|
|
160
|
-
frames = frames[
|
|
137
|
+
frames = frames[-CONFIG.LIMITS.STACK_SCOPE :]
|
|
161
138
|
|
|
162
139
|
for frame in frames:
|
|
163
140
|
frame_info = {
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import traceback
|
|
2
|
+
from datetime import date, datetime
|
|
3
|
+
from json import JSONEncoder
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
from types import TracebackType
|
|
6
|
+
from typing import List
|
|
7
|
+
|
|
8
|
+
from ..config import CONFIG
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class Encoder(JSONEncoder):
|
|
12
|
+
"""This class is used to encode the Episode object to json."""
|
|
13
|
+
|
|
14
|
+
def default(self, o):
|
|
15
|
+
"""This method is used to encode the Episode object to json.
|
|
16
|
+
|
|
17
|
+
Args:
|
|
18
|
+
o (object): The object to be encoded.
|
|
19
|
+
|
|
20
|
+
Returns:
|
|
21
|
+
str: The json string.
|
|
22
|
+
"""
|
|
23
|
+
try:
|
|
24
|
+
if hasattr(o, "__dict__"):
|
|
25
|
+
keys_to_remove = [
|
|
26
|
+
key for key in o.__dict__.keys() if any(s in str(key).lower() for s in CONFIG.KEYS_TO_REMOVE)
|
|
27
|
+
]
|
|
28
|
+
for key in keys_to_remove:
|
|
29
|
+
del o.__dict__[key]
|
|
30
|
+
return {str(key): str(value) for key, value in o.__dict__.items()}
|
|
31
|
+
if isinstance(o, (datetime, date)):
|
|
32
|
+
return o.isoformat()
|
|
33
|
+
if isinstance(o, Path):
|
|
34
|
+
return str(o)
|
|
35
|
+
return super().default(self, o)
|
|
36
|
+
except TypeError:
|
|
37
|
+
return str(o)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def get_frames(exc_traceback: TracebackType) -> List:
|
|
41
|
+
"""Get the frames of the exception.
|
|
42
|
+
|
|
43
|
+
Args:
|
|
44
|
+
exc_traceback (TracebackType): The traceback of the exception.
|
|
45
|
+
|
|
46
|
+
Returns:
|
|
47
|
+
List: The frames of the exception.
|
|
48
|
+
"""
|
|
49
|
+
return [
|
|
50
|
+
frame for frame in traceback.extract_tb(exc_traceback) if "site-packages" not in str(frame.filename).lower()
|
|
51
|
+
]
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def convert_keys_to_primitives(data: dict) -> dict:
|
|
55
|
+
"""A function that recursively converts keys in a nested dictionary to primitives.
|
|
56
|
+
|
|
57
|
+
Args:
|
|
58
|
+
data (dict): The input dictionary to convert keys.
|
|
59
|
+
|
|
60
|
+
Returns:
|
|
61
|
+
dict: A new dictionary with keys converted to strings.
|
|
62
|
+
"""
|
|
63
|
+
new_dict = {}
|
|
64
|
+
for key, value in data.items():
|
|
65
|
+
if isinstance(value, dict):
|
|
66
|
+
new_dict[str(key)] = convert_keys_to_primitives(value)
|
|
67
|
+
else:
|
|
68
|
+
new_dict[str(key)] = value
|
|
69
|
+
return new_dict
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import traceback
|
|
2
|
-
from datetime import date, datetime
|
|
3
|
-
from json import JSONEncoder
|
|
4
|
-
from pathlib import Path
|
|
5
|
-
from types import TracebackType
|
|
6
|
-
from typing import List
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
class Encoder(JSONEncoder):
|
|
10
|
-
"""This class is used to encode the Episode object to json."""
|
|
11
|
-
|
|
12
|
-
def default(self, o):
|
|
13
|
-
"""This method is used to encode the Episode object to json.
|
|
14
|
-
|
|
15
|
-
Args:
|
|
16
|
-
o (object): The object to be encoded.
|
|
17
|
-
|
|
18
|
-
Returns:
|
|
19
|
-
str: The json string.
|
|
20
|
-
"""
|
|
21
|
-
if hasattr(o, "__dict__"):
|
|
22
|
-
return o.__dict__
|
|
23
|
-
if isinstance(o, (datetime, date)):
|
|
24
|
-
return o.isoformat()
|
|
25
|
-
if isinstance(o, Path):
|
|
26
|
-
return str(o)
|
|
27
|
-
return JSONEncoder.default(self, o)
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
def get_frames(exc_traceback: TracebackType) -> List:
|
|
31
|
-
"""Get the frames of the exception.
|
|
32
|
-
|
|
33
|
-
Args:
|
|
34
|
-
exc_traceback (TracebackType): The traceback of the exception.
|
|
35
|
-
|
|
36
|
-
Returns:
|
|
37
|
-
List: The frames of the exception.
|
|
38
|
-
"""
|
|
39
|
-
return [
|
|
40
|
-
frame for frame in traceback.extract_tb(exc_traceback) if "site-packages" not in str(frame.filename).lower()
|
|
41
|
-
]
|
|
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
|