From d42a6da016599abc3d52ea32f4495eefac0af537 Mon Sep 17 00:00:00 2001 From: Henry Schreiner Date: Tue, 29 Mar 2022 14:02:11 -0400 Subject: [PATCH] fix(types): typing fixes exposed by extra checking Signed-off-by: Henry Schreiner --- pyproject.toml | 3 +-- rich/console.py | 2 +- rich/jupyter.py | 11 +++++++---- rich/measure.py | 4 ++-- rich/pretty.py | 11 +++++++---- rich/progress.py | 4 +--- rich/spinner.py | 3 ++- rich/style.py | 2 +- rich/tree.py | 2 +- 9 files changed, 23 insertions(+), 19 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index c9f22e5c..011a27a4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -54,10 +54,9 @@ build-backend = "poetry.core.masonry.api" [tool.mypy] files = ["rich"] -warn_unused_configs = true show_error_codes = true strict = true -enable_error_code = ["ignore-without-code"] +enable_error_code = ["ignore-without-code", "redundant-expr", "truthy-bool"] [[tool.mypy.overrides]] module = ["pygments.*", "IPython.*", "commonmark.*", "ipywidgets.*"] diff --git a/rich/console.py b/rich/console.py index bcacbc73..1556b10d 100644 --- a/rich/console.py +++ b/rich/console.py @@ -1947,7 +1947,7 @@ class Console: frame = currentframe() if frame is not None: # Use the faster currentframe where implemented - while offset and frame: + while offset and frame is not None: frame = frame.f_back offset -= 1 assert frame is not None diff --git a/rich/jupyter.py b/rich/jupyter.py index fa8948e8..7608bd01 100644 --- a/rich/jupyter.py +++ b/rich/jupyter.py @@ -1,4 +1,7 @@ -from typing import TYPE_CHECKING, Any, Dict, Iterable, List +from typing import Any, Dict, Iterable, List, TYPE_CHECKING, Sequence + +if TYPE_CHECKING: + from rich.console import ConsoleRenderable from . import get_console from .segment import Segment @@ -20,7 +23,7 @@ class JupyterRenderable: self.text = text def _repr_mimebundle_( - self, include: Iterable[str], exclude: Iterable[str], **kwargs: Any + self, include: Sequence[str], exclude: Sequence[str], **kwargs: Any ) -> Dict[str, str]: data = {"text/plain": self.text, "text/html": self.html} if include: @@ -37,8 +40,8 @@ class JupyterMixin: def _repr_mimebundle_( self: "ConsoleRenderable", - include: Iterable[str], - exclude: Iterable[str], + include: Sequence[str], + exclude: Sequence[str], **kwargs: Any, ) -> Dict[str, str]: console = get_console() diff --git a/rich/measure.py b/rich/measure.py index e12787c8..a508ffa8 100644 --- a/rich/measure.py +++ b/rich/measure.py @@ -1,5 +1,5 @@ from operator import itemgetter -from typing import TYPE_CHECKING, Callable, Iterable, NamedTuple, Optional +from typing import TYPE_CHECKING, Callable, NamedTuple, Optional, Sequence from . import errors from .protocol import is_renderable, rich_cast @@ -125,7 +125,7 @@ class Measurement(NamedTuple): def measure_renderables( console: "Console", options: "ConsoleOptions", - renderables: Iterable["RenderableType"], + renderables: Sequence["RenderableType"], ) -> "Measurement": """Get a measurement that would fit a number of renderables. diff --git a/rich/pretty.py b/rich/pretty.py index 8de12787..d3bac94e 100644 --- a/rich/pretty.py +++ b/rich/pretty.py @@ -19,6 +19,7 @@ from typing import ( Iterable, List, Optional, + Sequence, Set, Tuple, Union, @@ -28,8 +29,10 @@ from rich.repr import RichReprResult try: import attr as _attr_module + + _has_attrs = True except ImportError: # pragma: no cover - _attr_module = None # type: ignore[assignment] + _has_attrs = False from . import get_console from ._loop import loop_last @@ -54,12 +57,12 @@ if TYPE_CHECKING: def _is_attr_object(obj: Any) -> bool: """Check if an object was created with attrs module.""" - return _attr_module is not None and _attr_module.has(type(obj)) + return _has_attrs and _attr_module.has(type(obj)) -def _get_attr_fields(obj: Any) -> Iterable["_attr_module.Attribute[Any]"]: +def _get_attr_fields(obj: Any) -> Sequence["_attr_module.Attribute[Any]"]: """Get fields for an attrs object.""" - return _attr_module.fields(type(obj)) if _attr_module is not None else [] + return _attr_module.fields(type(obj)) if _has_attrs else [] def _is_dataclass_repr(obj: object) -> bool: diff --git a/rich/progress.py b/rich/progress.py index e4abbdb6..605afe83 100644 --- a/rich/progress.py +++ b/rich/progress.py @@ -643,9 +643,7 @@ class Progress(JupyterMixin): disable: bool = False, expand: bool = False, ) -> None: - assert ( - refresh_per_second is None or refresh_per_second > 0 - ), "refresh_per_second must be > 0" + assert refresh_per_second > 0, "refresh_per_second must be > 0" self._lock = RLock() self.columns = columns or self.get_default_columns() self.speed_estimate_period = speed_estimate_period diff --git a/rich/spinner.py b/rich/spinner.py index 5b13b1e9..9c814d56 100644 --- a/rich/spinner.py +++ b/rich/spinner.py @@ -79,7 +79,8 @@ class Spinner: self.speed = self._update_speed self._update_speed = 0.0 - if not self.text: + # This normally can't be str, unless someone assigned it later. + if not self.text: # type: ignore[truthy-bool] return frame elif isinstance(self.text, (str, Text)): return Text.assemble(frame, " ", self.text) diff --git a/rich/style.py b/rich/style.py index 0787c331..bccbf234 100644 --- a/rich/style.py +++ b/rich/style.py @@ -740,7 +740,7 @@ class Style: new_style._link = style._link or self._link new_style._link_id = style._link_id or self._link_id new_style._hash = style._hash - new_style._null = self._null or style._null + new_style._null = style._null if self._meta and style._meta: new_style._meta = dumps({**self.meta, **style.meta}) else: diff --git a/rich/tree.py b/rich/tree.py index 0beab7a9..b9b7bbe5 100644 --- a/rich/tree.py +++ b/rich/tree.py @@ -45,7 +45,7 @@ class Tree(JupyterMixin): style: Optional[StyleType] = None, guide_style: Optional[StyleType] = None, expanded: bool = True, - highlight: bool = False, + highlight: Optional[bool] = False, ) -> "Tree": """Add a child tree.