david got a fish trophy!
Add rich to RBTools and replace old modules.
Review Request #15151 — Created July 3, 2026 and submitted
This change adds the
richlibrary as a dependency, and creates the
basic framework for rich output. This is based on a combination of
Christian and my previous attempts at this work.This creates a new RBToolsConsole which wraps two rich
Consoleobjects
for stdout and stderr. This also includes a few helpers for multi-step
operations, some basic status levels, progress, spinners, and table
output. This console is first created in a command's__init__, but
will get recreated after we parse command-line options in order to
properly support the new--color=[auto,always,never]option.When commands are running in JSON output mode, a handler is pushed onto
the console that suppresses output. This allows commands to do what
they've always done: unconditionally write to both stdout/stderr and the
json output object, and whichever one is expected to run will work. The
existing output wrappers have also been updated to write through the
console object, so that can take advantage of the same suppression
method.All uses of the old
colorama,tqdm, andtexttablelibraries have
been replaced with the new rich output, but I've held off on other
output prettification for a separate change.
- Ran unit tests.
- Tested the various values of the
--coloroption, theCOLOR_MODE
config key, and theNO_COLORandFORCE_COLORenvironment variables. - Tested rich output for the
info,install,post, andstatus
commands.
| Summary | ID |
|---|---|
| kmrpxswxxprsrnyspyktlqwrrvwoxzuw |
| Description | From | Last Updated |
|---|---|---|
|
Can you add documentation for the COLOR_MODE config key in docs/rbtools/rbt/configuration/users.rst. |
|
|
|
'rich.table.Table' imported but unused Column: 1 Error code: F401 |
|
|
|
'collections.abc.Sequence' imported but unused Column: 5 Error code: F401 |
|
|
|
The return statements make this a bit wonky to reason about. The code kind of backs this up, because we're … |
|
|
|
This can be an if/else. |
|
|
|
Can we use if config := self.config so we don't have to re-get the attribute? |
|
|
|
We fetch these attributes twice. Let's pull them out. |
|
|
|
The placement of the parents makes this read kind of funky. |
|
|
|
We're accessing self.options.debug several times. Let's pull these out. |
|
|
|
We can now do if output_stream := self.output_stream: here. |
|
|
|
These can start on the Table( line, or could end with a ) on its own line. |
|
|
|
Same here. |
|
|
|
Same here. |
|
|
|
We can use the ColorMode type here. |
|
|
|
This comparison should be in parens. |
|
|
|
Can you swap these so they're in alphabetical order? |
|
|
|
Since order is crucial here, let's make them keyword-only arguments. |
|
|
|
Can we import this at the module level? |
|
|
|
"Rich" |
|
|
|
This is missing docs. |
|
|
|
Your other docstrings elsewhere in the change refer to this as "Rich", so we should keep consistent with these. Or … |
|
|
|
We should have a Prototype for this, so we can get proper typing and documentation on it. |
|
|
|
Let's reference: :py:class:`object.__len__` |
|
|
|
Can we import this at the module level? |
|
|
|
Private methods go below public. |
|
|
|
We can reference ColorMode here. |
|
|
|
We should never override _. This is a really big Claude smell (it's always trying to do this, even when … |
|
|
|
We should type this and use Final. Also, maybe call it DEFAULT_RBTOOLS_STYLES? |
|
|
|
Can we order these alphabetically? |
|
|
|
We reference this somewhat-complex type here and elsewhere in the code. Can we get a TypeAlias for it? If it's … |
|
|
|
Missing Version Added. |
|
|
|
We need a Version added for these. We probably don't need the trailing comment. |
|
|
|
'collections.abc.Mapping' imported but unused Column: 5 Error code: F401 |
|
|
|
These should be using our standard multi-line form. |
|
- Commits:
-
Summary ID kmrpxswxxprsrnyspyktlqwrrvwoxzuw kmrpxswxxprsrnyspyktlqwrrvwoxzuw
Checks run (2 succeeded)
- Commits:
-
Summary ID kmrpxswxxprsrnyspyktlqwrrvwoxzuw kmrpxswxxprsrnyspyktlqwrrvwoxzuw
Checks run (2 succeeded)
-
-
The return statements make this a bit wonky to reason about. The code kind of backs this up, because we're checking late into it for a valid value when we've already ruled out one of them.
I'd suggest:
if options is None: color_mode = 'auto' elif getattr(options, 'json_output', False): color_mode = 'never' else: color_mode = getattr(options, 'color', 'auto') if color_mode not in {'always', 'auto', 'never'}: color_mode = 'auto' if color_mode == 'auto': if os.environ.get('NO_COLOR'); color_mode = 'never' elif os.environ.get('FORCE_COLOR'); color_mode = 'always' return color_modeBy the time we're at the
return, we should have narrowed this to a valid type in all cases, and limited the conditions in which we've forced values. -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Your other docstrings elsewhere in the change refer to this as "Rich", so we should keep consistent with these. Or we could go the other way, avoid the capitalization if we want to say "rich" more generically.
This will apply to instances below as well, depending on the decision.
-
-
-
-
-
-
We should never override
_. This is a really big Claude smell (it's always trying to do this, even when I tell it not to) and not routine in our codebase due to ourgettextusage.Can just use
[0]here or[:2]below, as needed.Same below.
-
-
-
We reference this somewhat-complex type here and elsewhere in the code. Can we get a
TypeAliasfor it?If it's these specific types, maybe we'd also want a
Literalof keys. -
-
- Commits:
-
Summary ID kmrpxswxxprsrnyspyktlqwrrvwoxzuw kmrpxswxxprsrnyspyktlqwrrvwoxzuw