Skip to content

Commit

Permalink
REF: avoid circular imports in formats (#55467)
Browse files Browse the repository at this point in the history
* REF: avoid circular import of get_adjustment

* revert
  • Loading branch information
jbrockmendel authored Oct 10, 2023
1 parent 1025151 commit e22bfb3
Show file tree
Hide file tree
Showing 6 changed files with 92 additions and 86 deletions.
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 @@ -1437,8 +1440,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
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 @@ -347,69 +345,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 @@ -529,7 +464,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 @@ -1789,13 +1724,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()
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
11 changes: 5 additions & 6 deletions pandas/tests/io/formats/test_printing.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
import pandas as pd

from pandas.io.formats import printing
import pandas.io.formats.format as fmt


def test_adjoin():
Expand Down Expand Up @@ -48,7 +47,7 @@ def test_adjoin_unicode(self):
adjoined = printing.adjoin(2, *data)
assert adjoined == expected

adj = fmt._EastAsianTextAdjustment()
adj = printing._EastAsianTextAdjustment()

expected = """あ dd ggg
b ええ hhh
Expand All @@ -73,7 +72,7 @@ def test_adjoin_unicode(self):
assert adj.len(cols[2]) == 26

def test_justify(self):
adj = fmt._EastAsianTextAdjustment()
adj = printing._EastAsianTextAdjustment()

def just(x, *args, **kwargs):
# wrapper to test single str
Expand All @@ -95,7 +94,7 @@ def just(x, *args, **kwargs):
assert just("パンダ", 10, mode="right") == " パンダ"

def test_east_asian_len(self):
adj = fmt._EastAsianTextAdjustment()
adj = printing._EastAsianTextAdjustment()

assert adj.len("abc") == 3
assert adj.len("abc") == 3
Expand All @@ -106,11 +105,11 @@ def test_east_asian_len(self):
assert adj.len("パンダpanda") == 10

def test_ambiguous_width(self):
adj = fmt._EastAsianTextAdjustment()
adj = printing._EastAsianTextAdjustment()
assert adj.len("¡¡ab") == 4

with cf.option_context("display.unicode.ambiguous_as_wide", True):
adj = fmt._EastAsianTextAdjustment()
adj = printing._EastAsianTextAdjustment()
assert adj.len("¡¡ab") == 6

data = [["あ", "b", "c"], ["dd", "ええ", "ff"], ["ggg", "¡¡ab", "いいい"]]
Expand Down

0 comments on commit e22bfb3

Please sign in to comment.