diff --git a/sbapp/compat.py b/sbapp/compat.py new file mode 100644 index 0000000..d9e2252 --- /dev/null +++ b/sbapp/compat.py @@ -0,0 +1,43 @@ +def python314_kivy_patch(): + print("Running Kivy on Python 3.14+ detected, checking compatibility patch...") + import os + import importlib.util + from pathlib import Path + + def fail_patch(): + print("Error: Failed to open Kivy's lang/parser.py file for patching.") + print("Kivy currently has bugs that prevents it from running on Python 3.14") + print("and above, and this file needs to be patched to run Sideband.") + print("\nYou can patch this manually by locating the lang/parser.py file") + print(f"and replacing:\n\n{kivy_target_1}\n\nWith:\n\n{kivy_patch_1}\n") + os._exit(0) + + kivy_target_1 = """ if isinstance(node, (ast.JoinedStr, ast.BoolOp)): + for n in node.values: + if isinstance(n, ast.Str): + # NOTE: required for python3.6 + yield from cls.get_names_from_expression(n.s) + else: + yield from cls.get_names_from_expression(n.value)""" + + kivy_patch_1 = """ if isinstance(node, (ast.JoinedStr, ast.BoolOp)): + for n in node.values: + yield from cls.get_names_from_expression(n.value)""" + + spec = importlib.util.find_spec("kivy") + if spec is None or spec.origin is None or spec.submodule_search_locations is None: fail_patch() + contents = None + + target_path = f"{spec.submodule_search_locations[0]}/lang/parser.py" + with open(target_path, "rb") as fh: contents = fh.read().decode("utf-8") + if not contents: fail_patch() + contents = contents.replace("\r\n", "\n") + + if kivy_patch_1 in contents: print("Kivy already patched for Python 3.14 compatibility, continuing.") + if kivy_target_1 in contents: + print("Patching Kivy for Python 3.14 compatibility...") + contents = contents.replace(kivy_target_1, kivy_patch_1) + if not kivy_patch_1 in contents: fail_patch() + with open(target_path, "wb") as fh: + fh.write(contents.encode("utf-8")) + print("Kivy successfully patched for Python 3.14 compatibility") diff --git a/sbapp/main.py b/sbapp/main.py index 61e6f82..8fe040b 100644 --- a/sbapp/main.py +++ b/sbapp/main.py @@ -75,7 +75,6 @@ def get_display_res(): RNS.trace_exception(e) return None, None - def apply_ui_scale(): global app_ui_scaling_path global app_ui_wcfg_path @@ -149,6 +148,15 @@ def apply_ui_scale(): except Exception as e: RNS.log(f"Error while reading saved window configuration: {e}", RNS.LOG_ERROR) +################################################### +# Run-time patch to fix broken Kivy on Python 3.14 +# until a Kivy release is made that actually works. +# +if sys.version_info[0] >= 3 and sys.version_info[1] >= 14: + if RNS.vendor.platformutils.is_linux(): + from .compat import python314_kivy_patch + python314_kivy_patch() + ################################################### # Kivy/SDL2 run-time patch to fix horribly slow # window resize updates on Linux. For more info: