movoid-debug 1.2.0__tar.gz → 1.2.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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: movoid_debug
3
- Version: 1.2.0
3
+ Version: 1.2.2
4
4
  Home-page:
5
5
  Author: movoid
6
6
  Author-email: bobrobotsun@163.com
@@ -8,3 +8,4 @@
8
8
  """
9
9
  from .simple_debug import DEBUG, SimpleDebug
10
10
  from .simple_hot_pause import HOT_PAUSE, SimpleHotPause
11
+ from .flow import FLOW, Flow, FlowFunction, debug_function, debug_class_include, debug_class_exclude
@@ -6,6 +6,4 @@
6
6
  # Time : 2024/6/2 21:50
7
7
  # Description :
8
8
  """
9
-
10
- if __name__ == '__main__':
11
- pass
9
+ from .flow import FLOW, Flow, FlowFunction, debug_function, debug_class_include, debug_class_exclude
@@ -9,9 +9,9 @@
9
9
  import sys
10
10
  import traceback
11
11
 
12
- from movoid_function import Function, wraps
12
+ from movoid_function import Function, wraps, analyse_args_value_from_function
13
13
 
14
- from ..simple_ui import MainApp
14
+ from ..simple_ui import MainApp, MainWindow
15
15
 
16
16
 
17
17
  class Flow:
@@ -22,11 +22,12 @@ class Flow:
22
22
  self.raise_error = 0
23
23
  self.error_type = 0
24
24
  self.check_error_type()
25
+ self.app = None
25
26
 
26
27
  def check_error_type(self):
27
28
  for i in sys.argv:
28
- if i.startswith('_debug='):
29
- temp = i[7:]
29
+ if i.startswith('__debug='):
30
+ temp = i[8:]
30
31
  if temp == '1':
31
32
  self.error_type = 1
32
33
 
@@ -53,8 +54,10 @@ class Flow:
53
54
  self.test = False
54
55
 
55
56
  def when_error_debug(self):
56
- debug_app = MainApp(self)
57
- debug_app.exec()
57
+ if self.app is None:
58
+ self.app = MainApp()
59
+ self.app.main = MainWindow(self)
60
+ self.app.exec()
58
61
 
59
62
  def when_error_cmd(self):
60
63
  print('错误发生:')
@@ -85,6 +88,21 @@ class BasicFunction:
85
88
  self.error = None
86
89
  self.traceback = ''
87
90
  self.error_mode = {}
91
+ self.end = False
92
+ self.has_return = False
93
+ self.re_value = None
94
+
95
+ def result(self, simple=False, tostring=False):
96
+ if self.has_return:
97
+ re_value = str(self.re_value) if tostring else self.re_value
98
+ elif self.traceback:
99
+ if simple:
100
+ re_value = f'{type(self.error).__name__}:{self.error}' if tostring else self.error
101
+ else:
102
+ re_value = self.traceback
103
+ else:
104
+ re_value = 'not done yet'
105
+ return re_value
88
106
 
89
107
  def add_son(self, son, son_type='function'):
90
108
  """
@@ -156,12 +174,10 @@ class FlowFunction(BasicFunction):
156
174
  self.include_error = include
157
175
  self.args = []
158
176
  self.kwargs = {}
159
- self.has_return = False
160
- self.re_value = None
177
+ self.kwarg_value = {}
161
178
  self.flow = flow
162
179
  self.parent = flow.current_function
163
180
  self.raise_error = False
164
- self.end = False
165
181
  self.debug_mode = {
166
182
  0: True,
167
183
  1: True
@@ -169,13 +185,13 @@ class FlowFunction(BasicFunction):
169
185
 
170
186
  def __call__(self, *args, **kwargs):
171
187
  if self.flow.test:
172
- test = TestFunction(self.func, self.flow)
173
- self.son.append([test, 'function'])
188
+ test = TestFunction(self.func, self.flow, self)
174
189
  test(*args, **kwargs)
175
190
  else:
176
191
  try:
177
192
  self.args = args
178
193
  self.kwargs = kwargs
194
+ self.kwarg_value = analyse_args_value_from_function(self.func, *args, **kwargs)
179
195
  self.flow.set_current_function(self)
180
196
  re_value = self.func(*self.args, **self.kwargs)
181
197
  except self.exclude_error as err:
@@ -206,6 +222,7 @@ class FlowFunction(BasicFunction):
206
222
  self.re_value = re_value
207
223
  return self.re_value
208
224
  finally:
225
+ self.end = True
209
226
  self.flow.current_function_end()
210
227
 
211
228
  def self_text(self, indent=0):
@@ -224,34 +241,38 @@ class FlowFunction(BasicFunction):
224
241
  class TestFunction(BasicFunction):
225
242
  func_type = 'test'
226
243
 
227
- def __init__(self, func, flow):
244
+ def __init__(self, func, flow, ori):
228
245
  super().__init__()
229
246
  self.func = func
230
247
  self.flow = flow
248
+ self.ori = ori
231
249
  self.parent = self.flow.current_function
232
- self.has_return = False
233
- self.re_value = None
234
- self.end = False
235
250
 
236
251
  def __call__(self, *args, **kwargs):
237
- try:
238
- self.args = args
239
- self.kwargs = kwargs
240
- re_value = self.func(*args, **kwargs)
241
- except TestError as err:
242
- if isinstance(self.parent, TestFunction):
243
- raise err
244
- except Exception as err:
245
- self.err = err
246
- self.traceback = traceback.format_exc()
247
- if isinstance(self.parent, TestFunction):
248
- raise TestError
252
+ if self.end:
253
+ self.ori(*args, **kwargs)
249
254
  else:
250
- self.has_return = True
251
- self.re_value = re_value
252
- return self.re_value
253
- finally:
254
- self.end = True
255
+ try:
256
+ self.args = args
257
+ self.kwargs = kwargs
258
+ self.kwarg_value = analyse_args_value_from_function(self.func, *args, **kwargs)
259
+ self.flow.set_current_function(self)
260
+ re_value = self.func(*args, **kwargs)
261
+ except TestError as err:
262
+ if isinstance(self.parent, TestFunction):
263
+ raise err
264
+ except Exception as err:
265
+ self.error = err
266
+ self.traceback = traceback.format_exc()
267
+ if isinstance(self.parent, TestFunction):
268
+ raise TestError
269
+ else:
270
+ self.has_return = True
271
+ self.re_value = re_value
272
+ return self.re_value
273
+ finally:
274
+ self.end = True
275
+ self.flow.current_function_end()
255
276
 
256
277
  def self_text(self, indent=0):
257
278
  indent_str = '\t' * indent
@@ -274,3 +295,47 @@ class TestError(Exception):
274
295
 
275
296
 
276
297
  FLOW = Flow()
298
+
299
+
300
+ def debug_function(func):
301
+ @wraps(func)
302
+ def wrapper(*args, **kwargs):
303
+ temp = FlowFunction(func, FLOW)
304
+ temp(*args, **kwargs)
305
+
306
+ return wrapper
307
+
308
+
309
+ def debug_class_include(name_list):
310
+ """
311
+ 作为装饰器使用,传入一个列表,列表内所有函数的名称均会被增加debug
312
+ """
313
+
314
+ def dec(cls):
315
+ for name in name_list:
316
+ if hasattr(cls, name):
317
+ func = getattr(cls, name)
318
+ if callable(func):
319
+ setattr(cls, name, debug_function(func))
320
+ return cls
321
+
322
+ return dec
323
+
324
+
325
+ def debug_class_exclude(name_list=None):
326
+ """
327
+ 作为装饰器使用,传入一个列表,除了__开头和列表里的名称,所有的函数均会被增加debug
328
+ 不输入的情况下,会包含所有的函数
329
+ """
330
+
331
+ name_list = [] if name_list is None else list(name_list)
332
+
333
+ def dec(cls):
334
+ for name in dir(cls):
335
+ if not name.startswith('__') and name not in name_list:
336
+ func = getattr(cls, name)
337
+ if callable(func):
338
+ setattr(cls, name, debug_function(func))
339
+ return cls
340
+
341
+ return dec
@@ -12,10 +12,11 @@ from .main_window import MainWindow
12
12
 
13
13
 
14
14
  class MainApp:
15
- def __init__(self, flow):
15
+ def __init__(self):
16
16
  self.app = QApplication()
17
- self.main = MainWindow(flow)
18
17
 
19
18
  def exec(self):
20
19
  return self.app.exec()
21
20
 
21
+ def quit(self):
22
+ return self.app.quit()
@@ -0,0 +1,246 @@
1
+ #! /usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """
4
+ # File : main_window
5
+ # Author : Sun YiFan-Movoid
6
+ # Time : 2024/6/2 21:48
7
+ # Description :
8
+ """
9
+ from PySide6.QtWidgets import QMainWindow, QApplication, QWidget, QGridLayout, QTreeWidget, QTextEdit, QHBoxLayout, QVBoxLayout, QPushButton, QTreeWidgetItem
10
+ from .value_set_window import ValueSetWindow
11
+
12
+
13
+ class MainWindow(QMainWindow):
14
+ def __init__(self, flow):
15
+ super().__init__()
16
+ self.flow = flow
17
+ self.init_ui()
18
+ self.show()
19
+ self.refresh_ui()
20
+
21
+ def init_ui(self):
22
+ screen_rect = QApplication.primaryScreen().geometry()
23
+ self.setGeometry(int(screen_rect.width() * 0.2), int(screen_rect.height() * 0.2), int(screen_rect.width() * 0.6), int(screen_rect.height() * 0.6))
24
+ main_table = QWidget(self)
25
+ self.setCentralWidget(main_table)
26
+ main_gird = QGridLayout(main_table)
27
+ main_table.setLayout(main_gird)
28
+ main_gird.setColumnStretch(0, 4)
29
+ main_gird.setColumnStretch(1, 2)
30
+ main_gird.setColumnStretch(2, 3)
31
+ main_gird.setColumnStretch(3, 1)
32
+ main_gird.setRowStretch(0, 1)
33
+ main_gird.setRowStretch(1, 2)
34
+
35
+ flow_tree = QTreeWidget(main_table)
36
+ flow_tree.setObjectName('flow_tree')
37
+ main_gird.addWidget(flow_tree, 0, 0, 2, 1)
38
+ flow_tree.setHeaderLabels(['type', 'func', 'args', 'kwargs', 'status'])
39
+ flow_tree.itemClicked.connect(self.click_flow_refresh_ui)
40
+
41
+ print_text = QTextEdit(main_table)
42
+ print_text.setObjectName('print_text')
43
+ main_gird.addWidget(print_text, 0, 1)
44
+
45
+ current_text = QTextEdit(main_table)
46
+ current_text.setObjectName('current_text')
47
+ main_gird.addWidget(current_text, 1, 1, 2, 1)
48
+
49
+ arg_tree = QTreeWidget(main_table)
50
+ arg_tree.setObjectName('arg_tree')
51
+ main_gird.addWidget(arg_tree, 0, 2, 1, 1)
52
+ arg_tree.setHeaderLabels(['arg', 'name', 'type', 'value'])
53
+ arg_tree.itemDoubleClicked.connect(lambda: self.change_arg_tree_value())
54
+
55
+ global_tree = QTreeWidget(main_table)
56
+ global_tree.setObjectName('global_tree')
57
+ main_gird.addWidget(global_tree, 1, 2, 2, 1)
58
+ global_tree.setHeaderLabels(['key', 'type', 'value'])
59
+ global_tree.itemExpanded.connect(self.expand_global_tree_to_show_dir)
60
+
61
+ run_widget = QWidget(main_table)
62
+ end_widget = QWidget(main_table)
63
+ main_gird.addWidget(run_widget, 0, 3)
64
+ main_gird.addWidget(end_widget, 4, 0, 1, 3)
65
+ run_grid = QVBoxLayout(run_widget)
66
+ run_widget.setLayout(run_grid)
67
+ end_grid = QHBoxLayout(end_widget)
68
+ end_widget.setLayout(end_grid)
69
+
70
+ run_test_button = QPushButton('测试', main_table)
71
+ run_test_button.setObjectName('run_test_button')
72
+ run_grid.addWidget(run_test_button)
73
+ run_test_button.clicked.connect(self.run_test)
74
+ run_grid.addStretch(1)
75
+
76
+ run_continue_button = QPushButton('忽略错误并continue', main_table)
77
+ run_continue_button.setObjectName('run_continue_button')
78
+ run_grid.addWidget(run_continue_button)
79
+ run_continue_button.clicked.connect(self.run_continue)
80
+ run_grid.addStretch(1)
81
+
82
+ run_raise_button = QPushButton('忽略错误并raise error', main_table)
83
+ run_raise_button.setObjectName('run_raise_button')
84
+ run_grid.addWidget(run_raise_button)
85
+ run_raise_button.clicked.connect(self.run_raise)
86
+
87
+ run_grid.addStretch(10)
88
+
89
+ def refresh_ui(self):
90
+ self.refresh_flow_tree()
91
+ self.refresh_global_tree()
92
+
93
+ def refresh_flow_tree(self):
94
+ flow_tree: QTreeWidget = self.findChild(QTreeWidget, 'flow_tree')
95
+ print_text: QTextEdit = self.findChild(QTextEdit, 'print_text')
96
+ flow_tree.clear()
97
+ self.refresh_flow_tree_item(flow_tree, self.flow.main)
98
+ current_function = self.flow.current_function
99
+ print_text.setText(str(current_function.result(tostring=True)))
100
+ flow_tree.expandAll()
101
+
102
+ def refresh_flow_tree_item(self, top_item, flow):
103
+ arg_tree: QTreeWidget = self.findChild(QTreeWidget, 'arg_tree')
104
+ select_flow = getattr(arg_tree, 'flow', None)
105
+ for i in flow.son:
106
+ if i[1] == 'function':
107
+ child = QTreeWidgetItem(top_item)
108
+ child.setText(0, i[0].func_type)
109
+ child.setText(1, i[0].func.__name__)
110
+ child.setText(2, str(i[0].args))
111
+ child.setText(3, str(i[0].kwargs))
112
+ child.setText(4, str(i[0].result(True, tostring=True)))
113
+ setattr(child, '__flow', i[0])
114
+ self.refresh_flow_tree_item(child, i[0])
115
+ if i[0] == select_flow:
116
+ self.findChild(QTreeWidget, 'flow_tree').setCurrentItem(child)
117
+ else:
118
+ child = QTreeWidgetItem(top_item)
119
+ child.setText(0, 'log')
120
+ child.setText(1, str(i[0]))
121
+
122
+ def click_flow_refresh_ui(self, q):
123
+ flow_tree: QTreeWidget = self.findChild(QTreeWidget, 'flow_tree')
124
+ current_text: QTextEdit = self.findChild(QTextEdit, 'current_text')
125
+ arg_tree: QTreeWidget = self.findChild(QTreeWidget, 'arg_tree')
126
+ arg_tree.clear()
127
+ current_item = flow_tree.currentItem()
128
+ current_flow = getattr(current_item, '__flow')
129
+ current_text.setText(str(current_flow.result(tostring=True)))
130
+ self.refresh_arg_tree(current_flow)
131
+
132
+ def refresh_arg_tree(self, flow, kwarg_value=None):
133
+ kwarg_value = flow.kwarg_value if kwarg_value is None else kwarg_value
134
+ arg_tree: QTreeWidget = self.findChild(QTreeWidget, 'arg_tree')
135
+ setattr(arg_tree, 'flow', flow)
136
+ setattr(arg_tree, 'kwarg_value', kwarg_value)
137
+ arg_tree.clear()
138
+ for k, v in kwarg_value['arg'].items():
139
+ temp = QTreeWidgetItem(arg_tree)
140
+ temp.setText(0, 'arg')
141
+ temp.setText(1, str(k))
142
+ temp.setText(2, type(v).__name__)
143
+ temp.setText(3, str(v))
144
+ setattr(temp, 'kwarg_value', ['arg', k, v])
145
+ temp.setExpanded(True)
146
+ if 'args' in kwarg_value:
147
+ args_name = list(kwarg_value['args'].keys())[0]
148
+ args_list = kwarg_value['args'][args_name]
149
+ for k, v in enumerate(args_list):
150
+ temp = QTreeWidgetItem(arg_tree)
151
+ temp.setText(0, 'args')
152
+ temp.setText(1, f'{args_name}[{k}]')
153
+ temp.setText(2, type(v).__name__)
154
+ temp.setText(3, str(v))
155
+ setattr(temp, 'kwarg_value', ['args', args_name, k, v])
156
+ for k, v in kwarg_value['kwarg'].items():
157
+ temp = QTreeWidgetItem(arg_tree)
158
+ temp.setText(0, 'kwarg')
159
+ temp.setText(1, str(k))
160
+ temp.setText(2, type(v).__name__)
161
+ temp.setText(3, str(v))
162
+ setattr(temp, 'kwarg_value', ['kwarg', k, v])
163
+ if 'kwargs' in kwarg_value:
164
+ kwargs_name = list(kwarg_value['kwargs'].keys())[0]
165
+ kwargs_dict = kwarg_value['kwargs'][kwargs_name]
166
+ for k, v in kwargs_dict.items():
167
+ temp = QTreeWidgetItem(arg_tree)
168
+ temp.setText(0, 'kwargs')
169
+ temp.setText(1, f'{kwargs_name}[{k}]')
170
+ temp.setText(2, type(v).__name__)
171
+ temp.setText(3, str(v))
172
+ setattr(temp, 'kwarg_value', ['kwargs', kwargs_name, k, v])
173
+
174
+ def refresh_global_tree(self):
175
+ global_value = globals()
176
+ global_tree: QTreeWidget = self.findChild(QTreeWidget, 'global_tree')
177
+ for k, v in global_value.items():
178
+ if not k.startswith('__'):
179
+ temp = QTreeWidgetItem(global_tree)
180
+ temp.setText(0, k)
181
+ temp.setText(1, type(v).__name__)
182
+ temp.setText(2, str(v))
183
+ setattr(temp, '__value', v)
184
+ self.empty_tree_item_child(temp)
185
+
186
+ def run_test(self, q):
187
+ arg_tree: QTreeWidget = self.findChild(QTreeWidget, 'arg_tree')
188
+ if hasattr(arg_tree, 'flow'):
189
+ flow = getattr(arg_tree, 'flow')
190
+ kwarg_value = getattr(arg_tree, 'kwarg_value')
191
+ args = [_v for _k, _v in kwarg_value['arg'].items()]
192
+ if 'args' in kwarg_value:
193
+ args += [*list(kwarg_value['args'].values())[0]]
194
+ kwargs = {_k: _v for _k, _v in kwarg_value['kwarg'].items()}
195
+ if 'kwargs' in kwarg_value:
196
+ for k, v in list(kwarg_value['kwargs'].values())[0].items():
197
+ kwargs[k] = v
198
+ flow(*args, **kwargs)
199
+ self.refresh_ui()
200
+
201
+ def run_continue(self, q):
202
+ self.close()
203
+
204
+ def run_raise(self, q):
205
+ self.flow.raise_error = -1
206
+ self.close()
207
+
208
+ def change_arg_tree_value(self):
209
+ arg_tree: QTreeWidget = self.findChild(QTreeWidget, 'arg_tree')
210
+ flow = getattr(arg_tree, 'flow')
211
+ kwarg_value = getattr(arg_tree, 'kwarg_value')
212
+ current_item = arg_tree.currentItem()
213
+ current_value = getattr(current_item, 'kwarg_value')
214
+ new_value = ValueSetWindow.get_value(current_value[-1])
215
+ if new_value != current_value[-1]:
216
+ temp = kwarg_value
217
+ for i in current_value[:-2]:
218
+ temp = temp[i]
219
+ temp[current_value[-2]] = new_value
220
+ self.refresh_arg_tree(flow, kwarg_value)
221
+
222
+ def empty_tree_item_child(self, item):
223
+ value = getattr(item, '__value')
224
+ if type(value) in (int, float, bool, str, list, dict) or value is None:
225
+ setattr(item, '__expand', False)
226
+ else:
227
+ temp = QTreeWidgetItem(item)
228
+ setattr(temp, '__delete', True)
229
+
230
+ def expand_global_tree_to_show_dir(self, item: QTreeWidgetItem):
231
+ if getattr(item, '__expand', True):
232
+ for i in range(item.childCount() - 1, -1, -1):
233
+ tar_item = item.child(i)
234
+ if getattr(tar_item, '__delete', False):
235
+ item.removeChild(tar_item)
236
+ value = getattr(item, '__value')
237
+ for k in dir(value):
238
+ if not k.startswith('__'):
239
+ v = getattr(value, k)
240
+ if not callable(v):
241
+ temp = QTreeWidgetItem(item)
242
+ temp.setText(0, k)
243
+ temp.setText(1, type(v).__name__)
244
+ temp.setText(2, str(v))
245
+ setattr(temp, '__value', v)
246
+ self.empty_tree_item_child(temp)
@@ -0,0 +1,292 @@
1
+ #! /usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """
4
+ # File : value_set_window
5
+ # Author : Sun YiFan-Movoid
6
+ # Time : 2024/6/9 23:13
7
+ # Description :
8
+ """
9
+ import inspect
10
+ import traceback
11
+
12
+ from PySide6.QtWidgets import QWidget, QGridLayout, QApplication, QRadioButton, QErrorMessage, QVBoxLayout, QTextEdit, QTreeWidget, QHBoxLayout, QPushButton, QMessageBox, QDialog, QTreeWidgetItem
13
+
14
+
15
+ class ValueSetWindow(QDialog):
16
+ def __init__(self, ori_value):
17
+ super().__init__()
18
+ self.ori_value = ori_value
19
+ self.get_value = lambda: ''
20
+ self.re_value = self.ori_value
21
+ self.args = []
22
+ self.init_ui()
23
+ self.init_ori_value()
24
+
25
+ def init_ui(self):
26
+ screen_rect = QApplication.primaryScreen().geometry()
27
+ self.setGeometry(int(screen_rect.width() * 0.3), int(screen_rect.height() * 0.3), int(screen_rect.width() * 0.4), int(screen_rect.height() * 0.4))
28
+ main_grid = QGridLayout(self)
29
+ main_grid.setObjectName('main_grid')
30
+ self.setLayout(main_grid)
31
+ main_grid.setColumnStretch(0, 1)
32
+ main_grid.setColumnStretch(1, 4)
33
+ main_grid.setRowStretch(0, 4)
34
+ main_grid.setRowStretch(1, 1)
35
+
36
+ input_widget = QWidget(self)
37
+ main_grid.addWidget(input_widget, 0, 1)
38
+ input_grid = QGridLayout(input_widget)
39
+ input_widget.setLayout(input_grid)
40
+ input_text = QTextEdit(input_widget)
41
+ input_text.setObjectName('input_text')
42
+ input_grid.addWidget(input_text, 0, 0)
43
+ arg_tree = QTreeWidget(input_widget)
44
+ arg_tree.setObjectName('arg_tree')
45
+ arg_tree.setHeaderLabels(['from', 'name', 'type', 'value'])
46
+ input_grid.addWidget(arg_tree, 0, 1)
47
+ arg_tree.itemExpanded.connect(self.expand_object_to_show_dir)
48
+
49
+ type_widget = QWidget(self)
50
+ main_grid.addWidget(type_widget, 0, 0)
51
+ type_grid = QVBoxLayout(type_widget)
52
+ type_widget.setLayout(type_grid)
53
+
54
+ int_radio = QRadioButton(type_widget)
55
+ int_radio.setObjectName('int_radio')
56
+ type_grid.addWidget(int_radio, 0)
57
+ int_radio.setText('int')
58
+ int_radio.clicked.connect(lambda: self.radio_choose_int())
59
+
60
+ float_radio = QRadioButton(type_widget)
61
+ float_radio.setObjectName('float_radio')
62
+ type_grid.addWidget(float_radio, 1)
63
+ float_radio.setText('float')
64
+ float_radio.clicked.connect(lambda: self.radio_choose_float())
65
+
66
+ str_radio = QRadioButton(type_widget)
67
+ str_radio.setObjectName('str_radio')
68
+ type_grid.addWidget(str_radio, 0)
69
+ str_radio.setText('str')
70
+ str_radio.clicked.connect(lambda: self.radio_choose_str())
71
+
72
+ list_radio = QRadioButton(type_widget)
73
+ list_radio.setObjectName('list_radio')
74
+ type_grid.addWidget(list_radio, 0)
75
+ list_radio.setText('list')
76
+ list_radio.clicked.connect(lambda: self.radio_choose_list())
77
+
78
+ dict_radio = QRadioButton(type_widget)
79
+ dict_radio.setObjectName('dict_radio')
80
+ type_grid.addWidget(dict_radio, 0)
81
+ dict_radio.setText('dict')
82
+ dict_radio.clicked.connect(lambda: self.radio_choose_dict())
83
+
84
+ none_radio = QRadioButton(type_widget)
85
+ none_radio.setObjectName('none_radio')
86
+ type_grid.addWidget(none_radio, 0)
87
+ none_radio.setText('None')
88
+ none_radio.clicked.connect(lambda: self.radio_choose_none())
89
+
90
+ object_radio = QRadioButton(type_widget)
91
+ object_radio.setObjectName('object_radio')
92
+ type_grid.addWidget(object_radio, 0)
93
+ object_radio.setText('object')
94
+ object_radio.clicked.connect(lambda: self.radio_choose_object())
95
+
96
+ type_grid.addStretch(1)
97
+
98
+ end_widget = QWidget(self)
99
+ main_grid.addWidget(end_widget, 1, 0, 1, 2)
100
+ end_grid = QHBoxLayout(end_widget)
101
+ end_widget.setLayout(end_grid)
102
+
103
+ end_grid.addStretch(4)
104
+ end_ok = QPushButton(self)
105
+ end_ok.setText('OK')
106
+ end_grid.addWidget(end_ok)
107
+ end_ok.clicked.connect(lambda: self.end_ok())
108
+
109
+ end_grid.addStretch(1)
110
+ end_cancel = QPushButton(self)
111
+ end_cancel.setText('Cancel')
112
+ end_grid.addWidget(end_cancel)
113
+ end_cancel.clicked.connect(lambda: self.end_cancel())
114
+
115
+ def init_ori_value(self):
116
+ ori_type = type(self.ori_value)
117
+ if ori_type is int:
118
+ self.radio_choose_int(self.ori_value)
119
+ elif ori_type is float:
120
+ self.radio_choose_float(self.ori_value)
121
+ elif ori_type is str:
122
+ self.radio_choose_str(self.ori_value)
123
+ elif ori_type in (list, tuple, set):
124
+ self.radio_choose_list(self.ori_value)
125
+ elif ori_type is dict:
126
+ self.radio_choose_dict(self.ori_value)
127
+ elif self.ori_value is None:
128
+ self.radio_choose_none()
129
+ else:
130
+ self.args.append(self.ori_value)
131
+ self.radio_choose_object()
132
+
133
+ def radio_choose_int(self, init_text=None):
134
+ self.get_value = self._get_int
135
+ self.input_text_show(init_text=init_text)
136
+ radio: QRadioButton = self.findChild(QRadioButton, 'int_radio')
137
+ radio.setChecked(True)
138
+
139
+ def radio_choose_float(self, init_text=None):
140
+ self.get_value = self._get_float
141
+ self.input_text_show(init_text=init_text)
142
+ radio: QRadioButton = self.findChild(QRadioButton, 'float_radio')
143
+ radio.setChecked(True)
144
+
145
+ def radio_choose_str(self, init_text=None):
146
+ self.get_value = self._get_str
147
+ self.input_text_show(init_text=init_text)
148
+ radio: QRadioButton = self.findChild(QRadioButton, 'str_radio')
149
+ radio.setChecked(True)
150
+
151
+ def radio_choose_list(self, init_text=None):
152
+ self.get_value = self._get_list
153
+ self.input_text_show(init_text=init_text)
154
+ radio: QRadioButton = self.findChild(QRadioButton, 'list_radio')
155
+ radio.setChecked(True)
156
+
157
+ def radio_choose_dict(self, init_text=None):
158
+ self.get_value = self._get_dict
159
+ self.input_text_show(init_text=init_text)
160
+ radio: QRadioButton = self.findChild(QRadioButton, 'dict_radio')
161
+ radio.setChecked(True)
162
+
163
+ def radio_choose_none(self):
164
+ self.get_value = self._get_none
165
+ self.input_text_show('')
166
+ radio: QRadioButton = self.findChild(QRadioButton, 'none_radio')
167
+ radio.setChecked(True)
168
+
169
+ def radio_choose_object(self):
170
+ self.get_value = self._get_object
171
+ self.input_text_show('arg_tree')
172
+ radio: QRadioButton = self.findChild(QRadioButton, 'object_radio')
173
+ radio.setChecked(True)
174
+
175
+ def input_text_show(self, object_name='input_text', init_text=None):
176
+ arg_tree: QTreeWidget = self.findChild(QTreeWidget, 'arg_tree')
177
+ arg_tree.setVisible(False)
178
+ input_text: QTextEdit = self.findChild(QTextEdit, 'input_text')
179
+ input_text.setVisible(False)
180
+ if object_name == 'input_text':
181
+ input_text.setVisible(True)
182
+ input_text.clear()
183
+ if init_text:
184
+ input_text.setText(str(init_text))
185
+ elif object_name == 'arg_tree':
186
+ arg_tree.setVisible(True)
187
+ self.refresh_arg_tree()
188
+
189
+ def refresh_arg_tree(self):
190
+ arg_tree: QTreeWidget = self.findChild(QTreeWidget, 'arg_tree')
191
+ arg_tree.clear()
192
+ global_value = globals()
193
+ for i in self.args:
194
+ temp = QTreeWidgetItem(arg_tree)
195
+ temp.setText(0, 'ori')
196
+ temp.setText(2, type(i).__name__)
197
+ temp.setText(3, str(i))
198
+ setattr(temp, '__value', i)
199
+ arg_tree.setCurrentItem(temp)
200
+ self.empty_tree_item_child(temp)
201
+ for k, v in global_value.items():
202
+ if not k.startswith('__'):
203
+ temp = QTreeWidgetItem(arg_tree)
204
+ temp.setText(1, str(k))
205
+ temp.setText(2, type(v).__name__)
206
+ temp.setText(3, str(v))
207
+ setattr(temp, '__value', v)
208
+ self.empty_tree_item_child(temp)
209
+
210
+ def end_ok(self):
211
+ try:
212
+ self.re_value = self.get_value()
213
+ except Exception:
214
+ QMessageBox.critical(self, '获取值错误!', traceback.format_exc())
215
+ else:
216
+ self.done(0)
217
+
218
+ def end_cancel(self):
219
+ self.re_value = self.ori_value
220
+ self.done(1)
221
+
222
+ def _get_int(self):
223
+ input_text: QTextEdit = self.findChild(QTextEdit, 'input_text')
224
+ re_value = int(input_text.toPlainText())
225
+ return re_value
226
+
227
+ def _get_float(self):
228
+ input_text: QTextEdit = self.findChild(QTextEdit, 'input_text')
229
+ re_value = float(input_text.toPlainText())
230
+ return re_value
231
+
232
+ def _get_str(self):
233
+ input_text: QTextEdit = self.findChild(QTextEdit, 'input_text')
234
+ re_value = str(input_text.toPlainText())
235
+ return re_value
236
+
237
+ def _get_list(self):
238
+ input_text: QTextEdit = self.findChild(QTextEdit, 'input_text')
239
+ re_value = list(eval(input_text.toPlainText()))
240
+ return re_value
241
+
242
+ def _get_dict(self):
243
+ input_text: QTextEdit = self.findChild(QTextEdit, 'input_text')
244
+ re_value = dict(eval(input_text.toPlainText()))
245
+ return re_value
246
+
247
+ def _get_none(self):
248
+ return None
249
+
250
+ def _get_object(self):
251
+ arg_tree: QTreeWidget = self.findChild(QTreeWidget, 'arg_tree')
252
+ tar_arg = arg_tree.currentItem()
253
+ return getattr(tar_arg, '__value')
254
+
255
+ def get_re_value(self):
256
+ print('func', self, self.re_value)
257
+ return self.re_value
258
+
259
+ @classmethod
260
+ def get_value(cls, ori_value):
261
+ temp = ValueSetWindow(ori_value)
262
+ temp.show()
263
+ temp.exec()
264
+ return temp.re_value
265
+
266
+ def empty_tree_item_child(self, item):
267
+ value = getattr(item, '__value')
268
+ if type(value) in (int, float, bool, str, list, dict) or value is None:
269
+ setattr(item, '__expand', False)
270
+ else:
271
+ temp = QTreeWidgetItem(item)
272
+ setattr(temp, '__delete', True)
273
+ temp = QTreeWidgetItem(item)
274
+ setattr(temp, '__delete', True)
275
+
276
+ def expand_object_to_show_dir(self, item: QTreeWidgetItem):
277
+ if getattr(item, '__expand', True):
278
+ for i in range(item.childCount() - 1, -1, -1):
279
+ tar_item = item.child(i)
280
+ if getattr(tar_item, '__delete'):
281
+ item.removeChild(tar_item)
282
+ value = getattr(item, '__value')
283
+ for k in dir(value):
284
+ if not k.startswith('__'):
285
+ v = getattr(value, k)
286
+ if not callable(v):
287
+ temp = QTreeWidgetItem(item)
288
+ temp.setText(1, k)
289
+ temp.setText(2, type(v).__name__)
290
+ temp.setText(3, str(v))
291
+ setattr(temp, '__value', v)
292
+ self.empty_tree_item_child(temp)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: movoid_debug
3
- Version: 1.2.0
3
+ Version: 1.2.2
4
4
  Home-page:
5
5
  Author: movoid
6
6
  Author-email: bobrobotsun@163.com
@@ -12,4 +12,5 @@ movoid_debug.egg-info/top_level.txt
12
12
  movoid_debug/flow/__init__.py
13
13
  movoid_debug/flow/flow.py
14
14
  movoid_debug/simple_ui/__init__.py
15
- movoid_debug/simple_ui/main_window.py
15
+ movoid_debug/simple_ui/main_window.py
16
+ movoid_debug/simple_ui/value_set_window.py
@@ -5,7 +5,7 @@ with open("README.md", "r", encoding='utf-8') as fh:
5
5
 
6
6
  setup(
7
7
  name='movoid_debug',
8
- version='1.2.0',
8
+ version='1.2.2',
9
9
  packages=find_packages(),
10
10
  url='',
11
11
  license='',
@@ -1,163 +0,0 @@
1
- #! /usr/bin/env python3
2
- # -*- coding: utf-8 -*-
3
- """
4
- # File : main_window
5
- # Author : Sun YiFan-Movoid
6
- # Time : 2024/6/2 21:48
7
- # Description :
8
- """
9
- from PySide6.QtWidgets import QMainWindow, QApplication, QWidget, QGridLayout, QTreeWidget, QTextEdit, QHBoxLayout, QVBoxLayout, QPushButton, QTreeWidgetItem
10
-
11
-
12
- class MainWindow(QMainWindow):
13
- def __init__(self, flow):
14
- super().__init__()
15
- self.flow = flow
16
- self.init_ui()
17
- self.show()
18
- self.refresh_ui()
19
-
20
- def init_ui(self):
21
- screen_rect = QApplication.primaryScreen().geometry()
22
- self.setGeometry(int(screen_rect.width() * 0.2), int(screen_rect.height() * 0.2), int(screen_rect.width() * 0.6), int(screen_rect.height() * 0.6))
23
- main_table = QWidget(self)
24
- self.setCentralWidget(main_table)
25
- main_gird = QGridLayout(main_table)
26
- main_table.setLayout(main_gird)
27
- main_gird.setColumnStretch(0, 4)
28
- main_gird.setColumnStretch(1, 2)
29
- main_gird.setColumnStretch(2, 1)
30
-
31
- flow_tree = QTreeWidget(main_table)
32
- flow_tree.setObjectName('flow_tree')
33
- main_gird.addWidget(flow_tree, 0, 0, 2, 1)
34
- flow_tree.setHeaderLabels(['type', 'func', 'args', 'kwargs', 'status'])
35
- flow_tree.itemClicked.connect(self.refresh_current_text)
36
-
37
- print_text = QTextEdit(main_table)
38
- print_text.setObjectName('print_text')
39
- main_gird.addWidget(print_text, 0, 1)
40
-
41
- current_text = QTextEdit(main_table)
42
- current_text.setObjectName('current_text')
43
- main_gird.addWidget(current_text, 1, 1)
44
-
45
- run_widget = QWidget(main_table)
46
- end_widget = QWidget(main_table)
47
- main_gird.addWidget(run_widget, 0, 3)
48
- main_gird.addWidget(end_widget, 4, 0, 1, 3)
49
- run_grid = QVBoxLayout(run_widget)
50
- run_widget.setLayout(run_grid)
51
- end_grid = QHBoxLayout(end_widget)
52
- end_widget.setLayout(end_grid)
53
-
54
- run_test_button = QPushButton('测试', main_table)
55
- run_test_button.setObjectName('run_test_button')
56
- run_grid.addWidget(run_test_button)
57
- run_test_button.clicked.connect(self.run_test)
58
- run_grid.addStretch(1)
59
-
60
- run_continue_button = QPushButton('忽略错误并continue', main_table)
61
- run_continue_button.setObjectName('run_continue_button')
62
- run_grid.addWidget(run_continue_button)
63
- run_continue_button.clicked.connect(self.run_continue)
64
- run_grid.addStretch(1)
65
-
66
- run_raise_button = QPushButton('忽略错误并raise error', main_table)
67
- run_raise_button.setObjectName('run_raise_button')
68
- run_grid.addWidget(run_raise_button)
69
- run_raise_button.clicked.connect(self.run_raise)
70
-
71
- run_grid.addStretch(10)
72
-
73
- def refresh_ui(self):
74
- flow_tree: QTreeWidget = self.findChild(QTreeWidget, 'flow_tree')
75
- print_text: QTextEdit = self.findChild(QTextEdit, 'print_text')
76
- flow_tree.clear()
77
- main = self.flow.main
78
- for i in main.son:
79
- if i[1] == 'function':
80
- child = QTreeWidgetItem(flow_tree)
81
- child.setText(0, 'function')
82
- child.setText(1, i[0].func.__name__)
83
- child.setText(2, str(i[0].args))
84
- child.setText(3, str(i[0].kwargs))
85
- if i[0].end:
86
- if i[0].has_return:
87
- child_4_str = str(i[0].re_value)
88
- else:
89
- child_4_str = str(i[0].err)
90
- else:
91
- child_4_str = '未结束'
92
- child.setText(4, child_4_str)
93
- setattr(child, '__flow', i[0])
94
- flow_tree.addTopLevelItem(child)
95
- self.refresh_flow_tree(child, i[0])
96
- else:
97
- child = QTreeWidgetItem(flow_tree)
98
- child.setText(0, 'log')
99
- child.setText(1, str(i[0]))
100
- flow_tree.addTopLevelItem(child)
101
- current_function = self.flow.current_function
102
- if current_function.end:
103
- if current_function.has_return:
104
- print_str = str(current_function.re_value)
105
- else:
106
- print_str = str(current_function.traceback)
107
- else:
108
- print_str = '未结束'
109
- print_text.setText(print_str)
110
- flow_tree.expandAll()
111
-
112
- def refresh_flow_tree(self, top_item, flow):
113
- for i in flow.son:
114
- if i[1] == 'function':
115
- child = QTreeWidgetItem(top_item)
116
- child.setText(0, i[0].func_type)
117
- child.setText(1, i[0].func.__name__)
118
- child.setText(2, str(i[0].args))
119
- child.setText(3, str(i[0].kwargs))
120
- if i[0].end:
121
- if i[0].has_return:
122
- child_4_str = str(i[0].re_value)
123
- else:
124
- child_4_str = str(i[0].err)
125
- else:
126
- child_4_str = '未结束'
127
- child.setText(4, child_4_str)
128
- setattr(child, '__flow', i[0])
129
- top_item.addChild(child)
130
- self.refresh_flow_tree(child, i[0])
131
- else:
132
- child = QTreeWidgetItem(top_item)
133
- child.setText(0, 'log')
134
- child.setText(1, str(i[0]))
135
- top_item.addChild(child)
136
-
137
- def refresh_current_text(self, q):
138
- flow_tree: QTreeWidget = self.findChild(QTreeWidget, 'flow_tree')
139
- current_text: QTextEdit = self.findChild(QTextEdit, 'current_text')
140
- current_item = flow_tree.currentItem()
141
- current_flow = getattr(current_item, '__flow')
142
- if current_flow.end:
143
- if current_flow.has_return:
144
- current_str = str(current_flow.re_value)
145
- else:
146
- current_str = str(current_flow.traceback)
147
- else:
148
- current_str = '未结束'
149
- current_text.setText(current_str)
150
-
151
- def run_test(self, q):
152
- flow_tree: QTreeWidget = self.findChild(QTreeWidget, 'flow_tree')
153
- current_item = flow_tree.currentItem()
154
- current_flow = getattr(current_item, '__flow')
155
- current_flow(*current_flow.args, **current_flow.kwargs)
156
- self.refresh_ui()
157
-
158
- def run_continue(self, q):
159
- self.close()
160
-
161
- def run_raise(self, q):
162
- self.flow.raise_error = -1
163
- self.close()
File without changes
File without changes
File without changes