linux: fix URLs not opening in PyInstaller package
Because PyInstaller modifies the LD_LIBRARY_PATH environment variable to make things work correctly on Linux, when we try to launch any subprocess (such as the web browser), that modified variable gets picked up as well, causing things to go south. To work around this Linux-only problem, we have to: 1. Save the current value of LD_LIBRARY_PATH 2. Move the value of LD_LIBRARY_PATH_ORIG to LD_LIBRARY_PATH 3. Launch subprocess 4. Restore the saved LD_LIBRARY_PATH again Reference: https://pyinstaller.org/en/stable/runtime-information.html#ld-library-path-libpath-considerations Co-authored-by: DevilXD <bartosz.peszek@gmail.com>
This commit is contained in:
1 parent
e31dcd85b4
commit
5162e5c553
2 files changed
+32
-8
No files matched your search
@@ -6,7 +6,6 @@ import sys
|
|||||||
import ctypes
|
import ctypes
|
||||||
import asyncio
|
import asyncio
|
||||||
import logging
|
import logging
|
||||||
import webbrowser
|
|
||||||
import tkinter as tk
|
import tkinter as tk
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from collections import abc
|
from collections import abc
|
||||||
@@ -32,7 +31,7 @@ if sys.platform == "win32":
|
|||||||
from translate import _
|
from translate import _
|
||||||
from cache import ImageCache
|
from cache import ImageCache
|
||||||
from exceptions import ExitRequest
|
from exceptions import ExitRequest
|
||||||
from utils import resource_path, set_root_icon, Game, _T
|
from utils import resource_path, set_root_icon, webopen, Game, _T
|
||||||
from constants import (
|
from constants import (
|
||||||
SELF_PATH, OUTPUT_FORMATTER, WS_TOPICS_LIMIT, MAX_WEBSOCKETS, WINDOW_TITLE, State
|
SELF_PATH, OUTPUT_FORMATTER, WS_TOPICS_LIMIT, MAX_WEBSOCKETS, WINDOW_TITLE, State
|
||||||
)
|
)
|
||||||
@@ -344,10 +343,7 @@ class LinkLabel(ttk.Label):
|
|||||||
# W, N, E, S
|
# W, N, E, S
|
||||||
kwargs["padding"] = (0, 2, 0, 2)
|
kwargs["padding"] = (0, 2, 0, 2)
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
self.bind("<ButtonRelease-1>", self.webopen(self._link))
|
self.bind("<ButtonRelease-1>", lambda e: webopen(self._link))
|
||||||
|
|
||||||
def webopen(self, url: str):
|
|
||||||
return lambda e: webbrowser.open_new_tab(url)
|
|
||||||
|
|
||||||
|
|
||||||
class SelectMenu(tk.Menubutton, Generic[_T]):
|
class SelectMenu(tk.Menubutton, Generic[_T]):
|
||||||
@@ -558,7 +554,7 @@ class LoginForm:
|
|||||||
self._manager.print(_("gui", "login", "request"))
|
self._manager.print(_("gui", "login", "request"))
|
||||||
await self.wait_for_login_press()
|
await self.wait_for_login_press()
|
||||||
self._manager.print(f"Enter this code on the Twitch's device activation page: {user_code}")
|
self._manager.print(f"Enter this code on the Twitch's device activation page: {user_code}")
|
||||||
webbrowser.open_new_tab("https://www.twitch.tv/activate")
|
webopen("https://www.twitch.tv/activate")
|
||||||
|
|
||||||
def update(self, status: str, user_id: int | None):
|
def update(self, status: str, user_id: int | None):
|
||||||
if user_id is not None:
|
if user_id is not None:
|
||||||
|
|||||||
@@ -1,11 +1,14 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
import json
|
import json
|
||||||
import random
|
import random
|
||||||
import string
|
import string
|
||||||
import asyncio
|
import asyncio
|
||||||
import logging
|
import logging
|
||||||
import traceback
|
import traceback
|
||||||
|
import webbrowser
|
||||||
import tkinter as tk
|
import tkinter as tk
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
@@ -21,7 +24,7 @@ import yarl
|
|||||||
from PIL.ImageTk import PhotoImage
|
from PIL.ImageTk import PhotoImage
|
||||||
from PIL import Image as Image_module
|
from PIL import Image as Image_module
|
||||||
|
|
||||||
from constants import JsonType
|
from constants import JsonType, IS_PACKAGED
|
||||||
from exceptions import ExitRequest, ReloadRequest
|
from exceptions import ExitRequest, ReloadRequest
|
||||||
from constants import _resource_path as resource_path # noqa
|
from constants import _resource_path as resource_path # noqa
|
||||||
|
|
||||||
@@ -213,6 +216,31 @@ def json_save(path: Path, contents: Mapping[Any, Any], *, sort: bool = False) ->
|
|||||||
json.dump(contents, file, default=_serialize, sort_keys=sort, indent=4)
|
json.dump(contents, file, default=_serialize, sort_keys=sort, indent=4)
|
||||||
|
|
||||||
|
|
||||||
|
def webopen(url: str):
|
||||||
|
if IS_PACKAGED and sys.platform == "linux":
|
||||||
|
# https://pyinstaller.org/en/stable/
|
||||||
|
# runtime-information.html#ld-library-path-libpath-considerations
|
||||||
|
# NOTE: All 4 cases need to be handled here: either of the two values can be there or not.
|
||||||
|
ld_env = "LD_LIBRARY_PATH"
|
||||||
|
ld_path_curr = os.environ.get(ld_env)
|
||||||
|
ld_path_orig = os.environ.get(f"{ld_env}_ORIG")
|
||||||
|
if ld_path_orig is not None:
|
||||||
|
os.environ[ld_env] = ld_path_orig
|
||||||
|
elif ld_path_curr is not None:
|
||||||
|
# pop current
|
||||||
|
os.environ.pop(ld_env)
|
||||||
|
|
||||||
|
webbrowser.open_new_tab(url)
|
||||||
|
|
||||||
|
if ld_path_curr is not None:
|
||||||
|
os.environ[ld_env] = ld_path_curr
|
||||||
|
elif ld_path_orig is not None:
|
||||||
|
# pop original
|
||||||
|
os.environ.pop(ld_env)
|
||||||
|
else:
|
||||||
|
webbrowser.open_new_tab(url)
|
||||||
|
|
||||||
|
|
||||||
class ExponentialBackoff:
|
class ExponentialBackoff:
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
|
|||||||
Reference in new issue
Block a user