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,533 @@
1
+ """
2
+ Usage examples for the Melty converter system + auto-chaining.
3
+
4
+ This file includes a minimal registry and @converter decorator so
5
+ everything runs standalone. Replace with your real implementation.
6
+ """
7
+
8
+ from types import SimpleNamespace, ModuleType
9
+ from datetime import datetime, timedelta
10
+ from decimal import Decimal
11
+ from fractions import Fraction
12
+ from enum import Enum
13
+ from typing import Any
14
+
15
+ from meltygui.core.melty import Melty
16
+ from meltygui.code.libcst_conversion import register
17
+ from meltygui.core.conversion.path_finder import convert
18
+ from meltygui.core.conversion.path_finder import explain_chain
19
+ from meltygui.core.conversion.path_finder import all_paths
20
+ from meltygui.core.conversion.path_finder import all_reachable_from
21
+ from meltygui.core.conversion.path_finder import T
22
+
23
+
24
+ # ╔══════════════════════════════════════════════════════════════════════════════╗
25
+ # ║ Define a subset of converters (enough to show interesting chains) ║
26
+ # ╚══════════════════════════════════════════════════════════════════════════════╝
27
+
28
+ @register
29
+ def int_to_str(value: int) -> str:
30
+ return str(value)
31
+
32
+
33
+ @register
34
+ def str_to_int(value: str) -> int:
35
+ return int(value.strip())
36
+
37
+
38
+ @register
39
+ def float_to_str(value: float) -> str:
40
+ return str(value)
41
+
42
+
43
+ @register
44
+ def str_to_float(value: str) -> float:
45
+ return float(value.strip().replace(",", ""))
46
+
47
+
48
+ @register
49
+ def int_to_float(value: int) -> float:
50
+ return float(value)
51
+
52
+
53
+ @register
54
+ def float_to_int(value: float) -> int:
55
+ return int(value)
56
+
57
+
58
+ @register
59
+ def float_to_decimal(value: float) -> Decimal:
60
+ return Decimal(str(value))
61
+
62
+
63
+ @register
64
+ def decimal_to_float(value: Decimal) -> float:
65
+ return float(value)
66
+
67
+
68
+ @register
69
+ def str_to_decimal(value: str) -> Decimal:
70
+ return Decimal(value.strip())
71
+
72
+
73
+ @register
74
+ def decimal_to_str(value: Decimal) -> str:
75
+ return str(value)
76
+
77
+
78
+ @register
79
+ def float_to_fraction(value: float) -> Fraction:
80
+ return Fraction(value).limit_denominator()
81
+
82
+
83
+ @register
84
+ def fraction_to_float(value: Fraction) -> float:
85
+ return float(value)
86
+
87
+
88
+ @register
89
+ def str_to_bytes(value: str) -> bytes:
90
+ return value.encode("utf-8")
91
+
92
+
93
+ @register
94
+ def bytes_to_str(value: bytes) -> str:
95
+ return value.decode("utf-8")
96
+
97
+
98
+ @register
99
+ def int_to_datetime(value: int) -> datetime:
100
+ return datetime.fromtimestamp(value)
101
+
102
+
103
+ @register
104
+ def datetime_to_int(value: datetime) -> int:
105
+ return int(value.timestamp())
106
+
107
+
108
+ @register
109
+ def datetime_to_str(value: datetime) -> str:
110
+ return value.isoformat()
111
+
112
+
113
+ @register
114
+ def str_to_datetime(value: str) -> datetime:
115
+ return datetime.fromisoformat(value.strip())
116
+
117
+
118
+ @register
119
+ def int_to_timedelta(value: int) -> timedelta:
120
+ return timedelta(seconds=value)
121
+
122
+
123
+ @register
124
+ def timedelta_to_int(value: timedelta) -> int:
125
+ return int(value.total_seconds())
126
+
127
+
128
+ @register
129
+ def dict_to_str(value: dict) -> str:
130
+ import json
131
+ return json.dumps(value, indent=2, default=str)
132
+
133
+
134
+ @register
135
+ def str_to_dict(value: str) -> dict:
136
+ import json
137
+ return json.loads(value)
138
+
139
+
140
+ @register
141
+ def list_to_dict(value: list) -> dict:
142
+ return dict(value)
143
+
144
+
145
+ @register
146
+ def dict_to_list(value: dict) -> list:
147
+ return [list(pair) for pair in value.items()]
148
+
149
+
150
+ @register
151
+ def dict_to_namespace(value: dict) -> SimpleNamespace:
152
+ return SimpleNamespace(**value)
153
+
154
+
155
+ @register
156
+ def namespace_to_dict(value: SimpleNamespace) -> dict:
157
+ return vars(value).copy()
158
+
159
+
160
+ @register
161
+ def list_to_tuple(value: list) -> tuple:
162
+ return tuple(value)
163
+
164
+
165
+ @register
166
+ def tuple_to_list(value: tuple) -> list:
167
+ return list(value)
168
+
169
+
170
+ @register
171
+ def list_to_set(value: list) -> set:
172
+ return set(value)
173
+
174
+
175
+ @register
176
+ def set_to_list(value: set) -> list:
177
+ return sorted(value, key=repr)
178
+
179
+
180
+ @register
181
+ def exception_to_dict(value: Exception) -> dict:
182
+ return {
183
+ "__type__": type(value).__name__,
184
+ "__str__": str(value),
185
+ "args": [repr(a) for a in value.args],
186
+ }
187
+
188
+
189
+ """
190
+ Reversible object ↔ dict converters.
191
+
192
+ object_to_dict puts actual attributes as top-level dict keys so they
193
+ display naturally in a UI. Reconstruction metadata is tucked under
194
+ a single "__meta__" key that the UI filters out.
195
+
196
+ dict_to_object tries to instantiate the real class, falling back to
197
+ SimpleNamespace if the class can't be found or constructed.
198
+ """
199
+
200
+ import sys
201
+ from types import SimpleNamespace
202
+
203
+
204
+ def _serialize_value(v):
205
+ """Store the actual value when possible, fall back to a tagged repr."""
206
+ if v is None or isinstance(v, (str, int, float, bool)):
207
+ return v
208
+ if isinstance(v, (list, tuple, set, frozenset)):
209
+ converted = [_serialize_value(x) for x in v]
210
+ if isinstance(v, tuple):
211
+ return {"__type__": "tuple", "__items__": converted}
212
+ if isinstance(v, set):
213
+ return {"__type__": "set", "__items__": converted}
214
+ if isinstance(v, frozenset):
215
+ return {"__type__": "frozenset", "__items__": converted}
216
+ return converted
217
+ if isinstance(v, dict):
218
+ return {"__type__": "dict", "__items__": {str(k): _serialize_value(val) for k, val in v.items()}}
219
+ return {"__type__": "repr", "__repr__": repr(v), "__class__": type(v).__qualname__}
220
+
221
+
222
+ def _deserialize_value(v):
223
+ """Reverse of _serialize_value."""
224
+ if v is None or isinstance(v, (str, int, float, bool)):
225
+ return v
226
+ if isinstance(v, list):
227
+ return [_deserialize_value(x) for x in v]
228
+ if isinstance(v, dict):
229
+ tag = v.get("__type__")
230
+ if tag == "tuple":
231
+ return tuple(_deserialize_value(x) for x in v["__items__"])
232
+ if tag == "set":
233
+ return set(_deserialize_value(x) for x in v["__items__"])
234
+ if tag == "frozenset":
235
+ return frozenset(_deserialize_value(x) for x in v["__items__"])
236
+ if tag == "dict":
237
+ return {k: _deserialize_value(val) for k, val in v["__items__"].items()}
238
+ if tag == "repr":
239
+ try:
240
+ return eval(v["__repr__"]) # noqa: S307
241
+ except Exception:
242
+ return v["__repr__"]
243
+ return {k: _deserialize_value(val) for k, val in v.items()}
244
+ return v
245
+
246
+
247
+ @register
248
+ def object_to_dict(value: object) -> dict:
249
+ """Generic object → dict with attributes as top-level keys.
250
+
251
+ The dict looks like:
252
+ {
253
+ "color": "red",
254
+ "size": 42,
255
+ "items": [1, 2, 3],
256
+ "__meta__": {"__type__": "Widget", "__module__": "my_app.models"}
257
+ }
258
+
259
+ The UI sees color, size, items. __meta__ is filtered out by
260
+ the dunder convention but carries everything needed for dict_to_object.
261
+ """
262
+ cls = type(value)
263
+ result = {}
264
+
265
+ # Value types (int, float, str, bool, bytearray, bytes, etc.) don't
266
+ # store their payload in __dict__ or __slots__ - it lives in the
267
+ # C struct. Capture it explicitly so the round-trip preserves it.
268
+ _VALUE_TYPES = (int, float, str, bool, bytes, bytearray, complex)
269
+ if isinstance(value, _VALUE_TYPES):
270
+ result["value"] = value
271
+
272
+ # Hoist __dict__ attributes to top level
273
+ if hasattr(value, "__dict__"):
274
+ for k, v in value.__dict__.items():
275
+ if k.startswith("__") and k.endswith("__"):
276
+ continue
277
+ result[k] = _serialize_value(v)
278
+
279
+ # Hoist __slots__ attributes to top level
280
+ slots = set()
281
+ for klass in cls.__mro__:
282
+ slots.update(getattr(klass, "__slots__", ()))
283
+ for s in sorted(slots):
284
+ if s.startswith("__") and s.endswith("__"):
285
+ continue
286
+ try:
287
+ result[s] = _serialize_value(getattr(value, s))
288
+ except AttributeError:
289
+ pass
290
+
291
+ # Tuck reconstruction metadata under a single dunder key
292
+ result["__meta__"] = {
293
+ "__type__": cls.__qualname__,
294
+ "__module__": cls.__module__,
295
+ }
296
+
297
+ return result
298
+
299
+
300
+ @register
301
+ def dict_to_object(value: dict) -> object:
302
+ """Reconstruct an object from an object_to_dict snapshot.
303
+
304
+ Resolution strategy:
305
+ 1. Look up the real class from __meta__.__module__ + __meta__.__type__
306
+ 2. Instantiate with __new__ (bypassing __init__) and set attributes
307
+ 3. Fall back to SimpleNamespace if the class can't be found
308
+ """
309
+ meta = value.get("__meta__", {})
310
+ type_name = meta.get("__type__", "Unknown")
311
+ module_name = meta.get("__module__", "")
312
+
313
+ # Everything except dunders is an attribute to restore
314
+ attrs = {k: _deserialize_value(v) for k, v in value.items()
315
+ if not (k.startswith("__") and k.endswith("__"))}
316
+
317
+ # Try to find and instantiate the real class
318
+ cls = _resolve_class(module_name, type_name)
319
+ if cls is not None:
320
+ try:
321
+ # Value types (int, float, str, etc.) need the value passed
322
+ # to the constructor - you can't instantiate them via __new__
323
+ if "value" in attrs and issubclass(cls, (int, float, str, bool, bytes, bytearray, complex)):
324
+ obj = cls(attrs.pop("value"))
325
+ # Subclasses of builtins might still have other attrs
326
+ for k, v in attrs.items():
327
+ setattr(obj, k, v)
328
+ return obj
329
+
330
+ obj = cls.__new__(cls)
331
+ for k, v in attrs.items():
332
+ setattr(obj, k, v)
333
+ return obj
334
+ except Exception:
335
+ pass
336
+
337
+ # Fallback
338
+ ns = SimpleNamespace(**attrs)
339
+ ns.__original_type__ = type_name
340
+ ns.__original_module__ = module_name
341
+ return ns
342
+
343
+
344
+ def _resolve_class(module_name: str, qualname: str):
345
+ """Try to find a class by module + qualname, handling nested classes."""
346
+ mod = sys.modules.get(module_name)
347
+ if mod is None:
348
+ return None
349
+ obj = mod
350
+ for part in qualname.split("."):
351
+ obj = getattr(obj, part, None)
352
+ if obj is None:
353
+ return None
354
+ return obj if isinstance(obj, type) else None
355
+
356
+ #
357
+ # @register
358
+ # def float_to_dict(value: float) -> dict:
359
+ # return {
360
+ # "value": value,
361
+ # }
362
+ #
363
+ # @register
364
+ # def dict_to_float(value: dict) -> float:
365
+ # return float(value["value"])
366
+
367
+
368
+ # ╔══════════════════════════════════════════════════════════════════════════════╗
369
+ # ║ Import the chaining system ║
370
+ # ╚══════════════════════════════════════════════════════════════════════════════╝
371
+
372
+ # Assuming chaining.py is in the same directory or on the path.
373
+ # Adjust the import to match your setup.
374
+
375
+
376
+ def section(title: str):
377
+ print(f"\n{'─' * 60}")
378
+ print(f" {title}")
379
+ print(f"{'─' * 60}")
380
+
381
+
382
+ # ╔══════════════════════════════════════════════════════════════════════════════╗
383
+ # ║ Examples ║
384
+ # ╚══════════════════════════════════════════════════════════════════════════════╝
385
+ #
386
+ # if __name__ == "__main__":
387
+ #
388
+ # print(f"Registry: {Melty}")
389
+ #
390
+ # # ── 1. Direct conversions (single hop) ───────────────────────────
391
+ #
392
+ # section("Direct conversions")
393
+ #
394
+ # print(f" int → str: {convert(42, str, registry=Melty)!r}")
395
+ # print(f" str → float: {convert('3.14', float, registry=Melty)!r}")
396
+ # print(f" float → Decimal: {convert(0.1, Decimal, registry=Melty)!r}")
397
+ # print(f" int → datetime: {convert(0, datetime, registry=Melty)!r}")
398
+ #
399
+ # # ── 2. Auto-chained conversions (multi-hop) ─────────────────────
400
+ #
401
+ # section("Auto-chained conversions")
402
+ #
403
+ # # int → float → Decimal (no direct int→Decimal registered)
404
+ # result = convert(42, Decimal, registry=Melty)
405
+ # print(f" int → Decimal: {result!r} (type: {type(result).__name__})")
406
+ # print(f" chain: {explain_chain(int, Decimal, registry=Melty)}")
407
+ #
408
+ # # int → float → Fraction
409
+ # result = convert(3, Fraction, registry=Melty)
410
+ # print(f" int → Fraction: {result!r}")
411
+ # print(f" chain: {explain_chain(int, Fraction, registry=Melty)}")
412
+ #
413
+ # # int → str → bytes
414
+ # result = convert(12345, bytes, registry=Melty)
415
+ # print(f" int → bytes: {result!r}")
416
+ # print(f" chain: {explain_chain(int, bytes, registry=Melty)}")
417
+ #
418
+ # # int → str → dict (via JSON - "42" isn't valid JSON, but timestamps are fun)
419
+ # # Let's do datetime → str → dict instead
420
+ # # Actually: int → datetime → str
421
+ # result = convert(1700000000, str, registry=Melty)
422
+ # print(f" int → str: {result!r} (direct)")
423
+ #
424
+ # # ── 3. Longer chains ─────────────────────────────────────────────
425
+ #
426
+ # section("Longer chains")
427
+ #
428
+ # # dict → str → bytes
429
+ # data = {"name": "Alice", "balance": 100}
430
+ # result = convert(data, bytes, registry=Melty)
431
+ # print(f" dict → bytes: {result[:50]!r}...")
432
+ # print(f" chain: {explain_chain(dict, bytes, registry=Melty)}")
433
+ #
434
+ # # dict → SimpleNamespace (direct)
435
+ # ns = convert({"x": 1, "y": 2}, SimpleNamespace, registry=Melty)
436
+ # print(f" dict → NS: {ns!r}")
437
+ #
438
+ # # dict → list → tuple
439
+ # result = convert({"a": 1, "b": 2}, tuple, registry=Melty)
440
+ # print(f" dict → tuple: {result!r}")
441
+ # print(f" chain: {explain_chain(dict, tuple, registry=Melty)}")
442
+ #
443
+ # # tuple → list → set
444
+ # result = convert((3, 1, 4, 1, 5, 9), set, registry=Melty)
445
+ # print(f" tuple → set: {result!r}")
446
+ # print(f" chain: {explain_chain(tuple, set, registry=Melty)}")
447
+ #
448
+ # # ── 4. Subclass resolution ───────────────────────────────────────
449
+ #
450
+ # section("Subclass resolution")
451
+ #
452
+ # # ValueError is a subclass of Exception - should hit Exception→dict
453
+ # err = ValueError("something broke")
454
+ # result = convert(err, dict, registry=Melty)
455
+ # print(f" ValueError → dict: {result}")
456
+ # print(f" chain: {explain_chain(ValueError, dict, registry=Melty)}")
457
+ #
458
+ # # And longer chain down: ValueError → dict → str
459
+ # result = convert(err, str, registry=Melty)
460
+ # print(f" ValueError → str: {result[:60]!r}...")
461
+ # print(f" chain: {explain_chain(ValueError, str, registry=Melty)}")
462
+ #
463
+ #
464
+ # # A custom type hits object→dict via MRO
465
+ # class Widget:
466
+ # def __init__(self, color, size):
467
+ # self.color = color
468
+ # self.size = size
469
+ #
470
+ #
471
+ # w = Widget("red", 42)
472
+ # result = convert(w, dict, registry=Melty)
473
+ # print(f" Widget → dict: {result}")
474
+ # print(f" chain: {explain_chain(Widget, dict, registry=Melty)}")
475
+ #
476
+ # # Widget → dict → str
477
+ # result = convert(w, str, registry=Melty)
478
+ # print(f" Widget → str: {result[:60]!r}...")
479
+ #
480
+ # # Widget → dict → SimpleNamespace
481
+ # result = convert(w, SimpleNamespace, registry=Melty)
482
+ # print(f" Widget → NS: {result!r}")
483
+ # print(f" chain: {explain_chain(Widget, SimpleNamespace, registry=Melty)}")
484
+ #
485
+ # # ── 5. Round-trip demonstration ──────────────────────────────────
486
+ #
487
+ # section("Round-trips (showing lossy-ness)")
488
+ #
489
+ # original = 3.14159
490
+ # as_fraction = convert(original, Fraction, registry=Melty)
491
+ # back = convert(as_fraction, float, registry=Melty)
492
+ # print(f" float → Fraction → float: {original} → {as_fraction} → {back}")
493
+ # print(f" lost precision: {original != back}")
494
+ #
495
+ # original_dt = datetime(2024, 6, 15, 12, 30, 45)
496
+ # as_int = convert(original_dt, int, registry=Melty)
497
+ # back_dt = convert(as_int, datetime, registry=Melty)
498
+ # print(f" datetime → int → datetime: {original_dt} → {as_int} → {back_dt}")
499
+ # print(f" lost subsecond: {original_dt != back_dt}")
500
+ #
501
+ # # ── 6. Introspection tools ───────────────────────────────────────
502
+ #
503
+ # section("Introspection: all_reachable_from(int)")
504
+ #
505
+ # reachable = all_reachable_from(int, registry=Melty)
506
+ # print(f" int can reach {len(reachable)} types:")
507
+ # for t in sorted(reachable, key=lambda t: t.__name__):
508
+ # print(f" → {t.__name__}")
509
+ #
510
+ # section("Introspection: all_paths(int, bytes)")
511
+ #
512
+ # paths = all_paths(int, bytes, registry=Melty)
513
+ # for i, p in enumerate(paths):
514
+ # names = " → ".join(t.__name__ for t in p)
515
+ # print(f" path {i + 1} ({len(p) - 1} hops): {names}")
516
+ #
517
+ # section("Introspection: all_paths(tuple, set)")
518
+ #
519
+ # paths = all_paths(tuple, set, registry=Melty)
520
+ # for i, p in enumerate(paths):
521
+ # names = " → ".join(t.__name__ for t in p)
522
+ # print(f" path {i + 1} ({len(p) - 1} hops): {names}")
523
+ #
524
+ # # ── 7. Error case ────────────────────────────────────────────────
525
+ #
526
+ # section("Error: no path exists")
527
+ #
528
+ # try:
529
+ # convert(42, ModuleType, registry=Melty)
530
+ # except TypeError as e:
531
+ # print(f" {e}")
532
+ #
533
+ # print()