diff --git a/sdk/python/packages/flet-cli/src/flet_cli/utils/android_sdk.py b/sdk/python/packages/flet-cli/src/flet_cli/utils/android_sdk.py index da321f7f9b..b3b37d79b9 100644 --- a/sdk/python/packages/flet-cli/src/flet_cli/utils/android_sdk.py +++ b/sdk/python/packages/flet-cli/src/flet_cli/utils/android_sdk.py @@ -4,9 +4,10 @@ from pathlib import Path from typing import Optional +from rich.progress import Progress + from flet_cli.utils import processes from flet_cli.utils.distros import download_with_progress, extract_with_progress -from rich.progress import Progress ANDROID_CMDLINE_TOOLS_DOWNLOAD_VERSION = "11076708" ANDROID_CMDLINE_TOOLS_VERSION = "12.0" @@ -98,7 +99,7 @@ def cmdline_tools_url(self): }, }[platform.system()][platform.machine()] except KeyError: - raise Exception( + raise RuntimeError( f"Unsupported platform: {platform.system()}-{platform.machine()}" ) from None @@ -183,7 +184,7 @@ def _install_package(self, home_dir: Path, package_name: str) -> int: ) if p.returncode != 0: self.log(p.stderr) - raise Exception("Error installing Android SDK tools") + raise RuntimeError("Error installing Android SDK tools") return 1 def _accept_licenses(self, home_dir: Path): @@ -208,7 +209,7 @@ def _accept_licenses(self, home_dir: Path): ) if p.returncode != 0: self.log(p.stderr) - raise Exception("Error accepting Android SDK licenses") + raise RuntimeError("Error accepting Android SDK licenses") def get_installed_packages(self, home_dir: Path): self.log("Checking installed Android APIs and build tools") @@ -219,7 +220,7 @@ def get_installed_packages(self, home_dir: Path): ) if p.returncode != 0: self.log(p.stderr) - raise Exception( + raise RuntimeError( "Error retrieving the list of installed Android SDK packages" ) return p.stdout diff --git a/sdk/python/packages/flet-cli/src/flet_cli/utils/project_dependencies.py b/sdk/python/packages/flet-cli/src/flet_cli/utils/project_dependencies.py index 308be1e4d9..1bd711ca75 100644 --- a/sdk/python/packages/flet-cli/src/flet_cli/utils/project_dependencies.py +++ b/sdk/python/packages/flet-cli/src/flet_cli/utils/project_dependencies.py @@ -8,7 +8,6 @@ def get_poetry_dependencies( poetry_dependencies: Optional[dict[str, Any]] = None, ) -> Optional[list[str]]: - if poetry_dependencies is None: return None @@ -51,8 +50,9 @@ def format_dependency_version(dependency_name: str, dependency_value: Any): dependency_name = "" sep = "" else: - raise Exception( - f"Unsupported dependency specification: {dependency_name} = {dependency_value}" + raise ValueError( + "Unsupported dependency specification: " + f"{dependency_name} = {dependency_value}" ) # markers - common for all @@ -88,7 +88,6 @@ def format_dependency_version(dependency_name: str, dependency_value: Any): def get_project_dependencies( project_dependencies: Optional[dict[str, Any]] = None, ) -> Optional[list[str]]: - if project_dependencies is None: return None diff --git a/sdk/python/packages/flet-web/src/flet_web/fastapi/flet_app.py b/sdk/python/packages/flet-web/src/flet_web/fastapi/flet_app.py index d888ee2ac0..379db834e2 100644 --- a/sdk/python/packages/flet-web/src/flet_web/fastapi/flet_app.py +++ b/sdk/python/packages/flet-web/src/flet_web/fastapi/flet_app.py @@ -325,7 +325,7 @@ async def __on_message(self, data: Any): else: # it's something else - raise Exception(f'Unknown message "{action}": {body}') + raise RuntimeError(f'Unknown message "{action}": {body}') if task: self.__running_tasks.add(task) diff --git a/sdk/python/packages/flet-web/src/flet_web/fastapi/flet_app_manager.py b/sdk/python/packages/flet-web/src/flet_web/fastapi/flet_app_manager.py index 5832ef3b88..706ad4cbac 100644 --- a/sdk/python/packages/flet-web/src/flet_web/fastapi/flet_app_manager.py +++ b/sdk/python/packages/flet-web/src/flet_web/fastapi/flet_app_manager.py @@ -6,11 +6,10 @@ from datetime import datetime, timezone from typing import Optional +import flet_web.fastapi as flet_fastapi from flet.messaging.connection import Connection from flet.messaging.session import Session from flet.pubsub.pubsub_hub import PubSubHub - -import flet_web.fastapi as flet_fastapi from flet_web.fastapi.oauth_state import OAuthState logger = logging.getLogger(flet_fastapi.__name__) @@ -84,7 +83,7 @@ async def reconnect_session(self, session_id: str, conn: Connection): session = self.__sessions[session_id] await session.connect(conn) else: - raise Exception(f"Session has expired or not found: {session_id}") + raise RuntimeError(f"Session has expired or not found: {session_id}") async def disconnect_session(self, session_id: str, session_timeout_seconds: int): logger.info(f"Session disconnected: {session_id}") diff --git a/sdk/python/packages/flet-web/src/flet_web/fastapi/flet_static_files.py b/sdk/python/packages/flet-web/src/flet_web/fastapi/flet_static_files.py index 313a7a4487..a2985d0429 100644 --- a/sdk/python/packages/flet-web/src/flet_web/fastapi/flet_static_files.py +++ b/sdk/python/packages/flet-web/src/flet_web/fastapi/flet_static_files.py @@ -6,11 +6,11 @@ from typing import Optional from fastapi.staticfiles import StaticFiles -from flet.controls.types import RouteUrlStrategy, WebRenderer -from flet.utils import Once, get_bool_env_var from starlette.types import Receive, Scope, Send import flet_web.fastapi as flet_fastapi +from flet.controls.types import RouteUrlStrategy, WebRenderer +from flet.utils import Once, get_bool_env_var from flet_web import ( get_package_web_dir, patch_font_manifest_json, @@ -120,7 +120,7 @@ async def __config(self, root_path: str): logger.info(f"Web root: {web_dir}") if not os.path.exists(web_dir): - raise Exception(f"Web root path not found: {web_dir}") + raise RuntimeError(f"Web root path not found: {web_dir}") # user-defined assets if self.__assets_dir: diff --git a/sdk/python/packages/flet-web/src/flet_web/fastapi/flet_upload.py b/sdk/python/packages/flet-web/src/flet_web/fastapi/flet_upload.py index c69b5e85c7..ff28dafbab 100644 --- a/sdk/python/packages/flet-web/src/flet_web/fastapi/flet_upload.py +++ b/sdk/python/packages/flet-web/src/flet_web/fastapi/flet_upload.py @@ -3,9 +3,10 @@ from datetime import datetime, timezone from typing import Optional -import flet_web.fastapi as flet_fastapi from anyio import open_file -from fastapi import Request +from fastapi import HTTPException, Request, status + +import flet_web.fastapi as flet_fastapi from flet_web.uploads import build_upload_query_string, get_upload_signature logger = logging.getLogger(flet_fastapi.__name__) @@ -18,7 +19,8 @@ class FletUpload: Parameters: * `upload_dir` (str) - an absolute path to a directory with uploaded files. - * `max_upload_size` (str, int) - maximum size of a single upload, bytes. Unlimited if `None`. + * `max_upload_size` (str, int) - maximum size of a single upload, bytes. + Unlimited if `None`. * `secret_key` (str, optional) - secret key to sign and verify upload requests. """ @@ -50,14 +52,24 @@ def __init__( """ async def handle(self, request: Request): - file_name = request.query_params["f"] - expire_str = request.query_params["e"] - signature = request.query_params["s"] + query_params = request.query_params + file_name = query_params.get("f") + expire_str = query_params.get("e") + signature = query_params.get("s") if not file_name or not expire_str or not signature: - raise Exception("Invalid request") + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, + detail="Missing upload parameters", + ) - expire_date = datetime.fromisoformat(expire_str) + try: + expire_date = datetime.fromisoformat(expire_str) + except ValueError as e: + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, + detail="Invalid expiration parameter", + ) from e # verify signature query_string = build_upload_query_string(file_name, expire_date) @@ -67,17 +79,26 @@ async def handle(self, request: Request): ) != signature ): - raise Exception("Invalid request") + raise HTTPException( + status_code=status.HTTP_403_FORBIDDEN, + detail="Invalid upload signature", + ) # check expiration date if datetime.now(timezone.utc) >= expire_date: - raise Exception("Invalid request") + raise HTTPException( + status_code=status.HTTP_410_GONE, + detail="Upload URL has expired", + ) # build/validate dest path joined_path = os.path.join(self.__upload_dir, file_name) full_path = os.path.realpath(joined_path) if os.path.commonpath([full_path, self.__upload_dir]) != self.__upload_dir: - raise Exception("Invalid request") + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, + detail="Invalid upload destination", + ) # create directory if not exists dest_dir = os.path.dirname(full_path) @@ -89,7 +110,8 @@ async def handle(self, request: Request): async for chunk in request.stream(): size += len(chunk) if self.__max_upload_size and size > self.__max_upload_size: - raise Exception( - f"Max upload size reached: {self.__max_upload_size}" + raise HTTPException( + status_code=status.HTTP_413_REQUEST_ENTITY_TOO_LARGE, + detail="Max upload size exceeded", ) await f.write(chunk) diff --git a/sdk/python/packages/flet-web/src/flet_web/uploads.py b/sdk/python/packages/flet-web/src/flet_web/uploads.py index d25fc0c05e..d320e6f286 100644 --- a/sdk/python/packages/flet-web/src/flet_web/uploads.py +++ b/sdk/python/packages/flet-web/src/flet_web/uploads.py @@ -39,8 +39,9 @@ def get_upload_signature( if env_secret_key: secret_key = env_secret_key if not secret_key: - raise Exception( - "Specify secret_key parameter or set FLET_SECRET_KEY environment variable to enable uploads." + raise RuntimeError( + "Specify secret_key parameter or set FLET_SECRET_KEY environment " + "variable to enable uploads." ) signing_key = hmac.new( secret_key.encode("utf-8"), @@ -49,6 +50,6 @@ def get_upload_signature( ).digest() return hmac.new( signing_key, - f"{upload_endpoint_path.strip('/')}{query_string}".encode("utf-8"), + f"{upload_endpoint_path.strip('/')}{query_string}".encode(), hashlib.sha256, ).hexdigest() diff --git a/sdk/python/packages/flet/docs/cookbook/authentication.md b/sdk/python/packages/flet/docs/cookbook/authentication.md index c015a41680..e74f4d9b18 100644 --- a/sdk/python/packages/flet/docs/cookbook/authentication.md +++ b/sdk/python/packages/flet/docs/cookbook/authentication.md @@ -438,7 +438,7 @@ def main(page: Page): def on_login(e): if e.error: - raise Exception(e.error) + raise RuntimeError(e.error) print("User ID:", page.auth.user.id) print("Access token:", page.auth.token.access_token) diff --git a/sdk/python/packages/flet/src/flet/auth/authorization_service.py b/sdk/python/packages/flet/src/flet/auth/authorization_service.py index de84f0c94e..0f15c80cad 100644 --- a/sdk/python/packages/flet/src/flet/auth/authorization_service.py +++ b/sdk/python/packages/flet/src/flet/auth/authorization_service.py @@ -90,7 +90,7 @@ async def __fetch_user_and_groups(self): self.user = await self.provider._fetch_user(self.__token.access_token) if self.user is None and self.provider.user_endpoint is not None: if self.provider.user_id_fn is None: - raise Exception( + raise ValueError( "user_id_fn must be specified too if user_endpoint is not None" ) self.user = await self.__get_user() diff --git a/sdk/python/packages/flet/src/flet/auth/oauth_provider.py b/sdk/python/packages/flet/src/flet/auth/oauth_provider.py index eff83989d6..12f1cd4373 100644 --- a/sdk/python/packages/flet/src/flet/auth/oauth_provider.py +++ b/sdk/python/packages/flet/src/flet/auth/oauth_provider.py @@ -36,7 +36,7 @@ def __init__( self.code_verifier = code_verifier def _name(self): - raise Exception("Not implemented") + raise NotImplementedError("Subclasses must implement _name()") async def _fetch_groups(self, access_token: str) -> list[Group]: return [] diff --git a/sdk/python/packages/flet/src/flet/controls/base_control.py b/sdk/python/packages/flet/src/flet/controls/base_control.py index d805f5abf3..3e44338ecb 100644 --- a/sdk/python/packages/flet/src/flet/controls/base_control.py +++ b/sdk/python/packages/flet/src/flet/controls/base_control.py @@ -130,7 +130,7 @@ def __post_init__(self, ref: Optional[Ref[Any]]): self._i = ControlId.next() if not hasattr(self, "_c") or self._c is None: cls_name = f"{self.__class__.__module__}.{self.__class__.__qualname__}" - raise Exception( + raise ValueError( f"Control {cls_name} must have @control decorator with " "type_name specified." ) @@ -232,7 +232,7 @@ def will_unmount(self): # public methods def update(self) -> None: if hasattr(self, "_frozen"): - raise Exception("Frozen control cannot be updated.") + raise RuntimeError("Frozen control cannot be updated.") if not self.page: raise RuntimeError( f"{self.__class__.__qualname__} Control must be added to the page first" diff --git a/sdk/python/packages/flet/src/flet/controls/base_page.py b/sdk/python/packages/flet/src/flet/controls/base_page.py index 320907fff3..8abab1d702 100644 --- a/sdk/python/packages/flet/src/flet/controls/base_page.py +++ b/sdk/python/packages/flet/src/flet/controls/base_page.py @@ -329,7 +329,7 @@ def show_dialog(self, dialog: DialogControl) -> None: Exception: If the specified dialog is already open. """ if dialog in self._dialogs.controls: - raise Exception("Dialog is already opened") + raise RuntimeError("Dialog is already opened") original_on_dismiss = dialog.on_dismiss diff --git a/sdk/python/packages/flet/src/flet/controls/control.py b/sdk/python/packages/flet/src/flet/controls/control.py index b725afae8d..8dc023603c 100644 --- a/sdk/python/packages/flet/src/flet/controls/control.py +++ b/sdk/python/packages/flet/src/flet/controls/control.py @@ -146,6 +146,3 @@ def before_update(self): raise ValueError( f"expand must be of type bool or int, got {type(self.expand)}" ) - - def clean(self) -> None: - raise Exception("Deprecated!") diff --git a/sdk/python/packages/flet/src/flet/controls/control_event.py b/sdk/python/packages/flet/src/flet/controls/control_event.py index 2e729d86c9..93f1194ca8 100644 --- a/sdk/python/packages/flet/src/flet/controls/control_event.py +++ b/sdk/python/packages/flet/src/flet/controls/control_event.py @@ -83,7 +83,7 @@ def get_event_field_type(control: Any, field_name: str): return event_type except Exception as e: - raise Exception(f"[resolve error] {field_name}: {e}") from e + raise RuntimeError(f"[resolve error] {field_name}: {e}") from e EventControlType = TypeVar("EventControlType", bound="BaseControl") diff --git a/sdk/python/packages/flet/src/flet/controls/object_patch.py b/sdk/python/packages/flet/src/flet/controls/object_patch.py index 6c3f8b9db8..86366f5b92 100644 --- a/sdk/python/packages/flet/src/flet/controls/object_patch.py +++ b/sdk/python/packages/flet/src/flet/controls/object_patch.py @@ -1060,7 +1060,7 @@ def _dataclass_added(self, item, parent, frozen): if parent: logger.debug("\n\nAdding parent %s to item: %s", parent, item) if parent is item: - raise Exception(f"Parent is the same as item: {item}") + raise ObjectPatchException(f"Parent is the same as item: {item}") item._parent = weakref.ref(parent) else: logger.debug("\n\nSkip adding parent to item: %s", item) @@ -1113,7 +1113,7 @@ def _configure_dataclass(self, item, parent, frozen, configure_setattr_only=Fals if parent: if parent is item: - raise Exception(f"Parent is the same as item: {item}") + raise ObjectPatchException(f"Parent is the same as item: {item}") item._parent = weakref.ref(parent) if hasattr(item, "_frozen"): @@ -1130,7 +1130,9 @@ def control_setattr(obj, name, value): or not isinstance(obj, control_cls) ): if hasattr(obj, "_frozen"): - raise Exception("Frozen controls cannot be updated.") from None + raise RuntimeError( + "Frozen controls cannot be updated." + ) from None if hasattr(obj, "__changes"): old_value = getattr(obj, name, None) diff --git a/sdk/python/packages/flet/src/flet/controls/page.py b/sdk/python/packages/flet/src/flet/controls/page.py index 6c358a1974..5a9ab63e46 100644 --- a/sdk/python/packages/flet/src/flet/controls/page.py +++ b/sdk/python/packages/flet/src/flet/controls/page.py @@ -866,7 +866,7 @@ def session(self) -> "Session": """ if sess := self.__session(): return sess - raise Exception("An attempt to fetch destroyed session.") + raise RuntimeError("An attempt to fetch destroyed session.") @property def query(self) -> QueryString: diff --git a/sdk/python/packages/flet/src/flet/messaging/connection.py b/sdk/python/packages/flet/src/flet/messaging/connection.py index 377651a4ce..d063dca1e5 100644 --- a/sdk/python/packages/flet/src/flet/messaging/connection.py +++ b/sdk/python/packages/flet/src/flet/messaging/connection.py @@ -20,7 +20,7 @@ def __init__(self): @property def loop(self) -> AbstractEventLoop: if self.__loop is None: - raise Exception("Loop not initialized") + raise RuntimeError("Loop not initialized") return self.__loop @loop.setter @@ -30,7 +30,7 @@ def loop(self, value): @property def executor(self) -> ThreadPoolExecutor: if self.__executor is None: - raise Exception("Executor not initialized") + raise RuntimeError("Executor not initialized") return self.__executor @executor.setter @@ -40,7 +40,7 @@ def executor(self, value): @property def pubsubhub(self) -> PubSubHub: if self.__pubsubhub is None: - raise Exception("PubSubHub not initialized") + raise RuntimeError("PubSubHub not initialized") return self.__pubsubhub @pubsubhub.setter diff --git a/sdk/python/packages/flet/src/flet/messaging/flet_socket_server.py b/sdk/python/packages/flet/src/flet/messaging/flet_socket_server.py index f4391852da..12dfa94032 100644 --- a/sdk/python/packages/flet/src/flet/messaging/flet_socket_server.py +++ b/sdk/python/packages/flet/src/flet/messaging/flet_socket_server.py @@ -206,7 +206,7 @@ async def __on_message(self, data: Any): else: # it's something else - raise Exception(f'Unknown message "{action}": {body}') + raise RuntimeError(f'Unknown message "{action}": {body}') if task: self.__running_tasks.add(task) diff --git a/sdk/python/packages/flet/src/flet/messaging/protocol.py b/sdk/python/packages/flet/src/flet/messaging/protocol.py index adabea2476..ed70807dde 100644 --- a/sdk/python/packages/flet/src/flet/messaging/protocol.py +++ b/sdk/python/packages/flet/src/flet/messaging/protocol.py @@ -59,7 +59,7 @@ def encode_object_for_msgpack(obj): elif isinstance(obj, Duration): return msgpack.ExtType(3, obj.in_microseconds) elif callable(obj): - raise Exception(f"Cannot serialize method: {obj}") from None + raise RuntimeError(f"Cannot serialize method: {obj}") from None return obj return encode_object_for_msgpack diff --git a/sdk/python/packages/flet/src/flet/messaging/pyodide_connection.py b/sdk/python/packages/flet/src/flet/messaging/pyodide_connection.py index 479ba9f0e8..751a814618 100644 --- a/sdk/python/packages/flet/src/flet/messaging/pyodide_connection.py +++ b/sdk/python/packages/flet/src/flet/messaging/pyodide_connection.py @@ -4,6 +4,7 @@ import flet_js import msgpack + from flet.controls.base_control import BaseControl from flet.messaging.connection import Connection from flet.messaging.protocol import ( @@ -107,7 +108,7 @@ async def __on_message(self, data: Any): else: # it's something else - raise Exception(f'Unknown message "{action}": {body}') + raise RuntimeError(f'Unknown message "{action}": {body}') if task: self.__running_tasks.add(task) diff --git a/sdk/python/packages/flet/src/flet/messaging/session.py b/sdk/python/packages/flet/src/flet/messaging/session.py index 0238480ffa..604b11bdf6 100644 --- a/sdk/python/packages/flet/src/flet/messaging/session.py +++ b/sdk/python/packages/flet/src/flet/messaging/session.py @@ -229,7 +229,7 @@ async def invoke_method( result, err = self.__method_call_results.pop(evt) if err: - raise Exception(err) + raise RuntimeError(err) return result def handle_invoke_method_results( @@ -242,7 +242,7 @@ def handle_invoke_method_results( self.__method_call_results[evt] = (result, error) evt.set() else: - raise Exception( + raise RuntimeError( f"Error handling invoke method results. Control with ID {control_id} " "is not registered." ) diff --git a/sdk/python/packages/flet/src/flet/security/__init__.py b/sdk/python/packages/flet/src/flet/security/__init__.py index 7c0b889ecb..6b1f63dc64 100644 --- a/sdk/python/packages/flet/src/flet/security/__init__.py +++ b/sdk/python/packages/flet/src/flet/security/__init__.py @@ -8,7 +8,7 @@ from cryptography.hazmat.primitives.ciphers.aead import AESGCM from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC except ImportError as e: - raise Exception( + raise ImportError( 'Install "cryptography" Python package to use Flet security utils.' ) from e diff --git a/sdk/python/packages/flet/src/flet/testing/flet_test_app.py b/sdk/python/packages/flet/src/flet/testing/flet_test_app.py index 35b41612b8..337088e830 100644 --- a/sdk/python/packages/flet/src/flet/testing/flet_test_app.py +++ b/sdk/python/packages/flet/src/flet/testing/flet_test_app.py @@ -354,7 +354,7 @@ def assert_screenshot( f.write(screenshot) else: if not golden_image_path.exists(): - raise Exception( + raise RuntimeError( f"Golden image for {name} not found: {golden_image_path}" ) golden_img = self._load_image_from_file(golden_image_path) diff --git a/sdk/python/packages/flet/src/flet/utils/files.py b/sdk/python/packages/flet/src/flet/utils/files.py index 68dca221cc..65b2129033 100644 --- a/sdk/python/packages/flet/src/flet/utils/files.py +++ b/sdk/python/packages/flet/src/flet/utils/files.py @@ -16,7 +16,7 @@ def safe_tar_extractall(tar, path=".", members=None, *, numeric_owner=False): for member in tar.getmembers(): member_path = os.path.join(path, member.name) if not is_within_directory(path, member_path): - raise Exception("Attempted Path Traversal in Tar File") + raise RuntimeError("Attempted Path Traversal in Tar File") tar.extractall(path, members, numeric_owner=numeric_owner) diff --git a/sdk/python/packages/flet/src/flet/utils/platform_utils.py b/sdk/python/packages/flet/src/flet/utils/platform_utils.py index 4efdc1403d..0f3d019997 100644 --- a/sdk/python/packages/flet/src/flet/utils/platform_utils.py +++ b/sdk/python/packages/flet/src/flet/utils/platform_utils.py @@ -2,6 +2,8 @@ import os import sys +from flet.controls.exceptions import FletUnsupportedPlatformException + def get_bool_env_var(name: str): v = os.getenv(name) @@ -52,7 +54,7 @@ def is_linux_server(): # check if it's WSL p = "/proc/version" if os.path.exists(p): - with open(p, "r", encoding="utf-8") as file: + with open(p, encoding="utf-8") as file: if "microsoft" in file.read(): return False # it's WSL, not a server return os.environ.get("DISPLAY") is None @@ -72,7 +74,7 @@ def get_platform(): elif p == "Darwin": return "darwin" else: - raise Exception(f"Unsupported platform: {p}") + raise FletUnsupportedPlatformException(f"Unsupported platform: {p}") def get_arch(): @@ -84,4 +86,4 @@ def get_arch(): elif a.startswith("arm"): return "arm_7" else: - raise Exception(f"Unsupported architecture: {a}") + raise FletUnsupportedPlatformException(f"Unsupported architecture: {a}")