Table

Click Extra provides a way to render tables in the terminal.

Here how to use the standalone table rendering option decorator:

import click
from click_extra import pass_context, table_format_option, style, Color

@click.command
@table_format_option
@pass_context
def table_command(ctx):
    headers = ("Day", "Temperature")
    data = (
        (1, 42.9),
        ("2", None),
        (style("Friday", fg=Color.blue), style("Hot 🥵", fg=Color.red, bold=True)),
    )
    ctx.print_table(data, headers)

As you can see above, this option registers a ready-to-use print_table() method to the context object.

The default help message for this option list all available table formats:

$ table --help
Usage: table [OPTIONS]

Options:
  --table-format [aligned|asciidoc|colon-grid|csv|csv-excel|csv-excel-tab|csv-unix|double-grid|double-outline|fancy-grid|fancy-outline|github|grid|heavy-grid|heavy-outline|hjson|html|jira|json|json5|jsonc|latex|latex-booktabs|latex-longtable|latex-raw|mediawiki|mixed-grid|mixed-outline|moinmoin|orgtbl|outline|pipe|plain|presto|pretty|psql|rounded-grid|rounded-outline|rst|simple|simple-grid|simple-outline|textile|toml|tsv|unsafehtml|vertical|xml|yaml|youtrack]
                                  Rendering style of tables.
  --help                          Show this message and exit.

So you can use the --table-format option to change the table format:

$ table --table-format fancy-outline
╒════════╤═════════════╕
│ Day    │ Temperature │
╞════════╪═════════════╡
│ 1      │ 42.9        │
│ 2      │             │
│ FridayHot 🥵      │
╘════════╧═════════════╛
$ table --table-format asciidoc
[cols="<8,<13",options="header"]
|====
| Day    | Temperature 
| 1      | 42.9        
| 2      |             
| Friday | Hot 🥵      
|====

Tip

This example has been selected so you can see how print_table() handles:

  • Mixed data types (integers, floats, None, strings)

  • ANSI color codes (added with the click_extra.style() function)

  • Unicode characters (like the emojis)

Hint

There’s another method called render_table() that is registered in the context alongside print_table().

It works the same way, but instead of printing the table to the console, it returns the rendered table as a string.

Table formats

Table formats are aggregated from these sources:

They’re divided in 2 categories:

  • Formats that produce plain text output (like ASCII tables, grid tables, etc.) and are often composed of Unicode box-drawing characters, to be displayed in a terminal.

  • Formats that produce markup language output (like HTML, Markdown, LaTeX, etc.) and are expected to be rendered by a supporting viewer. This category also includes CSV, TSV, and structured serialization formats (HJSON, JSON, JSON5, JSONC, TOML, XML, YAML), which are plain text but meant to be processed by other tools.

Format ID

Description

Implementation

Markup

aligned

Compact table with single-space column separators and no borders

Click Extra

asciidoc

AsciiDoc table

python-tabulate

csv

Comma-separated values

csv

csv-excel

CSV with Excel dialect

csv

csv-excel-tab

CSV with Excel tab dialect

csv

csv-unix

CSV with Unix dialect

csv

double-grid

Double-line grid table

python-tabulate

double-outline

Double-line outline table

python-tabulate

fancy-grid

Grid with Unicode box-drawing characters

python-tabulate

fancy-outline

Outline with Unicode box-drawing characters

python-tabulate

github

GitHub-flavored Markdown table

python-tabulate

grid

Grid table with ASCII characters, also supported by Pandoc and reStructuredText

python-tabulate

heavy-grid

Heavy-line grid table

python-tabulate

heavy-outline

Heavy-line outline table

python-tabulate

hjson

HJSON array of objects

hjson

html

HTML table

python-tabulate

jira

Jira-style markup

python-tabulate

json

JSON array of objects

json

json5

Alias for json (JSON5 is a superset of JSON)

json

jsonc

Alias for json (JSONC is JSON with comments)

json

latex

LaTeX table

python-tabulate

latex-booktabs

LaTeX table with booktabs package

python-tabulate

latex-longtable

LaTeX longtable environment

python-tabulate

latex-raw

LaTeX table without escaping

python-tabulate

mediawiki

MediaWiki markup

python-tabulate

mixed-grid

Mixed-line grid table

python-tabulate

mixed-outline

Mixed-line outline table

python-tabulate

moinmoin

MoinMoin wiki markup

python-tabulate

orgtbl

Emacs org-mode table

python-tabulate

outline

Simple outline table

python-tabulate

pipe

PHP Markdown Extra pipes, also supported by Pandoc

python-tabulate

plain

Plain text, no formatting

python-tabulate

presto

Presto SQL output style

python-tabulate

pretty

Pretty ASCII table

python-tabulate

psql

PostgreSQL output style

python-tabulate

rounded-grid

Rounded grid table

python-tabulate

rounded-outline

Rounded outline table

python-tabulate

rst

reStructuredText simple table

python-tabulate

simple

Simple table with spaces, also supported by Pandoc

python-tabulate

simple-grid

Simple grid table

python-tabulate

simple-outline

Simple outline table

python-tabulate

textile

Textile markup

python-tabulate

toml

TOML array of tables

tomlkit

tsv

Tab-separated values

python-tabulate

unsafehtml

HTML table without escaping

python-tabulate

vertical

Vertical table layout

cli-helpers

xml

XML document

xmltodict

yaml

YAML sequence of mappings

PyYAML

youtrack

YouTrack markup

python-tabulate

Attention

By default, markup formats strip ANSI color codes from the output, to avoid injecting escape sequences into structured content like HTML, LaTeX, or CSV.

If you want to keep them, force the --color option when invoking the command.

Tip

Use the built-in click-extra render-matrix command to verify how ANSI codes are handled by each format:

$ uvx click-extra --table-format github render-matrix styles
$ uvx click-extra --table-format json render-matrix colors

Plain-text formats preserve ANSI styling. Markup formats strip it unless --color is passed explicitly.

$ table --table-format aligned
Day    Temperature
1      42.9
2
Friday Hot 🥵
$ table --table-format asciidoc
[cols="<8,<13",options="header"]
|====
| Day    | Temperature 
| 1      | 42.9        
| 2      |             
| Friday | Hot 🥵      
|====
$ table --table-format csv
Day,Temperature
1,42.9
2,
Friday,Hot 🥵
$ table --table-format csv-excel
Day,Temperature
1,42.9
2,
Friday,Hot 🥵
$ table --table-format csv-excel-tab
Day	Temperature
1	42.9
2	
Friday	Hot 🥵
$ table --table-format csv-unix
"Day","Temperature"
"1","42.9"
"2",""
"Friday","Hot 🥵"
$ table --table-format double-grid
╔════════╦═════════════╗
║ Day    ║ Temperature ║
╠════════╬═════════════╣
║ 1      ║ 42.9        ║
╠════════╬═════════════╣
║ 2      ║             ║
╠════════╬═════════════╣
║ FridayHot 🥵      ║
╚════════╩═════════════╝
$ table --table-format double-outline
╔════════╦═════════════╗
║ Day    ║ Temperature ║
╠════════╬═════════════╣
║ 1      ║ 42.9        ║
║ 2      ║             ║
║ FridayHot 🥵      ║
╚════════╩═════════════╝
$ table --table-format fancy-grid
╒════════╤═════════════╕
│ Day    │ Temperature │
╞════════╪═════════════╡
│ 1      │ 42.9        │
├────────┼─────────────┤
│ 2      │             │
├────────┼─────────────┤
│ FridayHot 🥵      │
╘════════╧═════════════╛
$ table --table-format fancy-outline
╒════════╤═════════════╕
│ Day    │ Temperature │
╞════════╪═════════════╡
│ 1      │ 42.9        │
│ 2      │             │
│ FridayHot 🥵      │
╘════════╧═════════════╛
$ table --table-format github
| Day    | Temperature |
| :----- | :---------- |
| 1      | 42.9        |
| 2      |             |
| Friday | Hot 🥵      |
$ table --table-format grid
+--------+-------------+
| Day    | Temperature |
+========+=============+
| 1      | 42.9        |
+--------+-------------+
| 2      |             |
+--------+-------------+
| Friday | Hot 🥵      |
+--------+-------------+
$ table --table-format heavy-grid
┏━━━━━━━━┳━━━━━━━━━━━━━┓
┃ Day    ┃ Temperature ┃
┣━━━━━━━━╋━━━━━━━━━━━━━┫
┃ 1      ┃ 42.9        ┃
┣━━━━━━━━╋━━━━━━━━━━━━━┫
┃ 2      ┃             ┃
┣━━━━━━━━╋━━━━━━━━━━━━━┫
┃ FridayHot 🥵      ┃
┗━━━━━━━━┻━━━━━━━━━━━━━┛
$ table --table-format heavy-outline
┏━━━━━━━━┳━━━━━━━━━━━━━┓
┃ Day    ┃ Temperature ┃
┣━━━━━━━━╋━━━━━━━━━━━━━┫
┃ 1      ┃ 42.9        ┃
┃ 2      ┃             ┃
┃ FridayHot 🥵      ┃
┗━━━━━━━━┻━━━━━━━━━━━━━┛
$ table --table-format hjson
[
  {
    Day: 1
    Temperature: 42.9
  }
  {
    Day: "2"
    Temperature: null
  }
  {
    Day: Friday
    Temperature: Hot 🥵
  }
]
$ table --table-format html
<table>
<thead>
<tr><th>Day   </th><th>Temperature</th></tr>
</thead>
<tbody>
<tr><td>1     </td><td>42.9       </td></tr>
<tr><td>2     </td><td>           </td></tr>
<tr><td>Friday</td><td>Hot 🥵     </td></tr>
</tbody>
</table>
$ table --table-format jira
|| Day    || Temperature ||
| 1      | 42.9        |
| 2      |             |
| Friday | Hot 🥵      |
$ table --table-format json
[
  {
    "Day": 1,
    "Temperature": 42.9
  },
  {
    "Day": "2",
    "Temperature": null
  },
  {
    "Day": "Friday",
    "Temperature": "Hot 🥵"
  }
]
$ table --table-format json5
[
  {
    "Day": 1,
    "Temperature": 42.9
  },
  {
    "Day": "2",
    "Temperature": null
  },
  {
    "Day": "Friday",
    "Temperature": "Hot 🥵"
  }
]
$ table --table-format jsonc
[
  {
    "Day": 1,
    "Temperature": 42.9
  },
  {
    "Day": "2",
    "Temperature": null
  },
  {
    "Day": "Friday",
    "Temperature": "Hot 🥵"
  }
]
$ table --table-format latex
\begin{tabular}{ll}
\hline
 Day    & Temperature \\
\hline
 1      & 42.9        \\
 2      &             \\
 Friday & Hot 🥵      \\
\hline
\end{tabular}
$ table --table-format latex-booktabs
\begin{tabular}{ll}
\toprule
 Day    & Temperature \\
\midrule
 1      & 42.9        \\
 2      &             \\
 Friday & Hot 🥵      \\
\bottomrule
\end{tabular}
$ table --table-format latex-longtable
\begin{longtable}{ll}
\hline
 Day    & Temperature \\
\hline
\endhead
 1      & 42.9        \\
 2      &             \\
 Friday & Hot 🥵      \\
\hline
\end{longtable}
$ table --table-format latex-raw
\begin{tabular}{ll}
\hline
 Day    & Temperature \\
\hline
 1      & 42.9        \\
 2      &             \\
 Friday & Hot 🥵      \\
\hline
\end{tabular}
$ table --table-format mediawiki
{| class="wikitable" style="text-align: left;"
|+ <!-- caption -->
|-
! Day    !! Temperature
|-
| 1      || 42.9
|-
| 2      ||
|-
| Friday || Hot 🥵
|}
$ table --table-format mixed-grid
┍━━━━━━━━┯━━━━━━━━━━━━━┑
│ Day    │ Temperature │
┝━━━━━━━━┿━━━━━━━━━━━━━┥
│ 1      │ 42.9        │
├────────┼─────────────┤
│ 2      │             │
├────────┼─────────────┤
│ FridayHot 🥵      │
┕━━━━━━━━┷━━━━━━━━━━━━━┙
$ table --table-format mixed-outline
┍━━━━━━━━┯━━━━━━━━━━━━━┑
│ Day    │ Temperature │
┝━━━━━━━━┿━━━━━━━━━━━━━┥
│ 1      │ 42.9        │
│ 2      │             │
│ FridayHot 🥵      │
┕━━━━━━━━┷━━━━━━━━━━━━━┙
$ table --table-format moinmoin
|| ''' Day    ''' || ''' Temperature ''' ||
||  1       ||  42.9         ||
||  2       ||               ||
||  Friday  ||  Hot 🥵       ||
$ table --table-format orgtbl
| Day    | Temperature |
|--------+-------------|
| 1      | 42.9        |
| 2      |             |
| Friday | Hot 🥵      |
$ table --table-format outline
+--------+-------------+
| Day    | Temperature |
+========+=============+
| 1      | 42.9        |
| 2      |             |
| Friday | Hot 🥵      |
+--------+-------------+
$ table --table-format pipe
| Day    | Temperature |
| :----- | :---------- |
| 1      | 42.9        |
| 2      |             |
| Friday | Hot 🥵      |
$ table --table-format plain
Day     Temperature
1       42.9
2
Friday  Hot 🥵
$ table --table-format presto
 Day    | Temperature
--------+-------------
 1      | 42.9
 2      |
 Friday | Hot 🥵
$ table --table-format pretty
+--------+-------------+
|  Day   | Temperature |
+--------+-------------+
|   1    |    42.9     |
|   2    |             |
| Friday |   Hot 🥵    |
+--------+-------------+
$ table --table-format psql
+--------+-------------+
| Day    | Temperature |
|--------+-------------|
| 1      | 42.9        |
| 2      |             |
| Friday | Hot 🥵      |
+--------+-------------+
$ table --table-format rounded-grid
╭────────┬─────────────╮
│ Day    │ Temperature │
├────────┼─────────────┤
│ 1      │ 42.9        │
├────────┼─────────────┤
│ 2      │             │
├────────┼─────────────┤
│ FridayHot 🥵      │
╰────────┴─────────────╯
$ table --table-format rounded-outline
╭────────┬─────────────╮
│ Day    │ Temperature │
├────────┼─────────────┤
│ 1      │ 42.9        │
│ 2      │             │
│ FridayHot 🥵      │
╰────────┴─────────────╯
$ table --table-format rst
======  ===========
Day     Temperature
======  ===========
1       42.9
2
Friday  Hot 🥵
======  ===========
$ table --table-format simple
Day     Temperature
------  -----------
1       42.9
2
Friday  Hot 🥵
$ table --table-format simple-grid
┌────────┬─────────────┐
│ Day    │ Temperature │
├────────┼─────────────┤
│ 1      │ 42.9        │
├────────┼─────────────┤
│ 2      │             │
├────────┼─────────────┤
│ FridayHot 🥵      │
└────────┴─────────────┘
$ table --table-format simple-outline
┌────────┬─────────────┐
│ Day    │ Temperature │
├────────┼─────────────┤
│ 1      │ 42.9        │
│ 2      │             │
│ FridayHot 🥵      │
└────────┴─────────────┘
$ table --table-format textile
|_.  Day    |_. Temperature |
|<. 1       |<. 42.9        |
|<. 2       |<.             |
|<. Friday  |<. Hot 🥵      |
$ table --table-format toml
[[record]]
Day = 1
Temperature = 42.9

[[record]]
Day = "2"

[[record]]
Day = "Friday"
Temperature = "Hot 🥵"
$ table --table-format tsv
Day   	Temperature
1     	42.9
2
Friday	Hot 🥵
$ table --table-format unsafehtml
<table>
<thead>
<tr><th>Day   </th><th>Temperature</th></tr>
</thead>
<tbody>
<tr><td>1     </td><td>42.9       </td></tr>
<tr><td>2     </td><td>           </td></tr>
<tr><td>Friday</td><td>Hot 🥵     </td></tr>
</tbody>
</table>
$ table --table-format vertical
***************************[ 1. row ]***************************
Day         | 1
Temperature | 42.9
***************************[ 2. row ]***************************
Day         | 2
Temperature | 
***************************[ 3. row ]***************************
Day         | Friday
Temperature | Hot 🥵
$ table --table-format xml
<records>
	<record>
		<Day>1</Day>
		<Temperature>42.9</Temperature>
	</record>
	<record>
		<Day>2</Day>
	</record>
	<record>
		<Day>Friday</Day>
		<Temperature>Hot 🥵</Temperature>
	</record>
</records>
$ table --table-format yaml
- Day: 1
  Temperature: 42.9
- Day: '2'
  Temperature: null
- Day: Friday
  Temperature: Hot 🥵
$ table --table-format youtrack
||  Day     ||  Temperature  ||
|  1       |  42.9         |
|  2       |               |
|  Friday  |  Hot 🥵       |

Get table format

You can get the ID of the current table format from the context:

import click
from click_extra import echo, pass_context, table_format_option

@click.command
@table_format_option
@pass_context
def vanilla_command(ctx):
    format_id = ctx.meta["click_extra.table_format"]
    echo(f"Table format: {format_id}")

    data = ((1, 87), (2, 80), (3, 79))
    headers = ("day", "temperature")
    ctx.print_table(data, headers)
$ vanilla --table-format fancy-outline
Table format: fancy-outline
╒═════╤═════════════╕
│ day │ temperature │
╞═════╪═════════════╡
│ 1   │ 87          │
│ 2   │ 80          │
│ 3   │ 79          │
╘═════╧═════════════╛

Data serialization

print_data() and serialize_data() handle arbitrary data structures (nested dicts, lists, scalars), unlike print_table() which expects tabular rows and headers. They support the structured serialization formats: JSON, HJSON, YAML, TOML, and XML.

from click_extra import command, pass_context, table_format_option
from click_extra.table import print_data

@command
@table_format_option
@pass_context
def data_command(ctx):
    """Serialize nested data."""
    data = {
        "city": "Paris",
        "population": 2161000,
        "landmarks": ["Eiffel Tower", "Louvre", "Notre-Dame"],
    }
    table_format = ctx.meta["click_extra.table_format"]
    print_data(data, table_format)
$ data --table-format json
{
  "city": "Paris",
  "population": 2161000,
  "landmarks": [
    "Eiffel Tower",
    "Louvre",
    "Notre-Dame"
  ]
}

/home/runner/work/click-extra/click-extra/.venv/lib/python3.14/site-packages/click/core.py:1223: UserWarning: The parameter --table-format is used more than once. Remove its duplicate as parameters should be unique.
  parser = self.make_parser(ctx)
/home/runner/work/click-extra/click-extra/.venv/lib/python3.14/site-packages/cloup/constraints/_support.py:183: UserWarning: The parameter --table-format is used more than once. Remove its duplicate as parameters should be unique.
  args = super().parse_args(ctx, args)  # type: ignore
/home/runner/work/click-extra/click-extra/click_extra/parameters.py:415: UserWarning: The parameter --table-format is used more than once. Remove its duplicate as parameters should be unique.
  for keys, param in self.walk_params():
$ data --table-format yaml
city: Paris
landmarks:
- Eiffel Tower
- Louvre
- Notre-Dame
population: 2161000

serialize_data() returns the serialized string instead of printing it:

Sorted tables

SortByOption adds a --sort-by CLI option whose choices are derived from column definitions. Column definitions are (label, column_id) tuples. Columns with column_id=None are displayed but not offered as sort choices.

The option can be repeated to define a multi-column sort priority: --sort-by name --sort-by age sorts by name first, then breaks ties by age.

When active, SortByOption replaces ctx.print_table with a sorted variant, so the command body doesn’t need any sorting logic.

from click_extra import command, pass_context, table_format_option
from click_extra.table import SortByOption

sort_opt = SortByOption(
    ("Fruit", "fruit"),
    ("Count", "count"),
    ("Notes", None),
)

@command(params=[sort_opt])
@table_format_option
@pass_context
def inventory(ctx):
    """Sortable fruit inventory."""
    header_defs = (("Fruit", "fruit"), ("Count", "count"), ("Notes", None))
    data = [
        ["Cherry", "50", "seasonal"],
        ["Apple", "120", ""],
        ["Banana", "80", "organic"],
    ]
    ctx.print_table(header_defs, data)
$ inventory --help
Usage: inventory [OPTIONS]

  Sortable fruit inventory.

Options:
  --sort-by [fruit|count]  Sort table by this column. Repeat to set priority.
                           [default: fruit]
  --table-format [aligned|asciidoc|colon-grid|csv|csv-excel|csv-excel-tab|csv-unix|double-grid|double-outline|fancy-grid|fancy-outline|github|grid|heavy-grid|heavy-outline|hjson|html|jira|json|json5|jsonc|latex|latex-booktabs|latex-longtable|latex-raw|mediawiki|mixed-grid|mixed-outline|moinmoin|orgtbl|outline|pipe|plain|presto|pretty|psql|rounded-grid|rounded-outline|rst|simple|simple-grid|simple-outline|textile|toml|tsv|unsafehtml|vertical|xml|yaml|youtrack]
                           Rendering style of tables.  [default: rounded-
                           outline]
  -h, --help               Show this message and exit.
$ inventory --table-format rounded-outline --sort-by fruit
╭────────┬───────┬──────────╮
│ FruitCountNotes    │
├────────┼───────┼──────────┤
│ Apple  │ 120   │          │
│ Banana │ 80    │ organic  │
│ Cherry │ 50    │ seasonal │
╰────────┴───────┴──────────╯
$ inventory --table-format rounded-outline --sort-by count
╭────────┬───────┬──────────╮
│ FruitCountNotes    │
├────────┼───────┼──────────┤
│ Apple  │ 120   │          │
│ Cherry │ 50    │ seasonal │
│ Banana │ 80    │ organic  │
╰────────┴───────┴──────────╯

Repeating --sort-by sets multi-column priority. Here, rows are sorted by count first, then ties broken by fruit name:

$ inventory --table-format rounded-outline --sort-by count --sort-by fruit
╭────────┬───────┬──────────╮
│ FruitCountNotes    │
├────────┼───────┼──────────┤
│ Apple  │ 120   │          │
│ Cherry │ 50    │ seasonal │
│ Banana │ 80    │ organic  │
╰────────┴───────┴──────────╯

For programmatic use without a CLI option, render_table() accepts a sort_key callable:

from click_extra import command, echo
from click_extra.table import render_table, TableFormat

@command
def sorted_demo():
    """Render a table sorted alphabetically."""
    data = [["Cherry", "50"], ["Apple", "120"], ["Banana", "80"]]
    output = render_table(
        data,
        headers=["Fruit", "Count"],
        table_format=TableFormat.ROUNDED_OUTLINE,
        sort_key=lambda row: row[0],
    )
    echo(output)
$ sorted-demo
╭────────┬───────╮
│ Fruit  │ Count │
├────────┼───────┤
│ Apple  │ 120   │
│ Banana │ 80    │
│ Cherry │ 50    │
╰────────┴───────╯

click_extra.table API

        classDiagram
  Enum <|-- TableFormat
  ExtraOption <|-- SortByOption
  ExtraOption <|-- TableFormatOption
    

Collection of table rendering utilities.

class click_extra.table.TableFormat(*values)[source]

Bases: Enum

Enumeration of supported table formats.

Hard-coded to be in alphabetical order. Content of this enum is checked in unit tests.

Warning

The youtrack format is missing in action from any official JetBrains documentation. It will be removed in python-tabulate v0.11.

ALIGNED = 'aligned'
ASCIIDOC = 'asciidoc'
COLON_GRID = 'colon-grid'
CSV = 'csv'
CSV_EXCEL = 'csv-excel'
CSV_EXCEL_TAB = 'csv-excel-tab'
CSV_UNIX = 'csv-unix'
DOUBLE_GRID = 'double-grid'
DOUBLE_OUTLINE = 'double-outline'
FANCY_GRID = 'fancy-grid'
FANCY_OUTLINE = 'fancy-outline'
GITHUB = 'github'
GRID = 'grid'
HEAVY_GRID = 'heavy-grid'
HEAVY_OUTLINE = 'heavy-outline'
HJSON = 'hjson'
HTML = 'html'
JIRA = 'jira'
JSON = 'json'
JSON5 = 'json5'
JSONC = 'jsonc'
LATEX = 'latex'
LATEX_BOOKTABS = 'latex-booktabs'
LATEX_LONGTABLE = 'latex-longtable'
LATEX_RAW = 'latex-raw'
MEDIAWIKI = 'mediawiki'
MIXED_GRID = 'mixed-grid'
MIXED_OUTLINE = 'mixed-outline'
MOINMOIN = 'moinmoin'
ORGTBL = 'orgtbl'
OUTLINE = 'outline'
PIPE = 'pipe'
PLAIN = 'plain'
PRESTO = 'presto'
PRETTY = 'pretty'
PSQL = 'psql'
ROUNDED_GRID = 'rounded-grid'
ROUNDED_OUTLINE = 'rounded-outline'
RST = 'rst'
SIMPLE = 'simple'
SIMPLE_GRID = 'simple-grid'
SIMPLE_OUTLINE = 'simple-outline'
TEXTILE = 'textile'
TOML = 'toml'
TSV = 'tsv'
UNSAFEHTML = 'unsafehtml'
VERTICAL = 'vertical'
XML = 'xml'
YAML = 'yaml'
YOUTRACK = 'youtrack'
property is_markup: bool

Whether this format is a markup rendering.

Markup formats have ANSI color codes stripped from their output by default. Use the --color flag to preserve them.

click_extra.table.MARKUP_FORMATS = frozenset({TableFormat.ASCIIDOC, TableFormat.CSV, TableFormat.CSV_EXCEL, TableFormat.CSV_EXCEL_TAB, TableFormat.CSV_UNIX, TableFormat.GITHUB, TableFormat.HJSON, TableFormat.HTML, TableFormat.JIRA, TableFormat.JSON, TableFormat.JSON5, TableFormat.JSONC, TableFormat.LATEX, TableFormat.LATEX_BOOKTABS, TableFormat.LATEX_LONGTABLE, TableFormat.LATEX_RAW, TableFormat.MEDIAWIKI, TableFormat.MOINMOIN, TableFormat.ORGTBL, TableFormat.PIPE, TableFormat.RST, TableFormat.TEXTILE, TableFormat.TOML, TableFormat.TSV, TableFormat.UNSAFEHTML, TableFormat.XML, TableFormat.YAML, TableFormat.YOUTRACK})

Subset of table formats that are considered as markup rendering.

click_extra.table.DEFAULT_FORMAT = TableFormat.ROUNDED_OUTLINE

Default table format, if none is specified.

click_extra.table.RECORD_KEY = 'record'

Key used for each record in structured formats that require named containers (TOML [[record]], XML <record>).

click_extra.table.XML_ROOT_KEY = 'records'

Root element name for XML table output.

click_extra.table.SERIALIZATION_FORMATS = frozenset({TableFormat.HJSON, TableFormat.JSON, TableFormat.JSON5, TableFormat.JSONC, TableFormat.TOML, TableFormat.XML, TableFormat.YAML})

Structured serialization formats whose renderers escape raw ESC bytes, making post-render strip_ansi() ineffective.

click_extra.table.render_table(table_data, headers=None, table_format=None, sort_key=None, **kwargs)[source]

Render a table and return it as a string.

Parameters:

sort_key (Callable[[Sequence[str | None]], Any] | None) – Optional callable passed to sorted() as the key argument. When provided, rows are sorted before rendering.

Return type:

str

click_extra.table.print_table(table_data, headers=None, table_format=None, sort_key=None, **kwargs)[source]

Render a table and print it to the console.

For markup formats, ANSI color codes are stripped from cell values before rendering unless --color is explicitly set.

Parameters:

sort_key (Callable[[Sequence[str | None]], Any] | None) – Optional callable passed to sorted() as the key argument. When provided, rows are sorted before rendering.

Return type:

None

click_extra.table.serialize_data(data, table_format, *, default=None, root_element='records', **kwargs)[source]

Serialize arbitrary Python data to a structured format.

Unlike render_table() which expects tabular rows and headers, this function accepts any JSON-compatible data structure (dicts, lists, nested combinations) and serializes it to the requested format.

Only formats in SERIALIZATION_FORMATS are supported.

Parameters:
  • data (Any) – Arbitrary data to serialize (dicts, lists, scalars).

  • table_format (TableFormat) – Target serialization format.

  • default (Callable | None) – Fallback serializer for types not natively supported. Defaults to str(), so Path and similar types are stringified automatically. Set to a custom callable for different behavior.

  • root_element (str) – Root element name for XML output.

  • kwargs – Extra keyword arguments forwarded to the underlying serializer (e.g. sort_keys, indent for JSON).

Raises:

ValueError – If the format is not a serialization format.

Return type:

str

click_extra.table.print_data(data, table_format, *, default=None, root_element='records', package='click-extra', **kwargs)[source]

Serialize arbitrary Python data and print it to the console.

Wraps serialize_data() with user-friendly error handling for missing optional dependencies.

Parameters:
  • data (Any) – Arbitrary data to serialize.

  • table_format (TableFormat) – Target serialization format.

  • default (Callable | None) – Fallback serializer for custom types. Defaults to str().

  • root_element (str) – Root element name for XML output.

  • package (str) – Package name for install instructions in error messages.

  • kwargs – Extra keyword arguments forwarded to the underlying serializer.

Return type:

None

class click_extra.table.TableFormatOption(param_decls=None, type=EnumChoice('aligned', 'asciidoc', 'colon-grid', 'csv', 'csv-excel', 'csv-excel-tab', 'csv-unix', 'double-grid', 'double-outline', 'fancy-grid', 'fancy-outline', 'github', 'grid', 'heavy-grid', 'heavy-outline', 'hjson', 'html', 'jira', 'json', 'json5', 'jsonc', 'latex', 'latex-booktabs', 'latex-longtable', 'latex-raw', 'mediawiki', 'mixed-grid', 'mixed-outline', 'moinmoin', 'orgtbl', 'outline', 'pipe', 'plain', 'presto', 'pretty', 'psql', 'rounded-grid', 'rounded-outline', 'rst', 'simple', 'simple-grid', 'simple-outline', 'textile', 'toml', 'tsv', 'unsafehtml', 'vertical', 'xml', 'yaml', 'youtrack'), default=TableFormat.ROUNDED_OUTLINE, expose_value=False, is_eager=True, help='Rendering style of tables.', **kwargs)[source]

Bases: ExtraOption

A pre-configured option that is adding a --table-format flag to select the rendering style of a table.

The selected table format ID is made available in the context in ctx.meta["click_extra.table_format"], and two helper methods are added to the context: - ctx.render_table(table_data, headers, **kwargs): renders and returns

the table as a string,

  • ctx.print_table(table_data, headers, **kwargs): renders and prints the table to the console.

Where: - table_data is a 2-dimensional iterable of iterables for rows and cells values, - headers is a list of string to be used as column headers, - **kwargs are any extra keyword arguments supported by the underlying table

formatting function.

init_formatter(ctx, param, table_format)[source]

Save in the context: table_format, render_table & print_table.

Return type:

None

click_extra.table.print_sorted_table(header_defs, table_data, sort_columns=None, table_format=None, *, cell_key=None, **kwargs)[source]

Sort and print a table using named column definitions.

header_defs is an ordered sequence of (label, column_id) tuples. Columns with column_id=None are not selectable for sorting but still participate in tie-breaking.

Parameters:
Return type:

None

class click_extra.table.SortByOption(*header_defs, param_decls=None, default=None, expose_value=False, cell_key=None, help='Sort table by this column. Repeat to set priority.', **kwargs)[source]

Bases: ExtraOption

A --sort-by option whose choices are derived from column definitions.

Stores the selected column IDs in ctx.meta["click_extra.sort_by"] and replaces ctx.print_table with print_sorted_table() so that table output is automatically sorted. The option accepts multiple=True, so users can repeat --sort-by to define a multi-column sort priority.

@command
@table_format_option
@sort_by_option(
    ("Package ID", "package_id"),
    ("Name", "package_name"),
    ("Manager", "manager_id"),
    ("Version", None),
)
@pass_context
def my_cmd(ctx):
    ctx.print_table(header_defs, rows)
init_sort(ctx, param, sort_columns)[source]

Store sort columns and override ctx.print_table with sorted variant.

Return type:

None