Skip to content

Commit 53a9e3f

Browse files
author
Kevin Sheppard
committed
Merge remote-tracking branch 'upstream/main' into io-fwf-csv-table2
2 parents 0677a2c + 4890dba commit 53a9e3f

File tree

6 files changed

+141
-34
lines changed

6 files changed

+141
-34
lines changed

pandas-stubs/_typing.pyi

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ from pandas._libs.tslibs import (
4040

4141
from pandas.core.dtypes.dtypes import ExtensionDtype
4242

43+
from pandas.io.formats.format import EngFormatter
44+
4345
ArrayLike = Union[ExtensionArray, np.ndarray]
4446
AnyArrayLike = Union[Index, Series, np.ndarray]
4547
PythonScalar = Union[str, bool, complex]
@@ -195,7 +197,10 @@ CompressionDict = dict[str, Any]
195197
CompressionOptions = Optional[
196198
Union[Literal["infer", "gzip", "bz2", "zip", "xz", "zstd"], CompressionDict]
197199
]
198-
200+
FormattersType = Union[
201+
list[Callable], tuple[Callable, ...], Mapping[Union[str, int], Callable]
202+
]
203+
FloatFormatType = str | Callable | EngFormatter
199204
# converters
200205
ConvertersArg = dict[Hashable, Callable[[Dtype], Dtype]]
201206

pandas-stubs/core/frame.pyi

Lines changed: 66 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -52,11 +52,14 @@ from pandas._typing import (
5252
AxisType,
5353
ColspaceArgType,
5454
CompressionOptions,
55+
CSVQuoting,
5556
Dtype,
5657
DtypeNp,
5758
FilePath,
5859
FilePathOrBuffer,
5960
FillnaOptions,
61+
FloatFormatType,
62+
FormattersType,
6063
GroupByObjectNonScalar,
6164
HashableT,
6265
IgnoreRaise,
@@ -347,7 +350,7 @@ class DataFrame(NDFrame, OpsMixin):
347350
def to_html(
348351
self,
349352
buf: FilePath | WriteBuffer[str],
350-
columns: list[HashableT] | None = ...,
353+
columns: list[HashableT] | Index | Series | None = ...,
351354
col_space: ColspaceArgType | None = ...,
352355
header: _bool = ...,
353356
index: _bool = ...,
@@ -1915,6 +1918,55 @@ class DataFrame(NDFrame, OpsMixin):
19151918
self, excel: _bool = ..., sep: _str | None = ..., **kwargs
19161919
) -> None: ...
19171920
@overload
1921+
def to_csv(
1922+
self,
1923+
path_or_buf: FilePathOrBuffer | None,
1924+
sep: _str = ...,
1925+
na_rep: _str = ...,
1926+
float_format: _str | None = ...,
1927+
columns: Sequence[Hashable] | None = ...,
1928+
header: _bool | list[_str] = ...,
1929+
index: _bool = ...,
1930+
index_label: _bool | _str | Sequence[Hashable] | None = ...,
1931+
mode: _str = ...,
1932+
encoding: _str | None = ...,
1933+
compression: _str | Mapping[_str, _str] = ...,
1934+
quoting: CSVQuoting | None = ...,
1935+
quotechar: _str = ...,
1936+
line_terminator: _str | None = ...,
1937+
chunksize: int | None = ...,
1938+
date_format: _str | None = ...,
1939+
doublequote: _bool = ...,
1940+
escapechar: _str | None = ...,
1941+
decimal: _str = ...,
1942+
errors: _str = ...,
1943+
storage_options: dict[_str, Any] | None = ...,
1944+
) -> None: ...
1945+
@overload
1946+
def to_csv(
1947+
self,
1948+
sep: _str = ...,
1949+
na_rep: _str = ...,
1950+
float_format: _str | None = ...,
1951+
columns: Sequence[Hashable] | None = ...,
1952+
header: _bool | list[_str] = ...,
1953+
index: _bool = ...,
1954+
index_label: _bool | _str | Sequence[Hashable] | None = ...,
1955+
mode: _str = ...,
1956+
encoding: _str | None = ...,
1957+
compression: _str | Mapping[_str, _str] = ...,
1958+
quoting: CSVQuoting | None = ...,
1959+
quotechar: _str = ...,
1960+
line_terminator: _str | None = ...,
1961+
chunksize: int | None = ...,
1962+
date_format: _str | None = ...,
1963+
doublequote: _bool = ...,
1964+
escapechar: _str | None = ...,
1965+
decimal: _str = ...,
1966+
errors: _str = ...,
1967+
storage_options: dict[_str, Any] | None = ...,
1968+
) -> _str: ...
1969+
@overload
19181970
def to_json(
19191971
self,
19201972
path_or_buf: FilePathOrBuffer | None,
@@ -1954,45 +2006,46 @@ class DataFrame(NDFrame, OpsMixin):
19542006
@overload
19552007
def to_string(
19562008
self,
1957-
buf: FilePathOrBuffer | None,
1958-
columns: Sequence[_str] | None = ...,
1959-
col_space: int | list[int] | dict[_str | int, int] | None = ...,
1960-
header: _bool | Sequence[_str] = ...,
2009+
buf: FilePath | WriteBuffer[str],
2010+
columns: list[HashableT] | Index | Series | None = ...,
2011+
col_space: int | list[int] | dict[HashableT, int] | None = ...,
2012+
header: _bool | list[_str] | tuple[str, ...] = ...,
19612013
index: _bool = ...,
19622014
na_rep: _str = ...,
1963-
formatters=...,
1964-
float_format=...,
2015+
formatters: FormattersType | None = ...,
2016+
float_format: FloatFormatType | None = ...,
19652017
sparsify: _bool | None = ...,
19662018
index_names: _bool = ...,
19672019
justify: _str | None = ...,
19682020
max_rows: int | None = ...,
1969-
min_rows: int | None = ...,
19702021
max_cols: int | None = ...,
19712022
show_dimensions: _bool = ...,
19722023
decimal: _str = ...,
19732024
line_width: int | None = ...,
2025+
min_rows: int | None = ...,
19742026
max_colwidth: int | None = ...,
19752027
encoding: _str | None = ...,
19762028
) -> None: ...
19772029
@overload
19782030
def to_string(
19792031
self,
1980-
columns: Sequence[_str] | None = ...,
1981-
col_space: int | list[int] | dict[_str | int, int] | None = ...,
2032+
buf: None = ...,
2033+
columns: list[HashableT] | Index | Series | None = ...,
2034+
col_space: int | list[int] | dict[Hashable, int] | None = ...,
19822035
header: _bool | Sequence[_str] = ...,
19832036
index: _bool = ...,
19842037
na_rep: _str = ...,
1985-
formatters=...,
1986-
float_format=...,
2038+
formatters: FormattersType | None = ...,
2039+
float_format: FloatFormatType | None = ...,
19872040
sparsify: _bool | None = ...,
19882041
index_names: _bool = ...,
19892042
justify: _str | None = ...,
19902043
max_rows: int | None = ...,
1991-
min_rows: int | None = ...,
19922044
max_cols: int | None = ...,
19932045
show_dimensions: _bool = ...,
19942046
decimal: _str = ...,
19952047
line_width: int | None = ...,
2048+
min_rows: int | None = ...,
19962049
max_colwidth: int | None = ...,
19972050
encoding: _str | None = ...,
19982051
) -> _str: ...

pandas-stubs/core/generic.pyi

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,7 @@ class NDFrame(PandasObject, indexing.IndexingMixin):
242242
mode: FileWriteMode = ...,
243243
encoding: _str | None = ...,
244244
compression: CompressionOptions = ...,
245-
quoting: int | None = ...,
245+
quoting: Literal[0, 1, 2, 3] | None = ...,
246246
quotechar: _str = ...,
247247
line_terminator: _str | None = ...,
248248
chunksize: int | None = ...,
@@ -267,7 +267,7 @@ class NDFrame(PandasObject, indexing.IndexingMixin):
267267
mode: FileWriteMode = ...,
268268
encoding: _str | None = ...,
269269
compression: CompressionOptions = ...,
270-
quoting: int | None = ...,
270+
quoting: Literal[0, 1, 2, 3] | None = ...,
271271
quotechar: _str = ...,
272272
line_terminator: _str | None = ...,
273273
chunksize: int | None = ...,

pandas-stubs/io/parsers/readers.pyi

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ def read_csv(
4444
| npt.NDArray
4545
| Callable[[str], bool]
4646
| None = ...,
47+
mangle_dupe_cols: bool = ...,
4748
dtype: DtypeArg | None = ...,
4849
engine: CSVEngine | None = ...,
4950
converters: dict[int | str, Callable[[str], Any]] = ...,
@@ -107,6 +108,7 @@ def read_csv(
107108
| npt.NDArray
108109
| Callable[[str], bool]
109110
| None = ...,
111+
mangle_dupe_cols: bool = ...,
110112
dtype: DtypeArg | None = ...,
111113
engine: CSVEngine | None = ...,
112114
converters: dict[int | str, Callable[[str], Any]] = ...,
@@ -170,6 +172,7 @@ def read_csv(
170172
| npt.NDArray
171173
| Callable[[str], bool]
172174
| None = ...,
175+
mangle_dupe_cols: bool = ...,
173176
dtype: DtypeArg | None = ...,
174177
engine: CSVEngine | None = ...,
175178
converters: dict[int | str, Callable[[str], Any]] = ...,
@@ -405,13 +408,39 @@ def read_table(
405408
float_precision: Literal["high", "legacy", "round_trip"] | None = ...,
406409
storage_options: StorageOptions | None = ...,
407410
) -> DataFrame: ...
411+
@overload
408412
def read_fwf(
409413
filepath_or_buffer: FilePath | ReadCsvBuffer[bytes] | ReadCsvBuffer[str],
410-
colspecs: Sequence[tuple[int, int]] | str | None = ...,
414+
colspecs: Sequence[tuple[int, int]] | Literal["infer"] | None = ...,
411415
widths: Sequence[int] | None = ...,
412416
infer_nrows: int = ...,
417+
*,
418+
iterator: Literal[True],
419+
chunksize: int | None = ...,
413420
**kwds: Any,
414-
) -> DataFrame | TextFileReader: ...
421+
) -> TextFileReader: ...
422+
@overload
423+
def read_fwf(
424+
filepath_or_buffer: FilePath | ReadCsvBuffer[bytes] | ReadCsvBuffer[str],
425+
colspecs: Sequence[tuple[int, int]] | Literal["infer"] | None = ...,
426+
widths: Sequence[int] | None = ...,
427+
infer_nrows: int = ...,
428+
*,
429+
iterator: bool = ...,
430+
chunksize: int,
431+
**kwds: Any,
432+
) -> TextFileReader: ...
433+
@overload
434+
def read_fwf(
435+
filepath_or_buffer: FilePath | ReadCsvBuffer[bytes] | ReadCsvBuffer[str],
436+
colspecs: Sequence[tuple[int, int]] | Literal["infer"] | None = ...,
437+
widths: Sequence[int] | None = ...,
438+
infer_nrows: int = ...,
439+
*,
440+
iterator: Literal[False] = ...,
441+
chunksize: None = ...,
442+
**kwds: Any,
443+
) -> DataFrame: ...
415444

416445
class TextFileReader(abc.Iterator):
417446
engine: CSVEngine

tests/test_frame.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from __future__ import annotations
22

33
from collections import defaultdict
4+
import csv
45
import datetime
56
import io
67
from pathlib import Path
@@ -114,6 +115,9 @@ def test_types_to_csv() -> None:
114115
# Testing support for binary file handles, added in 1.2.0 https://pandas.pydata.org/docs/whatsnew/v1.2.0.html
115116
df.to_csv(io.BytesIO(), encoding="utf-8", compression="gzip")
116117

118+
# Testing support for binary file handles, added in 1.2.0 https://pandas.pydata.org/docs/whatsnew/v1.2.0.html
119+
df.to_csv(io.BytesIO(), quoting=csv.QUOTE_ALL, encoding="utf-8", compression="gzip")
120+
117121

118122
def test_types_to_csv_when_path_passed() -> None:
119123
df = pd.DataFrame(data={"col1": [1, 2], "col2": [3, 4]})

tests/test_io.py

Lines changed: 32 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import csv
12
import io
23
import os.path
34
import pathlib
@@ -443,34 +444,28 @@ def test_read_table_iterator():
443444
)
444445

445446

446-
def test_read_fwf():
447+
def btest_read_fwf():
447448
with ensure_clean() as path:
448449
DF.to_string(path, index=False)
449-
check(assert_type(read_fwf(path), Union[DataFrame, TextFileReader]), DataFrame)
450-
check(
451-
assert_type(read_fwf(pathlib.Path(path)), Union[DataFrame, TextFileReader]),
452-
DataFrame,
453-
)
450+
check(assert_type(read_fwf(path), DataFrame), DataFrame)
451+
check(assert_type(read_fwf(pathlib.Path(path)), DataFrame), DataFrame)
454452

455453
with open(path) as fwf_file:
456454
check(
457-
assert_type(read_fwf(fwf_file), Union[DataFrame, TextFileReader]),
455+
assert_type(read_fwf(fwf_file), DataFrame),
458456
DataFrame,
459457
)
460458
with open(path) as fwf_file:
461459
sio = io.StringIO(fwf_file.read())
462-
check(
463-
assert_type(read_fwf(sio), Union[DataFrame, TextFileReader]), DataFrame
464-
)
460+
check(assert_type(read_fwf(sio), DataFrame), DataFrame)
465461
with open(path, "rb") as fwf_file:
466462
bio = io.BytesIO(fwf_file.read())
467-
check(
468-
assert_type(read_fwf(bio), Union[DataFrame, TextFileReader]), DataFrame
469-
)
463+
check(assert_type(read_fwf(bio), DataFrame), DataFrame)
470464
fwf_iterator = read_fwf(path, iterator=True)
471-
check(
472-
assert_type(fwf_iterator, Union[DataFrame, TextFileReader]), TextFileReader
473-
)
465+
check(assert_type(fwf_iterator, TextFileReader), TextFileReader)
466+
fwf_iterator.close()
467+
fwf_iterator2 = read_fwf(path, chunksize=1)
468+
check(assert_type(fwf_iterator2, TextFileReader), TextFileReader)
474469
fwf_iterator.close()
475470

476471

@@ -498,6 +493,17 @@ def test_to_csv_series():
498493
check(assert_type(s.to_csv(path), None), type(None))
499494

500495

496+
def test_to_string():
497+
check(assert_type(DF.to_string(), str), str)
498+
with ensure_clean() as path:
499+
check(assert_type(DF.to_string(path), None), type(None))
500+
check(assert_type(DF.to_string(pathlib.Path(path)), None), type(None))
501+
with open(path, "wt") as df_string:
502+
check(assert_type(DF.to_string(df_string), None), type(None))
503+
sio = io.StringIO()
504+
check(assert_type(DF.to_string(sio), None), type(None))
505+
506+
501507
def test_read_sql():
502508
with ensure_clean() as path:
503509
con = sqlite3.connect(path)
@@ -572,3 +578,13 @@ def test_read_html():
572578
with ensure_clean() as path:
573579
check(assert_type(DF.to_html(path), None), type(None))
574580
check(assert_type(read_html(path), List[DataFrame]), list)
581+
582+
583+
def test_csv_quoting():
584+
with ensure_clean() as path:
585+
check(assert_type(DF.to_csv(path, quoting=csv.QUOTE_ALL), None), type(None))
586+
check(assert_type(DF.to_csv(path, quoting=csv.QUOTE_NONE), None), type(None))
587+
check(
588+
assert_type(DF.to_csv(path, quoting=csv.QUOTE_NONNUMERIC), None), type(None)
589+
)
590+
check(assert_type(DF.to_csv(path, quoting=csv.QUOTE_MINIMAL), None), type(None))

0 commit comments

Comments
 (0)