From fa9917be279d82e6439c4e0221c0487f2b07e0c6 Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Thu, 1 Sep 2022 12:09:21 +0100 Subject: [PATCH 1/4] ENH: Improve to_string typing --- pandas-stubs/_typing.pyi | 6 +++++- pandas-stubs/core/frame.pyi | 29 ++++++++++++++++------------- 2 files changed, 21 insertions(+), 14 deletions(-) diff --git a/pandas-stubs/_typing.pyi b/pandas-stubs/_typing.pyi index 73617ff4f..f553fdbbe 100644 --- a/pandas-stubs/_typing.pyi +++ b/pandas-stubs/_typing.pyi @@ -23,6 +23,7 @@ from typing import ( Union, ) +import matplotlib.ticker import numpy as np from numpy import typing as npt from pandas.core.arrays import ExtensionArray @@ -186,7 +187,10 @@ CompressionDict = dict[str, Any] CompressionOptions = Optional[ Union[Literal["infer", "gzip", "bz2", "zip", "xz", "zstd"], CompressionDict] ] - +FormattersType = Union[ + list[Callable], tuple[Callable, ...], Mapping[Union[str, int], Callable] +] +FloatFormatType = str | Callable | matplotlib.ticker.EngFormatter # converters ConvertersArg = dict[Hashable, Callable[[Dtype], Dtype]] diff --git a/pandas-stubs/core/frame.pyi b/pandas-stubs/core/frame.pyi index 4bf3d5b8e..d1159bf69 100644 --- a/pandas-stubs/core/frame.pyi +++ b/pandas-stubs/core/frame.pyi @@ -55,6 +55,8 @@ from pandas._typing import ( FilePath, FilePathOrBuffer, FillnaOptions, + FloatFormatType, + FormattersType, GroupByObjectNonScalar, HashableT, IgnoreRaise, @@ -1962,48 +1964,49 @@ class DataFrame(NDFrame, OpsMixin): @overload def to_string( self, - buf: FilePathOrBuffer | None, + buf: FilePath | WriteBuffer[str], columns: Sequence[_str] | None = ..., - col_space: int | list[int] | dict[_str | int, int] | None = ..., - header: _bool | Sequence[_str] = ..., + col_space: int | list[int] | dict[HashableT, int] | None = ..., + header: _bool | list[_str] | tuple[str, ...] = ..., index: _bool = ..., na_rep: _str = ..., - formatters=..., - float_format=..., + formatters: FormattersType | None = ..., + float_format: FloatFormatType | None = ..., sparsify: _bool | None = ..., index_names: _bool = ..., justify: _str | None = ..., max_rows: int | None = ..., - min_rows: int | None = ..., max_cols: int | None = ..., - show_dimensions: _bool = ..., + show_dimensions: bool = ..., decimal: _str = ..., line_width: int | None = ..., + min_rows: int | None = ..., max_colwidth: int | None = ..., encoding: _str | None = ..., ) -> None: ... @overload def to_string( self, + buf: None = ..., columns: Sequence[_str] | None = ..., - col_space: int | list[int] | dict[_str | int, int] | None = ..., + col_space: int | list[int] | dict[Hashable, int] | None = ..., header: _bool | Sequence[_str] = ..., index: _bool = ..., na_rep: _str = ..., - formatters=..., - float_format=..., + formatters: fmt.FormattersType | None = ..., + float_format: fmt.FloatFormatType | None = ..., sparsify: _bool | None = ..., index_names: _bool = ..., justify: _str | None = ..., max_rows: int | None = ..., - min_rows: int | None = ..., max_cols: int | None = ..., - show_dimensions: _bool = ..., + show_dimensions: bool = ..., decimal: _str = ..., line_width: int | None = ..., + min_rows: int | None = ..., max_colwidth: int | None = ..., encoding: _str | None = ..., - ) -> _str: ... + ) -> str: ... def to_xarray(self): ... def truediv( self, From 805cf984704b936f1d78ef3b590b6fced558ac3c Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Thu, 1 Sep 2022 18:54:05 +0100 Subject: [PATCH 2/4] BUG/TST: Corect types and add test --- pandas-stubs/core/frame.pyi | 8 ++++---- tests/test_io.py | 11 +++++++++++ 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/pandas-stubs/core/frame.pyi b/pandas-stubs/core/frame.pyi index d1159bf69..b40871d9b 100644 --- a/pandas-stubs/core/frame.pyi +++ b/pandas-stubs/core/frame.pyi @@ -1977,7 +1977,7 @@ class DataFrame(NDFrame, OpsMixin): justify: _str | None = ..., max_rows: int | None = ..., max_cols: int | None = ..., - show_dimensions: bool = ..., + show_dimensions: _bool = ..., decimal: _str = ..., line_width: int | None = ..., min_rows: int | None = ..., @@ -1993,14 +1993,14 @@ class DataFrame(NDFrame, OpsMixin): header: _bool | Sequence[_str] = ..., index: _bool = ..., na_rep: _str = ..., - formatters: fmt.FormattersType | None = ..., - float_format: fmt.FloatFormatType | None = ..., + formatters: FormattersType | None = ..., + float_format: FloatFormatType | None = ..., sparsify: _bool | None = ..., index_names: _bool = ..., justify: _str | None = ..., max_rows: int | None = ..., max_cols: int | None = ..., - show_dimensions: bool = ..., + show_dimensions: _bool = ..., decimal: _str = ..., line_width: int | None = ..., min_rows: int | None = ..., diff --git a/tests/test_io.py b/tests/test_io.py index f87265710..50a30f9f6 100644 --- a/tests/test_io.py +++ b/tests/test_io.py @@ -337,3 +337,14 @@ def test_feather(): check(assert_type(DF.to_feather(bio), None), type(None)) bio.seek(0) check(assert_type(read_feather(bio), DataFrame), DataFrame) + + +def test_to_string(): + check(assert_type(DF.to_string(), str), str) + with ensure_clean() as path: + check(assert_type(DF.to_string(path), None), type(None)) + check(assert_type(DF.to_string(pathlib.Path(path)), None), type(None)) + with open(path, "wt") as df_string: + check(assert_type(DF.to_string(df_string), None), type(None)) + sio = io.StringIO() + check(assert_type(DF.to_string(sio), None), type(None)) From 8cca52faa8952cdaf88ad10e50b10984b98f2268 Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Sat, 3 Sep 2022 08:01:28 +0100 Subject: [PATCH 3/4] MAINT: Remove dep on matplotlib --- pandas-stubs/_typing.pyi | 5 +++-- pandas-stubs/core/frame.pyi | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/pandas-stubs/_typing.pyi b/pandas-stubs/_typing.pyi index 9f8eb80fa..21c1c8fae 100644 --- a/pandas-stubs/_typing.pyi +++ b/pandas-stubs/_typing.pyi @@ -23,7 +23,6 @@ from typing import ( Union, ) -import matplotlib.ticker import numpy as np from numpy import typing as npt from pandas.core.arrays import ExtensionArray @@ -40,6 +39,8 @@ from pandas._libs.tslibs import ( from pandas.core.dtypes.dtypes import ExtensionDtype +from pandas.io.formats.format import EngFormatter + ArrayLike = Union[ExtensionArray, np.ndarray] AnyArrayLike = Union[Index, Series, np.ndarray] PythonScalar = Union[str, bool, complex] @@ -192,7 +193,7 @@ CompressionOptions = Optional[ FormattersType = Union[ list[Callable], tuple[Callable, ...], Mapping[Union[str, int], Callable] ] -FloatFormatType = str | Callable | matplotlib.ticker.EngFormatter +FloatFormatType = str | Callable | EngFormatter # converters ConvertersArg = dict[Hashable, Callable[[Dtype], Dtype]] diff --git a/pandas-stubs/core/frame.pyi b/pandas-stubs/core/frame.pyi index 7db2f19c7..8251f161b 100644 --- a/pandas-stubs/core/frame.pyi +++ b/pandas-stubs/core/frame.pyi @@ -1999,7 +1999,7 @@ class DataFrame(NDFrame, OpsMixin): def to_string( self, buf: FilePath | WriteBuffer[str], - columns: Sequence[_str] | None = ..., + columns: list[HashableT] | Index | Series | None = ..., col_space: int | list[int] | dict[HashableT, int] | None = ..., header: _bool | list[_str] | tuple[str, ...] = ..., index: _bool = ..., @@ -2022,7 +2022,7 @@ class DataFrame(NDFrame, OpsMixin): def to_string( self, buf: None = ..., - columns: Sequence[_str] | None = ..., + columns: list[HashableT] | Index | None = ..., col_space: int | list[int] | dict[Hashable, int] | None = ..., header: _bool | Sequence[_str] = ..., index: _bool = ..., From e7a05c7e129fd769ab1c63036e1cd14d782098e3 Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Sun, 4 Sep 2022 00:59:36 +0100 Subject: [PATCH 4/4] MAINT: Use literal and add Series --- pandas-stubs/core/frame.pyi | 8 ++++---- pandas-stubs/core/generic.pyi | 4 ++-- pandas-stubs/io/clipboards.pyi | 6 +++--- tests/test_frame.py | 4 ++++ 4 files changed, 13 insertions(+), 9 deletions(-) diff --git a/pandas-stubs/core/frame.pyi b/pandas-stubs/core/frame.pyi index 051a1a1d3..6ddde00e2 100644 --- a/pandas-stubs/core/frame.pyi +++ b/pandas-stubs/core/frame.pyi @@ -349,7 +349,7 @@ class DataFrame(NDFrame, OpsMixin): def to_html( self, buf: FilePath | WriteBuffer[str], - columns: list[HashableT] | None = ..., + columns: list[HashableT] | Index | Series | None = ..., col_space: ColspaceArgType | None = ..., header: _bool = ..., index: _bool = ..., @@ -1930,7 +1930,7 @@ class DataFrame(NDFrame, OpsMixin): mode: _str = ..., encoding: _str | None = ..., compression: _str | Mapping[_str, _str] = ..., - quoting: int | None = ..., + quoting: Literal[0, 1, 2, 3] | None = ..., quotechar: _str = ..., line_terminator: _str | None = ..., chunksize: int | None = ..., @@ -1954,7 +1954,7 @@ class DataFrame(NDFrame, OpsMixin): mode: _str = ..., encoding: _str | None = ..., compression: _str | Mapping[_str, _str] = ..., - quoting: int | None = ..., + quoting: Literal[0, 1, 2, 3] | None = ..., quotechar: _str = ..., line_terminator: _str | None = ..., chunksize: int | None = ..., @@ -2029,7 +2029,7 @@ class DataFrame(NDFrame, OpsMixin): def to_string( self, buf: None = ..., - columns: list[HashableT] | Index | None = ..., + columns: list[HashableT] | Index | Series | None = ..., col_space: int | list[int] | dict[Hashable, int] | None = ..., header: _bool | Sequence[_str] = ..., index: _bool = ..., diff --git a/pandas-stubs/core/generic.pyi b/pandas-stubs/core/generic.pyi index 8dfcba55c..945a35303 100644 --- a/pandas-stubs/core/generic.pyi +++ b/pandas-stubs/core/generic.pyi @@ -242,7 +242,7 @@ class NDFrame(PandasObject, indexing.IndexingMixin): mode: _str = ..., encoding: _str | None = ..., compression: _str | Mapping[_str, _str] = ..., - quoting: int | None = ..., + quoting: Literal[0, 1, 2, 3] | None = ..., quotechar: _str = ..., line_terminator: _str | None = ..., chunksize: int | None = ..., @@ -266,7 +266,7 @@ class NDFrame(PandasObject, indexing.IndexingMixin): mode: _str = ..., encoding: _str | None = ..., compression: _str | Mapping[_str, _str] = ..., - quoting: int | None = ..., + quoting: Literal[0, 1, 2, 3] | None = ..., quotechar: _str = ..., line_terminator: _str | None = ..., chunksize: int | None = ..., diff --git a/pandas-stubs/io/clipboards.pyi b/pandas-stubs/io/clipboards.pyi index 6531f4641..62fbef460 100644 --- a/pandas-stubs/io/clipboards.pyi +++ b/pandas-stubs/io/clipboards.pyi @@ -71,7 +71,7 @@ def read_clipboard( decimal: str = ..., lineterminator: str | None = ..., quotechar: str = ..., - quoting: int = ..., + quoting: Literal[0, 1, 2, 3] | None = ..., doublequote: bool = ..., escapechar: str | None = ..., comment: str | None = ..., @@ -137,7 +137,7 @@ def read_clipboard( decimal: str = ..., lineterminator: str | None = ..., quotechar: str = ..., - quoting: int = ..., + quoting: Literal[0, 1, 2, 3] | None = ..., doublequote: bool = ..., escapechar: str | None = ..., comment: str | None = ..., @@ -203,7 +203,7 @@ def read_clipboard( decimal: str = ..., lineterminator: str | None = ..., quotechar: str = ..., - quoting: int = ..., + quoting: Literal[0, 1, 2, 3] | None = ..., doublequote: bool = ..., escapechar: str | None = ..., comment: str | None = ..., diff --git a/tests/test_frame.py b/tests/test_frame.py index 17a46951c..171bb0c3a 100644 --- a/tests/test_frame.py +++ b/tests/test_frame.py @@ -1,6 +1,7 @@ from __future__ import annotations from collections import defaultdict +import csv import datetime import io from pathlib import Path @@ -114,6 +115,9 @@ def test_types_to_csv() -> None: # Testing support for binary file handles, added in 1.2.0 https://pandas.pydata.org/docs/whatsnew/v1.2.0.html df.to_csv(io.BytesIO(), encoding="utf-8", compression="gzip") + # Testing support for binary file handles, added in 1.2.0 https://pandas.pydata.org/docs/whatsnew/v1.2.0.html + df.to_csv(io.BytesIO(), quoting=csv.QUOTE_ALL, encoding="utf-8", compression="gzip") + def test_types_to_csv_when_path_passed() -> None: df = pd.DataFrame(data={"col1": [1, 2], "col2": [3, 4]})