Skip to content
This repository was archived by the owner on Feb 20, 2026. It is now read-only.

Commit b3a7943

Browse files
committed
Fix bug when using info_table with keys="headers"
1 parent be2aaf9 commit b3a7943

2 files changed

Lines changed: 99 additions & 11 deletions

File tree

cli_ui/__init__.py

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -409,17 +409,31 @@ def tabs(num: int) -> str:
409409
def info_table(
410410
data: Any, *, headers: Union[str, Sequence[str]] = (), fileobj: FileObj = sys.stdout
411411
) -> None:
412-
colored_data = list()
413-
plain_data = list()
414-
for row in data:
415-
colored_row = list()
416-
plain_row = list()
417-
for item in row:
418-
colored_str, plain_str = process_tokens(item, end="")
419-
colored_row.append(colored_str)
420-
plain_row.append(plain_str)
421-
colored_data.append(colored_row)
422-
plain_data.append(plain_row)
412+
if headers == "keys":
413+
colored_data: Any = dict()
414+
plain_data: Any = dict()
415+
for key, sequence in data.items():
416+
colored_sequence = list()
417+
plain_sequence = list()
418+
for item in sequence:
419+
colored_str, plain_str = process_tokens(item, end="")
420+
colored_sequence.append(colored_str)
421+
plain_sequence.append(plain_str)
422+
colored_key, plain_key = process_tokens(key, end="")
423+
colored_data[colored_key] = colored_sequence
424+
plain_data[plain_key] = plain_sequence
425+
else:
426+
colored_data = list()
427+
plain_data = list()
428+
for row in data:
429+
colored_row = list()
430+
plain_row = list()
431+
for item in row:
432+
colored_str, plain_str = process_tokens(item, end="")
433+
colored_row.append(colored_str)
434+
plain_row.append(plain_str)
435+
colored_data.append(colored_row)
436+
plain_data.append(plain_row)
423437
if config_color(fileobj):
424438
data_for_tabulate = colored_data
425439
else:

cli_ui/tests/test_cli_ui.py

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,80 @@ def test_timestamp(dumb_tty: DumbTTY, toggle_timestamp: None) -> None:
113113
assert datetime.datetime.strptime(match.groups()[0], "%Y-%m-%d %H:%M:%S")
114114

115115

116+
def test_table_with_lists_no_color(dumb_tty: DumbTTY) -> None:
117+
headers = ["name", "score"]
118+
data = [
119+
[(cli_ui.bold, "John"), (cli_ui.green, 10)],
120+
[(cli_ui.bold, "Jane"), (cli_ui.green, 5)],
121+
]
122+
cli_ui.info_table(data, headers=headers, fileobj=dumb_tty)
123+
actual = dumb_tty.getvalue()
124+
# fmt: off
125+
expected = (
126+
"name score\n"
127+
"------ -------\n"
128+
"John 10\n"
129+
"Jane 5\n"
130+
)
131+
# fmt: on
132+
assert actual == expected
133+
134+
135+
def test_table_with_dict_no_color(dumb_tty: DumbTTY) -> None:
136+
data = {
137+
(cli_ui.bold, "Name"): [(cli_ui.green, "Alice"), (cli_ui.green, "Bob")],
138+
(cli_ui.bold, "Age"): [(cli_ui.blue, 24), (cli_ui.blue, 9)],
139+
}
140+
cli_ui.info_table(data, headers="keys", fileobj=dumb_tty)
141+
actual = dumb_tty.getvalue()
142+
# fmt: off
143+
expected = (
144+
"Name Age\n"
145+
"------ -----\n"
146+
"Alice 24\n"
147+
"Bob 9\n"
148+
)
149+
# fmt: on
150+
assert actual == expected
151+
152+
153+
def test_table_with_dict_and_color(smart_tty: SmartTTY) -> None:
154+
data = {
155+
(cli_ui.bold, "Name",): [(cli_ui.green, "Alice"), (cli_ui.green, "Bob")],
156+
(cli_ui.bold, "Age",): [(cli_ui.blue, 24), (cli_ui.blue, 9)],
157+
}
158+
cli_ui.info_table(data, headers="keys", fileobj=smart_tty)
159+
actual = smart_tty.getvalue()
160+
# fmt: off
161+
expected = (
162+
f"{BRIGHT}Name{RESET_ALL} {BRIGHT}Age{RESET_ALL}\n"
163+
"------ -----\n"
164+
f"{GREEN}Alice{RESET_ALL} {BLUE}24{RESET_ALL}\n"
165+
f"{GREEN}Bob{RESET_ALL} {BLUE}9{RESET_ALL}\n"
166+
)
167+
# fmt: on
168+
assert actual == expected
169+
170+
171+
def test_table_with_lists_with_color(smart_tty: SmartTTY) -> None:
172+
headers = ["name", "score"]
173+
data = [
174+
[(cli_ui.bold, "John"), (cli_ui.green, 10)],
175+
[(cli_ui.bold, "Jane"), (cli_ui.green, 5)],
176+
]
177+
cli_ui.info_table(data, headers=headers, fileobj=smart_tty)
178+
actual = smart_tty.getvalue()
179+
# fmt: off
180+
expected = (
181+
"name score\n"
182+
"------ -------\n"
183+
f"{BRIGHT}John{RESET_ALL} {GREEN}10{RESET_ALL}\n"
184+
f"{BRIGHT}Jane{RESET_ALL} {GREEN}5{RESET_ALL}\n"
185+
)
186+
# fmt: on
187+
assert actual == expected
188+
189+
116190
def test_record_message(message_recorder: MessageRecorder) -> None:
117191
cli_ui.info_1("This is foo")
118192
assert message_recorder.find("foo")

0 commit comments

Comments
 (0)