diff --git a/.changeset/two-ghosts-sneeze.md b/.changeset/two-ghosts-sneeze.md new file mode 100644 index 000000000000..4c0d758f3444 --- /dev/null +++ b/.changeset/two-ghosts-sneeze.md @@ -0,0 +1,5 @@ +--- +"gradio": patch +--- + +fix:Fixes issues related to `gr.Dataframe` receiving an empty dataframe diff --git a/gradio/components/dataframe.py b/gradio/components/dataframe.py index 13cdf45d93bd..081d3366f35d 100644 --- a/gradio/components/dataframe.py +++ b/gradio/components/dataframe.py @@ -126,7 +126,6 @@ def __init__( self.col_count = self.__process_counts( col_count, len(headers) if headers else 3 ) - self.__validate_headers(headers, self.col_count[0]) self.headers = ( @@ -199,13 +198,18 @@ def preprocess( """ if self.type == "pandas": if payload.headers is not None: - return pd.DataFrame(payload.data, columns=payload.headers) + return pd.DataFrame( + [] if payload.data == [[]] else payload.data, + columns=payload.headers, + ) else: return pd.DataFrame(payload.data) if self.type == "polars": polars = _import_polars() if payload.headers is not None: - return polars.DataFrame(payload.data, schema=payload.headers) + return polars.DataFrame( + [] if payload.data == [[]] else payload.data, schema=payload.headers + ) else: return polars.DataFrame(payload.data) if self.type == "numpy": @@ -240,12 +244,19 @@ def postprocess( if value is None: return self.postprocess(self.empty_input) if isinstance(value, dict): + if len(value) == 0: + return DataframeData(headers=self.headers, data=[[]]) return DataframeData( headers=value.get("headers", []), data=value.get("data", [[]]) ) if isinstance(value, (str, pd.DataFrame)): if isinstance(value, str): value = pd.read_csv(value) # type: ignore + if len(value) == 0: + return DataframeData( + headers=list(value.columns), # type: ignore + data=[[]], # type: ignore + ) return DataframeData( headers=list(value.columns), # type: ignore data=value.to_dict(orient="split")["data"], # type: ignore @@ -262,25 +273,27 @@ def postprocess( "Cannot display Styler object in interactive mode. Will display as a regular pandas dataframe instead." ) df: pd.DataFrame = value.data # type: ignore + if len(df) == 0: + return DataframeData( + headers=list(df.columns), + data=[[]], + metadata=self.__extract_metadata(value), # type: ignore + ) return DataframeData( headers=list(df.columns), data=df.to_dict(orient="split")["data"], # type: ignore metadata=self.__extract_metadata(value), # type: ignore ) - elif isinstance(value, (str, pd.DataFrame)): - df = pd.read_csv(value) if isinstance(value, str) else value # type: ignore - return DataframeData( - headers=list(df.columns), - data=df.to_dict(orient="split")["data"], # type: ignore - ) elif _is_polars_available() and isinstance(value, _import_polars().DataFrame): + if len(value) == 0: + return DataframeData(headers=list(value.to_dict().keys()), data=[[]]) df_dict = value.to_dict() headers = list(df_dict.keys()) data = list(zip(*df_dict.values())) return DataframeData(headers=headers, data=data) elif isinstance(value, (np.ndarray, list)): if len(value) == 0: - return self.postprocess([[]]) + return DataframeData(headers=self.headers, data=[[]]) if isinstance(value, np.ndarray): value = value.tolist() if not isinstance(value, list): diff --git a/test/test_components.py b/test/test_components.py index 955c20cec0c3..c430aaaeffca 100644 --- a/test/test_components.py +++ b/test/test_components.py @@ -1187,7 +1187,7 @@ def test_postprocess(self): """ dataframe_output = gr.Dataframe() output = dataframe_output.postprocess([]).model_dump() - assert output == {"data": [[]], "headers": [], "metadata": None} + assert output == {"data": [[]], "headers": ["1", "2", "3"], "metadata": None} output = dataframe_output.postprocess(np.zeros((2, 2))).model_dump() assert output == { "data": [[0, 0], [0, 0]],