Skip to content

Commit

Permalink
Merge branch 'main' into ref-format
Browse files Browse the repository at this point in the history
  • Loading branch information
jbrockmendel committed Oct 10, 2023
2 parents 072db8f + 66a54a3 commit b3288fc
Show file tree
Hide file tree
Showing 11 changed files with 113 additions and 99 deletions.
3 changes: 0 additions & 3 deletions asv_bench/benchmarks/series_methods.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,6 @@ def time_constructor_dict(self):
def time_constructor_no_data(self):
Series(data=None, index=self.idx)

def time_constructor_fastpath(self):
Series(self.array, index=self.idx2, name="name", fastpath=True)


class ToFrame:
params = [["int64", "datetime64[ns]", "category", "Int64"], [None, "foo"]]
Expand Down
1 change: 1 addition & 0 deletions doc/source/whatsnew/v2.2.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,7 @@ Other Deprecations
- Deprecated strings ``H``, ``S``, ``U``, and ``N`` denoting units in :func:`to_timedelta` (:issue:`52536`)
- Deprecated strings ``H``, ``T``, ``S``, ``L``, ``U``, and ``N`` denoting units in :class:`Timedelta` (:issue:`52536`)
- Deprecated strings ``T``, ``S``, ``L``, ``U``, and ``N`` denoting frequencies in :class:`Minute`, :class:`Second`, :class:`Milli`, :class:`Micro`, :class:`Nano` (:issue:`52536`)
- Deprecated the ``fastpath`` keyword in the :class:`Series` constructor (:issue:`20110`)
- Deprecated the extension test classes ``BaseNoReduceTests``, ``BaseBooleanReduceTests``, and ``BaseNumericReduceTests``, use ``BaseReduceTests`` instead (:issue:`54663`)
- Deprecated the option ``mode.data_manager`` and the ``ArrayManager``; only the ``BlockManager`` will be available in future versions (:issue:`55043`)
- Deprecating downcasting the results of :meth:`DataFrame.fillna`, :meth:`Series.fillna`, :meth:`DataFrame.ffill`, :meth:`Series.ffill`, :meth:`DataFrame.bfill`, :meth:`Series.bfill` in object-dtype cases. To opt in to the future version, use ``pd.set_option("future.no_silent_downcasting", True)`` (:issue:`54261`)
Expand Down
7 changes: 1 addition & 6 deletions pandas/core/frame.py
Original file line number Diff line number Diff line change
Expand Up @@ -5168,12 +5168,7 @@ def _sanitize_column(self, value) -> tuple[ArrayLike, BlockValuesRefs | None]:

@property
def _series(self):
return {
item: Series(
self._mgr.iget(idx), index=self.index, name=item, fastpath=True
)
for idx, item in enumerate(self.columns)
}
return {item: self._ixs(idx, axis=1) for idx, item in enumerate(self.columns)}

# ----------------------------------------------------------------------
# Reindexing and alignment
Expand Down
7 changes: 4 additions & 3 deletions pandas/core/indexes/multi.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,10 @@
lexsort_indexer,
)

from pandas.io.formats.printing import pprint_thing
from pandas.io.formats.printing import (
get_adjustment,
pprint_thing,
)

if TYPE_CHECKING:
from pandas import (
Expand Down Expand Up @@ -1446,8 +1449,6 @@ def format(
)

if adjoin:
from pandas.io.formats.format import get_adjustment

adj = get_adjustment()
return adj.adjoin(space, *result_levels).split("\n")
else:
Expand Down
15 changes: 13 additions & 2 deletions pandas/core/series.py
Original file line number Diff line number Diff line change
Expand Up @@ -374,8 +374,18 @@ def __init__(
dtype: Dtype | None = None,
name=None,
copy: bool | None = None,
fastpath: bool = False,
fastpath: bool | lib.NoDefault = lib.no_default,
) -> None:
if fastpath is not lib.no_default:
warnings.warn(
"The 'fastpath' keyword in pd.Series is deprecated and will "
"be removed in a future version.",
DeprecationWarning,
stacklevel=find_stack_level(),
)
else:
fastpath = False

if (
isinstance(data, (SingleBlockManager, SingleArrayManager))
and index is None
Expand Down Expand Up @@ -1009,7 +1019,8 @@ def _slice(self, slobj: slice, axis: AxisInt = 0) -> Series:
# axis kwarg is retained for compat with NDFrame method
# _slice is *always* positional
mgr = self._mgr.get_slice(slobj, axis=axis)
out = self._constructor(mgr, fastpath=True)
out = self._constructor_from_mgr(mgr, axes=mgr.axes)
out._name = self._name
return out.__finalize__(self)

def __getitem__(self, key):
Expand Down
6 changes: 4 additions & 2 deletions pandas/io/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,8 @@
is_integer,
is_list_like,
)
from pandas.core.dtypes.generic import ABCMultiIndex

from pandas.core.indexes.api import MultiIndex
from pandas.core.shared_docs import _shared_docs

_VALID_URLS = set(uses_relative + uses_netloc + uses_params)
Expand All @@ -91,6 +91,8 @@
WriteBuffer,
)

from pandas import MultiIndex


@dataclasses.dataclass
class IOArgs:
Expand Down Expand Up @@ -1228,7 +1230,7 @@ def is_potential_multi_index(

return bool(
len(columns)
and not isinstance(columns, MultiIndex)
and not isinstance(columns, ABCMultiIndex)
and all(isinstance(c, tuple) for c in columns if c not in list(index_col))
)

Expand Down
73 changes: 4 additions & 69 deletions pandas/io/formats/format.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
from collections.abc import (
Generator,
Hashable,
Iterable,
Mapping,
Sequence,
)
Expand All @@ -26,7 +25,6 @@
Final,
cast,
)
from unicodedata import east_asian_width

import numpy as np

Expand Down Expand Up @@ -226,7 +224,7 @@ def __init__(
float_format = get_option("display.float_format")
self.float_format = float_format
self.dtype = dtype
self.adj = get_adjustment()
self.adj = printing.get_adjustment()

self._chk_truncate()

Expand Down Expand Up @@ -353,69 +351,6 @@ def to_string(self) -> str:
return str("".join(result))


class _TextAdjustment:
def __init__(self) -> None:
self.encoding = get_option("display.encoding")

def len(self, text: str) -> int:
return len(text)

def justify(self, texts: Any, max_len: int, mode: str = "right") -> list[str]:
return printing.justify(texts, max_len, mode=mode)

def adjoin(self, space: int, *lists, **kwargs) -> str:
return printing.adjoin(
space, *lists, strlen=self.len, justfunc=self.justify, **kwargs
)


class _EastAsianTextAdjustment(_TextAdjustment):
def __init__(self) -> None:
super().__init__()
if get_option("display.unicode.ambiguous_as_wide"):
self.ambiguous_width = 2
else:
self.ambiguous_width = 1

# Definition of East Asian Width
# https://unicode.org/reports/tr11/
# Ambiguous width can be changed by option
self._EAW_MAP = {"Na": 1, "N": 1, "W": 2, "F": 2, "H": 1}

def len(self, text: str) -> int:
"""
Calculate display width considering unicode East Asian Width
"""
if not isinstance(text, str):
return len(text)

return sum(
self._EAW_MAP.get(east_asian_width(c), self.ambiguous_width) for c in text
)

def justify(
self, texts: Iterable[str], max_len: int, mode: str = "right"
) -> list[str]:
# re-calculate padding space per str considering East Asian Width
def _get_pad(t):
return max_len - self.len(t) + len(t)

if mode == "left":
return [x.ljust(_get_pad(x)) for x in texts]
elif mode == "center":
return [x.center(_get_pad(x)) for x in texts]
else:
return [x.rjust(_get_pad(x)) for x in texts]


def get_adjustment() -> _TextAdjustment:
use_east_asian_width = get_option("display.unicode.east_asian_width")
if use_east_asian_width:
return _EastAsianTextAdjustment()
else:
return _TextAdjustment()


def get_dataframe_repr_params() -> dict[str, Any]:
"""Get the parameters used to repr(dataFrame) calls using DataFrame.to_string.
Expand Down Expand Up @@ -535,7 +470,7 @@ def __init__(

self.tr_frame = self.frame
self.truncate()
self.adj = get_adjustment()
self.adj = printing.get_adjustment()

def get_strcols(self) -> list[list[str]]:
"""
Expand Down Expand Up @@ -1796,13 +1731,13 @@ def _make_fixed_width(
strings: list[str],
justify: str = "right",
minimum: int | None = None,
adj: _TextAdjustment | None = None,
adj: printing._TextAdjustment | None = None,
) -> list[str]:
if len(strings) == 0 or justify == "all":
return strings

if adj is None:
adjustment = get_adjustment()
adjustment = printing.get_adjustment()
else:
adjustment = adj

Expand Down
79 changes: 74 additions & 5 deletions pandas/io/formats/printing.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,14 @@
TypeVar,
Union,
)
from unicodedata import east_asian_width

from pandas._config import get_option

from pandas.core.dtypes.inference import is_sequence

from pandas.io.formats.console import get_console_size

EscapeChars = Union[Mapping[str, str], Iterable[str]]
_KT = TypeVar("_KT")
_VT = TypeVar("_VT")
Expand All @@ -42,7 +45,7 @@ def adjoin(space: int, *lists: list[str], **kwargs) -> str:
function used to justify str. Needed for unicode handling.
"""
strlen = kwargs.pop("strlen", len)
justfunc = kwargs.pop("justfunc", justify)
justfunc = kwargs.pop("justfunc", _adj_justify)

newLists = []
lengths = [max(map(strlen, x)) + space for x in lists[:-1]]
Expand All @@ -57,7 +60,7 @@ def adjoin(space: int, *lists: list[str], **kwargs) -> str:
return "\n".join("".join(lines) for lines in toJoin)


def justify(texts: Iterable[str], max_len: int, mode: str = "right") -> list[str]:
def _adj_justify(texts: Iterable[str], max_len: int, mode: str = "right") -> list[str]:
"""
Perform ljust, center, rjust against string or list-like
"""
Expand Down Expand Up @@ -314,9 +317,6 @@ def format_object_summary(
-------
summary string
"""
from pandas.io.formats.console import get_console_size
from pandas.io.formats.format import get_adjustment

display_width, _ = get_console_size()
if display_width is None:
display_width = get_option("display.width") or 80
Expand Down Expand Up @@ -501,3 +501,72 @@ class PrettyDict(dict[_KT, _VT]):

def __repr__(self) -> str:
return pprint_thing(self)


class _TextAdjustment:
def __init__(self) -> None:
self.encoding = get_option("display.encoding")

def len(self, text: str) -> int:
return len(text)

def justify(self, texts: Any, max_len: int, mode: str = "right") -> list[str]:
"""
Perform ljust, center, rjust against string or list-like
"""
if mode == "left":
return [x.ljust(max_len) for x in texts]
elif mode == "center":
return [x.center(max_len) for x in texts]
else:
return [x.rjust(max_len) for x in texts]

def adjoin(self, space: int, *lists, **kwargs) -> str:
return adjoin(space, *lists, strlen=self.len, justfunc=self.justify, **kwargs)


class _EastAsianTextAdjustment(_TextAdjustment):
def __init__(self) -> None:
super().__init__()
if get_option("display.unicode.ambiguous_as_wide"):
self.ambiguous_width = 2
else:
self.ambiguous_width = 1

# Definition of East Asian Width
# https://unicode.org/reports/tr11/
# Ambiguous width can be changed by option
self._EAW_MAP = {"Na": 1, "N": 1, "W": 2, "F": 2, "H": 1}

def len(self, text: str) -> int:
"""
Calculate display width considering unicode East Asian Width
"""
if not isinstance(text, str):
return len(text)

return sum(
self._EAW_MAP.get(east_asian_width(c), self.ambiguous_width) for c in text
)

def justify(
self, texts: Iterable[str], max_len: int, mode: str = "right"
) -> list[str]:
# re-calculate padding space per str considering East Asian Width
def _get_pad(t):
return max_len - self.len(t) + len(t)

if mode == "left":
return [x.ljust(_get_pad(x)) for x in texts]
elif mode == "center":
return [x.center(_get_pad(x)) for x in texts]
else:
return [x.rjust(_get_pad(x)) for x in texts]


def get_adjustment() -> _TextAdjustment:
use_east_asian_width = get_option("display.unicode.east_asian_width")
if use_east_asian_width:
return _EastAsianTextAdjustment()
else:
return _TextAdjustment()
8 changes: 6 additions & 2 deletions pandas/tests/copy_view/test_constructors.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,9 @@ def test_series_from_series_with_reindex(using_copy_on_write):
def test_series_from_array(using_copy_on_write, idx, dtype, fastpath, arr):
if idx is None or dtype is not None:
fastpath = False
ser = Series(arr, dtype=dtype, index=idx, fastpath=fastpath)
msg = "The 'fastpath' keyword in pd.Series is deprecated"
with tm.assert_produces_warning(DeprecationWarning, match=msg):
ser = Series(arr, dtype=dtype, index=idx, fastpath=fastpath)
ser_orig = ser.copy()
data = getattr(arr, "_data", arr)
if using_copy_on_write:
Expand Down Expand Up @@ -157,7 +159,9 @@ def test_series_from_index_different_dtypes(using_copy_on_write):
def test_series_from_block_manager(using_copy_on_write, idx, dtype, fastpath):
ser = Series([1, 2, 3], dtype="int64")
ser_orig = ser.copy()
ser2 = Series(ser._mgr, dtype=dtype, fastpath=fastpath, index=idx)
msg = "The 'fastpath' keyword in pd.Series is deprecated"
with tm.assert_produces_warning(DeprecationWarning, match=msg):
ser2 = Series(ser._mgr, dtype=dtype, fastpath=fastpath, index=idx)
assert np.shares_memory(get_array(ser), get_array(ser2))
if using_copy_on_write:
assert not ser2._mgr._has_no_reference(0)
Expand Down
2 changes: 1 addition & 1 deletion pandas/tests/io/formats/test_format.py
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ def test_repr_truncation(self):
r = repr(df)
r = r[r.find("\n") + 1 :]

adj = fmt.get_adjustment()
adj = printing.get_adjustment()

for line, value in zip(r.split("\n"), df["B"]):
if adj.len(value) + 1 > max_len:
Expand Down
Loading

0 comments on commit b3288fc

Please sign in to comment.