fix signature check for on_submit

This commit is contained in:
Lendemor 2025-01-16 16:44:14 +01:00
parent f03ccf7ca7
commit 3ac42f247c
3 changed files with 30 additions and 18 deletions

View File

@ -102,7 +102,7 @@ class Fieldset(Element):
name: Var[Union[str, int, bool]] name: Var[Union[str, int, bool]]
def on_submit_event_spec() -> Tuple[Var[Dict[str, Any]]]: def on_submit_event_spec() -> Tuple[Var[dict[str, Any]]]:
"""Event handler spec for the on_submit event. """Event handler spec for the on_submit event.
Returns: Returns:
@ -111,7 +111,7 @@ def on_submit_event_spec() -> Tuple[Var[Dict[str, Any]]]:
return (FORM_DATA,) return (FORM_DATA,)
def on_submit_string_event_spec() -> Tuple[Var[Dict[str, str]]]: def on_submit_string_event_spec() -> Tuple[Var[dict[str, str]]]:
"""Event handler spec for the on_submit event. """Event handler spec for the on_submit event.
Returns: Returns:

View File

@ -270,8 +270,8 @@ class Fieldset(Element):
""" """
... ...
def on_submit_event_spec() -> Tuple[Var[Dict[str, Any]]]: ... def on_submit_event_spec() -> Tuple[Var[dict[str, Any]]]: ...
def on_submit_string_event_spec() -> Tuple[Var[Dict[str, str]]]: ... def on_submit_string_event_spec() -> Tuple[Var[dict[str, str]]]: ...
class Form(BaseHTML): class Form(BaseHTML):
@overload @overload
@ -341,10 +341,10 @@ class Form(BaseHTML):
on_submit: Optional[ on_submit: Optional[
Union[ Union[
Union[ Union[
EventType[[], BASE_STATE], EventType[[Dict[str, Any]], BASE_STATE] EventType[[], BASE_STATE], EventType[[dict[str, Any]], BASE_STATE]
], ],
Union[ Union[
EventType[[], BASE_STATE], EventType[[Dict[str, str]], BASE_STATE] EventType[[], BASE_STATE], EventType[[dict[str, str]], BASE_STATE]
], ],
] ]
] = None, ] = None,

View File

@ -1222,11 +1222,13 @@ def call_event_handler(
key: The key to pass to the event handler. key: The key to pass to the event handler.
Raises: Raises:
EventHandlerArgTypeMismatchError: If the event handler arguments do not match the event spec. EventHandlerArgTypeMismatchError: If the event handler arguments do not match the event spec. #noqa: DAR402
TypeError: If the event handler arguments are invalid. TypeError: If the event handler arguments are invalid.
Returns: Returns:
The event spec from calling the event handler. The event spec from calling the event handler.
#noqa: DAR401
""" """
event_spec_args = parse_args_spec(event_spec) # type: ignore event_spec_args = parse_args_spec(event_spec) # type: ignore
@ -1263,6 +1265,13 @@ def call_event_handler(
), ),
) )
) )
type_match_found: dict[str, bool] = {}
delayed_exceptions: list[EventHandlerArgTypeMismatchError] = []
try:
type_hints_of_provided_callback = get_type_hints(event_callback.fn)
except NameError:
type_hints_of_provided_callback = {}
if event_spec_return_types: if event_spec_return_types:
event_callback_spec = inspect.getfullargspec(event_callback.fn) event_callback_spec = inspect.getfullargspec(event_callback.fn)
@ -1276,18 +1285,13 @@ def call_event_handler(
arg if get_origin(arg) is not Var else get_args(arg)[0] for arg in args arg if get_origin(arg) is not Var else get_args(arg)[0] for arg in args
] ]
try:
type_hints_of_provided_callback = get_type_hints(event_callback.fn)
except NameError:
type_hints_of_provided_callback = {}
failed_type_check = False
# check that args of event handler are matching the spec if type hints are provided # check that args of event handler are matching the spec if type hints are provided
for i, arg in enumerate(event_callback_spec.args[1:]): for i, arg in enumerate(event_callback_spec.args[1:]):
if arg not in type_hints_of_provided_callback: if arg not in type_hints_of_provided_callback:
continue continue
type_match_found.setdefault(arg, False)
try: try:
compare_result = typehint_issubclass( compare_result = typehint_issubclass(
args_types_without_vars[i], type_hints_of_provided_callback[arg] args_types_without_vars[i], type_hints_of_provided_callback[arg]
@ -1298,13 +1302,18 @@ def call_event_handler(
) from te ) from te
if compare_result: if compare_result:
type_match_found[arg] = True
continue continue
else: else:
raise EventHandlerArgTypeMismatchError( type_match_found[arg] = False
f"Event handler {key} expects {args_types_without_vars[i]} for argument {arg} but got {type_hints_of_provided_callback[arg]} as annotated in {event_callback.fn.__qualname__} instead." delayed_exceptions.append(
EventHandlerArgTypeMismatchError(
f"Event handler {key} expects {args_types_without_vars[i]} for argument {arg} but got {type_hints_of_provided_callback[arg]} as annotated in {event_callback.fn.__qualname__} instead."
)
) )
if not failed_type_check: if all(type_match_found.values()):
delayed_exceptions.clear()
if event_spec_index: if event_spec_index:
args = get_args(event_spec_return_types[0]) args = get_args(event_spec_return_types[0])
@ -1326,7 +1335,10 @@ def call_event_handler(
f"Event handler {key} expects ({expect_string}) -> () but got ({given_string}) -> () as annotated in {event_callback.fn.__qualname__} instead. " f"Event handler {key} expects ({expect_string}) -> () but got ({given_string}) -> () as annotated in {event_callback.fn.__qualname__} instead. "
f"This may lead to unexpected behavior but is intentionally ignored for {key}." f"This may lead to unexpected behavior but is intentionally ignored for {key}."
) )
return event_callback(*event_spec_args) break
if delayed_exceptions:
raise delayed_exceptions[0]
return event_callback(*event_spec_args) # type: ignore return event_callback(*event_spec_args) # type: ignore