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
This commit is contained in:
Elijah Ahianyo 2023-04-02 23:49:50 +00:00 committed by GitHub
parent e811a84ed4
commit 50cdfac24c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 122 additions and 2 deletions

View File

@ -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(

View File

@ -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

View File

@ -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