← baseline_full_v2

rich_3894

failed NO_PATCH NO_PATCH UNSUBMITTED empty_patch(None) · None tool calls · 0 s · Textualize/rich

Task input

Handle unusual __qualname__ in inspect

<!--
Please note that Rich isn't accepting any new features at this point.

If a feature can be implemented without modifying the core library, then
they should be released as a third-party module. I can accept updates to the
core library that make it easier to extend (think hooks).

Bugfixes are always welcome of course.

Sometimes it is not clear what is a feature and what is a bug fix.
If there is any doubt, please open a discussion first.

-->

<!--
*Are you contributing typo fixes?*

If your PR solely consists of typos, at least one must be in the docs to warrant an addition to CONTRIBUTORS.md
-->

## Type of changes

- [x] Bug fix
- [ ] New feature
- [ ] Documentation / docstrings
- [x] Tests
- [ ] Other

## Checklist

- [x] I've run the latest [black](https://github.com/psf/black) with default args on new code.
- [x] I've updated CHANGELOG.md and CONTRIBUTORS.md where appropriate (see note about typos above).
- [x] I've added tests for new code.
- [x] I accept that @willmcgugan may be pedantic in the code review.

## Description

I discovered, that an object with an unusual `__qualname__` attribute (not a `str`, e.g. a descriptor) causes `inspect` to fail.
This can happen if an object is created this way intentionally, but I discovered it, when decorating a class with `@functools.lru_cache` which forwards the underlying attributes using a descriptor when it can't add the to it's `__dict__` because the class uses `__slots__`:

```python
from functools import lru_cache
from rich import inspect


@lru_cache
class Klaas:
    __slots__ = ("__qualname__",)


if __name__ == "__main__":
    from rich.traceback import install

    install()

    inspect(Klaas.__qualname__)
    inspect(Klaas, all=True)
```

I fixed it by checking the type of `__qualname__` falling back to `__name__` and if that isn't a `str` using the already provided fallback.

Tool calls (0)

#ToolArgumentsResult
No trace captured.

Test output

show
...s....sss...F
=================================== FAILURES ===================================
____________________________ test_qualname_in_slots ____________________________

    def test_qualname_in_slots():
        from functools import lru_cache
    
        @lru_cache
        class Klass:
            __slots__ = ("__qualname__",)
    
        try:
>           inspect(Klass)

tests/test_inspect.py:415: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
rich/__init__.py:173: in inspect
    _console.print(_inspect)
rich/console.py:1698: in print
    renderables = self._collect_renderables(
rich/console.py:1555: in _collect_renderables
    renderable = rich_cast(renderable)
rich/protocol.py:36: in rich_cast
    renderable = cast_method()
rich/_inspect.py:76: in __rich__
    Group(*self._render()),
rich/_inspect.py:153: in _render
    signature = self._get_signature("", obj)
rich/_inspect.py:113: in _get_signature
    qual_signature = Text.assemble(
rich/text.py:397: in assemble
    append(*part)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <text 'def ' [Span(0, 4, 'inspect.def')] ''>
text = <member '__qualname__' of 'Klass' objects>, style = 'inspect.callable'

    def append(
        self, text: Union["Text", str], style: Optional[Union[str, "Style"]] = None
    ) -> "Text":
        """Add text with an optional style.
    
        Args:
            text (Union[Text, str]): A str or Text to append.
            style (str, optional): A style name. Defaults to None.
    
        Returns:
            Text: Returns self for chaining.
        """
    
        if not isinstance(text, (str, Text)):
>           raise TypeError("Only str or Text can be appended to Text")
E           TypeError: Only str or Text can be appended to Text

rich/text.py:979: TypeError

During handling of the above exception, another exception occurred:

    def test_qualname_in_slots():
        from functools import lru_cache
    
        @lru_cache
        class Klass:
            __slots__ = ("__qualname__",)
    
        try:
            inspect(Klass)
        except Exception as e:
>           assert False, f"Class with __qualname__ in __slots__ shouldn't raise {e}"
E           AssertionError: Class with __qualname__ in __slots__ shouldn't raise Only str or Text can be appended to Text
E           assert False

tests/test_inspect.py:417: AssertionError
!!!!!!!!!!!!!!!!!!!!!!!!!! stopping after 1 failures !!!!!!!!!!!!!!!!!!!!!!!!!!!
1 failed, 10 passed, 4 skipped in 0.18s