check for dict passed as children for component (#4656)
This commit is contained in:
parent
268effe62e
commit
9c019a65d5
@ -740,22 +740,21 @@ class Component(BaseComponent, ABC):
|
|||||||
# Import here to avoid circular imports.
|
# Import here to avoid circular imports.
|
||||||
from reflex.components.base.bare import Bare
|
from reflex.components.base.bare import Bare
|
||||||
from reflex.components.base.fragment import Fragment
|
from reflex.components.base.fragment import Fragment
|
||||||
from reflex.utils.exceptions import ComponentTypeError
|
from reflex.utils.exceptions import ChildrenTypeError
|
||||||
|
|
||||||
# Filter out None props
|
# Filter out None props
|
||||||
props = {key: value for key, value in props.items() if value is not None}
|
props = {key: value for key, value in props.items() if value is not None}
|
||||||
|
|
||||||
def validate_children(children):
|
def validate_children(children):
|
||||||
for child in children:
|
for child in children:
|
||||||
if isinstance(child, tuple):
|
if isinstance(child, (tuple, list)):
|
||||||
validate_children(child)
|
validate_children(child)
|
||||||
|
|
||||||
# Make sure the child is a valid type.
|
# Make sure the child is a valid type.
|
||||||
if not types._isinstance(child, ComponentChild):
|
if isinstance(child, dict) or not types._isinstance(
|
||||||
raise ComponentTypeError(
|
child, ComponentChild
|
||||||
"Children of Reflex components must be other components, "
|
):
|
||||||
"state vars, or primitive Python types. "
|
raise ChildrenTypeError(component=cls.__name__, child=child)
|
||||||
f"Got child {child} of type {type(child)}.",
|
|
||||||
)
|
|
||||||
|
|
||||||
# Validate all the children.
|
# Validate all the children.
|
||||||
validate_children(children)
|
validate_children(children)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
"""Custom Exceptions."""
|
"""Custom Exceptions."""
|
||||||
|
|
||||||
from typing import NoReturn
|
from typing import Any, NoReturn
|
||||||
|
|
||||||
|
|
||||||
class ReflexError(Exception):
|
class ReflexError(Exception):
|
||||||
@ -31,6 +31,22 @@ class ComponentTypeError(ReflexError, TypeError):
|
|||||||
"""Custom TypeError for component related errors."""
|
"""Custom TypeError for component related errors."""
|
||||||
|
|
||||||
|
|
||||||
|
class ChildrenTypeError(ComponentTypeError):
|
||||||
|
"""Raised when the children prop of a component is not a valid type."""
|
||||||
|
|
||||||
|
def __init__(self, component: str, child: Any):
|
||||||
|
"""Initialize the exception.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
component: The name of the component.
|
||||||
|
child: The child that caused the error.
|
||||||
|
"""
|
||||||
|
super().__init__(
|
||||||
|
f"Component {component} received child {child} of type {type(child)}. "
|
||||||
|
"Accepted types are other components, state vars, or primitive Python types (dict excluded)."
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class EventHandlerTypeError(ReflexError, TypeError):
|
class EventHandlerTypeError(ReflexError, TypeError):
|
||||||
"""Custom TypeError for event handler related errors."""
|
"""Custom TypeError for event handler related errors."""
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ from reflex.event import (
|
|||||||
from reflex.state import BaseState
|
from reflex.state import BaseState
|
||||||
from reflex.style import Style
|
from reflex.style import Style
|
||||||
from reflex.utils import imports
|
from reflex.utils import imports
|
||||||
from reflex.utils.exceptions import EventFnArgMismatch
|
from reflex.utils.exceptions import ChildrenTypeError, EventFnArgMismatch
|
||||||
from reflex.utils.imports import ImportDict, ImportVar, ParsedImportDict, parse_imports
|
from reflex.utils.imports import ImportDict, ImportVar, ParsedImportDict, parse_imports
|
||||||
from reflex.vars import VarData
|
from reflex.vars import VarData
|
||||||
from reflex.vars.base import LiteralVar, Var
|
from reflex.vars.base import LiteralVar, Var
|
||||||
@ -645,14 +645,17 @@ def test_create_filters_none_props(test_component):
|
|||||||
assert str(component.style["text-align"]) == '"center"'
|
assert str(component.style["text-align"]) == '"center"'
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("children", [((None,),), ("foo", ("bar", (None,)))])
|
@pytest.mark.parametrize(
|
||||||
|
"children",
|
||||||
|
[
|
||||||
|
((None,),),
|
||||||
|
("foo", ("bar", (None,))),
|
||||||
|
({"foo": "bar"},),
|
||||||
|
],
|
||||||
|
)
|
||||||
def test_component_create_unallowed_types(children, test_component):
|
def test_component_create_unallowed_types(children, test_component):
|
||||||
with pytest.raises(TypeError) as err:
|
with pytest.raises(ChildrenTypeError):
|
||||||
test_component.create(*children)
|
test_component.create(*children)
|
||||||
assert (
|
|
||||||
err.value.args[0]
|
|
||||||
== "Children of Reflex components must be other components, state vars, or primitive Python types. Got child None of type <class 'NoneType'>."
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
|
Loading…
Reference in New Issue
Block a user