rich icon indicating copy to clipboard operation
rich copied to clipboard

[BUG] rich.inspect() does not appear to honor the "sort" keyword argument

Open rengrub opened this issue 1 year ago • 8 comments

  • [x] I've checked docs and closed issues for possible solutions.
  • [x] I can't find my issue in the FAQ.

Describe the bug

Performing rich.inspect() on a class object with sort=False and sort=True results in the same output for class attributes which are not already naturally in alphabetical order (i.e. both appear sorted alphabetically).

import rich
class Test:
    def __init__(self):
        self.c = 1
        self.b = 2
        self.a = 3

test = Test()
rich.inspect(test)

Result: image

import rich
class Test:
    def __init__(self):
        self.c = 1
        self.b = 2
        self.a = 3

test = Test()
rich.inspect(test, sort=False)

Result: image

Platform Python 3.11.3 WSL: Ubuntu-22.04

If you're using Rich in a terminal:

python -m rich.diagnose
pip freeze | grep rich

If you're using Rich in a Jupyter Notebook, run the following snippet in a cell and paste the output in your bug report.

from rich.diagnose import report
report()
╭────────────────────── <class 'rich.console.Console'> ──────────────────────╮
│ A high level console interface.                                            │
│                                                                            │
│ ╭────────────────────────────────────────────────────────────────────────╮ │
│ │ <console width=115 ColorSystem.TRUECOLOR>                              │ │
│ ╰────────────────────────────────────────────────────────────────────────╯ │
│                                                                            │
│     color_system = 'truecolor'                                             │
│         encoding = 'utf-8'                                                 │
│             file = <ipykernel.iostream.OutStream object at 0x7f96e251ab90> │
│           height = 100                                                     │
│    is_alt_screen = False                                                   │
│ is_dumb_terminal = False                                                   │
│   is_interactive = False                                                   │
│       is_jupyter = True                                                    │
│      is_terminal = False                                                   │
│   legacy_windows = False                                                   │
│         no_color = False                                                   │
│          options = ConsoleOptions(                                         │
│                        size=ConsoleDimensions(width=115, height=100),      │
│                        legacy_windows=False,                               │
│                        min_width=1,                                        │
│                        max_width=115,                                      │
│                        is_terminal=False,                                  │
│                        encoding='utf-8',                                   │
│                        max_height=100,                                     │
│                        justify=None,                                       │
│                        overflow=None,                                      │
│                        no_wrap=False,                                      │
│                        highlight=None,                                     │
│                        markup=None,                                        │
│                        height=None                                         │
│                    )                                                       │
│            quiet = False                                                   │
│           record = False                                                   │
│         safe_box = True                                                    │
│             size = ConsoleDimensions(width=115, height=100)                │
│        soft_wrap = False                                                   │
│           stderr = False                                                   │
│            style = None                                                    │
│         tab_size = 8                                                       │
│            width = 115                                                     │
╰────────────────────────────────────────────────────────────────────────────╯
╭─── <class 'rich._windows.WindowsConsoleFeatures'> ────╮
│ Windows features available.                           │
│                                                       │
│ ╭───────────────────────────────────────────────────╮ │
│ │ WindowsConsoleFeatures(vt=False, truecolor=False) │ │
│ ╰───────────────────────────────────────────────────╯ │
│                                                       │
│ truecolor = False                                     │
│        vt = False                                     │
╰───────────────────────────────────────────────────────╯
╭────── Environment Variables ───────╮
│ {                                  │
│     'TERM': 'xterm-color',         │
│     'COLORTERM': None,             │
│     'CLICOLOR': '1',               │
│     'NO_COLOR': None,              │
│     'TERM_PROGRAM': None,          │
│     'COLUMNS': None,               │
│     'LINES': None,                 │
│     'JUPYTER_COLUMNS': None,       │
│     'JUPYTER_LINES': None,         │
│     'JPY_PARENT_PID': None,        │
│     'VSCODE_VERBOSE_LOGGING': None │
│ }                                  │
╰────────────────────────────────────╯
platform="Linux"
rich==13.7.1

rengrub avatar Jul 18 '24 13:07 rengrub

Thank you for your issue. Give us a little time to review it.

PS. You might want to check the FAQ if you haven't done so already.

This is an automated reply, generated by FAQtory

github-actions[bot] avatar Jul 18 '24 13:07 github-actions[bot]

Presumably rich.inspect relies on Python's dir where the "resulting list is sorted alphabetically"? If that's the case the sort argument doesn't really make sense!

TomJGooding avatar Jul 18 '24 15:07 TomJGooding

Presumably rich.inspect relies on Python's dir

It does: https://github.com/Textualize/rich/blob/a060eed19bfa1d6a9159efcc784ae504fa938e17/rich/_inspect.py#L136-L145

Even if the object defines __dir__() and returns unsorted entries, calling dir() on it will sort them. So I agree with your analysis.

devdanzin avatar Jul 19 '24 20:07 devdanzin

Ahh interesting, look at that, they will always be sorted. So then, what behavior should I expect from the rich.inspect sort keyword argument?

rengrub avatar Jul 21 '24 13:07 rengrub

I suspect in an older version, the output could be unsorted. But it does seem redundant now.

Removing the option would be sensible, but that would constitute a breaking change.

willmcgugan avatar Nov 01 '24 16:11 willmcgugan

Out of curiosity, I went looking through the old Python docs and it looks like the results of dir() have been sorted for a long time! https://docs.python.org/release/1.4/lib/node26.html#1169

TomJGooding avatar Nov 01 '24 18:11 TomJGooding

My goal is to have a natural sort of the values in attributes. as I do not want to have a list like the following

value_0_etc
value_10_etc
value_11_etc
value_1_etc
value_2_etc
...

I want

value_0_etc
value_1_etc
value_2_etc
...
value_10_etc
value_11_etc

So I first though to customize the sort on the output of __dir__, unfortunately the builtin dir internally sorts the output in C.

Then I thought about monkey patching the sort method, and nested closure functions are not trivial monkey patches.

My ideal solution would be to allow sort to take either a bool or a callable key to do the sorting.

if self.sort:
    items.sort(key=self.sort if callable(self.sort) else sort_items)

This way I can pass in sort = natsort.natsort_key, to get my desired sorting.

hardkrash avatar Jun 19 '25 00:06 hardkrash

I just implemented my preferred sort using this line.

        if self.sort:
            items.sort(key=natsort_keygen(key=sort_items))

hardkrash avatar Jun 19 '25 00:06 hardkrash