support running in pywebview in windows.

This commit is contained in:
arabcoders 2025-07-07 18:37:11 +03:00
parent 7a557027be
commit 37dab36fc9
8 changed files with 53 additions and 12 deletions

View file

@ -23,6 +23,7 @@
"consoletitle", "consoletitle",
"cookiesfrombrowser", "cookiesfrombrowser",
"copyts", "copyts",
"creationflags",
"cronsim", "cronsim",
"datas", "datas",
"dateparser", "dateparser",

View file

@ -42,10 +42,18 @@ class PackageInstaller:
return return
LOG.info(f"'{pkg}' is already installed. Checking for upgrades...") LOG.info(f"'{pkg}' is already installed. Checking for upgrades...")
subprocess.run([sys.executable, "-m", "pip", "install", "--upgrade", pkg], check=True) # noqa: S603 subprocess.run(
[sys.executable, "-m", "pip", "install", "--upgrade", pkg],
check=True,
creationflags=subprocess.CREATE_NO_WINDOW if os.name == "nt" else 0,
)
except ImportError: except ImportError:
LOG.info(f"'{pkg}' is not installed. Installing...") LOG.info(f"'{pkg}' is not installed. Installing...")
subprocess.run([sys.executable, "-m", "pip", "install", pkg], check=True) # noqa: S603 subprocess.run(
[sys.executable, "-m", "pip", "install", pkg],
check=True,
creationflags=subprocess.CREATE_NO_WINDOW if os.name == "nt" else 0,
)
def check(self, pkgs: Packages): def check(self, pkgs: Packages):
""" """

View file

@ -1,6 +1,8 @@
import asyncio import asyncio
import hashlib import hashlib
import logging import logging
import os
import subprocess
import tempfile import tempfile
from pathlib import Path from pathlib import Path
@ -86,6 +88,7 @@ class Segments:
stdin=asyncio.subprocess.DEVNULL, stdin=asyncio.subprocess.DEVNULL,
stdout=asyncio.subprocess.PIPE, stdout=asyncio.subprocess.PIPE,
stderr=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE,
creationflags=subprocess.CREATE_NO_WINDOW if os.name == "nt" else 0,
) )
client_disconnected = False client_disconnected = False

View file

@ -348,7 +348,10 @@ class Config:
raise TypeError(msg) raise TypeError(msg)
coloredlogs.install( coloredlogs.install(
level=numeric_level, fmt="%(asctime)s [%(name)s] [%(levelname)-5.5s] %(message)s", datefmt="%H:%M:%S" level=numeric_level,
fmt="%(asctime)s [%(name)s] [%(levelname)-5.5s] %(message)s",
datefmt="%H:%M:%S",
encoding="utf-8",
) )
LOG = logging.getLogger("config") LOG = logging.getLogger("config")
@ -427,6 +430,7 @@ class Config:
filename=loggingPath / "app.log", filename=loggingPath / "app.log",
when="midnight", when="midnight",
backupCount=3, backupCount=3,
encoding="utf-8",
) )
handler.setLevel(log_level_file) handler.setLevel(log_level_file)
@ -545,6 +549,7 @@ class Config:
capture_output=True, capture_output=True,
text=True, text=True,
check=False, check=False,
creationflags=subprocess.CREATE_NO_WINDOW if os.name == "nt" else 0,
) )
if 0 != branch_result.returncode: if 0 != branch_result.returncode:
@ -562,6 +567,7 @@ class Config:
capture_output=True, capture_output=True,
text=True, text=True,
check=False, check=False,
creationflags=subprocess.CREATE_NO_WINDOW if os.name == "nt" else 0,
) )
if 0 != commit_result.returncode: if 0 != commit_result.returncode:

View file

@ -7,6 +7,7 @@ import functools
import json import json
import operator import operator
import os import os
import subprocess
from pathlib import Path from pathlib import Path
import anyio import anyio
@ -267,7 +268,13 @@ async def ffprobe(file: str) -> FFProbeResult:
""" """
try: try:
async with await anyio.open_file(os.devnull, "w") as tempf: async with await anyio.open_file(os.devnull, "w") as tempf:
await asyncio.create_subprocess_exec("ffprobe", "-h", stdout=tempf, stderr=tempf) await asyncio.create_subprocess_exec(
"ffprobe",
"-h",
stdout=tempf,
stderr=tempf,
creationflags=subprocess.CREATE_NO_WINDOW if os.name == "nt" else 0,
)
except FileNotFoundError as e: except FileNotFoundError as e:
msg = "ffprobe not found." msg = "ffprobe not found."
raise OSError(msg) from e raise OSError(msg) from e
@ -283,6 +290,7 @@ async def ffprobe(file: str) -> FFProbeResult:
*args, *args,
stdout=asyncio.subprocess.PIPE, stdout=asyncio.subprocess.PIPE,
stderr=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE,
creationflags=subprocess.CREATE_NO_WINDOW if os.name == "nt" else 0,
) )
exitCode = await p.wait() exitCode = await p.wait()

View file

@ -155,4 +155,7 @@ class Main:
if __name__ == "__main__": if __name__ == "__main__":
logging.basicConfig(level=logging.DEBUG) logging.basicConfig(level=logging.DEBUG)
from multiprocessing import freeze_support
freeze_support()
Main().start() Main().start()

View file

@ -107,26 +107,33 @@ def run_backend(host: str, port: int, ready_event: threading.Event, error_queue:
ready_event.set() ready_event.set()
def get_usable_port(host: str = "127.0.0.1") -> int:
"""
Get a usable port on the specified host.
If no port is available, it will raise an OSError.
"""
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.bind((host, 0))
port = s.getsockname()[1]
s.close()
return port
def main(): def main():
host = "127.0.0.1" host = "127.0.0.1"
set_env() set_env()
cfg_path: Path = Path(os.getenv("YTP_CONFIG_PATH")) / "webview.json" cfg_path: Path = Path(os.getenv("YTP_CONFIG_PATH")) / "webview.json"
port = None
win_conf: dict[str, int] = {} win_conf: dict[str, int] = {}
if cfg_path.exists(): if cfg_path.exists():
data = json.loads(cfg_path.read_text()) data = json.loads(cfg_path.read_text())
port = data.get("port")
for key in ("width", "height", "x", "y"): for key in ("width", "height", "x", "y"):
if key in data: if key in data:
win_conf[key] = data[key] win_conf[key] = data[key]
if not port: port = get_usable_port(host)
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.bind((host, 0))
port = s.getsockname()[1]
cfg_path.write_text(json.dumps({"port": port}))
ready = threading.Event() ready = threading.Event()
errors: queue.Queue = queue.Queue() errors: queue.Queue = queue.Queue()
@ -170,6 +177,9 @@ def main():
if __name__ == "__main__": if __name__ == "__main__":
try: try:
from multiprocessing import freeze_support
freeze_support()
main() main()
except Exception as e: except Exception as e:
logging.exception(e) logging.exception(e)

View file

@ -1,4 +1,5 @@
import logging import logging
import os
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
from app.library.config import Config from app.library.config import Config
@ -25,8 +26,8 @@ async def cli_post(config: Config, notify: EventBus, sid: str, data: str):
import asyncio import asyncio
import errno import errno
import os
import shlex import shlex
import subprocess # ignore
try: try:
LOG.info(f"Cli command from client '{sid}'. '{data}'") LOG.info(f"Cli command from client '{sid}'. '{data}'")
@ -66,6 +67,7 @@ async def cli_post(config: Config, notify: EventBus, sid: str, data: str):
stdout=stdout_arg, stdout=stdout_arg,
stderr=stderr_arg, stderr=stderr_arg,
env=_env, env=_env,
creationflags=subprocess.CREATE_NO_WINDOW if os.name == "nt" else 0,
) )
if use_pty: if use_pty: