0
# Storage
1
2
Browser storage APIs including localStorage, sessionStorage, and IndexedDB with Python interfaces for persistent data management in web applications.
3
4
## Capabilities
5
6
### Local Storage
7
8
Persistent key-value storage that survives browser sessions and page reloads.
9
10
```python { .api }
11
class LocalStorage:
12
"""
13
Interface to browser localStorage API.
14
"""
15
16
def __getitem__(self, key: str) -> str:
17
"""
18
Get item from localStorage.
19
20
Args:
21
key: Storage key
22
23
Returns:
24
Stored value as string
25
26
Raises:
27
KeyError: If key doesn't exist
28
"""
29
30
def __setitem__(self, key: str, value: str) -> None:
31
"""
32
Set item in localStorage.
33
34
Args:
35
key: Storage key
36
value: Value to store (converted to string)
37
"""
38
39
def __delitem__(self, key: str) -> None:
40
"""
41
Remove item from localStorage.
42
43
Args:
44
key: Storage key to remove
45
46
Raises:
47
KeyError: If key doesn't exist
48
"""
49
50
def __contains__(self, key: str) -> bool:
51
"""Check if key exists in localStorage."""
52
53
def __len__(self) -> int:
54
"""Get number of items in localStorage."""
55
56
def keys(self) -> list[str]:
57
"""Get all storage keys."""
58
59
def values(self) -> list[str]:
60
"""Get all storage values."""
61
62
def items(self) -> list[tuple[str, str]]:
63
"""Get all key-value pairs."""
64
65
def clear(self) -> None:
66
"""Clear all localStorage data."""
67
68
def get(self, key: str, default: str = None) -> str:
69
"""Get item with default value."""
70
71
def pop(self, key: str, default: str = None) -> str:
72
"""Remove and return item."""
73
```
74
75
**Usage:**
76
```python
77
from browser.local_storage import LocalStorage
78
import json
79
80
storage = LocalStorage()
81
82
# Basic operations
83
storage['username'] = 'john_doe'
84
storage['theme'] = 'dark'
85
86
username = storage['username'] # 'john_doe'
87
theme = storage.get('theme', 'light') # 'dark'
88
89
# Store complex data as JSON
90
user_data = {
91
'name': 'John Doe',
92
'email': 'john@example.com',
93
'preferences': {'theme': 'dark', 'language': 'en'}
94
}
95
96
storage['user_data'] = json.dumps(user_data)
97
98
# Retrieve and parse JSON
99
stored_data = json.loads(storage['user_data'])
100
print(stored_data['name']) # 'John Doe'
101
102
# Check existence and iterate
103
if 'settings' in storage:
104
print("Settings found")
105
106
for key in storage.keys():
107
print(f"{key}: {storage[key]}")
108
109
# Clean up
110
del storage['old_data']
111
storage.clear() # Remove all data
112
```
113
114
### Session Storage
115
116
Temporary storage that persists only for the browser tab session.
117
118
```python { .api }
119
class SessionStorage(LocalStorage):
120
"""
121
Interface to browser sessionStorage API.
122
Inherits all LocalStorage methods but data is session-scoped.
123
"""
124
```
125
126
**Usage:**
127
```python
128
from browser.session_storage import SessionStorage
129
130
session = SessionStorage()
131
132
# Temporary data that won't persist across browser restarts
133
session['temp_token'] = 'abc123'
134
session['form_draft'] = json.dumps({
135
'title': 'Draft Article',
136
'content': 'Work in progress...'
137
})
138
139
# Data available only in current tab/window
140
temp_token = session.get('temp_token')
141
142
# Will be cleared when tab/window closes
143
```
144
145
### IndexedDB
146
147
Advanced database storage for large amounts of structured data with indexing and transactions.
148
149
```python { .api }
150
class IndexedDB:
151
"""
152
Interface to browser IndexedDB API for structured data storage.
153
"""
154
155
def __init__(self, name: str, version: int = 1):
156
"""
157
Initialize IndexedDB connection.
158
159
Args:
160
name: Database name
161
version: Database version number
162
"""
163
164
def open(self) -> None:
165
"""Open database connection."""
166
167
def close(self) -> None:
168
"""Close database connection."""
169
170
def delete_database(self) -> None:
171
"""Delete entire database."""
172
173
def transaction(self, stores: list[str], mode: str = 'readonly') -> 'Transaction':
174
"""
175
Create database transaction.
176
177
Args:
178
stores: List of object store names
179
mode: Transaction mode ('readonly', 'readwrite')
180
181
Returns:
182
Transaction object
183
"""
184
185
def create_object_store(self, name: str, options: dict = None) -> 'ObjectStore':
186
"""
187
Create object store (table).
188
189
Args:
190
name: Store name
191
options: Store configuration (keyPath, autoIncrement, etc.)
192
193
Returns:
194
ObjectStore object
195
"""
196
197
class Transaction:
198
"""Database transaction for atomic operations."""
199
200
def objectStore(self, name: str) -> 'ObjectStore':
201
"""Get object store from transaction."""
202
203
def abort(self) -> None:
204
"""Abort transaction."""
205
206
def commit(self) -> None:
207
"""Commit transaction (usually automatic)."""
208
209
class ObjectStore:
210
"""Object store for data operations."""
211
212
def add(self, value: Any, key: Any = None) -> None:
213
"""Add new record."""
214
215
def put(self, value: Any, key: Any = None) -> None:
216
"""Add or update record."""
217
218
def get(self, key: Any) -> Any:
219
"""Get record by key."""
220
221
def delete(self, key: Any) -> None:
222
"""Delete record by key."""
223
224
def clear(self) -> None:
225
"""Clear all records."""
226
227
def count(self) -> int:
228
"""Count records."""
229
230
def getAll(self, query: Any = None) -> list[Any]:
231
"""Get all records matching query."""
232
233
def getAllKeys(self) -> list[Any]:
234
"""Get all keys."""
235
236
def create_index(self, name: str, keyPath: str, options: dict = None) -> 'Index':
237
"""Create index for faster queries."""
238
```
239
240
**Usage:**
241
```python
242
from browser.indexed_db import IndexedDB, EventListener
243
244
# Database setup
245
class UserDB:
246
def __init__(self):
247
self.db = IndexedDB('UserDatabase', 1)
248
self.setup_database()
249
250
def setup_database(self):
251
def on_upgrade_needed(event):
252
# Create object stores during upgrade
253
users_store = self.db.create_object_store('users', {
254
'keyPath': 'id',
255
'autoIncrement': True
256
})
257
258
# Create indexes
259
users_store.create_index('email', 'email', {'unique': True})
260
users_store.create_index('name', 'name')
261
262
listener = EventListener()
263
listener.bind('upgradeneeded', on_upgrade_needed)
264
self.db.open()
265
266
def add_user(self, user_data):
267
"""Add new user to database."""
268
transaction = self.db.transaction(['users'], 'readwrite')
269
users_store = transaction.objectStore('users')
270
271
def on_success(event):
272
print(f"User added with ID: {event.target.result}")
273
274
def on_error(event):
275
print(f"Error adding user: {event.target.error}")
276
277
request = users_store.add(user_data)
278
request.bind('success', on_success)
279
request.bind('error', on_error)
280
281
def get_user(self, user_id):
282
"""Get user by ID."""
283
transaction = self.db.transaction(['users'], 'readonly')
284
users_store = transaction.objectStore('users')
285
286
def on_success(event):
287
user = event.target.result
288
if user:
289
display_user(user)
290
else:
291
print("User not found")
292
293
request = users_store.get(user_id)
294
request.bind('success', on_success)
295
296
def find_user_by_email(self, email):
297
"""Find user by email using index."""
298
transaction = self.db.transaction(['users'], 'readonly')
299
users_store = transaction.objectStore('users')
300
email_index = users_store.index('email')
301
302
def on_success(event):
303
user = event.target.result
304
if user:
305
print(f"Found user: {user['name']}")
306
else:
307
print("No user with that email")
308
309
request = email_index.get(email)
310
request.bind('success', on_success)
311
312
# Usage
313
user_db = UserDB()
314
315
# Add users
316
user_db.add_user({
317
'name': 'John Doe',
318
'email': 'john@example.com',
319
'age': 30,
320
'created': str(datetime.now())
321
})
322
323
# Retrieve users
324
user_db.get_user(1)
325
user_db.find_user_by_email('john@example.com')
326
```
327
328
### Object Storage
329
330
Generic storage interface for managing Python objects with automatic serialization.
331
332
```python { .api }
333
class ObjectStorage:
334
"""
335
High-level storage interface for Python objects.
336
"""
337
338
def __init__(self, storage_type: str = 'local'):
339
"""
340
Initialize object storage.
341
342
Args:
343
storage_type: 'local', 'session', or 'indexed'
344
"""
345
346
def store(self, key: str, obj: Any) -> None:
347
"""
348
Store Python object.
349
350
Args:
351
key: Storage key
352
obj: Object to store (will be serialized)
353
"""
354
355
def retrieve(self, key: str) -> Any:
356
"""
357
Retrieve and deserialize object.
358
359
Args:
360
key: Storage key
361
362
Returns:
363
Deserialized Python object
364
"""
365
366
def remove(self, key: str) -> None:
367
"""Remove stored object."""
368
369
def exists(self, key: str) -> bool:
370
"""Check if object exists."""
371
372
def list_keys(self) -> list[str]:
373
"""List all storage keys."""
374
```
375
376
**Usage:**
377
```python
378
from browser.object_storage import ObjectStorage
379
380
storage = ObjectStorage('local')
381
382
# Store complex objects
383
user_profile = {
384
'id': 123,
385
'name': 'Jane Smith',
386
'settings': {
387
'theme': 'dark',
388
'notifications': True,
389
'language': 'en'
390
},
391
'history': ['page1', 'page2', 'page3']
392
}
393
394
storage.store('user_profile', user_profile)
395
396
# Retrieve objects
397
profile = storage.retrieve('user_profile')
398
print(profile['settings']['theme']) # 'dark'
399
400
# Manage storage
401
if storage.exists('user_profile'):
402
print("Profile found")
403
404
for key in storage.list_keys():
405
print(f"Stored object: {key}")
406
407
storage.remove('old_data')
408
```
409
410
### Cache Management
411
412
Intelligent caching system with expiration and size management.
413
414
```python { .api }
415
class CacheManager:
416
"""
417
Advanced caching with expiration and size limits.
418
"""
419
420
def set(self, key: str, value: Any, ttl: int = None) -> None:
421
"""
422
Set cached value with optional TTL.
423
424
Args:
425
key: Cache key
426
value: Value to cache
427
ttl: Time to live in seconds
428
"""
429
430
def get(self, key: str) -> Any:
431
"""Get cached value (None if expired/missing)."""
432
433
def invalidate(self, key: str) -> None:
434
"""Remove cached value."""
435
436
def clear_expired(self) -> None:
437
"""Remove all expired cache entries."""
438
439
def clear_all(self) -> None:
440
"""Clear entire cache."""
441
442
def get_stats(self) -> dict:
443
"""Get cache statistics."""
444
```
445
446
**Usage:**
447
```python
448
from browser.storage import CacheManager
449
450
cache = CacheManager()
451
452
# Cache API responses with TTL
453
def fetch_user_data(user_id):
454
cache_key = f'user_{user_id}'
455
456
# Check cache first
457
cached_data = cache.get(cache_key)
458
if cached_data:
459
print("Using cached data")
460
return cached_data
461
462
# Fetch from API if not cached
463
def on_success(req):
464
user_data = req.json
465
# Cache for 5 minutes
466
cache.set(cache_key, user_data, ttl=300)
467
return user_data
468
469
ajax = Ajax()
470
ajax.bind('complete', on_success)
471
ajax.open('GET', f'/api/users/{user_id}')
472
ajax.send()
473
474
# Periodic cache cleanup
475
from browser.timer import set_interval
476
477
def cleanup_cache():
478
cache.clear_expired()
479
stats = cache.get_stats()
480
print(f"Cache: {stats['size']} items, {stats['expired']} expired")
481
482
# Clean up every 10 minutes
483
set_interval(cleanup_cache, 600000)
484
```
485
486
## Storage Best Practices
487
488
### Data Serialization
489
490
```python
491
import json
492
from datetime import datetime
493
494
def serialize_data(data):
495
"""Convert complex data types for storage."""
496
if isinstance(data, datetime):
497
return data.isoformat()
498
elif hasattr(data, '__dict__'):
499
return data.__dict__
500
return data
501
502
def deserialize_data(data):
503
"""Restore complex data types from storage."""
504
if isinstance(data, str) and 'T' in data:
505
try:
506
return datetime.fromisoformat(data)
507
except:
508
pass
509
return data
510
```
511
512
### Storage Quotas
513
514
```python
515
def check_storage_quota():
516
"""Check available storage space."""
517
try:
518
# Test storage availability
519
test_key = '__storage_test__'
520
storage[test_key] = 'x' * 1024 # 1KB test
521
del storage[test_key]
522
return True
523
except:
524
print("Storage quota exceeded")
525
return False
526
527
def cleanup_old_data():
528
"""Remove old data to free space."""
529
current_time = datetime.now().timestamp()
530
531
for key in list(storage.keys()):
532
if key.startswith('temp_'):
533
try:
534
data = json.loads(storage[key])
535
if 'timestamp' in data:
536
age = current_time - data['timestamp']
537
if age > 86400: # 24 hours
538
del storage[key]
539
except:
540
# Remove corrupted data
541
del storage[key]
542
```
543
544
This comprehensive storage system provides persistent data management capabilities for Brython applications, from simple key-value storage to complex database operations with indexing and transactions.