pytron-kit 0.3.12__py3-none-macosx_11_0_universal2.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.
- pytron/__init__.py +112 -0
- pytron/application.py +562 -0
- pytron/apputils/__init__.py +0 -0
- pytron/apputils/chrome_ipc.py +203 -0
- pytron/apputils/codegen.py +261 -0
- pytron/apputils/config.py +303 -0
- pytron/apputils/deadmansswitch.py +47 -0
- pytron/apputils/extras.py +76 -0
- pytron/apputils/native.py +148 -0
- pytron/apputils/shell.py +73 -0
- pytron/apputils/windows.py +286 -0
- pytron/cli.py +384 -0
- pytron/commands/__init__.py +0 -0
- pytron/commands/android.py +28 -0
- pytron/commands/build.py +26 -0
- pytron/commands/doctor.py +221 -0
- pytron/commands/engine.py +23 -0
- pytron/commands/frontend.py +60 -0
- pytron/commands/harvest.py +112 -0
- pytron/commands/helpers.py +239 -0
- pytron/commands/info.py +50 -0
- pytron/commands/init.py +521 -0
- pytron/commands/install.py +294 -0
- pytron/commands/login.py +130 -0
- pytron/commands/package.py +228 -0
- pytron/commands/plugin.py +442 -0
- pytron/commands/run.py +312 -0
- pytron/commands/scan.py +210 -0
- pytron/commands/show.py +23 -0
- pytron/commands/uninstall.py +150 -0
- pytron/commands/utils.py +42 -0
- pytron/commands/workflow.py +95 -0
- pytron/console.py +133 -0
- pytron/core.py +18 -0
- pytron/dependencies/WebView2Loader.dll +0 -0
- pytron/dependencies/__init__.py +1 -0
- pytron/dependencies/pytron_native.so +0 -0
- pytron/engines/chrome/adapter.py +445 -0
- pytron/engines/chrome/engine.py +576 -0
- pytron/engines/chrome/forge.py +147 -0
- pytron/engines/chrome/shell/package.json +8 -0
- pytron/engines/chrome/shell/preload.js +12 -0
- pytron/engines/chrome/shell/shell.js +534 -0
- pytron/exceptions.py +36 -0
- pytron/inspector.py +201 -0
- pytron/inspector_ui.py +512 -0
- pytron/installer/Installation.nsi +236 -0
- pytron/installer/header.bmp +0 -0
- pytron/installer/pytron.ico +0 -0
- pytron/installer/sidebar.bmp +0 -0
- pytron/llms.md +98 -0
- pytron/manifests/README.md +29 -0
- pytron/manifests/windows-utf8.manifest +44 -0
- pytron/menu.py +128 -0
- pytron/nsis-setup.exe +0 -0
- pytron/pack/__init__.py +0 -0
- pytron/pack/assets.py +131 -0
- pytron/pack/compilers.py +289 -0
- pytron/pack/crystal.py +297 -0
- pytron/pack/graph.py +377 -0
- pytron/pack/inference.py +157 -0
- pytron/pack/installers.py +402 -0
- pytron/pack/introspect.py +357 -0
- pytron/pack/metadata.py +213 -0
- pytron/pack/modules.py +618 -0
- pytron/pack/nuitka.py +108 -0
- pytron/pack/pipeline.py +107 -0
- pytron/pack/pyinstaller.py +176 -0
- pytron/pack/rust_engine.py +273 -0
- pytron/pack/secure.py +309 -0
- pytron/pack/secure_loader/bin/pytron_rust_bootloader +0 -0
- pytron/pack/secure_loader/icon.ico +0 -0
- pytron/pack/utils.py +110 -0
- pytron/pack/virtual_root.py +124 -0
- pytron/platforms/__init__.py +0 -0
- pytron/platforms/android/__init__.py +3 -0
- pytron/platforms/android/android.py +103 -0
- pytron/platforms/android/builder.py +736 -0
- pytron/platforms/android/ops/build.py +79 -0
- pytron/platforms/android/ops/init.py +63 -0
- pytron/platforms/android/ops/run.py +79 -0
- pytron/platforms/android/ops/sync.py +770 -0
- pytron/platforms/android/ops/utils.py +8 -0
- pytron/platforms/android/shell/README.md +30 -0
- pytron/platforms/android/shell/app/build.gradle +64 -0
- pytron/platforms/android/shell/app/src/main/AndroidManifest.xml +29 -0
- pytron/platforms/android/shell/app/src/main/assets/python/main.py +86 -0
- pytron/platforms/android/shell/app/src/main/assets/python/python314.zip +0 -0
- pytron/platforms/android/shell/app/src/main/cpp/CMakeLists.txt +25 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/Python.h +155 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/abstract.h +915 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/audit.h +30 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/bltinmodule.h +14 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/boolobject.h +54 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/bytearrayobject.h +44 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/bytesobject.h +66 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/ceval.h +145 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/codecs.h +176 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/compile.h +22 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/complexobject.h +30 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/cpython/abstract.h +104 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/cpython/audit.h +8 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/cpython/bytearrayobject.h +38 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/cpython/bytesobject.h +42 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/cpython/cellobject.h +50 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/cpython/ceval.h +43 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/cpython/classobject.h +71 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/cpython/code.h +340 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/cpython/compile.h +50 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/cpython/complexobject.h +33 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/cpython/context.h +107 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/cpython/critical_section.h +154 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/cpython/descrobject.h +62 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/cpython/dictobject.h +105 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/cpython/fileobject.h +16 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/cpython/fileutils.h +16 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/cpython/floatobject.h +27 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/cpython/frameobject.h +35 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/cpython/funcobject.h +185 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/cpython/genobject.h +56 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/cpython/import.h +30 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/cpython/initconfig.h +334 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/cpython/listobject.h +53 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/cpython/lock.h +74 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/cpython/longintrepr.h +184 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/cpython/longobject.h +89 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/cpython/memoryobject.h +50 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/cpython/methodobject.h +66 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/cpython/modsupport.h +26 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/cpython/monitoring.h +269 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/cpython/object.h +493 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/cpython/objimpl.h +104 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/cpython/odictobject.h +43 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/cpython/picklebufobject.h +31 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/cpython/pthread_stubs.h +105 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/cpython/pyatomic.h +614 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/cpython/pyatomic_gcc.h +615 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/cpython/pyatomic_msc.h +1197 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/cpython/pyatomic_std.h +1112 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/cpython/pyctype.h +39 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/cpython/pydebug.h +38 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/cpython/pyerrors.h +132 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/cpython/pyfpe.h +15 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/cpython/pyframe.h +45 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/cpython/pyhash.h +54 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/cpython/pylifecycle.h +89 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/cpython/pymem.h +84 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/cpython/pystate.h +275 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/cpython/pystats.h +194 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/cpython/pythonrun.h +96 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/cpython/pythread.h +43 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/cpython/pytime.h +27 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/cpython/setobject.h +71 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/cpython/traceback.h +13 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/cpython/tracemalloc.h +32 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/cpython/tupleobject.h +40 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/cpython/unicodeobject.h +773 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/cpython/warnings.h +20 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/cpython/weakrefobject.h +66 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/critical_section.h +16 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/datetime.h +267 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/descrobject.h +100 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/dictobject.h +108 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/dynamic_annotations.h +499 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/enumobject.h +17 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/errcode.h +45 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/exports.h +105 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/fileobject.h +41 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/fileutils.h +62 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/floatobject.h +54 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/frameobject.h +20 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/genericaliasobject.h +14 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/import.h +103 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/mimalloc/mimalloc/atomic.h +392 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/mimalloc/mimalloc/internal.h +969 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/mimalloc/mimalloc/prim.h +329 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/mimalloc/mimalloc/track.h +147 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/mimalloc/mimalloc/types.h +721 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/mimalloc/mimalloc.h +565 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_abstract.h +61 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_asdl.h +112 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_ast.h +945 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_ast_state.h +271 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_atexit.h +31 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_audit.h +35 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_backoff.h +133 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_bitutils.h +186 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_blocks_output_buffer.h +321 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_brc.h +73 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_bytes_methods.h +82 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_bytesobject.h +149 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_c_array.h +39 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_call.h +206 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_capsule.h +17 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_cell.h +75 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_ceval.h +390 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_ceval_state.h +48 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_code.h +671 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_codecs.h +76 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_compile.h +230 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_complexobject.h +34 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_condvar.h +93 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_context.h +59 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_critical_section.h +237 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_crossinterp.h +406 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_crossinterp_data_registry.h +41 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_debug_offsets.h +379 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_descrobject.h +28 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_dict.h +410 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_dict_state.h +28 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_dtoa.h +40 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_emscripten_signal.h +30 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_emscripten_trampoline.h +70 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_exceptions.h +40 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_faulthandler.h +100 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_fileutils.h +320 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_fileutils_windows.h +98 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_floatobject.h +49 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_flowgraph.h +47 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_format.h +27 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_frame.h +61 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_freelist.h +111 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_freelist_state.h +70 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_function.h +53 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_gc.h +378 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_genobject.h +43 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_getopt.h +22 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_gil.h +66 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_global_objects.h +34 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_global_objects_fini_generated.h +1592 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_global_strings.h +854 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_hamt.h +113 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_hashtable.h +150 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_import.h +141 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_importdl.h +139 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_index_pool.h +36 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_initconfig.h +197 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_instruction_sequence.h +83 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_instruments.h +127 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_interp.h +109 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_interp_structs.h +977 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_interpframe.h +401 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_interpframe_structs.h +95 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_interpolation.h +26 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_intrinsics.h +51 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_jit.h +29 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_list.h +81 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_llist.h +106 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_lock.h +236 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_long.h +319 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_magic_number.h +305 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_memoryobject.h +20 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_mimalloc.h +69 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_modsupport.h +99 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_moduleobject.h +62 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_namespace.h +21 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_object.h +1029 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_object_alloc.h +71 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_object_deferred.h +32 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_object_stack.h +95 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_object_state.h +49 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_obmalloc.h +702 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_obmalloc_init.h +66 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_opcode_metadata.h +2117 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_opcode_utils.h +90 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_optimizer.h +318 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_parking_lot.h +97 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_parser.h +78 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_pathconfig.h +26 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_pyarena.h +68 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_pyatomic_ft_wrappers.h +174 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_pybuffer.h +21 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_pyerrors.h +213 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_pyhash.h +91 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_pylifecycle.h +136 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_pymath.h +205 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_pymem.h +145 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_pymem_init.h +103 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_pystate.h +339 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_pystats.h +21 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_pythonrun.h +68 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_pythread.h +172 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_qsbr.h +172 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_range.h +21 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_runtime.h +63 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_runtime_init.h +239 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_runtime_init_generated.h +1589 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_runtime_structs.h +310 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_semaphore.h +67 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_setobject.h +41 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_signal.h +108 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_sliceobject.h +20 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_stackref.h +791 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_stats.h +97 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_strhex.h +39 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_structs.h +88 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_structseq.h +40 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_symtable.h +201 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_sysmodule.h +32 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_template.h +26 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_time.h +334 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_token.h +110 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_traceback.h +111 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_tracemalloc.h +164 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_tstate.h +88 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_tuple.h +75 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_typedefs.h +18 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_typeobject.h +155 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_typevarobject.h +28 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_ucnhash.h +36 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_unicodeobject.h +308 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_unicodeobject_generated.h +3132 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_unionobject.h +26 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_uniqueid.h +57 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_uop_ids.h +335 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_uop_metadata.h +1204 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_warnings.h +21 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/internal/pycore_weakref.h +133 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/intrcheck.h +23 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/iterobject.h +24 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/listobject.h +55 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/lock.h +16 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/longobject.h +178 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/marshal.h +31 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/memoryobject.h +34 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/methodobject.h +146 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/modsupport.h +146 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/moduleobject.h +122 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/monitoring.h +18 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/object.h +828 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/objimpl.h +211 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/opcode.h +43 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/opcode_ids.h +259 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/osdefs.h +57 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/osmodule.h +17 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/patchlevel.h +49 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/py_curses.h +117 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/pyatomic.h +16 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/pybuffer.h +145 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/pycapsule.h +58 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/pyconfig.h +2088 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/pydtrace.h +59 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/pyerrors.h +335 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/pyexpat.h +62 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/pyframe.h +26 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/pyhash.h +59 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/pylifecycle.h +80 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/pymacconfig.h +91 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/pymacro.h +243 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/pymath.h +65 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/pymem.h +110 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/pyport.h +710 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/pystate.h +132 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/pystats.h +28 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/pystrcmp.h +23 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/pystrtod.h +37 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/pythonrun.h +42 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/pythread.h +131 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/pytypedefs.h +30 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/rangeobject.h +27 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/refcount.h +555 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/setobject.h +49 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/sliceobject.h +69 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/structmember.h +56 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/structseq.h +46 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/sysmodule.h +27 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/traceback.h +26 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/tupleobject.h +46 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/typeslots.h +96 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/unicodeobject.h +1029 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/warnings.h +45 -0
- pytron/platforms/android/shell/app/src/main/cpp/include/weakrefobject.h +46 -0
- pytron/platforms/android/shell/app/src/main/cpp/pytron_bridge.cpp +224 -0
- pytron/platforms/android/shell/app/src/main/java/com/pytron/shell/MainActivity.kt +208 -0
- pytron/platforms/android/shell/app/src/main/res/mipmap-xxhdpi/ic_launcher.png +0 -0
- pytron/platforms/android/shell/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png +0 -0
- pytron/platforms/android/shell/build.gradle +11 -0
- pytron/platforms/android/shell/gradle/wrapper/gradle-wrapper.jar +0 -0
- pytron/platforms/android/shell/gradle/wrapper/gradle-wrapper.properties +5 -0
- pytron/platforms/android/shell/gradle.properties +2 -0
- pytron/platforms/android/shell/gradlew.bat +85 -0
- pytron/platforms/android/shell/settings.gradle +16 -0
- pytron/platforms/darwin.py +82 -0
- pytron/platforms/darwin_ops/libs.py +31 -0
- pytron/platforms/darwin_ops/system.py +182 -0
- pytron/platforms/darwin_ops/utils.py +85 -0
- pytron/platforms/darwin_ops/webview.py +5 -0
- pytron/platforms/darwin_ops/window.py +102 -0
- pytron/platforms/interface.py +152 -0
- pytron/platforms/linux.py +82 -0
- pytron/platforms/linux_ops/libs.py +49 -0
- pytron/platforms/linux_ops/system.py +316 -0
- pytron/platforms/linux_ops/utils.py +19 -0
- pytron/platforms/linux_ops/webview.py +5 -0
- pytron/platforms/linux_ops/window.py +115 -0
- pytron/platforms/windows.py +136 -0
- pytron/platforms/windows_ops/__init__.py +0 -0
- pytron/platforms/windows_ops/constants.py +126 -0
- pytron/platforms/windows_ops/system.py +518 -0
- pytron/platforms/windows_ops/utils.py +3 -0
- pytron/platforms/windows_ops/webview.py +5 -0
- pytron/platforms/windows_ops/window.py +361 -0
- pytron/plugin.py +467 -0
- pytron/rcedit-x64.exe +0 -0
- pytron/router.py +146 -0
- pytron/serializer.py +240 -0
- pytron/shortcuts.py +279 -0
- pytron/state.py +76 -0
- pytron/tray.py +399 -0
- pytron/updater.py +181 -0
- pytron/utf8_hook.py +112 -0
- pytron/utils.py +44 -0
- pytron/webview.py +722 -0
- pytron_kit-0.3.12.dist-info/METADATA +131 -0
- pytron_kit-0.3.12.dist-info/RECORD +419 -0
- pytron_kit-0.3.12.dist-info/WHEEL +5 -0
- pytron_kit-0.3.12.dist-info/entry_points.txt +2 -0
- pytron_kit-0.3.12.dist-info/licenses/LICENSE +201 -0
- pytron_kit-0.3.12.dist-info/top_level.txt +1 -0
pytron/plugin.py
ADDED
|
@@ -0,0 +1,467 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import json
|
|
3
|
+
import sys
|
|
4
|
+
import importlib
|
|
5
|
+
import importlib.util
|
|
6
|
+
import logging
|
|
7
|
+
import subprocess
|
|
8
|
+
import threading
|
|
9
|
+
import traceback
|
|
10
|
+
import shutil
|
|
11
|
+
from typing import Dict, Any, List
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class PluginError(Exception):
|
|
15
|
+
pass
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class PluginStorage:
|
|
19
|
+
"""Provides a plugin with its own private JSON storage and data folder."""
|
|
20
|
+
|
|
21
|
+
def __init__(self, app_instance, plugin_name):
|
|
22
|
+
self._app = app_instance
|
|
23
|
+
self._name = plugin_name
|
|
24
|
+
self._dir = os.path.join(self._app.storage_path, "plugins", self._name)
|
|
25
|
+
os.makedirs(self._dir, exist_ok=True)
|
|
26
|
+
self._file = os.path.join(self._dir, "data.json")
|
|
27
|
+
|
|
28
|
+
def set(self, key, value):
|
|
29
|
+
data = self._read()
|
|
30
|
+
data[key] = value
|
|
31
|
+
self._write(data)
|
|
32
|
+
|
|
33
|
+
def get(self, key, default=None):
|
|
34
|
+
data = self._read()
|
|
35
|
+
return data.get(key, default)
|
|
36
|
+
|
|
37
|
+
def delete(self, key):
|
|
38
|
+
data = self._read()
|
|
39
|
+
if key in data:
|
|
40
|
+
del data[key]
|
|
41
|
+
self._write(data)
|
|
42
|
+
|
|
43
|
+
def path(self, *suffixes):
|
|
44
|
+
"""Returns an absolute path to a file in the plugin's private folder."""
|
|
45
|
+
path = os.path.join(self._dir, *suffixes)
|
|
46
|
+
os.makedirs(os.path.dirname(path), exist_ok=True)
|
|
47
|
+
return path
|
|
48
|
+
|
|
49
|
+
def _read(self):
|
|
50
|
+
if not os.path.exists(self._file):
|
|
51
|
+
return {}
|
|
52
|
+
try:
|
|
53
|
+
with open(self._file, "r", encoding="utf-8") as f:
|
|
54
|
+
return json.load(f)
|
|
55
|
+
except:
|
|
56
|
+
return {}
|
|
57
|
+
|
|
58
|
+
def _write(self, data):
|
|
59
|
+
with open(self._file, "w", encoding="utf-8") as f:
|
|
60
|
+
json.dump(data, f, indent=4)
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
class SupervisedApp:
|
|
64
|
+
"""
|
|
65
|
+
A proxy for the App instance that protects the main app from plugin crashes.
|
|
66
|
+
"""
|
|
67
|
+
|
|
68
|
+
def __init__(self, app, plugin_name):
|
|
69
|
+
self._app = app
|
|
70
|
+
self._plugin_name = plugin_name
|
|
71
|
+
self.logger = logging.getLogger(f"Pytron.Plugin.{plugin_name}.Supervisor")
|
|
72
|
+
self.storage = PluginStorage(app, plugin_name)
|
|
73
|
+
|
|
74
|
+
def expose(self, func, name=None, secure=False):
|
|
75
|
+
"""Wraps the exposed function in an error handler."""
|
|
76
|
+
func_name = name or func.__name__
|
|
77
|
+
|
|
78
|
+
def safe_wrapper(*args, **kwargs):
|
|
79
|
+
try:
|
|
80
|
+
return func(*args, **kwargs)
|
|
81
|
+
except Exception as e:
|
|
82
|
+
self.logger.error(
|
|
83
|
+
f"Plugin '{self._plugin_name}' crashed in '{func_name}': {e}"
|
|
84
|
+
)
|
|
85
|
+
self.logger.debug(traceback.format_exc())
|
|
86
|
+
return {"error": "Plugin Execution Failed", "message": str(e)}
|
|
87
|
+
|
|
88
|
+
return self._app.expose(safe_wrapper, name=name, secure=secure)
|
|
89
|
+
|
|
90
|
+
def __getattr__(self, name):
|
|
91
|
+
# Delegate everything else (state, broadcast, etc.) to the real app
|
|
92
|
+
return getattr(self._app, name)
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
class Plugin:
|
|
96
|
+
"""
|
|
97
|
+
Represents a loaded Pytron Plugin.
|
|
98
|
+
"""
|
|
99
|
+
|
|
100
|
+
def __init__(self, manifest_path: str):
|
|
101
|
+
self.manifest_path = os.path.abspath(manifest_path)
|
|
102
|
+
self.directory = os.path.dirname(self.manifest_path)
|
|
103
|
+
self.manifest = self._load_manifest()
|
|
104
|
+
self.logger = logging.getLogger(f"Pytron.Plugin.{self.name}")
|
|
105
|
+
|
|
106
|
+
def _load_manifest(self) -> Dict[str, Any]:
|
|
107
|
+
if not os.path.exists(self.manifest_path):
|
|
108
|
+
raise PluginError(f"Manifest not found at {self.manifest_path}")
|
|
109
|
+
|
|
110
|
+
try:
|
|
111
|
+
with open(self.manifest_path, "r") as f:
|
|
112
|
+
data = json.load(f)
|
|
113
|
+
except json.JSONDecodeError as e:
|
|
114
|
+
raise PluginError(f"Invalid JSON in manifest: {e}")
|
|
115
|
+
|
|
116
|
+
required_fields = ["name", "version", "entry_point"]
|
|
117
|
+
for field in required_fields:
|
|
118
|
+
if field not in data:
|
|
119
|
+
raise PluginError(f"Manifest missing required field: {field}")
|
|
120
|
+
|
|
121
|
+
return data
|
|
122
|
+
|
|
123
|
+
@property
|
|
124
|
+
def name(self) -> str:
|
|
125
|
+
return self.manifest.get("name", "unknown")
|
|
126
|
+
|
|
127
|
+
@property
|
|
128
|
+
def version(self) -> str:
|
|
129
|
+
return self.manifest.get("version", "0.0.0")
|
|
130
|
+
|
|
131
|
+
@property
|
|
132
|
+
def python_dependencies(self) -> List[str]:
|
|
133
|
+
return self.manifest.get("python_dependencies", [])
|
|
134
|
+
|
|
135
|
+
@property
|
|
136
|
+
def npm_dependencies(self) -> Dict[str, str]:
|
|
137
|
+
return self.manifest.get("npm_dependencies", {})
|
|
138
|
+
|
|
139
|
+
@property
|
|
140
|
+
def entry_point(self) -> str:
|
|
141
|
+
return self.manifest.get("entry_point")
|
|
142
|
+
|
|
143
|
+
@property
|
|
144
|
+
def ui_entry(self) -> str:
|
|
145
|
+
"""Relative path to the JS/WebComponent entry point for this plugin."""
|
|
146
|
+
return self.manifest.get("ui_entry")
|
|
147
|
+
|
|
148
|
+
@property
|
|
149
|
+
def config(self) -> Dict[str, Any]:
|
|
150
|
+
"""Plugin-specific configuration from manifest."""
|
|
151
|
+
return self.manifest.get("config", {})
|
|
152
|
+
|
|
153
|
+
@property
|
|
154
|
+
def isolated(self) -> bool:
|
|
155
|
+
"""Whether this plugin should run in its own process/venv."""
|
|
156
|
+
return self.manifest.get("isolated", False)
|
|
157
|
+
|
|
158
|
+
def check_js_dependencies(self) -> bool:
|
|
159
|
+
"""
|
|
160
|
+
Checks if JS dependencies are installed (rudimentary check for node_modules).
|
|
161
|
+
"""
|
|
162
|
+
if not self.npm_dependencies:
|
|
163
|
+
return True
|
|
164
|
+
node_modules = os.path.join(self.directory, "node_modules")
|
|
165
|
+
return os.path.exists(node_modules) and os.path.isdir(node_modules)
|
|
166
|
+
|
|
167
|
+
def check_dependencies(self) -> bool:
|
|
168
|
+
"""
|
|
169
|
+
Checks if Python dependencies are installed.
|
|
170
|
+
Returns True if all dependencies are present.
|
|
171
|
+
"""
|
|
172
|
+
missing = []
|
|
173
|
+
for dep in self.python_dependencies:
|
|
174
|
+
try:
|
|
175
|
+
importlib.import_module(dep) # nosemgrep
|
|
176
|
+
except ImportError:
|
|
177
|
+
missing.append(dep)
|
|
178
|
+
|
|
179
|
+
if missing:
|
|
180
|
+
self.logger.warning(f"Missing Python dependencies: {', '.join(missing)}")
|
|
181
|
+
return False
|
|
182
|
+
|
|
183
|
+
return True
|
|
184
|
+
|
|
185
|
+
def install_dependencies(self, frontend_dir: str = None, provider: str = "npm"):
|
|
186
|
+
"""
|
|
187
|
+
Attempts to install missing Python and JS dependencies.
|
|
188
|
+
"""
|
|
189
|
+
# GUARD: Do not install dependencies in packaged/frozen apps.
|
|
190
|
+
if getattr(sys, "frozen", False):
|
|
191
|
+
self.logger.info(
|
|
192
|
+
f"Skipping dependency install for '{self.name}' (Frozen Environment)"
|
|
193
|
+
)
|
|
194
|
+
return
|
|
195
|
+
|
|
196
|
+
# 1. Python Dependencies
|
|
197
|
+
py_deps = self.python_dependencies
|
|
198
|
+
if py_deps:
|
|
199
|
+
# Check if they are already installed to avoid redundant operations
|
|
200
|
+
if self.check_dependencies():
|
|
201
|
+
self.logger.debug(f"Python dependencies for {self.name} are satisfied.")
|
|
202
|
+
else:
|
|
203
|
+
self.logger.info(
|
|
204
|
+
f"Installing Python dependencies for {self.name}: {py_deps}"
|
|
205
|
+
)
|
|
206
|
+
try:
|
|
207
|
+
# Resolve the project's virtual environment if it exists
|
|
208
|
+
python_exe = sys.executable
|
|
209
|
+
venv_scripts = os.path.join(os.getcwd(), "env", "Scripts", "python.exe")
|
|
210
|
+
venv_bin = os.path.join(os.getcwd(), "env", "bin", "python")
|
|
211
|
+
|
|
212
|
+
if os.path.exists(venv_scripts):
|
|
213
|
+
python_exe = venv_scripts
|
|
214
|
+
elif os.path.exists(venv_bin):
|
|
215
|
+
python_exe = venv_bin
|
|
216
|
+
|
|
217
|
+
subprocess.check_call([python_exe, "-m", "pip", "install"] + py_deps)
|
|
218
|
+
self.logger.info(f"Python dependencies installed into {python_exe}")
|
|
219
|
+
except subprocess.CalledProcessError as e:
|
|
220
|
+
self.logger.error(f"Failed to install Python dependencies: {e}")
|
|
221
|
+
raise PluginError(f"Python dependency installation failed: {e}")
|
|
222
|
+
|
|
223
|
+
# 2. JS Dependencies
|
|
224
|
+
js_deps = self.npm_dependencies
|
|
225
|
+
if js_deps:
|
|
226
|
+
if self.check_js_dependencies():
|
|
227
|
+
self.logger.debug(f"JS dependencies for {self.name} are satisfied.")
|
|
228
|
+
return
|
|
229
|
+
|
|
230
|
+
# ISOLATION: Install inside the plugin directory
|
|
231
|
+
target_dir = self.directory
|
|
232
|
+
|
|
233
|
+
self.logger.info(
|
|
234
|
+
f"Installing JS dependencies for {self.name} using '{provider}' in {target_dir} for isolation..."
|
|
235
|
+
)
|
|
236
|
+
|
|
237
|
+
# Ensure a package.json exists in the plugin directory
|
|
238
|
+
pkg_json_path = os.path.join(target_dir, "package.json")
|
|
239
|
+
if not os.path.exists(pkg_json_path):
|
|
240
|
+
pkg_data = {
|
|
241
|
+
"name": f"pytron-plugin-{self.name}",
|
|
242
|
+
"version": self.version,
|
|
243
|
+
"dependencies": js_deps,
|
|
244
|
+
}
|
|
245
|
+
with open(pkg_json_path, "w") as f:
|
|
246
|
+
json.dump(pkg_data, f, indent=2)
|
|
247
|
+
|
|
248
|
+
try:
|
|
249
|
+
# Find JS provider binary
|
|
250
|
+
provider_bin = shutil.which(provider)
|
|
251
|
+
if not provider_bin:
|
|
252
|
+
self.logger.warning(
|
|
253
|
+
f"JS Provider '{provider}' not found in PATH. Skipping JS dependencies."
|
|
254
|
+
)
|
|
255
|
+
return
|
|
256
|
+
|
|
257
|
+
subprocess.check_call(
|
|
258
|
+
[provider_bin, "install"],
|
|
259
|
+
cwd=target_dir,
|
|
260
|
+
shell=False,
|
|
261
|
+
) # nosec B603
|
|
262
|
+
self.logger.info(
|
|
263
|
+
f"JS dependencies installed successfully using {provider}."
|
|
264
|
+
)
|
|
265
|
+
except Exception as e:
|
|
266
|
+
self.logger.error(f"Failed to install JS dependencies: {e}")
|
|
267
|
+
raise PluginError(f"JS dependency installation failed: {e}")
|
|
268
|
+
# We don't necessarily want to crash the whole app if NPM is missing,
|
|
269
|
+
# but we should log it.
|
|
270
|
+
|
|
271
|
+
def load(self, app_instance):
|
|
272
|
+
"""
|
|
273
|
+
Loads the entry point and runs initialization. (Senior Fix: Isolated Namespace)
|
|
274
|
+
"""
|
|
275
|
+
# Ensure we use an absolute path
|
|
276
|
+
plugin_dir = os.path.abspath(self.directory)
|
|
277
|
+
entry_str = self.entry_point
|
|
278
|
+
|
|
279
|
+
if ":" not in entry_str:
|
|
280
|
+
raise PluginError(
|
|
281
|
+
f"Invalid entry_point format '{entry_str}'. Expected 'module:function' or 'module:Class'"
|
|
282
|
+
)
|
|
283
|
+
|
|
284
|
+
module_name, object_name = entry_str.split(":")
|
|
285
|
+
|
|
286
|
+
# Senior Fix: Define a unique name for the module (e.g., "pytron_plugins.myplugin")
|
|
287
|
+
# This prevents collisions if multiple plugins have a 'main.py' or 'app.py'
|
|
288
|
+
safe_name = self.name.replace("-", "_").replace(".", "_")
|
|
289
|
+
unique_module_name = f"pytron_plugins.{safe_name}"
|
|
290
|
+
|
|
291
|
+
# Resolve the file path (handles packages and submodules)
|
|
292
|
+
module_path_parts = module_name.split(".")
|
|
293
|
+
file_path = os.path.join(plugin_dir, *module_path_parts) + ".py"
|
|
294
|
+
if not os.path.exists(file_path):
|
|
295
|
+
init_path = os.path.join(plugin_dir, *module_path_parts, "__init__.py")
|
|
296
|
+
if os.path.exists(init_path):
|
|
297
|
+
file_path = init_path
|
|
298
|
+
|
|
299
|
+
if not os.path.exists(file_path):
|
|
300
|
+
raise PluginError(
|
|
301
|
+
f"Could not find entry point file for plugin '{self.name}': {file_path}"
|
|
302
|
+
)
|
|
303
|
+
|
|
304
|
+
# Create the Supervised proxy
|
|
305
|
+
supervised_app = SupervisedApp(app_instance, self.name)
|
|
306
|
+
|
|
307
|
+
try:
|
|
308
|
+
# Senior Fix: Load the module directly via spec without polluting global sys.path
|
|
309
|
+
spec = importlib.util.spec_from_file_location(unique_module_name, file_path)
|
|
310
|
+
if spec and spec.loader:
|
|
311
|
+
self.module = importlib.util.module_from_spec(spec)
|
|
312
|
+
sys.modules[unique_module_name] = self.module # Register it safely
|
|
313
|
+
|
|
314
|
+
# To support local imports inside the plugin folder, we briefly add to path
|
|
315
|
+
# only during the execution of the module.
|
|
316
|
+
path_added = False
|
|
317
|
+
if plugin_dir not in sys.path:
|
|
318
|
+
sys.path.insert(0, plugin_dir)
|
|
319
|
+
path_added = True
|
|
320
|
+
|
|
321
|
+
try:
|
|
322
|
+
spec.loader.exec_module(self.module)
|
|
323
|
+
except ImportError as e:
|
|
324
|
+
raise PluginError(f"Import Error in {self.name}: {e}")
|
|
325
|
+
finally:
|
|
326
|
+
if path_added and plugin_dir in sys.path:
|
|
327
|
+
sys.path.remove(plugin_dir)
|
|
328
|
+
else:
|
|
329
|
+
raise PluginError(f"Could not load module spec for {self.name}")
|
|
330
|
+
|
|
331
|
+
# Get the object
|
|
332
|
+
if not hasattr(self.module, object_name):
|
|
333
|
+
raise PluginError(
|
|
334
|
+
f"Entry point '{object_name}' not found in module '{module_name}'"
|
|
335
|
+
)
|
|
336
|
+
|
|
337
|
+
entry_obj = getattr(self.module, object_name)
|
|
338
|
+
|
|
339
|
+
def init_plugin():
|
|
340
|
+
try:
|
|
341
|
+
self.logger.debug(
|
|
342
|
+
f"Initializing entry point: {entry_obj} (Type: {type(entry_obj).__name__})"
|
|
343
|
+
)
|
|
344
|
+
|
|
345
|
+
# 1. If it's a function, call it with `supervised_app`
|
|
346
|
+
if callable(entry_obj) and not isinstance(entry_obj, type):
|
|
347
|
+
self.logger.info(
|
|
348
|
+
f"Initializing plugin '{self.name}' via function '{object_name}'"
|
|
349
|
+
)
|
|
350
|
+
# Check for manual configuration from the 'plugins' pseudo-module if it exists
|
|
351
|
+
manual_config = {}
|
|
352
|
+
if "plugins" in sys.modules:
|
|
353
|
+
p_mod = sys.modules["plugins"]
|
|
354
|
+
if hasattr(p_mod, "get_registered_config"):
|
|
355
|
+
manual_config = p_mod.get_registered_config(self.name)
|
|
356
|
+
|
|
357
|
+
if manual_config:
|
|
358
|
+
self.logger.info(
|
|
359
|
+
f"Applying manual configuration to '{self.name}': {list(manual_config.keys())}"
|
|
360
|
+
)
|
|
361
|
+
|
|
362
|
+
self.instance = entry_obj(supervised_app, **manual_config)
|
|
363
|
+
|
|
364
|
+
# 2. If it's a class, instantiate it with `supervised_app`
|
|
365
|
+
elif isinstance(entry_obj, type):
|
|
366
|
+
self.logger.info(
|
|
367
|
+
f"Initializing plugin '{self.name}' via class '{object_name}'"
|
|
368
|
+
)
|
|
369
|
+
# Check for manual configuration from the 'plugins' pseudo-module if it exists
|
|
370
|
+
manual_config = {}
|
|
371
|
+
if "plugins" in sys.modules:
|
|
372
|
+
p_mod = sys.modules["plugins"]
|
|
373
|
+
if hasattr(p_mod, "get_registered_config"):
|
|
374
|
+
manual_config = p_mod.get_registered_config(self.name)
|
|
375
|
+
|
|
376
|
+
if manual_config:
|
|
377
|
+
self.logger.info(
|
|
378
|
+
f"Applying manual configuration to '{self.name}': {list(manual_config.keys())}"
|
|
379
|
+
)
|
|
380
|
+
|
|
381
|
+
self.instance = entry_obj(supervised_app, **manual_config)
|
|
382
|
+
|
|
383
|
+
# If the class has a 'setup' method, call it
|
|
384
|
+
if hasattr(self.instance, "setup"):
|
|
385
|
+
self.instance.setup()
|
|
386
|
+
|
|
387
|
+
else:
|
|
388
|
+
self.logger.error(
|
|
389
|
+
f"Entry point '{object_name}' is not callable. Got type: {type(entry_obj)}"
|
|
390
|
+
)
|
|
391
|
+
|
|
392
|
+
except TypeError as e:
|
|
393
|
+
if "NoneType" in str(e) and "callable" in str(e):
|
|
394
|
+
self.logger.error(
|
|
395
|
+
f"CRITICAL: 'NoneType' object is not callable in {self.name}. Check if entry point is valid or if dependencies are missing."
|
|
396
|
+
)
|
|
397
|
+
self.logger.error(
|
|
398
|
+
f"Plugin '{self.name}' initialization crash (TypeError): {e}"
|
|
399
|
+
)
|
|
400
|
+
self.logger.debug(traceback.format_exc())
|
|
401
|
+
except Exception as e:
|
|
402
|
+
self.logger.error(f"Plugin '{self.name}' initialization crash: {e}")
|
|
403
|
+
self.logger.debug(traceback.format_exc())
|
|
404
|
+
|
|
405
|
+
if self.isolated:
|
|
406
|
+
self.logger.info(
|
|
407
|
+
f"Plugin '{self.name}' is isolated. Starting in worker thread..."
|
|
408
|
+
)
|
|
409
|
+
thread = threading.Thread(
|
|
410
|
+
target=init_plugin, name=f"Plugin-{self.name}", daemon=True
|
|
411
|
+
)
|
|
412
|
+
thread.start()
|
|
413
|
+
else:
|
|
414
|
+
init_plugin()
|
|
415
|
+
|
|
416
|
+
except Exception as e:
|
|
417
|
+
raise PluginError(f"Failed to load plugin '{self.name}': {e}")
|
|
418
|
+
|
|
419
|
+
def unload(self):
|
|
420
|
+
"""
|
|
421
|
+
Unloads the plugin by calling its teardown method if available.
|
|
422
|
+
"""
|
|
423
|
+
if hasattr(self, "instance") and self.instance:
|
|
424
|
+
if hasattr(self.instance, "teardown"):
|
|
425
|
+
try:
|
|
426
|
+
self.instance.teardown()
|
|
427
|
+
self.logger.info(f"Plugin '{self.name}' torn down successfully.")
|
|
428
|
+
except Exception as e:
|
|
429
|
+
self.logger.error(f"Error tearing down plugin '{self.name}': {e}")
|
|
430
|
+
self.instance = None
|
|
431
|
+
|
|
432
|
+
if hasattr(self, "module") and self.module:
|
|
433
|
+
# Note: We don't remove from sys.modules to avoid breaking background threads
|
|
434
|
+
# that might still be using the code, but we clear the local reference.
|
|
435
|
+
del self.module
|
|
436
|
+
|
|
437
|
+
def invoke_package_hook(self, context: Dict[str, Any]):
|
|
438
|
+
"""
|
|
439
|
+
Invoked during 'pytron package'. Allows plugins to add extra data,
|
|
440
|
+
hidden imports, or run custom build scripts.
|
|
441
|
+
"""
|
|
442
|
+
if hasattr(self, "instance") and hasattr(self.instance, "on_package"):
|
|
443
|
+
try:
|
|
444
|
+
self.logger.info(f"Invoking on_package hook for '{self.name}'...")
|
|
445
|
+
self.instance.on_package(context)
|
|
446
|
+
except Exception as e:
|
|
447
|
+
self.logger.error(f"Error in on_package hook for '{self.name}': {e}")
|
|
448
|
+
self.logger.debug(traceback.format_exc())
|
|
449
|
+
|
|
450
|
+
|
|
451
|
+
def discover_plugins(plugins_dir: str) -> List[Plugin]:
|
|
452
|
+
"""
|
|
453
|
+
Utility to find all plugins in a directory without loading them.
|
|
454
|
+
"""
|
|
455
|
+
plugins = []
|
|
456
|
+
if not os.path.exists(plugins_dir):
|
|
457
|
+
return plugins
|
|
458
|
+
|
|
459
|
+
for item in os.listdir(plugins_dir):
|
|
460
|
+
plugin_path = os.path.join(plugins_dir, item)
|
|
461
|
+
manifest_path = os.path.join(plugin_path, "manifest.json")
|
|
462
|
+
if os.path.isdir(plugin_path) and os.path.exists(manifest_path):
|
|
463
|
+
try:
|
|
464
|
+
plugins.append(Plugin(manifest_path))
|
|
465
|
+
except Exception:
|
|
466
|
+
pass
|
|
467
|
+
return plugins
|
pytron/rcedit-x64.exe
ADDED
|
Binary file
|
pytron/router.py
ADDED
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import re
|
|
2
|
+
import urllib.parse
|
|
3
|
+
import inspect
|
|
4
|
+
import logging
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class DeepLink:
|
|
8
|
+
"""
|
|
9
|
+
Represents a parsed Deep Link.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
def __init__(self, raw_url: str, params: dict = None):
|
|
13
|
+
self.raw_url = raw_url
|
|
14
|
+
self.parsed = urllib.parse.urlparse(raw_url)
|
|
15
|
+
self.scheme = self.parsed.scheme
|
|
16
|
+
self.netloc = self.parsed.netloc
|
|
17
|
+
self.path = self.parsed.path
|
|
18
|
+
|
|
19
|
+
# Parse query params (returns dict of lists)
|
|
20
|
+
self.query = urllib.parse.parse_qs(self.parsed.query)
|
|
21
|
+
|
|
22
|
+
# Flatten query params if single value (optional utility)
|
|
23
|
+
self.args = {k: v[0] if len(v) == 1 else v for k, v in self.query.items()}
|
|
24
|
+
|
|
25
|
+
# Path parameters extracted from route
|
|
26
|
+
self.params = params or {}
|
|
27
|
+
|
|
28
|
+
def __repr__(self):
|
|
29
|
+
return f"<DeepLink scheme='{self.scheme}' path='{self.netloc}{self.path}' params={self.params} args={self.args}>"
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class Router:
|
|
33
|
+
"""
|
|
34
|
+
Handles matching Deep Links to registered callback functions.
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
def __init__(self, logger=None):
|
|
38
|
+
self.routes = []
|
|
39
|
+
self._default_handler = None
|
|
40
|
+
self.logger = logger or logging.getLogger("Pytron.Router")
|
|
41
|
+
|
|
42
|
+
def add_route(self, pattern: str, func):
|
|
43
|
+
"""
|
|
44
|
+
Registers a route pattern.
|
|
45
|
+
Pattern examples:
|
|
46
|
+
- "home" matches myapp://home
|
|
47
|
+
- "document/{id}" matches myapp://document/123
|
|
48
|
+
- "user/{name}/profile" matches myapp://user/alice/profile
|
|
49
|
+
"""
|
|
50
|
+
# 1. Normalize pattern to ensure it handles the 'netloc' vs 'path' ambiguity of custom schemes
|
|
51
|
+
# We treat everything after 'scheme://' as the routable path.
|
|
52
|
+
clean_pattern = pattern.strip("/")
|
|
53
|
+
|
|
54
|
+
# 2. Convert {param} to Regex Group (?P<param>[^/]+)
|
|
55
|
+
# Escape special regex chars but leave our braces
|
|
56
|
+
regex_pattern = re.escape(clean_pattern)
|
|
57
|
+
|
|
58
|
+
# Replace escaped braces \{param\} back to capture groups
|
|
59
|
+
# We manually build the regex: replace \{([^}]+)\} with (?P<\1>[^/]+)
|
|
60
|
+
# Note: re.escape escapes {, }, so we look for \\{ and \\}
|
|
61
|
+
regex_pattern = re.sub(
|
|
62
|
+
r"\\{([a-zA-Z0-9_]+)\\}", r"(?P<\1>[^/]+)", regex_pattern
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
# Anchor start/end
|
|
66
|
+
regex_pattern = f"^{regex_pattern}$"
|
|
67
|
+
|
|
68
|
+
self.routes.append(
|
|
69
|
+
{"pattern": clean_pattern, "regex": re.compile(regex_pattern), "func": func}
|
|
70
|
+
)
|
|
71
|
+
self.logger.debug(f"Registered deep link route: {clean_pattern}")
|
|
72
|
+
|
|
73
|
+
def route(self, pattern: str):
|
|
74
|
+
"""
|
|
75
|
+
Decorator to register a route.
|
|
76
|
+
"""
|
|
77
|
+
|
|
78
|
+
def decorator(func):
|
|
79
|
+
self.add_route(pattern, func)
|
|
80
|
+
return func
|
|
81
|
+
|
|
82
|
+
return decorator
|
|
83
|
+
|
|
84
|
+
def set_default_handler(self, func):
|
|
85
|
+
self._default_handler = func
|
|
86
|
+
|
|
87
|
+
def dispatch(self, raw_url: str):
|
|
88
|
+
"""
|
|
89
|
+
Parses the URL and calls the matching handler.
|
|
90
|
+
"""
|
|
91
|
+
if not raw_url:
|
|
92
|
+
return
|
|
93
|
+
|
|
94
|
+
try:
|
|
95
|
+
parsed = urllib.parse.urlparse(raw_url)
|
|
96
|
+
# Reconstruct the "routable path": netloc + path
|
|
97
|
+
# e.g. myapp://user/1 -> netloc="user", path="/1" -> "user/1"
|
|
98
|
+
# e.g. myapp://home -> netloc="home", path="" -> "home"
|
|
99
|
+
routable_path = f"{parsed.netloc}{parsed.path}".strip("/")
|
|
100
|
+
|
|
101
|
+
matched = False
|
|
102
|
+
for route in self.routes:
|
|
103
|
+
match = route["regex"].match(routable_path)
|
|
104
|
+
if match:
|
|
105
|
+
params = match.groupdict()
|
|
106
|
+
link = DeepLink(raw_url, params)
|
|
107
|
+
self._invoke_handler(route["func"], link)
|
|
108
|
+
matched = True
|
|
109
|
+
break
|
|
110
|
+
|
|
111
|
+
if not matched:
|
|
112
|
+
self.logger.debug(f"No route matched for: {routable_path}")
|
|
113
|
+
if self._default_handler:
|
|
114
|
+
link = DeepLink(raw_url)
|
|
115
|
+
self._invoke_handler(self._default_handler, link)
|
|
116
|
+
|
|
117
|
+
except Exception as e:
|
|
118
|
+
self.logger.error(f"Error dispatching deep link '{raw_url}': {e}")
|
|
119
|
+
|
|
120
|
+
def _invoke_handler(self, func, link):
|
|
121
|
+
"""
|
|
122
|
+
Invokes the handler, injecting arguments if needed.
|
|
123
|
+
"""
|
|
124
|
+
try:
|
|
125
|
+
sig = inspect.signature(func)
|
|
126
|
+
kwargs = {}
|
|
127
|
+
|
|
128
|
+
# 1. Check if handler wants the full 'link' object
|
|
129
|
+
if "link" in sig.parameters:
|
|
130
|
+
kwargs["link"] = link
|
|
131
|
+
|
|
132
|
+
# 2. Inject path params if they match argument names
|
|
133
|
+
for name, value in link.params.items():
|
|
134
|
+
if name in sig.parameters:
|
|
135
|
+
kwargs[name] = value
|
|
136
|
+
|
|
137
|
+
# 3. Inject query args if they match argument names
|
|
138
|
+
for name, value in link.args.items():
|
|
139
|
+
if name in sig.parameters:
|
|
140
|
+
kwargs[name] = value
|
|
141
|
+
|
|
142
|
+
# Invoke
|
|
143
|
+
func(**kwargs)
|
|
144
|
+
|
|
145
|
+
except Exception as e:
|
|
146
|
+
self.logger.error(f"Handler failed for deep link: {e}")
|