From 196a1b161d92813bf79e76caba6713c232617386 Mon Sep 17 00:00:00 2001 From: Puneet Dixit Date: Thu, 21 May 2026 14:19:48 +0530 Subject: [PATCH] Fix DataTable conditional style typing --- components/dash-table/dash_prop_typing.py | 27 ++++++++ .../development/test_dash_table_typing.py | 64 +++++++++++++++++++ 2 files changed, 91 insertions(+) create mode 100644 components/dash-table/dash_prop_typing.py create mode 100644 tests/unit/development/test_dash_table_typing.py diff --git a/components/dash-table/dash_prop_typing.py b/components/dash-table/dash_prop_typing.py new file mode 100644 index 0000000000..22fa7fd2a5 --- /dev/null +++ b/components/dash-table/dash_prop_typing.py @@ -0,0 +1,27 @@ +# This file is automatically loaded on build time to generate types. + +from dash.development._py_prop_typing import get_prop_typing + + +def generate_conditional_style(type_info, component_name, prop_name): + condition_type = get_prop_typing( + type_info["value"]["name"], + component_name, + prop_name, + type_info["value"], + ) + return ( + "typing.Sequence[" + f"typing.Union[{condition_type}, typing.Dict[str, typing.Any]]" + "]" + ) + + +custom_props = { + "DataTable": { + "style_cell_conditional": generate_conditional_style, + "style_data_conditional": generate_conditional_style, + "style_filter_conditional": generate_conditional_style, + "style_header_conditional": generate_conditional_style, + }, +} diff --git a/tests/unit/development/test_dash_table_typing.py b/tests/unit/development/test_dash_table_typing.py new file mode 100644 index 0000000000..77383f1091 --- /dev/null +++ b/tests/unit/development/test_dash_table_typing.py @@ -0,0 +1,64 @@ +import sys +from pathlib import Path + +import pytest + +from dash.development._py_components_generation import generate_class_string +from dash.development._py_prop_typing import shapes + +CONDITIONAL_STYLE_TYPE = { + "name": "arrayOf", + "value": { + "name": "shape", + "value": { + "if": { + "name": "exact", + "value": { + "column_id": {"name": "string", "required": False}, + }, + "required": False, + }, + }, + }, +} + + +@pytest.mark.parametrize( + "prop_name, shape_name", + [ + ("style_cell_conditional", "StyleCellConditional"), + ("style_data_conditional", "StyleDataConditional"), + ("style_filter_conditional", "StyleFilterConditional"), + ("style_header_conditional", "StyleHeaderConditional"), + ], +) +def test_datatable_conditional_styles_allow_style_keys( + monkeypatch, prop_name, shape_name +): + dash_table_dir = Path(__file__).resolve().parents[3] / "components" / "dash-table" + monkeypatch.syspath_prepend(str(dash_table_dir)) + sys.modules.pop("dash_prop_typing", None) + shapes.clear() + + generated = generate_class_string( + typename="DataTable", + props={ + prop_name: { + "type": CONDITIONAL_STYLE_TYPE, + "required": False, + "description": "Conditional style", + }, + }, + description="DataTable", + namespace="dash_table", + custom_typing_module="dash_prop_typing", + ) + + assert ( + f'{prop_name}: typing.Optional[typing.Sequence[typing.Union["{shape_name}", ' + "typing.Dict[str, typing.Any]]]] = None" + ) in generated + assert f'"if": NotRequired["{shape_name}If"]' in generated + + shapes.clear() + sys.modules.pop("dash_prop_typing", None)