swarm-debug 0.1.0__py3-none-any.whl
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.
- backend/__init__.py +0 -0
- backend/apps/__init__.py +0 -0
- backend/apps/debugger/__init__.py +0 -0
- backend/apps/debugger/debugger.py +83 -0
- backend/apps/health/__init__.py +0 -0
- backend/apps/health/health.py +33 -0
- backend/config/Apps.py +48 -0
- backend/config/__init__.py +0 -0
- backend/core/DEFAULTS.py +29 -0
- backend/core/Debugleton.py +87 -0
- backend/core/__init__.py +0 -0
- backend/core/data_dir.py +30 -0
- backend/core/log/__init__.py +2 -0
- backend/core/log/log_config.py +46 -0
- backend/core/log/log_mode.py +13 -0
- backend/core/models/DebugFile.py +28 -0
- backend/core/models/Directory.py +216 -0
- backend/core/models/File.py +29 -0
- backend/core/models/__init__.py +4 -0
- backend/core/models/project_scanner.py +153 -0
- backend/core/utils/__init__.py +3 -0
- backend/core/utils/color_adjuster.py +13 -0
- backend/core/utils/debug_arg_parser.py +22 -0
- backend/core/utils/path_mngr.py +15 -0
- backend/debugger_gui_build/bundle.js +102 -0
- backend/debugger_gui_build/bundle.js.LICENSE.txt +68 -0
- backend/debugger_gui_build/index.html +1 -0
- backend/main.py +40 -0
- debug.py +57 -0
- swarm_debug-0.1.0.dist-info/METADATA +237 -0
- swarm_debug-0.1.0.dist-info/RECORD +34 -0
- swarm_debug-0.1.0.dist-info/WHEEL +5 -0
- swarm_debug-0.1.0.dist-info/entry_points.txt +2 -0
- swarm_debug-0.1.0.dist-info/top_level.txt +2 -0
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import json
|
|
3
|
+
import colorsys
|
|
4
|
+
from typing import Union
|
|
5
|
+
from backend.core.models.Directory import Directory
|
|
6
|
+
from backend.core.DEFAULTS import DEFAULT_COLOR, DEFAULT_TOGGLED, DEFAULT_SET_MANUALLY, DEFAULT_SET_MANUALLY_EMOJI, TOGGLE_FILE, DEFAULT_EMOJI
|
|
7
|
+
from backend.core.models.DebugFile import DebugFile
|
|
8
|
+
from collections import OrderedDict
|
|
9
|
+
|
|
10
|
+
def merge_directories(json_dir: Directory, scanned_dir: Directory):
|
|
11
|
+
"""
|
|
12
|
+
Merges two Directory instances: one loaded from JSON (json_dir) and one built from scanning (scanned_dir).
|
|
13
|
+
The values from json_dir take precedence where attributes overlap.
|
|
14
|
+
It matches based on full directory and file structure, not just file names.
|
|
15
|
+
"""
|
|
16
|
+
# print(f"Merging JSON_DIR: {json_dir.path}\n with SCAN_DIR: {scanned_dir.path}")
|
|
17
|
+
json_abspaths, json_instances = json_dir.get_ordered_abspaths_and_instances()
|
|
18
|
+
# print(f"json_abspaths: {json_abspaths}")
|
|
19
|
+
scanned_abspaths, scanned_instances = scanned_dir.get_ordered_abspaths_and_instances()
|
|
20
|
+
# print(f"scanned_abspaths: {scanned_abspaths}")
|
|
21
|
+
|
|
22
|
+
def find_matching_in_structure(scanned_child: Union[DebugFile, Directory], json_dir: Directory):
|
|
23
|
+
assert json_dir in json_instances, f"JSON_DIR: {json_dir.path} not in json_instances"
|
|
24
|
+
assert scanned_child in scanned_instances, f"SCANNED_CHILD: {scanned_child.path} not in scanned_instances"
|
|
25
|
+
scanned_id = scanned_instances.index(scanned_child)
|
|
26
|
+
scanned_abspath = scanned_abspaths[scanned_id]
|
|
27
|
+
json_instance = None
|
|
28
|
+
try:
|
|
29
|
+
json_id = json_abspaths.index(scanned_abspath)
|
|
30
|
+
json_instance = json_instances[json_id]
|
|
31
|
+
# print(f"Match found: {scanned_child.path} == {json_instance.path}")
|
|
32
|
+
except ValueError:
|
|
33
|
+
# print(f"SCANNED_ABSPATH: {scanned_abspath} not in JSON_ABSPATHS")
|
|
34
|
+
pass
|
|
35
|
+
return json_instance
|
|
36
|
+
|
|
37
|
+
def construct_merged_dir(json_dir: Directory, scanned_dir: Directory):
|
|
38
|
+
for scanned_child in scanned_dir.children:
|
|
39
|
+
# Use the new recursive function to find the corresponding child in the JSON directory structure
|
|
40
|
+
matching_json_child = find_matching_in_structure(scanned_child, json_dir)
|
|
41
|
+
|
|
42
|
+
if isinstance(scanned_child, DebugFile) and matching_json_child:
|
|
43
|
+
scanned_child.color = matching_json_child.color
|
|
44
|
+
scanned_child.is_toggled = matching_json_child.is_toggled
|
|
45
|
+
scanned_child.set_manually = matching_json_child.set_manually
|
|
46
|
+
scanned_child.set_manually_emoji = matching_json_child.set_manually_emoji
|
|
47
|
+
scanned_child.emoji = matching_json_child.emoji
|
|
48
|
+
|
|
49
|
+
elif isinstance(scanned_child, Directory) and matching_json_child:
|
|
50
|
+
scanned_child.color = matching_json_child.color
|
|
51
|
+
scanned_child.is_toggled = matching_json_child.is_toggled
|
|
52
|
+
scanned_child.set_manually = matching_json_child.set_manually
|
|
53
|
+
scanned_child.set_manually_emoji = matching_json_child.set_manually_emoji
|
|
54
|
+
scanned_child.emoji = matching_json_child.emoji
|
|
55
|
+
|
|
56
|
+
# Recursively merge the subdirectories
|
|
57
|
+
construct_merged_dir(matching_json_child, scanned_child)
|
|
58
|
+
else:
|
|
59
|
+
scanned_child.color = DEFAULT_COLOR
|
|
60
|
+
scanned_child.is_toggled = DEFAULT_TOGGLED
|
|
61
|
+
scanned_child.set_manually = DEFAULT_SET_MANUALLY
|
|
62
|
+
scanned_child.set_manually_emoji = DEFAULT_SET_MANUALLY_EMOJI
|
|
63
|
+
scanned_child.emoji = DEFAULT_EMOJI
|
|
64
|
+
|
|
65
|
+
construct_merged_dir(json_dir, scanned_dir)
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def update_debug_toggles(save_to_file=True) -> Directory:
|
|
69
|
+
# print(f"[update_debug_toggles]: START")
|
|
70
|
+
json_loaded_dir = None
|
|
71
|
+
if os.path.exists(TOGGLE_FILE):
|
|
72
|
+
with open(TOGGLE_FILE, 'r', encoding='utf-8') as file:
|
|
73
|
+
try:
|
|
74
|
+
json_data = json.load(file)
|
|
75
|
+
json_loaded_dir = Directory("")
|
|
76
|
+
json_loaded_dir = Directory(path="",
|
|
77
|
+
color=json_data[0].get('color', DEFAULT_COLOR),
|
|
78
|
+
is_toggled=json_data[0].get('is_toggled', DEFAULT_TOGGLED),
|
|
79
|
+
set_manually=json_data[0].get('set_manually', DEFAULT_SET_MANUALLY),
|
|
80
|
+
set_manually_emoji=json_data[0].get('set_manually_emoji', DEFAULT_SET_MANUALLY_EMOJI),
|
|
81
|
+
emoji=json_data[0].get('emoji', DEFAULT_EMOJI)
|
|
82
|
+
)
|
|
83
|
+
# print(f"Root: {json_loaded_dir}")
|
|
84
|
+
# print("Json Children 1:")
|
|
85
|
+
# [print(child.path) for child in json_loaded_dir.children]
|
|
86
|
+
|
|
87
|
+
json_loaded_dir.load_from_json(json_data[0]['children']) # Assuming the root is in json_data[0]
|
|
88
|
+
# print("Json Children 2:")
|
|
89
|
+
# [print(child.path) for child in json_loaded_dir.children]
|
|
90
|
+
|
|
91
|
+
except json.JSONDecodeError:
|
|
92
|
+
ValueError("Error: JSON file could not be decoded.")
|
|
93
|
+
else:
|
|
94
|
+
print("No JSON file found")
|
|
95
|
+
# 1. Create a directory structure from the filesystem scan
|
|
96
|
+
# print("Scanning directory...")
|
|
97
|
+
scanned_dir = Directory(path="",
|
|
98
|
+
color=json_loaded_dir.color if json_loaded_dir else DEFAULT_COLOR,
|
|
99
|
+
is_toggled=json_loaded_dir.is_toggled if json_loaded_dir else DEFAULT_TOGGLED,
|
|
100
|
+
set_manually=json_loaded_dir.set_manually if json_loaded_dir else DEFAULT_SET_MANUALLY,
|
|
101
|
+
set_manually_emoji=json_loaded_dir.set_manually_emoji if json_loaded_dir else DEFAULT_SET_MANUALLY_EMOJI,
|
|
102
|
+
emoji=json_loaded_dir.emoji if json_loaded_dir else DEFAULT_EMOJI
|
|
103
|
+
)
|
|
104
|
+
# print(f"\n\nNum Children 1: {len(scanned_dir.children)}")
|
|
105
|
+
# [print(child.path) for child in scanned_dir.children]
|
|
106
|
+
scanned_dir.build_structure()
|
|
107
|
+
# print(f"\n\nNum Children 2: {len(scanned_dir.children)}")
|
|
108
|
+
# [print(child.path) for child in scanned_dir.children]
|
|
109
|
+
scanned_dir.prune_empty()
|
|
110
|
+
# print(f"\n\nNum Children 3: {len(scanned_dir.children)}")
|
|
111
|
+
# [print(child.path) for child in scanned_dir.children]
|
|
112
|
+
|
|
113
|
+
# print("1.1 Merged Dir First Child: ", scanned_dir.children[0])
|
|
114
|
+
# 4. Propagate the toggled state and color through the merged structure
|
|
115
|
+
scanned_dir.propagate_toggled_state()
|
|
116
|
+
# print(f"\n\nNum Children 4: {len(scanned_dir.children)}")
|
|
117
|
+
# [print(child.path) for child in scanned_dir.children]
|
|
118
|
+
|
|
119
|
+
# 3. Merge the two directory structures
|
|
120
|
+
if json_loaded_dir:
|
|
121
|
+
merge_directories(json_loaded_dir, scanned_dir)
|
|
122
|
+
|
|
123
|
+
# print(f"\n\nNum Children 5: {len(scanned_dir.children)}")
|
|
124
|
+
scanned_dir.propagate_color()
|
|
125
|
+
output = dir_to_output_format(scanned_dir)
|
|
126
|
+
# print(f"\n\nNum Children 6: {len(scanned_dir.children)}")
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
# 5. Write the updated structure back to the JSON file
|
|
130
|
+
if save_to_file:
|
|
131
|
+
with open(TOGGLE_FILE, 'w', encoding='utf-8') as file:
|
|
132
|
+
json.dump(output, file, ensure_ascii=False, indent=4)
|
|
133
|
+
# print(f"[update_debug_toggles]: END")
|
|
134
|
+
return scanned_dir
|
|
135
|
+
|
|
136
|
+
def dir_to_output_format(input_dir):
|
|
137
|
+
root_node = {
|
|
138
|
+
"name": "root",
|
|
139
|
+
"color": input_dir.color,
|
|
140
|
+
"is_toggled": input_dir.is_toggled,
|
|
141
|
+
"set_manually": input_dir.set_manually,
|
|
142
|
+
"set_manually_emoji": input_dir.set_manually_emoji,
|
|
143
|
+
"emoji": input_dir.emoji,
|
|
144
|
+
"children": input_dir.to_dict()["children"]
|
|
145
|
+
}
|
|
146
|
+
return [ordered(root_node)]
|
|
147
|
+
|
|
148
|
+
def ordered(obj):
|
|
149
|
+
if isinstance(obj, dict):
|
|
150
|
+
return OrderedDict((k, ordered(v)) for k, v in obj.items())
|
|
151
|
+
if isinstance(obj, list):
|
|
152
|
+
return [ordered(x) for x in obj]
|
|
153
|
+
return obj
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
|
|
2
|
+
def rgb_to_ansi(rgb):
|
|
3
|
+
return '\033[38;2;{};{};{}m'.format(*rgb)
|
|
4
|
+
|
|
5
|
+
def bold_and_italicize_text(text):
|
|
6
|
+
return f"\033[1m\033[3m{text}\033[0m"
|
|
7
|
+
|
|
8
|
+
def hex_to_rgb(hex_code):
|
|
9
|
+
# Remove the '#' symbol if it exists
|
|
10
|
+
hex_code = hex_code.lstrip('#')
|
|
11
|
+
|
|
12
|
+
# Convert the hex code to RGB
|
|
13
|
+
return tuple(int(hex_code[i:i+2], 16) for i in (0, 2, 4))
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
x = "y"
|
|
2
|
+
|
|
3
|
+
def is_fstring(arg_name):
|
|
4
|
+
if not isinstance(arg_name, str):
|
|
5
|
+
return False
|
|
6
|
+
# print(f"arg_name: {arg_name}")
|
|
7
|
+
fstring_start_values = ["f'", "f\""]
|
|
8
|
+
num_start_matches = sum(arg_name.startswith(start_value) for start_value in fstring_start_values)
|
|
9
|
+
conditions = [num_start_matches == 1]
|
|
10
|
+
return all(conditions)
|
|
11
|
+
|
|
12
|
+
def is_text(arg_value, arg_name):
|
|
13
|
+
arg_is_text = isinstance(arg_value, str) and len(arg_name) > 2 and arg_name[1:len(arg_name)-1] == arg_value and not arg_name.endswith(")")
|
|
14
|
+
if not arg_is_text:
|
|
15
|
+
arg_is_text = is_fstring(arg_name)
|
|
16
|
+
# print(f"is_text: {arg_is_text}")
|
|
17
|
+
return arg_is_text
|
|
18
|
+
|
|
19
|
+
def is_error(arg_value, arg_name):
|
|
20
|
+
arg_is_error = isinstance(arg_value, Exception) or "error" in str(arg_value).lower() or "error" in str(arg_name).lower()
|
|
21
|
+
return arg_is_error
|
|
22
|
+
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from backend.core.DEFAULTS import get_root_dir
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def get_abspath(path: str):
|
|
6
|
+
return os.path.join(get_root_dir(), path)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def get_root_rel_path(path: str):
|
|
10
|
+
root = get_root_dir()
|
|
11
|
+
assert path.startswith(root)
|
|
12
|
+
path = path[len(root):]
|
|
13
|
+
while path.startswith(os.sep):
|
|
14
|
+
path = path[1:]
|
|
15
|
+
return path
|