diff --git a/pynecone/components/datadisplay/datatable.py b/pynecone/components/datadisplay/datatable.py index ac7ede059..a3ef5b7a6 100644 --- a/pynecone/components/datadisplay/datatable.py +++ b/pynecone/components/datadisplay/datatable.py @@ -5,7 +5,7 @@ from typing import Any, List, Optional from pynecone.components.component import Component from pynecone.components.tags import Tag from pynecone.utils import format, imports, types -from pynecone.var import BaseVar, Var +from pynecone.var import BaseVar, ComputedVar, Var class Gridjs(Component): @@ -61,6 +61,19 @@ class DataTable(Gridjs): ValueError: If a pandas dataframe is passed in and columns are also provided. """ data = props.get("data") + columns = props.get("columns") + + # The annotation should be provided if data is a computed var. We need this to know how to + # render pandas dataframes. + if isinstance(data, ComputedVar) and data.type_ == Any: + raise ValueError( + "Annotation of the computed var assigned to the data field should be provided." + ) + + if columns and isinstance(columns, ComputedVar) and columns.type_ == Any: + raise ValueError( + "Annotation of the computed var assigned to the column field should be provided." + ) # If data is a pandas dataframe and columns are provided throw an error. if ( @@ -73,7 +86,7 @@ class DataTable(Gridjs): # If data is a list and columns are not provided, throw an error if ( - (isinstance(data, Var) and issubclass(data.type_, List)) + (isinstance(data, Var) and types._issubclass(data.type_, List)) or issubclass(type(data), List) ) and not props.get("columns"): raise ValueError( diff --git a/tests/components/datadisplay/conftest.py b/tests/components/datadisplay/conftest.py index 903572e9a..12a9cf04c 100644 --- a/tests/components/datadisplay/conftest.py +++ b/tests/components/datadisplay/conftest.py @@ -1,5 +1,7 @@ """Data display component tests fixtures.""" +from typing import List +import pandas as pd import pytest import pynecone as pc @@ -21,3 +23,67 @@ def data_table_state(request): columns = ["column1", "column2"] return DataTableState + + +@pytest.fixture +def data_table_state2(): + """Get a data table state. + + Returns: + The data table state class. + """ + + class DataTableState(pc.State): + _data = pd.DataFrame() + + @pc.var # type: ignore + def data(self): + return self._data + + return DataTableState + + +@pytest.fixture +def data_table_state3(): + """Get a data table state. + + Returns: + The data table state class. + """ + + class DataTableState(pc.State): + _data: List = [] + _columns: List = ["col1", "col2"] + + @pc.var # type: ignore + def data(self) -> List: + return self._data + + @pc.var # type: ignore + def columns(self): + return self._columns + + return DataTableState + + +@pytest.fixture +def data_table_state4(): + """Get a data table state. + + Returns: + The data table state class. + """ + + class DataTableState(pc.State): + _data: List = [] + _columns: List = ["col1", "col2"] + + @pc.var # type: ignore + def data(self): + return self._data + + @pc.var # type: ignore + def columns(self) -> List: + return self._columns + + return DataTableState diff --git a/tests/components/datadisplay/test_datatable.py b/tests/components/datadisplay/test_datatable.py index 10360ed7d..b2ed7f2a9 100644 --- a/tests/components/datadisplay/test_datatable.py +++ b/tests/components/datadisplay/test_datatable.py @@ -62,3 +62,44 @@ def test_invalid_props(props): """ with pytest.raises(ValueError): data_table(**props) + + +@pytest.mark.parametrize( + "fixture, err_msg, is_data_frame", + [ + ( + "data_table_state2", + "Annotation of the computed var assigned to the data field should be provided.", + True, + ), + ( + "data_table_state3", + "Annotation of the computed var assigned to the column field should be provided.", + False, + ), + ( + "data_table_state4", + "Annotation of the computed var assigned to the data field should be provided.", + False, + ), + ], +) +def test_computed_var_without_annotation(fixture, request, err_msg, is_data_frame): + """Test if value error is thrown when the computed var assigned to the data/column prop is not annotated. + + Args: + fixture: the state. + request: fixture request. + err_msg: expected error message. + is_data_frame: whether data field is a pandas dataframe. + """ + with pytest.raises(ValueError) as err: + + if is_data_frame: + data_table(data=request.getfixturevalue(fixture).data) + else: + data_table( + data=request.getfixturevalue(fixture).data, + columns=request.getfixturevalue(fixture).columns, + ) + assert err.value.args[0] == err_msg