Honor --no-headers for --fmt and --table output (#566) (#751)

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Johnson K C 2026-07-06 09:54:17 -07:00 committed by GitHub
commit d516e58543
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 67 additions and 11 deletions

View file

@ -116,7 +116,7 @@ See :ref:`cli_query`.
--arrays Output rows as arrays instead of objects
--csv Output CSV
--tsv Output TSV
--no-headers Omit CSV headers
--no-headers Omit headers from CSV/TSV and table/--fmt output
-t, --table Output as a formatted table
--fmt TEXT Table format - one of asciidoc, colon_grid,
double_grid, double_outline, fancy_grid,
@ -185,7 +185,7 @@ See :ref:`cli_memory`.
--arrays Output rows as arrays instead of objects
--csv Output CSV
--tsv Output TSV
--no-headers Omit CSV headers
--no-headers Omit headers from CSV/TSV and table/--fmt output
-t, --table Output as a formatted table
--fmt TEXT Table format - one of asciidoc, colon_grid,
double_grid, double_outline, fancy_grid,
@ -422,7 +422,7 @@ See :ref:`cli_search`.
--arrays Output rows as arrays instead of objects
--csv Output CSV
--tsv Output TSV
--no-headers Omit CSV headers
--no-headers Omit headers from CSV/TSV and table/--fmt output
-t, --table Output as a formatted table
--fmt TEXT Table format - one of asciidoc, colon_grid,
double_grid, double_outline, fancy_grid, fancy_outline,
@ -688,7 +688,7 @@ See :ref:`cli_tables`.
--arrays Output rows as arrays instead of objects
--csv Output CSV
--tsv Output TSV
--no-headers Omit CSV headers
--no-headers Omit headers from CSV/TSV and table/--fmt output
-t, --table Output as a formatted table
--fmt TEXT Table format - one of asciidoc, colon_grid,
double_grid, double_outline, fancy_grid, fancy_outline,
@ -730,7 +730,7 @@ See :ref:`cli_views`.
--arrays Output rows as arrays instead of objects
--csv Output CSV
--tsv Output TSV
--no-headers Omit CSV headers
--no-headers Omit headers from CSV/TSV and table/--fmt output
-t, --table Output as a formatted table
--fmt TEXT Table format - one of asciidoc, colon_grid,
double_grid, double_outline, fancy_grid, fancy_outline,
@ -777,7 +777,7 @@ See :ref:`cli_rows`.
--arrays Output rows as arrays instead of objects
--csv Output CSV
--tsv Output TSV
--no-headers Omit CSV headers
--no-headers Omit headers from CSV/TSV and table/--fmt output
-t, --table Output as a formatted table
--fmt TEXT Table format - one of asciidoc, colon_grid,
double_grid, double_outline, fancy_grid,
@ -817,7 +817,7 @@ See :ref:`cli_triggers`.
--arrays Output rows as arrays instead of objects
--csv Output CSV
--tsv Output TSV
--no-headers Omit CSV headers
--no-headers Omit headers from CSV/TSV and table/--fmt output
-t, --table Output as a formatted table
--fmt TEXT Table format - one of asciidoc, colon_grid,
double_grid, double_outline, fancy_grid, fancy_outline,
@ -857,7 +857,7 @@ See :ref:`cli_indexes`.
--arrays Output rows as arrays instead of objects
--csv Output CSV
--tsv Output TSV
--no-headers Omit CSV headers
--no-headers Omit headers from CSV/TSV and table/--fmt output
-t, --table Output as a formatted table
--fmt TEXT Table format - one of asciidoc, colon_grid,
double_grid, double_outline, fancy_grid, fancy_outline,

View file

@ -111,7 +111,11 @@ def output_options(fn):
),
click.option("--csv", is_flag=True, help="Output CSV"),
click.option("--tsv", is_flag=True, help="Output TSV"),
click.option("--no-headers", is_flag=True, help="Omit CSV headers"),
click.option(
"--no-headers",
is_flag=True,
help="Omit headers from CSV/TSV and table/--fmt output",
),
click.option(
"-t", "--table", is_flag=True, help="Output as a formatted table"
),
@ -240,7 +244,13 @@ def tables(
yield row
if table or fmt:
print(tabulate.tabulate(_iter(), headers=headers, tablefmt=fmt or "simple"))
print(
tabulate.tabulate(
_iter(),
headers=() if no_headers else headers,
tablefmt=fmt or "simple",
)
)
elif csv or tsv:
writer = csv_std.writer(sys.stdout, dialect="excel-tab" if tsv else "excel")
if not no_headers:
@ -2145,7 +2155,9 @@ def _execute_query(
elif fmt or table:
print(
tabulate.tabulate(
list(cursor), headers=headers, tablefmt=fmt or "simple"
list(cursor),
headers=() if no_headers else headers,
tablefmt=fmt or "simple",
)
)
elif csv or tsv:

View file

@ -195,6 +195,50 @@ def test_output_table(db_path, options, expected):
assert expected == result.output.strip()
@pytest.mark.parametrize(
"fmt_option", [["--fmt", "simple"], ["-t"], ["--fmt", "github"]]
)
def test_output_table_no_headers(db_path, fmt_option):
# --no-headers should omit the header row from --fmt/--table output too, not
# just from --csv/--tsv (#566). Previously the flag was silently ignored for
# tabulate formats and the column names were always printed.
db = Database(db_path)
with db.conn:
db["dogs"].insert_all(
[
{"id": 1, "name": "Cleo", "age": 4},
{"id": 2, "name": "Pancakes", "age": 2},
]
)
sql = "select id, name, age from dogs order by id"
with_headers = CliRunner().invoke(cli.cli, ["query", db_path, sql] + fmt_option)
without_headers = CliRunner().invoke(
cli.cli, ["query", db_path, sql] + fmt_option + ["--no-headers"]
)
assert with_headers.exit_code == 0
assert without_headers.exit_code == 0
# The column names appear when headers are shown, and must not appear at all
# once --no-headers is passed.
assert "name" in with_headers.output
for header in ("id", "name", "age"):
assert (
header not in without_headers.output
), f"header {header!r} leaked into --no-headers output"
# The data is still all present.
for value in ("Cleo", "Pancakes", "1", "2", "4"):
assert value in without_headers.output
# The rows command shares the same code path.
rows_no_headers = CliRunner().invoke(
cli.cli, ["rows", db_path, "dogs"] + fmt_option + ["--no-headers"]
)
assert rows_no_headers.exit_code == 0
assert "name" not in rows_no_headers.output
assert "Cleo" in rows_no_headers.output
def test_create_index(db_path):
db = Database(db_path)
assert [] == db["Gosh"].indexes