pytron-kit 0.3.12__py3-none-win_amd64.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.pyd +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.exe +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
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import sys
|
|
3
|
+
import json
|
|
4
|
+
import logging
|
|
5
|
+
from ..utils import get_resource_path
|
|
6
|
+
from ..exceptions import ConfigError
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class ConfigMixin:
|
|
10
|
+
def _setup_logging(self):
|
|
11
|
+
# If we use basicConfig, it might interfere with user's settings.
|
|
12
|
+
# But for a simple CLI tool, it's often preferred.
|
|
13
|
+
# Let's check if the root logger has any handlers already.
|
|
14
|
+
if not logging.root.handlers:
|
|
15
|
+
logging.basicConfig(
|
|
16
|
+
level=logging.INFO,
|
|
17
|
+
format="[Pytron] %(asctime)s - %(levelname)s - %(message)s",
|
|
18
|
+
datefmt="%H:%M:%S",
|
|
19
|
+
)
|
|
20
|
+
self.logger = logging.getLogger("Pytron")
|
|
21
|
+
|
|
22
|
+
def _check_deep_link(self):
|
|
23
|
+
self.state.launch_url = None
|
|
24
|
+
# Scan all args for a possible deep link (some OS pass it at different positions)
|
|
25
|
+
# or it might be preceded by flags.
|
|
26
|
+
for arg in sys.argv[1:]:
|
|
27
|
+
if arg.startswith("pytron:") or "://" in arg:
|
|
28
|
+
# Basic validation: ensure it's not a local file path with :// (unlikely on Win)
|
|
29
|
+
if ":" in arg and not os.path.exists(arg):
|
|
30
|
+
self.logger.info(f"App launched via Deep Link: {arg}")
|
|
31
|
+
self.state.launch_url = arg
|
|
32
|
+
break
|
|
33
|
+
# Defer dispatch to run-time if needed, but since plugins/handlers
|
|
34
|
+
# might be registered AFTER init, we might need to handle this carefully.
|
|
35
|
+
# However, for now, we'll store it. The handlers usually aren't registered
|
|
36
|
+
# until the user script runs.
|
|
37
|
+
# So we should probably dispatch in app.run().
|
|
38
|
+
|
|
39
|
+
def _load_config(self, config_file):
|
|
40
|
+
self.config = {}
|
|
41
|
+
path = get_resource_path(config_file)
|
|
42
|
+
self.logger.debug(f"Resolved settings path: {path}")
|
|
43
|
+
|
|
44
|
+
if not os.path.exists(path):
|
|
45
|
+
path = os.path.abspath(config_file)
|
|
46
|
+
|
|
47
|
+
if os.path.exists(path):
|
|
48
|
+
try:
|
|
49
|
+
with open(path, "r") as f:
|
|
50
|
+
self.config = json.load(f)
|
|
51
|
+
|
|
52
|
+
if self.config.get("debug", False):
|
|
53
|
+
self.logger.setLevel(logging.DEBUG)
|
|
54
|
+
for handler in logging.root.handlers:
|
|
55
|
+
handler.setLevel(logging.DEBUG)
|
|
56
|
+
self.logger.debug("Debug mode enabled.")
|
|
57
|
+
|
|
58
|
+
dev_url = os.environ.get("PYTRON_DEV_URL")
|
|
59
|
+
if dev_url:
|
|
60
|
+
self.config["url"] = dev_url
|
|
61
|
+
self.logger.info(f"Dev mode: Overriding URL to {dev_url}")
|
|
62
|
+
|
|
63
|
+
config_version = self.config.get("pytron_version")
|
|
64
|
+
if config_version:
|
|
65
|
+
try:
|
|
66
|
+
from .. import __version__
|
|
67
|
+
|
|
68
|
+
if config_version != __version__:
|
|
69
|
+
self.logger.warning(
|
|
70
|
+
f"Version mismatch: Settings({config_version}) vs Installed({__version__})"
|
|
71
|
+
)
|
|
72
|
+
except ImportError:
|
|
73
|
+
pass
|
|
74
|
+
except json.JSONDecodeError as e:
|
|
75
|
+
self.logger.error(f"Failed to parse settings.json: {e}")
|
|
76
|
+
raise ConfigError(f"Invalid JSON in settings file: {path}") from e
|
|
77
|
+
except Exception as e:
|
|
78
|
+
self.logger.error(f"Failed to load settings: {e}")
|
|
79
|
+
raise ConfigError(f"Could not load settings from {path}") from e
|
|
80
|
+
else:
|
|
81
|
+
self.logger.warning(
|
|
82
|
+
f"Settings file not found at {path}. Using default configuration."
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
def _setup_identity(self):
|
|
86
|
+
title = self.config.get("title", "Pytron App")
|
|
87
|
+
safe_title = "".join(
|
|
88
|
+
c if c.isalnum() or c in ("-", "_") else "_" for c in title
|
|
89
|
+
).strip("_")
|
|
90
|
+
app_id = self._register_app_id(title, safe_title)
|
|
91
|
+
|
|
92
|
+
# Single Instance Guard
|
|
93
|
+
if self.config.get("single_instance", True):
|
|
94
|
+
self._setup_single_instance(app_id)
|
|
95
|
+
|
|
96
|
+
return title, safe_title
|
|
97
|
+
|
|
98
|
+
def _register_app_id(self, title, safe_title):
|
|
99
|
+
author = self.config.get("author", "PytronUser")
|
|
100
|
+
if not safe_title:
|
|
101
|
+
safe_title = (
|
|
102
|
+
"".join([c for c in (title or "Pytron") if c.isalnum()]) or "PytronApp"
|
|
103
|
+
)
|
|
104
|
+
app_id = f"{author}.{safe_title}.App"
|
|
105
|
+
|
|
106
|
+
if sys.platform == "win32" and getattr(sys, "frozen", False):
|
|
107
|
+
try:
|
|
108
|
+
from ..platforms.windows import WindowsImplementation
|
|
109
|
+
|
|
110
|
+
WindowsImplementation().set_app_id(app_id)
|
|
111
|
+
self.logger.debug(f"Set Windows AppUserModelID: {app_id}")
|
|
112
|
+
except Exception as e:
|
|
113
|
+
self.logger.debug(f"Failed to set App ID: {e}")
|
|
114
|
+
elif sys.platform == "linux":
|
|
115
|
+
try:
|
|
116
|
+
from ..platforms.linux import LinuxImplementation
|
|
117
|
+
|
|
118
|
+
LinuxImplementation().set_app_id(safe_title)
|
|
119
|
+
except Exception as e:
|
|
120
|
+
self.logger.debug(f"Failed to set Linux App ID: {e}")
|
|
121
|
+
elif sys.platform == "darwin":
|
|
122
|
+
try:
|
|
123
|
+
from ..platforms.darwin import DarwinImplementation
|
|
124
|
+
|
|
125
|
+
DarwinImplementation().set_app_id(title)
|
|
126
|
+
except Exception as e:
|
|
127
|
+
self.logger.debug(f"Failed to set Darwin App ID: {e}")
|
|
128
|
+
return app_id
|
|
129
|
+
|
|
130
|
+
def _setup_single_instance(self, app_id):
|
|
131
|
+
import socket
|
|
132
|
+
import hashlib
|
|
133
|
+
import threading
|
|
134
|
+
import os
|
|
135
|
+
|
|
136
|
+
# Skip during tests and development as they often require flexibility
|
|
137
|
+
if "PYTEST_CURRENT_TEST" in os.environ or not getattr(sys, "frozen", False):
|
|
138
|
+
return
|
|
139
|
+
|
|
140
|
+
# Generate a stable port between 10000-60000 based on app_id
|
|
141
|
+
# B324: Use SHA256 instead of MD5 for port generation stability
|
|
142
|
+
port = 10000 + (int(hashlib.sha256(app_id.encode()).hexdigest(), 16) % 50000)
|
|
143
|
+
self._instance_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
144
|
+
|
|
145
|
+
try:
|
|
146
|
+
self._instance_socket.bind(("127.0.0.1", port))
|
|
147
|
+
self._instance_socket.listen(1)
|
|
148
|
+
|
|
149
|
+
def _listen_for_other_instances():
|
|
150
|
+
while True:
|
|
151
|
+
try:
|
|
152
|
+
conn, _ = self._instance_socket.accept()
|
|
153
|
+
data = conn.recv(1024).decode("utf-8")
|
|
154
|
+
if data:
|
|
155
|
+
msg = json.loads(data)
|
|
156
|
+
url = msg.get("url")
|
|
157
|
+
if url:
|
|
158
|
+
self.logger.info(
|
|
159
|
+
f"Received deep link from another instance: {url}"
|
|
160
|
+
)
|
|
161
|
+
# Update launch URL and show windows
|
|
162
|
+
self.state.launch_url = url
|
|
163
|
+
self.router.dispatch(url)
|
|
164
|
+
for window in self.windows:
|
|
165
|
+
window.show()
|
|
166
|
+
window.emit("pytron:deep-link", {"url": url})
|
|
167
|
+
conn.close()
|
|
168
|
+
except Exception:
|
|
169
|
+
break
|
|
170
|
+
|
|
171
|
+
t = threading.Thread(target=_listen_for_other_instances, daemon=True)
|
|
172
|
+
t.start()
|
|
173
|
+
|
|
174
|
+
@self.on_exit
|
|
175
|
+
def _close_instance_socket():
|
|
176
|
+
try:
|
|
177
|
+
self._instance_socket.close()
|
|
178
|
+
except Exception as e:
|
|
179
|
+
self.logger.debug(f"Error closing instance socket: {e}")
|
|
180
|
+
|
|
181
|
+
except socket.error:
|
|
182
|
+
# Instance already running!
|
|
183
|
+
self.logger.info(
|
|
184
|
+
"Another instance is already running. Forwarding launch URL and exiting."
|
|
185
|
+
)
|
|
186
|
+
try:
|
|
187
|
+
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
188
|
+
client.connect(("127.0.0.1", port))
|
|
189
|
+
client.send(json.dumps({"url": self.state.launch_url}).encode("utf-8"))
|
|
190
|
+
client.close()
|
|
191
|
+
except Exception:
|
|
192
|
+
pass
|
|
193
|
+
# Critical: Use os._exit(0) instead of sys.exit(0)
|
|
194
|
+
# sys.exit() raises SystemExit, which can be caught by the bootstrap wrapper
|
|
195
|
+
# or Cython, leading to a false positive "Shield Error".
|
|
196
|
+
# os._exit() terminates immediately at the OS level, which is safe here
|
|
197
|
+
# because we want to vanish instantly after forwarding the intent.
|
|
198
|
+
os._exit(0)
|
|
199
|
+
|
|
200
|
+
def _setup_storage(self, safe_title):
|
|
201
|
+
if sys.platform == "win32":
|
|
202
|
+
base_path = os.environ.get("LOCALAPPDATA", os.path.expanduser("~"))
|
|
203
|
+
elif os.environ.get("PYTHON_PLATFORM") == "android":
|
|
204
|
+
python_home = os.environ.get("PYTHONHOME")
|
|
205
|
+
if python_home:
|
|
206
|
+
base_path = os.path.dirname(python_home)
|
|
207
|
+
else:
|
|
208
|
+
base_path = os.path.expanduser("~")
|
|
209
|
+
else:
|
|
210
|
+
base_path = os.path.expanduser("~/.config")
|
|
211
|
+
|
|
212
|
+
self.storage_path = os.path.join(base_path, safe_title)
|
|
213
|
+
|
|
214
|
+
if getattr(sys, "frozen", False):
|
|
215
|
+
self.app_root = os.path.dirname(os.path.abspath(sys.executable))
|
|
216
|
+
else:
|
|
217
|
+
# Better way to find app root than os.getcwd() which depends on where user ran Python
|
|
218
|
+
main_module = sys.modules.get("__main__")
|
|
219
|
+
if main_module and hasattr(main_module, "__file__"):
|
|
220
|
+
self.app_root = os.path.dirname(os.path.abspath(main_module.__file__))
|
|
221
|
+
else:
|
|
222
|
+
self.app_root = os.path.abspath(
|
|
223
|
+
sys.path[0] if sys.path and sys.path[0] else os.getcwd()
|
|
224
|
+
)
|
|
225
|
+
|
|
226
|
+
try:
|
|
227
|
+
os.makedirs(self.storage_path, exist_ok=True)
|
|
228
|
+
if getattr(sys, "frozen", False):
|
|
229
|
+
os.chdir(self.storage_path)
|
|
230
|
+
self.logger.info(f"Changed Working Directory to: {self.storage_path}")
|
|
231
|
+
else:
|
|
232
|
+
self.logger.debug(
|
|
233
|
+
f"Dev Mode: Storage directory ready at {self.storage_path}"
|
|
234
|
+
)
|
|
235
|
+
except Exception as e:
|
|
236
|
+
self.logger.warning(
|
|
237
|
+
f"Could not create storage directory at {self.storage_path}: {e}"
|
|
238
|
+
)
|
|
239
|
+
|
|
240
|
+
def _resolve_resources(self):
|
|
241
|
+
def resolve_resource(path):
|
|
242
|
+
if (
|
|
243
|
+
not path
|
|
244
|
+
or path.startswith(("http:", "https:", "file:"))
|
|
245
|
+
or os.path.isabs(path)
|
|
246
|
+
):
|
|
247
|
+
return path
|
|
248
|
+
|
|
249
|
+
internal = os.path.join(self.app_root, "_internal", path)
|
|
250
|
+
if os.path.exists(internal):
|
|
251
|
+
return internal
|
|
252
|
+
|
|
253
|
+
candidate = os.path.join(self.app_root, path)
|
|
254
|
+
if os.path.exists(candidate):
|
|
255
|
+
return candidate
|
|
256
|
+
|
|
257
|
+
return get_resource_path(path)
|
|
258
|
+
|
|
259
|
+
if "url" in self.config:
|
|
260
|
+
self.config["url"] = resolve_resource(self.config["url"])
|
|
261
|
+
|
|
262
|
+
if "icon" in self.config:
|
|
263
|
+
orig_icon = self.config["icon"]
|
|
264
|
+
resolved_icon = resolve_resource(orig_icon)
|
|
265
|
+
if os.path.exists(resolved_icon):
|
|
266
|
+
self.config["icon"] = resolved_icon
|
|
267
|
+
self.logger.info(f"Resolved icon to: {resolved_icon}")
|
|
268
|
+
else:
|
|
269
|
+
self.logger.warning(f"Could not find icon at: {orig_icon}")
|
|
270
|
+
|
|
271
|
+
def _setup_key_value_store(self):
|
|
272
|
+
self._store_file = os.path.join(self.storage_path, "store.json")
|
|
273
|
+
self._kv_store = {}
|
|
274
|
+
if os.path.exists(self._store_file):
|
|
275
|
+
try:
|
|
276
|
+
with open(self._store_file, "r") as f:
|
|
277
|
+
self._kv_store = json.load(f)
|
|
278
|
+
except Exception as e:
|
|
279
|
+
self.logger.warning(f"Failed to load persistent store: {e}")
|
|
280
|
+
|
|
281
|
+
def store_set(self, key, value):
|
|
282
|
+
"""Sets a value in the persistent store."""
|
|
283
|
+
self._kv_store[key] = value
|
|
284
|
+
self._save_store()
|
|
285
|
+
|
|
286
|
+
def store_get(self, key, default=None):
|
|
287
|
+
"""Gets a value from the persistent store."""
|
|
288
|
+
return self._kv_store.get(key, default)
|
|
289
|
+
|
|
290
|
+
def store_delete(self, key):
|
|
291
|
+
"""Removes a key from the persistent store."""
|
|
292
|
+
if key in self._kv_store:
|
|
293
|
+
del self._kv_store[key]
|
|
294
|
+
self._save_store()
|
|
295
|
+
return True
|
|
296
|
+
return False
|
|
297
|
+
|
|
298
|
+
def _save_store(self):
|
|
299
|
+
try:
|
|
300
|
+
with open(self._store_file, "w") as f:
|
|
301
|
+
json.dump(self._kv_store, f)
|
|
302
|
+
except Exception as e:
|
|
303
|
+
self.logger.error(f"Failed to save persistent store: {e}")
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import time
|
|
2
|
+
import os
|
|
3
|
+
import threading
|
|
4
|
+
import logging
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class DeadMansSwitch:
|
|
8
|
+
"""
|
|
9
|
+
Ensures that if the UI process (Child) dies, the Backend (Parent) commits seppuku immediately.
|
|
10
|
+
Preventing zombie python processes in the background.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
def __init__(self, ui_process):
|
|
14
|
+
"""
|
|
15
|
+
ui_process: The subprocess.Popen object of electron.exe or webview
|
|
16
|
+
"""
|
|
17
|
+
self.proc = ui_process
|
|
18
|
+
self.running = True
|
|
19
|
+
self.logger = logging.getLogger("Pytron.DeadMansSwitch")
|
|
20
|
+
self._thread = threading.Thread(target=self._monitor, daemon=True)
|
|
21
|
+
self._thread.start()
|
|
22
|
+
|
|
23
|
+
def _monitor(self):
|
|
24
|
+
while self.running:
|
|
25
|
+
try:
|
|
26
|
+
# 1. Check if Child (UI) is alive
|
|
27
|
+
if self.proc.poll() is not None:
|
|
28
|
+
self.logger.warning(
|
|
29
|
+
f"UI Process {self.proc.pid} died. Exiting backend..."
|
|
30
|
+
)
|
|
31
|
+
self.kill_backend()
|
|
32
|
+
|
|
33
|
+
# 2. Check if Parent (Launcher) is alive
|
|
34
|
+
# (Only needed if Pytron itself is launched by another tool)
|
|
35
|
+
# if os.getppid() == 1: # On Linux, adopted by init
|
|
36
|
+
# self.kill_backend()
|
|
37
|
+
|
|
38
|
+
time.sleep(1) # Low overhead polling
|
|
39
|
+
except Exception:
|
|
40
|
+
# If we can't poll, something is wrong
|
|
41
|
+
self.kill_backend()
|
|
42
|
+
|
|
43
|
+
def kill_backend(self):
|
|
44
|
+
self.running = False
|
|
45
|
+
self.logger.critical("Dead Man's Switch Triggered.")
|
|
46
|
+
# Hard exit to ensure we don't hang on cleanup
|
|
47
|
+
os._exit(0)
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from ..tray import SystemTray
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class ExtrasMixin:
|
|
6
|
+
def load_plugin(self, manifest_path):
|
|
7
|
+
from ..plugin import Plugin, PluginError
|
|
8
|
+
|
|
9
|
+
try:
|
|
10
|
+
plugin = Plugin(manifest_path)
|
|
11
|
+
plugin.check_dependencies()
|
|
12
|
+
plugin.load(self)
|
|
13
|
+
self.plugins.append(plugin)
|
|
14
|
+
self.logger.info(f"Loaded plugin: {plugin.name} v{plugin.version}")
|
|
15
|
+
except PluginError as e:
|
|
16
|
+
self.logger.error(f"Failed to load plugin from {manifest_path}: {e}")
|
|
17
|
+
except Exception as e:
|
|
18
|
+
self.logger.error(
|
|
19
|
+
f"Unexpected error loading plugin from {manifest_path}: {e}"
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
def setup_tray(self, title=None, icon=None):
|
|
23
|
+
if not title:
|
|
24
|
+
title = self.config.get("title", "Pytron")
|
|
25
|
+
if not icon and "icon" in self.config:
|
|
26
|
+
icon = self.config["icon"]
|
|
27
|
+
if icon and not os.path.isabs(icon):
|
|
28
|
+
icon = os.path.join(self.app_root, icon)
|
|
29
|
+
self.tray = SystemTray(title, icon)
|
|
30
|
+
return self.tray
|
|
31
|
+
|
|
32
|
+
def setup_tray_standard(self, title=None, icon=None):
|
|
33
|
+
# Native Engine Check
|
|
34
|
+
if hasattr(self, "engine") and self.engine == "native":
|
|
35
|
+
# We assume window 0 is main.
|
|
36
|
+
# If windows aren't created yet, we can't create tray on native easily unless we cache it.
|
|
37
|
+
# But setup_tray is usually called before run().
|
|
38
|
+
# The native tray requires the event loop (which starts in run()).
|
|
39
|
+
# So we should queue this creation?
|
|
40
|
+
# Or we leverage the fact that user calls `app.setup_tray` then `app.run`.
|
|
41
|
+
# `app.run` calls `self.windows[0].start()`.
|
|
42
|
+
# `webview.py` start connects bindings.
|
|
43
|
+
|
|
44
|
+
# The best way is to let `webview.create_tray` happen AFTER run starts?
|
|
45
|
+
# No, `create_tray` sends an event. If loop not started, event is lost or queued?
|
|
46
|
+
# `EventLoopProxy` can send events before run? Yes, usually.
|
|
47
|
+
|
|
48
|
+
if not title:
|
|
49
|
+
title = self.config.get("title", "Pytron")
|
|
50
|
+
if not icon:
|
|
51
|
+
icon = self.config.get("icon")
|
|
52
|
+
if icon and not os.path.isabs(icon):
|
|
53
|
+
icon = os.path.join(self.app_root, icon)
|
|
54
|
+
|
|
55
|
+
# We defer this to the first window's initialization if possible, or sets a config?
|
|
56
|
+
# Actually, if we just call it on the window instance, and the window exists...
|
|
57
|
+
# app.windows is empty at setup time usually?
|
|
58
|
+
# In `app.py`: `app = App(...)`, `app.create_window(...)`, `app.setup_tray...`
|
|
59
|
+
# If create_window already added to self.windows, then yes.
|
|
60
|
+
|
|
61
|
+
if self.windows:
|
|
62
|
+
try:
|
|
63
|
+
self.windows[0].create_tray(icon, title)
|
|
64
|
+
self.logger.info("Used Native Tray integration.")
|
|
65
|
+
# Enable Close-to-Tray for standard tray setup
|
|
66
|
+
self.windows[0].config["close_to_tray"] = True
|
|
67
|
+
return None
|
|
68
|
+
except Exception as e:
|
|
69
|
+
self.logger.warning(f"Native Tray failed, falling back: {e}")
|
|
70
|
+
|
|
71
|
+
tray = self.setup_tray(title, icon)
|
|
72
|
+
tray.add_item("Show App", self.show)
|
|
73
|
+
tray.add_item("Hide App", self.hide)
|
|
74
|
+
tray.add_separator()
|
|
75
|
+
tray.add_item("Quit", self.quit)
|
|
76
|
+
return tray
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
import os
|
|
3
|
+
from typing import Optional
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class NativeMixin:
|
|
7
|
+
"""
|
|
8
|
+
Mixin class to handle native system interactions.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
def set_start_on_boot(self, enable=True):
|
|
12
|
+
"""
|
|
13
|
+
Enables or disables automatic application startup on system boot.
|
|
14
|
+
"""
|
|
15
|
+
app_name = self.config.get("title", "PytronApp")
|
|
16
|
+
# Sanitize for registry key
|
|
17
|
+
safe_name = "".join(c if c.isalnum() else "_" for c in app_name)
|
|
18
|
+
|
|
19
|
+
if not getattr(sys, "frozen", False):
|
|
20
|
+
self.logger.info("Skipping Start-on-Boot registration in Development Mode.")
|
|
21
|
+
return False
|
|
22
|
+
|
|
23
|
+
exe_path = f'"{sys.executable}"' # Quote for safety
|
|
24
|
+
|
|
25
|
+
# We need a platform instance.
|
|
26
|
+
# Since App doesn't hold it, we instantiate temporarily or grab from first window
|
|
27
|
+
if self.windows:
|
|
28
|
+
# Best effort
|
|
29
|
+
try:
|
|
30
|
+
return self.windows[0]._platform.set_launch_on_boot(
|
|
31
|
+
safe_name, exe_path, enable
|
|
32
|
+
)
|
|
33
|
+
except Exception as e:
|
|
34
|
+
self.logger.debug(f"Failed to set start on boot via window: {e}")
|
|
35
|
+
|
|
36
|
+
# Fallback if no window yet or needed
|
|
37
|
+
try:
|
|
38
|
+
import platform
|
|
39
|
+
|
|
40
|
+
sys_plat = platform.system()
|
|
41
|
+
impl = None
|
|
42
|
+
if sys_plat == "Windows":
|
|
43
|
+
from ..platforms.windows import WindowsImplementation
|
|
44
|
+
|
|
45
|
+
impl = WindowsImplementation()
|
|
46
|
+
elif sys_plat == "Linux":
|
|
47
|
+
from ..platforms.linux import LinuxImplementation
|
|
48
|
+
|
|
49
|
+
impl = LinuxImplementation()
|
|
50
|
+
elif sys_plat == "Darwin":
|
|
51
|
+
from ..platforms.darwin import DarwinImplementation
|
|
52
|
+
|
|
53
|
+
impl = DarwinImplementation()
|
|
54
|
+
|
|
55
|
+
if impl:
|
|
56
|
+
return impl.set_launch_on_boot(safe_name, exe_path, enable)
|
|
57
|
+
except Exception as e:
|
|
58
|
+
self.logger.warning(f"Could not set start on boot: {e}")
|
|
59
|
+
|
|
60
|
+
def message_box(self, title, message, style=0):
|
|
61
|
+
"""
|
|
62
|
+
Shows a native message box.
|
|
63
|
+
Styles: 0=OK, 1=OK/Cancel, 2=Abort/Retry/Ignore, 3=Yes/No/Cancel, 4=Yes/No, 5=Retry/Cancel
|
|
64
|
+
Returns: 1=OK, 2=Cancel, 6=Yes, 7=No
|
|
65
|
+
"""
|
|
66
|
+
if self.windows:
|
|
67
|
+
return self.windows[0].message_box(title, message, style)
|
|
68
|
+
return 0
|
|
69
|
+
|
|
70
|
+
def dialog_save_file(
|
|
71
|
+
self, title="Save File", default_path=None, default_name=None, file_types=None
|
|
72
|
+
):
|
|
73
|
+
"""Opens a native save file dialog. Returns the selected path or None."""
|
|
74
|
+
if self.windows:
|
|
75
|
+
return self.windows[0].dialog_save_file(
|
|
76
|
+
title, default_path, default_name, file_types
|
|
77
|
+
)
|
|
78
|
+
return None
|
|
79
|
+
|
|
80
|
+
def dialog_open_file(self, title="Open File", default_path=None, file_types=None):
|
|
81
|
+
"""Opens a native file selection dialog. Returns the selected path or None."""
|
|
82
|
+
if self.windows:
|
|
83
|
+
return self.windows[0].dialog_open_file(title, default_path, file_types)
|
|
84
|
+
return None
|
|
85
|
+
|
|
86
|
+
def dialog_open_folder(self, title="Select Folder", default_path=None):
|
|
87
|
+
"""Opens a native folder selection dialog. Returns the selected path or None."""
|
|
88
|
+
if self.windows:
|
|
89
|
+
return self.windows[0].dialog_open_folder(title, default_path)
|
|
90
|
+
return None
|
|
91
|
+
|
|
92
|
+
def system_notification(self, title: Optional[str] = None, message: str = ""):
|
|
93
|
+
"""Sends a system-level (tray/toast) notification via the OS."""
|
|
94
|
+
if not title:
|
|
95
|
+
title = self.config.get("author", self.config.get("title", "Pytron"))
|
|
96
|
+
|
|
97
|
+
icon = self.config.get("icon")
|
|
98
|
+
|
|
99
|
+
if self.windows:
|
|
100
|
+
for window in self.windows:
|
|
101
|
+
try:
|
|
102
|
+
window.system_notification(title, message, icon=icon)
|
|
103
|
+
break
|
|
104
|
+
except Exception as e:
|
|
105
|
+
self.logger.debug(
|
|
106
|
+
f"Failed to send notification via window {window}: {e}"
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
def copy_to_clipboard(self, text: str):
|
|
110
|
+
"""Copies text to the system clipboard."""
|
|
111
|
+
if self.windows:
|
|
112
|
+
return self.windows[0]._platform.set_clipboard_text(text)
|
|
113
|
+
return False
|
|
114
|
+
|
|
115
|
+
def get_clipboard_text(self):
|
|
116
|
+
"""Returns text from the system clipboard."""
|
|
117
|
+
if self.windows:
|
|
118
|
+
return self.windows[0]._platform.get_clipboard_text()
|
|
119
|
+
return None
|
|
120
|
+
|
|
121
|
+
def get_system_info(self):
|
|
122
|
+
"""Returns hardware and OS information."""
|
|
123
|
+
if self.windows:
|
|
124
|
+
return self.windows[0]._platform.get_system_info()
|
|
125
|
+
|
|
126
|
+
# Fallback if no window
|
|
127
|
+
import platform
|
|
128
|
+
|
|
129
|
+
return {"os": platform.system(), "arch": platform.machine()}
|
|
130
|
+
|
|
131
|
+
def store_set(self, key: str, value):
|
|
132
|
+
"""Persists a value to the app's local storage."""
|
|
133
|
+
# Fix recursion: This was incorrectly calling self.store_set instead of the ConfigMixin implementation
|
|
134
|
+
if hasattr(super(), "store_set"):
|
|
135
|
+
return super().store_set(key, value)
|
|
136
|
+
return False
|
|
137
|
+
|
|
138
|
+
def store_get(self, key: str, default=None):
|
|
139
|
+
"""Retrieves a persisted value from the app's local storage."""
|
|
140
|
+
if hasattr(super(), "store_get"):
|
|
141
|
+
return super().store_get(key, default)
|
|
142
|
+
return default
|
|
143
|
+
|
|
144
|
+
def store_delete(self, key: str):
|
|
145
|
+
"""Removes a persisted value."""
|
|
146
|
+
if hasattr(super(), "store_delete"):
|
|
147
|
+
return super().store_delete(key)
|
|
148
|
+
return False
|
pytron/apputils/shell.py
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import subprocess
|
|
3
|
+
import platform
|
|
4
|
+
|
|
5
|
+
import shutil
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class Shell:
|
|
9
|
+
"""
|
|
10
|
+
Native OS Shell utilities for Pytron.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
@staticmethod
|
|
14
|
+
def _resolve_bin(bin_name):
|
|
15
|
+
return shutil.which(bin_name) or bin_name
|
|
16
|
+
|
|
17
|
+
@staticmethod
|
|
18
|
+
def open_external(url: str):
|
|
19
|
+
"""
|
|
20
|
+
Opens a URL or file path in the default system browser/handler.
|
|
21
|
+
"""
|
|
22
|
+
if platform.system() == "Windows":
|
|
23
|
+
os.startfile(url)
|
|
24
|
+
elif platform.system() == "Darwin":
|
|
25
|
+
bin_path = Shell._resolve_bin("open")
|
|
26
|
+
subprocess.run([bin_path, url])
|
|
27
|
+
else:
|
|
28
|
+
bin_path = Shell._resolve_bin("xdg-open")
|
|
29
|
+
subprocess.run([bin_path, url])
|
|
30
|
+
|
|
31
|
+
@staticmethod
|
|
32
|
+
def show_item_in_folder(path: str):
|
|
33
|
+
"""
|
|
34
|
+
Opens the folder containing the file and selects it.
|
|
35
|
+
"""
|
|
36
|
+
path = os.path.abspath(path)
|
|
37
|
+
if platform.system() == "Windows":
|
|
38
|
+
bin_path = Shell._resolve_bin("explorer")
|
|
39
|
+
subprocess.run([bin_path, "/select,", path])
|
|
40
|
+
elif platform.system() == "Darwin":
|
|
41
|
+
bin_path = Shell._resolve_bin("open")
|
|
42
|
+
subprocess.run([bin_path, "-R", path])
|
|
43
|
+
else:
|
|
44
|
+
# Linux doesn't have a universal 'select' but we can open the dir
|
|
45
|
+
bin_path = Shell._resolve_bin("xdg-open")
|
|
46
|
+
subprocess.run([bin_path, os.path.dirname(path)])
|
|
47
|
+
|
|
48
|
+
@staticmethod
|
|
49
|
+
def trash_item(path: str):
|
|
50
|
+
"""
|
|
51
|
+
Moves a file to the system trash/recycle bin.
|
|
52
|
+
Requires 'send2trash' library if available, else fails.
|
|
53
|
+
"""
|
|
54
|
+
try:
|
|
55
|
+
import logging
|
|
56
|
+
|
|
57
|
+
logger = logging.getLogger("Pytron.Shell")
|
|
58
|
+
from send2trash import send2trash
|
|
59
|
+
|
|
60
|
+
send2trash(path)
|
|
61
|
+
return True
|
|
62
|
+
except ImportError:
|
|
63
|
+
import logging
|
|
64
|
+
|
|
65
|
+
logging.getLogger("Pytron.Shell").warning(
|
|
66
|
+
"send2trash is not installed. File cannot be moved to trash."
|
|
67
|
+
)
|
|
68
|
+
return False
|
|
69
|
+
except Exception as e:
|
|
70
|
+
import logging
|
|
71
|
+
|
|
72
|
+
logging.getLogger("Pytron.Shell").error(f"Failed to trash item: {e}")
|
|
73
|
+
return False
|