11import asyncio
2+ from contextvars import ContextVar
23import json
34import logging
45import threading
5152 ScrollMode ,
5253 ThemeMode ,
5354)
54- from flet_core .utils import deprecated
55+ from flet_core .utils import deprecated , classproperty
5556from flet_core .utils .concurrency_utils import is_pyodide
5657from flet_core .view import View
5758
5859logger = logging .getLogger (flet_core .__name__ )
5960
61+ _session_page = ContextVar ("flet_session_page" , default = None )
62+
63+
64+ class context :
65+ @classproperty
66+ def page (cls ) -> "Page" :
67+ return _session_page .get ()
68+
6069
6170try :
6271 from flet_runtime .auth .authorization import Authorization
@@ -239,6 +248,8 @@ def convert_page_media_change_event(e):
239248 self .__on_error = EventHandler ()
240249 self ._add_event_handler ("error" , self .__on_error .get_handler ())
241250
251+ _session_page .set (self )
252+
242253 def get_control (self , id ):
243254 return self ._index .get (id )
244255
@@ -296,6 +307,7 @@ async def fetch_page_details_async(self):
296307 self ._set_attr (props [i ], values [i ], False )
297308
298309 async def _connect (self , conn : Connection ):
310+ _session_page .set (self )
299311 self .__conn = conn
300312 self .__expires_at = None
301313 await self .on_event_async (Event ("page" , "connect" , "" ))
@@ -495,6 +507,7 @@ def __on_page_change_event(self, data):
495507 self ._index [id ]._set_attr (name , props [name ], dirty = False )
496508
497509 def run_task (self , handler : Callable [..., Awaitable [Any ]], * args , ** kwargs ):
510+ _session_page .set (self )
498511 assert asyncio .iscoroutinefunction (handler )
499512
500513 future = asyncio .run_coroutine_threadsafe (handler (* args , ** kwargs ), self .__loop )
@@ -509,13 +522,24 @@ def _on_completion(f):
509522
510523 return future
511524
525+ def __context_wrapper (self , handler ):
526+ def wrapper (* args ):
527+ _session_page .set (self )
528+ handler (* args )
529+
530+ return wrapper
531+
512532 def run_thread (self , handler , * args ):
533+ handler_with_context = self .__context_wrapper (handler )
513534 if is_pyodide ():
514- handler (* args )
535+ handler_with_context (* args )
515536 else :
516537 assert self .__loop
517538 self .__loop .call_soon_threadsafe (
518- self .__loop .run_in_executor , self .__executor , handler , * args
539+ self .__loop .run_in_executor ,
540+ self .__executor ,
541+ handler_with_context ,
542+ * args ,
519543 )
520544
521545 def go (self , route , skip_route_change_event = False , ** kwargs ):
0 commit comments