@@ -17,27 +17,51 @@ def compose(node: App | Widget) -> list[Widget]:
1717 A list of widgets.
1818 """
1919 _rich_traceback_omit = True
20+ from .widget import MountError , Widget
21+
2022 app = node .app
2123 nodes : list [Widget ] = []
2224 compose_stack : list [Widget ] = []
2325 composed : list [Widget ] = []
2426 app ._compose_stacks .append (compose_stack )
2527 app ._composed .append (composed )
2628 iter_compose = iter (node .compose ())
29+ is_generator = hasattr (iter_compose , "throw" )
2730 try :
2831 while True :
2932 try :
3033 child = next (iter_compose )
3134 except StopIteration :
3235 break
36+
37+ if not isinstance (child , Widget ):
38+ mount_error = MountError (
39+ f"Can't mount { type (child )} ; expected a Widget instance."
40+ )
41+ if is_generator :
42+ iter_compose .throw (mount_error ) # type: ignore
43+ else :
44+ raise mount_error from None
45+
46+ try :
47+ child .id
48+ except AttributeError :
49+ mount_error = MountError (
50+ "Widget is missing an 'id' attribute; did you forget to call super().__init__()?"
51+ )
52+ if is_generator :
53+ iter_compose .throw (mount_error ) # type: ignore
54+ else :
55+ raise mount_error from None
56+
3357 if composed :
3458 nodes .extend (composed )
3559 composed .clear ()
3660 if compose_stack :
3761 try :
3862 compose_stack [- 1 ].compose_add_child (child )
3963 except Exception as error :
40- if hasattr ( iter_compose , "throw" ) :
64+ if is_generator :
4165 # So the error is raised inside the generator
4266 # This will generate a more sensible traceback for the dev
4367 iter_compose .throw (error ) # type: ignore
0 commit comments