je-editor 0.0.223__py3-none-any.whl → 0.0.224__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.

Potentially problematic release.


This version of je-editor might be problematic. Click here for more details.

Files changed (71) hide show
  1. je_editor/git_client/commit_graph.py +7 -7
  2. je_editor/git_client/git_action.py +0 -7
  3. je_editor/pyside_ui/browser/browser_widget.py +24 -11
  4. je_editor/pyside_ui/browser/main_browser_widget.py +40 -27
  5. je_editor/pyside_ui/code/auto_save/auto_save_manager.py +34 -2
  6. je_editor/pyside_ui/code/auto_save/auto_save_thread.py +19 -6
  7. je_editor/pyside_ui/code/code_format/pep8_format.py +53 -9
  8. je_editor/pyside_ui/code/code_process/code_exec.py +88 -52
  9. je_editor/pyside_ui/code/plaintext_code_edit/code_edit_plaintext.py +116 -55
  10. je_editor/pyside_ui/code/running_process_manager.py +19 -1
  11. je_editor/pyside_ui/code/shell_process/shell_exec.py +71 -48
  12. je_editor/pyside_ui/code/syntax/python_syntax.py +45 -10
  13. je_editor/pyside_ui/code/syntax/syntax_setting.py +40 -12
  14. je_editor/pyside_ui/code/textedit_code_result/code_record.py +34 -12
  15. je_editor/pyside_ui/code/variable_inspector/inspector_gui.py +53 -6
  16. je_editor/pyside_ui/dialog/ai_dialog/set_ai_dialog.py +30 -3
  17. je_editor/pyside_ui/dialog/file_dialog/create_file_dialog.py +35 -2
  18. je_editor/pyside_ui/dialog/file_dialog/open_file_dialog.py +33 -5
  19. je_editor/pyside_ui/dialog/file_dialog/save_file_dialog.py +25 -3
  20. je_editor/pyside_ui/dialog/search_ui/search_error_box.py +26 -1
  21. je_editor/pyside_ui/dialog/search_ui/search_text_box.py +26 -1
  22. je_editor/pyside_ui/git_ui/code_diff_compare/code_diff_viewer_widget.py +11 -11
  23. je_editor/pyside_ui/git_ui/git_client/commit_table.py +46 -8
  24. je_editor/pyside_ui/git_ui/git_client/git_branch_tree_widget.py +49 -15
  25. je_editor/pyside_ui/git_ui/git_client/graph_view.py +64 -20
  26. je_editor/pyside_ui/main_ui/ai_widget/ai_config.py +20 -5
  27. je_editor/pyside_ui/main_ui/ai_widget/ask_thread.py +20 -1
  28. je_editor/pyside_ui/main_ui/ai_widget/chat_ui.py +56 -41
  29. je_editor/pyside_ui/main_ui/ai_widget/langchain_interface.py +45 -6
  30. je_editor/pyside_ui/main_ui/console_widget/console_gui.py +44 -12
  31. je_editor/pyside_ui/main_ui/console_widget/qprocess_adapter.py +34 -13
  32. je_editor/pyside_ui/main_ui/dock/destroy_dock.py +33 -2
  33. je_editor/pyside_ui/main_ui/editor/editor_widget.py +104 -20
  34. je_editor/pyside_ui/main_ui/editor/editor_widget_dock.py +34 -7
  35. je_editor/pyside_ui/main_ui/editor/process_input.py +38 -11
  36. je_editor/pyside_ui/main_ui/ipython_widget/rich_jupyter.py +46 -11
  37. je_editor/pyside_ui/main_ui/main_editor.py +175 -37
  38. je_editor/pyside_ui/main_ui/menu/check_style_menu/build_check_style_menu.py +51 -28
  39. je_editor/pyside_ui/main_ui/menu/dock_menu/build_dock_menu.py +80 -22
  40. je_editor/pyside_ui/main_ui/menu/file_menu/build_file_menu.py +70 -17
  41. je_editor/pyside_ui/main_ui/menu/help_menu/build_help_menu.py +34 -3
  42. je_editor/pyside_ui/main_ui/menu/language_menu/build_language_server.py +41 -1
  43. je_editor/pyside_ui/main_ui/menu/python_env_menu/build_venv_menu.py +100 -42
  44. je_editor/pyside_ui/main_ui/menu/run_menu/build_run_menu.py +57 -7
  45. je_editor/pyside_ui/main_ui/menu/run_menu/under_run_menu/build_debug_menu.py +50 -4
  46. je_editor/pyside_ui/main_ui/menu/run_menu/under_run_menu/build_program_menu.py +52 -6
  47. je_editor/pyside_ui/main_ui/menu/run_menu/under_run_menu/build_shell_menu.py +44 -4
  48. je_editor/pyside_ui/main_ui/menu/run_menu/under_run_menu/utils.py +23 -1
  49. je_editor/pyside_ui/main_ui/menu/set_menu_bar.py +37 -12
  50. je_editor/pyside_ui/main_ui/menu/style_menu/build_style_menu.py +44 -7
  51. je_editor/pyside_ui/main_ui/menu/tab_menu/build_tab_menu.py +126 -28
  52. je_editor/pyside_ui/main_ui/menu/text_menu/build_text_menu.py +65 -1
  53. je_editor/pyside_ui/main_ui/save_settings/setting_utils.py +18 -1
  54. je_editor/pyside_ui/main_ui/save_settings/user_color_setting_file.py +33 -3
  55. je_editor/pyside_ui/main_ui/save_settings/user_setting_file.py +38 -11
  56. je_editor/pyside_ui/main_ui/system_tray/extend_system_tray.py +39 -2
  57. je_editor/start_editor.py +26 -1
  58. je_editor/utils/encodings/python_encodings.py +101 -98
  59. je_editor/utils/file/open/open_file.py +36 -19
  60. je_editor/utils/file/save/save_file.py +35 -14
  61. je_editor/utils/json/json_file.py +29 -14
  62. je_editor/utils/json_format/json_process.py +33 -2
  63. je_editor/utils/logging/loggin_instance.py +38 -8
  64. je_editor/utils/multi_language/multi_language_wrapper.py +29 -4
  65. je_editor/utils/redirect_manager/redirect_manager_class.py +49 -11
  66. je_editor/utils/venv_check/check_venv.py +45 -15
  67. {je_editor-0.0.223.dist-info → je_editor-0.0.224.dist-info}/METADATA +1 -1
  68. {je_editor-0.0.223.dist-info → je_editor-0.0.224.dist-info}/RECORD +71 -71
  69. {je_editor-0.0.223.dist-info → je_editor-0.0.224.dist-info}/WHEEL +0 -0
  70. {je_editor-0.0.223.dist-info → je_editor-0.0.224.dist-info}/licenses/LICENSE +0 -0
  71. {je_editor-0.0.223.dist-info → je_editor-0.0.224.dist-info}/top_level.txt +0 -0
@@ -1,11 +1,15 @@
1
1
  from __future__ import annotations
2
+ # 啟用未來註解功能,允許型別提示使用字串前向參照
3
+ # Enable future annotations, allowing forward references in type hints
2
4
 
3
5
  from typing import TYPE_CHECKING
4
-
5
6
  from je_editor.utils.logging.loggin_instance import jeditor_logger
6
7
 
7
8
  if TYPE_CHECKING:
8
9
  from je_editor.pyside_ui.main_ui.main_editor import EditorMain
10
+ # 僅在型別檢查時匯入 EditorMain,避免循環依賴
11
+ # Import EditorMain only for type checking
12
+
9
13
  import sys
10
14
 
11
15
  from PySide6.QtGui import QAction
@@ -14,38 +18,71 @@ from je_editor.utils.multi_language.multi_language_wrapper import language_wrapp
14
18
 
15
19
 
16
20
  class ExtendSystemTray(QSystemTrayIcon):
21
+ """
22
+ 擴充系統匣功能,提供隱藏、最大化、還原、關閉等操作
23
+ Extend system tray functionality with hide, maximize, restore, and close actions
24
+ """
17
25
 
18
26
  def __init__(self, main_window: EditorMain):
27
+ # 初始化並記錄日誌
28
+ # Initialize and log
19
29
  jeditor_logger.info(f"Init ExtendSystemTray main_window: {main_window}")
20
30
  super().__init__(parent=main_window)
31
+
32
+ # 建立右鍵選單
33
+ # Create context menu
21
34
  self.menu = QMenu()
22
35
  self.main_window = main_window
36
+
37
+ # === 隱藏主視窗 / Hide main window ===
23
38
  self.hide_main_window_action = QAction(
24
39
  language_wrapper.language_word_dict.get("system_tray_hide"))
25
40
  self.hide_main_window_action.triggered.connect(self.main_window.hide)
26
41
  self.menu.addAction(self.hide_main_window_action)
42
+
43
+ # === 最大化主視窗 / Maximize main window ===
27
44
  self.maximized_main_window_action = QAction(
28
45
  language_wrapper.language_word_dict.get("system_tray_maximized"))
29
46
  self.maximized_main_window_action.triggered.connect(self.main_window.showMaximized)
30
47
  self.menu.addAction(self.maximized_main_window_action)
48
+
49
+ # === 還原主視窗 / Restore main window ===
31
50
  self.normal_main_window_action = QAction(
32
51
  language_wrapper.language_word_dict.get("system_tray_normal"))
33
52
  self.normal_main_window_action.triggered.connect(self.main_window.showNormal)
34
53
  self.menu.addAction(self.normal_main_window_action)
54
+
55
+ # === 關閉應用程式 / Close application ===
35
56
  self.close_main_window_action = QAction(
36
57
  language_wrapper.language_word_dict.get("system_tray_close"))
37
58
  self.close_main_window_action.triggered.connect(self.close_all)
38
59
  self.menu.addAction(self.close_main_window_action)
60
+
61
+ # 設定選單到系統匣圖示
62
+ # Attach menu to system tray icon
39
63
  self.setContextMenu(self.menu)
64
+
65
+ # 綁定點擊事件 (例如雙擊)
66
+ # Connect click events (e.g., double-click)
40
67
  self.activated.connect(self.clicked)
41
68
 
42
69
  def close_all(self):
70
+ """
71
+ 關閉應用程式:隱藏圖示、關閉主視窗並結束程式
72
+ Close the application: hide tray icon, close main window, and exit program
73
+ """
43
74
  jeditor_logger.info("ExtendSystemTray close_all")
44
75
  self.setVisible(False)
45
76
  self.main_window.close()
46
77
  sys.exit(0)
47
78
 
48
79
  def clicked(self, reason):
80
+ """
81
+ 處理系統匣點擊事件
82
+ Handle system tray click events
83
+ """
49
84
  if reason == self.ActivationReason.DoubleClick:
85
+ # 如果是雙擊,最大化主視窗
86
+ # If double-click, maximize the main window
50
87
  jeditor_logger.info("ExtendSystemTray DoubleClick")
51
- self.main_window.showMaximized()
88
+ self.main_window.showMaximized()
je_editor/start_editor.py CHANGED
@@ -8,10 +8,35 @@ from je_editor.pyside_ui.main_ui.main_editor import EditorMain
8
8
 
9
9
 
10
10
  def start_editor(debug_mode: bool = False) -> None:
11
+ """
12
+ 功能說明 (Function Description):
13
+ 啟動編輯器主程式,建立 QApplication 實例,套用主題,並顯示主視窗。
14
+ Start the main editor application, create QApplication instance, apply theme, and show main window.
15
+
16
+ :param debug_mode: 是否啟用除錯模式 / whether to enable debug mode
17
+ """
18
+
19
+ # 嘗試取得現有的 QCoreApplication 實例
20
+ # Try to get an existing QCoreApplication instance
11
21
  new_editor = QCoreApplication.instance()
22
+
23
+ # 如果沒有現有實例,建立新的 QApplication
24
+ # If no instance exists, create a new QApplication
12
25
  if new_editor is None:
13
26
  new_editor = QApplication(sys.argv)
27
+
28
+ # 建立主視窗,傳入 debug_mode
29
+ # Create the main editor window, passing debug_mode
14
30
  window = EditorMain(debug_mode)
31
+
32
+ # 套用 qt-material 主題 (dark amber)
33
+ # Apply qt-material theme (dark amber)
15
34
  apply_stylesheet(new_editor, theme='dark_amber.xml')
35
+
36
+ # 最大化顯示主視窗
37
+ # Show the main window maximized
16
38
  window.showMaximized()
17
- sys.exit(new_editor.exec())
39
+
40
+ # 啟動事件迴圈,並在結束時退出程式
41
+ # Start the event loop and exit the program when it ends
42
+ sys.exit(new_editor.exec())
@@ -1,99 +1,102 @@
1
+ # 定義一個 Python 支援的文字編碼清單
2
+ # Define a list of text encodings supported by Python
3
+
1
4
  python_encodings_list = [
2
- 'ascii',
3
- 'big5',
4
- 'big5hkscs',
5
- 'cp037',
6
- 'cp273',
7
- 'cp424',
8
- 'cp437',
9
- 'cp500',
10
- 'cp720',
11
- 'cp737',
12
- 'cp775',
13
- 'cp850',
14
- 'cp852',
15
- 'cp855',
16
- 'cp856',
17
- 'cp857',
18
- 'cp858',
19
- 'cp860',
20
- 'cp861',
21
- 'cp862',
22
- 'cp863',
23
- 'cp864',
24
- 'cp865',
25
- 'cp866',
26
- 'cp869',
27
- 'cp874',
28
- 'cp875',
29
- 'cp932',
30
- 'cp949',
31
- 'cp950',
32
- 'cp1006',
33
- 'cp1026',
34
- 'cp1125',
35
- 'cp1140',
36
- 'cp1250',
37
- 'cp1251',
38
- 'cp1252',
39
- 'cp1253',
40
- 'cp1254',
41
- 'cp1255',
42
- 'cp1256',
43
- 'cp1257',
44
- 'cp1258',
45
- 'euc_jp',
46
- 'euc_jis_2004',
47
- 'euc_jisx0213',
48
- 'euc_kr',
49
- 'gb2312',
50
- 'gbk',
51
- 'gb18030',
52
- 'hz',
53
- 'iso2022_jp',
54
- 'iso2022_jp_1',
55
- 'iso2022_jp_2',
56
- 'iso2022_jp_2004',
57
- 'iso2022_jp_3',
58
- 'iso2022_jp_ext',
59
- 'iso2022_kr',
60
- 'latin_1',
61
- 'iso8859_2',
62
- 'iso8859_3',
63
- 'iso8859_4',
64
- 'iso8859_5',
65
- 'iso8859_6',
66
- 'iso8859_7',
67
- 'iso8859_8',
68
- 'iso8859_9',
69
- 'iso8859_10',
70
- 'iso8859_11',
71
- 'iso8859_13',
72
- 'iso8859_14',
73
- 'iso8859_15',
74
- 'iso8859_16',
75
- 'johab',
76
- 'koi8_r',
77
- 'koi8_t',
78
- 'koi8_u',
79
- 'kz1048',
80
- 'mac_cyrillic',
81
- 'mac_greek',
82
- 'mac_iceland',
83
- 'mac_latin2',
84
- 'mac_roman',
85
- 'mac_turkish',
86
- 'ptcp154',
87
- 'shift_jis',
88
- 'shift_jis_2004',
89
- 'shift_jisx0213',
90
- 'utf_32',
91
- 'utf_32_be',
92
- 'utf_32_le',
93
- 'utf_16',
94
- 'utf_16_be',
95
- 'utf_16_le',
96
- 'utf_7',
97
- 'utf_8',
98
- 'utf_8_sig'
99
- ]
5
+ 'ascii', # ASCII 編碼 (基本的英文字符集, 7-bit) / Basic English character set
6
+ 'big5', # Big5 編碼 (繁體中文常用, 台灣/香港) / Traditional Chinese encoding (Taiwan/HK)
7
+ 'big5hkscs', # Big5-HKSCS (香港增補字集) / Big5 with Hong Kong Supplementary Character Set
8
+ 'cp037', # IBM EBCDIC US/Canada / IBM mainframe encoding
9
+ 'cp273', # IBM EBCDIC Germany / 德國 EBCDIC 編碼
10
+ 'cp424', # IBM EBCDIC Hebrew / 希伯來文編碼
11
+ 'cp437', # 原始 IBM PC 編碼 (DOS Latin US) / Original IBM PC encoding
12
+ 'cp500', # IBM EBCDIC International / 國際版 EBCDIC
13
+ 'cp720', # 阿拉伯文 (DOS) / Arabic (DOS)
14
+ 'cp737', # 希臘文 (DOS) / Greek (DOS)
15
+ 'cp775', # 波羅的海語系 (DOS) / Baltic languages (DOS)
16
+ 'cp850', # 西歐語系 (DOS) / Western Europe (DOS)
17
+ 'cp852', # 中歐語系 (DOS) / Central Europe (DOS)
18
+ 'cp855', # 西里爾字母 (DOS) / Cyrillic (DOS)
19
+ 'cp856', # 希伯來文 (DOS) / Hebrew (DOS)
20
+ 'cp857', # 土耳其文 (DOS) / Turkish (DOS)
21
+ 'cp858', # 西歐語系 (含歐元符號) / Western Europe with Euro sign
22
+ 'cp860', # 葡萄牙文 (DOS) / Portuguese (DOS)
23
+ 'cp861', # 冰島文 (DOS) / Icelandic (DOS)
24
+ 'cp862', # 希伯來文 (DOS) / Hebrew (DOS)
25
+ 'cp863', # 加拿大法文 (DOS) / Canadian French (DOS)
26
+ 'cp864', # 阿拉伯文 (DOS) / Arabic (DOS)
27
+ 'cp865', # 北歐語系 (DOS) / Nordic languages (DOS)
28
+ 'cp866', # 俄文 (DOS) / Russian (DOS)
29
+ 'cp869', # 希臘文 (DOS) / Greek (DOS)
30
+ 'cp874', # 泰文 (Windows) / Thai (Windows)
31
+ 'cp875', # IBM EBCDIC Greek / 希臘文 EBCDIC
32
+ 'cp932', # 日文 Shift_JIS (Windows) / Japanese Shift_JIS (Windows)
33
+ 'cp949', # 韓文 (Windows) / Korean (Windows)
34
+ 'cp950', # 繁體中文 Big5 (Windows) / Traditional Chinese Big5 (Windows)
35
+ 'cp1006', # 烏爾都文 (Urdu) / Urdu
36
+ 'cp1026', # IBM EBCDIC Turkish / 土耳其文 EBCDIC
37
+ 'cp1125', # 烏克蘭文 (DOS) / Ukrainian (DOS)
38
+ 'cp1140', # EBCDIC with Euro / EBCDIC 含歐元符號
39
+ 'cp1250', # 中歐語系 (Windows) / Central Europe (Windows)
40
+ 'cp1251', # 西里爾字母 (Windows) / Cyrillic (Windows)
41
+ 'cp1252', # 西歐語系 (Windows, 常見) / Western Europe (Windows, very common)
42
+ 'cp1253', # 希臘文 (Windows) / Greek (Windows)
43
+ 'cp1254', # 土耳其文 (Windows) / Turkish (Windows)
44
+ 'cp1255', # 希伯來文 (Windows) / Hebrew (Windows)
45
+ 'cp1256', # 阿拉伯文 (Windows) / Arabic (Windows)
46
+ 'cp1257', # 波羅的海語系 (Windows) / Baltic (Windows)
47
+ 'cp1258', # 越南文 (Windows) / Vietnamese (Windows)
48
+ 'euc_jp', # 日文 EUC 編碼 / Japanese EUC encoding
49
+ 'euc_jis_2004', # 日文 EUC (JIS 2004) / Japanese EUC (JIS 2004)
50
+ 'euc_jisx0213', # 日文 EUC (JIS X 0213) / Japanese EUC (JIS X 0213)
51
+ 'euc_kr', # 韓文 EUC 編碼 / Korean EUC encoding
52
+ 'gb2312', # 簡體中文 (舊標準) / Simplified Chinese (older standard)
53
+ 'gbk', # 簡體中文 (擴展) / Simplified Chinese (extended)
54
+ 'gb18030', # 簡體中文 (最新國標) / Simplified Chinese (latest national standard)
55
+ 'hz', # HZ-GB-2312 (簡體中文, 郵件常用) / Simplified Chinese (email encoding)
56
+ 'iso2022_jp', # 日文 ISO-2022-JP / Japanese ISO-2022-JP
57
+ 'iso2022_jp_1', # 日文 ISO-2022-JP-1 / Japanese ISO-2022-JP-1
58
+ 'iso2022_jp_2', # 日文 ISO-2022-JP-2 / Japanese ISO-2022-JP-2
59
+ 'iso2022_jp_2004', # 日文 ISO-2022-JP-2004 / Japanese ISO-2022-JP-2004
60
+ 'iso2022_jp_3', # 日文 ISO-2022-JP-3 / Japanese ISO-2022-JP-3
61
+ 'iso2022_jp_ext', # 日文 ISO-2022-JP-EXT / Japanese ISO-2022-JP-EXT
62
+ 'iso2022_kr', # 韓文 ISO-2022-KR / Korean ISO-2022-KR
63
+ 'latin_1', # ISO-8859-1 (西歐語系, 常見) / Western Europe (very common)
64
+ 'iso8859_2', # 中歐語系 / Central Europe
65
+ 'iso8859_3', # 南歐語系 / South Europe
66
+ 'iso8859_4', # 北歐語系 / North Europe
67
+ 'iso8859_5', # 西里爾字母 / Cyrillic
68
+ 'iso8859_6', # 阿拉伯文 / Arabic
69
+ 'iso8859_7', # 希臘文 / Greek
70
+ 'iso8859_8', # 希伯來文 / Hebrew
71
+ 'iso8859_9', # 土耳其文 / Turkish
72
+ 'iso8859_10', # 北歐語系 / Nordic
73
+ 'iso8859_11', # 泰文 / Thai
74
+ 'iso8859_13', # 波羅的海語系 / Baltic
75
+ 'iso8859_14', # 凱爾特語 / Celtic
76
+ 'iso8859_15', # 西歐語系 (含歐元) / Western Europe with Euro
77
+ 'iso8859_16', # 東歐語系 / Eastern Europe
78
+ 'johab', # 韓文 Johab 編碼 / Korean Johab encoding
79
+ 'koi8_r', # 俄文 KOI8-R / Russian KOI8-R
80
+ 'koi8_t', # 塔吉克文 KOI8-T / Tajik KOI8-T
81
+ 'koi8_u', # 烏克蘭文 KOI8-U / Ukrainian KOI8-U
82
+ 'kz1048', # 哈薩克文 / Kazakh
83
+ 'mac_cyrillic', # Mac OS 西里爾字母 / Mac Cyrillic
84
+ 'mac_greek', # Mac OS 希臘文 / Mac Greek
85
+ 'mac_iceland', # Mac OS 冰島文 / Mac Icelandic
86
+ 'mac_latin2', # Mac OS 中歐語系 / Mac Central Europe
87
+ 'mac_roman', # Mac OS 西歐語系 / Mac Roman
88
+ 'mac_turkish', # Mac OS 土耳其文 / Mac Turkish
89
+ 'ptcp154', # 中亞語系 (西里爾字母) / Central Asian Cyrillic
90
+ 'shift_jis', # 日文 Shift JIS 編碼 (常見於 Windows 與網頁) / Japanese Shift JIS encoding (commonly used in Windows & web)
91
+ 'shift_jis_2004', # 日文 Shift JIS (JIS 2004 標準) / Japanese Shift JIS (JIS 2004 standard)
92
+ 'shift_jisx0213', # 日文 Shift JIS (JIS X 0213 擴展) / Japanese Shift JIS (JIS X 0213 extension)
93
+ 'utf_32', # UTF-32 (依平台大小端序, 4 bytes per char) / UTF-32 (platform-dependent endianness, 4 bytes per char)
94
+ 'utf_32_be', # UTF-32 Big Endian / UTF-32 大端序
95
+ 'utf_32_le', # UTF-32 Little Endian / UTF-32 小端序
96
+ 'utf_16', # UTF-16 (依平台大小端序, 2 or 4 bytes per char) / UTF-16 (platform-dependent endianness)
97
+ 'utf_16_be', # UTF-16 Big Endian / UTF-16 大端序
98
+ 'utf_16_le', # UTF-16 Little Endian / UTF-16 小端序
99
+ 'utf_7', # UTF-7 (為電子郵件設計, 已過時) / UTF-7 (designed for email, obsolete)
100
+ 'utf_8', # UTF-8 (最常用, 網頁與跨平台標準) / UTF-8 (most common, web & cross-platform standard)
101
+ 'utf_8_sig' # UTF-8 with BOM (Byte Order Mark) / UTF-8 含 BOM 標記
102
+ ]
@@ -2,34 +2,51 @@ import typing
2
2
  from pathlib import Path
3
3
  from threading import Lock
4
4
 
5
+ # 匯入自訂例外與日誌工具
6
+ # Import custom exception and logging utility
5
7
  from je_editor.utils.exception.exceptions import JEditorOpenFileException
6
8
  from je_editor.utils.logging.loggin_instance import jeditor_logger
7
9
 
8
10
 
9
- def read_file(file_path: str) -> typing.List[typing.Union[str, str]]:
11
+ def read_file(file_path: str) -> list[Path | str] | None:
10
12
  """
11
- use to check file is exist and open
12
- :param file_path: the file we want to read its whole file path
13
- :return: read's file and file content
14
- try
15
- lock thread
16
- find file is exist ? and is file ?
17
- if both is true
18
- try to open it and read
19
- return file and content
20
- finally
21
- release lock
13
+ 功能說明 (Function Description):
14
+ 用來檢查檔案是否存在並嘗試開啟,讀取其內容。
15
+ Used to check if a file exists and open it to read its content.
16
+
17
+ :param file_path: 檔案完整路徑 / the full path of the file to read
18
+ :return: [檔案路徑, 檔案內容] / [file path, file content]
19
+
20
+ 流程 (Logic):
21
+ 1. 嘗試鎖定執行緒 (避免多執行緒同時存取)
22
+ Try to lock the thread (prevent concurrent access).
23
+ 2. 檢查檔案路徑是否為空,並確認檔案存在且為檔案。
24
+ Check if file path is not empty, exists, and is a file.
25
+ 3. 若條件成立,嘗試以 UTF-8 編碼開啟檔案並讀取內容。
26
+ If true, open the file with UTF-8 encoding and read content.
27
+ 4. 最後釋放鎖。
28
+ Finally, release the lock.
22
29
  """
30
+
31
+ # 記錄日誌,方便除錯與追蹤
32
+ # Log the file path for debugging and tracking
23
33
  jeditor_logger.info(f"open_file.py read_file file_path: {file_path}")
24
- lock = Lock()
34
+
35
+ lock = Lock() # 建立一個執行緒鎖 / Create a thread lock
25
36
  try:
26
- lock.acquire()
27
- if file_path != "" and file_path is not None:
28
- file_path = Path(file_path)
29
- if file_path.exists() and file_path.is_file():
37
+ lock.acquire() # 嘗試鎖定資源 / Acquire the lock
38
+ if file_path != "" and file_path is not None: # 確認路徑不為空 / Ensure path is not empty
39
+ file_path = Path(file_path) # 轉換為 Path 物件 / Convert to Path object
40
+ if file_path.exists() and file_path.is_file(): # 檢查檔案存在且為檔案 / Check file existence
41
+ # 以讀寫模式開啟檔案 (UTF-8 編碼)
42
+ # Open file in read+write mode with UTF-8 encoding
30
43
  with open(file_path, "r+", encoding="utf-8") as open_read_file:
31
- return [file_path, open_read_file.read()]
44
+ return [file_path, open_read_file.read()] # 回傳檔案路徑與內容 / Return file path and content
32
45
  except JEditorOpenFileException:
46
+ # 捕捉自訂例外並重新拋出
47
+ # Catch custom exception and re-raise
33
48
  raise JEditorOpenFileException
34
49
  finally:
35
- lock.release()
50
+ # 確保鎖一定會被釋放
51
+ # Ensure the lock is always released
52
+ lock.release()
@@ -1,31 +1,52 @@
1
1
  from threading import Lock
2
2
 
3
+ # 匯入自訂例外與日誌工具
4
+ # Import custom exception and logging utility
3
5
  from je_editor.utils.exception.exceptions import JEditorSaveFileException
4
6
  from je_editor.utils.logging.loggin_instance import jeditor_logger
5
7
 
6
8
 
7
9
  def write_file(file_path: str, content: str) -> None:
8
10
  """
9
- :param file_path: file we want to write
10
- :param content: content write in file
11
- try
12
- lock thread
13
- if file not empty string
14
- write content to file
15
- finally
16
- release lock
11
+ 功能說明 (Function Description):
12
+ 將指定內容寫入檔案,並確保在多執行緒環境下安全操作。
13
+ Write the given content into a file, ensuring thread safety.
14
+
15
+ :param file_path: 要寫入的檔案路徑 / the file path to write
16
+ :param content: 要寫入的內容 / the content to write
17
+
18
+ 流程 (Logic):
19
+ 1. 嘗試鎖定執行緒 (避免多執行緒同時存取檔案)
20
+ Try to lock the thread (prevent concurrent file access).
21
+ 2. 檢查檔案路徑是否為空字串或 None。
22
+ Check if file path is not empty or None.
23
+ 3. 若條件成立,開啟檔案並以 UTF-8 編碼寫入內容。
24
+ If valid, open the file and write content with UTF-8 encoding.
25
+ 4. 最後釋放鎖。
26
+ Finally, release the lock.
17
27
  """
28
+
29
+ # 記錄日誌,方便除錯與追蹤
30
+ # Log the file path and content for debugging and tracking
18
31
  jeditor_logger.info("save_file.py write_file "
19
32
  f"file_path: {file_path} "
20
33
  f"content: {content}")
21
- lock = Lock()
22
- content = str(content)
34
+
35
+ lock = Lock() # 建立一個執行緒鎖 / Create a thread lock
36
+ content = str(content) # 確保內容為字串 / Ensure content is a string
37
+
23
38
  try:
24
- lock.acquire()
25
- if file_path != "" and file_path is not None:
39
+ lock.acquire() # 嘗試鎖定資源 / Acquire the lock
40
+ if file_path != "" and file_path is not None: # 確認路徑有效 / Ensure path is valid
41
+ # 以寫入模式開啟檔案 (UTF-8 編碼)
42
+ # Open file in write+read mode with UTF-8 encoding
26
43
  with open(file_path, "w+", encoding="utf-8") as file_to_write:
27
- file_to_write.write(content)
44
+ file_to_write.write(content) # 寫入內容 / Write content
28
45
  except JEditorSaveFileException:
46
+ # 捕捉自訂例外並重新拋出
47
+ # Catch custom exception and re-raise
29
48
  raise JEditorSaveFileException
30
49
  finally:
31
- lock.release()
50
+ # 確保鎖一定會被釋放
51
+ # Ensure the lock is always released
52
+ lock.release()
@@ -1,48 +1,63 @@
1
1
  import json
2
2
  from pathlib import Path
3
3
  from threading import Lock
4
- from typing import Union
4
+ from typing import Union, Any
5
5
 
6
+ # 匯入自訂錯誤訊息與例外類別
7
+ # Import custom error messages and exception class
6
8
  from je_editor.utils.exception.exception_tags import cant_find_json_error
7
9
  from je_editor.utils.exception.exception_tags import cant_save_json_error
8
10
  from je_editor.utils.exception.exceptions import JEditorJsonException
9
11
  from je_editor.utils.logging.loggin_instance import jeditor_logger
10
12
 
13
+ # 全域鎖,確保多執行緒存取 JSON 檔案時的安全性
14
+ # Global lock to ensure thread safety when accessing JSON files
11
15
  _lock = Lock()
12
16
 
13
17
 
14
- def read_json(json_file_path: str) -> Union[list, dict]:
18
+ def read_json(json_file_path: str) -> Any | None:
15
19
  """
16
- use to read action file
17
- :param json_file_path json file's path to read
20
+ 功能說明 (Function Description):
21
+ 讀取 JSON 檔案並回傳其內容。
22
+ Read a JSON file and return its content.
23
+
24
+ :param json_file_path: JSON 檔案路徑 / path to the JSON file
25
+ :return: list 或 dict,取決於 JSON 結構 / list or dict depending on JSON structure
18
26
  """
19
27
  jeditor_logger.info(f"json_file.py read_json json_file_path: {json_file_path}")
20
- _lock.acquire()
28
+ _lock.acquire() # 嘗試鎖定資源 / Acquire the lock
21
29
  try:
22
30
  file_path = Path(json_file_path)
23
- if file_path.exists() and file_path.is_file():
24
- with open(json_file_path) as read_file:
25
- return json.loads(read_file.read())
31
+ if file_path.exists() and file_path.is_file(): # 確認檔案存在且為檔案 / Ensure file exists
32
+ with open(json_file_path) as read_file: # 開啟檔案 (預設 UTF-8)
33
+ return json.loads(read_file.read()) # 載入 JSON 並回傳 / Load JSON and return
26
34
  except JEditorJsonException:
35
+ # 捕捉自訂例外並重新拋出
36
+ # Catch custom exception and re-raise
27
37
  raise JEditorJsonException(cant_find_json_error)
28
38
  finally:
29
- _lock.release()
39
+ _lock.release() # 確保鎖一定會被釋放 / Ensure the lock is always released
30
40
 
31
41
 
32
42
  def write_json(json_save_path: str, data_to_output: Union[list, dict]) -> None:
33
43
  """
34
- use to save action file
35
- :param json_save_path json save path
36
- :param data_to_output data to output
44
+ 功能說明 (Function Description):
45
+ 將資料寫入 JSON 檔案。
46
+ Write data into a JSON file.
47
+
48
+ :param json_save_path: JSON 檔案儲存路徑 / path to save the JSON file
49
+ :param data_to_output: 要輸出的資料 (list 或 dict) / data to output (list or dict)
37
50
  """
38
51
  jeditor_logger.info("json_file.py write_json "
39
52
  f"json_save_path: {json_save_path} "
40
53
  f"data_to_output: {data_to_output}")
41
- _lock.acquire()
54
+ _lock.acquire() # 嘗試鎖定資源 / Acquire the lock
42
55
  try:
56
+ # 以寫入模式開啟檔案,並將資料轉換為 JSON 格式 (縮排 4 格)
57
+ # Open file in write mode and dump data as JSON (indent=4)
43
58
  with open(json_save_path, "w+") as file_to_write:
44
59
  file_to_write.write(json.dumps(data_to_output, indent=4))
45
60
  except JEditorJsonException:
46
61
  raise JEditorJsonException(cant_save_json_error)
47
62
  finally:
48
- _lock.release()
63
+ _lock.release() # 確保鎖一定會被釋放 / Ensure the lock is always released
@@ -3,6 +3,8 @@ import sys
3
3
  from json import dumps
4
4
  from json import loads
5
5
 
6
+ # 匯入自訂錯誤訊息與例外類別
7
+ # Import custom error messages and exception class
6
8
  from je_editor.utils.exception.exception_tags import cant_reformat_json_error
7
9
  from je_editor.utils.exception.exception_tags import wrong_json_data_error
8
10
  from je_editor.utils.exception.exceptions import JEditorJsonException
@@ -10,24 +12,53 @@ from je_editor.utils.logging.loggin_instance import jeditor_logger
10
12
 
11
13
 
12
14
  def __process_json(json_string: str, **kwargs) -> str:
15
+ """
16
+ 功能說明 (Function Description):
17
+ 嘗試將輸入的 JSON 字串重新格式化 (pretty print)。
18
+ Try to reformat the input JSON string (pretty print).
19
+
20
+ :param json_string: JSON 格式字串 / JSON formatted string
21
+ :param kwargs: 額外參數傳給 json.dumps / extra arguments for json.dumps
22
+ :return: 格式化後的 JSON 字串 / formatted JSON string
23
+ """
13
24
  try:
25
+ # 嘗試先將字串解析為 JSON,再重新輸出為縮排格式
26
+ # Try to parse string into JSON, then dump with indentation
14
27
  return dumps(loads(json_string), indent=4, sort_keys=True, **kwargs)
15
28
  except json.JSONDecodeError as error:
29
+ # 如果 JSON 格式錯誤,輸出錯誤訊息到 stderr 並拋出例外
30
+ # If JSON format is invalid, print error to stderr and raise exception
16
31
  print(wrong_json_data_error, file=sys.stderr)
17
32
  raise error
18
33
  except TypeError:
34
+ # 如果輸入不是合法 JSON 字串,嘗試直接將物件轉為 JSON
35
+ # If input is not a valid JSON string, try dumping the object directly
19
36
  try:
20
37
  return dumps(json_string, indent=4, sort_keys=True, **kwargs)
21
38
  except TypeError:
39
+ # 若仍失敗,拋出自訂例外
40
+ # If still fails, raise custom exception
22
41
  raise JEditorJsonException(wrong_json_data_error)
23
42
 
24
43
 
25
44
  def reformat_json(json_string: str, **kwargs) -> str:
26
- # Make json pretty
45
+ """
46
+ 功能說明 (Function Description):
47
+ 對外提供的 JSON 格式化函式,會呼叫內部的 __process_json。
48
+ Public function to reformat JSON string, calls __process_json internally.
49
+
50
+ :param json_string: JSON 格式字串 / JSON formatted string
51
+ :param kwargs: 額外參數傳給 json.dumps / extra arguments for json.dumps
52
+ :return: 格式化後的 JSON 字串 / formatted JSON string
53
+ """
54
+ # 記錄日誌,方便除錯與追蹤
55
+ # Log the input string and kwargs for debugging and tracking
27
56
  jeditor_logger.info(f"json_process.py reformat_json "
28
57
  f"json_string: {json_string} "
29
58
  f"kwargs: {kwargs}")
30
59
  try:
31
60
  return __process_json(json_string, **kwargs)
32
61
  except JEditorJsonException:
33
- raise JEditorJsonException(cant_reformat_json_error)
62
+ # 捕捉自訂例外並重新拋出
63
+ # Catch custom exception and re-raise
64
+ raise JEditorJsonException(cant_reformat_json_error)