meltygui 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.
Files changed (372) hide show
  1. meltygui/__init__.py +107 -0
  2. meltygui/accounts/__init__.py +0 -0
  3. meltygui/accounts/internet_accounts.py +1355 -0
  4. meltygui/chat/__init__.py +91 -0
  5. meltygui/chat/activity.py +75 -0
  6. meltygui/chat/backends.py +36 -0
  7. meltygui/chat/chat_interface.py +732 -0
  8. meltygui/chat/chat_proxy.py +352 -0
  9. meltygui/chat/codex_proxy.py +592 -0
  10. meltygui/chat/codex_settings.py +100 -0
  11. meltygui/chat/codex_transport.py +60 -0
  12. meltygui/chat/command_parser.py +204 -0
  13. meltygui/chat/images.py +227 -0
  14. meltygui/chat/messages.py +417 -0
  15. meltygui/chat/metadata.py +139 -0
  16. meltygui/chat/writer_locks.py +64 -0
  17. meltygui/code/__init__.py +0 -0
  18. meltygui/code/basic_converters.py +533 -0
  19. meltygui/code/chain_converters.py +2111 -0
  20. meltygui/code/code_checks.py +2209 -0
  21. meltygui/code/core_syntax.py +1430 -0
  22. meltygui/code/file_converters.py +1933 -0
  23. meltygui/code/fileref.py +702 -0
  24. meltygui/code/hotswap_guard.py +144 -0
  25. meltygui/code/libcst_conversion.py +9724 -0
  26. meltygui/code/live_instrument.py +392 -0
  27. meltygui/code/live_view.py +2490 -0
  28. meltygui/code/melty_scan.py +2684 -0
  29. meltygui/code/new_codecs.py +1255 -0
  30. meltygui/code/new_converters.py +3017 -0
  31. meltygui/code/project_code.py +278 -0
  32. meltygui/code/source_context.py +63 -0
  33. meltygui/code/symbol_roster.py +1588 -0
  34. meltygui/code/syntax_check.py +34 -0
  35. meltygui/code/syntax_check_worker.py +114 -0
  36. meltygui/completion/__init__.py +0 -0
  37. meltygui/completion/fim.py +1232 -0
  38. meltygui/completion/fim_context.py +481 -0
  39. meltygui/completion/providers/__init__.py +0 -0
  40. meltygui/completion/providers/anthropic_oauth.py +446 -0
  41. meltygui/completion/providers/anthropic_requests.py +69 -0
  42. meltygui/completion/providers/claude.py +203 -0
  43. meltygui/completion/providers/claude_usage.py +499 -0
  44. meltygui/completion/providers/codex_accounts.py +180 -0
  45. meltygui/completion/providers/copilot.py +617 -0
  46. meltygui/completion/providers/oauth_popup.py +220 -0
  47. meltygui/completion/providers/ollama.py +320 -0
  48. meltygui/completion/providers/profiles.py +23 -0
  49. meltygui/core/README.md +88 -0
  50. meltygui/core/__init__.py +1 -0
  51. meltygui/core/automation/__init__.py +1 -0
  52. meltygui/core/automation/action_core.py +153 -0
  53. meltygui/core/automation/collection_action.py +45 -0
  54. meltygui/core/automation/mcp_eval.py +167 -0
  55. meltygui/core/automation/mcp_hotswap.py +107 -0
  56. meltygui/core/automation/mcp_query.py +552 -0
  57. meltygui/core/automation/mcp_server.py +657 -0
  58. meltygui/core/automation/orchestration_core.py +2636 -0
  59. meltygui/core/automation/query_core.py +124 -0
  60. meltygui/core/automation/search_core.py +26 -0
  61. meltygui/core/automation/selector_core.py +340 -0
  62. meltygui/core/automation/value_core.py +1752 -0
  63. meltygui/core/cache/__init__.py +1 -0
  64. meltygui/core/cache/cache_diagnostics.py +0 -0
  65. meltygui/core/cache/invalidation_decoration.py +153 -0
  66. meltygui/core/cache/invalidation_tracker.py +43 -0
  67. meltygui/core/cache/tile_cache.py +5968 -0
  68. meltygui/core/conversion/__init__.py +1 -0
  69. meltygui/core/conversion/bubbling.py +599 -0
  70. meltygui/core/conversion/cache_tree.py +188 -0
  71. meltygui/core/conversion/chain.py +113 -0
  72. meltygui/core/conversion/converter_register.py +145 -0
  73. meltygui/core/conversion/data_decoration.py +67 -0
  74. meltygui/core/conversion/dict_conversion.py +1815 -0
  75. meltygui/core/conversion/dict_conversion_util.py +177 -0
  76. meltygui/core/conversion/dynamic_obj.py +89 -0
  77. meltygui/core/conversion/graph_compare.py +183 -0
  78. meltygui/core/conversion/load_save_v2.py +1032 -0
  79. meltygui/core/conversion/missing_saved_class.py +39 -0
  80. meltygui/core/conversion/path_finder.py +606 -0
  81. meltygui/core/conversion/render_host.py +1083 -0
  82. meltygui/core/core_render.py +6537 -0
  83. meltygui/core/definition_hotswap.py +231 -0
  84. meltygui/core/diagnostics/__init__.py +1 -0
  85. meltygui/core/diagnostics/attribute_churn.py +38 -0
  86. meltygui/core/diagnostics/fps_counter.py +39 -0
  87. meltygui/core/diagnostics/gpu_frame_timer.py +103 -0
  88. meltygui/core/diagnostics/inspection_core.py +169 -0
  89. meltygui/core/diagnostics/monitor_core.py +105 -0
  90. meltygui/core/diagnostics/notifications.py +706 -0
  91. meltygui/core/diagnostics/perf_trace.py +281 -0
  92. meltygui/core/diagnostics/profile_decoration.py +88 -0
  93. meltygui/core/diagnostics/resize_trace.py +62 -0
  94. meltygui/core/diagnostics/screenshot_core.py +247 -0
  95. meltygui/core/diagnostics/session_status.py +98 -0
  96. meltygui/core/diagnostics/trace_core.py +445 -0
  97. meltygui/core/files/__init__.py +1 -0
  98. meltygui/core/files/file_core.py +208 -0
  99. meltygui/core/files/file_explorer_core.py +104 -0
  100. meltygui/core/files/file_tree_core.py +198 -0
  101. meltygui/core/files/file_watch_core.py +43 -0
  102. meltygui/core/files/import_graph_core.py +43 -0
  103. meltygui/core/files/metadata_core.py +51 -0
  104. meltygui/core/graphics/__init__.py +1 -0
  105. meltygui/core/graphics/cuda_context_core.py +166 -0
  106. meltygui/core/graphics/cuda_interop_core.py +136 -0
  107. meltygui/core/graphics/cuda_kernel_core.py +91 -0
  108. meltygui/core/graphics/framebuffer_recorder.py +337 -0
  109. meltygui/core/graphics/gl_state.py +658 -0
  110. meltygui/core/graphics/lut_core.py +52 -0
  111. meltygui/core/graphics/overlay_renderer.py +984 -0
  112. meltygui/core/graphics/scene_target.py +180 -0
  113. meltygui/core/graphics/screenshot.py +439 -0
  114. meltygui/core/graphics/shader_func.py +478 -0
  115. meltygui/core/graphics/tensor_core.py +45 -0
  116. meltygui/core/graphics/text_texture.py +329 -0
  117. meltygui/core/graphics/wayland_color.py +635 -0
  118. meltygui/core/input/__init__.py +1 -0
  119. meltygui/core/input/collision.py +165 -0
  120. meltygui/core/input/drag_drop_core.py +1525 -0
  121. meltygui/core/input/hypr_left_drag.py +323 -0
  122. meltygui/core/input/input_core.py +245 -0
  123. meltygui/core/input/input_handler.py +1101 -0
  124. meltygui/core/input/mouse_cursor.py +355 -0
  125. meltygui/core/input/pynput_backend.py +1054 -0
  126. meltygui/core/input/space_mouse.py +338 -0
  127. meltygui/core/input/touchpad_backend.py +393 -0
  128. meltygui/core/input/view_selection.py +177 -0
  129. meltygui/core/layout/__init__.py +1 -0
  130. meltygui/core/layout/column_core.py +2153 -0
  131. meltygui/core/layout/cursor_core.py +161 -0
  132. meltygui/core/layout/dropdown_core.py +278 -0
  133. meltygui/core/layout/edge_constraints.py +155 -0
  134. meltygui/core/layout/grid_core.py +117 -0
  135. meltygui/core/layout/header_core.py +23 -0
  136. meltygui/core/layout/header_runtime.py +67 -0
  137. meltygui/core/layout/layout_core.py +87 -0
  138. meltygui/core/layout/tile_manager_core.py +591 -0
  139. meltygui/core/melty.py +6726 -0
  140. meltygui/core/module_map.json +896 -0
  141. meltygui/core/module_names.py +19 -0
  142. meltygui/core/rendering/__init__.py +1 -0
  143. meltygui/core/rendering/core_decoration.py +431 -0
  144. meltygui/core/rendering/core_render_helpers.py +328 -0
  145. meltygui/core/rendering/func_metadata.py +398 -0
  146. meltygui/core/rendering/mode.py +818 -0
  147. meltygui/core/rendering/mode_defaults.py +41 -0
  148. meltygui/core/rendering/modes.py +136 -0
  149. meltygui/core/rendering/parameter_core.py +1665 -0
  150. meltygui/core/rendering/render_dispatch.py +1891 -0
  151. meltygui/core/rendering/render_funcs.py +273 -0
  152. meltygui/core/rendering/shaped.py +312 -0
  153. meltygui/core/rendering/window_decoration.py +25 -0
  154. meltygui/core/runtime/__init__.py +1 -0
  155. meltygui/core/runtime/app.py +735 -0
  156. meltygui/core/runtime/app_session.py +140 -0
  157. meltygui/core/runtime/background.py +564 -0
  158. meltygui/core/runtime/extensions.py +53 -0
  159. meltygui/core/runtime/gc_manager.py +1163 -0
  160. meltygui/core/runtime/lifecycle.py +21 -0
  161. meltygui/core/runtime/paths.py +27 -0
  162. meltygui/core/runtime/settings.py +14 -0
  163. meltygui/core/runtime/singleton.py +16 -0
  164. meltygui/core/runtime/thread_safe_bool.py +24 -0
  165. meltygui/core/runtime/thread_signal.py +30 -0
  166. meltygui/core/runtime/toggles.py +3115 -0
  167. meltygui/core/services/__init__.py +1 -0
  168. meltygui/core/services/account_core.py +10 -0
  169. meltygui/core/services/chat_core.py +19 -0
  170. meltygui/core/services/claude_terminal_core.py +346 -0
  171. meltygui/core/services/terminal_core.py +458 -0
  172. meltygui/core/services/terminal_runtime.py +78 -0
  173. meltygui/core/styling/__init__.py +1 -0
  174. meltygui/core/styling/color_core.py +46 -0
  175. meltygui/core/styling/fonts.py +639 -0
  176. meltygui/core/styling/global_style.py +338 -0
  177. meltygui/core/styling/style.py +198 -0
  178. meltygui/core/styling/style_core.py +522 -0
  179. meltygui/core/styling/warm_start.py +149 -0
  180. meltygui/core/windowing/__init__.py +1 -0
  181. meltygui/core/windowing/backends/PYIMGUI_LICENSE +28 -0
  182. meltygui/core/windowing/backends/__init__.py +1 -0
  183. meltygui/core/windowing/backends/imgui_renderer.py +138 -0
  184. meltygui/core/windowing/backends/native_wayland.py +850 -0
  185. meltygui/core/windowing/backends/protocols/xdg-decoration-unstable-v1.xml +156 -0
  186. meltygui/core/windowing/backends/protocols/xdg-shell.xml +1420 -0
  187. meltygui/core/windowing/backends/wayland_protocol.py +101 -0
  188. meltygui/core/windowing/dock_core.py +182 -0
  189. meltygui/core/windowing/frame_geometry.py +42 -0
  190. meltygui/core/windowing/geometry_feed.py +864 -0
  191. meltygui/core/windowing/glfw_utils.py +1343 -0
  192. meltygui/core/windowing/os_frame.py +1552 -0
  193. meltygui/core/windowing/surface.py +643 -0
  194. meltygui/core/windowing/titlebar.py +1560 -0
  195. meltygui/core/windowing/titlebar_buttons.py +281 -0
  196. meltygui/core/windowing/wayland_move.py +932 -0
  197. meltygui/core/windowing/window_api.py +62 -0
  198. meltygui/core/windowing/window_constants.py +339 -0
  199. meltygui/core/windowing/window_visibility.py +162 -0
  200. meltygui/debug/__init__.py +0 -0
  201. meltygui/debug/app_view_utils.py +9 -0
  202. meltygui/editor/__init__.py +0 -0
  203. meltygui/editor/bash_syntax.py +30 -0
  204. meltygui/editor/code_line_fast.py +152 -0
  205. meltygui/editor/diff.py +139 -0
  206. meltygui/editor/external_changes.py +159 -0
  207. meltygui/editor/file_header.py +41 -0
  208. meltygui/editor/live_usage.py +169 -0
  209. meltygui/editor/live_view_views.py +1803 -0
  210. meltygui/editor/pending_save.py +1351 -0
  211. meltygui/editor/roster_tints.py +547 -0
  212. meltygui/editor/source_preview.py +16 -0
  213. meltygui/editor/source_tools.py +10 -0
  214. meltygui/editor/source_ui.py +70 -0
  215. meltygui/editor/spell_check.py +77 -0
  216. meltygui/editor/text_editor.py +9076 -0
  217. meltygui/editor/usage_picker.py +538 -0
  218. meltygui/events/__init__.py +0 -0
  219. meltygui/events/example.py +118 -0
  220. meltygui/examples/__init__.py +0 -0
  221. meltygui/examples/columns_demo.py +33 -0
  222. meltygui/examples/columns_window_demo.py +60 -0
  223. meltygui/examples/context_menu_demo.py +24 -0
  224. meltygui/examples/context_menu_window_demo.py +49 -0
  225. meltygui/examples/gui_playground.py +127 -0
  226. meltygui/examples/live_view_playground.py +256 -0
  227. meltygui/examples/lora.py +43 -0
  228. meltygui/examples/lora_data.py +59 -0
  229. meltygui/examples/lora_policies.py +67 -0
  230. meltygui/examples/mode_demo.py +49 -0
  231. meltygui/examples/modifies_demo.py +119 -0
  232. meltygui/examples/scalar_policies.py +60 -0
  233. meltygui/examples/style_layouts.py +149 -0
  234. meltygui/examples/tile_manager_demo.py +74 -0
  235. meltygui/examples/tint_demo.py +160 -0
  236. meltygui/examples/tint_functions.py +56 -0
  237. meltygui/examples/trace_demo.py +88 -0
  238. meltygui/examples/two_windows.py +36 -0
  239. meltygui/files/__init__.py +0 -0
  240. meltygui/files/fast_file_explorer.py +439 -0
  241. meltygui/gnome_extension/lsd-window-geometry@latent-descent/extension.js +237 -0
  242. meltygui/gnome_extension/lsd-window-geometry@latent-descent/lsd-window-geometry@latent-descent.iml +9 -0
  243. meltygui/gnome_extension/lsd-window-geometry@latent-descent/metadata.json +7 -0
  244. meltygui/graphics/__init__.py +6 -0
  245. meltygui/graphics/base.py +85 -0
  246. meltygui/graphics/examples.py +507 -0
  247. meltygui/graphics/executor.py +520 -0
  248. meltygui/graphics/filter.py +667 -0
  249. meltygui/graphics/filter.pyi +856 -0
  250. meltygui/graphics/generate_stubs.py +22 -0
  251. meltygui/graphics/registry.py +203 -0
  252. meltygui/graphics/shader_compiler.py +155 -0
  253. meltygui/graphics/shaders.py +1302 -0
  254. meltygui/graphics/stub_generator.py +250 -0
  255. meltygui/graphics/texture_manager.py +170 -0
  256. meltygui/graphics/texture_min_max.py +295 -0
  257. meltygui/hdr_color.py +757 -0
  258. meltygui/image_load.py +308 -0
  259. meltygui/model/__init__.py +1 -0
  260. meltygui/model/account_model.py +142 -0
  261. meltygui/model/camera_model.py +159 -0
  262. meltygui/model/chat_model.py +86 -0
  263. meltygui/model/code_model.py +62 -0
  264. meltygui/model/code_proxy_model.py +876 -0
  265. meltygui/model/collection_model.py +41 -0
  266. meltygui/model/color_model.py +127 -0
  267. meltygui/model/cuda_tensor_model.py +36 -0
  268. meltygui/model/cuda_texture_model.py +149 -0
  269. meltygui/model/dropdown_model.py +137 -0
  270. meltygui/model/file_metadata_model.py +73 -0
  271. meltygui/model/file_model.py +289 -0
  272. meltygui/model/format_model.py +390 -0
  273. meltygui/model/graph_model.py +98 -0
  274. meltygui/model/icon_model.py +1024 -0
  275. meltygui/model/import_graph_model.py +468 -0
  276. meltygui/model/layout_model.py +15 -0
  277. meltygui/model/lut_model.py +266 -0
  278. meltygui/model/search_model.py +173 -0
  279. meltygui/model/tensor_model.py +402 -0
  280. meltygui/model/terminal_model.py +329 -0
  281. meltygui/model/texture_model.py +146 -0
  282. meltygui/model/tile_model.py +24 -0
  283. meltygui/model/trace_model.py +198 -0
  284. meltygui/model/trace_report_model.py +146 -0
  285. meltygui/models/__init__.py +0 -0
  286. meltygui/models/file_meta.py +613 -0
  287. meltygui/models/function_console.py +184 -0
  288. meltygui/models/orchestration.py +48 -0
  289. meltygui/pbr.py +1576 -0
  290. meltygui/png_unfilter.c +49 -0
  291. meltygui/resources/JetBrainsMono-Regular.ttf +0 -0
  292. meltygui/resources/THIRD_PARTY_NOTICES.md +21 -0
  293. meltygui/resources/dejavu/DejaVuSans-Bold.ttf +0 -0
  294. meltygui/resources/dejavu/DejaVuSans-ExtraLight.ttf +0 -0
  295. meltygui/resources/dejavu/DejaVuSans.ttf +0 -0
  296. meltygui/resources/dejavu/LICENSE.txt +78 -0
  297. meltygui/resources/fontawesome-LICENSE.txt +121 -0
  298. meltygui/resources/fontawesome-webfont.ttf +0 -0
  299. meltygui/resources/hdri/studio_small_09_1k.hdr +0 -0
  300. meltygui/resources/jetbrains-weights/JetBrainsMono-Bold.ttf +0 -0
  301. meltygui/resources/jetbrains-weights/JetBrainsMono-ExtraBold.ttf +0 -0
  302. meltygui/resources/jetbrains-weights/JetBrainsMono-ExtraLight.ttf +0 -0
  303. meltygui/resources/jetbrains-weights/JetBrainsMono-Light.ttf +0 -0
  304. meltygui/resources/jetbrains-weights/JetBrainsMono-Medium.ttf +0 -0
  305. meltygui/resources/jetbrains-weights/JetBrainsMono-SemiBold.ttf +0 -0
  306. meltygui/resources/jetbrains-weights/JetBrainsMono-Thin.ttf +0 -0
  307. meltygui/resources/jetbrains-weights/OFL.txt +93 -0
  308. meltygui/resources/jetbrains-weights/README.md +2 -0
  309. meltygui/state/__init__.py +0 -0
  310. meltygui/state/account_state.py +22 -0
  311. meltygui/state/animation_state.py +97 -0
  312. meltygui/state/annotation_state.py +22 -0
  313. meltygui/state/chat_state.py +36 -0
  314. meltygui/state/code_state.py +10 -0
  315. meltygui/state/core_enums.py +59 -0
  316. meltygui/state/core_markers.py +115 -0
  317. meltygui/state/core_undo.py +1075 -0
  318. meltygui/state/file_state.py +75 -0
  319. meltygui/state/graph_state.py +26 -0
  320. meltygui/state/inspection_state.py +47 -0
  321. meltygui/state/menu_state.py +10 -0
  322. meltygui/state/model_enums.py +11 -0
  323. meltygui/state/new_core_model.py +2394 -0
  324. meltygui/state/orchestration_state.py +14 -0
  325. meltygui/state/query_state.py +24 -0
  326. meltygui/state/tensor_state.py +10 -0
  327. meltygui/state/terminal_state.py +23 -0
  328. meltygui/state/trace_state.py +32 -0
  329. meltygui/state/voxel_state.py +12 -0
  330. meltygui/text_index.py +816 -0
  331. meltygui/utils/__init__.py +0 -0
  332. meltygui/utils/jump_to_code.py +344 -0
  333. meltygui/utils/pkl_inspect.py +90 -0
  334. meltygui/utils/render_utils.py +1419 -0
  335. meltygui/view/__init__.py +1 -0
  336. meltygui/view/account_view.py +524 -0
  337. meltygui/view/action_view.py +73 -0
  338. meltygui/view/chat_decoration_view.py +112 -0
  339. meltygui/view/chat_view.py +1703 -0
  340. meltygui/view/code_view.py +2677 -0
  341. meltygui/view/collection_view.py +1185 -0
  342. meltygui/view/color_view.py +824 -0
  343. meltygui/view/control_view.py +559 -0
  344. meltygui/view/decoration_view.py +439 -0
  345. meltygui/view/diagnostic_view.py +177 -0
  346. meltygui/view/dropdown_view.py +1082 -0
  347. meltygui/view/file_view.py +1599 -0
  348. meltygui/view/graph_cuda_view.py +105 -0
  349. meltygui/view/graph_view.py +882 -0
  350. meltygui/view/header_view.py +848 -0
  351. meltygui/view/input_view.py +238 -0
  352. meltygui/view/inspection_view.py +1783 -0
  353. meltygui/view/layout_view.py +596 -0
  354. meltygui/view/lut_view.py +45 -0
  355. meltygui/view/menu_view.py +212 -0
  356. meltygui/view/orchestration_view.py +658 -0
  357. meltygui/view/query_view.py +118 -0
  358. meltygui/view/search_view.py +342 -0
  359. meltygui/view/tab_view.py +258 -0
  360. meltygui/view/tensor_view.py +430 -0
  361. meltygui/view/terminal_view.py +355 -0
  362. meltygui/view/text_view.py +8031 -0
  363. meltygui/view/texture_view.py +480 -0
  364. meltygui/view/tile_view.py +38 -0
  365. meltygui/view/trace_view.py +923 -0
  366. meltygui/view/voxel_cuda_view.py +824 -0
  367. meltygui/view/voxel_view.py +1860 -0
  368. meltygui/view/window_view.py +111 -0
  369. meltygui-0.1.0.dist-info/METADATA +143 -0
  370. meltygui-0.1.0.dist-info/RECORD +372 -0
  371. meltygui-0.1.0.dist-info/WHEEL +4 -0
  372. meltygui-0.1.0.dist-info/licenses/LICENSE +202 -0
@@ -0,0 +1,19 @@
1
+ """Translate identifiers in older saved sessions to the canonical package."""
2
+ import json
3
+ from pathlib import Path
4
+
5
+ _MODULES = json.loads(Path(__file__).with_name('module_map.json').read_text())
6
+
7
+
8
+ def canonical_name(name):
9
+ parts = name.split('.')
10
+ for boundary in range(len(parts), 0, -1):
11
+ prefix = '.'.join(parts[:boundary])
12
+ if prefix in _MODULES:
13
+ return '.'.join([_MODULES[prefix], *parts[boundary:]])
14
+ return name
15
+
16
+
17
+ def register_names(names):
18
+ """Let application packages migrate their own persisted identifiers."""
19
+ _MODULES.update(names)
@@ -0,0 +1 @@
1
+ """Shared framework rendering machinery."""
@@ -0,0 +1,431 @@
1
+ import inspect
2
+
3
+
4
+ class _MockNode:
5
+ """A lazy reference to a location reachable from the mock meltygui, e.g.
6
+ ``meltygui.type_defaults[cls]`` or ``meltygui.cache.invalidate_up_by_obj``.
7
+
8
+ Attribute/item access returns further nodes so chains keep building; writes
9
+ (``__setattr__`` / ``__setitem__``) and calls (``__call__``) append an entry
10
+ to the shared op-log instead of touching anything real. ``path`` is the chain
11
+ of steps needed to reach this location from the meltygui root.
12
+ """
13
+
14
+ def __init__(self, ops, path):
15
+ object.__setattr__(self, "_ops", ops)
16
+ object.__setattr__(self, "_path", path)
17
+
18
+ def __getattr__(self, name):
19
+ if name.startswith("_"):
20
+ raise AttributeError(name)
21
+ return _MockNode(self._ops, self._path + (("attr", name),))
22
+
23
+ def __setattr__(self, name, value):
24
+ self._ops.append((self._path + (("attr", name),), "set", value))
25
+
26
+ def __getitem__(self, key):
27
+ return _MockNode(self._ops, self._path + (("item", key),))
28
+
29
+ def __setitem__(self, key, value):
30
+ self._ops.append((self._path + (("item", key),), "set", value))
31
+
32
+ # Without these, ``x in node`` falls back to the sequence protocol and calls
33
+ # __getitem__(0), __getitem__(1), ... forever (each returns a node, never
34
+ # IndexError) -> hang. A pre-init collection is empty: nothing is in it.
35
+ def __contains__(self, key):
36
+ return False
37
+
38
+ def __iter__(self):
39
+ return iter(())
40
+
41
+ def __call__(self, *args, **kwargs):
42
+ self._ops.append((self._path, "call", (args, kwargs)))
43
+ # Allow chaining off the return value (e.g. meltygui.foo(...).bar = x). The
44
+ # call's args travel with the step so replay can reproduce it faithfully.
45
+ return _MockNode(self._ops, self._path + (("call", args, kwargs),))
46
+
47
+
48
+ class MockMelty:
49
+ """Stand-in for ``Melty`` used before ``Melty.init()`` runs.
50
+
51
+ ``core_decoration.py`` must not import ``meltygui`` (circular import), so all
52
+ pre-init access to Melty — chiefly the ``@defaults`` decorator writing
53
+ ``type_defaults[cls] = meta`` at class-definition time — goes through this
54
+ recorder. Every write and call is appended to a flat op-log; ``replay``
55
+ re-applies that log against the real Melty during init so nothing done at
56
+ import/decoration time is lost.
57
+ """
58
+ def __init__(self):
59
+ # Each entry is (path, kind, payload):
60
+ # path - tuple of ("attr", name) / ("item", key) / ("call",) steps
61
+ # kind - "set" | "call"
62
+ # payload - the value (for "set") or (args, kwargs) (for "call")
63
+ object.__setattr__(self, "_ops", [])
64
+
65
+ def __getattr__(self, name):
66
+ if name.startswith("_"):
67
+ raise AttributeError(name)
68
+ return _MockNode(self._ops, (("attr", name),))
69
+
70
+ def __setattr__(self, name, value):
71
+ self._ops.append(((("attr", name),), "set", value))
72
+
73
+ @staticmethod
74
+ def _walk(target, path):
75
+ cur = target
76
+ for kind, *rest in path:
77
+ if kind == "attr":
78
+ cur = getattr(cur, rest[0])
79
+ elif kind == "item":
80
+ cur = cur[rest[0]]
81
+ elif kind == "call":
82
+ args, kwargs = rest
83
+ cur = cur(*args, **kwargs)
84
+ return cur
85
+
86
+ def _apply(self, target, path, kind, payload):
87
+ if kind == "set":
88
+ container = self._walk(target, path[:-1])
89
+ last_kind, last_arg = path[-1]
90
+ if last_kind == "attr":
91
+ setattr(container, last_arg, payload)
92
+ else: # item
93
+ container[last_arg] = payload
94
+ elif kind == "call":
95
+ fn = self._walk(target, path)
96
+ args, kwargs = payload
97
+ fn(*args, **kwargs)
98
+
99
+ def replay(self, target):
100
+ """Re-apply every recorded interaction against the real meltygui ``target``.
101
+
102
+ Best-effort: the only op that must land is ``@defaults`` writing
103
+ ``type_defaults[cls] = meta``. Other entries are incidental side effects
104
+ of pre-init read-chains (e.g. ``type_defaults.get(...)`` lookups or
105
+ live-attribute registration on objects built before init) — those re-run
106
+ naturally at runtime, so a failure to replay one is skipped, not fatal.
107
+ """
108
+ applied = skipped = 0
109
+ for path, kind, payload in self._ops:
110
+ try:
111
+ self._apply(target, path, kind, payload)
112
+ applied += 1
113
+ except Exception as exc:
114
+ skipped += 1
115
+ names = ".".join(str(s[1]) for s in path if len(s) > 1)
116
+ print(f"MockMelty.replay: skipped {kind} on '{names}': {exc!r}")
117
+ return applied, skipped
118
+
119
+
120
+ class Core:
121
+ melty = MockMelty()
122
+
123
+
124
+ def defaults(*args, **kwargs):
125
+ """Class decorator setting Meta defaults.
126
+
127
+ Without ``attr`` the Meta applies to the class itself (registered in
128
+ ``type_defaults``). With ``attr`` the remaining kwargs become the Meta for
129
+ that attribute, stored as ``{name}_meta`` on the class — exactly where
130
+ ``Meta.get_child_meta`` looks it up. ``attr`` accepts a single name or an
131
+ iterable of names sharing the same overrides:
132
+
133
+ @defaults(attr="some_attrib", show_tint=False, show_bg=True)
134
+ @defaults(show_name=True) # class-level default
135
+ class Foo: ...
136
+
137
+ ``attrib`` is accepted as an alias for ``attr``.
138
+ """
139
+ attr = kwargs.pop("attr", None)
140
+ if attr is None:
141
+ attr = kwargs.pop("attrib", None)
142
+ else:
143
+ kwargs.pop("attrib", None)
144
+
145
+ def decorator(cls):
146
+
147
+ # from meltygui.state.annotation_state import Meta
148
+ if attr is None:
149
+ # DecorationManager.melty.type_defaults[cls] = Meta(**kwargs)
150
+ for key in kwargs:
151
+ Core.melty.default_kwargs_by_type[cls][key] = kwargs[key]
152
+
153
+ else:
154
+ names = [attr] if isinstance(attr, str) else list(attr)
155
+ for name in names:
156
+ for key in kwargs:
157
+ Core.melty.default_kwargs_by_attrib_type[cls][name][key] = kwargs[key]
158
+ print(f"Registered default for {cls.__name__}.{name}: {key}={kwargs[key]}")
159
+ if key == "view_function" or key == "func":
160
+ Core.melty.default_funcs_by_name_type[cls][name] = kwargs[key]
161
+
162
+ # child_meta = Meta(**kwargs)
163
+ # child_meta.name = name
164
+ # setattr(cls, f"{name}_meta", child_meta)
165
+ return cls
166
+
167
+ return decorator
168
+
169
+
170
+ def attribute(func):
171
+ """Decorator that makes a method appear in __dict__"""
172
+ func._add_to_dict = True
173
+ return func
174
+
175
+ class auto_eval:
176
+ _add_to_dict = True # Class attribute
177
+
178
+ def __init__(self, fget=None, fset=None, fdel=None):
179
+ self.fget = fget
180
+ self._add_to_dict = True # Set on the instance
181
+ self.fset = fset
182
+ self.fdel = fdel
183
+ self.name = None
184
+ self.last_known_value = None
185
+
186
+
187
+ def __set_name__(self, owner, name):
188
+ self.name = name
189
+ self.private_name = f'_{name}'
190
+
191
+ def __get__(self, obj, objtype=None):
192
+ if obj is None:
193
+ self.last_known_value = None
194
+ return self
195
+
196
+ # Register on first access if not already registered
197
+ if obj not in Core.melty.live_attributes:
198
+ Core.melty.live_attributes[obj] = set()
199
+ if self.name not in Core.melty.live_attributes[obj]:
200
+ Core.melty.live_attributes[obj].add(self.name)
201
+
202
+ if self.fget is None:
203
+ new_val = obj.__dict__.get(self.private_name)
204
+ self._on_change(obj, self.last_known_value, new_val)
205
+ self.last_known_value = new_val
206
+ return new_val
207
+
208
+ new_val = self.fget(obj)
209
+ self._on_change(obj, self.last_known_value, new_val)
210
+ self.last_known_value = new_val
211
+ return new_val
212
+
213
+ def __set__(self, obj, value):
214
+ # Register on first set if not already registered
215
+ if obj not in Core.melty.live_attributes:
216
+ Core.melty.live_attributes[obj] = set()
217
+ if self.name not in Core.melty.live_attributes[obj]:
218
+ Core.melty.live_attributes[obj].add(self.name)
219
+
220
+ old_value = obj.__dict__.get(self.private_name)
221
+
222
+ if self.fset is None:
223
+ obj.__dict__[self.private_name] = value
224
+ else:
225
+ self.fset(obj, value)
226
+
227
+ # Your custom callback logic here
228
+ if old_value != value:
229
+ self._on_change(obj, old_value, value)
230
+
231
+ def __delete__(self, obj):
232
+ if self.fdel is None:
233
+ del obj.__dict__[self.private_name]
234
+ else:
235
+ self.fdel(obj)
236
+
237
+ def setter(self, fset):
238
+ return type(self)(self.fget, fset, self.fdel)
239
+
240
+ def deleter(self, fdel):
241
+ return type(self)(self.fget, self.fset, fdel)
242
+
243
+ def _on_change(self, obj, old_value, new_value):
244
+ from meltygui.core.windowing.glfw_utils import request_render
245
+ deep_refresh_names = getattr(self, '__deep_refresh__', set())
246
+
247
+ if Core.melty.silence_invalidate:
248
+ return
249
+
250
+ excluded = getattr(obj, '__excluded_attrs__', set())
251
+ invalidate_all_flag = getattr(self, '__invalidate_all__', set())
252
+
253
+ do_deep_refresh = self.name in deep_refresh_names and not Core.melty.window_drag
254
+ visible = self.name not in excluded
255
+ visible = visible or do_deep_refresh
256
+
257
+ if self.name in invalidate_all_flag:
258
+ Core.melty.cache.invalidate_all()
259
+ print(f"Invalidate all called due to change in {self.name}")
260
+ request_render()
261
+ return
262
+
263
+ if old_value != new_value:
264
+ if visible and not self.name.startswith('_') \
265
+ and self.name != "driver" and Core.melty.frame_count > 3:
266
+ Core.melty.last_attr = self.name
267
+ from meltygui.core.cache.invalidation_tracker import Note
268
+ if do_deep_refresh:
269
+ note = Note(name="Core decoration", reason="invalidate_up_by_obj", tint=(0, 0, 1))
270
+ Core.melty.cache.invalidate_up_by_obj(obj=obj, name=self.name, max_depth=6, force=True, note=note)
271
+ request_render()
272
+
273
+ if hasattr(self, "context_menu_ds"):
274
+ print(f"Context menu ds found, invalidating {self.name}")
275
+ else:
276
+ note = Note(name="Core decoration", reason="invalidate_up_by_obj", tint=(0, 0, 1))
277
+
278
+ Core.melty.cache.invalidate_up_by_obj(obj, self.name, max_depth=3, note=note)
279
+ request_render()
280
+
281
+
282
+
283
+ """Override this or add your universal callback logic here"""
284
+
285
+
286
+ def setter(self, fset):
287
+ return type(self)(self.fget, fset, self.fdel)
288
+
289
+ def deleter(self, fdel):
290
+ return type(self)(self.fget, self.fset, fdel)
291
+
292
+
293
+ def deep_refresh(*args, **kwargs):
294
+ def decorator(cls):
295
+ if len(args) == 1 and isinstance(args[0], (list, set, tuple)):
296
+ from_args = args[0]
297
+ else:
298
+ from_args = set(args)
299
+ already_excluded = getattr(cls, '__deep_refresh__', set())
300
+ merged_names = already_excluded.union(set(from_args))
301
+ merged_names = merged_names.union(from_args)
302
+
303
+ setattr(cls, '__deep_refresh__', merged_names)
304
+ return cls
305
+
306
+ return decorator
307
+ #
308
+ # def tint(*args, **kwargs):
309
+ # def decorator(cls):
310
+ # if len(args) == 1 and isinstance(args[0], (list, set, tuple, dict)):
311
+ # from_args = args[0]
312
+ # setattr(cls, '__tint__', from_args)
313
+ # return cls
314
+ #
315
+ # return decorator
316
+
317
+ def invalidate_all(*args, **kwargs):
318
+ def decorator(cls):
319
+ if len(args) == 1 and isinstance(args[0], (list, set, tuple)):
320
+ from_args = args[0]
321
+ else:
322
+ from_args = set(args)
323
+ already_excluded = getattr(cls, '__invalidate_all__', set())
324
+ merged_names = already_excluded.union(set(from_args))
325
+ merged_names = merged_names.union(from_args)
326
+
327
+ setattr(cls, '__invalidate_all__', merged_names)
328
+ return cls
329
+
330
+ return decorator
331
+
332
+ global_hotkeys = {}
333
+
334
+ def no_save(*args, **kwargs):
335
+ def decorator(cls):
336
+ if len(args) == 1 and isinstance(args[0], (list, set, tuple)):
337
+ from_args = args[0]
338
+ else:
339
+ from_args = set(args)
340
+ already_excluded = getattr(cls, '__no_save__', set())
341
+ merged_names = already_excluded.union(set(from_args))
342
+ merged_names = merged_names.union(from_args)
343
+
344
+ setattr(cls, '__no_save__', merged_names)
345
+ return cls
346
+
347
+ return decorator
348
+
349
+
350
+ def exclude(*args, **kwargs):
351
+ def decorator(cls):
352
+ if len(args) == 1 and isinstance(args[0], (list, set, tuple)):
353
+ from_args = args[0]
354
+ else:
355
+ from_args = set(args)
356
+ already_excluded = getattr(cls, '__excluded_attrs__', set())
357
+ merged_names = already_excluded.union(set(from_args))
358
+ merged_names = merged_names.union(from_args)
359
+
360
+ setattr(cls, '__excluded_attrs__', merged_names)
361
+ return cls
362
+
363
+ return decorator
364
+
365
+
366
+ def no_save_exclude(*args, **kwargs):
367
+ def decorator(cls):
368
+ if len(args) == 1 and isinstance(args[0], (list, set, tuple)):
369
+ from_args = args[0]
370
+ else:
371
+ from_args = set(args)
372
+ already_excluded = getattr(cls, '__excluded_attrs__', set())
373
+ merged_names = already_excluded.union(set(from_args))
374
+ merged_names = merged_names.union(from_args)
375
+ setattr(cls, '__excluded_attrs__', merged_names)
376
+
377
+ already_no_save = getattr(cls, '__no_save__', set())
378
+ merged_names_ns = already_no_save.union(set(from_args))
379
+ merged_names_ns = merged_names_ns.union(from_args)
380
+
381
+ setattr(cls, '__no_save__', merged_names_ns)
382
+
383
+ return cls
384
+
385
+ return decorator
386
+
387
+
388
+
389
+ def hotkey(key):
390
+ """
391
+ This is the decorator factory. It takes arguments for the decorator.
392
+ """
393
+
394
+ def actual_decorator(func):
395
+ """
396
+ This is the actual decorator. It takes the function to be decorated.
397
+ """
398
+ sig = inspect.signature(func)
399
+ params = sig.parameters
400
+
401
+ if isinstance(key, int):
402
+ from meltygui.state.new_core_model import Hotkey
403
+ the_hotkey = Hotkey(key=key)
404
+ else:
405
+ the_hotkey = key
406
+
407
+
408
+ def wrapper(*args, **kwargs):
409
+ to_remove = []
410
+ for name, arg in kwargs.items():
411
+ if name not in params:
412
+ to_remove.append(name)
413
+ for name in to_remove:
414
+ kwargs.pop(name)
415
+
416
+ for wanted_name, param in params.items():
417
+ if wanted_name in Core.melty.global_attrs and wanted_name not in kwargs:
418
+ kwargs[wanted_name] = Core.melty.global_attrs[wanted_name]
419
+
420
+ result = func(*args, **kwargs) # Call the original function
421
+ return result
422
+
423
+ if hotkey in global_hotkeys:
424
+ print(f"Warning: hotkey '{hotkey}' is already registered to "
425
+ f"{global_hotkeys[hotkey].__name__}, overwriting with {func.__name__}")
426
+ global_hotkeys[the_hotkey] = wrapper
427
+
428
+ return wrapper
429
+
430
+ return actual_decorator
431
+