@@ -38,15 +38,18 @@ class LayoutEvent(NamedTuple):
3838 """A list of event data passed to the event handler."""
3939
4040
41- class AbstractLayout (HasAsyncResources , abc .ABC ):
42- """Renders the models generated by :class:`AbstractElement` objects.
41+ class ElementState (NamedTuple ):
42+ model : Dict [str , Any ]
43+ path : List [int ]
44+ element_obj : AbstractElement
45+ event_handler_ids : Set [str ]
46+ child_elements_ids : List [str ]
47+ life_cycle_hook : LifeCycleHook
4348
44- Parameters:
45- root: The root element of the layout.
46- loop: What loop the layout should be using to schedule tasks.
47- """
4849
49- __slots__ = ["_loop" , "_root" ]
50+ class Layout (HasAsyncResources ):
51+
52+ __slots__ = ["_root" , "_event_handlers" ]
5053
5154 if not hasattr (abc .ABC , "__weakref__" ): # pragma: no cover
5255 __slots__ .append ("__weakref__" )
@@ -55,71 +58,23 @@ def __init__(
5558 self , root : "AbstractElement" , loop : Optional [asyncio .AbstractEventLoop ] = None
5659 ) -> None :
5760 super ().__init__ ()
58- if loop is None :
59- loop = asyncio .get_event_loop ()
6061 if not isinstance (root , AbstractElement ):
6162 raise TypeError ("Expected an AbstractElement, not %r" % root )
62- self ._loop = loop
6363 self ._root = root
64-
65- @property
66- def loop (self ) -> asyncio .AbstractEventLoop :
67- """The event loop the layout is using."""
68- return self ._loop
64+ self ._event_handlers : Dict [str , EventHandler ] = {}
6965
7066 @property
7167 def root (self ) -> str :
7268 """Id of the root element."""
7369 return self ._root .id
7470
75- @abc .abstractmethod
76- async def render (self ) -> LayoutUpdate :
77- """Await an update to the model."""
78-
79- @abc .abstractmethod
80- def update (self , element : AbstractElement ) -> None :
81- """Schedule the element to be re-renderer."""
82-
83- @abc .abstractmethod
84- async def trigger (self , event : LayoutEvent ) -> None :
85- """Trigger an event handler
86-
87- Parameters:
88- event: Event data passed to the event handler.
89- """
90-
91- def __repr__ (self ) -> str :
92- return f"{ type (self ).__name__ } ({ self ._root } )"
93-
94-
95- class ElementState (NamedTuple ):
96- model : Dict [str , Any ]
97- path : List [int ]
98- element_obj : AbstractElement
99- event_handler_ids : Set [str ]
100- child_elements_ids : List [str ]
101- life_cycle_hook : LifeCycleHook
102-
103-
104- class Layout (AbstractLayout ):
105-
106- __slots__ = "_event_handlers" , "_rendering_queue"
107-
108- def __init__ (
109- self , root : "AbstractElement" , loop : Optional [asyncio .AbstractEventLoop ] = None
110- ) -> None :
111- super ().__init__ (root , loop )
112- self ._event_handlers : Dict [str , EventHandler ] = {}
113- self ._rendering_queue = _ElementQueue ()
114- self ._rendering_queue .put (self ._root )
115-
11671 def update (self , element : "AbstractElement" ) -> None :
11772 try :
11873 self ._rendering_queue .put (element )
11974 except CannotAccessResource :
12075 logger .info (f"Did not update { element } - resources of { self } are closed" )
12176
122- async def trigger (self , event : LayoutEvent ) -> None :
77+ async def dispatch (self , event : LayoutEvent ) -> None :
12378 # It is possible for an element in the frontend to produce an event
12479 # associated with a backend model that has been deleted. We only handle
12580 # events if the element and the handler exist in the backend. Otherwise
@@ -134,6 +89,12 @@ async def render(self) -> Dict[str, Any]:
13489 if element .id in self ._element_states :
13590 return await self ._create_layout_update (element )
13691
92+ @async_resource
93+ async def _rendering_queue (self ) -> AsyncIterator ["_ElementQueue" ]:
94+ queue = _ElementQueue ()
95+ queue .put (self ._root )
96+ yield queue
97+
13798 @async_resource
13899 async def _element_states (self ) -> AsyncIterator [ElementState ]:
139100 root_element_state = self ._create_element_state (self ._root , "" )
0 commit comments