Explorar o código

bugfix/723: pc.data_table not working well with pandas as computed vars (#745)

* bugfix/723: pc.data_table not working well with pandas as computed vars

Turns out this isnt really a bug. You need to specify an annotation for the computed var to work. This Pr adds a check for annotations on computed vars for data tables

* added more validation for column field
Elijah Ahianyo %!s(int64=2) %!d(string=hai) anos
pai
achega
50cdfac24c

+ 15 - 2
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(

+ 66 - 0
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

+ 41 - 0
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