From de27e1d6dfd1b41e0dd846dd80a21989d08195e9 Mon Sep 17 00:00:00 2001 From: David Vegh Date: Tue, 1 Aug 2023 16:25:45 +0200 Subject: [PATCH 01/15] Extract pandas df converter into separate module --- src/ipyvizzu/animation.py | 170 +++++++++--------- .../data/converters/pandas_converter.py | 141 +++++++++++++++ src/ipyvizzu/data/infer_type.py | 22 +++ 3 files changed, 253 insertions(+), 80 deletions(-) create mode 100644 src/ipyvizzu/data/converters/pandas_converter.py create mode 100644 src/ipyvizzu/data/infer_type.py diff --git a/src/ipyvizzu/animation.py b/src/ipyvizzu/animation.py index 1440c749..032b1f1b 100644 --- a/src/ipyvizzu/animation.py +++ b/src/ipyvizzu/animation.py @@ -1,15 +1,12 @@ """A module for working with chart animations.""" import abc -from enum import Enum from os import PathLike import json -from typing import Optional, Union, List, Any, Tuple +from typing import Optional, Union, List, Dict, Any, Tuple import jsonschema # type: ignore -import pandas as pd # type: ignore -from pandas.api.types import is_numeric_dtype # type: ignore - +from ipyvizzu.data.converters.pandas_converter import PandasDataFrameConverter from ipyvizzu.json import RawJavaScript, RawJavaScriptEncoder from ipyvizzu.schema import DATA_SCHEMA @@ -59,16 +56,6 @@ def build(self) -> dict: return self -class InferType(Enum): - """An enum class for storing data infer types.""" - - DIMENSION = "dimension" - """An enum key-value for storing dimension infer type.""" - - MEASURE = "measure" - """An enum key-value for storing measure infer type.""" - - class Data(dict, AbstractAnimation): """ A class for representing data animation. @@ -211,6 +198,18 @@ def add_series(self, name: str, values: Optional[list] = None, **kwargs) -> None self._add_named_value("series", name, values, **kwargs) + def add_series_list(self, series: List[Dict[str, Union[str, List[Any]]]]) -> None: + """ + A method for adding list of series to an existing + [Data][ipyvizzu.animation.Data] class instance. + + Args: + series: List of series. + """ + + if series: + self.setdefault("series", []).extend(series) + def add_dimension(self, name: str, values: Optional[list] = None, **kwargs) -> None: """ A method for adding a dimension to an existing @@ -255,24 +254,26 @@ def add_measure(self, name: str, values: Optional[list] = None, **kwargs) -> Non self._add_named_value("measures", name, values, **kwargs) - def add_data_frame( + def add_df( self, - data_frame: Union[pd.DataFrame, pd.Series], + df: Union["pd.DataFrame", "pd.Series"], # type: ignore default_measure_value: Optional[Any] = 0, default_dimension_value: Optional[Any] = "", + include_index: Optional[str] = None, ) -> None: """ - A method for adding data frame to an existing + Add a `pandas` `DataFrame` or `Series` to an existing [Data][ipyvizzu.animation.Data] class instance. Args: - data_frame: The pandas data frame object. - default_measure_value: The default measure value to fill the empty values. - default_dimension_value: The default dimension value to fill the empty values. - - Raises: - TypeError: If `data_frame` is not instance of [pd.DataFrame][pandas.DataFrame] - or [pd.Series][pandas.Series]. + df: + The `pandas` `DataFrame` or `Series` to add. + default_measure_value: + The default measure value to fill empty values. Defaults to 0. + default_dimension_value: + The default dimension value to fill empty values. Defaults to an empty string. + include_index: + Add the data frame's index as a column with the given name. Defaults to `None`. Example: Adding a data frame to a [Data][ipyvizzu.animation.Data] class instance: @@ -285,81 +286,90 @@ def add_data_frame( } ) data = Data() - data.add_data_frame(df) + data.add_df(df) """ - if not isinstance(data_frame, type(None)): - if isinstance(data_frame, pd.Series): - data_frame = pd.DataFrame(data_frame) - if not isinstance(data_frame, pd.DataFrame): - raise TypeError( - "data_frame must be instance of pandas.DataFrame or pandas.Series" - ) - for name in data_frame.columns: - values = [] - if is_numeric_dtype(data_frame[name].dtype): - infer_type = InferType.MEASURE - values = ( - data_frame[name] - .fillna(default_measure_value) - .astype(float) - .values.tolist() - ) - else: - infer_type = InferType.DIMENSION - values = ( - data_frame[name] - .fillna(default_dimension_value) - .astype(str) - .values.tolist() - ) - self.add_series( - name, - values, - type=infer_type.value, - ) + converter = PandasDataFrameConverter( + df, default_measure_value, default_dimension_value, include_index + ) + series_list = converter.get_series_list_from_columns() + self.add_series_list(series_list) - def add_data_frame_index( + def add_data_frame( self, - data_frame: Union[pd.DataFrame, pd.Series], - name: Optional[str], + data_frame: Union["pd.DataFrame", "pd.Series"], # type: ignore + default_measure_value: Optional[Any] = 0, + default_dimension_value: Optional[Any] = "", ) -> None: """ - A method for adding data frame's index to an existing + [Deprecated] Add a `pandas` `DataFrame` or `Series` to an existing [Data][ipyvizzu.animation.Data] class instance. + This function is kept for backward compatibility + and calls the `add_df` method with the same arguments. + Args: - data_frame: The pandas data frame object. - name: The name of the index series. + data_frame: + The `pandas` `DataFrame` or `Series` to add. + default_measure_value: + The default measure value to fill empty values. Defaults to 0. + default_dimension_value: + The default dimension value to fill empty values. Defaults to an empty string. + """ + self.add_df(data_frame, default_measure_value, default_dimension_value) - Raises: - TypeError: If `data_frame` is not instance of [pd.DataFrame][pandas.DataFrame] - or [pd.Series][pandas.Series]. + def add_df_index( + self, + df: Union["pd.DataFrame", "pd.Series"], # type: ignore + name: str, + ) -> None: + """ + Add the index of a `pandas` `DataFrame` as a series to an existing + [Data][ipyvizzu.animation.Data] class instance. + + Args: + df: + The `pandas` `DataFrame` or `Series` from which to extract the index. + name: + The name of the index series. Example: - Adding a data frame's index to a [Data][ipyvizzu.animation.Data] class instance: + Adding a data frame's index to a + [Data][ipyvizzu.animation.Data] class instance: df = pd.DataFrame( {"Popularity": [114, 96]}, index=["x", "y"] ) data = Data() - data.add_data_frame_index(df, "DataFrameIndex") - data.add_data_frame(df) + data.add_df_index(df, "DataFrameIndex") + data.add_df(df) """ - if data_frame is not None: - if isinstance(data_frame, pd.Series): - data_frame = pd.DataFrame(data_frame) - if not isinstance(data_frame, pd.DataFrame): - raise TypeError( - "data_frame must be instance of pandas.DataFrame or pandas.Series" - ) - self.add_series( - str(name), - [str(i) for i in data_frame.index], - type=InferType.DIMENSION.value, - ) + converter = PandasDataFrameConverter(df, include_index=name) + index_series = converter.get_series_from_index() + if index_series: + self.add_series(**index_series) # type: ignore + + def add_data_frame_index( + self, + data_frame: Union["pd.DataFrame", "pd.Series"], # type: ignore + name: str, + ) -> None: + """ + [Deprecated] Add the index of a `pandas` `DataFrame` as a series to an existing + [Data][ipyvizzu.animation.Data] class instance. + + This function is kept for backward compatibility + and calls the `add_df_index` method with the same arguments. + + Args: + data_frame: + The `pandas` `DataFrame` or `Series` from which to extract the index. + name: + The name of the index series. + """ + self.add_df_index(data_frame, name) def _add_named_value( self, dest: str, name: str, values: Optional[list] = None, **kwargs diff --git a/src/ipyvizzu/data/converters/pandas_converter.py b/src/ipyvizzu/data/converters/pandas_converter.py new file mode 100644 index 00000000..929a3713 --- /dev/null +++ b/src/ipyvizzu/data/converters/pandas_converter.py @@ -0,0 +1,141 @@ +""" +This module provides the `PandasDataFrameConverter` class, +which allows converting a `pandas` `DataFrame` or `Series` +into a list of dictionaries representing series. +""" + +from typing import Optional, Any, List, Dict, Union, Tuple + +from ipyvizzu.data.infer_type import InferType + + +class PandasDataFrameConverter: + """ + Converts a `pandas` `DataFrame` or `Series` into a list of dictionaries representing series. + Each dictionary contains information about the series `name`, `values` and `type`. + + Parameters: + df: The `pandas` `DataFrame` or `Series` to convert. + default_measure_value: + Default value to use for missing measure values. Defaults to 0. + default_dimension_value: + Default value to use for missing dimension values. Defaults to an empty string. + include_index: + Name for the index column to include as a series. + If provided, the index column will be added. Defaults to None. + + Example: + Get series list from `DataFrame` columns: + + converter = PandasDataFrameConverter(df) + series_list = converter.get_series_list_from_columns() + """ + + def __init__( + self, + df: Union["pd.DataFrame", "pd.Series"], # type: ignore + default_measure_value: Optional[Any] = 0, + default_dimension_value: Optional[Any] = "", + include_index: Optional[str] = None, + ) -> None: + self._df = self._get_df(df) + self._default_measure_value = default_measure_value + self._default_dimension_value = default_dimension_value + self._include_index = include_index + + def _get_df(self, df: Union["pd.DataFrame", "pd.Series"]) -> "pd.DataFrame": # type: ignore + try: + import pandas as pd # pylint: disable=import-outside-toplevel + + if isinstance(df, pd.DataFrame): + return df + if isinstance(df, pd.Series): + return pd.DataFrame(df) + if df is None: + return pd.DataFrame() + raise TypeError( + "df must be an instance of pandas.DataFrame or pandas.Series" + ) + except ImportError as error: + raise ImportError( + "pandas is not available. Please install pandas to use this feature." + ) from error + + def get_series_list_from_columns(self) -> List[Dict[str, Union[str, List[Any]]]]: + """ + Convert the `DataFrame` columns to a list of dictionaries representing series. + + Returns: + A list of dictionaries representing series, + where each dictionary has `name`, `values` and `type` keys. + """ + + series_list = [] + for name in self._df.columns: + series_list.append(self._get_series_from_column(name)) + index_series = self.get_series_from_index() + if index_series: + series_list.append(index_series) + return series_list + + def get_series_from_index(self) -> Optional[Dict[str, Union[str, List[Any]]]]: + """ + Convert the `DataFrame` index to a dictionary representing a series, + if `include_index` is provided. + + Returns: + A dictionary representing the index series with `name`, `values` and `type` keys. + Returns `None` if `include_index` is not provided. + """ + + if not self._include_index: + return None + name = self._include_index + values, infer_type = self._get_column_data(self._df.index) + return self._convert_to_series(name, values, infer_type) + + def _get_series_from_column( + self, column_name: str + ) -> Dict[str, Union[str, List[Any]]]: + column = self._df[column_name] + values, infer_type = self._get_column_data(column) + return self._convert_to_series(column_name, values, infer_type) + + def _get_column_data(self, column: "pd.Series") -> Tuple[List[Any], InferType]: # type: ignore + try: + from pandas.api.types import ( # pylint: disable=import-outside-toplevel + is_numeric_dtype, + ) + + if is_numeric_dtype(column.dtype): + return self._get_measure_column_data(column) + return self._get_dimension_column_data(column) + except ImportError as error: + raise ImportError( + "pandas is not available. Please install pandas to use this feature." + ) from error + + def _get_measure_column_data( + self, column: "pd.Series" # type: ignore + ) -> Tuple[List[Any], InferType]: + return ( + column.fillna(self._default_measure_value).astype(float).values.tolist(), + InferType.MEASURE, + ) + + def _get_dimension_column_data( + self, column: "pd.Series" # type: ignore + ) -> Tuple[List[Any], InferType]: + return ( + column.fillna(self._default_dimension_value).astype(str).values.tolist(), + InferType.DIMENSION, + ) + + def _convert_to_series( + self, name: str, values: List[Any], infer_type: InferType + ) -> Dict[str, Union[str, List[Any]]]: + return { + "name": name, + "values": values, + "type": infer_type.value, + } diff --git a/src/ipyvizzu/data/infer_type.py b/src/ipyvizzu/data/infer_type.py new file mode 100644 index 00000000..371923a9 --- /dev/null +++ b/src/ipyvizzu/data/infer_type.py @@ -0,0 +1,22 @@ +""" +This module provides the `InferType` class, which stores data infer types. +""" + +from enum import Enum + + +class InferType(Enum): + """ + An enum class for storing data infer types. + + Attributes: + DIMENSION: An enum key-value for storing dimension infer type. + Dimensions are categorical series that can contain strings and numbers, + but both will be treated as strings. + + MEASURE: An enum key-value for storing measure infer type. + Measures can only be numerical. + """ + + DIMENSION = "dimension" + MEASURE = "measure" From 159ba3749d8a9ced7213dbdda316be8facd1efea Mon Sep 17 00:00:00 2001 From: David Vegh Date: Tue, 1 Aug 2023 17:02:23 +0200 Subject: [PATCH 02/15] Replace add_data_frame method to add_df in the doc --- README.md | 2 +- community/color-blindness_theme.ipynb | 4 +- community/dark_theme.ipynb | 4 +- docs/environments/bi/mode.md | 2 +- docs/environments/ide/pycharm.md | 2 +- docs/environments/ide/vscode.md | 2 +- docs/environments/notebook/colab.md | 2 +- docs/environments/notebook/databricks.md | 2 +- docs/environments/notebook/datacamp.md | 2 +- docs/environments/notebook/deepnote.md | 2 +- docs/environments/notebook/jupyterlab.md | 2 +- docs/environments/notebook/jupyterlite.md | 2 +- docs/environments/notebook/jupyternotebook.md | 2 +- docs/environments/notebook/kaggle.md | 2 +- docs/environments/notebook/noteable.md | 2 +- docs/environments/platform/flask.md | 2 +- docs/environments/platform/mercury.md | 2 +- docs/environments/platform/panel.md | 2 +- docs/environments/platform/streamlit.md | 2 +- docs/environments/platform/voila.md | 2 +- docs/showcases/music.md | 2 +- docs/showcases/musicformats.md | 2 +- docs/showcases/nadal.md | 2 +- docs/showcases/sales.md | 2 +- docs/showcases/titanic.md | 2 +- docs/tutorial/align_range.md | 2 +- docs/tutorial/animation_control_keyframes.md | 2 +- docs/tutorial/animation_options.md | 2 +- docs/tutorial/axes_title_tooltip.md | 2 +- docs/tutorial/changing_dimensions.md | 2 +- docs/tutorial/channels_legend.md | 2 +- docs/tutorial/chart_layout.md | 2 +- docs/tutorial/chart_presets.md | 2 +- docs/tutorial/color_palette_fonts.md | 2 +- docs/tutorial/data.md | 43 +++++++++++++------ docs/tutorial/events.md | 2 +- docs/tutorial/filter_add_new_records.md | 2 +- docs/tutorial/geometry.md | 2 +- docs/tutorial/group_stack.md | 2 +- docs/tutorial/orientation_split_polar.md | 2 +- docs/tutorial/shorthands_store.md | 2 +- docs/tutorial/sorting.md | 2 +- .../without_coordinates_noop_channel.md | 2 +- src/ipyvizzu/data/infer_type.py | 4 +- src/ipyvizzu/integrations/fugue.py | 6 +-- .../assets/{data_frame_in.json => df_in.json} | 0 tests/assets/{data_frame_na.csv => df_na.csv} | 0 .../{data_frame_out.json => df_out.json} | 0 tests/assets/fugue_preset.txt | 2 +- tests/assets/fugue_timeline.txt | 2 +- tests/test_fugue.py | 3 +- tools/docs/examples/mjs2md.mjs | 2 +- 52 files changed, 82 insertions(+), 68 deletions(-) rename tests/assets/{data_frame_in.json => df_in.json} (100%) rename tests/assets/{data_frame_na.csv => df_na.csv} (100%) rename tests/assets/{data_frame_out.json => df_out.json} (100%) diff --git a/README.md b/README.md index c6d9f6b8..d2a8c660 100644 --- a/README.md +++ b/README.md @@ -75,7 +75,7 @@ df = pd.read_csv( "https://ipyvizzu.vizzuhq.com/latest/showcases/titanic/titanic.csv" ) data = Data() -data.add_data_frame(df) +data.add_df(df) chart = Chart(width="640px", height="360px") diff --git a/community/color-blindness_theme.ipynb b/community/color-blindness_theme.ipynb index 74822293..eeaa1c10 100644 --- a/community/color-blindness_theme.ipynb +++ b/community/color-blindness_theme.ipynb @@ -33,12 +33,12 @@ "\n", "# Create data object, read csv to data frame and add data frame to data object.\n", "data = Data()\n", - "data_frame = pd.read_csv(\n", + "df = pd.read_csv(\n", " \"https://raw.githubusercontent.com/vizzuhq/ipyvizzu/\"\n", " + \"gh-pages/docs/data/chart_types_eu.csv\",\n", " dtype={\"Year\": str, \"Timeseries\": str},\n", ")\n", - "data.add_data_frame(data_frame)" + "data.add_df(df)" ] }, { diff --git a/community/dark_theme.ipynb b/community/dark_theme.ipynb index c47e0808..04ec6057 100644 --- a/community/dark_theme.ipynb +++ b/community/dark_theme.ipynb @@ -21,12 +21,12 @@ "\n", "# Create data object, read csv to data frame and add data frame to data object.\n", "data = Data()\n", - "data_frame = pd.read_csv(\n", + "df = pd.read_csv(\n", " \"https://raw.githubusercontent.com/vizzuhq/ipyvizzu/\"\n", " + \"gh-pages/docs/data/chart_types_eu.csv\",\n", " dtype={\"Year\": str, \"Timeseries\": str},\n", ")\n", - "data.add_data_frame(data_frame)" + "data.add_df(df)" ] }, { diff --git a/docs/environments/bi/mode.md b/docs/environments/bi/mode.md index 352e780b..d9453ca6 100644 --- a/docs/environments/bi/mode.md +++ b/docs/environments/bi/mode.md @@ -62,7 +62,7 @@ data = Data() df = pd.read_csv( "https://ipyvizzu.vizzuhq.com/latest/showcases/titanic/titanic.csv" ) -data.add_data_frame(df) +data.add_df(df) chart.animate(data) diff --git a/docs/environments/ide/pycharm.md b/docs/environments/ide/pycharm.md index 68922d6d..b671c157 100644 --- a/docs/environments/ide/pycharm.md +++ b/docs/environments/ide/pycharm.md @@ -68,7 +68,7 @@ data = Data() df = pd.read_csv( "https://ipyvizzu.vizzuhq.com/latest/showcases/titanic/titanic.csv" ) -data.add_data_frame(df) +data.add_df(df) chart.animate(data) diff --git a/docs/environments/ide/vscode.md b/docs/environments/ide/vscode.md index d3558cc7..2dff16cb 100644 --- a/docs/environments/ide/vscode.md +++ b/docs/environments/ide/vscode.md @@ -68,7 +68,7 @@ data = Data() df = pd.read_csv( "https://ipyvizzu.vizzuhq.com/latest/showcases/titanic/titanic.csv" ) -data.add_data_frame(df) +data.add_df(df) chart.animate(data) diff --git a/docs/environments/notebook/colab.md b/docs/environments/notebook/colab.md index e65ce38e..86b3cc6b 100644 --- a/docs/environments/notebook/colab.md +++ b/docs/environments/notebook/colab.md @@ -66,7 +66,7 @@ data = Data() df = pd.read_csv( "https://ipyvizzu.vizzuhq.com/latest/showcases/titanic/titanic.csv" ) -data.add_data_frame(df) +data.add_df(df) chart.animate(data) diff --git a/docs/environments/notebook/databricks.md b/docs/environments/notebook/databricks.md index d71b9723..91d2cfdc 100644 --- a/docs/environments/notebook/databricks.md +++ b/docs/environments/notebook/databricks.md @@ -66,7 +66,7 @@ data = Data() df = pd.read_csv( "https://ipyvizzu.vizzuhq.com/latest/showcases/titanic/titanic.csv" ) -data.add_data_frame(df) +data.add_df(df) chart.animate(data) diff --git a/docs/environments/notebook/datacamp.md b/docs/environments/notebook/datacamp.md index 04d62d69..13503ae5 100644 --- a/docs/environments/notebook/datacamp.md +++ b/docs/environments/notebook/datacamp.md @@ -67,7 +67,7 @@ data = Data() df = pd.read_csv( "https://ipyvizzu.vizzuhq.com/latest/showcases/titanic/titanic.csv" ) -data.add_data_frame(df) +data.add_df(df) chart.animate(data) diff --git a/docs/environments/notebook/deepnote.md b/docs/environments/notebook/deepnote.md index 9995519e..1f002f83 100644 --- a/docs/environments/notebook/deepnote.md +++ b/docs/environments/notebook/deepnote.md @@ -66,7 +66,7 @@ data = Data() df = pd.read_csv( "https://ipyvizzu.vizzuhq.com/latest/showcases/titanic/titanic.csv" ) -data.add_data_frame(df) +data.add_df(df) chart.animate(data) diff --git a/docs/environments/notebook/jupyterlab.md b/docs/environments/notebook/jupyterlab.md index 98309136..ba6fe9d8 100644 --- a/docs/environments/notebook/jupyterlab.md +++ b/docs/environments/notebook/jupyterlab.md @@ -71,7 +71,7 @@ data = Data() df = pd.read_csv( "https://ipyvizzu.vizzuhq.com/latest/showcases/titanic/titanic.csv" ) -data.add_data_frame(df) +data.add_df(df) chart.animate(data) diff --git a/docs/environments/notebook/jupyterlite.md b/docs/environments/notebook/jupyterlite.md index 775e7608..6886d47f 100644 --- a/docs/environments/notebook/jupyterlite.md +++ b/docs/environments/notebook/jupyterlite.md @@ -103,7 +103,7 @@ async def get_contents(path): data = Data() data_csv = await get_contents("titanic.csv") df = pd.read_csv(StringIO(data_csv["content"])) -data.add_data_frame(df) +data.add_df(df) chart.animate(data) diff --git a/docs/environments/notebook/jupyternotebook.md b/docs/environments/notebook/jupyternotebook.md index 11ded331..92c2e04b 100644 --- a/docs/environments/notebook/jupyternotebook.md +++ b/docs/environments/notebook/jupyternotebook.md @@ -71,7 +71,7 @@ data = Data() df = pd.read_csv( "https://ipyvizzu.vizzuhq.com/latest/showcases/titanic/titanic.csv" ) -data.add_data_frame(df) +data.add_df(df) chart.animate(data) diff --git a/docs/environments/notebook/kaggle.md b/docs/environments/notebook/kaggle.md index f3bedb71..fce69cce 100644 --- a/docs/environments/notebook/kaggle.md +++ b/docs/environments/notebook/kaggle.md @@ -69,7 +69,7 @@ data = Data() df = pd.read_csv( "https://ipyvizzu.vizzuhq.com/latest/showcases/titanic/titanic.csv" ) -data.add_data_frame(df) +data.add_df(df) chart.animate(data) diff --git a/docs/environments/notebook/noteable.md b/docs/environments/notebook/noteable.md index f5770bdd..d5b9715e 100644 --- a/docs/environments/notebook/noteable.md +++ b/docs/environments/notebook/noteable.md @@ -65,7 +65,7 @@ data = Data() df = pd.read_csv( "https://ipyvizzu.vizzuhq.com/latest/showcases/titanic/titanic.csv" ) -data.add_data_frame(df) +data.add_df(df) chart.animate(data) diff --git a/docs/environments/platform/flask.md b/docs/environments/platform/flask.md index d77180a0..410a3350 100644 --- a/docs/environments/platform/flask.md +++ b/docs/environments/platform/flask.md @@ -66,7 +66,7 @@ data = Data() df = pd.read_csv( "https://ipyvizzu.vizzuhq.com/latest/showcases/titanic/titanic.csv" ) -data.add_data_frame(df) +data.add_df(df) chart.animate(data) diff --git a/docs/environments/platform/mercury.md b/docs/environments/platform/mercury.md index 1c71bb4d..23e9c05e 100644 --- a/docs/environments/platform/mercury.md +++ b/docs/environments/platform/mercury.md @@ -86,7 +86,7 @@ data = Data() df = pd.read_csv( "https://ipyvizzu.vizzuhq.com/latest/showcases/titanic/titanic.csv" ) -data.add_data_frame(df) +data.add_df(df) chart.animate(data) diff --git a/docs/environments/platform/panel.md b/docs/environments/platform/panel.md index 665ad95b..34bb40f7 100644 --- a/docs/environments/platform/panel.md +++ b/docs/environments/platform/panel.md @@ -63,7 +63,7 @@ def create_chart(): df = pd.read_csv( "https://ipyvizzu.vizzuhq.com/latest/showcases/titanic/titanic.csv" ) - data.add_data_frame(df) + data.add_df(df) chart.animate(data) diff --git a/docs/environments/platform/streamlit.md b/docs/environments/platform/streamlit.md index 4497db1a..67821d5b 100644 --- a/docs/environments/platform/streamlit.md +++ b/docs/environments/platform/streamlit.md @@ -68,7 +68,7 @@ def create_chart(): df = pd.read_csv( "https://ipyvizzu.vizzuhq.com/latest/showcases/titanic/titanic.csv" ) - data.add_data_frame(df) + data.add_df(df) chart.animate(data) diff --git a/docs/environments/platform/voila.md b/docs/environments/platform/voila.md index 4d658c1f..89a1f6d0 100644 --- a/docs/environments/platform/voila.md +++ b/docs/environments/platform/voila.md @@ -71,7 +71,7 @@ data = Data() df = pd.read_csv( "https://ipyvizzu.vizzuhq.com/latest/showcases/titanic/titanic.csv" ) -data.add_data_frame(df) +data.add_df(df) chart.animate(data) diff --git a/docs/showcases/music.md b/docs/showcases/music.md index 252e80df..f653774b 100644 --- a/docs/showcases/music.md +++ b/docs/showcases/music.md @@ -19,7 +19,7 @@ df = pd.read_csv( dtype={"Year": str}, ) data = Data() -data.add_data_frame(df) +data.add_df(df) chart = Chart() diff --git a/docs/showcases/musicformats.md b/docs/showcases/musicformats.md index b7970871..7b8f97df 100644 --- a/docs/showcases/musicformats.md +++ b/docs/showcases/musicformats.md @@ -19,7 +19,7 @@ df = pd.read_csv( dtype={"Year": str}, ) data = Data() -data.add_data_frame(df) +data.add_df(df) config = { "channels": { diff --git a/docs/showcases/nadal.md b/docs/showcases/nadal.md index 66ac9c8e..fefa32c7 100644 --- a/docs/showcases/nadal.md +++ b/docs/showcases/nadal.md @@ -27,7 +27,7 @@ df = pd.read_csv( }, ) data = Data() -data.add_data_frame(df) +data.add_df(df) chart = Chart(display=DisplayTarget.END) chart.animate(data) diff --git a/docs/showcases/sales.md b/docs/showcases/sales.md index 870bd719..a75db156 100644 --- a/docs/showcases/sales.md +++ b/docs/showcases/sales.md @@ -18,7 +18,7 @@ df = pd.read_csv( "https://ipyvizzu.vizzuhq.com/latest/showcases/sales/sales.csv" ) data = Data() -data.add_data_frame(df) +data.add_df(df) chart = Chart() diff --git a/docs/showcases/titanic.md b/docs/showcases/titanic.md index c9bdfb11..65e0b6eb 100644 --- a/docs/showcases/titanic.md +++ b/docs/showcases/titanic.md @@ -18,7 +18,7 @@ df = pd.read_csv( "https://ipyvizzu.vizzuhq.com/latest/showcases/titanic/titanic.csv" ) data = Data() -data.add_data_frame(df) +data.add_df(df) chart = Chart() diff --git a/docs/tutorial/align_range.md b/docs/tutorial/align_range.md index 73f4e298..f62ce126 100644 --- a/docs/tutorial/align_range.md +++ b/docs/tutorial/align_range.md @@ -30,7 +30,7 @@ whereas on a bar chart, horizontally. "https://ipyvizzu.vizzuhq.com/latest/assets/data/music_data.csv" ) data = Data() - data.add_data_frame(df) + data.add_df(df) chart = Chart() diff --git a/docs/tutorial/animation_control_keyframes.md b/docs/tutorial/animation_control_keyframes.md index c89dc41a..ddaeca4d 100644 --- a/docs/tutorial/animation_control_keyframes.md +++ b/docs/tutorial/animation_control_keyframes.md @@ -20,7 +20,7 @@ In this step, we seek forward to `50%` of progress after the animation starts. "https://ipyvizzu.vizzuhq.com/latest/assets/data/music_data.csv" ) data = Data() - data.add_data_frame(df) + data.add_df(df) chart = Chart() diff --git a/docs/tutorial/animation_options.md b/docs/tutorial/animation_options.md index 191d4028..3f7cb89b 100644 --- a/docs/tutorial/animation_options.md +++ b/docs/tutorial/animation_options.md @@ -23,7 +23,7 @@ the default animation options. "https://ipyvizzu.vizzuhq.com/latest/assets/data/music_data.csv" ) data = Data() - data.add_data_frame(df) + data.add_df(df) chart = Chart() diff --git a/docs/tutorial/axes_title_tooltip.md b/docs/tutorial/axes_title_tooltip.md index 4ac9b5ba..ed626759 100644 --- a/docs/tutorial/axes_title_tooltip.md +++ b/docs/tutorial/axes_title_tooltip.md @@ -24,7 +24,7 @@ the measure (`Popularity`) to the y-axis using the set property. "https://ipyvizzu.vizzuhq.com/latest/assets/data/music_data.csv" ) data = Data() - data.add_data_frame(df) + data.add_df(df) chart = Chart() diff --git a/docs/tutorial/changing_dimensions.md b/docs/tutorial/changing_dimensions.md index 60f08972..26f70bc8 100644 --- a/docs/tutorial/changing_dimensions.md +++ b/docs/tutorial/changing_dimensions.md @@ -24,7 +24,7 @@ the elements. "https://ipyvizzu.vizzuhq.com/latest/assets/data/music_data.csv" ) data = Data() - data.add_data_frame(df) + data.add_df(df) chart = Chart() diff --git a/docs/tutorial/channels_legend.md b/docs/tutorial/channels_legend.md index 37ec10f1..0b137622 100644 --- a/docs/tutorial/channels_legend.md +++ b/docs/tutorial/channels_legend.md @@ -28,7 +28,7 @@ you can set them differently with the `Style` object introduced in the "https://ipyvizzu.vizzuhq.com/latest/assets/data/music_data.csv" ) data = Data() - data.add_data_frame(df) + data.add_df(df) chart = Chart() diff --git a/docs/tutorial/chart_layout.md b/docs/tutorial/chart_layout.md index 68dde6ac..591b3943 100644 --- a/docs/tutorial/chart_layout.md +++ b/docs/tutorial/chart_layout.md @@ -27,7 +27,7 @@ are aligned. "https://ipyvizzu.vizzuhq.com/latest/assets/data/music_data.csv" ) data = Data() - data.add_data_frame(df) + data.add_df(df) chart = Chart() diff --git a/docs/tutorial/chart_presets.md b/docs/tutorial/chart_presets.md index a53cd15a..5ce102e8 100644 --- a/docs/tutorial/chart_presets.md +++ b/docs/tutorial/chart_presets.md @@ -28,7 +28,7 @@ using its preset. "https://ipyvizzu.vizzuhq.com/latest/assets/data/music_data.csv" ) data = Data() - data.add_data_frame(df) + data.add_df(df) chart = Chart() diff --git a/docs/tutorial/color_palette_fonts.md b/docs/tutorial/color_palette_fonts.md index dc0394fa..3d1644fd 100644 --- a/docs/tutorial/color_palette_fonts.md +++ b/docs/tutorial/color_palette_fonts.md @@ -32,7 +32,7 @@ you should add "https://ipyvizzu.vizzuhq.com/latest/assets/data/music_data.csv" ) data = Data() - data.add_data_frame(df) + data.add_df(df) chart = Chart() diff --git a/docs/tutorial/data.md b/docs/tutorial/data.md index eb0219d0..04738e34 100644 --- a/docs/tutorial/data.md +++ b/docs/tutorial/data.md @@ -49,7 +49,7 @@ There are multiple ways you can add data to `ipyvizzu`. ### Using `pandas` DataFrame Use -[`add_data_frame`](../reference/ipyvizzu/animation.md#ipyvizzu.animation.Data.add_data_frame) +[`add_df`](../reference/ipyvizzu/animation.md#ipyvizzu.animation.Data.add_df) method for adding data frame to [`Data`](../reference/ipyvizzu/animation.md#ipyvizzu.animation.Data). @@ -105,7 +105,7 @@ data = { df = pd.DataFrame(data) data = Data() -data.add_data_frame(df) +data.add_df(df) ``` !!! info @@ -113,9 +113,24 @@ data.add_data_frame(df) and not numeric (dimension). A column's `dtype` specifies that the column is handled as a measure or as a dimension. -It is also possible to add data frame index to -[`Data`](../reference/ipyvizzu/animation.md#ipyvizzu.animation.Data) with the -[`add_data_frame_index`](../reference/ipyvizzu/animation.md#ipyvizzu.animation.Data.add_data_frame_index) +It is also possible to add the data frame's index as a series column while +adding the data frame + +```python +import pandas as pd +from ipyvizzu import Data + + +df = pd.DataFrame( + {"Popularity": [114, 96, 78]}, index=["x", "y", "z"] +) + +data = Data() +data.add_df(df, include_index="IndexColumnName") +``` + +or later with the +[`add_df_index`](../reference/ipyvizzu/animation.md#ipyvizzu.animation.Data.add_df_index) method. ```python @@ -128,8 +143,8 @@ df = pd.DataFrame( ) data = Data() -data.add_data_frame(df) -data.add_data_frame_index(df, "DataFrameIndex") +data.add_df(df) +data.add_df_index(df, name="IndexColumnName") ``` #### Using csv @@ -146,7 +161,7 @@ df = pd.read_csv( ) data = Data() -data.add_data_frame(df) +data.add_df(df) ``` #### Using Excel spreadsheet @@ -163,7 +178,7 @@ df = pd.read_excel( ) data = Data() -data.add_data_frame(df) +data.add_df(df) ``` #### Using Google Sheets @@ -181,7 +196,7 @@ df = pd.read_csv( ) data = Data() -data.add_data_frame(df) +data.add_df(df) ``` For example if the url is @@ -204,7 +219,7 @@ df = pd.read_sql("SELECT * FROM mytable", conn) conn.close() data = Data() -data.add_data_frame(df) +data.add_df(df) ``` !!! note @@ -232,7 +247,7 @@ df = pd.read_sql("SELECT * FROM mytable", con=conn) conn.close() data = Data() -data.add_data_frame(df) +data.add_df(df) ``` !!! note @@ -261,7 +276,7 @@ df = pd.read_sql("SELECT * FROM mytable", con=conn) conn.close() data = Data() -data.add_data_frame(df) +data.add_df(df) ``` !!! note @@ -290,7 +305,7 @@ df = pd.read_sql("SELECT * FROM mytable", con=conn) conn.close() data = Data() -data.add_data_frame(df) +data.add_df(df) ``` !!! note diff --git a/docs/tutorial/events.md b/docs/tutorial/events.md index 46b3d791..9fedf105 100644 --- a/docs/tutorial/events.md +++ b/docs/tutorial/events.md @@ -28,7 +28,7 @@ block with information about the clicked marker. "https://ipyvizzu.vizzuhq.com/latest/assets/data/music_data.csv" ) data = Data() - data.add_data_frame(df) + data.add_df(df) chart = Chart() diff --git a/docs/tutorial/filter_add_new_records.md b/docs/tutorial/filter_add_new_records.md index 90661a7b..1794aa10 100644 --- a/docs/tutorial/filter_add_new_records.md +++ b/docs/tutorial/filter_add_new_records.md @@ -25,7 +25,7 @@ from the chart. "https://ipyvizzu.vizzuhq.com/latest/assets/data/music_data.csv" ) data1 = Data() - data1.add_data_frame(df) + data1.add_df(df) chart = Chart() diff --git a/docs/tutorial/geometry.md b/docs/tutorial/geometry.md index c6d5c8bb..1eb041f6 100644 --- a/docs/tutorial/geometry.md +++ b/docs/tutorial/geometry.md @@ -21,7 +21,7 @@ Switching the geometry to area. "https://ipyvizzu.vizzuhq.com/latest/assets/data/music_data.csv" ) data = Data() - data.add_data_frame(df) + data.add_df(df) chart = Chart() diff --git a/docs/tutorial/group_stack.md b/docs/tutorial/group_stack.md index 80bedfc9..d985a1be 100644 --- a/docs/tutorial/group_stack.md +++ b/docs/tutorial/group_stack.md @@ -22,7 +22,7 @@ we also add the same dimension to the color channel. "https://ipyvizzu.vizzuhq.com/latest/assets/data/music_data.csv" ) data = Data() - data.add_data_frame(df) + data.add_df(df) chart = Chart() diff --git a/docs/tutorial/orientation_split_polar.md b/docs/tutorial/orientation_split_polar.md index b75d6544..4de2cce6 100644 --- a/docs/tutorial/orientation_split_polar.md +++ b/docs/tutorial/orientation_split_polar.md @@ -23,7 +23,7 @@ only use temporarily. "https://ipyvizzu.vizzuhq.com/latest/assets/data/music_data.csv" ) data = Data() - data.add_data_frame(df) + data.add_df(df) chart = Chart() diff --git a/docs/tutorial/shorthands_store.md b/docs/tutorial/shorthands_store.md index 1ee9158d..7b723c98 100644 --- a/docs/tutorial/shorthands_store.md +++ b/docs/tutorial/shorthands_store.md @@ -22,7 +22,7 @@ that state or animation once again. "https://ipyvizzu.vizzuhq.com/latest/assets/data/music_data.csv" ) data = Data() - data.add_data_frame(df) + data.add_df(df) chart = Chart() diff --git a/docs/tutorial/sorting.md b/docs/tutorial/sorting.md index 2b9e7ee3..5a8ce795 100644 --- a/docs/tutorial/sorting.md +++ b/docs/tutorial/sorting.md @@ -22,7 +22,7 @@ ascending order. "https://ipyvizzu.vizzuhq.com/latest/assets/data/music_data.csv" ) data = Data() - data.add_data_frame(df) + data.add_df(df) chart = Chart() diff --git a/docs/tutorial/without_coordinates_noop_channel.md b/docs/tutorial/without_coordinates_noop_channel.md index 8b6eddd6..d8076da4 100644 --- a/docs/tutorial/without_coordinates_noop_channel.md +++ b/docs/tutorial/without_coordinates_noop_channel.md @@ -23,7 +23,7 @@ still on the `color` channel. "https://ipyvizzu.vizzuhq.com/latest/assets/data/music_data.csv" ) data = Data() - data.add_data_frame(df) + data.add_df(df) chart = Chart() diff --git a/src/ipyvizzu/data/infer_type.py b/src/ipyvizzu/data/infer_type.py index 371923a9..4cb1807f 100644 --- a/src/ipyvizzu/data/infer_type.py +++ b/src/ipyvizzu/data/infer_type.py @@ -18,5 +18,5 @@ class InferType(Enum): Measures can only be numerical. """ - DIMENSION = "dimension" - MEASURE = "measure" + DIMENSION: str = "dimension" + MEASURE: str = "measure" diff --git a/src/ipyvizzu/integrations/fugue.py b/src/ipyvizzu/integrations/fugue.py index b8480878..c27c8a3f 100644 --- a/src/ipyvizzu/integrations/fugue.py +++ b/src/ipyvizzu/integrations/fugue.py @@ -17,7 +17,7 @@ from typing import Any, Dict, Tuple -import pandas as pd # type: ignore +import pandas as pd from fugue import DataFrames, Outputter # type: ignore from fugue.exceptions import FugueWorkflowError # type: ignore from fugue.extensions import namespace_candidate # type: ignore @@ -60,7 +60,7 @@ def process(self, dfs: DataFrames) -> None: def _process_preset(self, df: pd.DataFrame) -> None: # pylint: disable=invalid-name data = Data() - data.add_data_frame(df) + data.add_df(df) chart = Chart(display=DisplayTarget.END) chart.animate(data) chart.animate(self._func(dict(self.params))) @@ -81,7 +81,7 @@ def _process_timeline( keys.sort() idx = pd.DataFrame({"_idx": range(len(keys)), key: keys}) df = df.sort_values(key).merge(idx) - data.add_data_frame(df) + data.add_df(df) chart.animate(data) for i, key in enumerate(keys): diff --git a/tests/assets/data_frame_in.json b/tests/assets/df_in.json similarity index 100% rename from tests/assets/data_frame_in.json rename to tests/assets/df_in.json diff --git a/tests/assets/data_frame_na.csv b/tests/assets/df_na.csv similarity index 100% rename from tests/assets/data_frame_na.csv rename to tests/assets/df_na.csv diff --git a/tests/assets/data_frame_out.json b/tests/assets/df_out.json similarity index 100% rename from tests/assets/data_frame_out.json rename to tests/assets/df_out.json diff --git a/tests/assets/fugue_preset.txt b/tests/assets/fugue_preset.txt index 1421316d..8f1d82f5 100644 --- a/tests/assets/fugue_preset.txt +++ b/tests/assets/fugue_preset.txt @@ -1,3 +1,3 @@ {'application/javascript': "window.ipyvizzu.createChart(element, id, 'https://cdn.jsdelivr.net/npm/vizzu@0.7/dist/vizzu.min.js', '800px', '480px');"} -{'application/javascript': 'window.ipyvizzu.animate(element, id, id, \'end\', false, lib => { return {"data": {"series": [{"name": "a", "type": "dimension", "values": ["a", "b", "c", "d", "e"]}, {"name": "b", "type": "measure", "values": [0.0, 1.0, 2.0, 3.0, 4.0]}]}} }, undefined);'} +{'application/javascript': 'window.ipyvizzu.animate(element, id, id, \'end\', false, lib => { return {"data": {"series": [{"name": "a", "values": ["a", "b", "c", "d", "e"], "type": "dimension"}, {"name": "b", "values": [0.0, 1.0, 2.0, 3.0, 4.0], "type": "measure"}]}} }, undefined);'} {'application/javascript': 'window.ipyvizzu.animate(element, id, id, \'end\', false, lib => { return {"config": lib.presets.bar({\'x\': \'a\', \'y\': \'b\'})} }, undefined);'} diff --git a/tests/assets/fugue_timeline.txt b/tests/assets/fugue_timeline.txt index 44baba51..b9a7d34e 100644 --- a/tests/assets/fugue_timeline.txt +++ b/tests/assets/fugue_timeline.txt @@ -1,5 +1,5 @@ {'application/javascript': "window.ipyvizzu.createChart(element, id, 'https://cdn.jsdelivr.net/npm/vizzu@0.7/dist/vizzu.min.js', '800px', '480px');"} -{'application/javascript': 'window.ipyvizzu.animate(element, id, id, \'end\', false, lib => { return {"data": {"series": [{"name": "a", "type": "dimension", "values": ["a", "b", "c", "d", "e"]}, {"name": "b", "type": "measure", "values": [0.0, 1.0, 2.0, 3.0, 4.0]}, {"name": "c", "type": "measure", "values": [1.0, 1.0, 2.0, 2.0, 3.0]}, {"name": "_idx", "type": "measure", "values": [0.0, 0.0, 1.0, 1.0, 2.0]}]}} }, undefined);'} +{'application/javascript': 'window.ipyvizzu.animate(element, id, id, \'end\', false, lib => { return {"data": {"series": [{"name": "a", "values": ["a", "b", "c", "d", "e"], "type": "dimension"}, {"name": "b", "values": [0.0, 1.0, 2.0, 3.0, 4.0], "type": "measure"}, {"name": "c", "values": [1.0, 1.0, 2.0, 2.0, 3.0], "type": "measure"}, {"name": "_idx", "values": [0.0, 0.0, 1.0, 1.0, 2.0], "type": "measure"}]}} }, undefined);'} {'application/javascript': 'window.ipyvizzu.animate(element, id, id, \'end\', false, lib => { return {"data": {"filter": record => { return (record._idx == 0) }}, "config": lib.presets.bar({\'x\': \'b\', \'y\': \'a\', \'title\': \'x 1\'})} }, {"show": {"delay": 0}, "hide": {"delay": 0}, "title": {"duration": 0, "delay": 0}, "duration": 0.3});'} {'application/javascript': 'window.ipyvizzu.animate(element, id, id, \'end\', false, lib => { return {"data": {"filter": record => { return (record._idx == 1) }}, "config": lib.presets.bar({\'x\': \'b\', \'y\': \'a\', \'title\': \'x 2\'})} }, {"show": {"delay": 0}, "hide": {"delay": 0}, "title": {"duration": 0, "delay": 0}, "duration": 0.3});'} {'application/javascript': 'window.ipyvizzu.animate(element, id, id, \'end\', false, lib => { return {"data": {"filter": record => { return (record._idx == 2) }}, "config": lib.presets.bar({\'x\': \'b\', \'y\': \'a\', \'title\': \'x 3\'})} }, {"show": {"delay": 0}, "hide": {"delay": 0}, "title": {"duration": 0, "delay": 0}, "duration": 0.3});'} diff --git a/tests/test_fugue.py b/tests/test_fugue.py index 0190e3b6..cd3fe7c9 100644 --- a/tests/test_fugue.py +++ b/tests/test_fugue.py @@ -5,8 +5,7 @@ from contextlib import redirect_stdout import pathlib import unittest -import pandas as pd # type: ignore - +import pandas as pd from tests.normalizer import Normalizer diff --git a/tools/docs/examples/mjs2md.mjs b/tools/docs/examples/mjs2md.mjs index ce0d5f0b..28a9551c 100644 --- a/tools/docs/examples/mjs2md.mjs +++ b/tools/docs/examples/mjs2md.mjs @@ -41,7 +41,7 @@ csv_url: ${assetsPath}/assets/data/${dataFileName}.csv dtype={"Year": str, "Timeseries": str}, ) data = Data() - data.add_data_frame(df) + data.add_df(df) chart = Chart() chart.animate(data) From d7703a32e631a460b3d03729806342b30cf667c9 Mon Sep 17 00:00:00 2001 From: David Vegh Date: Tue, 1 Aug 2023 17:10:10 +0200 Subject: [PATCH 03/15] Add pandas-stubs development dependency --- pdm.lock | 208 ++++++++++++++++++++++++++++++++----------------- pyproject.toml | 1 + 2 files changed, 137 insertions(+), 72 deletions(-) diff --git a/pdm.lock b/pdm.lock index ce6a15b3..a994bbfc 100644 --- a/pdm.lock +++ b/pdm.lock @@ -6,7 +6,7 @@ groups = ["codequality", "docs", "env", "packagedeps", "packagetool"] cross_platform = true static_urls = false lock_version = "4.3" -content_hash = "sha256:943d098d267a6feb8641cb82fc4867d4ae470976aef5c1b7a4f653c430cc1cb3" +content_hash = "sha256:6c32194cdc472c817bc25e4c888f8e4d0788cd98a86444b1bb445b936ca8d6d9" [[package]] name = "adagio" @@ -151,15 +151,15 @@ files = [ [[package]] name = "async-lru" -version = "2.0.3" +version = "2.0.4" requires_python = ">=3.8" summary = "Simple LRU cache for asyncio" dependencies = [ "typing-extensions>=4.0.0; python_version < \"3.11\"", ] files = [ - {file = "async-lru-2.0.3.tar.gz", hash = "sha256:b714c9d1415fca4e264da72a9e2abc66880ce7430e03a973341f88ea4c0d4869"}, - {file = "async_lru-2.0.3-py3-none-any.whl", hash = "sha256:00c0a8899c20b9c88663a47732689ff98189c9fa08ad9f734d7722f934d250b1"}, + {file = "async-lru-2.0.4.tar.gz", hash = "sha256:b8a59a5df60805ff63220b2a0c5b5393da5521b113cd5465a44eb037d81a5627"}, + {file = "async_lru-2.0.4-py3-none-any.whl", hash = "sha256:ff02944ce3c288c5be660c42dbcca0742b32c3b279d6dceda655190240b99224"}, ] [[package]] @@ -353,6 +353,13 @@ dependencies = [ "pycparser", ] files = [ + {file = "cffi-1.15.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:a66d3508133af6e8548451b25058d5812812ec3798c886bf38ed24a98216fab2"}, + {file = "cffi-1.15.1-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:470c103ae716238bbe698d67ad020e1db9d9dba34fa5a899b5e21577e6d52ed2"}, + {file = "cffi-1.15.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:9ad5db27f9cabae298d151c85cf2bad1d359a1b9c686a275df03385758e2f914"}, + {file = "cffi-1.15.1-cp27-cp27m-win32.whl", hash = "sha256:b3bbeb01c2b273cca1e1e0c5df57f12dce9a4dd331b4fa1635b8bec26350bde3"}, + {file = "cffi-1.15.1-cp27-cp27m-win_amd64.whl", hash = "sha256:e00b098126fd45523dd056d2efba6c5a63b71ffe9f2bbe1a4fe1716e1d0c331e"}, + {file = "cffi-1.15.1-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:d61f4695e6c866a23a21acab0509af1cdfd2c013cf256bbf5b6b5e2695827162"}, + {file = "cffi-1.15.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:ed9cb427ba5504c1dc15ede7d516b84757c3e3d7868ccc85121d9310d27eed0b"}, {file = "cffi-1.15.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:39d39875251ca8f612b6f33e6b1195af86d1b3e60086068be9cc053aa4376e21"}, {file = "cffi-1.15.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:285d29981935eb726a4399badae8f0ffdff4f5050eaa6d0cfc3f64b857b77185"}, {file = "cffi-1.15.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3eb6971dcff08619f8d91607cfc726518b6fa2a9eba42856be181c6d0d9515fd"}, @@ -770,7 +777,7 @@ files = [ [[package]] name = "fugue" -version = "0.8.5" +version = "0.8.6" requires_python = ">=3.7" summary = "An abstraction layer for distributed computation" dependencies = [ @@ -779,13 +786,13 @@ dependencies = [ "jinja2", "pandas>=1.2.0", "pyarrow>=0.15.1", - "qpd>=0.4.3", + "qpd>=0.4.4", "sqlglot", - "triad>=0.9.0", + "triad>=0.9.1", ] files = [ - {file = "fugue-0.8.5-py3-none-any.whl", hash = "sha256:cb4173bd787a7afbabf96b5233f942c1422ce6722dcdd64daef72814be791d69"}, - {file = "fugue-0.8.5.tar.gz", hash = "sha256:e6bee3339d1cfeed3bec5967884914da492305fe19262a718b2796481e9a7cfa"}, + {file = "fugue-0.8.6-py3-none-any.whl", hash = "sha256:e92742b309a0283ccd021f3ab7a6d8ecd32980179ee3539bcf679173dceac5d4"}, + {file = "fugue-0.8.6.tar.gz", hash = "sha256:4e30c4edbaee31a768b9a097e60d29b39d736a0302d3b611075de3fa73162d09"}, ] [[package]] @@ -971,15 +978,15 @@ files = [ [[package]] name = "jedi" -version = "0.18.2" +version = "0.19.0" requires_python = ">=3.6" summary = "An autocompletion tool for Python that can be used for text editors." dependencies = [ - "parso<0.9.0,>=0.8.0", + "parso<0.9.0,>=0.8.3", ] files = [ - {file = "jedi-0.18.2-py2.py3-none-any.whl", hash = "sha256:203c1fd9d969ab8f2119ec0a3342e0b49910045abe6af0a3ae83a5764d54639e"}, - {file = "jedi-0.18.2.tar.gz", hash = "sha256:bae794c30d07f6d910d32a7048af09b5a39ed740918da923c6b780790ebac612"}, + {file = "jedi-0.19.0-py2.py3-none-any.whl", hash = "sha256:cb8ce23fbccff0025e9386b5cf85e892f94c9b822378f8da49970471335ac64e"}, + {file = "jedi-0.19.0.tar.gz", hash = "sha256:bcf9894f1753969cbac8022a8c2eaee06bfa3724e4192470aaffe7eb6272b0c4"}, ] [[package]] @@ -1121,20 +1128,21 @@ files = [ [[package]] name = "jupyter-events" -version = "0.6.3" -requires_python = ">=3.7" +version = "0.7.0" +requires_python = ">=3.8" summary = "Jupyter Event System library" dependencies = [ - "jsonschema[format-nongpl]>=3.2.0", + "jsonschema[format-nongpl]>=4.18.0", "python-json-logger>=2.0.4", "pyyaml>=5.3", + "referencing", "rfc3339-validator", "rfc3986-validator>=0.1.1", "traitlets>=5.3", ] files = [ - {file = "jupyter_events-0.6.3-py3-none-any.whl", hash = "sha256:57a2749f87ba387cd1bfd9b22a0875b889237dbf2edc2121ebb22bde47036c17"}, - {file = "jupyter_events-0.6.3.tar.gz", hash = "sha256:9a6e9995f75d1b7146b436ea24d696ce3a35bfa8bfe45e0c33c334c79464d0b3"}, + {file = "jupyter_events-0.7.0-py3-none-any.whl", hash = "sha256:4753da434c13a37c3f3c89b500afa0c0a6241633441421f6adafe2fb2e2b924e"}, + {file = "jupyter_events-0.7.0.tar.gz", hash = "sha256:7be27f54b8388c03eefea123a4f79247c5b9381c49fb1cd48615ee191eb12615"}, ] [[package]] @@ -1314,6 +1322,13 @@ version = "4.9.3" requires_python = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, != 3.4.*" summary = "Powerful and Pythonic XML processing library combining libxml2/libxslt with the ElementTree API." files = [ + {file = "lxml-4.9.3-cp27-cp27m-macosx_11_0_x86_64.whl", hash = "sha256:b0a545b46b526d418eb91754565ba5b63b1c0b12f9bd2f808c852d9b4b2f9b5c"}, + {file = "lxml-4.9.3-cp27-cp27m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:075b731ddd9e7f68ad24c635374211376aa05a281673ede86cbe1d1b3455279d"}, + {file = "lxml-4.9.3-cp27-cp27m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:1e224d5755dba2f4a9498e150c43792392ac9b5380aa1b845f98a1618c94eeef"}, + {file = "lxml-4.9.3-cp27-cp27m-win32.whl", hash = "sha256:2c74524e179f2ad6d2a4f7caf70e2d96639c0954c943ad601a9e146c76408ed7"}, + {file = "lxml-4.9.3-cp27-cp27m-win_amd64.whl", hash = "sha256:4f1026bc732b6a7f96369f7bfe1a4f2290fb34dce00d8644bc3036fb351a4ca1"}, + {file = "lxml-4.9.3-cp27-cp27mu-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c0781a98ff5e6586926293e59480b64ddd46282953203c76ae15dbbbf302e8bb"}, + {file = "lxml-4.9.3-cp27-cp27mu-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:cef2502e7e8a96fe5ad686d60b49e1ab03e438bd9123987994528febd569868e"}, {file = "lxml-4.9.3-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:b86164d2cff4d3aaa1f04a14685cbc072efd0b4f99ca5708b2ad1b9b5988a991"}, {file = "lxml-4.9.3-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:42871176e7896d5d45138f6d28751053c711ed4d48d8e30b498da155af39aebd"}, {file = "lxml-4.9.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:ae8b9c6deb1e634ba4f1930eb67ef6e6bf6a44b6eb5ad605642b2d6d5ed9ce3c"}, @@ -1338,6 +1353,10 @@ files = [ {file = "lxml-4.9.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:b4e4bc18382088514ebde9328da057775055940a1f2e18f6ad2d78aa0f3ec5b9"}, {file = "lxml-4.9.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:fc9b106a1bf918db68619fdcd6d5ad4f972fdd19c01d19bdb6bf63f3589a9ec5"}, {file = "lxml-4.9.3-cp312-cp312-win_amd64.whl", hash = "sha256:d37017287a7adb6ab77e1c5bee9bcf9660f90ff445042b790402a654d2ad81d8"}, + {file = "lxml-4.9.3-cp35-cp35m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:56dc1f1ebccc656d1b3ed288f11e27172a01503fc016bcabdcbc0978b19352b7"}, + {file = "lxml-4.9.3-cp35-cp35m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:578695735c5a3f51569810dfebd05dd6f888147a34f0f98d4bb27e92b76e05c2"}, + {file = "lxml-4.9.3-cp35-cp35m-win32.whl", hash = "sha256:704f61ba8c1283c71b16135caf697557f5ecf3e74d9e453233e4771d68a1f42d"}, + {file = "lxml-4.9.3-cp35-cp35m-win_amd64.whl", hash = "sha256:c41bfca0bd3532d53d16fd34d20806d5c2b1ace22a2f2e4c0008570bf2c58833"}, {file = "lxml-4.9.3-cp36-cp36m-macosx_11_0_x86_64.whl", hash = "sha256:64f479d719dc9f4c813ad9bb6b28f8390360660b73b2e4beb4cb0ae7104f1c12"}, {file = "lxml-4.9.3-cp36-cp36m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:dd708cf4ee4408cf46a48b108fb9427bfa00b9b85812a9262b5c668af2533ea5"}, {file = "lxml-4.9.3-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c31c7462abdf8f2ac0577d9f05279727e698f97ecbb02f17939ea99ae8daa98"}, @@ -2073,7 +2092,7 @@ files = [ [[package]] name = "nbformat" -version = "5.9.1" +version = "5.9.2" requires_python = ">=3.8" summary = "The Jupyter Notebook format" dependencies = [ @@ -2083,18 +2102,18 @@ dependencies = [ "traitlets>=5.1", ] files = [ - {file = "nbformat-5.9.1-py3-none-any.whl", hash = "sha256:b7968ebf4811178a4108ee837eae1442e3f054132100f0359219e9ed1ce3ca45"}, - {file = "nbformat-5.9.1.tar.gz", hash = "sha256:3a7f52d040639cbd8a3890218c8b0ffb93211588c57446c90095e32ba5881b5d"}, + {file = "nbformat-5.9.2-py3-none-any.whl", hash = "sha256:1c5172d786a41b82bcfd0c23f9e6b6f072e8fb49c39250219e4acfff1efe89e9"}, + {file = "nbformat-5.9.2.tar.gz", hash = "sha256:5f98b5ba1997dff175e77e0c17d5c10a96eaed2cbd1de3533d1fc35d5e111192"}, ] [[package]] name = "nest-asyncio" -version = "1.5.6" +version = "1.5.7" requires_python = ">=3.5" summary = "Patch asyncio to allow nested event loops" files = [ - {file = "nest_asyncio-1.5.6-py3-none-any.whl", hash = "sha256:b9a953fb40dceaa587d109609098db21900182b16440652454a146cffb06e8b8"}, - {file = "nest_asyncio-1.5.6.tar.gz", hash = "sha256:d267cc1ff794403f7df692964d1d2a3fa9418ffea2a3f6859a439ff482fef290"}, + {file = "nest_asyncio-1.5.7-py3-none-any.whl", hash = "sha256:5301c82941b550b3123a1ea772ba9a1c80bad3a182be8c1a5ae6ad3be57a9657"}, + {file = "nest_asyncio-1.5.7.tar.gz", hash = "sha256:6a80f7b98f24d9083ed24608977c09dd608d83f91cccc24c9d2cba6d10e01c10"}, ] [[package]] @@ -2112,7 +2131,7 @@ files = [ [[package]] name = "notebook" -version = "7.0.0" +version = "7.0.1" requires_python = ">=3.8" summary = "Jupyter Notebook - A web-based notebook environment for interactive computing" dependencies = [ @@ -2123,8 +2142,8 @@ dependencies = [ "tornado>=6.2.0", ] files = [ - {file = "notebook-7.0.0-py3-none-any.whl", hash = "sha256:71b4e695e658763a2766613176491854708fb46fbe7664bf5e494deeeab92d60"}, - {file = "notebook-7.0.0.tar.gz", hash = "sha256:38b55e6939df0ba73b53212c3b234e41102f1789e0158606cedaebf00abef6c8"}, + {file = "notebook-7.0.1-py3-none-any.whl", hash = "sha256:35327476042140e8739ff8fcfecdc915658ae72b4db72d6e3b537badcdbf9e35"}, + {file = "notebook-7.0.1.tar.gz", hash = "sha256:2e16ad4e63ea89f7efbe212ee7c1693fcfa5ab55ffef75047530f74af4bd926c"}, ] [[package]] @@ -2142,35 +2161,35 @@ files = [ [[package]] name = "numpy" -version = "1.25.1" +version = "1.25.2" requires_python = ">=3.9" summary = "Fundamental package for array computing in Python" files = [ - {file = "numpy-1.25.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:77d339465dff3eb33c701430bcb9c325b60354698340229e1dff97745e6b3efa"}, - {file = "numpy-1.25.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d736b75c3f2cb96843a5c7f8d8ccc414768d34b0a75f466c05f3a739b406f10b"}, - {file = "numpy-1.25.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4a90725800caeaa160732d6b31f3f843ebd45d6b5f3eec9e8cc287e30f2805bf"}, - {file = "numpy-1.25.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c6c9261d21e617c6dc5eacba35cb68ec36bb72adcff0dee63f8fbc899362588"}, - {file = "numpy-1.25.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:0def91f8af6ec4bb94c370e38c575855bf1d0be8a8fbfba42ef9c073faf2cf19"}, - {file = "numpy-1.25.1-cp310-cp310-win32.whl", hash = "sha256:fd67b306320dcadea700a8f79b9e671e607f8696e98ec255915c0c6d6b818503"}, - {file = "numpy-1.25.1-cp310-cp310-win_amd64.whl", hash = "sha256:c1516db588987450b85595586605742879e50dcce923e8973f79529651545b57"}, - {file = "numpy-1.25.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6b82655dd8efeea69dbf85d00fca40013d7f503212bc5259056244961268b66e"}, - {file = "numpy-1.25.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e8f6049c4878cb16960fbbfb22105e49d13d752d4d8371b55110941fb3b17800"}, - {file = "numpy-1.25.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:41a56b70e8139884eccb2f733c2f7378af06c82304959e174f8e7370af112e09"}, - {file = "numpy-1.25.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d5154b1a25ec796b1aee12ac1b22f414f94752c5f94832f14d8d6c9ac40bcca6"}, - {file = "numpy-1.25.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:38eb6548bb91c421261b4805dc44def9ca1a6eef6444ce35ad1669c0f1a3fc5d"}, - {file = "numpy-1.25.1-cp311-cp311-win32.whl", hash = "sha256:791f409064d0a69dd20579345d852c59822c6aa087f23b07b1b4e28ff5880fcb"}, - {file = "numpy-1.25.1-cp311-cp311-win_amd64.whl", hash = "sha256:c40571fe966393b212689aa17e32ed905924120737194b5d5c1b20b9ed0fb171"}, - {file = "numpy-1.25.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3d7abcdd85aea3e6cdddb59af2350c7ab1ed764397f8eec97a038ad244d2d105"}, - {file = "numpy-1.25.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1a180429394f81c7933634ae49b37b472d343cccb5bb0c4a575ac8bbc433722f"}, - {file = "numpy-1.25.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d412c1697c3853c6fc3cb9751b4915859c7afe6a277c2bf00acf287d56c4e625"}, - {file = "numpy-1.25.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:20e1266411120a4f16fad8efa8e0454d21d00b8c7cee5b5ccad7565d95eb42dd"}, - {file = "numpy-1.25.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:f76aebc3358ade9eacf9bc2bb8ae589863a4f911611694103af05346637df1b7"}, - {file = "numpy-1.25.1-cp39-cp39-win32.whl", hash = "sha256:247d3ffdd7775bdf191f848be8d49100495114c82c2bd134e8d5d075fb386a1c"}, - {file = "numpy-1.25.1-cp39-cp39-win_amd64.whl", hash = "sha256:1d5d3c68e443c90b38fdf8ef40e60e2538a27548b39b12b73132456847f4b631"}, - {file = "numpy-1.25.1-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:35a9527c977b924042170a0887de727cd84ff179e478481404c5dc66b4170009"}, - {file = "numpy-1.25.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0d3fe3dd0506a28493d82dc3cf254be8cd0d26f4008a417385cbf1ae95b54004"}, - {file = "numpy-1.25.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:012097b5b0d00a11070e8f2e261128c44157a8689f7dedcf35576e525893f4fe"}, - {file = "numpy-1.25.1.tar.gz", hash = "sha256:9a3a9f3a61480cc086117b426a8bd86869c213fc4072e606f01c4e4b66eb92bf"}, + {file = "numpy-1.25.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:db3ccc4e37a6873045580d413fe79b68e47a681af8db2e046f1dacfa11f86eb3"}, + {file = "numpy-1.25.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:90319e4f002795ccfc9050110bbbaa16c944b1c37c0baeea43c5fb881693ae1f"}, + {file = "numpy-1.25.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dfe4a913e29b418d096e696ddd422d8a5d13ffba4ea91f9f60440a3b759b0187"}, + {file = "numpy-1.25.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f08f2e037bba04e707eebf4bc934f1972a315c883a9e0ebfa8a7756eabf9e357"}, + {file = "numpy-1.25.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:bec1e7213c7cb00d67093247f8c4db156fd03075f49876957dca4711306d39c9"}, + {file = "numpy-1.25.2-cp310-cp310-win32.whl", hash = "sha256:7dc869c0c75988e1c693d0e2d5b26034644399dd929bc049db55395b1379e044"}, + {file = "numpy-1.25.2-cp310-cp310-win_amd64.whl", hash = "sha256:834b386f2b8210dca38c71a6e0f4fd6922f7d3fcff935dbe3a570945acb1b545"}, + {file = "numpy-1.25.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c5462d19336db4560041517dbb7759c21d181a67cb01b36ca109b2ae37d32418"}, + {file = "numpy-1.25.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c5652ea24d33585ea39eb6a6a15dac87a1206a692719ff45d53c5282e66d4a8f"}, + {file = "numpy-1.25.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0d60fbae8e0019865fc4784745814cff1c421df5afee233db6d88ab4f14655a2"}, + {file = "numpy-1.25.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:60e7f0f7f6d0eee8364b9a6304c2845b9c491ac706048c7e8cf47b83123b8dbf"}, + {file = "numpy-1.25.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:bb33d5a1cf360304754913a350edda36d5b8c5331a8237268c48f91253c3a364"}, + {file = "numpy-1.25.2-cp311-cp311-win32.whl", hash = "sha256:5883c06bb92f2e6c8181df7b39971a5fb436288db58b5a1c3967702d4278691d"}, + {file = "numpy-1.25.2-cp311-cp311-win_amd64.whl", hash = "sha256:5c97325a0ba6f9d041feb9390924614b60b99209a71a69c876f71052521d42a4"}, + {file = "numpy-1.25.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b79e513d7aac42ae918db3ad1341a015488530d0bb2a6abcbdd10a3a829ccfd3"}, + {file = "numpy-1.25.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:eb942bfb6f84df5ce05dbf4b46673ffed0d3da59f13635ea9b926af3deb76926"}, + {file = "numpy-1.25.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e0746410e73384e70d286f93abf2520035250aad8c5714240b0492a7302fdca"}, + {file = "numpy-1.25.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d7806500e4f5bdd04095e849265e55de20d8cc4b661b038957354327f6d9b295"}, + {file = "numpy-1.25.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8b77775f4b7df768967a7c8b3567e309f617dd5e99aeb886fa14dc1a0791141f"}, + {file = "numpy-1.25.2-cp39-cp39-win32.whl", hash = "sha256:2792d23d62ec51e50ce4d4b7d73de8f67a2fd3ea710dcbc8563a51a03fb07b01"}, + {file = "numpy-1.25.2-cp39-cp39-win_amd64.whl", hash = "sha256:76b4115d42a7dfc5d485d358728cdd8719be33cc5ec6ec08632a5d6fca2ed380"}, + {file = "numpy-1.25.2-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:1a1329e26f46230bf77b02cc19e900db9b52f398d6722ca853349a782d4cff55"}, + {file = "numpy-1.25.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4c3abc71e8b6edba80a01a52e66d83c5d14433cbcd26a40c329ec7ed09f37901"}, + {file = "numpy-1.25.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:1b9735c27cea5d995496f46a8b1cd7b408b3f34b6d50459d9ac8fe3a20cc17bf"}, + {file = "numpy-1.25.2.tar.gz", hash = "sha256:fd608e19c8d7c55021dffd43bfe5492fab8cc105cc8986f813f8c3c048b38760"}, ] [[package]] @@ -2233,6 +2252,20 @@ files = [ {file = "pandas-2.0.3.tar.gz", hash = "sha256:c02f372a88e0d17f36d3093a644c73cfc1788e876a7c4bcb4020a77512e2043c"}, ] +[[package]] +name = "pandas-stubs" +version = "2.0.2.230605" +requires_python = ">=3.8" +summary = "Type annotations for pandas" +dependencies = [ + "numpy>=1.24.3", + "types-pytz>=2022.1.1", +] +files = [ + {file = "pandas_stubs-2.0.2.230605-py3-none-any.whl", hash = "sha256:39106b602f3cb6dc5f728b84e1b32bde6ecf41ee34ee714c66228009609fbada"}, + {file = "pandas_stubs-2.0.2.230605.tar.gz", hash = "sha256:624c7bb06d38145a44b61be459ccd19b038e0bf20364a025ecaab78fea65e858"}, +] + [[package]] name = "pandocfilters" version = "1.5.0" @@ -2255,12 +2288,12 @@ files = [ [[package]] name = "pathspec" -version = "0.11.1" +version = "0.11.2" requires_python = ">=3.7" summary = "Utility library for gitignore style pattern matching of file paths." files = [ - {file = "pathspec-0.11.1-py3-none-any.whl", hash = "sha256:d8af70af76652554bd134c22b3e8a1cc46ed7d91edcdd721ef1a0c51a84a5293"}, - {file = "pathspec-0.11.1.tar.gz", hash = "sha256:2798de800fa92780e33acca925945e9a19a133b715067cf165b8866c15a31687"}, + {file = "pathspec-0.11.2-py3-none-any.whl", hash = "sha256:1d6ed233af05e679efb96b1851550ea95bbb64b7c490b0f5aa52996c11e92a20"}, + {file = "pathspec-0.11.2.tar.gz", hash = "sha256:e0d8d0ac2f12da61956eb2306b69f9469b42f4deb0f3cb6ed47b9cce9996ced3"}, ] [[package]] @@ -2325,12 +2358,12 @@ files = [ [[package]] name = "platformdirs" -version = "3.9.1" +version = "3.10.0" requires_python = ">=3.7" summary = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." files = [ - {file = "platformdirs-3.9.1-py3-none-any.whl", hash = "sha256:ad8291ae0ae5072f66c16945166cb11c63394c7a3ad1b1bc9828ca3162da8c2f"}, - {file = "platformdirs-3.9.1.tar.gz", hash = "sha256:1b42b450ad933e981d56e59f1b97495428c9bd60698baab9f3eb3d00d5822421"}, + {file = "platformdirs-3.10.0-py3-none-any.whl", hash = "sha256:d7c24979f292f916dc9cbf8648319032f551ea8c49a4c9bf2fb556a02070ec1d"}, + {file = "platformdirs-3.10.0.tar.gz", hash = "sha256:b45696dab2d7cc691a3226759c0d3b00c47c8b6e293d96f6436f733303f77f6d"}, ] [[package]] @@ -2389,6 +2422,13 @@ version = "5.9.5" requires_python = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" summary = "Cross-platform lib for process and system monitoring in Python." files = [ + {file = "psutil-5.9.5-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:be8929ce4313f9f8146caad4272f6abb8bf99fc6cf59344a3167ecd74f4f203f"}, + {file = "psutil-5.9.5-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:ab8ed1a1d77c95453db1ae00a3f9c50227ebd955437bcf2a574ba8adbf6a74d5"}, + {file = "psutil-5.9.5-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:4aef137f3345082a3d3232187aeb4ac4ef959ba3d7c10c33dd73763fbc063da4"}, + {file = "psutil-5.9.5-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:ea8518d152174e1249c4f2a1c89e3e6065941df2fa13a1ab45327716a23c2b48"}, + {file = "psutil-5.9.5-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:acf2aef9391710afded549ff602b5887d7a2349831ae4c26be7c807c0a39fac4"}, + {file = "psutil-5.9.5-cp27-none-win32.whl", hash = "sha256:5b9b8cb93f507e8dbaf22af6a2fd0ccbe8244bf30b1baad6b3954e935157ae3f"}, + {file = "psutil-5.9.5-cp27-none-win_amd64.whl", hash = "sha256:8c5f7c5a052d1d567db4ddd231a9d27a74e8e4a9c3f44b1032762bd7b9fdcd42"}, {file = "psutil-5.9.5-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:3c6f686f4225553615612f6d9bc21f1c0e305f75d7d8454f9b46e901778e7217"}, {file = "psutil-5.9.5-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7a7dd9997128a0d928ed4fb2c2d57e5102bb6089027939f3b722f3a210f9a8da"}, {file = "psutil-5.9.5-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:89518112647f1276b03ca97b65cc7f64ca587b1eb0278383017c2a0dcc26cbe4"}, @@ -2474,11 +2514,11 @@ files = [ [[package]] name = "pylint" -version = "2.17.4" +version = "2.17.5" requires_python = ">=3.7.2" summary = "python code static checker" dependencies = [ - "astroid<=2.17.0-dev0,>=2.15.4", + "astroid<=2.17.0-dev0,>=2.15.6", "colorama>=0.4.5; sys_platform == \"win32\"", "dill>=0.2; python_version < \"3.11\"", "dill>=0.3.6; python_version >= \"3.11\"", @@ -2489,8 +2529,8 @@ dependencies = [ "tomlkit>=0.10.1", ] files = [ - {file = "pylint-2.17.4-py3-none-any.whl", hash = "sha256:7a1145fb08c251bdb5cca11739722ce64a63db479283d10ce718b2460e54123c"}, - {file = "pylint-2.17.4.tar.gz", hash = "sha256:5dcf1d9e19f41f38e4e85d10f511e5b9c35e1aa74251bf95cdd8cb23584e2db1"}, + {file = "pylint-2.17.5-py3-none-any.whl", hash = "sha256:73995fb8216d3bed149c8d51bba25b2c52a8251a2c8ac846ec668ce38fab5413"}, + {file = "pylint-2.17.5.tar.gz", hash = "sha256:f7b601cbc06fef7e62a754e2b41294c2aa31f1cb659624b9a85bcba29eaf8252"}, ] [[package]] @@ -2887,7 +2927,7 @@ files = [ [[package]] name = "rich" -version = "13.4.2" +version = "13.5.1" requires_python = ">=3.7.0" summary = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" dependencies = [ @@ -2895,8 +2935,8 @@ dependencies = [ "pygments<3.0.0,>=2.13.0", ] files = [ - {file = "rich-13.4.2-py3-none-any.whl", hash = "sha256:8f87bc7ee54675732fa66a05ebfe489e27264caeeff3728c945d25971b6485ec"}, - {file = "rich-13.4.2.tar.gz", hash = "sha256:d653d6bccede5844304c605d5aac802c7cf9621efd700b46c7ec2b51ea914898"}, + {file = "rich-13.5.1-py3-none-any.whl", hash = "sha256:b97381b204a206e1be618f5e1215a57174a1a7732490b3bf6668cf41d30bc72d"}, + {file = "rich-13.5.1.tar.gz", hash = "sha256:881653ee7037803559d8eae98f145e0a4c4b0ec3ff0300d2cc8d479c71fc6819"}, ] [[package]] @@ -3138,11 +3178,11 @@ files = [ [[package]] name = "sqlglot" -version = "17.8.0" +version = "17.9.0" summary = "An easily customizable SQL parser and transpiler" files = [ - {file = "sqlglot-17.8.0-py3-none-any.whl", hash = "sha256:2b62a9e620fa39d4f237e8c53ada5d822f5f90fe76b581db8fe96c96b2c62ab9"}, - {file = "sqlglot-17.8.0.tar.gz", hash = "sha256:482462f80f7a4b307c2089fde051daf58e4962784caff1a4641f4deebf954aac"}, + {file = "sqlglot-17.9.0-py3-none-any.whl", hash = "sha256:92c2f4cfd8258805071733ac4a5e26086168a4180cb1d250809704161ad9620f"}, + {file = "sqlglot-17.9.0.tar.gz", hash = "sha256:a7aa51f0ef7bf32f8a916f685150589b2ac314aeb20c704daad159ca48214f18"}, ] [[package]] @@ -3209,12 +3249,12 @@ files = [ [[package]] name = "tomlkit" -version = "0.11.8" +version = "0.12.1" requires_python = ">=3.7" summary = "Style preserving TOML library" files = [ - {file = "tomlkit-0.11.8-py3-none-any.whl", hash = "sha256:8c726c4c202bdb148667835f68d68780b9a003a9ec34167b6c673b38eff2a171"}, - {file = "tomlkit-0.11.8.tar.gz", hash = "sha256:9330fc7faa1db67b541b28e62018c17d20be733177d290a13b24c62d1614e0c3"}, + {file = "tomlkit-0.12.1-py3-none-any.whl", hash = "sha256:712cbd236609acc6a3e2e97253dfc52d4c2082982a88f61b640ecf0817eab899"}, + {file = "tomlkit-0.12.1.tar.gz", hash = "sha256:38e1ff8edb991273ec9f6181244a6a391ac30e9f5098e7535640ea6be97a7c86"}, ] [[package]] @@ -3325,6 +3365,15 @@ files = [ {file = "types_Markdown-3.4.2.10-py3-none-any.whl", hash = "sha256:543ff3027fda21c3149780bf835a721cd094c5729e9a87725f180569c960bff8"}, ] +[[package]] +name = "types-pytz" +version = "2023.3.0.0" +summary = "Typing stubs for pytz" +files = [ + {file = "types-pytz-2023.3.0.0.tar.gz", hash = "sha256:ecdc70d543aaf3616a7e48631543a884f74205f284cefd6649ddf44c6a820aac"}, + {file = "types_pytz-2023.3.0.0-py3-none-any.whl", hash = "sha256:4fc2a7fbbc315f0b6630e0b899fd6c743705abe1094d007b0e612d10da15e0f3"}, +] + [[package]] name = "types-pyyaml" version = "6.0.12.11" @@ -3522,6 +3571,15 @@ version = "1.15.0" requires_python = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" summary = "Module for decorators, wrappers and monkey patching." files = [ + {file = "wrapt-1.15.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:ca1cccf838cd28d5a0883b342474c630ac48cac5df0ee6eacc9c7290f76b11c1"}, + {file = "wrapt-1.15.0-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:e826aadda3cae59295b95343db8f3d965fb31059da7de01ee8d1c40a60398b29"}, + {file = "wrapt-1.15.0-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:5fc8e02f5984a55d2c653f5fea93531e9836abbd84342c1d1e17abc4a15084c2"}, + {file = "wrapt-1.15.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:96e25c8603a155559231c19c0349245eeb4ac0096fe3c1d0be5c47e075bd4f46"}, + {file = "wrapt-1.15.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:40737a081d7497efea35ab9304b829b857f21558acfc7b3272f908d33b0d9d4c"}, + {file = "wrapt-1.15.0-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:f87ec75864c37c4c6cb908d282e1969e79763e0d9becdfe9fe5473b7bb1e5f09"}, + {file = "wrapt-1.15.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:1286eb30261894e4c70d124d44b7fd07825340869945c79d05bda53a40caa079"}, + {file = "wrapt-1.15.0-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:493d389a2b63c88ad56cdc35d0fa5752daac56ca755805b1b0c530f785767d5e"}, + {file = "wrapt-1.15.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:58d7a75d731e8c63614222bcb21dd992b4ab01a399f1f09dd82af17bbfc2368a"}, {file = "wrapt-1.15.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:21f6d9a0d5b3a207cdf7acf8e58d7d13d463e639f0c7e01d82cdb671e6cb7923"}, {file = "wrapt-1.15.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ce42618f67741d4697684e501ef02f29e758a123aa2d669e2d964ff734ee00ee"}, {file = "wrapt-1.15.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:41d07d029dd4157ae27beab04d22b8e261eddfc6ecd64ff7000b10dc8b3a5727"}, @@ -3542,6 +3600,12 @@ files = [ {file = "wrapt-1.15.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:74934ebd71950e3db69960a7da29204f89624dde411afbfb3b4858c1409b1e98"}, {file = "wrapt-1.15.0-cp311-cp311-win32.whl", hash = "sha256:bd84395aab8e4d36263cd1b9308cd504f6cf713b7d6d3ce25ea55670baec5416"}, {file = "wrapt-1.15.0-cp311-cp311-win_amd64.whl", hash = "sha256:a487f72a25904e2b4bbc0817ce7a8de94363bd7e79890510174da9d901c38705"}, + {file = "wrapt-1.15.0-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:4ff0d20f2e670800d3ed2b220d40984162089a6e2c9646fdb09b85e6f9a8fc29"}, + {file = "wrapt-1.15.0-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:9ed6aa0726b9b60911f4aed8ec5b8dd7bf3491476015819f56473ffaef8959bd"}, + {file = "wrapt-1.15.0-cp35-cp35m-manylinux2010_i686.whl", hash = "sha256:896689fddba4f23ef7c718279e42f8834041a21342d95e56922e1c10c0cc7afb"}, + {file = "wrapt-1.15.0-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:75669d77bb2c071333417617a235324a1618dba66f82a750362eccbe5b61d248"}, + {file = "wrapt-1.15.0-cp35-cp35m-win32.whl", hash = "sha256:fbec11614dba0424ca72f4e8ba3c420dba07b4a7c206c8c8e4e73f2e98f4c559"}, + {file = "wrapt-1.15.0-cp35-cp35m-win_amd64.whl", hash = "sha256:fd69666217b62fa5d7c6aa88e507493a34dec4fa20c5bd925e4bc12fce586639"}, {file = "wrapt-1.15.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:b0724f05c396b0a4c36a3226c31648385deb6a65d8992644c12a4963c70326ba"}, {file = "wrapt-1.15.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bbeccb1aa40ab88cd29e6c7d8585582c99548f55f9b2581dfc5ba68c59a85752"}, {file = "wrapt-1.15.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:38adf7198f8f154502883242f9fe7333ab05a5b02de7d83aa2d88ea621f13364"}, diff --git a/pyproject.toml b/pyproject.toml index f6a7a072..130a35d1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -172,6 +172,7 @@ packagedeps = [ "IPython ; python_version >= '3.10'", "jsonschema ; python_version >= '3.10'", "pandas ; python_version >= '3.10'", + "pandas-stubs ; python_version >= '3.10'", "fugue >= 0.8.1 ; python_version >= '3.10'", ] codequality = [ From 32cdfefb8114f909bdfca68e4a2f67d9db165f8e Mon Sep 17 00:00:00 2001 From: David Vegh Date: Tue, 1 Aug 2023 17:19:47 +0200 Subject: [PATCH 04/15] Fix data frame tests --- src/ipyvizzu/__init__.py | 4 +- src/ipyvizzu/data/__init__.py | 0 src/ipyvizzu/data/converters/__init__.py | 0 tests/test_animation.py | 84 +++++++----------------- tests/test_doc.py | 20 +++--- 5 files changed, 37 insertions(+), 71 deletions(-) create mode 100644 src/ipyvizzu/data/__init__.py create mode 100644 src/ipyvizzu/data/converters/__init__.py diff --git a/src/ipyvizzu/__init__.py b/src/ipyvizzu/__init__.py index d7459851..9211a557 100644 --- a/src/ipyvizzu/__init__.py +++ b/src/ipyvizzu/__init__.py @@ -16,13 +16,13 @@ `ipyvizzu` package imports the following objects in `__init__.py`: * [Chart][ipyvizzu.chart.Chart] +* [InferType][ipyvizzu.data.infer_type.InferType] * [Data][ipyvizzu.animation.Data] * [Config][ipyvizzu.animation.Config] * [Style][ipyvizzu.animation.Style] * [Keyframe][ipyvizzu.animation.Keyframe] * [Snapshot][ipyvizzu.animation.Snapshot] * [Animation][ipyvizzu.animation.Animation] -* [InferType][ipyvizzu.animation.InferType] * [AbstractAnimation][ipyvizzu.animation.AbstractAnimation] * [PlainAnimation][ipyvizzu.animation.PlainAnimation] * [AnimationMerger][ipyvizzu.animation.AnimationMerger] @@ -43,10 +43,10 @@ """ from .chart import Chart +from .data.infer_type import InferType from .animation import ( AbstractAnimation, PlainAnimation, - InferType, Data, Config, Style, diff --git a/src/ipyvizzu/data/__init__.py b/src/ipyvizzu/data/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/src/ipyvizzu/data/converters/__init__.py b/src/ipyvizzu/data/converters/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/test_animation.py b/tests/test_animation.py index fc70e8c0..fbaa3b1e 100644 --- a/tests/test_animation.py +++ b/tests/test_animation.py @@ -4,7 +4,7 @@ import pathlib import unittest import jsonschema # type: ignore -import pandas as pd # type: ignore +import pandas as pd from tests import ( PlainAnimation, @@ -211,38 +211,38 @@ def test_data_cube(self) -> None: self.data.build(), ) - def test_data_frame_with_not_df(self) -> None: + def test_add_df_with_none(self) -> None: data = Data() with self.assertRaises(TypeError): - data.add_data_frame("") + data.add_df("") - def test_data_frame_with_none(self) -> None: + def test_df_with_none(self) -> None: data = Data() - data.add_data_frame(None) + data.add_df(None) self.assertEqual( {"data": {}}, data.build(), ) - def test_data_frame(self) -> None: - with open(self.asset_dir / "data_frame_in.json", encoding="utf8") as fh_in: + def test_add_df_with_df(self) -> None: + with open(self.asset_dir / "df_in.json", encoding="utf8") as fh_in: fc_in = json.load(fh_in) - with open(self.asset_dir / "data_frame_out.json", encoding="utf8") as fh_out: + with open(self.asset_dir / "df_out.json", encoding="utf8") as fh_out: fc_out = json.load(fh_out) df = pd.DataFrame(fc_in) df = df.astype({"PopularityAsDimension": str}) - self.data.add_data_frame(df) + self.data.add_df(df) self.assertEqual( fc_out, self.data.build(), ) - def test_data_frame_na(self) -> None: + def test_add_df_with_df_contains_na(self) -> None: df = pd.read_csv( - self.asset_dir / "data_frame_na.csv", dtype={"PopularityAsDimension": str} + self.asset_dir / "df_na.csv", dtype={"PopularityAsDimension": str} ) - self.data.add_data_frame(df) + self.data.add_df(df) self.assertEqual( { "data": { @@ -263,10 +263,10 @@ def test_data_frame_na(self) -> None: self.data.build(), ) - def test_data_frame_with_pd_series(self) -> None: + def test_add_df_with_series(self) -> None: data = Data() - data.add_data_frame(pd.Series([1, 2], name="series1")) - data.add_data_frame( + data.add_df(pd.Series([1, 2], name="series1")) + data.add_df( pd.Series({"x": 3, "y": 4, "z": 5}, index=["x", "y"], name="series2") ) self.assertEqual( @@ -281,74 +281,40 @@ def test_data_frame_with_pd_series(self) -> None: data.build(), ) - def test_data_frame_index_with_not_df(self) -> None: - data = Data() - with self.assertRaises(TypeError): - data.add_data_frame_index(data_frame="", name="") - - def test_data_frame_index_with_none_and_none(self) -> None: - data = Data() - data.add_data_frame_index(data_frame=None, name=None) - self.assertEqual( - {"data": {}}, - data.build(), - ) - - def test_data_frame_index_with_df_and_none(self) -> None: - data = Data() - df = pd.DataFrame( - pd.Series({"x": 1, "y": 2, "z": 3}, index=["x", "y"], name="series") - ) - data.add_data_frame_index(data_frame=df, name=None) - data.add_data_frame(df) - self.assertEqual( - { - "data": { - "series": [ - {"name": "None", "type": "dimension", "values": ["x", "y"]}, - {"name": "series", "type": "measure", "values": [1.0, 2.0]}, - ] - } - }, - data.build(), - ) - - def test_data_frame_index_with_df_and_index(self) -> None: + def test_add_df_with_df_and_with_include_index(self) -> None: data = Data() df = pd.DataFrame({"series": [1, 2, 3]}, index=["x", "y", "z"]) - data.add_data_frame_index(data_frame=df, name="Index") - data.add_data_frame(df) + data.add_df(df, include_index="Index") self.assertEqual( { "data": { "series": [ - { - "name": "Index", - "type": "dimension", - "values": ["x", "y", "z"], - }, { "name": "series", "type": "measure", "values": [1.0, 2.0, 3.0], }, + { + "name": "Index", + "type": "dimension", + "values": ["x", "y", "z"], + }, ] } }, data.build(), ) - def test_data_frame_index_with_pd_series(self) -> None: + def test_add_df_with_series_and_with_include_index(self) -> None: data = Data() df = pd.Series({"x": 1, "y": 2, "z": 3}, index=["x", "y"], name="series") - data.add_data_frame_index(data_frame=df, name="Index") - data.add_data_frame(df) + data.add_df(df, include_index="Index") self.assertEqual( { "data": { "series": [ - {"name": "Index", "type": "dimension", "values": ["x", "y"]}, {"name": "series", "type": "measure", "values": [1.0, 2.0]}, + {"name": "Index", "type": "dimension", "values": ["x", "y"]}, ] } }, diff --git a/tests/test_doc.py b/tests/test_doc.py index f132a3ce..fd6ebedd 100644 --- a/tests/test_doc.py +++ b/tests/test_doc.py @@ -4,7 +4,7 @@ import json import pathlib import unittest -import pandas as pd # type: ignore +import pandas as pd from tests import Data @@ -21,15 +21,15 @@ def setUpClass(cls) -> None: def setUp(self) -> None: self.data = Data() - def test_data_frame_with_csv(self) -> None: - with open(self.asset_dir / "data_frame_out.json", encoding="utf8") as fh_out: + def test_add_df_with_csv(self) -> None: + with open(self.asset_dir / "df_out.json", encoding="utf8") as fh_out: fc_out = json.load(fh_out) fc_out["data"]["series"] = fc_out["data"]["series"][:-1] df = pd.read_csv(self.doc_dir / "music_data.csv") data = Data() - data.add_data_frame(df) + data.add_df(df) self.assertEqual( fc_out, data.build(), @@ -37,22 +37,22 @@ def test_data_frame_with_csv(self) -> None: # TODO: remove decorator once support for Python 3.6 is dropped @unittest.skipUnless(sys.version_info >= (3, 7), "at least Python 3.7 is required") - def test_data_frame_with_xlsx(self) -> None: - with open(self.asset_dir / "data_frame_out.json", encoding="utf8") as fh_out: + def test_add_df_with_xlsx(self) -> None: + with open(self.asset_dir / "df_out.json", encoding="utf8") as fh_out: fc_out = json.load(fh_out) fc_out["data"]["series"] = fc_out["data"]["series"][:-1] df = pd.read_excel(self.doc_dir / "music_data.xlsx") data = Data() - data.add_data_frame(df) + data.add_df(df) self.assertEqual( fc_out, data.build(), ) - def test_data_frame_with_googlesheet(self) -> None: - with open(self.asset_dir / "data_frame_out.json", encoding="utf8") as fh_out: + def test_add_df_with_googlesheet(self) -> None: + with open(self.asset_dir / "df_out.json", encoding="utf8") as fh_out: fc_out = json.load(fh_out) fc_out["data"]["series"] = fc_out["data"]["series"][:-1] @@ -64,7 +64,7 @@ def test_data_frame_with_googlesheet(self) -> None: ) data = Data() - data.add_data_frame(df) + data.add_df(df) self.assertEqual( fc_out, data.build(), From 20760f0c98d985bfd7ed26e510c1d67fa8a4aadd Mon Sep 17 00:00:00 2001 From: David Vegh Date: Wed, 2 Aug 2023 11:41:44 +0200 Subject: [PATCH 05/15] Add better data type hints --- pyproject.toml | 2 +- src/ipyvizzu/animation.py | 47 ++++++++++++++----- .../data/converters/pandas_converter.py | 34 ++++++++------ src/ipyvizzu/data/typing_alias.py | 22 +++++++++ tests/test_animation.py | 6 ++- 5 files changed, 83 insertions(+), 28 deletions(-) create mode 100644 src/ipyvizzu/data/typing_alias.py diff --git a/pyproject.toml b/pyproject.toml index 130a35d1..00ec7a81 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -228,4 +228,4 @@ path = "src/ipyvizzu/__version__.py" [tool.pylint.messages-control] disable = ["fixme"] -good-names= ["i", "df"] \ No newline at end of file +good-names= ["i", "df"] diff --git a/src/ipyvizzu/animation.py b/src/ipyvizzu/animation.py index 032b1f1b..7bd4910b 100644 --- a/src/ipyvizzu/animation.py +++ b/src/ipyvizzu/animation.py @@ -3,9 +3,17 @@ import abc from os import PathLike import json -from typing import Optional, Union, List, Dict, Any, Tuple +from typing import List, Optional, Tuple, Union import jsonschema # type: ignore +from ipyvizzu.data.typing_alias import ( + DimensionValue, + NestedMeasureValues, + MeasureValue, + Record, + Series, + SeriesValues, +) from ipyvizzu.data.converters.pandas_converter import PandasDataFrameConverter from ipyvizzu.json import RawJavaScript, RawJavaScriptEncoder from ipyvizzu.schema import DATA_SCHEMA @@ -122,7 +130,7 @@ class instance which has been created from a json file. with open(filename, "r", encoding="utf8") as file_desc: return cls(json.load(file_desc)) - def add_record(self, record: list) -> None: + def add_record(self, record: Record) -> None: """ A method for adding a record to an existing [Data][ipyvizzu.animation.Data] class instance. @@ -140,7 +148,7 @@ def add_record(self, record: list) -> None: self._add_value("records", record) - def add_records(self, records: List[list]) -> None: + def add_records(self, records: List[Record]) -> None: """ A method for adding records to an existing [Data][ipyvizzu.animation.Data] class instance. @@ -163,7 +171,9 @@ def add_records(self, records: List[list]) -> None: list(map(self.add_record, records)) - def add_series(self, name: str, values: Optional[list] = None, **kwargs) -> None: + def add_series( + self, name: str, values: Optional[SeriesValues] = None, **kwargs + ) -> None: """ A method for adding a series to an existing [Data][ipyvizzu.animation.Data] class instance. @@ -198,7 +208,7 @@ def add_series(self, name: str, values: Optional[list] = None, **kwargs) -> None self._add_named_value("series", name, values, **kwargs) - def add_series_list(self, series: List[Dict[str, Union[str, List[Any]]]]) -> None: + def add_series_list(self, series: List[Series]) -> None: """ A method for adding list of series to an existing [Data][ipyvizzu.animation.Data] class instance. @@ -210,7 +220,9 @@ def add_series_list(self, series: List[Dict[str, Union[str, List[Any]]]]) -> Non if series: self.setdefault("series", []).extend(series) - def add_dimension(self, name: str, values: Optional[list] = None, **kwargs) -> None: + def add_dimension( + self, name: str, values: Optional[List[DimensionValue]] = None, **kwargs + ) -> None: """ A method for adding a dimension to an existing [Data][ipyvizzu.animation.Data] class instance. @@ -229,7 +241,9 @@ def add_dimension(self, name: str, values: Optional[list] = None, **kwargs) -> N self._add_named_value("dimensions", name, values, **kwargs) - def add_measure(self, name: str, values: Optional[list] = None, **kwargs) -> None: + def add_measure( + self, name: str, values: Optional[NestedMeasureValues] = None, **kwargs + ) -> None: """ A method for adding a measure to an existing [Data][ipyvizzu.animation.Data] class instance. @@ -257,8 +271,8 @@ def add_measure(self, name: str, values: Optional[list] = None, **kwargs) -> Non def add_df( self, df: Union["pd.DataFrame", "pd.Series"], # type: ignore - default_measure_value: Optional[Any] = 0, - default_dimension_value: Optional[Any] = "", + default_measure_value: Optional[MeasureValue] = 0, + default_dimension_value: Optional[DimensionValue] = "", include_index: Optional[str] = None, ) -> None: """ @@ -298,8 +312,8 @@ def add_df( def add_data_frame( self, data_frame: Union["pd.DataFrame", "pd.Series"], # type: ignore - default_measure_value: Optional[Any] = 0, - default_dimension_value: Optional[Any] = "", + default_measure_value: Optional[MeasureValue] = 0, + default_dimension_value: Optional[DimensionValue] = "", ) -> None: """ [Deprecated] Add a `pandas` `DataFrame` or `Series` to an existing @@ -372,7 +386,16 @@ def add_data_frame_index( self.add_df_index(data_frame, name) def _add_named_value( - self, dest: str, name: str, values: Optional[list] = None, **kwargs + self, + dest: str, + name: str, + values: Optional[ + Union[ + SeriesValues, + NestedMeasureValues, + ] + ] = None, + **kwargs, ) -> None: value = {"name": name, **kwargs} diff --git a/src/ipyvizzu/data/converters/pandas_converter.py b/src/ipyvizzu/data/converters/pandas_converter.py index 929a3713..6dc2260d 100644 --- a/src/ipyvizzu/data/converters/pandas_converter.py +++ b/src/ipyvizzu/data/converters/pandas_converter.py @@ -4,8 +4,14 @@ into a list of dictionaries representing series. """ -from typing import Optional, Any, List, Dict, Union, Tuple - +from typing import Optional, List, Tuple, Union + +from ipyvizzu.data.typing_alias import ( + DimensionValue, + MeasureValue, + Series, + SeriesValues, +) from ipyvizzu.data.infer_type import InferType @@ -34,8 +40,8 @@ class PandasDataFrameConverter: def __init__( self, df: Union["pd.DataFrame", "pd.Series"], # type: ignore - default_measure_value: Optional[Any] = 0, - default_dimension_value: Optional[Any] = "", + default_measure_value: Optional[MeasureValue] = 0, + default_dimension_value: Optional[DimensionValue] = "", include_index: Optional[str] = None, ) -> None: self._df = self._get_df(df) @@ -61,7 +67,7 @@ def _get_df(self, df: Union["pd.DataFrame", "pd.Series"]) -> "pd.DataFrame": # "pandas is not available. Please install pandas to use this feature." ) from error - def get_series_list_from_columns(self) -> List[Dict[str, Union[str, List[Any]]]]: + def get_series_list_from_columns(self) -> List[Series]: """ Convert the `DataFrame` columns to a list of dictionaries representing series. @@ -78,7 +84,7 @@ def get_series_list_from_columns(self) -> List[Dict[str, Union[str, List[Any]]]] series_list.append(index_series) return series_list - def get_series_from_index(self) -> Optional[Dict[str, Union[str, List[Any]]]]: + def get_series_from_index(self) -> Optional[Series]: """ Convert the `DataFrame` index to a dictionary representing a series, if `include_index` is provided. @@ -94,14 +100,14 @@ def get_series_from_index(self) -> Optional[Dict[str, Union[str, List[Any]]]]: values, infer_type = self._get_column_data(self._df.index) return self._convert_to_series(name, values, infer_type) - def _get_series_from_column( - self, column_name: str - ) -> Dict[str, Union[str, List[Any]]]: + def _get_series_from_column(self, column_name: str) -> Series: column = self._df[column_name] values, infer_type = self._get_column_data(column) return self._convert_to_series(column_name, values, infer_type) - def _get_column_data(self, column: "pd.Series") -> Tuple[List[Any], InferType]: # type: ignore + def _get_column_data( + self, column: "pd.Series" # type: ignore + ) -> Tuple[SeriesValues, InferType]: try: from pandas.api.types import ( # pylint: disable=import-outside-toplevel is_numeric_dtype, @@ -117,7 +123,7 @@ def _get_column_data(self, column: "pd.Series") -> Tuple[List[Any], InferType]: def _get_measure_column_data( self, column: "pd.Series" # type: ignore - ) -> Tuple[List[Any], InferType]: + ) -> Tuple[List[MeasureValue], InferType]: return ( column.fillna(self._default_measure_value).astype(float).values.tolist(), InferType.MEASURE, @@ -125,15 +131,15 @@ def _get_measure_column_data( def _get_dimension_column_data( self, column: "pd.Series" # type: ignore - ) -> Tuple[List[Any], InferType]: + ) -> Tuple[List[DimensionValue], InferType]: return ( column.fillna(self._default_dimension_value).astype(str).values.tolist(), InferType.DIMENSION, ) def _convert_to_series( - self, name: str, values: List[Any], infer_type: InferType - ) -> Dict[str, Union[str, List[Any]]]: + self, name: str, values: SeriesValues, infer_type: InferType + ) -> Series: return { "name": name, "values": values, diff --git a/src/ipyvizzu/data/typing_alias.py b/src/ipyvizzu/data/typing_alias.py new file mode 100644 index 00000000..3754e0ae --- /dev/null +++ b/src/ipyvizzu/data/typing_alias.py @@ -0,0 +1,22 @@ +""" +This module provides typing aliases for data used in ipyvizzu. +""" + +from typing import Dict, List, Sequence, Union + + +DimensionValue = str + +MeasureValue = Union[int, float] + +NestedMeasureValues = Union[MeasureValue, List["NestedMeasureValues"]] + +Value = Union[DimensionValue, MeasureValue] + +RecordValues = Union[DimensionValue, MeasureValue] + +Record = List[RecordValues] + +SeriesValues = Union[Sequence[DimensionValue], Sequence[MeasureValue]] + +Series = Dict[str, Union[str, SeriesValues]] diff --git a/tests/test_animation.py b/tests/test_animation.py index fbaa3b1e..e60121fa 100644 --- a/tests/test_animation.py +++ b/tests/test_animation.py @@ -2,10 +2,14 @@ import json import pathlib +from typing import List import unittest + import jsonschema # type: ignore import pandas as pd +from ipyvizzu.data.typing_alias import Record + from tests import ( PlainAnimation, Data, @@ -173,7 +177,7 @@ def test_series_without_values(self) -> None: self.data.add_series("Genres", type="dimension") self.data.add_series("Kinds", type="dimension") self.data.add_series("Popularity", type="measure") - records = [["Rock", "Hard", 96], ["Pop", "Hard", 114]] + records: List[Record] = [["Rock", "Hard", 96], ["Pop", "Hard", 114]] self.data.add_records(records) self.assertEqual( { From 11eebaff001197c06dcaaa86f05d0121be13d261 Mon Sep 17 00:00:00 2001 From: David Vegh Date: Wed, 2 Aug 2023 11:58:06 +0200 Subject: [PATCH 06/15] Fix RecordValue type hint --- src/ipyvizzu/data/typing_alias.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/ipyvizzu/data/typing_alias.py b/src/ipyvizzu/data/typing_alias.py index 3754e0ae..3ba61cf8 100644 --- a/src/ipyvizzu/data/typing_alias.py +++ b/src/ipyvizzu/data/typing_alias.py @@ -11,11 +11,9 @@ NestedMeasureValues = Union[MeasureValue, List["NestedMeasureValues"]] -Value = Union[DimensionValue, MeasureValue] +RecordValue = Union[DimensionValue, MeasureValue] -RecordValues = Union[DimensionValue, MeasureValue] - -Record = List[RecordValues] +Record = List[RecordValue] SeriesValues = Union[Sequence[DimensionValue], Sequence[MeasureValue]] From 7ba32a96fabf5532f45173160db264474667e613 Mon Sep 17 00:00:00 2001 From: David Vegh Date: Wed, 2 Aug 2023 12:41:51 +0200 Subject: [PATCH 07/15] Remove pandas from dependencies, add to extras --- pdm.lock | 62 +++++++++---------- pyproject.toml | 8 ++- .../data/converters/pandas_converter.py | 42 ++++++------- 3 files changed, 56 insertions(+), 56 deletions(-) diff --git a/pdm.lock b/pdm.lock index a994bbfc..8109fb54 100644 --- a/pdm.lock +++ b/pdm.lock @@ -6,7 +6,7 @@ groups = ["codequality", "docs", "env", "packagedeps", "packagetool"] cross_platform = true static_urls = false lock_version = "4.3" -content_hash = "sha256:6c32194cdc472c817bc25e4c888f8e4d0788cd98a86444b1bb445b936ca8d6d9" +content_hash = "sha256:5be8b82d2ae3db81267ccff5423f8bfb8f5197cb0b3b4ce2dfca412dc96be7ea" [[package]] name = "adagio" @@ -431,12 +431,12 @@ files = [ [[package]] name = "chardet" -version = "5.1.0" +version = "5.2.0" requires_python = ">=3.7" summary = "Universal encoding detector for Python 3" files = [ - {file = "chardet-5.1.0-py3-none-any.whl", hash = "sha256:362777fb014af596ad31334fde1e8c327dfdb076e1960d1694662d46a6917ab9"}, - {file = "chardet-5.1.0.tar.gz", hash = "sha256:0d62712b956bc154f85fb0a266e2a3c5913c2967e00348701b32411d6def31e5"}, + {file = "chardet-5.2.0-py3-none-any.whl", hash = "sha256:e1cf59446890a00105fe7b7912492ea04b6e6f06d4b742b2c788469e34c82970"}, + {file = "chardet-5.2.0.tar.gz", hash = "sha256:1b3b6ff479a8c414bc3fa2c0852995695c4a026dcd6d0633b2dd092ca39c1cf7"}, ] [[package]] @@ -561,36 +561,36 @@ files = [ [[package]] name = "cryptography" -version = "41.0.2" +version = "41.0.3" requires_python = ">=3.7" summary = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." dependencies = [ "cffi>=1.12", ] files = [ - {file = "cryptography-41.0.2-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:01f1d9e537f9a15b037d5d9ee442b8c22e3ae11ce65ea1f3316a41c78756b711"}, - {file = "cryptography-41.0.2-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:079347de771f9282fbfe0e0236c716686950c19dee1b76240ab09ce1624d76d7"}, - {file = "cryptography-41.0.2-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:439c3cc4c0d42fa999b83ded80a9a1fb54d53c58d6e59234cfe97f241e6c781d"}, - {file = "cryptography-41.0.2-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f14ad275364c8b4e525d018f6716537ae7b6d369c094805cae45300847e0894f"}, - {file = "cryptography-41.0.2-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:84609ade00a6ec59a89729e87a503c6e36af98ddcd566d5f3be52e29ba993182"}, - {file = "cryptography-41.0.2-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:49c3222bb8f8e800aead2e376cbef687bc9e3cb9b58b29a261210456a7783d83"}, - {file = "cryptography-41.0.2-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:d73f419a56d74fef257955f51b18d046f3506270a5fd2ac5febbfa259d6c0fa5"}, - {file = "cryptography-41.0.2-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:2a034bf7d9ca894720f2ec1d8b7b5832d7e363571828037f9e0c4f18c1b58a58"}, - {file = "cryptography-41.0.2-cp37-abi3-win32.whl", hash = "sha256:d124682c7a23c9764e54ca9ab5b308b14b18eba02722b8659fb238546de83a76"}, - {file = "cryptography-41.0.2-cp37-abi3-win_amd64.whl", hash = "sha256:9c3fe6534d59d071ee82081ca3d71eed3210f76ebd0361798c74abc2bcf347d4"}, - {file = "cryptography-41.0.2-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:a719399b99377b218dac6cf547b6ec54e6ef20207b6165126a280b0ce97e0d2a"}, - {file = "cryptography-41.0.2-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:182be4171f9332b6741ee818ec27daff9fb00349f706629f5cbf417bd50e66fd"}, - {file = "cryptography-41.0.2-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:7a9a3bced53b7f09da251685224d6a260c3cb291768f54954e28f03ef14e3766"}, - {file = "cryptography-41.0.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:f0dc40e6f7aa37af01aba07277d3d64d5a03dc66d682097541ec4da03cc140ee"}, - {file = "cryptography-41.0.2-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:674b669d5daa64206c38e507808aae49904c988fa0a71c935e7006a3e1e83831"}, - {file = "cryptography-41.0.2-pp38-pypy38_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:7af244b012711a26196450d34f483357e42aeddb04128885d95a69bd8b14b69b"}, - {file = "cryptography-41.0.2-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:9b6d717393dbae53d4e52684ef4f022444fc1cce3c48c38cb74fca29e1f08eaa"}, - {file = "cryptography-41.0.2-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:192255f539d7a89f2102d07d7375b1e0a81f7478925b3bc2e0549ebf739dae0e"}, - {file = "cryptography-41.0.2-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:f772610fe364372de33d76edcd313636a25684edb94cee53fd790195f5989d14"}, - {file = "cryptography-41.0.2-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:b332cba64d99a70c1e0836902720887fb4529ea49ea7f5462cf6640e095e11d2"}, - {file = "cryptography-41.0.2-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:9a6673c1828db6270b76b22cc696f40cde9043eb90373da5c2f8f2158957f42f"}, - {file = "cryptography-41.0.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:342f3767e25876751e14f8459ad85e77e660537ca0a066e10e75df9c9e9099f0"}, - {file = "cryptography-41.0.2.tar.gz", hash = "sha256:7d230bf856164de164ecb615ccc14c7fc6de6906ddd5b491f3af90d3514c925c"}, + {file = "cryptography-41.0.3-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:652627a055cb52a84f8c448185922241dd5217443ca194d5739b44612c5e6507"}, + {file = "cryptography-41.0.3-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:8f09daa483aedea50d249ef98ed500569841d6498aa9c9f4b0531b9964658922"}, + {file = "cryptography-41.0.3-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4fd871184321100fb400d759ad0cddddf284c4b696568204d281c902fc7b0d81"}, + {file = "cryptography-41.0.3-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:84537453d57f55a50a5b6835622ee405816999a7113267739a1b4581f83535bd"}, + {file = "cryptography-41.0.3-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:3fb248989b6363906827284cd20cca63bb1a757e0a2864d4c1682a985e3dca47"}, + {file = "cryptography-41.0.3-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:42cb413e01a5d36da9929baa9d70ca90d90b969269e5a12d39c1e0d475010116"}, + {file = "cryptography-41.0.3-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:aeb57c421b34af8f9fe830e1955bf493a86a7996cc1338fe41b30047d16e962c"}, + {file = "cryptography-41.0.3-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:6af1c6387c531cd364b72c28daa29232162010d952ceb7e5ca8e2827526aceae"}, + {file = "cryptography-41.0.3-cp37-abi3-win32.whl", hash = "sha256:0d09fb5356f975974dbcb595ad2d178305e5050656affb7890a1583f5e02a306"}, + {file = "cryptography-41.0.3-cp37-abi3-win_amd64.whl", hash = "sha256:a983e441a00a9d57a4d7c91b3116a37ae602907a7618b882c8013b5762e80574"}, + {file = "cryptography-41.0.3-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5259cb659aa43005eb55a0e4ff2c825ca111a0da1814202c64d28a985d33b087"}, + {file = "cryptography-41.0.3-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:67e120e9a577c64fe1f611e53b30b3e69744e5910ff3b6e97e935aeb96005858"}, + {file = "cryptography-41.0.3-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:7efe8041897fe7a50863e51b77789b657a133c75c3b094e51b5e4b5cec7bf906"}, + {file = "cryptography-41.0.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:ce785cf81a7bdade534297ef9e490ddff800d956625020ab2ec2780a556c313e"}, + {file = "cryptography-41.0.3-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:57a51b89f954f216a81c9d057bf1a24e2f36e764a1ca9a501a6964eb4a6800dd"}, + {file = "cryptography-41.0.3-pp38-pypy38_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:4c2f0d35703d61002a2bbdcf15548ebb701cfdd83cdc12471d2bae80878a4207"}, + {file = "cryptography-41.0.3-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:23c2d778cf829f7d0ae180600b17e9fceea3c2ef8b31a99e3c694cbbf3a24b84"}, + {file = "cryptography-41.0.3-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:95dd7f261bb76948b52a5330ba5202b91a26fbac13ad0e9fc8a3ac04752058c7"}, + {file = "cryptography-41.0.3-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:41d7aa7cdfded09b3d73a47f429c298e80796c8e825ddfadc84c8a7f12df212d"}, + {file = "cryptography-41.0.3-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:d0d651aa754ef58d75cec6edfbd21259d93810b73f6ec246436a21b7841908de"}, + {file = "cryptography-41.0.3-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:ab8de0d091acbf778f74286f4989cf3d1528336af1b59f3e5d2ebca8b5fe49e1"}, + {file = "cryptography-41.0.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:a74fbcdb2a0d46fe00504f571a2a540532f4c188e6ccf26f1f178480117b33c4"}, + {file = "cryptography-41.0.3.tar.gz", hash = "sha256:6d192741113ef5e30d89dcb5b956ef4e1578f304708701b8b73d38e3e1461f34"}, ] [[package]] @@ -2927,7 +2927,7 @@ files = [ [[package]] name = "rich" -version = "13.5.1" +version = "13.5.2" requires_python = ">=3.7.0" summary = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" dependencies = [ @@ -2935,8 +2935,8 @@ dependencies = [ "pygments<3.0.0,>=2.13.0", ] files = [ - {file = "rich-13.5.1-py3-none-any.whl", hash = "sha256:b97381b204a206e1be618f5e1215a57174a1a7732490b3bf6668cf41d30bc72d"}, - {file = "rich-13.5.1.tar.gz", hash = "sha256:881653ee7037803559d8eae98f145e0a4c4b0ec3ff0300d2cc8d479c71fc6819"}, + {file = "rich-13.5.2-py3-none-any.whl", hash = "sha256:146a90b3b6b47cac4a73c12866a499e9817426423f57c5a66949c086191a8808"}, + {file = "rich-13.5.2.tar.gz", hash = "sha256:fb9d6c0a0f643c99eed3875b5377a184132ba9be4d61516a55273d3554d75a39"}, ] [[package]] diff --git a/pyproject.toml b/pyproject.toml index 00ec7a81..af4c67f6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -10,7 +10,6 @@ requires-python = ">=3.6" dependencies = [ "IPython", "jsonschema", - "pandas", ] license = {text = "Apache-2.0"} classifiers = [ @@ -38,6 +37,9 @@ keywords = [ ] [project.optional-dependencies] +pandas = [ + "pandas ; python_version >= '3.6'", +] fugue = [ "fugue >= 0.8.1 ; python_version >= '3.7'", ] @@ -143,12 +145,15 @@ deps = [testenv:py{36}] setenv = COVERAGE_FILE = .tox/py36/.coverage +extras = + pandas commands = python -m coverage run --branch --source ipyvizzu -m unittest discover tests python -m coverage report -m --fail-under=100 --omit src/ipyvizzu/integrations/fugue.py [testenv:py{37,38,39,311}] extras = + pandas fugue commands = python -m coverage run --data-file .tox/{envname}/.coverage --branch --source ipyvizzu -m unittest discover tests @@ -156,6 +161,7 @@ commands = [testenv:py{310}] extras = + pandas fugue commands = python -m coverage run --data-file .tox/{envname}/.coverage --branch --source ipyvizzu -m unittest discover tests diff --git a/src/ipyvizzu/data/converters/pandas_converter.py b/src/ipyvizzu/data/converters/pandas_converter.py index 6dc2260d..4789c086 100644 --- a/src/ipyvizzu/data/converters/pandas_converter.py +++ b/src/ipyvizzu/data/converters/pandas_converter.py @@ -4,15 +4,16 @@ into a list of dictionaries representing series. """ -from typing import Optional, List, Tuple, Union +from types import ModuleType +from typing import List, Optional, Tuple, Union +from ipyvizzu.data.infer_type import InferType from ipyvizzu.data.typing_alias import ( DimensionValue, MeasureValue, Series, SeriesValues, ) -from ipyvizzu.data.infer_type import InferType class PandasDataFrameConverter: @@ -44,29 +45,31 @@ def __init__( default_dimension_value: Optional[DimensionValue] = "", include_index: Optional[str] = None, ) -> None: + self._pd = self._get_pandas() self._df = self._get_df(df) self._default_measure_value = default_measure_value self._default_dimension_value = default_dimension_value self._include_index = include_index - def _get_df(self, df: Union["pd.DataFrame", "pd.Series"]) -> "pd.DataFrame": # type: ignore + def _get_pandas(self) -> ModuleType: try: import pandas as pd # pylint: disable=import-outside-toplevel - if isinstance(df, pd.DataFrame): - return df - if isinstance(df, pd.Series): - return pd.DataFrame(df) - if df is None: - return pd.DataFrame() - raise TypeError( - "df must be an instance of pandas.DataFrame or pandas.Series" - ) + return pd except ImportError as error: raise ImportError( "pandas is not available. Please install pandas to use this feature." ) from error + def _get_df(self, df: Union["pd.DataFrame", "pd.Series"]) -> "pd.DataFrame": # type: ignore + if isinstance(df, self._pd.DataFrame): + return df + if isinstance(df, self._pd.Series): + return self._pd.DataFrame(df) + if df is None: + return self._pd.DataFrame() + raise TypeError("df must be an instance of pandas.DataFrame or pandas.Series") + def get_series_list_from_columns(self) -> List[Series]: """ Convert the `DataFrame` columns to a list of dictionaries representing series. @@ -108,18 +111,9 @@ def _get_series_from_column(self, column_name: str) -> Series: def _get_column_data( self, column: "pd.Series" # type: ignore ) -> Tuple[SeriesValues, InferType]: - try: - from pandas.api.types import ( # pylint: disable=import-outside-toplevel - is_numeric_dtype, - ) - - if is_numeric_dtype(column.dtype): - return self._get_measure_column_data(column) - return self._get_dimension_column_data(column) - except ImportError as error: - raise ImportError( - "pandas is not available. Please install pandas to use this feature." - ) from error + if self._pd.api.types.is_numeric_dtype(column.dtype): + return self._get_measure_column_data(column) + return self._get_dimension_column_data(column) def _get_measure_column_data( self, column: "pd.Series" # type: ignore From 2e37584617690aa1a9dfb64ce35117e7739124b9 Mon Sep 17 00:00:00 2001 From: David Vegh Date: Wed, 2 Aug 2023 12:55:44 +0200 Subject: [PATCH 08/15] Fix typing for pandas converter --- src/ipyvizzu/animation.py | 8 ++++---- src/ipyvizzu/data/converters/pandas_converter.py | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/ipyvizzu/animation.py b/src/ipyvizzu/animation.py index 7bd4910b..22af5bb7 100644 --- a/src/ipyvizzu/animation.py +++ b/src/ipyvizzu/animation.py @@ -270,7 +270,7 @@ def add_measure( def add_df( self, - df: Union["pd.DataFrame", "pd.Series"], # type: ignore + df: Union["pd.DataFrame", "pd.Series", type(None)], # type: ignore default_measure_value: Optional[MeasureValue] = 0, default_dimension_value: Optional[DimensionValue] = "", include_index: Optional[str] = None, @@ -311,7 +311,7 @@ def add_df( def add_data_frame( self, - data_frame: Union["pd.DataFrame", "pd.Series"], # type: ignore + data_frame: Union["pd.DataFrame", "pd.Series", type(None)], # type: ignore default_measure_value: Optional[MeasureValue] = 0, default_dimension_value: Optional[DimensionValue] = "", ) -> None: @@ -334,7 +334,7 @@ def add_data_frame( def add_df_index( self, - df: Union["pd.DataFrame", "pd.Series"], # type: ignore + df: Union["pd.DataFrame", "pd.Series", type(None)], # type: ignore name: str, ) -> None: """ @@ -367,7 +367,7 @@ def add_df_index( def add_data_frame_index( self, - data_frame: Union["pd.DataFrame", "pd.Series"], # type: ignore + data_frame: Union["pd.DataFrame", "pd.Series", type(None)], # type: ignore name: str, ) -> None: """ diff --git a/src/ipyvizzu/data/converters/pandas_converter.py b/src/ipyvizzu/data/converters/pandas_converter.py index 4789c086..fb0b33e6 100644 --- a/src/ipyvizzu/data/converters/pandas_converter.py +++ b/src/ipyvizzu/data/converters/pandas_converter.py @@ -40,7 +40,7 @@ class PandasDataFrameConverter: def __init__( self, - df: Union["pd.DataFrame", "pd.Series"], # type: ignore + df: Union["pd.DataFrame", "pd.Series", type(None)], # type: ignore default_measure_value: Optional[MeasureValue] = 0, default_dimension_value: Optional[DimensionValue] = "", include_index: Optional[str] = None, @@ -66,7 +66,7 @@ def _get_df(self, df: Union["pd.DataFrame", "pd.Series"]) -> "pd.DataFrame": # return df if isinstance(df, self._pd.Series): return self._pd.DataFrame(df) - if df is None: + if isinstance(df, type(None)): return self._pd.DataFrame() raise TypeError("df must be an instance of pandas.DataFrame or pandas.Series") From f221c49e4fb30e5887af6877b3dacab6ff981e08 Mon Sep 17 00:00:00 2001 From: David Vegh Date: Wed, 2 Aug 2023 12:58:23 +0200 Subject: [PATCH 09/15] Remove redundant version strict --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index af4c67f6..9d798e45 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -38,7 +38,7 @@ keywords = [ [project.optional-dependencies] pandas = [ - "pandas ; python_version >= '3.6'", + "pandas", ] fugue = [ "fugue >= 0.8.1 ; python_version >= '3.7'", From 10b20881ebe376ed005bd4f89138681d7fc5b26d Mon Sep 17 00:00:00 2001 From: David Vegh Date: Wed, 2 Aug 2023 13:28:06 +0200 Subject: [PATCH 10/15] Replace ty[e(None) to Optional --- src/ipyvizzu/animation.py | 8 ++++---- src/ipyvizzu/data/converters/pandas_converter.py | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/ipyvizzu/animation.py b/src/ipyvizzu/animation.py index 22af5bb7..54770aca 100644 --- a/src/ipyvizzu/animation.py +++ b/src/ipyvizzu/animation.py @@ -270,7 +270,7 @@ def add_measure( def add_df( self, - df: Union["pd.DataFrame", "pd.Series", type(None)], # type: ignore + df: Optional[Union["pd.DataFrame", "pd.Series"]], # type: ignore default_measure_value: Optional[MeasureValue] = 0, default_dimension_value: Optional[DimensionValue] = "", include_index: Optional[str] = None, @@ -311,7 +311,7 @@ def add_df( def add_data_frame( self, - data_frame: Union["pd.DataFrame", "pd.Series", type(None)], # type: ignore + data_frame: Optional[Union["pd.DataFrame", "pd.Series"]], # type: ignore default_measure_value: Optional[MeasureValue] = 0, default_dimension_value: Optional[DimensionValue] = "", ) -> None: @@ -334,7 +334,7 @@ def add_data_frame( def add_df_index( self, - df: Union["pd.DataFrame", "pd.Series", type(None)], # type: ignore + df: Optional[Union["pd.DataFrame", "pd.Series"]], # type: ignore name: str, ) -> None: """ @@ -367,7 +367,7 @@ def add_df_index( def add_data_frame_index( self, - data_frame: Union["pd.DataFrame", "pd.Series", type(None)], # type: ignore + data_frame: Optional[Union["pd.DataFrame", "pd.Series"]], # type: ignore name: str, ) -> None: """ diff --git a/src/ipyvizzu/data/converters/pandas_converter.py b/src/ipyvizzu/data/converters/pandas_converter.py index fb0b33e6..7416462e 100644 --- a/src/ipyvizzu/data/converters/pandas_converter.py +++ b/src/ipyvizzu/data/converters/pandas_converter.py @@ -40,7 +40,7 @@ class PandasDataFrameConverter: def __init__( self, - df: Union["pd.DataFrame", "pd.Series", type(None)], # type: ignore + df: Optional[Union["pd.DataFrame", "pd.Series"]], # type: ignore default_measure_value: Optional[MeasureValue] = 0, default_dimension_value: Optional[DimensionValue] = "", include_index: Optional[str] = None, From 389d7e3be362641c5efed3f980d4596a0139fa05 Mon Sep 17 00:00:00 2001 From: David Vegh Date: Wed, 2 Aug 2023 14:25:55 +0200 Subject: [PATCH 11/15] Add deprication warning for old df funcitons --- src/ipyvizzu/__init__.py | 9 +- src/ipyvizzu/animation.py | 48 ++++-- .../data/converters/pandas_converter.py | 8 +- tests/test_animation.py | 156 ++++++++++++++++-- 4 files changed, 188 insertions(+), 33 deletions(-) diff --git a/src/ipyvizzu/__init__.py b/src/ipyvizzu/__init__.py index 9211a557..d2bdf46c 100644 --- a/src/ipyvizzu/__init__.py +++ b/src/ipyvizzu/__init__.py @@ -16,7 +16,6 @@ `ipyvizzu` package imports the following objects in `__init__.py`: * [Chart][ipyvizzu.chart.Chart] -* [InferType][ipyvizzu.data.infer_type.InferType] * [Data][ipyvizzu.animation.Data] * [Config][ipyvizzu.animation.Config] * [Style][ipyvizzu.animation.Style] @@ -27,6 +26,8 @@ * [PlainAnimation][ipyvizzu.animation.PlainAnimation] * [AnimationMerger][ipyvizzu.animation.AnimationMerger] * [AnimationControl][ipyvizzu.animationcontrol.AnimationControl] +* [InferType][ipyvizzu.data.infer_type.InferType] +* [PandasDataFrameConverter][data.converters.pandas_converter.PandasDataFrameConverter] * [Animate][ipyvizzu.method.Animate] * [Feature][ipyvizzu.method.Feature] * [Store][ipyvizzu.method.Store] @@ -43,7 +44,6 @@ """ from .chart import Chart -from .data.infer_type import InferType from .animation import ( AbstractAnimation, PlainAnimation, @@ -56,6 +56,8 @@ AnimationMerger, ) from .animationcontrol import AnimationControl +from .data.converters.pandas_converter import PandasDataFrameConverter +from .data.infer_type import InferType from .method import Method, Animate, Feature, Store, EventOn, EventOff, Log from .json import RawJavaScript, RawJavaScriptEncoder from .template import ChartProperty, DisplayTarget, DisplayTemplate @@ -71,7 +73,6 @@ "Keyframe", "Snapshot", "Animation", - "InferType", "AbstractAnimation", "PlainAnimation", "AnimationMerger", @@ -82,6 +83,8 @@ "EventOff", "Log", "AnimationControl", + "PandasDataFrameConverter", + "InferType", "Method", "EventHandler", "RawJavaScript", diff --git a/src/ipyvizzu/animation.py b/src/ipyvizzu/animation.py index 54770aca..c3975a63 100644 --- a/src/ipyvizzu/animation.py +++ b/src/ipyvizzu/animation.py @@ -1,11 +1,14 @@ """A module for working with chart animations.""" import abc -from os import PathLike import json +from os import PathLike from typing import List, Optional, Tuple, Union +import warnings + import jsonschema # type: ignore +from ipyvizzu.data.converters.pandas_converter import PandasDataFrameConverter from ipyvizzu.data.typing_alias import ( DimensionValue, NestedMeasureValues, @@ -14,7 +17,6 @@ Series, SeriesValues, ) -from ipyvizzu.data.converters.pandas_converter import PandasDataFrameConverter from ipyvizzu.json import RawJavaScript, RawJavaScriptEncoder from ipyvizzu.schema import DATA_SCHEMA @@ -316,11 +318,13 @@ def add_data_frame( default_dimension_value: Optional[DimensionValue] = "", ) -> None: """ - [Deprecated] Add a `pandas` `DataFrame` or `Series` to an existing + [Deprecated] This function is deprecated and will be removed in future versions. + Use [add_df][ipyvizzu.animation.Data.add_df] function instead. + + Add a `pandas` `DataFrame` or `Series` to an existing [Data][ipyvizzu.animation.Data] class instance. - This function is kept for backward compatibility - and calls the `add_df` method with the same arguments. + Args: data_frame: @@ -330,12 +334,21 @@ def add_data_frame( default_dimension_value: The default dimension value to fill empty values. Defaults to an empty string. """ + + # pylint: disable=line-too-long + + reference = "https://ipyvizzu.vizzuhq.com/0.16/reference/ipyvizzu/animation/#ipyvizzu.animation.Data.add_df" + warnings.warn( + f"'add_data_frame' is deprecated and will be removed in future versions. Use 'add_df' instead - see {reference}", + DeprecationWarning, + stacklevel=2, + ) self.add_df(data_frame, default_measure_value, default_dimension_value) def add_df_index( self, df: Optional[Union["pd.DataFrame", "pd.Series"]], # type: ignore - name: str, + column_name: str = "Index", ) -> None: """ Add the index of a `pandas` `DataFrame` as a series to an existing @@ -344,8 +357,8 @@ def add_df_index( Args: df: The `pandas` `DataFrame` or `Series` from which to extract the index. - name: - The name of the index series. + column_name: + Name for the index column to add as a series. Example: Adding a data frame's index to a @@ -360,7 +373,7 @@ def add_df_index( data.add_df(df) """ - converter = PandasDataFrameConverter(df, include_index=name) + converter = PandasDataFrameConverter(df, include_index=column_name) index_series = converter.get_series_from_index() if index_series: self.add_series(**index_series) # type: ignore @@ -371,11 +384,11 @@ def add_data_frame_index( name: str, ) -> None: """ - [Deprecated] Add the index of a `pandas` `DataFrame` as a series to an existing - [Data][ipyvizzu.animation.Data] class instance. + [Deprecated] This function is deprecated and will be removed in future versions. + Use [add_df_index][ipyvizzu.animation.Data.add_df_index] function instead. - This function is kept for backward compatibility - and calls the `add_df_index` method with the same arguments. + Add the index of a `pandas` `DataFrame` as a series to an existing + [Data][ipyvizzu.animation.Data] class instance. Args: data_frame: @@ -383,6 +396,15 @@ def add_data_frame_index( name: The name of the index series. """ + + # pylint: disable=line-too-long + + reference = "https://ipyvizzu.vizzuhq.com/0.16/reference/ipyvizzu/animation/#ipyvizzu.animation.Data.add_df_index" + warnings.warn( + f"'add_data_frame_index' is deprecated and will be removed in future versions. Use 'add_df_index' instead - see {reference}", + DeprecationWarning, + stacklevel=2, + ) self.add_df_index(data_frame, name) def _add_named_value( diff --git a/src/ipyvizzu/data/converters/pandas_converter.py b/src/ipyvizzu/data/converters/pandas_converter.py index 7416462e..c1896926 100644 --- a/src/ipyvizzu/data/converters/pandas_converter.py +++ b/src/ipyvizzu/data/converters/pandas_converter.py @@ -56,7 +56,7 @@ def _get_pandas(self) -> ModuleType: import pandas as pd # pylint: disable=import-outside-toplevel return pd - except ImportError as error: + except ImportError as error: # pragma: no cover raise ImportError( "pandas is not available. Please install pandas to use this feature." ) from error @@ -80,11 +80,11 @@ def get_series_list_from_columns(self) -> List[Series]: """ series_list = [] - for name in self._df.columns: - series_list.append(self._get_series_from_column(name)) index_series = self.get_series_from_index() if index_series: series_list.append(index_series) + for name in self._df.columns: + series_list.append(self._get_series_from_column(name)) return series_list def get_series_from_index(self) -> Optional[Series]: @@ -97,7 +97,7 @@ def get_series_from_index(self) -> Optional[Series]: Returns `None` if `include_index` is not provided. """ - if not self._include_index: + if not self._include_index or self._df.index.empty: return None name = self._include_index values, infer_type = self._get_column_data(self._df.index) diff --git a/tests/test_animation.py b/tests/test_animation.py index e60121fa..4b21f164 100644 --- a/tests/test_animation.py +++ b/tests/test_animation.py @@ -110,12 +110,6 @@ def test_from_json(self) -> None: class TestData(unittest.TestCase): - asset_dir: pathlib.Path - - @classmethod - def setUpClass(cls) -> None: - cls.asset_dir = pathlib.Path(__file__).parent / "assets" - def setUp(self) -> None: self.data = Data() @@ -215,12 +209,23 @@ def test_data_cube(self) -> None: self.data.build(), ) - def test_add_df_with_none(self) -> None: + +class TestDataAddDf(unittest.TestCase): + asset_dir: pathlib.Path + + @classmethod + def setUpClass(cls) -> None: + cls.asset_dir = pathlib.Path(__file__).parent / "assets" + + def setUp(self) -> None: + self.data = Data() + + def test_add_df_with_not_df(self) -> None: data = Data() with self.assertRaises(TypeError): data.add_df("") - def test_df_with_none(self) -> None: + def test_add_df_with_none(self) -> None: data = Data() data.add_df(None) self.assertEqual( @@ -293,16 +298,16 @@ def test_add_df_with_df_and_with_include_index(self) -> None: { "data": { "series": [ - { - "name": "series", - "type": "measure", - "values": [1.0, 2.0, 3.0], - }, { "name": "Index", "type": "dimension", "values": ["x", "y", "z"], }, + { + "name": "series", + "type": "measure", + "values": [1.0, 2.0, 3.0], + }, ] } }, @@ -317,8 +322,133 @@ def test_add_df_with_series_and_with_include_index(self) -> None: { "data": { "series": [ + {"name": "Index", "type": "dimension", "values": ["x", "y"]}, {"name": "series", "type": "measure", "values": [1.0, 2.0]}, + ] + } + }, + data.build(), + ) + + def test_add_df_index(self) -> None: + data = Data() + df = pd.Series({"x": 1, "y": 2, "z": 3}, index=["x", "y"], name="series") + data.add_df_index(df, column_name="Index") + data.add_df(df) + self.assertEqual( + { + "data": { + "series": [ {"name": "Index", "type": "dimension", "values": ["x", "y"]}, + {"name": "series", "type": "measure", "values": [1.0, 2.0]}, + ] + } + }, + data.build(), + ) + + def test_add_df_index_with_none(self) -> None: + data = Data() + df = pd.DataFrame() + data.add_df_index(df, column_name="Index") + data.add_df(df) + self.assertEqual( + {"data": {}}, + data.build(), + ) + + +class TestDataAddDataframe(unittest.TestCase): + asset_dir: pathlib.Path + + @classmethod + def setUpClass(cls) -> None: + cls.asset_dir = pathlib.Path(__file__).parent / "assets" + + def setUp(self) -> None: + self.data = Data() + + def test_add_data_frame_with_not_df(self) -> None: + data = Data() + with self.assertRaises(TypeError): + data.add_data_frame("") + + def test_add_data_frame_with_none(self) -> None: + data = Data() + data.add_data_frame(None) + self.assertEqual( + {"data": {}}, + data.build(), + ) + + def test_add_data_frame_with_df(self) -> None: + with open(self.asset_dir / "df_in.json", encoding="utf8") as fh_in: + fc_in = json.load(fh_in) + with open(self.asset_dir / "df_out.json", encoding="utf8") as fh_out: + fc_out = json.load(fh_out) + + df = pd.DataFrame(fc_in) + df = df.astype({"PopularityAsDimension": str}) + self.data.add_data_frame(df) + self.assertEqual( + fc_out, + self.data.build(), + ) + + def test_add_data_frame_with_df_contains_na(self) -> None: + df = pd.read_csv( + self.asset_dir / "df_na.csv", dtype={"PopularityAsDimension": str} + ) + self.data.add_data_frame(df) + self.assertEqual( + { + "data": { + "series": [ + { + "name": "Popularity", + "type": "measure", + "values": [100.0, 0.0], + }, + { + "name": "PopularityAsDimension", + "type": "dimension", + "values": ["", "100"], + }, + ] + } + }, + self.data.build(), + ) + + def test_add_data_frame_with_series(self) -> None: + data = Data() + data.add_data_frame(pd.Series([1, 2], name="series1")) + data.add_data_frame( + pd.Series({"x": 3, "y": 4, "z": 5}, index=["x", "y"], name="series2") + ) + self.assertEqual( + { + "data": { + "series": [ + {"name": "series1", "type": "measure", "values": [1.0, 2.0]}, + {"name": "series2", "type": "measure", "values": [3.0, 4.0]}, + ] + } + }, + data.build(), + ) + + def test_add_data_frame_index(self) -> None: + data = Data() + df = pd.Series({"x": 1, "y": 2, "z": 3}, index=["x", "y"], name="series") + data.add_data_frame_index(df, name="Index") + data.add_data_frame(df) + self.assertEqual( + { + "data": { + "series": [ + {"name": "Index", "type": "dimension", "values": ["x", "y"]}, + {"name": "series", "type": "measure", "values": [1.0, 2.0]}, ] } }, From ffd3c0cfa197836770b1c13df1f0ec7a6179f927 Mon Sep 17 00:00:00 2001 From: David Vegh Date: Wed, 2 Aug 2023 15:14:43 +0200 Subject: [PATCH 12/15] Fix unit tests, used editable install --- .github/workflows/ci.yml | 8 +------- pyproject.toml | 4 +++- tests/__init__.py | 28 ---------------------------- tests/test_animation.py | 12 ++++++------ tests/test_animationcontrol.py | 3 ++- tests/test_chart.py | 13 +++++++------ tests/test_doc.py | 5 +++-- tests/test_fugue.py | 5 +++-- tests/test_json.py | 2 +- tests/test_method.py | 20 ++++++++++---------- 10 files changed, 36 insertions(+), 64 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6126c606..049f3d92 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -130,12 +130,6 @@ jobs: path: .venv key: cache_dev_py_ubuntu22_${{ hashFiles('pdm.lock') }} - - name: Cache package - uses: actions/cache@v3 - with: - path: dist/ - key: cache_package_${{ github.run_id }} - - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v4 with: @@ -151,7 +145,7 @@ jobs: "3.10") python_test_env="py310";; "3.11") python_test_env="py311";; esac - pdm run test -e "${python_test_env}" --installpkg dist/*.whl + pdm run test -e "${python_test_env}" - name: Cache coverage if: startsWith(matrix.python-version, '3.10') diff --git a/pyproject.toml b/pyproject.toml index 9d798e45..2834089e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -149,9 +149,10 @@ extras = pandas commands = python -m coverage run --branch --source ipyvizzu -m unittest discover tests - python -m coverage report -m --fail-under=100 --omit src/ipyvizzu/integrations/fugue.py + python -m coverage report -m --fail-under=100 --omit .tox/py36/lib/python3.6/site-packages/ipyvizzu/integrations/fugue.py [testenv:py{37,38,39,311}] +package = editable extras = pandas fugue @@ -160,6 +161,7 @@ commands = python -m coverage report --data-file .tox/{envname}/.coverage -m --fail-under=100 [testenv:py{310}] +package = editable extras = pandas fugue diff --git a/tests/__init__.py b/tests/__init__.py index 3288fb4c..735077cd 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -1,29 +1 @@ # pylint: disable=missing-module-docstring,missing-class-docstring,missing-function-docstring - -import sys - -sys.path.insert(0, "./src") - - -from ipyvizzu import ( # pylint: disable=wrong-import-position - Animate, - AnimationMerger, - Chart, - ChartProperty, - Config, - Data, - EventHandler, - EventOff, - EventOn, - Feature, - Keyframe, - Log, - Method, - PlainAnimation, - RawJavaScript, - RawJavaScriptEncoder, - Snapshot, - Animation, - Store, - Style, -) diff --git a/tests/test_animation.py b/tests/test_animation.py index 4b21f164..ff2bf5db 100644 --- a/tests/test_animation.py +++ b/tests/test_animation.py @@ -10,15 +10,15 @@ from ipyvizzu.data.typing_alias import Record -from tests import ( - PlainAnimation, - Data, +from ipyvizzu import ( + Animation, + AnimationMerger, Config, - Style, + Data, Keyframe, + PlainAnimation, Snapshot, - Animation, - AnimationMerger, + Style, ) diff --git a/tests/test_animationcontrol.py b/tests/test_animationcontrol.py index 0a0f6794..88ad625c 100644 --- a/tests/test_animationcontrol.py +++ b/tests/test_animationcontrol.py @@ -3,7 +3,8 @@ import unittest import unittest.mock -from tests import Style +from ipyvizzu import Style + from tests.test_chart import TestChart diff --git a/tests/test_chart.py b/tests/test_chart.py index f24ec177..0e169e38 100644 --- a/tests/test_chart.py +++ b/tests/test_chart.py @@ -1,22 +1,23 @@ # pylint: disable=missing-module-docstring,missing-class-docstring,missing-function-docstring import abc +from typing import Callable import unittest import unittest.mock -from typing import Callable -from tests.normalizer import Normalizer -from tests import ( +from ipyvizzu import ( + Animation, Chart, ChartProperty, - Data, Config, + Data, + EventHandler, Snapshot, Style, - EventHandler, - Animation, ) +from tests.normalizer import Normalizer + class TestChart(unittest.TestCase, abc.ABC): normalizer: Normalizer diff --git a/tests/test_doc.py b/tests/test_doc.py index fd6ebedd..ed379aed 100644 --- a/tests/test_doc.py +++ b/tests/test_doc.py @@ -1,12 +1,13 @@ # pylint: disable=missing-module-docstring,missing-class-docstring,missing-function-docstring -import sys import json import pathlib +import sys import unittest + import pandas as pd -from tests import Data +from ipyvizzu import Data class TestData(unittest.TestCase): diff --git a/tests/test_fugue.py b/tests/test_fugue.py index cd3fe7c9..00f64580 100644 --- a/tests/test_fugue.py +++ b/tests/test_fugue.py @@ -1,10 +1,11 @@ # pylint: disable=missing-module-docstring,missing-class-docstring,missing-function-docstring -import sys -import io from contextlib import redirect_stdout +import io import pathlib +import sys import unittest + import pandas as pd from tests.normalizer import Normalizer diff --git a/tests/test_json.py b/tests/test_json.py index 05a098d0..0a048150 100644 --- a/tests/test_json.py +++ b/tests/test_json.py @@ -3,7 +3,7 @@ import json import unittest -from tests import RawJavaScriptEncoder, RawJavaScript +from ipyvizzu import RawJavaScriptEncoder, RawJavaScript class TestRawJavaScriptEncoder(unittest.TestCase): diff --git a/tests/test_method.py b/tests/test_method.py index 25b15bf9..45b49079 100644 --- a/tests/test_method.py +++ b/tests/test_method.py @@ -2,20 +2,20 @@ import unittest -from tests import ( - Method, +from ipyvizzu import ( Animate, - Feature, - Store, - EventOn, + AnimationMerger, + ChartProperty, + Config, + EventHandler, EventOff, + EventOn, + Feature, Log, - Config, - Style, + Method, Snapshot, - AnimationMerger, - EventHandler, - ChartProperty, + Store, + Style, ) From c7c14777ee28c21f6b0e6a14133b2b4f98fa03ec Mon Sep 17 00:00:00 2001 From: David Vegh Date: Wed, 2 Aug 2023 15:34:47 +0200 Subject: [PATCH 13/15] Test pandas import error --- src/ipyvizzu/__init__.py | 2 +- src/ipyvizzu/data/converters/pandas_converter.py | 2 +- tests/test_animation.py | 15 +++++++++++++++ 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/ipyvizzu/__init__.py b/src/ipyvizzu/__init__.py index d2bdf46c..7dc5ec3c 100644 --- a/src/ipyvizzu/__init__.py +++ b/src/ipyvizzu/__init__.py @@ -27,7 +27,7 @@ * [AnimationMerger][ipyvizzu.animation.AnimationMerger] * [AnimationControl][ipyvizzu.animationcontrol.AnimationControl] * [InferType][ipyvizzu.data.infer_type.InferType] -* [PandasDataFrameConverter][data.converters.pandas_converter.PandasDataFrameConverter] +* [PandasDataFrameConverter][ipyvizzu.data.converters.pandas_converter.PandasDataFrameConverter] * [Animate][ipyvizzu.method.Animate] * [Feature][ipyvizzu.method.Feature] * [Store][ipyvizzu.method.Store] diff --git a/src/ipyvizzu/data/converters/pandas_converter.py b/src/ipyvizzu/data/converters/pandas_converter.py index c1896926..c28914fd 100644 --- a/src/ipyvizzu/data/converters/pandas_converter.py +++ b/src/ipyvizzu/data/converters/pandas_converter.py @@ -56,7 +56,7 @@ def _get_pandas(self) -> ModuleType: import pandas as pd # pylint: disable=import-outside-toplevel return pd - except ImportError as error: # pragma: no cover + except ImportError as error: raise ImportError( "pandas is not available. Please install pandas to use this feature." ) from error diff --git a/tests/test_animation.py b/tests/test_animation.py index ff2bf5db..7f1b469e 100644 --- a/tests/test_animation.py +++ b/tests/test_animation.py @@ -4,6 +4,7 @@ import pathlib from typing import List import unittest +from unittest.mock import patch import jsonschema # type: ignore import pandas as pd @@ -357,6 +358,20 @@ def test_add_df_index_with_none(self) -> None: data.build(), ) + def test_add_df_if_pandas_not_installed(self) -> None: + with patch("builtins.__import__") as mock_import: + + def import_replacement(name, *args, **kwargs): + if name == "pandas": + raise ImportError("pandas is not available") + return mock_import(name, *args, **kwargs) + + mock_import.side_effect = import_replacement + + data = Data() + with self.assertRaises(ImportError): + data.add_df(None) + class TestDataAddDataframe(unittest.TestCase): asset_dir: pathlib.Path From c4db6170207dfe61698f6578d38a5d84e9ec85ad Mon Sep 17 00:00:00 2001 From: David Vegh Date: Wed, 2 Aug 2023 16:34:49 +0200 Subject: [PATCH 14/15] Improve data module docstrings --- src/ipyvizzu/__init__.py | 2 ++ src/ipyvizzu/data/__init__.py | 4 ++++ src/ipyvizzu/data/converters/__init__.py | 5 +++++ src/ipyvizzu/data/typing_alias.py | 27 ++++++++++++++++++++++++ 4 files changed, 38 insertions(+) diff --git a/src/ipyvizzu/__init__.py b/src/ipyvizzu/__init__.py index 7dc5ec3c..d64c6e2c 100644 --- a/src/ipyvizzu/__init__.py +++ b/src/ipyvizzu/__init__.py @@ -12,6 +12,8 @@ * [Json][ipyvizzu.json] * [Template][ipyvizzu.template] * [Schema][ipyvizzu.schema] +* [Data][ipyvizzu.data] +* [Integrations][ipyvizzu.integrations] `ipyvizzu` package imports the following objects in `__init__.py`: diff --git a/src/ipyvizzu/data/__init__.py b/src/ipyvizzu/data/__init__.py index e69de29b..315cb1fc 100644 --- a/src/ipyvizzu/data/__init__.py +++ b/src/ipyvizzu/data/__init__.py @@ -0,0 +1,4 @@ +""" +This module serves as a collection of data-related utilities, +including converter classes, data infer types and data typing aliases. +""" diff --git a/src/ipyvizzu/data/converters/__init__.py b/src/ipyvizzu/data/converters/__init__.py index e69de29b..93bd26df 100644 --- a/src/ipyvizzu/data/converters/__init__.py +++ b/src/ipyvizzu/data/converters/__init__.py @@ -0,0 +1,5 @@ +""" +This module contains converter classes that offer a user-friendly interface for data conversion, +enabling users to effortlessly transform various data formats into a standardized representation +of series compatible with `ipyvizzu`. +""" diff --git a/src/ipyvizzu/data/typing_alias.py b/src/ipyvizzu/data/typing_alias.py index 3ba61cf8..1fe873dc 100644 --- a/src/ipyvizzu/data/typing_alias.py +++ b/src/ipyvizzu/data/typing_alias.py @@ -6,15 +6,42 @@ DimensionValue = str +""" +Represents a value that can be either a string or a number, +but both will be treated as strings. +""" MeasureValue = Union[int, float] +""" +Represents a numerical value, which can be either an int or a float. +""" NestedMeasureValues = Union[MeasureValue, List["NestedMeasureValues"]] +""" +Represents a nested structure of MeasureValues. +It can be a single MeasureValue or a list containing other NestedMeasureValues. +""" RecordValue = Union[DimensionValue, MeasureValue] +""" +Represents a value that can be either a DimensionValue or a MeasureValue. +""" Record = List[RecordValue] +""" +Represents a Record, which is a list of RecordValues. +In other words, it's a list containing a mix of DimensionValues and MeasureValues. +""" SeriesValues = Union[Sequence[DimensionValue], Sequence[MeasureValue]] +""" +Represents a collection of values for a Series. +It can be a list of DimensionValues or a list of MeasureValues. +""" Series = Dict[str, Union[str, SeriesValues]] +""" +Represents a Series in a dictionary format. +It consists of a name (string), an optional type (also a string), +and a values key which contains a SeriesValues. +""" From 2b54e300b533e2fc8e2159595fc048be5904bd14 Mon Sep 17 00:00:00 2001 From: David Vegh Date: Wed, 2 Aug 2023 16:46:04 +0200 Subject: [PATCH 15/15] Add installation note about extra. --- docs/environments/bi/mode.md | 2 +- docs/environments/ide/pycharm.md | 4 ++-- docs/environments/ide/vscode.md | 4 ++-- docs/environments/notebook/colab.md | 2 +- docs/environments/notebook/databricks.md | 2 +- docs/environments/notebook/datacamp.md | 2 +- docs/environments/notebook/deepnote.md | 2 +- docs/environments/notebook/jupyterlab.md | 4 ++-- docs/environments/notebook/jupyternotebook.md | 4 ++-- docs/environments/notebook/kaggle.md | 2 +- docs/environments/notebook/noteable.md | 2 +- docs/environments/platform/flask.md | 2 +- docs/environments/platform/panel.md | 2 +- docs/environments/platform/streamlit.md | 2 +- docs/environments/platform/voila.md | 4 ++-- docs/installation.md | 10 +++++++++- 16 files changed, 29 insertions(+), 21 deletions(-) diff --git a/docs/environments/bi/mode.md b/docs/environments/bi/mode.md index d9453ca6..c735c824 100644 --- a/docs/environments/bi/mode.md +++ b/docs/environments/bi/mode.md @@ -35,7 +35,7 @@ Place the following code into a notebook cell in order to install `ipyvizzu` details). ``` -!pip install ipyvizzu -t "/tmp" > /dev/null 2>&1 +!pip install ipyvizzu pandas -t "/tmp" > /dev/null 2>&1 ``` ## Sample diff --git a/docs/environments/ide/pycharm.md b/docs/environments/ide/pycharm.md index b671c157..0dd91407 100644 --- a/docs/environments/ide/pycharm.md +++ b/docs/environments/ide/pycharm.md @@ -33,7 +33,7 @@ details. Run the following command in your command line ```sh -pip install ipyvizzu +pip install ipyvizzu pandas ``` or place the following code into a notebook cell in order to install `ipyvizzu` @@ -41,7 +41,7 @@ or place the following code into a notebook cell in order to install `ipyvizzu` details). ``` -!pip install ipyvizzu +!pip install ipyvizzu pandas ``` ## Sample diff --git a/docs/environments/ide/vscode.md b/docs/environments/ide/vscode.md index 2dff16cb..0a9d6adc 100644 --- a/docs/environments/ide/vscode.md +++ b/docs/environments/ide/vscode.md @@ -33,7 +33,7 @@ details. Run the following command in your command line ```sh -pip install ipyvizzu +pip install ipyvizzu pandas ``` or place the following code into a notebook cell in order to install `ipyvizzu` @@ -41,7 +41,7 @@ or place the following code into a notebook cell in order to install `ipyvizzu` details). ``` -!pip install ipyvizzu +!pip install ipyvizzu pandas ``` ## Sample diff --git a/docs/environments/notebook/colab.md b/docs/environments/notebook/colab.md index 86b3cc6b..f5e63457 100644 --- a/docs/environments/notebook/colab.md +++ b/docs/environments/notebook/colab.md @@ -39,7 +39,7 @@ Place the following code into a notebook cell in order to install `ipyvizzu` details). ``` -!pip install ipyvizzu +!pip install ipyvizzu pandas ``` ## Sample diff --git a/docs/environments/notebook/databricks.md b/docs/environments/notebook/databricks.md index 91d2cfdc..b11f7f85 100644 --- a/docs/environments/notebook/databricks.md +++ b/docs/environments/notebook/databricks.md @@ -39,7 +39,7 @@ Place the following code into a notebook cell in order to install `ipyvizzu` details). ``` -!pip install ipyvizzu +!pip install ipyvizzu pandas ``` ## Sample diff --git a/docs/environments/notebook/datacamp.md b/docs/environments/notebook/datacamp.md index 13503ae5..e0c10651 100644 --- a/docs/environments/notebook/datacamp.md +++ b/docs/environments/notebook/datacamp.md @@ -38,7 +38,7 @@ Place the following code into a notebook cell in order to install `ipyvizzu` details). ``` -!pip install ipyvizzu +!pip install ipyvizzu pandas ``` ## Sample diff --git a/docs/environments/notebook/deepnote.md b/docs/environments/notebook/deepnote.md index 1f002f83..d7f78ac1 100644 --- a/docs/environments/notebook/deepnote.md +++ b/docs/environments/notebook/deepnote.md @@ -39,7 +39,7 @@ Place the following code into a notebook cell in order to install `ipyvizzu` details). ``` -!pip install ipyvizzu +!pip install ipyvizzu pandas ``` ## Sample diff --git a/docs/environments/notebook/jupyterlab.md b/docs/environments/notebook/jupyterlab.md index ba6fe9d8..ad22ce9c 100644 --- a/docs/environments/notebook/jupyterlab.md +++ b/docs/environments/notebook/jupyterlab.md @@ -33,7 +33,7 @@ details. Run the following command in your command line ```sh -pip install ipyvizzu +pip install ipyvizzu pandas ``` or place the following code into a notebook cell in order to install `ipyvizzu` @@ -41,7 +41,7 @@ or place the following code into a notebook cell in order to install `ipyvizzu` details). ``` -!pip install ipyvizzu +!pip install ipyvizzu pandas ``` ## Sample diff --git a/docs/environments/notebook/jupyternotebook.md b/docs/environments/notebook/jupyternotebook.md index 92c2e04b..135ce26a 100644 --- a/docs/environments/notebook/jupyternotebook.md +++ b/docs/environments/notebook/jupyternotebook.md @@ -33,7 +33,7 @@ details. Run the following command in your command line ```sh -pip install ipyvizzu +pip install ipyvizzu pandas ``` or place the following code into a notebook cell in order to install `ipyvizzu` @@ -41,7 +41,7 @@ or place the following code into a notebook cell in order to install `ipyvizzu` details). ``` -!pip install ipyvizzu +!pip install ipyvizzu pandas ``` ## Sample diff --git a/docs/environments/notebook/kaggle.md b/docs/environments/notebook/kaggle.md index fce69cce..d980703e 100644 --- a/docs/environments/notebook/kaggle.md +++ b/docs/environments/notebook/kaggle.md @@ -39,7 +39,7 @@ Place the following code into a notebook cell in order to install `ipyvizzu` details). ``` -!pip install ipyvizzu +!pip install ipyvizzu pandas ``` ## Sample diff --git a/docs/environments/notebook/noteable.md b/docs/environments/notebook/noteable.md index d5b9715e..5e1d85f6 100644 --- a/docs/environments/notebook/noteable.md +++ b/docs/environments/notebook/noteable.md @@ -35,7 +35,7 @@ Place the following code into a notebook cell in order to install `ipyvizzu` details). ``` -!pip install ipyvizzu +!pip install ipyvizzu pandas ``` ## Sample diff --git a/docs/environments/platform/flask.md b/docs/environments/platform/flask.md index 410a3350..4c451b6f 100644 --- a/docs/environments/platform/flask.md +++ b/docs/environments/platform/flask.md @@ -37,7 +37,7 @@ Run the following command in your command line in order to install `ipyvizzu` details). ```sh -pip install ipyvizzu flask +pip install ipyvizzu pandas flask ``` ## Sample diff --git a/docs/environments/platform/panel.md b/docs/environments/platform/panel.md index 34bb40f7..d3cb9324 100644 --- a/docs/environments/platform/panel.md +++ b/docs/environments/platform/panel.md @@ -35,7 +35,7 @@ Run the following command in your command line in order to install `ipyvizzu` details). ```sh -pip install ipyvizzu panel +pip install ipyvizzu pandas panel ``` ## Sample diff --git a/docs/environments/platform/streamlit.md b/docs/environments/platform/streamlit.md index 67821d5b..8e3363ef 100644 --- a/docs/environments/platform/streamlit.md +++ b/docs/environments/platform/streamlit.md @@ -40,7 +40,7 @@ Run the following command in your command line in order to install `ipyvizzu` details). ```sh -pip install ipyvizzu streamlit +pip install ipyvizzu pandas streamlit ``` ## Sample diff --git a/docs/environments/platform/voila.md b/docs/environments/platform/voila.md index 89a1f6d0..c42ee43e 100644 --- a/docs/environments/platform/voila.md +++ b/docs/environments/platform/voila.md @@ -33,7 +33,7 @@ details. Run the following command in your command line ```sh -pip install ipyvizzu voila +pip install ipyvizzu pandas voila ``` or place the following code into a notebook cell in order to install `ipyvizzu` @@ -41,7 +41,7 @@ or place the following code into a notebook cell in order to install `ipyvizzu` details). ``` -!pip install ipyvizzu +!pip install ipyvizzu pandas ``` ## Sample diff --git a/docs/installation.md b/docs/installation.md index 7258efa5..b6553a1c 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -1,6 +1,6 @@ # Installation -`ipyvizzu` requires the `IPython`, `jsonschema` and `pandas` packages. +`ipyvizzu` requires the `IPython` and `jsonschema` packages. !!! info `ipyvizzu` requires and downloads the @@ -24,6 +24,14 @@ and this is how to upgrade it. pip install -U ipyvizzu ``` +!!! note + If you want to work with `pandas` `DataFrame` and `ipyvizzu`, you need to + install `pandas` or install it as an extra: + + ```sh + pip install ipyvizzu[pandas] + ``` + You can use `ipyvizzu` in `Jupyter/IPython`, `Streamlit` or `Panel` (see [Environments chapter](environments/index.md) for more details).