From b1aa662c81047631edee11bc34cd1f21fa1a8cdb Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 9 Mar 2026 22:02:46 +0000 Subject: [PATCH 01/13] Initial plan From 469242a6b564302bf87e4c06dc4d4201563219a4 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 9 Mar 2026 22:07:06 +0000 Subject: [PATCH 02/13] Add AwaitableResponse type hints, delete_rows/get_data methods, remove check_interval Co-authored-by: AlePiccin <149101764+AlePiccin@users.noreply.github.com> --- nicegui_tabulator/core/tabulator.py | 88 +++++++++++++++-------------- 1 file changed, 47 insertions(+), 41 deletions(-) diff --git a/nicegui_tabulator/core/tabulator.py b/nicegui_tabulator/core/tabulator.py index a68cc9d..0fac311 100644 --- a/nicegui_tabulator/core/tabulator.py +++ b/nicegui_tabulator/core/tabulator.py @@ -1,5 +1,5 @@ from pathlib import Path -from typing import Callable, Dict, List, Optional, Tuple, Union +from typing import Any, Callable, Dict, List, Optional, Tuple, Union from nicegui.element import Element from nicegui.awaitable_response import AwaitableResponse from warnings import warn @@ -116,7 +116,7 @@ def _(): return self def run_table_method( - self, name: str, *args, timeout: float = 1, check_interval: float = 0.01 + self, name: str, *args, timeout: float = 1 ) -> AwaitableResponse: """ Run a method on the tabulator table. @@ -125,7 +125,6 @@ def run_table_method( name (str): The name of the method to run. *args: The arguments to pass to the method. timeout (float, optional): The maximum time to wait for the method to complete. Defaults to 1. - check_interval (float, optional): The interval at which to check if the method has completed. Defaults to 0.01. """ return self.run_method("run_table_method", name, *args, timeout=timeout) @@ -352,9 +351,7 @@ def fn(row_number: int, row_index: int): return wrapper - def set_data( - self, data: List[Dict], *, timeout: float = 1, check_interval: float = 0.01 - ): + def set_data(self, data: List[Dict], *, timeout: float = 1) -> AwaitableResponse: """set the data of the table. @see https://tabulator.info/docs/6.2/data#array @@ -362,15 +359,12 @@ def set_data( Args: data (List[Dict]): The data to set for the table. timeout (float, optional): The maximum time to wait for the method to complete. Defaults to 1. - check_interval (float, optional): The interval at which to check if the method has completed. Defaults to 0.01. """ self._set_data_on_server(data) - return self.run_table_method( - "setData", data, timeout=timeout, check_interval=check_interval - ) + return self.run_table_method("setData", data, timeout=timeout) - def replace_data(self, data: List[Dict]): + def replace_data(self, data: List[Dict]) -> AwaitableResponse: """replace the data of the table. @see https://tabulator.info/docs/6.2/update#alter-replace @@ -381,9 +375,7 @@ def replace_data(self, data: List[Dict]): """ return self.set_data(data) - def update_data( - self, data: List[Dict], *, timeout: float = 1, check_interval: float = 0.01 - ): + def update_data(self, data: List[Dict], *, timeout: float = 1) -> AwaitableResponse: """update the data of the table. @see https://tabulator.info/docs/6.2/update#alter-update @@ -391,13 +383,10 @@ def update_data( Args: data (List[Dict]): The data to update the current data with. timeout (float, optional): The maximum time to wait for the method to complete. Defaults to 1. - check_interval (float, optional): The interval at which to check if the method has completed. Defaults to 0.01. """ self._update_data_on_server(data) - return self.run_table_method( - "updateData", data, timeout=timeout, check_interval=check_interval - ) + return self.run_table_method("updateData", data, timeout=timeout) def add_data( self, @@ -406,8 +395,7 @@ def add_data( index: Optional[Union[int, str]] = None, *, timeout: float = 1, - check_interval: float = 0.01, - ): + ) -> AwaitableResponse: """add data to the table. @see https://tabulator.info/docs/6.2/update#alter-add @@ -417,7 +405,6 @@ def add_data( at_top (Optional[bool], optional): determines whether the data is added to the top or bottom of the table. A value of true will add the data to the top of the table, a value of false will add the data to the bottom of the table. If the parameter is not set the data will be placed according to the addRowPos global option. index (Optional[Union[int, str]], optional): table row index. position the new rows next to the specified row (above or below based on the value of the second argument). This argument will take any of the standard row component look up options timeout (float, optional): The maximum time to wait for the method to complete. Defaults to 1. - check_interval (float, optional): The interval at which to check if the method has completed. Defaults to 0.01. """ self._add_data_on_server(data, at_top, index) @@ -427,12 +414,11 @@ def add_data( at_top, index, timeout=timeout, - check_interval=check_interval, ) def update_or_add_data( - self, data: List[Dict], *, timeout: float = 1, check_interval: float = 0.01 - ): + self, data: List[Dict], *, timeout: float = 1 + ) -> AwaitableResponse: """update or add data to the table. If the data you are passing to the table contains a mix of existing rows to be updated and new rows to be added then you can call the updateOrAddData function. This will check each row object provided and update the existing row if available, or else create a new row with the data. @@ -441,30 +427,24 @@ def update_or_add_data( Args: data (List[Dict]): The data to update or add to the current data. timeout (float, optional): The maximum time to wait for the method to complete. Defaults to 1. - check_interval (float, optional): The interval at which to check if the method has completed. Defaults to 0.01. """ self._update_or_add_data_on_server(data) - return self.run_table_method( - "updateOrAddData", data, timeout=timeout, check_interval=check_interval - ) + return self.run_table_method("updateOrAddData", data, timeout=timeout) - def clear_data(self, *, timeout: float = 1, check_interval: float = 0.01): + def clear_data(self, *, timeout: float = 1) -> AwaitableResponse: """clear the data of the table. @see https://tabulator.info/docs/6.2/update#alter-empty Args: timeout (float, optional): The maximum time to wait for the method to complete. Defaults to 1. - check_interval (float, optional): The interval at which to check if the method has completed. Defaults to 0.01. """ self._set_data_on_server([]) - return self.run_table_method( - "clearData", timeout=timeout, check_interval=check_interval - ) + return self.run_table_method("clearData", timeout=timeout) - def sync_data_to_client(self): + def sync_data_to_client(self) -> AwaitableResponse: """sync server data to the client. @see https://github.com/CrystalWindSnake/nicegui-tabulator/tree/main?tab=readme-ov-file##cell-slot @@ -532,7 +512,7 @@ def print( row_range_lookup: Optional[T_Row_Range_Lookup] = None, style: Optional[bool] = True, config: Optional[Dict] = None, - ): + ) -> AwaitableResponse: """A full page printing of the contents of the table without any other elements from the page. Args: @@ -543,10 +523,36 @@ def print( self.sync_data_to_client() return self.run_table_method("print", row_range_lookup, style, config) - async def get_selected_data( - self, *, timeout: float = 1, check_interval: float = 0.01 - ) -> List[Dict]: + def delete_rows( + self, rows_indexes: List[Any], timeout: float = 30 + ) -> AwaitableResponse: + """Delete rows from the table by their index values. + + Args: + rows_indexes (List[Any]): The list of row index values to delete. + timeout (float, optional): The maximum time to wait for the method to complete. Defaults to 30. + + """ + self._delete_rows_on_server(rows_indexes) + return self.run_table_method("deleteRow", rows_indexes, timeout=timeout) + + def _delete_rows_on_server(self, rows_indexes: List[Any]) -> None: + index_field = self.index_field + set_indexes = set(rows_indexes) + new_data = [ + row for row in self.data if row.get(index_field, None) not in set_indexes + ] + self._set_data_on_server(data=new_data) + + async def get_data(self, timeout: float = 30) -> List[Dict[str, Any]]: + """Get the data from the table. + + Args: + timeout (float, optional): The maximum time to wait for the method to complete. Defaults to 30. + + """ + return await self.run_table_method("getData", timeout=timeout) + + async def get_selected_data(self, *, timeout: float = 1) -> List[Dict]: """Get the selected data from the table.""" - return await self.run_table_method( - "getSelectedData", timeout=timeout, check_interval=check_interval - ) + return await self.run_table_method("getSelectedData", timeout=timeout) From 484f133b6ffb36279d36ed1a0d6f4a6a3d7d88e1 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 9 Mar 2026 22:18:01 +0000 Subject: [PATCH 03/13] Modernize type hints across codebase, simplify _set_data_on_server, add missing return types Co-authored-by: AlePiccin <149101764+AlePiccin@users.noreply.github.com> --- nicegui_tabulator/core/dependencies.py | 4 +- nicegui_tabulator/core/tabulator.py | 124 +++++++++++++------------ nicegui_tabulator/core/themes.py | 6 +- nicegui_tabulator/core/types.py | 8 +- nicegui_tabulator/core/utils.py | 15 +-- 5 files changed, 82 insertions(+), 75 deletions(-) diff --git a/nicegui_tabulator/core/dependencies.py b/nicegui_tabulator/core/dependencies.py index 8e81b40..623065b 100644 --- a/nicegui_tabulator/core/dependencies.py +++ b/nicegui_tabulator/core/dependencies.py @@ -6,7 +6,9 @@ ) -def import_luxon(shared: bool = True, script_url: str = LUXON_DEFAULT_SCRIPT_URL): +def import_luxon( + shared: bool = True, script_url: str = LUXON_DEFAULT_SCRIPT_URL +) -> None: """Inject Luxon into the page so Tabulator date/time features can work. Tabulator's date/time formatters and sorters require Luxon to be available in the diff --git a/nicegui_tabulator/core/tabulator.py b/nicegui_tabulator/core/tabulator.py index 0fac311..c2c576c 100644 --- a/nicegui_tabulator/core/tabulator.py +++ b/nicegui_tabulator/core/tabulator.py @@ -1,12 +1,16 @@ +from __future__ import annotations + from pathlib import Path -from typing import Any, Callable, Dict, List, Optional, Tuple, Union -from nicegui.element import Element -from nicegui.awaitable_response import AwaitableResponse +from typing import Any, Callable from warnings import warn -from .utils import DeferredTask + +from nicegui.awaitable_response import AwaitableResponse +from nicegui.element import Element from nicegui.elements.teleport import Teleport as teleport -from .types import CellSlotProps, T_Row_Range_Lookup + from . import utils +from .types import CellSlotProps, T_Row_Range_Lookup +from .utils import DeferredTask try: import pandas as pd @@ -19,13 +23,13 @@ class Tabulator( ): def __init__( self, - options: Dict, - row_key: Optional[str] = "id", + options: dict, + row_key: str | None = "id", ) -> None: """Create a new tabulator table. Args: - options (Dict): The options for the tabulator table. + options (dict): The options for the tabulator table. row_key (str, optional): The field to be used as the unique index for each row. Defaults to "id". """ super().__init__() @@ -37,8 +41,8 @@ def __init__( self._props["options"] = options self.add_resource(Path(__file__).parent / "libs") - self._cell_slot_map: Dict[str, Callable] = {} - self._teleport_slots_cache: Dict[Tuple[str, int], teleport] = {} + self._cell_slot_map: dict[str, Callable] = {} + self._teleport_slots_cache: dict[tuple[str, int], teleport] = {} def on_update_cell_slot(e): field = e.args["field"] @@ -70,12 +74,12 @@ def on_connected(): self.on("connected", on_connected) @property - def index_field(self): + def index_field(self) -> str: """Get the index field for the tabulator table.By default Tabulator will look for this value in the id field for the data.""" return self._props["options"].get("index", "id") @property - def data(self): + def data(self) -> list[dict]: """Get or set the data for the tabulator table.""" if "data" not in self._props["options"]: self._props["options"]["data"] = [] @@ -129,14 +133,14 @@ def run_table_method( """ return self.run_method("run_table_method", name, *args, timeout=timeout) - def set_columns(self, columns: List[Dict]) -> None: + def set_columns(self, columns: list[dict]) -> None: """ To replace the current column definitions for all columns in a table. @see https://tabulator.info/docs/6.2/columns#replace Args: - columns (List[Dict]): The list of column definition objects for the table. + columns (list[dict]): The list of column definition objects for the table. ## Example Usage @@ -156,7 +160,7 @@ def set_columns(self, columns: List[Dict]) -> None: def _(): return self.run_method("setColumns", columns) - def update_column_definition(self, field: str, definition: Dict) -> None: + def update_column_definition(self, field: str, definition: dict) -> None: """ Update an existing column definition. @@ -164,7 +168,7 @@ def update_column_definition(self, field: str, definition: Dict) -> None: Args: field (str): The field name of the column you want to update. - definition (Dict): The new column definition object for the column. + definition (dict): The new column definition object for the column. ## Example Usage @@ -180,9 +184,9 @@ def _(): def add_column( self, - definition: Dict, - before: Optional[bool] = None, - position: Optional[str] = None, + definition: dict, + before: bool | None = None, + position: str | None = None, ) -> None: """ Add a column to the table. @@ -191,9 +195,9 @@ def add_column( Args: - definition (Dict): The column definition object for the column you want to add. - before (Optional[bool], optional): Determines how to position the new column. A value of true will insert the column to the left of existing columns, a value of false will insert it to the right. If a Position argument is supplied then this will determine whether the new colum is inserted before or after this column. - position (Optional[str], optional): The field to insert the new column next to, this can be any of the standard column component look up options. + definition (dict): The column definition object for the column you want to add. + before (bool | None, optional): Determines how to position the new column. A value of true will insert the column to the left of existing columns, a value of false will insert it to the right. If a Position argument is supplied then this will determine whether the new colum is inserted before or after this column. + position (str | None, optional): The field to insert the new column next to, this can be any of the standard column component look up options. ## Example Usage @@ -212,10 +216,10 @@ def from_pandas( cls, df: "pd.DataFrame", *, - index: Optional[str] = None, + index: str | None = None, auto_index=False, - options: Optional[Dict] = None, - column_definition: Optional[Callable[[str], Dict]] = None, + options: dict | None = None, + column_definition: Callable[[str], dict] | None = None, ): """Create a table from a Pandas DataFrame. @@ -227,8 +231,8 @@ def from_pandas( df (pd.DataFrame): The DataFrame to create the table from. index (str, optional): The field to be used as the unique index for each row. auto_index (bool, optional): If `True` and the `index` parameter is `None`, a sequence number column will be automatically generated as the index. - options (Dict, optional): The options for the tabulator table. - column_definition (Callable[[str], Dict], optional): A function that takes a column name and returns a column definition object for that column. + options (dict, optional): The options for the tabulator table. + column_definition (Callable[[str], dict], optional): A function that takes a column name and returns a column definition object for that column. """ def is_special_dtype(dtype): @@ -251,7 +255,7 @@ def is_special_dtype(dtype): '`df.columns = ["_".join(col) for col in df.columns.values]`.' ) - columns: List[Dict] = [ + columns: list[dict] = [ {"title": col, "field": col} if column_definition is None else {"field": col, **column_definition(col)} @@ -351,37 +355,37 @@ def fn(row_number: int, row_index: int): return wrapper - def set_data(self, data: List[Dict], *, timeout: float = 1) -> AwaitableResponse: + def set_data(self, data: list[dict], *, timeout: float = 1) -> AwaitableResponse: """set the data of the table. @see https://tabulator.info/docs/6.2/data#array Args: - data (List[Dict]): The data to set for the table. + data (list[dict]): The data to set for the table. timeout (float, optional): The maximum time to wait for the method to complete. Defaults to 1. """ self._set_data_on_server(data) return self.run_table_method("setData", data, timeout=timeout) - def replace_data(self, data: List[Dict]) -> AwaitableResponse: + def replace_data(self, data: list[dict]) -> AwaitableResponse: """replace the data of the table. @see https://tabulator.info/docs/6.2/update#alter-replace Args: - data (List[Dict]): The data to replace the current data with. + data (list[dict]): The data to replace the current data with. """ return self.set_data(data) - def update_data(self, data: List[Dict], *, timeout: float = 1) -> AwaitableResponse: + def update_data(self, data: list[dict], *, timeout: float = 1) -> AwaitableResponse: """update the data of the table. @see https://tabulator.info/docs/6.2/update#alter-update Args: - data (List[Dict]): The data to update the current data with. + data (list[dict]): The data to update the current data with. timeout (float, optional): The maximum time to wait for the method to complete. Defaults to 1. """ @@ -390,9 +394,9 @@ def update_data(self, data: List[Dict], *, timeout: float = 1) -> AwaitableRespo def add_data( self, - data: List[Dict], - at_top: Optional[bool] = None, - index: Optional[Union[int, str]] = None, + data: list[dict], + at_top: bool | None = None, + index: int | str | None = None, *, timeout: float = 1, ) -> AwaitableResponse: @@ -401,9 +405,9 @@ def add_data( @see https://tabulator.info/docs/6.2/update#alter-add Args: - data (List[Dict]): The data to add to the current data. - at_top (Optional[bool], optional): determines whether the data is added to the top or bottom of the table. A value of true will add the data to the top of the table, a value of false will add the data to the bottom of the table. If the parameter is not set the data will be placed according to the addRowPos global option. - index (Optional[Union[int, str]], optional): table row index. position the new rows next to the specified row (above or below based on the value of the second argument). This argument will take any of the standard row component look up options + data (list[dict]): The data to add to the current data. + at_top (bool | None, optional): determines whether the data is added to the top or bottom of the table. A value of true will add the data to the top of the table, a value of false will add the data to the bottom of the table. If the parameter is not set the data will be placed according to the addRowPos global option. + index (int | str | None, optional): table row index. position the new rows next to the specified row (above or below based on the value of the second argument). This argument will take any of the standard row component look up options timeout (float, optional): The maximum time to wait for the method to complete. Defaults to 1. """ @@ -417,7 +421,7 @@ def add_data( ) def update_or_add_data( - self, data: List[Dict], *, timeout: float = 1 + self, data: list[dict], *, timeout: float = 1 ) -> AwaitableResponse: """update or add data to the table. If the data you are passing to the table contains a mix of existing rows to be updated and new rows to be added then you can call the updateOrAddData function. This will check each row object provided and update the existing row if available, or else create a new row with the data. @@ -425,7 +429,7 @@ def update_or_add_data( @see https://tabulator.info/docs/6.2/update#alter-add Args: - data (List[Dict]): The data to update or add to the current data. + data (list[dict]): The data to update or add to the current data. timeout (float, optional): The maximum time to wait for the method to complete. Defaults to 1. """ @@ -453,9 +457,9 @@ def sync_data_to_client(self) -> AwaitableResponse: def _add_data_on_server( self, - data: List[Dict], - at_top: Optional[bool] = None, - index: Optional[Union[int, str]] = None, + data: list[dict], + at_top: bool | None = None, + index: int | str | None = None, ): at_top = ( at_top @@ -477,12 +481,10 @@ def _add_data_on_server( self._set_data_on_server(self.data[:row_index] + data + self.data[row_index:]) - def _set_data_on_server(self, data: List[Dict]): - if "data" not in self._props["options"]: - self._props["options"]["data"] = None + def _set_data_on_server(self, data: list[dict]) -> None: self._props["options"]["data"] = data[:] - def _update_data_on_server(self, data: List[Dict]): + def _update_data_on_server(self, data: list[dict]) -> None: index_field = self.index_field update_dict = {record[index_field]: record for record in data} @@ -496,7 +498,7 @@ def _update_data_on_server(self, data: List[Dict]): if update_record: row.update(update_record) - def _update_or_add_data_on_server(self, data: List[Dict]): + def _update_or_add_data_on_server(self, data: list[dict]) -> None: index_field = self.index_field update_dict = {item[index_field]: item for item in data} @@ -509,34 +511,34 @@ def _update_or_add_data_on_server(self, data: List[Dict]): def print( self, *, - row_range_lookup: Optional[T_Row_Range_Lookup] = None, - style: Optional[bool] = True, - config: Optional[Dict] = None, + row_range_lookup: T_Row_Range_Lookup | None = None, + style: bool | None = True, + config: dict | None = None, ) -> AwaitableResponse: """A full page printing of the contents of the table without any other elements from the page. Args: - row_range_lookup (Optional[T_Row_Range_Lookup], optional): Determins which rows are shown in the printed table, if no value is set it will use the value set in the printRowRange option. - style (Optional[bool], optional): Determines if the output of the function should be styled to match the table (true) or be a blank html table (false), if you leave this argument out it will take the value of the printStyled option. Defaults to True. - config (Optional[Dict], optional): An object that can be used to override the object set on the printConfig option. Defaults to None. + row_range_lookup (T_Row_Range_Lookup | None, optional): Determins which rows are shown in the printed table, if no value is set it will use the value set in the printRowRange option. + style (bool | None, optional): Determines if the output of the function should be styled to match the table (true) or be a blank html table (false), if you leave this argument out it will take the value of the printStyled option. Defaults to True. + config (dict | None, optional): An object that can be used to override the object set on the printConfig option. Defaults to None. """ self.sync_data_to_client() return self.run_table_method("print", row_range_lookup, style, config) def delete_rows( - self, rows_indexes: List[Any], timeout: float = 30 + self, rows_indexes: list[Any], timeout: float = 30 ) -> AwaitableResponse: """Delete rows from the table by their index values. Args: - rows_indexes (List[Any]): The list of row index values to delete. + rows_indexes (list[Any]): The list of row index values to delete. timeout (float, optional): The maximum time to wait for the method to complete. Defaults to 30. """ self._delete_rows_on_server(rows_indexes) return self.run_table_method("deleteRow", rows_indexes, timeout=timeout) - def _delete_rows_on_server(self, rows_indexes: List[Any]) -> None: + def _delete_rows_on_server(self, rows_indexes: list[Any]) -> None: index_field = self.index_field set_indexes = set(rows_indexes) new_data = [ @@ -544,7 +546,7 @@ def _delete_rows_on_server(self, rows_indexes: List[Any]) -> None: ] self._set_data_on_server(data=new_data) - async def get_data(self, timeout: float = 30) -> List[Dict[str, Any]]: + async def get_data(self, timeout: float = 30) -> list[dict[str, Any]]: """Get the data from the table. Args: @@ -553,6 +555,6 @@ async def get_data(self, timeout: float = 30) -> List[Dict[str, Any]]: """ return await self.run_table_method("getData", timeout=timeout) - async def get_selected_data(self, *, timeout: float = 1) -> List[Dict]: + async def get_selected_data(self, *, timeout: float = 1) -> list[dict]: """Get the selected data from the table.""" return await self.run_table_method("getSelectedData", timeout=timeout) diff --git a/nicegui_tabulator/core/themes.py b/nicegui_tabulator/core/themes.py index 0f8a8ef..3130664 100644 --- a/nicegui_tabulator/core/themes.py +++ b/nicegui_tabulator/core/themes.py @@ -1,6 +1,6 @@ from __future__ import annotations from pathlib import Path -from typing import Literal, Optional +from typing import Literal from nicegui import ui, app, Client _ASSETS_DIR = Path(__file__).parent / "libs" @@ -28,12 +28,12 @@ """ -def use_theme(theme_name: _T_THEME_NAME, shared: Optional[bool] = None) -> None: +def use_theme(theme_name: _T_THEME_NAME, shared: bool | None = None) -> None: """Use a tabulator theme. Args: theme_name (_T_THEME_NAME): name of the theme to use. - shared (Optional[bool], optional): Whether to use the theme for all clients or only the current client. + shared (bool | None, optional): Whether to use the theme for all clients or only the current client. `None`(default): use the theme for all clients if there is no client context (e.g. at startup), otherwise use it only for the current client. `True`: use the theme for all clients. `False`: use the theme only for the current client. diff --git a/nicegui_tabulator/core/types.py b/nicegui_tabulator/core/types.py index 4f7b8a1..56dd6fd 100644 --- a/nicegui_tabulator/core/types.py +++ b/nicegui_tabulator/core/types.py @@ -1,6 +1,6 @@ from __future__ import annotations from dataclasses import dataclass, field as dc_field -from typing import Any, Dict, Literal +from typing import Any, Literal from typing import TYPE_CHECKING @@ -14,7 +14,7 @@ class CellSlotProps: """The name of the field in the row data.""" value: Any """The value of the field in the row data.""" - row: Dict + row: dict """The row data.""" row_number: int """The position(starting from 1) of the row in the table data.""" @@ -23,13 +23,13 @@ class CellSlotProps: table: Tabulator = dc_field(init=True, repr=False) """The parent Tabulator instance.""" - def update_value(self, value): + def update_value(self, value: Any) -> None: """Updates the value of the field in the row data only on the server side.""" index_field = self.table.index_field data = [{index_field: self.row[index_field], self.field: value}] self.table._update_data_on_server(data) - def update_to_client(self): + def update_to_client(self) -> None: """Updates the value of the field in the row data on the client side.""" index_field = self.table.index_field diff --git a/nicegui_tabulator/core/utils.py b/nicegui_tabulator/core/utils.py index 74f2504..e6607c8 100644 --- a/nicegui_tabulator/core/utils.py +++ b/nicegui_tabulator/core/utils.py @@ -1,10 +1,13 @@ -from typing import Union, Callable -from nicegui import ui, Client as ng_client -from nicegui.awaitable_response import AwaitableResponse +from __future__ import annotations + +from typing import Callable import asyncio import uuid -_TTask = Union[Callable[..., None], Callable[..., AwaitableResponse]] +from nicegui import ui, Client as ng_client +from nicegui.awaitable_response import AwaitableResponse + +_TTask = Callable[..., None] | Callable[..., AwaitableResponse] class DeferredTask: @@ -33,11 +36,11 @@ def flush(self): self._tasks.clear() - def _execute_task(self, task): + def _execute_task(self, task: _TTask) -> None: result = task() if asyncio.iscoroutine(result): asyncio.create_task(result) -def generate_dataframe_unique_id_column_name(): +def generate_dataframe_unique_id_column_name() -> str: return f"__{uuid.uuid4().hex}" From 24f37b7c21b5720792fd69da49d6eb1e9c897eaf Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 9 Mar 2026 22:31:52 +0000 Subject: [PATCH 04/13] Remove replace_data method and standardize all timeout defaults to 1 Co-authored-by: AlePiccin <149101764+AlePiccin@users.noreply.github.com> --- nicegui_tabulator/core/tabulator.py | 19 ++++--------------- tests/test_tabulator.py | 29 ----------------------------- 2 files changed, 4 insertions(+), 44 deletions(-) diff --git a/nicegui_tabulator/core/tabulator.py b/nicegui_tabulator/core/tabulator.py index c2c576c..9a4c813 100644 --- a/nicegui_tabulator/core/tabulator.py +++ b/nicegui_tabulator/core/tabulator.py @@ -368,17 +368,6 @@ def set_data(self, data: list[dict], *, timeout: float = 1) -> AwaitableResponse self._set_data_on_server(data) return self.run_table_method("setData", data, timeout=timeout) - def replace_data(self, data: list[dict]) -> AwaitableResponse: - """replace the data of the table. - - @see https://tabulator.info/docs/6.2/update#alter-replace - - Args: - data (list[dict]): The data to replace the current data with. - - """ - return self.set_data(data) - def update_data(self, data: list[dict], *, timeout: float = 1) -> AwaitableResponse: """update the data of the table. @@ -526,13 +515,13 @@ def print( return self.run_table_method("print", row_range_lookup, style, config) def delete_rows( - self, rows_indexes: list[Any], timeout: float = 30 + self, rows_indexes: list[Any], timeout: float = 1 ) -> AwaitableResponse: """Delete rows from the table by their index values. Args: rows_indexes (list[Any]): The list of row index values to delete. - timeout (float, optional): The maximum time to wait for the method to complete. Defaults to 30. + timeout (float, optional): The maximum time to wait for the method to complete. Defaults to 1. """ self._delete_rows_on_server(rows_indexes) @@ -546,11 +535,11 @@ def _delete_rows_on_server(self, rows_indexes: list[Any]) -> None: ] self._set_data_on_server(data=new_data) - async def get_data(self, timeout: float = 30) -> list[dict[str, Any]]: + async def get_data(self, timeout: float = 1) -> list[dict[str, Any]]: """Get the data from the table. Args: - timeout (float, optional): The maximum time to wait for the method to complete. Defaults to 30. + timeout (float, optional): The maximum time to wait for the method to complete. Defaults to 1. """ return await self.run_table_method("getData", timeout=timeout) diff --git a/tests/test_tabulator.py b/tests/test_tabulator.py index ab78034..6e36934 100644 --- a/tests/test_tabulator.py +++ b/tests/test_tabulator.py @@ -586,35 +586,6 @@ def _(): server_data_checker.expect_server_data(page) -def test_replace_data(browser: BrowserManager, page_path: str): - server_data_checker = ServerDataChecker() - - @ui.page(page_path) - def _(): - table = tabulator(create_table_options()).classes("target") - - label_server_data = server_data_checker.create_elements(table) - - ui.button( - "replace data", - on_click=lambda: ( - table.replace_data( - [{"id": 1, "name": "bar-replace-data", "age": "12"}] - ), - label_server_data.set_text(str(table.data)), - ), - ) - - page = browser.open(page_path) - table_locator = page.locator(".target") - - # set data - page.get_by_role("button").filter(has_text="replace data").click() - check_table_rows(table_locator, [["bar-replace-data", "12"]]) - - server_data_checker.expect_server_data(page) - - def test_update_data(browser: BrowserManager, page_path: str): server_data_checker = ServerDataChecker() From 97d94cba094747567d3cbc2fbfb0711308c4bac5 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 10 Mar 2026 14:51:41 +0000 Subject: [PATCH 05/13] Initial plan From 279f7a903783f639d9c72087bed92c591db77ea7 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 10 Mar 2026 14:56:25 +0000 Subject: [PATCH 06/13] fix: use Union[] instead of | for type alias to support Python 3.9 Co-authored-by: AlePiccin <149101764+AlePiccin@users.noreply.github.com> --- nicegui_tabulator/core/utils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nicegui_tabulator/core/utils.py b/nicegui_tabulator/core/utils.py index e6607c8..49c606e 100644 --- a/nicegui_tabulator/core/utils.py +++ b/nicegui_tabulator/core/utils.py @@ -1,13 +1,13 @@ from __future__ import annotations -from typing import Callable +from typing import Callable, Union import asyncio import uuid from nicegui import ui, Client as ng_client from nicegui.awaitable_response import AwaitableResponse -_TTask = Callable[..., None] | Callable[..., AwaitableResponse] +_TTask = Union[Callable[..., None], Callable[..., AwaitableResponse]] class DeferredTask: From 4b00b5c555981756fc84982279323f368a18c5ef Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 10 Mar 2026 15:10:29 +0000 Subject: [PATCH 07/13] fix: bump requires-python to >=3.10 instead of changing union syntax Co-authored-by: AlePiccin <149101764+AlePiccin@users.noreply.github.com> --- nicegui_tabulator/core/utils.py | 4 ++-- pyproject.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/nicegui_tabulator/core/utils.py b/nicegui_tabulator/core/utils.py index 49c606e..e6607c8 100644 --- a/nicegui_tabulator/core/utils.py +++ b/nicegui_tabulator/core/utils.py @@ -1,13 +1,13 @@ from __future__ import annotations -from typing import Callable, Union +from typing import Callable import asyncio import uuid from nicegui import ui, Client as ng_client from nicegui.awaitable_response import AwaitableResponse -_TTask = Union[Callable[..., None], Callable[..., AwaitableResponse]] +_TTask = Callable[..., None] | Callable[..., AwaitableResponse] class DeferredTask: diff --git a/pyproject.toml b/pyproject.toml index d4a273b..cbdeb64 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,7 +8,7 @@ readme = "README.md" authors = [ { name = "CrystalWindSnake", email = "568166495@qq.com" } ] -requires-python = ">=3.9" +requires-python = ">=3.10" dependencies = [ "nicegui~=3.5", From 762dfb4827159adff6d78b2ba26b262ef39ac977 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 11 Mar 2026 14:32:18 +0000 Subject: [PATCH 08/13] Initial plan From 8dea47ee928a76278692b679a007d21d54caf3de Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 11 Mar 2026 14:38:58 +0000 Subject: [PATCH 09/13] Make compatible with Python 3.9: update requires-python and fix runtime type union in utils.py Co-authored-by: AlePiccin <149101764+AlePiccin@users.noreply.github.com> --- nicegui_tabulator/core/utils.py | 4 ++-- pyproject.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/nicegui_tabulator/core/utils.py b/nicegui_tabulator/core/utils.py index e6607c8..49c606e 100644 --- a/nicegui_tabulator/core/utils.py +++ b/nicegui_tabulator/core/utils.py @@ -1,13 +1,13 @@ from __future__ import annotations -from typing import Callable +from typing import Callable, Union import asyncio import uuid from nicegui import ui, Client as ng_client from nicegui.awaitable_response import AwaitableResponse -_TTask = Callable[..., None] | Callable[..., AwaitableResponse] +_TTask = Union[Callable[..., None], Callable[..., AwaitableResponse]] class DeferredTask: diff --git a/pyproject.toml b/pyproject.toml index cbdeb64..d4a273b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,7 +8,7 @@ readme = "README.md" authors = [ { name = "CrystalWindSnake", email = "568166495@qq.com" } ] -requires-python = ">=3.10" +requires-python = ">=3.9" dependencies = [ "nicegui~=3.5", From b8066efff8ac95448ac04741b9a7a8cf73283db0 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 11 Mar 2026 15:14:21 +0000 Subject: [PATCH 10/13] Standardize type notation: replace pipe unions with Union/Optional, remove from __future__ import annotations Co-authored-by: AlePiccin <149101764+AlePiccin@users.noreply.github.com> --- =0.7.1 | 34 +++++++++++++++ nicegui_tabulator/core/events.py | 2 - nicegui_tabulator/core/tabulator.py | 64 ++++++++++++++--------------- nicegui_tabulator/core/themes.py | 5 +-- nicegui_tabulator/core/types.py | 3 +- nicegui_tabulator/core/utils.py | 6 +-- 6 files changed, 70 insertions(+), 44 deletions(-) create mode 100644 =0.7.1 diff --git a/=0.7.1 b/=0.7.1 new file mode 100644 index 0000000..3be9cd7 --- /dev/null +++ b/=0.7.1 @@ -0,0 +1,34 @@ +Defaulting to user installation because normal site-packages is not writeable +Collecting playwright==1.57.0 + Downloading playwright-1.57.0-py3-none-manylinux1_x86_64.whl.metadata (3.5 kB) +Collecting pytest-playwright + Downloading pytest_playwright-0.7.2-py3-none-any.whl.metadata (14 kB) +Collecting pyee<14,>=13 (from playwright==1.57.0) + Downloading pyee-13.0.1-py3-none-any.whl.metadata (3.0 kB) +Collecting greenlet<4.0.0,>=3.1.1 (from playwright==1.57.0) + Downloading greenlet-3.3.2-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl.metadata (3.7 kB) +Requirement already satisfied: pytest<10.0.0,>=6.2.4 in /home/runner/.local/lib/python3.12/site-packages (from pytest-playwright) (9.0.2) +Collecting pytest-base-url<3.0.0,>=1.0.0 (from pytest-playwright) + Downloading pytest_base_url-2.1.0-py3-none-any.whl.metadata (6.6 kB) +Collecting python-slugify<9.0.0,>=6.0.0 (from pytest-playwright) + Downloading python_slugify-8.0.4-py2.py3-none-any.whl.metadata (8.5 kB) +Requirement already satisfied: typing-extensions in /home/runner/.local/lib/python3.12/site-packages (from pyee<14,>=13->playwright==1.57.0) (4.15.0) +Requirement already satisfied: iniconfig>=1.0.1 in /home/runner/.local/lib/python3.12/site-packages (from pytest<10.0.0,>=6.2.4->pytest-playwright) (2.3.0) +Requirement already satisfied: packaging>=22 in /usr/lib/python3/dist-packages (from pytest<10.0.0,>=6.2.4->pytest-playwright) (24.0) +Requirement already satisfied: pluggy<2,>=1.5 in /home/runner/.local/lib/python3.12/site-packages (from pytest<10.0.0,>=6.2.4->pytest-playwright) (1.6.0) +Requirement already satisfied: pygments>=2.7.2 in /usr/lib/python3/dist-packages (from pytest<10.0.0,>=6.2.4->pytest-playwright) (2.17.2) +Requirement already satisfied: requests>=2.9 in /usr/lib/python3/dist-packages (from pytest-base-url<3.0.0,>=1.0.0->pytest-playwright) (2.31.0) +Collecting text-unidecode>=1.3 (from python-slugify<9.0.0,>=6.0.0->pytest-playwright) + Downloading text_unidecode-1.3-py2.py3-none-any.whl.metadata (2.4 kB) +Downloading playwright-1.57.0-py3-none-manylinux1_x86_64.whl (46.0 MB) + ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 46.0/46.0 MB 51.0 MB/s eta 0:00:00 +Downloading pytest_playwright-0.7.2-py3-none-any.whl (16 kB) +Downloading greenlet-3.3.2-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl (613 kB) + ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 613.9/613.9 kB 94.5 MB/s eta 0:00:00 +Downloading pyee-13.0.1-py3-none-any.whl (15 kB) +Downloading pytest_base_url-2.1.0-py3-none-any.whl (5.3 kB) +Downloading python_slugify-8.0.4-py2.py3-none-any.whl (10 kB) +Downloading text_unidecode-1.3-py2.py3-none-any.whl (78 kB) + ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 78.2/78.2 kB 31.0 MB/s eta 0:00:00 +Installing collected packages: text-unidecode, python-slugify, pyee, greenlet, pytest-base-url, playwright, pytest-playwright +Successfully installed greenlet-3.3.2 playwright-1.57.0 pyee-13.0.1 pytest-base-url-2.1.0 pytest-playwright-0.7.2 python-slugify-8.0.4 text-unidecode-1.3 diff --git a/nicegui_tabulator/core/events.py b/nicegui_tabulator/core/events.py index 3cb9671..d78da6a 100644 --- a/nicegui_tabulator/core/events.py +++ b/nicegui_tabulator/core/events.py @@ -1,5 +1,3 @@ -from __future__ import annotations - from dataclasses import dataclass from typing import ( Any, diff --git a/nicegui_tabulator/core/tabulator.py b/nicegui_tabulator/core/tabulator.py index 9a4c813..9c563e6 100644 --- a/nicegui_tabulator/core/tabulator.py +++ b/nicegui_tabulator/core/tabulator.py @@ -1,7 +1,5 @@ -from __future__ import annotations - from pathlib import Path -from typing import Any, Callable +from typing import Any, Callable, Dict, List, Optional, Tuple, Union from warnings import warn from nicegui.awaitable_response import AwaitableResponse @@ -24,7 +22,7 @@ class Tabulator( def __init__( self, options: dict, - row_key: str | None = "id", + row_key: Optional[str] = "id", ) -> None: """Create a new tabulator table. @@ -41,8 +39,8 @@ def __init__( self._props["options"] = options self.add_resource(Path(__file__).parent / "libs") - self._cell_slot_map: dict[str, Callable] = {} - self._teleport_slots_cache: dict[tuple[str, int], teleport] = {} + self._cell_slot_map: Dict[str, Callable] = {} + self._teleport_slots_cache: Dict[Tuple[str, int], teleport] = {} def on_update_cell_slot(e): field = e.args["field"] @@ -79,7 +77,7 @@ def index_field(self) -> str: return self._props["options"].get("index", "id") @property - def data(self) -> list[dict]: + def data(self) -> List[dict]: """Get or set the data for the tabulator table.""" if "data" not in self._props["options"]: self._props["options"]["data"] = [] @@ -133,7 +131,7 @@ def run_table_method( """ return self.run_method("run_table_method", name, *args, timeout=timeout) - def set_columns(self, columns: list[dict]) -> None: + def set_columns(self, columns: List[dict]) -> None: """ To replace the current column definitions for all columns in a table. @@ -185,8 +183,8 @@ def _(): def add_column( self, definition: dict, - before: bool | None = None, - position: str | None = None, + before: Optional[bool] = None, + position: Optional[str] = None, ) -> None: """ Add a column to the table. @@ -216,10 +214,10 @@ def from_pandas( cls, df: "pd.DataFrame", *, - index: str | None = None, + index: Optional[str] = None, auto_index=False, - options: dict | None = None, - column_definition: Callable[[str], dict] | None = None, + options: Optional[dict] = None, + column_definition: Optional[Callable[[str], dict]] = None, ): """Create a table from a Pandas DataFrame. @@ -255,7 +253,7 @@ def is_special_dtype(dtype): '`df.columns = ["_".join(col) for col in df.columns.values]`.' ) - columns: list[dict] = [ + columns: List[dict] = [ {"title": col, "field": col} if column_definition is None else {"field": col, **column_definition(col)} @@ -355,7 +353,7 @@ def fn(row_number: int, row_index: int): return wrapper - def set_data(self, data: list[dict], *, timeout: float = 1) -> AwaitableResponse: + def set_data(self, data: List[dict], *, timeout: float = 1) -> AwaitableResponse: """set the data of the table. @see https://tabulator.info/docs/6.2/data#array @@ -368,7 +366,7 @@ def set_data(self, data: list[dict], *, timeout: float = 1) -> AwaitableResponse self._set_data_on_server(data) return self.run_table_method("setData", data, timeout=timeout) - def update_data(self, data: list[dict], *, timeout: float = 1) -> AwaitableResponse: + def update_data(self, data: List[dict], *, timeout: float = 1) -> AwaitableResponse: """update the data of the table. @see https://tabulator.info/docs/6.2/update#alter-update @@ -383,9 +381,9 @@ def update_data(self, data: list[dict], *, timeout: float = 1) -> AwaitableRespo def add_data( self, - data: list[dict], - at_top: bool | None = None, - index: int | str | None = None, + data: List[dict], + at_top: Optional[bool] = None, + index: Union[int, str, None] = None, *, timeout: float = 1, ) -> AwaitableResponse: @@ -410,7 +408,7 @@ def add_data( ) def update_or_add_data( - self, data: list[dict], *, timeout: float = 1 + self, data: List[dict], *, timeout: float = 1 ) -> AwaitableResponse: """update or add data to the table. If the data you are passing to the table contains a mix of existing rows to be updated and new rows to be added then you can call the updateOrAddData function. This will check each row object provided and update the existing row if available, or else create a new row with the data. @@ -446,9 +444,9 @@ def sync_data_to_client(self) -> AwaitableResponse: def _add_data_on_server( self, - data: list[dict], - at_top: bool | None = None, - index: int | str | None = None, + data: List[dict], + at_top: Optional[bool] = None, + index: Union[int, str, None] = None, ): at_top = ( at_top @@ -470,10 +468,10 @@ def _add_data_on_server( self._set_data_on_server(self.data[:row_index] + data + self.data[row_index:]) - def _set_data_on_server(self, data: list[dict]) -> None: + def _set_data_on_server(self, data: List[dict]) -> None: self._props["options"]["data"] = data[:] - def _update_data_on_server(self, data: list[dict]) -> None: + def _update_data_on_server(self, data: List[dict]) -> None: index_field = self.index_field update_dict = {record[index_field]: record for record in data} @@ -487,7 +485,7 @@ def _update_data_on_server(self, data: list[dict]) -> None: if update_record: row.update(update_record) - def _update_or_add_data_on_server(self, data: list[dict]) -> None: + def _update_or_add_data_on_server(self, data: List[dict]) -> None: index_field = self.index_field update_dict = {item[index_field]: item for item in data} @@ -500,9 +498,9 @@ def _update_or_add_data_on_server(self, data: list[dict]) -> None: def print( self, *, - row_range_lookup: T_Row_Range_Lookup | None = None, - style: bool | None = True, - config: dict | None = None, + row_range_lookup: Optional[T_Row_Range_Lookup] = None, + style: Optional[bool] = True, + config: Optional[dict] = None, ) -> AwaitableResponse: """A full page printing of the contents of the table without any other elements from the page. @@ -515,7 +513,7 @@ def print( return self.run_table_method("print", row_range_lookup, style, config) def delete_rows( - self, rows_indexes: list[Any], timeout: float = 1 + self, rows_indexes: List[Any], timeout: float = 1 ) -> AwaitableResponse: """Delete rows from the table by their index values. @@ -527,7 +525,7 @@ def delete_rows( self._delete_rows_on_server(rows_indexes) return self.run_table_method("deleteRow", rows_indexes, timeout=timeout) - def _delete_rows_on_server(self, rows_indexes: list[Any]) -> None: + def _delete_rows_on_server(self, rows_indexes: List[Any]) -> None: index_field = self.index_field set_indexes = set(rows_indexes) new_data = [ @@ -535,7 +533,7 @@ def _delete_rows_on_server(self, rows_indexes: list[Any]) -> None: ] self._set_data_on_server(data=new_data) - async def get_data(self, timeout: float = 1) -> list[dict[str, Any]]: + async def get_data(self, timeout: float = 1) -> List[Dict[str, Any]]: """Get the data from the table. Args: @@ -544,6 +542,6 @@ async def get_data(self, timeout: float = 1) -> list[dict[str, Any]]: """ return await self.run_table_method("getData", timeout=timeout) - async def get_selected_data(self, *, timeout: float = 1) -> list[dict]: + async def get_selected_data(self, *, timeout: float = 1) -> List[dict]: """Get the selected data from the table.""" return await self.run_table_method("getSelectedData", timeout=timeout) diff --git a/nicegui_tabulator/core/themes.py b/nicegui_tabulator/core/themes.py index 3130664..039cfe0 100644 --- a/nicegui_tabulator/core/themes.py +++ b/nicegui_tabulator/core/themes.py @@ -1,6 +1,5 @@ -from __future__ import annotations from pathlib import Path -from typing import Literal +from typing import Literal, Optional from nicegui import ui, app, Client _ASSETS_DIR = Path(__file__).parent / "libs" @@ -28,7 +27,7 @@ """ -def use_theme(theme_name: _T_THEME_NAME, shared: bool | None = None) -> None: +def use_theme(theme_name: _T_THEME_NAME, shared: Optional[bool] = None) -> None: """Use a tabulator theme. Args: diff --git a/nicegui_tabulator/core/types.py b/nicegui_tabulator/core/types.py index 56dd6fd..cf325b8 100644 --- a/nicegui_tabulator/core/types.py +++ b/nicegui_tabulator/core/types.py @@ -1,4 +1,3 @@ -from __future__ import annotations from dataclasses import dataclass, field as dc_field from typing import Any, Literal @@ -20,7 +19,7 @@ class CellSlotProps: """The position(starting from 1) of the row in the table data.""" row_index: int """The index of the row in the table data.""" - table: Tabulator = dc_field(init=True, repr=False) + table: "Tabulator" = dc_field(init=True, repr=False) """The parent Tabulator instance.""" def update_value(self, value: Any) -> None: diff --git a/nicegui_tabulator/core/utils.py b/nicegui_tabulator/core/utils.py index 49c606e..e4da7c5 100644 --- a/nicegui_tabulator/core/utils.py +++ b/nicegui_tabulator/core/utils.py @@ -1,6 +1,4 @@ -from __future__ import annotations - -from typing import Callable, Union +from typing import Callable, List, Union import asyncio import uuid @@ -12,7 +10,7 @@ class DeferredTask: def __init__(self): - self._tasks: list[_TTask] = [] + self._tasks: List[_TTask] = [] self.component_connected = False async def on_client_connect( From b7e34637ebed64a347e967a763514067ec3946d7 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 11 Mar 2026 15:14:36 +0000 Subject: [PATCH 11/13] Remove accidental pip artifact file Co-authored-by: AlePiccin <149101764+AlePiccin@users.noreply.github.com> --- =0.7.1 | 34 ---------------------------------- 1 file changed, 34 deletions(-) delete mode 100644 =0.7.1 diff --git a/=0.7.1 b/=0.7.1 deleted file mode 100644 index 3be9cd7..0000000 --- a/=0.7.1 +++ /dev/null @@ -1,34 +0,0 @@ -Defaulting to user installation because normal site-packages is not writeable -Collecting playwright==1.57.0 - Downloading playwright-1.57.0-py3-none-manylinux1_x86_64.whl.metadata (3.5 kB) -Collecting pytest-playwright - Downloading pytest_playwright-0.7.2-py3-none-any.whl.metadata (14 kB) -Collecting pyee<14,>=13 (from playwright==1.57.0) - Downloading pyee-13.0.1-py3-none-any.whl.metadata (3.0 kB) -Collecting greenlet<4.0.0,>=3.1.1 (from playwright==1.57.0) - Downloading greenlet-3.3.2-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl.metadata (3.7 kB) -Requirement already satisfied: pytest<10.0.0,>=6.2.4 in /home/runner/.local/lib/python3.12/site-packages (from pytest-playwright) (9.0.2) -Collecting pytest-base-url<3.0.0,>=1.0.0 (from pytest-playwright) - Downloading pytest_base_url-2.1.0-py3-none-any.whl.metadata (6.6 kB) -Collecting python-slugify<9.0.0,>=6.0.0 (from pytest-playwright) - Downloading python_slugify-8.0.4-py2.py3-none-any.whl.metadata (8.5 kB) -Requirement already satisfied: typing-extensions in /home/runner/.local/lib/python3.12/site-packages (from pyee<14,>=13->playwright==1.57.0) (4.15.0) -Requirement already satisfied: iniconfig>=1.0.1 in /home/runner/.local/lib/python3.12/site-packages (from pytest<10.0.0,>=6.2.4->pytest-playwright) (2.3.0) -Requirement already satisfied: packaging>=22 in /usr/lib/python3/dist-packages (from pytest<10.0.0,>=6.2.4->pytest-playwright) (24.0) -Requirement already satisfied: pluggy<2,>=1.5 in /home/runner/.local/lib/python3.12/site-packages (from pytest<10.0.0,>=6.2.4->pytest-playwright) (1.6.0) -Requirement already satisfied: pygments>=2.7.2 in /usr/lib/python3/dist-packages (from pytest<10.0.0,>=6.2.4->pytest-playwright) (2.17.2) -Requirement already satisfied: requests>=2.9 in /usr/lib/python3/dist-packages (from pytest-base-url<3.0.0,>=1.0.0->pytest-playwright) (2.31.0) -Collecting text-unidecode>=1.3 (from python-slugify<9.0.0,>=6.0.0->pytest-playwright) - Downloading text_unidecode-1.3-py2.py3-none-any.whl.metadata (2.4 kB) -Downloading playwright-1.57.0-py3-none-manylinux1_x86_64.whl (46.0 MB) - ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 46.0/46.0 MB 51.0 MB/s eta 0:00:00 -Downloading pytest_playwright-0.7.2-py3-none-any.whl (16 kB) -Downloading greenlet-3.3.2-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl (613 kB) - ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 613.9/613.9 kB 94.5 MB/s eta 0:00:00 -Downloading pyee-13.0.1-py3-none-any.whl (15 kB) -Downloading pytest_base_url-2.1.0-py3-none-any.whl (5.3 kB) -Downloading python_slugify-8.0.4-py2.py3-none-any.whl (10 kB) -Downloading text_unidecode-1.3-py2.py3-none-any.whl (78 kB) - ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 78.2/78.2 kB 31.0 MB/s eta 0:00:00 -Installing collected packages: text-unidecode, python-slugify, pyee, greenlet, pytest-base-url, playwright, pytest-playwright -Successfully installed greenlet-3.3.2 playwright-1.57.0 pyee-13.0.1 pytest-base-url-2.1.0 pytest-playwright-0.7.2 python-slugify-8.0.4 text-unidecode-1.3 From 19c5eaf866e5baf9a49793534a6521e17ce9f8d8 Mon Sep 17 00:00:00 2001 From: Alexandre Piccin <149101764+AlePiccin@users.noreply.github.com> Date: Thu, 30 Apr 2026 11:41:08 -0300 Subject: [PATCH 12/13] Update tabulator.py add Data setter --- nicegui_tabulator/core/tabulator.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/nicegui_tabulator/core/tabulator.py b/nicegui_tabulator/core/tabulator.py index 9c563e6..8d02875 100644 --- a/nicegui_tabulator/core/tabulator.py +++ b/nicegui_tabulator/core/tabulator.py @@ -82,7 +82,13 @@ def data(self) -> List[dict]: if "data" not in self._props["options"]: self._props["options"]["data"] = [] return self._props["options"]["data"] - + + @data.setter + def data_setter(self, data: List[Dict]): + """Set the data for the tabulator table.""" + self._props["options"]["data"] = data + return self + def delete(self) -> None: for tp in self._teleport_slots_cache.values(): tp.delete() From 5c8cbe53b92295d5c4a161ac4b0516f807ff284b Mon Sep 17 00:00:00 2001 From: Alexandre Piccin <149101764+AlePiccin@users.noreply.github.com> Date: Thu, 30 Apr 2026 11:43:38 -0300 Subject: [PATCH 13/13] Update tabulator.py minor corrections --- nicegui_tabulator/core/tabulator.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/nicegui_tabulator/core/tabulator.py b/nicegui_tabulator/core/tabulator.py index 8d02875..b82e2ea 100644 --- a/nicegui_tabulator/core/tabulator.py +++ b/nicegui_tabulator/core/tabulator.py @@ -84,10 +84,9 @@ def data(self) -> List[dict]: return self._props["options"]["data"] @data.setter - def data_setter(self, data: List[Dict]): + def data(self, data: List[Dict]): """Set the data for the tabulator table.""" self._props["options"]["data"] = data - return self def delete(self) -> None: for tp in self._teleport_slots_cache.values():