1+ from logging import getLogger
12from uuid import uuid4
23
34import dill as pickle
78from reactpy_django import models
89from reactpy_django .config import (
910 REACTPY_DATABASE ,
11+ REACTPY_DEBUG_MODE ,
1012 REACTPY_RECONNECT_MAX ,
1113 REACTPY_WEBSOCKET_URL ,
1214)
15+ from reactpy_django .exceptions import ComponentDoesNotExistError , ComponentParamError
1316from reactpy_django .types import ComponentParamData
14- from reactpy_django .utils import _register_component , func_has_params
17+ from reactpy_django .utils import (
18+ _register_component ,
19+ check_component_args ,
20+ func_has_args ,
21+ )
1522
1623
1724REACTPY_WEB_MODULES_URL = reverse ("reactpy:web_modules" , args = ["x" ])[:- 1 ][1 :]
1825register = template .Library ()
26+ _logger = getLogger (__name__ )
1927
2028
2129@register .inclusion_tag ("reactpy/component.html" )
@@ -39,24 +47,45 @@ def component(dotted_path: str, *args, **kwargs):
3947 </body>
4048 </html>
4149 """
42- component = _register_component (dotted_path )
43- uuid = uuid4 ().hex
44- class_ = kwargs .pop ("class" , "" )
45- kwargs .pop ("key" , "" ) # `key` is effectively useless for the root node
50+
51+ # Register the component if needed
52+ try :
53+ component = _register_component (dotted_path )
54+ uuid = uuid4 ().hex
55+ class_ = kwargs .pop ("class" , "" )
56+ kwargs .pop ("key" , "" ) # `key` is effectively useless for the root node
57+
58+ except Exception as e :
59+ if isinstance (e , ComponentDoesNotExistError ):
60+ _logger .error (str (e ))
61+ else :
62+ _logger .exception (
63+ "An unknown error has occurred while registering component '%s'." ,
64+ dotted_path ,
65+ )
66+ return failure_context (dotted_path , e )
4667
4768 # Store the component's args/kwargs in the database if needed
4869 # This will be fetched by the websocket consumer later
4970 try :
50- if func_has_params (component , * args , ** kwargs ):
71+ check_component_args (component , * args , ** kwargs )
72+ if func_has_args (component ):
5173 params = ComponentParamData (args , kwargs )
5274 model = models .ComponentSession (uuid = uuid , params = pickle .dumps (params ))
5375 model .full_clean ()
5476 model .save (using = REACTPY_DATABASE )
55- except TypeError as e :
56- raise TypeError (
57- f"The provided parameters are incompatible with component '{ dotted_path } '."
58- ) from e
5977
78+ except Exception as e :
79+ if isinstance (e , ComponentParamError ):
80+ _logger .error (str (e ))
81+ else :
82+ _logger .exception (
83+ "An unknown error has occurred while saving component params for '%s'." ,
84+ dotted_path ,
85+ )
86+ return failure_context (dotted_path , e )
87+
88+ # Return the template rendering context
6089 return {
6190 "class" : class_ ,
6291 "reactpy_websocket_url" : REACTPY_WEBSOCKET_URL ,
@@ -65,3 +94,12 @@ def component(dotted_path: str, *args, **kwargs):
6594 "reactpy_mount_uuid" : uuid ,
6695 "reactpy_component_path" : f"{ dotted_path } /{ uuid } /" ,
6796 }
97+
98+
99+ def failure_context (dotted_path : str , error : Exception ):
100+ return {
101+ "reactpy_failure" : True ,
102+ "reactpy_debug_mode" : REACTPY_DEBUG_MODE ,
103+ "reactpy_dotted_path" : dotted_path ,
104+ "reactpy_error" : type (error ).__name__ ,
105+ }
0 commit comments