Implemented runtime patch to fix broken Kivy on Python 3.14+

This commit is contained in:
Mark Qvist 2026-04-13 13:56:55 +02:00
commit 1fe28ae702
2 changed files with 52 additions and 1 deletions

43
sbapp/compat.py Normal file
View file

@ -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")

View file

@ -75,7 +75,6 @@ def get_display_res():
RNS.trace_exception(e) RNS.trace_exception(e)
return None, None return None, None
def apply_ui_scale(): def apply_ui_scale():
global app_ui_scaling_path global app_ui_scaling_path
global app_ui_wcfg_path global app_ui_wcfg_path
@ -149,6 +148,15 @@ def apply_ui_scale():
except Exception as e: except Exception as e:
RNS.log(f"Error while reading saved window configuration: {e}", RNS.LOG_ERROR) 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 # Kivy/SDL2 run-time patch to fix horribly slow
# window resize updates on Linux. For more info: # window resize updates on Linux. For more info: