A lightweight utility for simplified client-side storage management in Flet applications.
Project description
Flet Storage
🌐 Translations: 🇺🇦 Українська
A lightweight, asynchronous, namespaced storage utility for Flet applications.
FletStorage is a powerful wrapper around Flet's built-in SharedPreferences. It simplifies client-side data persistence by adding automatic JSON serialization, allowing you to store and retrieve complex Python objects without manual conversion, while keeping your data organized and isolated.
Features
- Automatic JSON serialization: Store and retrieve
dict,list,int,bool,str, andsetdirectly without manual conversion. - Namespaced storage: Automatically prefixes keys with
app_nameto prevent data collisions between different applications on the same device. - Asynchronous and parallel: Fully asynchronous API with parallel deletion in the
clear()method for maximum performance. - Robust error handling: Clear
KeyErrorandValueErrorexceptions for predictable data management. - Set support: Python sets are automatically preserved during serialization and deserialization.
Installation
pip install flet-storage
Quick Start
import flet as ft
from flet_storage import FletStorage
async def main(page: ft.Page):
# Initialize storage with a unique namespace
storage = FletStorage("my_app")
# Save data
await storage.set("user", {"name": "Ivan", "age": 25})
await storage.set("settings", {"theme": "dark", "language": "en"})
# Retrieve data
user = await storage.get("user")
print(user) # {'name': 'Ivan', 'age': 25}
# Get with default value
config = await storage.get_or_default("config", {"version": "1.0"})
print(config) # {'version': '1.0'}
# Check if key exists
exists = await storage.contains_key("user")
print(exists) # True
# Get all keys
keys = await storage.get_keys()
print(keys) # ['user', 'settings']
# Remove a key
await storage.remove("settings")
# Clear entire storage
await storage.clear()
ft.run(main)
Supported Data Types
FletStorage automatically serializes and deserializes the following Python types:
| Type | Description | Example |
|---|---|---|
dict |
Dictionaries | {"key": "value"} |
list |
Lists | [1, 2, 3] |
set |
Sets (preserved) | {"a", "b", "c"} |
str |
Strings | "hello" |
int, float |
Numbers | 42, 3.14 |
bool |
Booleans | True, False |
None |
None value | None |
Working with Sets
Sets are automatically preserved during storage and retrieval:
# Storing a set
tags = {"python", "flet", "async"}
await storage.set("tags", tags)
# Retrieving (returns a set, not a list!)
tags = await storage.get("tags")
print(type(tags)) # <class 'set'> ✅
print(tags) # {'python', 'flet', 'async'}
# Sets in nested structures work too
data = {
"user": "Ivan",
"tags": {"web", "mobile"},
"categories": ["tech", "programming"]
}
await storage.set("profile", data)
profile = await storage.get("profile")
# profile["tags"] is a set ✅
# profile["categories"] is a list ✅
Technical Note: Sets are stored internally as {"__type__": "set", "values": [...]}. If you need to store a dictionary with a "__type__" key that equals "set", it may be incorrectly interpreted as a set marker during deserialization.
API Reference
__init__(app_name: str)
Initializes the storage with a unique namespace.
Parameters:
app_name(str): The unique namespace for the application.
Example:
storage = FletStorage("todo_app")
async set(key: str, obj: object) -> bool
Serializes an object to JSON and stores it under a namespaced key.
Parameters:
key(str): The unique key identifier (without namespace).obj(object): Any JSON-serializable object (dict, list, set, str, int, etc.).
Returns:
bool:Trueif the operation was successful.
Example:
await storage.set("preferences", {"notifications": True})
await storage.set("tags", {"python", "flet"}) # Sets are supported!
async get(key: str) -> Any
Retrieves and deserializes an object by its key.
Parameters:
key(str): The key identifier to look up.
Returns:
Any: The deserialized Python object.
Raises:
KeyError: If the key does not exist in the storage.ValueError: If the stored data is not valid JSON.
Example:
try:
data = await storage.get("preferences")
except KeyError:
print("Key not found")
async get_or_default(key: str, default: Any = None) -> Any
Gets the value for the given key or returns a default value if not found.
Parameters:
key(str): The key identifier to look up.default(Any): The value to return if the key does not exist. Defaults toNone.
Returns:
Any: The deserialized object if found, otherwise the default value.
Raises:
ValueError: If the stored data is not valid JSON.
Example:
config = await storage.get_or_default("config", {"version": "1.0"})
async contains_key(key: str) -> bool
Checks if a specific key exists within the application namespace.
Parameters:
key(str): The key identifier to check.
Returns:
bool:Trueif the key exists,Falseotherwise.
Example:
if await storage.contains_key("user_token"):
token = await storage.get("user_token")
async remove(key: str) -> bool
Removes a specific key and its value from the storage.
Parameters:
key(str): The key identifier to remove.
Returns:
bool:Trueif the operation was successful.
Example:
await storage.remove("temp_data")
async get_keys() -> list[str]
Retrieves all keys belonging to the current application namespace.
Returns:
list[str]: A list of keys with theapp_name.prefix removed.
Example:
all_keys = await storage.get_keys()
print(f"Stored {len(all_keys)} keys")
async clear() -> None
Deletes all keys and values associated with the current application namespace. Other namespaces in SharedPreferences remain untouched.
Example:
await storage.clear() # Removes all app data
Usage Examples
Saving User Settings
async def save_user_settings(storage: FletStorage, settings: dict):
await storage.set("settings", settings)
print("Settings saved")
async def load_user_settings(storage: FletStorage) -> dict:
return await storage.get_or_default("settings", {
"theme": "light",
"language": "en",
"notifications": True
})
Managing a Todo List
async def add_todo(storage: FletStorage, task: str):
todos = await storage.get_or_default("todos", [])
todos.append({"task": task, "completed": False})
await storage.set("todos", todos)
async def get_all_todos(storage: FletStorage) -> list:
return await storage.get_or_default("todos", [])
async def clear_completed_todos(storage: FletStorage):
todos = await storage.get_or_default("todos", [])
active_todos = [t for t in todos if not t["completed"]]
await storage.set("todos", active_todos)
Working with Tags (Sets)
async def add_tag(storage: FletStorage, tag: str):
tags = await storage.get_or_default("tags", set())
tags.add(tag)
await storage.set("tags", tags)
async def remove_tag(storage: FletStorage, tag: str):
tags = await storage.get_or_default("tags", set())
tags.discard(tag)
await storage.set("tags", tags)
async def get_all_tags(storage: FletStorage) -> set:
return await storage.get_or_default("tags", set())
Data Caching
import time
async def cache_data(storage: FletStorage, key: str, data: Any, ttl: int = 3600):
cache_entry = {
"data": data,
"expires_at": time.time() + ttl
}
await storage.set(f"cache_{key}", cache_entry)
async def get_cached_data(storage: FletStorage, key: str) -> Any | None:
try:
cache_entry = await storage.get(f"cache_{key}")
if time.time() < cache_entry["expires_at"]:
return cache_entry["data"]
else:
await storage.remove(f"cache_{key}")
return None
except KeyError:
return None
Error Handling
async def safe_get_data(storage: FletStorage, key: str):
try:
data = await storage.get(key)
return data
except KeyError:
print(f"Key '{key}' not found")
return None
except ValueError as e:
print(f"JSON error: {e}")
return None
Best Practices
-
Use descriptive namespace names: Choose a unique
app_nameto avoid conflicts with other applications. -
Handle exceptions: Always handle
KeyErrorandValueErrorwhen working withget(). -
Use
get_or_default(): For optional data, this is more convenient than exception handling. -
Structure your data: Store related data together in dictionaries for better organization.
-
Clean up stale data: Regularly remove unnecessary keys to keep storage clean.
-
Use sets for unique collections: Sets are automatically preserved and are perfect for storing unique items like tags or categories.
Requirements
- Python 3.12+
- Flet >= 0.80.1
License
MIT License
Contributing
Contributions are welcome! Please submit pull requests on GitHub.
Support
If you encounter any issues or have questions:
- Open an issue on GitHub
Made with ❤️ for the Flet community
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file flet_storage-1.1.0.tar.gz.
File metadata
- Download URL: flet_storage-1.1.0.tar.gz
- Upload date:
- Size: 7.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
127e929aeae513fecffb2c96337b23db372d97292131ba470edbd23a1650c286
|
|
| MD5 |
96595d97d32a36574eced10ec5363ffb
|
|
| BLAKE2b-256 |
f245815b512b114f3d1f3b4fc363fb7f0b9f8085d35dada8d2b8d408577d9dcc
|
File details
Details for the file flet_storage-1.1.0-py3-none-any.whl.
File metadata
- Download URL: flet_storage-1.1.0-py3-none-any.whl
- Upload date:
- Size: 7.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8f8e3f0df09c3cfcaf12e347b3bfe89c95dc0178f9f40720d3f0b2f59e9214e8
|
|
| MD5 |
36521171eb196f49ea5e18d32453007e
|
|
| BLAKE2b-256 |
ddf0801b6387c736ca56d43c51ad261720dd3b84dc1464f9d7d6d2fab5b455b3
|