refactor(utils)!: move markdown_table to utility module

Moved the markdown_table utility function from the Python documentation
generator core module to the utility module. The public exports
definition of the utility module and all imports were updated.

The test module was also moved to the appropriate new path and the
testing functions were renamed.
This commit is contained in:
jakob.scheid committed 2026-10-21 13:02:36 +02:00
1 parent 36bc14185a
commit 6ddbd17497
3 files changed
+111 -110

No files matched your search

+3 -105
View File
@@ -28,7 +28,7 @@ from ...exceptions import (
InvalidNamespaceError,
PythonArgumentStructureError,
)
from ...utils import fit_row_length, get_relative_path_segments, non_empty_str
from ...utils import get_relative_path_segments, markdown_table, non_empty_str
from .arguments import PythonArgumentKind, PythonFunctionArgument
from .definitions import (
PythonAsyncFunctionDefinition,
@@ -184,108 +184,6 @@ def _signature_argument_list(
return args
def _markdown_table(
header: tuple,
body: list[tuple],
*,
allow_markdown_table: bool = False,
force_row_lengths: bool = False,
one_line_values: bool = True,
missing_value: str = '--',
) -> str:
"""
Generates a table.
If ``allow_markdown_table`` is ``False``, an alternative
representation is used.
:param headers: The table headers.
:type headers: tuple
:param body: The table body.
:type body: list[tuple]
:param allow_markdown_table: Controls whether a markdown table may be
used.
:type allow_markdown_table: bool
:param force_row_lengths: Controls whether an exception is raised if
a row does not have the correct length.
:type force_row_lengths: bool
:param one_line_values: Controls whether all newlines in all values
are replaced with spaces.
:type one_line_values: bool
:param missing_value: The string that is used if a value is missing
(only if ``force_row_lengths`` is ``False``).
:type missing_value: str
"""
if not header or not body:
return ''
header_len = len(header)
if allow_markdown_table:
table = (
'| ' + ' | '.join(header) + ' |\n|' + ' --- |' * len(header) + '\n'
)
for row in body:
if len(row) != header_len:
if force_row_lengths:
raise ValueError(
f'expected {header_len} value'
f'{"s" if header_len > 1 else ""}, got {len(row)}'
)
else:
row = fit_row_length(header_len, row)
table += (
'| '
+ ' | '.join(
[
str(col if col is not None else missing_value)
.replace('\n', ' ')
.replace('|', '\\|')
if one_line_values
else str(
col if col is not None else missing_value
).replace('|', '\\|')
for col in row
]
)
+ ' |\n'
)
else:
table = ''
for row in body:
if len(row) != header_len:
if force_row_lengths:
raise ValueError(
f'expected {header_len} value'
f'{"s" if header_len > 1 else ""}, got {len(row)}'
)
else:
row = fit_row_length(header_len, row)
sep = '- '
for i, col in enumerate(row):
table += (
sep
+ header[i]
+ ': '
+ (
str(col if col is not None else missing_value).replace(
'\n', ' '
)
if one_line_values
else str(col if col is not None else missing_value)
)
+ '\n\n'
)
sep = ' '
return table.strip()
def _is_docstring(docstring: str | PythonDocstring | None) -> bool:
"""
Checks whether the docstring is a docstring or an empty docstring.
@@ -621,7 +519,7 @@ class PythonDefinitionDocumentationGenerator:
)
if params_types:
md += _markdown_table(
md += markdown_table(
['Parameter', 'Type', 'Kind', 'Default value', 'Description'],
[
(
@@ -700,7 +598,7 @@ class PythonDefinitionDocumentationGenerator:
md += self.level * '#' + '# Exceptions\n\n'
if self._docstring.raises:
md += _markdown_table(
md += markdown_table(
('Exception', 'Description'),
[
(
+103
View File
@@ -35,6 +35,7 @@ __all__ = [
'non_empty_str',
'get_relative_path_segments',
'fit_row_length',
'markdown_table',
]
@@ -260,3 +261,105 @@ def fit_row_length(expected: int, row: tuple) -> tuple:
return row[:expected]
else:
return row + (None,) * (expected - len(row))
def markdown_table(
header: tuple,
body: list[tuple],
*,
allow_markdown_table: bool = False,
force_row_lengths: bool = False,
one_line_values: bool = True,
missing_value: str = '--',
) -> str:
"""
Generates a table.
If ``allow_markdown_table`` is ``False``, an alternative
representation is used.
:param headers: The table headers.
:type headers: tuple
:param body: The table body.
:type body: list[tuple]
:param allow_markdown_table: Controls whether a markdown table may be
used.
:type allow_markdown_table: bool
:param force_row_lengths: Controls whether an exception is raised if
a row does not have the correct length.
:type force_row_lengths: bool
:param one_line_values: Controls whether all newlines in all values
are replaced with spaces.
:type one_line_values: bool
:param missing_value: The string that is used if a value is missing
(only if ``force_row_lengths`` is ``False``).
:type missing_value: str
"""
if not header or not body:
return ''
header_len = len(header)
if allow_markdown_table:
table = (
'| ' + ' | '.join(header) + ' |\n|' + ' --- |' * len(header) + '\n'
)
for row in body:
if len(row) != header_len:
if force_row_lengths:
raise ValueError(
f'expected {header_len} value'
f'{"s" if header_len > 1 else ""}, got {len(row)}'
)
else:
row = fit_row_length(header_len, row)
table += (
'| '
+ ' | '.join(
[
str(col if col is not None else missing_value)
.replace('\n', ' ')
.replace('|', '\\|')
if one_line_values
else str(
col if col is not None else missing_value
).replace('|', '\\|')
for col in row
]
)
+ ' |\n'
)
else:
table = ''
for row in body:
if len(row) != header_len:
if force_row_lengths:
raise ValueError(
f'expected {header_len} value'
f'{"s" if header_len > 1 else ""}, got {len(row)}'
)
else:
row = fit_row_length(header_len, row)
sep = '- '
for i, col in enumerate(row):
table += (
sep
+ header[i]
+ ': '
+ (
str(col if col is not None else missing_value).replace(
'\n', ' '
)
if one_line_values
else str(col if col is not None else missing_value)
)
+ '\n\n'
)
sep = ' '
return table.strip()
@@ -14,7 +14,7 @@
import pytest
from src.jcloud_docsgen.core.python._core import _markdown_table
from src.jcloud_docsgen.utils import markdown_table
@pytest.mark.parametrize(
@@ -318,7 +318,7 @@ from src.jcloud_docsgen.core.python._core import _markdown_table
),
],
)
def test__markdown_table(
def test_markdown_table(
header,
body,
allow_markdown_table,
@@ -328,7 +328,7 @@ def test__markdown_table(
expected,
):
assert (
_markdown_table(
markdown_table(
header,
body,
allow_markdown_table=allow_markdown_table,
@@ -468,7 +468,7 @@ def test__markdown_table(
),
],
)
def test__markdown_table_exceptions(
def test_markdown_table_exceptions(
header,
body,
allow_markdown_table,
@@ -479,7 +479,7 @@ def test__markdown_table_exceptions(
expected_exception_msg,
):
with pytest.raises(expected_exception) as exc_info:
_markdown_table(
markdown_table(
header,
body,
allow_markdown_table=allow_markdown_table,