Tabs validate parent is proper tab container (#2463)

This commit is contained in:
Tianze 2024-01-31 03:45:00 +08:00 committed by GitHub
parent 3ff88390c2
commit 209c5fab7b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 42 additions and 1 deletions

View File

@ -90,20 +90,28 @@ class Tab(ChakraComponent):
# The id of the panel.
panel_id: Var[str]
_valid_parents: List[str] = ["TabList"]
class TabList(ChakraComponent):
"""Wrapper for the Tab components."""
tag = "TabList"
_valid_parents: List[str] = ["Tabs"]
class TabPanels(ChakraComponent):
"""Wrapper for the Tab components."""
tag = "TabPanels"
_valid_parents: List[str] = ["Tabs"]
class TabPanel(ChakraComponent):
"""An element that contains the content associated with a tab."""
tag = "TabPanel"
_valid_parents: List[str] = ["TabPanels"]

View File

@ -155,6 +155,9 @@ class Component(BaseComponent, ABC):
# only components that are allowed as children
_valid_children: List[str] = []
# only components that are allowed as parent
_valid_parents: List[str] = []
# custom attribute
custom_attrs: Dict[str, Union[Var, str]] = {}
@ -651,7 +654,8 @@ class Component(BaseComponent, ABC):
children: The children of the component.
"""
if not self._invalid_children and not self._valid_children:
skip_parentable = all(child._valid_parents == [] for child in children)
if not self._invalid_children and not self._valid_children and skip_parentable:
return
comp_name = type(self).__name__
@ -671,6 +675,15 @@ class Component(BaseComponent, ABC):
f"The component `{comp_name}` only allows the components: {valid_child_list} as children. Got `{child_name}` instead."
)
def validate_vaild_parent(child_name, valid_parents):
if comp_name not in valid_parents:
valid_parent_list = ", ".join(
[f"`{v_parent}`" for v_parent in valid_parents]
)
raise ValueError(
f"The component `{child_name}` can only be a child of the components: {valid_parent_list}. Got `{comp_name}` instead."
)
for child in children:
name = type(child).__name__
@ -680,6 +693,9 @@ class Component(BaseComponent, ABC):
if self._valid_children:
validate_valid_child(name)
if child._valid_parents:
validate_vaild_parent(name, child._valid_parents)
@staticmethod
def _get_vars_from_event_triggers(
event_triggers: dict[str, EventChain | Var],

View File

@ -55,6 +55,7 @@ EXCLUDED_PROPS = [
"_invalid_children",
"_memoization_mode",
"_valid_children",
"_valid_parents",
]
DEFAULT_TYPING_IMPORTS = {

View File

@ -137,6 +137,8 @@ def component5() -> Type[Component]:
_valid_children: List[str] = ["Text"]
_valid_parents: List[str] = ["Text"]
return TestComponent5
@ -569,6 +571,20 @@ def test_unsupported_child_components(fixture, request):
)
def test_unsupported_parent_components(component5):
"""Test that a value error is raised when an component is not in _valid_parents of one of its children.
Args:
component5: component with valid parent of "Text" only
"""
with pytest.raises(ValueError) as err:
rx.Box(children=[component5.create()])
assert (
err.value.args[0]
== f"The component `{component5.__name__}` can only be a child of the components: `{component5._valid_parents[0]}`. Got `Box` instead."
)
@pytest.mark.parametrize("fixture", ["component5", "component7"])
def test_component_with_only_valid_children(fixture, request):
"""Test that a value error is raised when an unsupported component (a child component not found in the