Skip to content

TYPING: add type hints to pandas\io\formats\printing.py #27579

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 49 additions & 38 deletions pandas/io/formats/printing.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@
"""

import sys
from typing import Callable, Dict, Iterable, List, Optional, Sequence, Tuple, Union

from pandas._config import get_option

from pandas.core.dtypes.inference import is_sequence


def adjoin(space, *lists, **kwargs):
def adjoin(space: int, *lists: List[str], **kwargs) -> str:
"""
Glues together two sets of strings using the amount of space requested.
The idea is to prettify.
Expand Down Expand Up @@ -40,11 +41,11 @@ def adjoin(space, *lists, **kwargs):
newLists.append(nl)
toJoin = zip(*newLists)
for lines in toJoin:
out_lines.append(_join_unicode(lines))
return _join_unicode(out_lines, sep="\n")
out_lines.append("".join(lines))
return "\n".join(out_lines)


def justify(texts, max_len, mode="right"):
def justify(texts: Iterable[str], max_len: int, mode: str = "right") -> List[str]:
"""
Perform ljust, center, rjust against string or list-like
"""
Expand All @@ -56,14 +57,6 @@ def justify(texts, max_len, mode="right"):
return [x.rjust(max_len) for x in texts]


def _join_unicode(lines, sep=""):
try:
return sep.join(lines)
except UnicodeDecodeError:
sep = str(sep)
return sep.join([x.decode("utf-8") if isinstance(x, str) else x for x in lines])


# Unicode consolidation
# ---------------------
#
Expand All @@ -88,7 +81,9 @@ def _join_unicode(lines, sep=""):
# working with straight ascii.


def _pprint_seq(seq, _nest_lvl=0, max_seq_items=None, **kwds):
def _pprint_seq(
seq: Sequence, _nest_lvl: int = 0, max_seq_items: Optional[int] = None, **kwds
) -> str:
"""
internal. pprinter for iterables. you should probably use pprint_thing()
rather then calling this directly.
Expand Down Expand Up @@ -121,7 +116,9 @@ def _pprint_seq(seq, _nest_lvl=0, max_seq_items=None, **kwds):
return fmt.format(body=body)


def _pprint_dict(seq, _nest_lvl=0, max_seq_items=None, **kwds):
def _pprint_dict(
seq: Dict, _nest_lvl: int = 0, max_seq_items: Optional[int] = None, **kwds
) -> str:
"""
internal. pprinter for iterables. you should probably use pprint_thing()
rather then calling this directly.
Expand Down Expand Up @@ -152,12 +149,12 @@ def _pprint_dict(seq, _nest_lvl=0, max_seq_items=None, **kwds):

def pprint_thing(
thing,
_nest_lvl=0,
escape_chars=None,
default_escapes=False,
quote_strings=False,
max_seq_items=None,
):
_nest_lvl: int = 0,
escape_chars: Optional[Union[Dict[str, str], Iterable[str]]] = None,
default_escapes: bool = False,
quote_strings: bool = False,
max_seq_items: Optional[int] = None,
) -> str:
"""
This function is the sanctioned way of converting objects
to a unicode representation.
Expand Down Expand Up @@ -234,12 +231,14 @@ def as_escaped_unicode(thing, escape_chars=escape_chars):
return str(result) # always unicode


def pprint_thing_encoded(object, encoding="utf-8", errors="replace", **kwds):
def pprint_thing_encoded(
object, encoding: str = "utf-8", errors: str = "replace"
) -> bytes:
value = pprint_thing(object) # get unicode representation of object
return value.encode(encoding, errors, **kwds)
return value.encode(encoding, errors)


def _enable_data_resource_formatter(enable):
def _enable_data_resource_formatter(enable: bool) -> None:
if "IPython" not in sys.modules:
# definitely not in IPython
return
Expand Down Expand Up @@ -279,12 +278,12 @@ class TableSchemaFormatter(BaseFormatter):

def format_object_summary(
obj,
formatter,
is_justify=True,
name=None,
indent_for_name=True,
line_break_each_value=False,
):
formatter: Callable,
is_justify: bool = True,
name: Optional[str] = None,
indent_for_name: bool = True,
line_break_each_value: bool = False,
) -> str:
"""
Return the formatted obj as a unicode string

Expand Down Expand Up @@ -448,7 +447,9 @@ def best_len(values):
return summary


def _justify(head, tail):
def _justify(
head: List[Sequence[str]], tail: List[Sequence[str]]
) -> Tuple[List[Tuple[str, ...]], List[Tuple[str, ...]]]:
"""
Justify items in head and tail, so they are right-aligned when stacked.

Expand Down Expand Up @@ -484,10 +485,16 @@ def _justify(head, tail):
tail = [
tuple(x.rjust(max_len) for x, max_len in zip(seq, max_length)) for seq in tail
]
return head, tail
# https://github.com/python/mypy/issues/4975
# error: Incompatible return value type (got "Tuple[List[Sequence[str]],
# List[Sequence[str]]]", expected "Tuple[List[Tuple[str, ...]],
# List[Tuple[str, ...]]]")
return head, tail # type: ignore


def format_object_attrs(obj, include_dtype=True):
def format_object_attrs(
obj: Sequence, include_dtype: bool = True
) -> List[Tuple[str, Union[str, int]]]:
"""
Return a list of tuples of the (attr, formatted_value)
for common attrs, including dtype, name, length
Expand All @@ -501,16 +508,20 @@ def format_object_attrs(obj, include_dtype=True):

Returns
-------
list
list of 2-tuple

"""
attrs = []
attrs = [] # type: List[Tuple[str, Union[str, int]]]
if hasattr(obj, "dtype") and include_dtype:
attrs.append(("dtype", "'{}'".format(obj.dtype)))
# error: "Sequence[Any]" has no attribute "dtype"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm this type of introspection is going to be interesting with annotations. Something to think about moving forward

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

attrs.append(("dtype", "'{}'".format(obj.dtype))) # type: ignore
if getattr(obj, "name", None) is not None:
attrs.append(("name", default_pprint(obj.name)))
elif getattr(obj, "names", None) is not None and any(obj.names):
attrs.append(("names", default_pprint(obj.names)))
# error: "Sequence[Any]" has no attribute "name"
attrs.append(("name", default_pprint(obj.name))) # type: ignore
# error: "Sequence[Any]" has no attribute "names"
elif getattr(obj, "names", None) is not None and any(obj.names): # type: ignore
# error: "Sequence[Any]" has no attribute "names"
attrs.append(("names", default_pprint(obj.names))) # type: ignore
max_seq_items = get_option("display.max_seq_items") or len(obj)
if len(obj) > max_seq_items:
attrs.append(("length", len(obj)))
Expand Down