← mined_oracle

rich_2366

failed WRONG_FIX UNSUBMITTED wrong_fix_unsubmitted(None) · None tool calls · 0 s · Textualize/rich

Task input

(not found in data/tasks.jsonl)

Tool calls (0)

#ToolArgumentsResult
No trace captured.

Patch

--- a/rich/_inspect.py
+++ b/rich/_inspect.py
@@ -2,7 +2,7 @@ from __future__ import absolute_import
 
 import inspect
 from inspect import cleandoc, getdoc, getfile, isclass, ismodule, signature
-from typing import Any, Iterable, Optional, Tuple
+from typing import Any, Collection, Iterable, Optional, Tuple, Type, Union
 
 from .console import Group, RenderableType
 from .control import escape_control_codes
@@ -233,3 +233,38 @@ class Inspect(JupyterMixin):
         if not self.help:
             docs = _first_paragraph(docs)
         return escape_control_codes(docs)
+
+
+def get_object_types_mro(obj: Union[object, Type[Any]]) -> Tuple[type, ...]:
+    """Returns the MRO of an object's class, or of the object itself if it's a class."""
+    if not hasattr(obj, "__mro__"):
+        # N.B. we cannot use `if type(obj) is type` here because it doesn't work with
+        # some types of classes, such as the ones that use abc.ABCMeta.
+        obj = type(obj)
+    return getattr(obj, "__mro__", ())
+
+
+def get_object_types_mro_as_strings(obj: object) -> Collection[str]:
+    """
+    Returns the MRO of an object's class as full qualified names, or of the object itself if it's a class.
+
+    Examples:
+        `object_types_mro_as_strings(JSONDecoder)` will return `['json.decoder.JSONDecoder', 'builtins.object']`
+    """
+    return [
+        f'{getattr(type_, "__module__", "")}.{getattr(type_, "__qualname__", "")}'
+        for type_ in get_object_types_mro(obj)
+    ]
+
+
+def is_object_one_of_types(
+    obj: object, fully_qualified_types_names: Collection[str]
+) -> bool:
+    """
+    Returns `True` if the given object's class (or the object itself, if it's a class) has one of the
+    fully qualified names in its MRO.
+    """
+    for type_name in get_object_types_mro_as_strings(obj):
+        if type_name in fully_qualified_types_names:
+            return True
+    return False
--- a/rich/jupyter.py
+++ b/rich/jupyter.py
@@ -1,4 +1,4 @@
-from typing import Any, Dict, Iterable, List, TYPE_CHECKING, Sequence
+from typing import TYPE_CHECKING, Any, Dict, Iterable, List, Sequence
 
 if TYPE_CHECKING:
     from rich.console import ConsoleRenderable
--- a/rich/pretty.py
+++ b/rich/pretty.py
@@ -55,6 +55,13 @@ if TYPE_CHECKING:
     )
 
 
+JUPYTER_CLASSES_TO_NOT_RENDER = {
+    # Matplotlib "Artists" manage their own rendering in a Jupyter notebook, and we should not try to render them too.
+    # "Typically, all [Matplotlib] visible elements in a figure are subclasses of Artist."
+    "matplotlib.artist.Artist",
+}
+
+
 def _is_attr_object(obj: Any) -> bool:
     """Check if an object was created with attrs module."""
     return _has_attrs and _attr_module.has(type(obj))
@@ -115,7 +122,9 @@ def _ipy_display_hook(
     max_string: Optional[int] = None,
     expand_all: bool = False,
 ) -> None:
-    from .console import ConsoleRenderable  # needed here to prevent circular import
+    # needed here to prevent circular import:
+    from ._inspect import is_object_one_of_types
+    from .console import ConsoleRenderable
 
     # always skip rich generated jupyter renderables or None values
     if _safe_isinstance(value, JupyterRenderable) or value is None:
@@ -148,6 +157,13 @@ def _ipy_display_hook(
                 if repr_result is not None:
                     return  # Delegate rendering to IPython
 
+        # When in a Jupyter notebook let's avoid the display of some specific classes,
+        # as they result in the rendering of useless and noisy lines such as `<Figure size 432x288 with 1 Axes>`.
+        # What does this do?
+        # --> if the class has "matplotlib.artist.Artist" in its hierarchy for example, we don't render it.
+        if is_object_one_of_types(value, JUPYTER_CLASSES_TO_NOT_RENDER):
+            return
+
     # certain renderables should start on a new line
     if _safe_isinstance(value, ConsoleRenderable):
         console.line()

Test output

show
.F
=================================== FAILURES ===================================
______________________________ test_inspect_text _______________________________

    @skip_pypy3
    def test_inspect_text():
        expected = (
            "╭──────────────── <class 'str'> ─────────────────╮\n"
            "│ str(object='') -> str                          │\n"
            "│ str(bytes_or_buffer[, encoding[, errors]]) ->  │\n"
            "│ str                                            │\n"
            "│                                                │\n"
            "│ 33 attribute(s) not shown. Run                 │\n"
            "│ inspect(inspect) for options.                  │\n"
            "╰────────────────────────────────────────────────╯\n"
        )
        print(repr(expected))
>       assert expected == render("Hello")
E       AssertionError: assert '╭───────────...──────────╯\n' == '╭───────────...──────────╯\n'
E         
E         Skipping 248 identical leading characters in diff, use -v to show
E         Skipping 140 identical trailing characters in diff, use -v to show
E                │
E         - │ 34 attribut
E         ?    ^
E         + │ 33 attribut
E         ?    ^

tests/test_inspect.py:112: AssertionError
----------------------------- Captured stdout call -----------------------------
"╭──────────────── <class 'str'> ─────────────────╮\n│ str(object='') -> str                          │\n│ str(bytes_or_buffer[, encoding[, errors]]) ->  │\n│ str                                            │\n│                                                │\n│ 33 attribute(s) not shown. Run                 │\n│ inspect(inspect) for options.                  │\n╰────────────────────────────────────────────────╯\n"
!!!!!!!!!!!!!!!!!!!!!!!!!! stopping after 1 failures !!!!!!!!!!!!!!!!!!!!!!!!!!!
1 failed, 1 passed in 0.17s