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.
Files changed (27) hide show
  1. {t_bug_catcher-0.4.1 → t_bug_catcher-0.4.2}/PKG-INFO +1 -1
  2. {t_bug_catcher-0.4.1 → t_bug_catcher-0.4.2}/setup.cfg +1 -1
  3. {t_bug_catcher-0.4.1 → t_bug_catcher-0.4.2}/setup.py +1 -1
  4. {t_bug_catcher-0.4.1 → t_bug_catcher-0.4.2}/t_bug_catcher/__init__.py +1 -1
  5. {t_bug_catcher-0.4.1 → t_bug_catcher-0.4.2}/t_bug_catcher/config.py +2 -0
  6. {t_bug_catcher-0.4.1 → t_bug_catcher-0.4.2}/t_bug_catcher/stack_saver.py +10 -33
  7. t_bug_catcher-0.4.2/t_bug_catcher/utils/common.py +69 -0
  8. {t_bug_catcher-0.4.1 → t_bug_catcher-0.4.2}/t_bug_catcher.egg-info/PKG-INFO +1 -1
  9. t_bug_catcher-0.4.1/t_bug_catcher/utils/common.py +0 -41
  10. {t_bug_catcher-0.4.1 → t_bug_catcher-0.4.2}/MANIFEST.in +0 -0
  11. {t_bug_catcher-0.4.1 → t_bug_catcher-0.4.2}/README.rst +0 -0
  12. {t_bug_catcher-0.4.1 → t_bug_catcher-0.4.2}/pyproject.toml +0 -0
  13. {t_bug_catcher-0.4.1 → t_bug_catcher-0.4.2}/requirements.txt +0 -0
  14. {t_bug_catcher-0.4.1 → t_bug_catcher-0.4.2}/t_bug_catcher/bug_catcher.py +0 -0
  15. {t_bug_catcher-0.4.1 → t_bug_catcher-0.4.2}/t_bug_catcher/bug_snag.py +0 -0
  16. {t_bug_catcher-0.4.1 → t_bug_catcher-0.4.2}/t_bug_catcher/exceptions.py +0 -0
  17. {t_bug_catcher-0.4.1 → t_bug_catcher-0.4.2}/t_bug_catcher/jira.py +0 -0
  18. {t_bug_catcher-0.4.1 → t_bug_catcher-0.4.2}/t_bug_catcher/resources/whispers_config.yml +0 -0
  19. {t_bug_catcher-0.4.1 → t_bug_catcher-0.4.2}/t_bug_catcher/utils/__init__.py +0 -0
  20. {t_bug_catcher-0.4.1 → t_bug_catcher-0.4.2}/t_bug_catcher/utils/logger.py +0 -0
  21. {t_bug_catcher-0.4.1 → t_bug_catcher-0.4.2}/t_bug_catcher/workitems.py +0 -0
  22. {t_bug_catcher-0.4.1 → t_bug_catcher-0.4.2}/t_bug_catcher.egg-info/SOURCES.txt +0 -0
  23. {t_bug_catcher-0.4.1 → t_bug_catcher-0.4.2}/t_bug_catcher.egg-info/dependency_links.txt +0 -0
  24. {t_bug_catcher-0.4.1 → t_bug_catcher-0.4.2}/t_bug_catcher.egg-info/not-zip-safe +0 -0
  25. {t_bug_catcher-0.4.1 → t_bug_catcher-0.4.2}/t_bug_catcher.egg-info/requires.txt +0 -0
  26. {t_bug_catcher-0.4.1 → t_bug_catcher-0.4.2}/t_bug_catcher.egg-info/top_level.txt +0 -0
  27. {t_bug_catcher-0.4.1 → t_bug_catcher-0.4.2}/tests/test_t_bug_catcher.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: t_bug_catcher
3
- Version: 0.4.1
3
+ Version: 0.4.2
4
4
  Summary: Bug catcher
5
5
  Home-page: https://www.thoughtful.ai/
6
6
  Author: Thoughtful
@@ -1,5 +1,5 @@
1
1
  [bumpversion]
2
- current_version = 0.4.1
2
+ current_version = 0.4.2
3
3
  commit = True
4
4
  tag = False
5
5
 
@@ -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.1",
29
+ version="0.4.2",
30
30
  zip_safe=False,
31
31
  install_requires=install_requirements,
32
32
  include_package_data=True,
@@ -3,7 +3,7 @@
3
3
  __author__ = """Thoughtful"""
4
4
  __email__ = "support@thoughtful.ai"
5
5
  # fmt: off
6
- __version__ = '0.4.1'
6
+ __version__ = '0.4.2'
7
7
  # fmt: on
8
8
 
9
9
  from .bug_catcher import (
@@ -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
- @staticmethod
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 unique_secrets:
100
+ if not secrets:
124
101
  break
125
102
 
126
- for secret in unique_secrets:
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
- unique_secrets.pop(unique_secrets.index(secret))
106
+ secrets.pop(secrets.index(secret))
130
107
  break
131
108
 
132
- if unique_secrets:
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[: CONFIG.LIMITS.STACK_SCOPE]
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,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: t_bug_catcher
3
- Version: 0.4.1
3
+ Version: 0.4.2
4
4
  Summary: Bug catcher
5
5
  Home-page: https://www.thoughtful.ai/
6
6
  Author: Thoughtful
@@ -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