Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 13 additions & 7 deletions sdk/python/packages/flet/src/flet/async_local_socket_connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import tempfile
import threading
from pathlib import Path
from typing import List
from typing import List, Optional

from flet.utils import get_free_tcp_port, is_windows
from flet_core.local_connection import LocalConnection
Expand All @@ -27,18 +27,19 @@ class AsyncLocalSocketConnection(LocalConnection):
def __init__(
self,
port: int = 0,
uds_path: Optional[str] = None,
on_event=None,
on_session_created=None,
):
super().__init__()
self.__send_queue = asyncio.Queue(1)
self.__port = port
self.__uds_path = uds_path
self.__on_event = on_event
self.__on_session_created = on_session_created

async def connect(self):
self.__connected = False
self.__uds_path = None
if is_windows() or self.__port > 0:
# TCP
host = "localhost"
Expand All @@ -49,9 +50,10 @@ async def connect(self):
self.__server = asyncio.create_task(server.serve_forever())
else:
# UDS
self.__uds_path = str(
Path(tempfile.gettempdir()).joinpath(random_string(10))
)
if not self.__uds_path:
self.__uds_path = str(
Path(tempfile.gettempdir()).joinpath(random_string(10))
)
self.page_url = self.__uds_path
logging.info(f"Starting up UDS server on {self.__uds_path}")
server = await asyncio.start_unix_server(
Expand All @@ -65,8 +67,8 @@ async def handle_connection(
if not self.__connected:
self.__connected = True
logging.debug("Connected new TCP client")
asyncio.create_task(self.__receive_loop(reader))
asyncio.create_task(self.__send_loop(writer))
self.__receive_loop_task = asyncio.create_task(self.__receive_loop(reader))
self.__send_loop_task = asyncio.create_task(self.__send_loop(writer))

async def __receive_loop(self, reader: asyncio.StreamReader):
while True:
Expand Down Expand Up @@ -156,6 +158,10 @@ async def __send(self, message: ClientMessage):
async def close(self):
logging.debug("Closing connection...")
# close socket
if self.__receive_loop_task:
self.__receive_loop_task.cancel()
if self.__send_loop_task:
self.__send_loop_task.cancel()
if self.__server:
self.__server.cancel()

Expand Down
24 changes: 18 additions & 6 deletions sdk/python/packages/flet/src/flet/cli/commands/run.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
import argparse
import os
import signal
import subprocess
import sys
import tempfile
import threading
import time
from pathlib import Path

from flet.cli.commands.base import BaseCommand
from flet.flet import close_flet_view, open_flet_view
from flet.utils import get_free_tcp_port, open_in_browser
from flet.utils import get_free_tcp_port, is_windows, open_in_browser
from flet_core.utils import random_string
from watchdog.events import FileSystemEventHandler
from watchdog.observers import Observer

Expand Down Expand Up @@ -82,9 +85,13 @@ def handle(self, options: argparse.Namespace) -> None:
script_dir = os.path.dirname(script_path)

port = options.port
if options.port is None:
if port is None and is_windows():
port = get_free_tcp_port()

uds_path = None
if port is None and not is_windows():
uds_path = str(Path(tempfile.gettempdir()).joinpath(random_string(10)))

assets_dir = options.assets_dir
if assets_dir and not Path(assets_dir).is_absolute():
assets_dir = str(
Expand All @@ -95,6 +102,7 @@ def handle(self, options: argparse.Namespace) -> None:
[sys.executable, "-u", script_path],
None if options.directory or options.recursive else script_path,
port,
uds_path,
options.web,
options.hidden,
assets_dir,
Expand All @@ -117,11 +125,14 @@ def handle(self, options: argparse.Namespace) -> None:


class Handler(FileSystemEventHandler):
def __init__(self, args, script_path, port, web, hidden, assets_dir) -> None:
def __init__(
self, args, script_path, port, uds_path, web, hidden, assets_dir
) -> None:
super().__init__()
self.args = args
self.script_path = script_path
self.port = port
self.uds_path = uds_path
self.web = web
self.hidden = hidden
self.assets_dir = assets_dir
Expand All @@ -140,6 +151,8 @@ def start_process(self):
p_env["FLET_FORCE_WEB_VIEW"] = "true"
if self.port is not None:
p_env["FLET_SERVER_PORT"] = str(self.port)
if self.uds_path is not None:
p_env["FLET_SERVER_UDS_PATH"] = self.uds_path
p_env["FLET_DISPLAY_URL_PREFIX"] = self.page_url_prefix

p_env["PYTHONIOENCODING"] = "utf-8"
Expand Down Expand Up @@ -187,12 +200,11 @@ def open_flet_view_and_wait(self):
self.page_url, self.assets_dir, self.hidden
)
self.fvp.wait()
self.p.kill()
self.p.send_signal(signal.SIGTERM)
self.terminate.set()

def restart_program(self):
self.is_running = False
self.p.kill()
self.p.send_signal(signal.SIGTERM)
self.p.wait()
time.sleep(0.5)
self.start_process()
8 changes: 7 additions & 1 deletion sdk/python/packages/flet/src/flet/flet.py
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ async def app_async(

def exit_gracefully(signum, frame):
logging.debug("Gracefully terminating Flet app...")
terminate.set()
asyncio.get_running_loop().call_soon_threadsafe(terminate.set)

signal.signal(signal.SIGINT, exit_gracefully)
signal.signal(signal.SIGTERM, exit_gracefully)
Expand Down Expand Up @@ -270,6 +270,8 @@ def __connect_internal_sync(
if env_port is not None and env_port:
port = int(env_port)

uds_path = os.getenv("FLET_SERVER_UDS_PATH")

is_desktop = view == FLET_APP or view == FLET_APP_HIDDEN
if server is None and not is_desktop:
server = __start_flet_server(
Expand Down Expand Up @@ -308,6 +310,7 @@ def on_session_created(conn, session_data):
if is_desktop:
conn = SyncLocalSocketConnection(
port,
uds_path,
on_event=on_event,
on_session_created=on_session_created,
)
Expand Down Expand Up @@ -342,6 +345,8 @@ async def __connect_internal_async(
if env_port is not None and env_port:
port = int(env_port)

uds_path = os.getenv("FLET_SERVER_UDS_PATH")

is_desktop = view == FLET_APP or view == FLET_APP_HIDDEN
if server is None and not is_desktop:
server = __start_flet_server(
Expand Down Expand Up @@ -382,6 +387,7 @@ async def on_session_created(session_data):
if is_desktop:
conn = AsyncLocalSocketConnection(
port,
uds_path,
on_event=on_event,
on_session_created=on_session_created,
)
Expand Down
18 changes: 12 additions & 6 deletions sdk/python/packages/flet/src/flet/sync_local_socket_connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import tempfile
import threading
from pathlib import Path
from typing import List
from typing import List, Optional

from flet.utils import get_free_tcp_port, is_windows
from flet_core.local_connection import LocalConnection
Expand All @@ -26,29 +26,32 @@ class SyncLocalSocketConnection(LocalConnection):
def __init__(
self,
port: int = 0,
uds_path: Optional[str] = None,
on_event=None,
on_session_created=None,
):
super().__init__()
self.__port = port
self.__uds_path = uds_path
self.__on_event = on_event
self.__on_session_created = on_session_created

def connect(self):
self.__uds_path = None
if is_windows() or self.__port > 0:
# TCP
port = self.__port if self.__port > 0 else get_free_tcp_port()
self.page_url = f"tcp://localhost:{port}"
server_address = ("localhost", port)
self.__sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.__sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
logging.info(f"Starting up TCP server on {server_address}")
self.__sock.bind(server_address)
else:
# UDS
self.__uds_path = str(
Path(tempfile.gettempdir()).joinpath(random_string(10))
)
if not self.__uds_path:
self.__uds_path = str(
Path(tempfile.gettempdir()).joinpath(random_string(10))
)
self.page_url = self.__uds_path
self.__sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
logging.info(f"Starting up UDS server on {self.__uds_path}")
Expand Down Expand Up @@ -173,7 +176,10 @@ def __recvall(self, sock, n):
# Helper function to recv n bytes or return None if EOF is hit
data = bytearray()
while len(data) < n:
packet = sock.recv(n - len(data))
try:
packet = sock.recv(n - len(data))
except:
return None
# print("packet received:", len(packet))
if not packet:
return None
Expand Down