Flet is a rich User Interface framework to quickly build interactive web, desktop and mobile apps in Python without prior knowledge of web technologies.
—
This document covers Flet's utility functions, platform detection capabilities, file operations, network utilities, storage systems, and helper classes for cross-platform development.
import flet as ft
import flet.utils as flet_utilsdef is_mobile() -> bool:
"""Check if running on mobile platform (Android or iOS)."""
def is_android() -> bool:
"""Check if running on Android."""
def is_ios() -> bool:
"""Check if running on iOS."""
def is_windows() -> bool:
"""Check if running on Windows."""
def is_macos() -> bool:
"""Check if running on macOS."""
def is_linux() -> bool:
"""Check if running on Linux."""
def is_linux_server() -> bool:
"""Check if running on Linux server (no GUI)."""
def is_embedded() -> bool:
"""Check if running in embedded mode."""
def is_pyodide() -> bool:
"""Check if running in Pyodide (web assembly)."""
def is_asyncio() -> bool:
"""Check if asyncio is available and running."""
def get_platform() -> str:
"""Get platform name (windows, macos, linux, android, ios, web)."""
def get_arch() -> str:
"""Get architecture name (x86, x64, arm64, etc.)."""Example:
def configure_for_platform():
if flet_utils.is_mobile():
# Mobile-specific configuration
page.window_width = None # Use full width
page.window_height = None # Use full height
elif flet_utils.is_windows():
# Windows-specific configuration
page.window_width = 800
page.window_height = 600
page.window_center()
elif flet_utils.is_macos():
# macOS-specific configuration
page.window_width = 900
page.window_height = 700
platform_info = ft.Text(
f"Platform: {flet_utils.get_platform()} ({flet_utils.get_arch()})"
)
# Conditional UI based on platform
if flet_utils.is_mobile():
return create_mobile_ui()
else:
return create_desktop_ui()def get_bool_env_var(name: str, default_value: bool = False) -> bool:
"""Get boolean environment variable with default fallback."""Example:
debug_mode = flet_utils.get_bool_env_var("DEBUG", False)
production = flet_utils.get_bool_env_var("PRODUCTION", True)
if debug_mode:
page.add(ft.Text("Debug mode enabled"))def get_current_script_dir() -> str:
"""Get directory of the currently executing script."""
def cleanup_path(path: str) -> str:
"""Clean and normalize file path."""
def is_within_directory(directory: str, target: str) -> bool:
"""Check if target path is within directory (security check)."""Example:
# Get assets directory relative to script
script_dir = flet_utils.get_current_script_dir()
assets_dir = os.path.join(script_dir, "assets")
# Clean user-provided path
safe_path = flet_utils.cleanup_path(user_input_path)
# Security check for file access
if flet_utils.is_within_directory(allowed_dir, requested_file):
# Safe to access file
with open(requested_file, 'r') as f:
content = f.read()def copy_tree(src: str, dst: str, ignore: callable = None) -> None:
"""Copy directory tree with optional ignore function."""Example:
# Copy assets directory, ignoring cache files
def ignore_cache(path, names):
return [name for name in names if name.startswith('.cache')]
flet_utils.copy_tree("src/assets", "dist/assets", ignore=ignore_cache)def safe_tar_extractall(tar_file, path: str = ".", members=None) -> None:
"""Safely extract tar archive preventing directory traversal attacks."""Example:
import tarfile
# Safely extract uploaded tar file
with tarfile.open(uploaded_file) as tar:
flet_utils.safe_tar_extractall(tar, "extracted_files/")def get_free_tcp_port() -> int:
"""Get available TCP port number."""
def get_local_ip() -> str:
"""Get local IP address."""
def which(command: str) -> str:
"""Find executable in PATH (cross-platform 'which' command)."""Example:
# Dynamic port allocation
free_port = flet_utils.get_free_tcp_port()
print(f"Starting server on port {free_port}")
# Network information
local_ip = flet_utils.get_local_ip()
print(f"Server accessible at: http://{local_ip}:{free_port}")
# Check for required executables
git_path = flet_utils.which("git")
if git_path:
print(f"Git found at: {git_path}")
else:
print("Git not available")def slugify(text: str) -> str:
"""Convert string to URL-friendly slug."""
def random_string(length: int = 10, chars: str = None) -> str:
"""Generate random string of specified length."""Example:
# Create URL-friendly identifiers
title = "My Blog Post: Special Characters & Symbols!"
slug = flet_utils.slugify(title) # "my-blog-post-special-characters-symbols"
# Generate session IDs
session_id = flet_utils.random_string(16) # Random 16-character string
api_key = flet_utils.random_string(32, "ABCDEF0123456789") # Hex stringdef sha1(text: str) -> str:
"""Calculate SHA1 hash of text."""
def calculate_file_hash(file_path: str, algorithm: str = "sha256") -> str:
"""Calculate hash of file contents."""Example:
# Content hashing
content_hash = flet_utils.sha1("Hello, World!")
print(f"SHA1: {content_hash}")
# File integrity checking
file_hash = flet_utils.calculate_file_hash("important_file.dat", "sha256")
expected_hash = "abc123..."
if file_hash == expected_hash:
print("File integrity verified")
else:
print("File may be corrupted")def open_in_browser(url: str) -> None:
"""Open URL in default browser."""Example:
def open_help(e):
flet_utils.open_in_browser("https://flet.dev/docs")
def open_external_link(e):
flet_utils.open_in_browser("https://example.com")
ft.Row([
ft.ElevatedButton("Help", on_click=open_help),
ft.ElevatedButton("External Link", on_click=open_external_link)
])class ClientStorage:
"""Client-side storage (localStorage in web, file-based elsewhere)."""
def get(self, key: str) -> str:
"""Get value by key."""
def set(self, key: str, value: str) -> None:
"""Set key-value pair."""
def contains_key(self, key: str) -> bool:
"""Check if key exists."""
def remove(self, key: str) -> None:
"""Remove key."""
def clear(self) -> None:
"""Clear all stored data."""
def get_keys(self, prefix: str = "") -> List[str]:
"""Get all keys with optional prefix filter."""Example:
# Store user preferences
def save_preferences(theme, language):
page.client_storage.set("theme", theme)
page.client_storage.set("language", language)
def load_preferences():
theme = page.client_storage.get("theme") or "light"
language = page.client_storage.get("language") or "en"
return theme, language
# Settings UI
def toggle_theme(e):
current_theme = page.client_storage.get("theme") or "light"
new_theme = "dark" if current_theme == "light" else "light"
page.client_storage.set("theme", new_theme)
apply_theme(new_theme)
ft.Switch(
label="Dark Theme",
value=page.client_storage.get("theme") == "dark",
on_change=toggle_theme
)class SessionStorage:
"""Session-scoped storage (sessionStorage in web, memory elsewhere)."""
# Same API as ClientStorage but data persists only for session
def get(self, key: str) -> str: ...
def set(self, key: str, value: str) -> None: ...
def contains_key(self, key: str) -> bool: ...
def remove(self, key: str) -> None: ...
def clear(self) -> None: ...
def get_keys(self, prefix: str = "") -> List[str]: ...Example:
# Temporary session data
def store_form_data():
page.session.set("form_step", "2")
page.session.set("user_input", text_field.value)
def restore_form_data():
step = page.session.get("form_step") or "1"
user_input = page.session.get("user_input") or ""
return int(step), user_input
# Form wizard with session persistence
current_step, saved_input = restore_form_data()class Vector:
"""2D vector utility class."""
def __init__(self, x: float, y: float):
self.x = x
self.y = y
def magnitude(self) -> float:
"""Calculate vector magnitude."""
def normalize(self) -> "Vector":
"""Get normalized vector."""
def dot(self, other: "Vector") -> float:
"""Dot product with another vector."""
def distance_to(self, other: "Vector") -> float:
"""Distance to another vector."""
def __add__(self, other: "Vector") -> "Vector":
"""Vector addition."""
def __sub__(self, other: "Vector") -> "Vector":
"""Vector subtraction."""
def __mul__(self, scalar: float) -> "Vector":
"""Scalar multiplication."""Example:
# Physics calculations
pos = flet_utils.Vector(100, 200)
velocity = flet_utils.Vector(5, -2)
# Update position
new_pos = pos + velocity
# Calculate distance between points
distance = pos.distance_to(target_pos)
# Normalize direction vector
direction = (target_pos - pos).normalize()class classproperty:
"""Decorator for class-level properties."""
def __init__(self, func):
self.func = func
def __get__(self, instance, owner):
return self.func(owner)Example:
class AppConfig:
_theme = "light"
@flet_utils.classproperty
def current_theme(cls):
return cls._theme
@current_theme.setter
def current_theme(cls, value):
cls._theme = value
# Usage
print(AppConfig.current_theme) # Access as class propertydef deprecated(reason: str = None):
"""Decorator to mark functions as deprecated."""
def decorator(func):
def wrapper(*args, **kwargs):
import warnings
warnings.warn(
f"{func.__name__} is deprecated. {reason or ''}",
DeprecationWarning,
stacklevel=2
)
return func(*args, **kwargs)
return wrapper
return decoratorExample:
@flet_utils.deprecated("Use new_function() instead")
def old_function():
return "old implementation"
# Usage will show deprecation warning
result = old_function()class Once:
"""Execute-once utility."""
def __init__(self):
self._called = False
def __call__(self, func):
def wrapper(*args, **kwargs):
if not self._called:
self._called = True
return func(*args, **kwargs)
return wrapperExample:
# Ensure initialization happens only once
initialize_once = flet_utils.Once()
@initialize_once
def initialize_app():
print("App initialized")
# Expensive initialization code
# Multiple calls, but initialization runs only once
initialize_app() # Runs initialization
initialize_app() # Skipped
initialize_app() # Skippedclass QueryString:
"""URL query string handler."""
def __init__(self, query_string: str = ""):
self.params = {}
def get(self, key: str, default: str = None) -> str:
"""Get query parameter value."""
def set(self, key: str, value: str) -> None:
"""Set query parameter."""
def remove(self, key: str) -> None:
"""Remove query parameter."""
def to_string(self) -> str:
"""Convert to query string."""class TemplateRoute:
"""Template-based routing system."""
def __init__(self, route_template: str):
self.template = route_template
def match(self, route: str) -> dict:
"""Match route against template and extract parameters."""
def build(self, **params) -> str:
"""Build route from template with parameters."""Example:
# URL parameter handling
def handle_route_change(e):
route = e.route
query = flet_utils.QueryString(page.route.split('?')[1] if '?' in page.route else "")
# Extract query parameters
user_id = query.get('user_id')
tab = query.get('tab', 'profile')
if user_id:
load_user_profile(user_id, tab)
# Template routing
user_route = flet_utils.TemplateRoute("/user/{user_id}/tab/{tab}")
# Match incoming route
params = user_route.match("/user/123/tab/settings")
# Returns: {"user_id": "123", "tab": "settings"}
# Build route from parameters
new_route = user_route.build(user_id="456", tab="profile")
# Returns: "/user/456/tab/profile"def create_adaptive_button(text, on_click):
"""Create platform-appropriate button."""
if flet_utils.is_ios():
return ft.CupertinoButton(text=text, on_click=on_click)
else:
return ft.ElevatedButton(text=text, on_click=on_click)
def create_adaptive_dialog(title, content, actions):
"""Create platform-appropriate dialog."""
if flet_utils.is_ios():
return ft.CupertinoAlertDialog(
title=ft.Text(title),
content=ft.Text(content),
actions=actions
)
else:
return ft.AlertDialog(
title=ft.Text(title),
content=ft.Text(content),
actions=actions
)class PlatformConfig:
"""Platform-specific configuration manager."""
def __init__(self):
self.config = self._load_platform_config()
def _load_platform_config(self):
base_config = {
"window_width": 800,
"window_height": 600,
"font_family": "default"
}
if flet_utils.is_mobile():
base_config.update({
"window_width": None,
"window_height": None,
"font_size": 16
})
elif flet_utils.is_macos():
base_config.update({
"font_family": "SF Pro Display",
"window_width": 900
})
elif flet_utils.is_windows():
base_config.update({
"font_family": "Segoe UI",
"window_width": 850
})
return base_config
def get(self, key, default=None):
return self.config.get(key, default)
# Usage
config = PlatformConfig()
page.window_width = config.get("window_width")
page.window_height = config.get("window_height")def get_platform_asset(asset_name):
"""Get platform-specific asset path."""
platform = flet_utils.get_platform()
# Try platform-specific asset first
platform_asset = f"assets/{platform}/{asset_name}"
if os.path.exists(platform_asset):
return platform_asset
# Fall back to generic asset
return f"assets/{asset_name}"
def load_platform_strings():
"""Load platform-appropriate localized strings."""
if flet_utils.is_ios():
return load_strings("ios_strings.json")
elif flet_utils.is_android():
return load_strings("android_strings.json")
else:
return load_strings("desktop_strings.json")def optimize_for_platform():
"""Apply platform-specific optimizations."""
if flet_utils.is_mobile():
# Mobile optimizations
page.scroll = ft.ScrollMode.AUTO
page.auto_scroll = True
elif flet_utils.is_web():
# Web optimizations
page.web_renderer = ft.WebRenderer.HTML
# Memory management
if flet_utils.is_linux_server():
# Server environment optimizations
disable_animations()
reduce_ui_complexity()
def create_efficient_list_for_platform(items):
"""Create optimized list based on platform capabilities."""
if flet_utils.is_mobile() and len(items) > 100:
# Use virtual scrolling for large lists on mobile
return create_virtual_list(items)
else:
# Standard list for desktop/smaller lists
return ft.ListView(controls=[
ft.ListTile(title=ft.Text(item)) for item in items
])This covers Flet's comprehensive utility system and platform detection capabilities, enabling you to create truly cross-platform applications that adapt to different environments and provide optimal user experiences across all supported platforms.
Install with Tessl CLI
npx tessl i tessl/pypi-flet