From e5a448cd5f36bb715e75efe01da89fe0fa52d6b1 Mon Sep 17 00:00:00 2001 From: Benjamin Schubert Date: Tue, 21 Nov 2023 22:05:37 +0000 Subject: [PATCH] pprint: Type annotate the module This will make it easier to refactor --- src/_pytest/_io/pprint.py | 253 ++++++++++++++++++++++++++++++++------ 1 file changed, 217 insertions(+), 36 deletions(-) diff --git a/src/_pytest/_io/pprint.py b/src/_pytest/_io/pprint.py index 8dc2dc028..876723fbb 100644 --- a/src/_pytest/_io/pprint.py +++ b/src/_pytest/_io/pprint.py @@ -21,7 +21,10 @@ from typing import Any from typing import Callable from typing import Dict from typing import IO +from typing import Iterator from typing import List +from typing import Optional +from typing import Tuple class _safe_key: @@ -57,13 +60,13 @@ def _safe_tuple(t): class PrettyPrinter: def __init__( self, - indent=4, - width=80, - depth=None, + indent: int = 4, + width: int = 80, + depth: Optional[int] = None, *, - sort_dicts=True, - underscore_numbers=False, - ): + sort_dicts: bool = True, + underscore_numbers: bool = False, + ) -> None: """Handle pretty printing operations onto a stream using a set of configured parameters. @@ -99,7 +102,15 @@ class PrettyPrinter: self._format(object, sio, 0, 0, {}, 0) return sio.getvalue() - def _format(self, object, stream, indent, allowance, context, level): + def _format( + self, + object: Any, + stream: IO[str], + indent: int, + allowance: int, + context: Dict[int, int], + level: int, + ) -> None: objid = id(object) if objid in context: stream.write(_recursion(object)) @@ -129,7 +140,15 @@ class PrettyPrinter: else: stream.write(self._repr(object, context, level)) - def _pprint_dataclass(self, object, stream, indent, allowance, context, level): + def _pprint_dataclass( + self, + object: Any, + stream: IO[str], + indent: int, + allowance: int, + context: Dict[int, int], + level: int, + ) -> None: cls_name = object.__class__.__name__ items = [ (f.name, getattr(object, f.name)) @@ -142,10 +161,18 @@ class PrettyPrinter: _dispatch: Dict[ Callable[..., str], - Callable[["PrettyPrinter", Any, IO[str], int, int, Dict[int, int], int], str], + Callable[["PrettyPrinter", Any, IO[str], int, int, Dict[int, int], int], None], ] = {} - def _pprint_dict(self, object, stream, indent, allowance, context, level): + def _pprint_dict( + self, + object: Any, + stream: IO[str], + indent: int, + allowance: int, + context: Dict[int, int], + level: int, + ) -> None: write = stream.write write("{") if self._sort_dicts: @@ -157,7 +184,15 @@ class PrettyPrinter: _dispatch[dict.__repr__] = _pprint_dict - def _pprint_ordered_dict(self, object, stream, indent, allowance, context, level): + def _pprint_ordered_dict( + self, + object: Any, + stream: IO[str], + indent: int, + allowance: int, + context: Dict[int, int], + level: int, + ) -> None: if not len(object): stream.write(repr(object)) return @@ -168,21 +203,45 @@ class PrettyPrinter: _dispatch[_collections.OrderedDict.__repr__] = _pprint_ordered_dict - def _pprint_list(self, object, stream, indent, allowance, context, level): + def _pprint_list( + self, + object: Any, + stream: IO[str], + indent: int, + allowance: int, + context: Dict[int, int], + level: int, + ) -> None: stream.write("[") self._format_items(object, stream, indent, allowance, context, level) stream.write("]") _dispatch[list.__repr__] = _pprint_list - def _pprint_tuple(self, object, stream, indent, allowance, context, level): + def _pprint_tuple( + self, + object: Any, + stream: IO[str], + indent: int, + allowance: int, + context: Dict[int, int], + level: int, + ) -> None: stream.write("(") self._format_items(object, stream, indent, allowance, context, level) stream.write(")") _dispatch[tuple.__repr__] = _pprint_tuple - def _pprint_set(self, object, stream, indent, allowance, context, level): + def _pprint_set( + self, + object: Any, + stream: IO[str], + indent: int, + allowance: int, + context: Dict[int, int], + level: int, + ) -> None: if not len(object): stream.write(repr(object)) return @@ -200,7 +259,15 @@ class PrettyPrinter: _dispatch[set.__repr__] = _pprint_set _dispatch[frozenset.__repr__] = _pprint_set - def _pprint_str(self, object, stream, indent, allowance, context, level): + def _pprint_str( + self, + object: Any, + stream: IO[str], + indent: int, + allowance: int, + context: Dict[int, int], + level: int, + ) -> None: write = stream.write if not len(object): write(repr(object)) @@ -251,7 +318,15 @@ class PrettyPrinter: _dispatch[str.__repr__] = _pprint_str - def _pprint_bytes(self, object, stream, indent, allowance, context, level): + def _pprint_bytes( + self, + object: Any, + stream: IO[str], + indent: int, + allowance: int, + context: Dict[int, int], + level: int, + ) -> None: write = stream.write if len(object) <= 4: write(repr(object)) @@ -272,7 +347,15 @@ class PrettyPrinter: _dispatch[bytes.__repr__] = _pprint_bytes - def _pprint_bytearray(self, object, stream, indent, allowance, context, level): + def _pprint_bytearray( + self, + object: Any, + stream: IO[str], + indent: int, + allowance: int, + context: Dict[int, int], + level: int, + ) -> None: write = stream.write write("bytearray(") self._pprint_bytes( @@ -282,7 +365,15 @@ class PrettyPrinter: _dispatch[bytearray.__repr__] = _pprint_bytearray - def _pprint_mappingproxy(self, object, stream, indent, allowance, context, level): + def _pprint_mappingproxy( + self, + object: Any, + stream: IO[str], + indent: int, + allowance: int, + context: Dict[int, int], + level: int, + ) -> None: stream.write("mappingproxy(") self._format(object.copy(), stream, indent, allowance, context, level) stream.write(")") @@ -290,8 +381,14 @@ class PrettyPrinter: _dispatch[_types.MappingProxyType.__repr__] = _pprint_mappingproxy def _pprint_simplenamespace( - self, object, stream, indent, allowance, context, level - ): + self, + object: Any, + stream: IO[str], + indent: int, + allowance: int, + context: Dict[int, int], + level: int, + ) -> None: if type(object) is _types.SimpleNamespace: # The SimpleNamespace repr is "namespace" instead of the class # name, so we do the same here. For subclasses; use the class name. @@ -305,7 +402,15 @@ class PrettyPrinter: _dispatch[_types.SimpleNamespace.__repr__] = _pprint_simplenamespace - def _format_dict_items(self, items, stream, indent, allowance, context, level): + def _format_dict_items( + self, + items: List[Tuple[Any, Any]], + stream: IO[str], + indent: int, + allowance: int, + context: Dict[int, int], + level: int, + ) -> None: if not items: return @@ -321,7 +426,15 @@ class PrettyPrinter: write("\n" + " " * indent) - def _format_namespace_items(self, items, stream, indent, allowance, context, level): + def _format_namespace_items( + self, + items: List[Tuple[Any, Any]], + stream: IO[str], + indent: int, + allowance: int, + context: Dict[int, int], + level: int, + ) -> None: if not items: return @@ -350,7 +463,15 @@ class PrettyPrinter: write("\n" + " " * indent) - def _format_items(self, items, stream, indent, allowance, context, level): + def _format_items( + self, + items: List[Any], + stream: IO[str], + indent: int, + allowance: int, + context: Dict[int, int], + level: int, + ) -> None: if not items: return @@ -365,7 +486,7 @@ class PrettyPrinter: write("\n" + " " * indent) - def _repr(self, object, context, level): + def _repr(self, object: Any, context: Dict[int, int], level: int) -> str: repr, readable, recursive = self.format( object, context.copy(), self._depth, level ) @@ -375,14 +496,24 @@ class PrettyPrinter: self._recursive = True return repr - def format(self, object, context, maxlevels, level): + def format( + self, object: Any, context: Dict[int, int], maxlevels: Optional[int], level: int + ) -> Tuple[str, bool, bool]: """Format object for a specific context, returning a string and flags indicating whether the representation is 'readable' and whether the object represents a recursive construct. """ return self._safe_repr(object, context, maxlevels, level) - def _pprint_default_dict(self, object, stream, indent, allowance, context, level): + def _pprint_default_dict( + self, + object: Any, + stream: IO[str], + indent: int, + allowance: int, + context: Dict[int, int], + level: int, + ) -> None: rdf = self._repr(object.default_factory, context, level) stream.write(f"{object.__class__.__name__}({rdf}, ") self._pprint_dict(object, stream, indent, allowance, context, level) @@ -390,7 +521,15 @@ class PrettyPrinter: _dispatch[_collections.defaultdict.__repr__] = _pprint_default_dict - def _pprint_counter(self, object, stream, indent, allowance, context, level): + def _pprint_counter( + self, + object: Any, + stream: IO[str], + indent: int, + allowance: int, + context: Dict[int, int], + level: int, + ) -> None: stream.write(object.__class__.__name__ + "(") if object: @@ -403,7 +542,15 @@ class PrettyPrinter: _dispatch[_collections.Counter.__repr__] = _pprint_counter - def _pprint_chain_map(self, object, stream, indent, allowance, context, level): + def _pprint_chain_map( + self, + object: Any, + stream: IO[str], + indent: int, + allowance: int, + context: Dict[int, int], + level: int, + ) -> None: if not len(object.maps) or (len(object.maps) == 1 and not len(object.maps[0])): stream.write(repr(object)) return @@ -414,7 +561,15 @@ class PrettyPrinter: _dispatch[_collections.ChainMap.__repr__] = _pprint_chain_map - def _pprint_deque(self, object, stream, indent, allowance, context, level): + def _pprint_deque( + self, + object: Any, + stream: IO[str], + indent: int, + allowance: int, + context: Dict[int, int], + level: int, + ) -> None: stream.write(object.__class__.__name__ + "(") if object.maxlen is not None: stream.write("maxlen=%d, " % object.maxlen) @@ -425,22 +580,48 @@ class PrettyPrinter: _dispatch[_collections.deque.__repr__] = _pprint_deque - def _pprint_user_dict(self, object, stream, indent, allowance, context, level): + def _pprint_user_dict( + self, + object: Any, + stream: IO[str], + indent: int, + allowance: int, + context: Dict[int, int], + level: int, + ) -> None: self._format(object.data, stream, indent, allowance, context, level - 1) _dispatch[_collections.UserDict.__repr__] = _pprint_user_dict - def _pprint_user_list(self, object, stream, indent, allowance, context, level): + def _pprint_user_list( + self, + object: Any, + stream: IO[str], + indent: int, + allowance: int, + context: Dict[int, int], + level: int, + ) -> None: self._format(object.data, stream, indent, allowance, context, level - 1) _dispatch[_collections.UserList.__repr__] = _pprint_user_list - def _pprint_user_string(self, object, stream, indent, allowance, context, level): + def _pprint_user_string( + self, + object: Any, + stream: IO[str], + indent: int, + allowance: int, + context: Dict[int, int], + level: int, + ) -> None: self._format(object.data, stream, indent, allowance, context, level - 1) _dispatch[_collections.UserString.__repr__] = _pprint_user_string - def _safe_repr(self, object, context, maxlevels, level): + def _safe_repr( + self, object: Any, context: Dict[int, int], maxlevels: Optional[int], level: int + ) -> Tuple[str, bool, bool]: # Return triple (repr_string, isreadable, isrecursive). typ = type(object) if typ in _builtin_scalars: @@ -517,17 +698,17 @@ class PrettyPrinter: return format % ", ".join(components), readable, recursive rep = repr(object) - return rep, (rep and not rep.startswith("<")), False + return rep, bool(rep and not rep.startswith("<")), False _builtin_scalars = frozenset({str, bytes, bytearray, float, complex, bool, type(None)}) -def _recursion(object): +def _recursion(object: Any) -> str: return f"" -def _wrap_bytes_repr(object, width, allowance): +def _wrap_bytes_repr(object: Any, width: int, allowance: int) -> Iterator[str]: current = b"" last = len(object) // 4 * 4 for i in range(0, len(object), 4):