generated from jCloud/repository-template
Compare commits
29
Commits
310861dacc
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
347bff5dac
|
||
|
|
7ff849387a
|
||
|
|
2b31b82a06
|
||
|
|
92dc2fcd47 | ||
|
|
b1727c100f
|
||
|
|
6ddbd17497
|
||
|
|
36bc14185a
|
||
|
|
39d3b0ace4
|
||
|
|
3f74e6457e
|
||
|
|
a6b5e8f1c9
|
||
|
|
a85cd1b433
|
||
|
|
06f91a18e9
|
||
|
|
bc542ed781
|
||
|
|
aa44f9c3a1
|
||
|
|
0f4c344676
|
||
|
|
ae01f223e3
|
||
|
|
4781e21f5d
|
||
|
|
0d86785dba
|
||
|
|
5402dd960e
|
||
|
|
d8249d3eb1
|
||
|
|
6c593a286c
|
||
|
|
4b659d7d2d | ||
|
|
1ccb610310
|
||
|
|
a25c66d77b
|
||
|
|
82e10c5493
|
||
|
|
03fa81f0df
|
||
|
|
efa2dbf724
|
||
|
|
0f8f9d3cfa
|
||
|
|
3e77ebb7d0
|
No files matched your search
+18
-1
@@ -1,11 +1,28 @@
|
||||
# Changelog
|
||||
|
||||
## [Unreleased]
|
||||
## [0.2.3] - 2026-10-21
|
||||
|
||||
### Fixed
|
||||
|
||||
- Escape sequences for pipe characters in values of Markdown table cells
|
||||
|
||||
## [0.2.2] - 2026-10-14
|
||||
|
||||
### Fixed
|
||||
|
||||
- Import error in Python <3.13 which prevented the tool from running and made it unusuable in Python <3.13
|
||||
|
||||
## [0.2.1] - 2026-10-06
|
||||
|
||||
### Fixed
|
||||
|
||||
- Python namespace name conflict when package and module have the same name
|
||||
- Internal namespace name error which occured when generating Python documentation with `.` as the project directory
|
||||
- Ignore Python namespaces with invalid names during documentation generation
|
||||
|
||||
### Changed
|
||||
|
||||
- Stricter Python namespace name validation
|
||||
|
||||
## [0.2.0] - 2026-09-28
|
||||
|
||||
|
||||
@@ -116,106 +116,6 @@ Returns a list of the arguments as strings for a function signature.
|
||||
:return: The list of function signature argument strings.
|
||||
:rtype: list[str]
|
||||
|
||||
## Function `_fit_row_length`
|
||||
|
||||
Fits the row length to the expected length.
|
||||
|
||||
If the row is too long, the tail, that makes it too long, is omitted.
|
||||
If it is too short, it is filled with ``None`` (at the end).
|
||||
|
||||
### Function signature
|
||||
|
||||
```python
|
||||
_fit_row_length(expected: int, row: tuple) -> tuple
|
||||
```
|
||||
|
||||
### Returns
|
||||
|
||||
Return type: `tuple`
|
||||
|
||||
### Parameters
|
||||
|
||||
| Parameter | Type | Kind | Default value | Description |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| `expected` | `int` | normal | -- | The expected length. |
|
||||
| `row` | `tuple` | normal | -- | The row. |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
### Docstring
|
||||
|
||||
Fits the row length to the expected length.
|
||||
|
||||
If the row is too long, the tail, that makes it too long, is omitted.
|
||||
If it is too short, it is filled with ``None`` (at the end).
|
||||
|
||||
:param expected: The expected length.
|
||||
:type expected: int
|
||||
:param row: The row.
|
||||
:type row: tuple
|
||||
|
||||
## Function `_markdown_table`
|
||||
|
||||
Generates a table.
|
||||
|
||||
If ``allow_markdown_table`` is ``False``, an alternative
|
||||
representation is used.
|
||||
|
||||
### Function signature
|
||||
|
||||
```python
|
||||
_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
|
||||
```
|
||||
|
||||
### Returns
|
||||
|
||||
Return type: `str`
|
||||
|
||||
### Parameters
|
||||
|
||||
| Parameter | Type | Kind | Default value | Description |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| `header` | `tuple` | normal | -- | -- |
|
||||
| `body` | `list[tuple]` | normal | -- | The table body. |
|
||||
| `allow_markdown_table` | `bool` | keyword-only | `False` | Controls whether a markdown table may be used. |
|
||||
| `force_row_lengths` | `bool` | keyword-only | `False` | Controls whether an exception is raised if a row does not have the correct length. |
|
||||
| `one_line_values` | `bool` | keyword-only | `True` | Controls whether all newlines in all values are replaced with spaces. |
|
||||
| `missing_value` | `str` | keyword-only | `'--'` | The string that is used if a value is missing (only if ``force_row_lengths`` is ``False``). |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
### Docstring
|
||||
|
||||
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
|
||||
|
||||
## Function `_is_docstring`
|
||||
|
||||
Checks whether the docstring is a docstring or an empty docstring.
|
||||
|
||||
@@ -1,5 +1,45 @@
|
||||
# Module `jcloud_docsgen.core.python.namespaces`
|
||||
|
||||
## Function `validate_namespace_name`
|
||||
|
||||
Checks whether a namespace name is valid. Namespace names are valid
|
||||
if they contain no dots and are valid Python identifiers.
|
||||
|
||||
### Function signature
|
||||
|
||||
```python
|
||||
validate_namespace_name(name: str) -> bool
|
||||
```
|
||||
|
||||
### Returns
|
||||
|
||||
Whether the namespace name is valid.
|
||||
|
||||
Return type: `bool`
|
||||
|
||||
### Parameters
|
||||
|
||||
| Parameter | Type | Kind | Default value | Description |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| `name` | `str` | normal | -- | The namespace name to validate. |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
### Docstring
|
||||
|
||||
Checks whether a namespace name is valid. Namespace names are valid
|
||||
if they contain no dots and are valid Python identifiers.
|
||||
|
||||
:param name: The namespace name to validate.
|
||||
:type name: str
|
||||
|
||||
:returns: Whether the namespace name is valid.
|
||||
:rtype: bool
|
||||
|
||||
## Class `PythonNamespace`
|
||||
|
||||
The base class for all Python namespaces such as modules or packages.
|
||||
@@ -57,6 +97,8 @@ The base class for all Python namespaces such as modules or packages.
|
||||
:param name: The name of the namespace.
|
||||
:type name: str
|
||||
|
||||
:raises InvalidNamespaceError: If the namespace name is invalid.
|
||||
|
||||
## Class `PythonPackageNamespace`
|
||||
|
||||
A subclass of ``PythonNamespace`` for Python package namespaces.
|
||||
@@ -381,6 +423,8 @@ A subclass of ``PythonNamespace`` for Python package namespaces.
|
||||
:param sub_namespaces: The sub-namespaces.
|
||||
:type sub_namespaces: list[PythonNamespace]
|
||||
|
||||
:raises InvalidNamespaceError: If the namespace name is invalid.
|
||||
|
||||
## Class `PythonModuleNamespace`
|
||||
|
||||
A subclass of ``PythonNamespace`` for Python module namespaces.
|
||||
|
||||
@@ -340,4 +340,104 @@ Returns the path segments relative to ``root``.
|
||||
:type root: pathlib.Path
|
||||
|
||||
:return: The path segments relative to ``root``.
|
||||
:rtype: list[str]
|
||||
:rtype: list[str]
|
||||
|
||||
## Function `fit_row_length`
|
||||
|
||||
Fits the row length to the expected length.
|
||||
|
||||
If the row is too long, the tail, that makes it too long, is omitted.
|
||||
If it is too short, it is filled with ``None`` (at the end).
|
||||
|
||||
### Function signature
|
||||
|
||||
```python
|
||||
fit_row_length(expected: int, row: tuple) -> tuple
|
||||
```
|
||||
|
||||
### Returns
|
||||
|
||||
Return type: `tuple`
|
||||
|
||||
### Parameters
|
||||
|
||||
| Parameter | Type | Kind | Default value | Description |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| `expected` | `int` | normal | -- | The expected length. |
|
||||
| `row` | `tuple` | normal | -- | The row. |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
### Docstring
|
||||
|
||||
Fits the row length to the expected length.
|
||||
|
||||
If the row is too long, the tail, that makes it too long, is omitted.
|
||||
If it is too short, it is filled with ``None`` (at the end).
|
||||
|
||||
:param expected: The expected length.
|
||||
:type expected: int
|
||||
:param row: The row.
|
||||
:type row: tuple
|
||||
|
||||
## Function `markdown_table`
|
||||
|
||||
Generates a table.
|
||||
|
||||
If ``allow_markdown_table`` is ``False``, an alternative
|
||||
representation is used.
|
||||
|
||||
### Function signature
|
||||
|
||||
```python
|
||||
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
|
||||
```
|
||||
|
||||
### Returns
|
||||
|
||||
Return type: `str`
|
||||
|
||||
### Parameters
|
||||
|
||||
| Parameter | Type | Kind | Default value | Description |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| `header` | `tuple` | normal | -- | -- |
|
||||
| `body` | `list[tuple]` | normal | -- | The table body. |
|
||||
| `allow_markdown_table` | `bool` | keyword-only | `False` | Controls whether a markdown table may be used. |
|
||||
| `force_row_lengths` | `bool` | keyword-only | `False` | Controls whether an exception is raised if a row does not have the correct length. |
|
||||
| `one_line_values` | `bool` | keyword-only | `True` | Controls whether all newlines in all values are replaced with spaces. |
|
||||
| `missing_value` | `str` | keyword-only | `'--'` | The string that is used if a value is missing (only if ``force_row_lengths`` is ``False``). |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
### Docstring
|
||||
|
||||
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
|
||||
Generated
+4
-4
@@ -1,4 +1,4 @@
|
||||
# This file is automatically @generated by Poetry 2.4.3 and should not be changed by hand.
|
||||
# This file is automatically @generated by Poetry 2.5.1 and should not be changed by hand.
|
||||
|
||||
[[package]]
|
||||
name = "colorama"
|
||||
@@ -235,14 +235,14 @@ version = "4.16.0"
|
||||
description = "Backported and Experimental Type Hints for Python 3.9+"
|
||||
optional = false
|
||||
python-versions = ">=3.9"
|
||||
groups = ["dev"]
|
||||
markers = "python_version == \"3.10\""
|
||||
groups = ["main", "dev"]
|
||||
files = [
|
||||
{file = "typing_extensions-4.16.0-py3-none-any.whl", hash = "sha256:481caa481374e813c1b176ada14e97f1f67a4539ce9cfeb3f350d78d6370c2e8"},
|
||||
{file = "typing_extensions-4.16.0.tar.gz", hash = "sha256:dc983d19a509c94dba722ee6abd33940f7c05a89e243c47e907eb4db6f1a43e5"},
|
||||
]
|
||||
markers = {dev = "python_version == \"3.10\""}
|
||||
|
||||
[metadata]
|
||||
lock-version = "2.1"
|
||||
python-versions = ">=3.10"
|
||||
content-hash = "24c9a2d464f6c737eeae0a66f792fa23824c3960b7cc72a22fff1408f21ec812"
|
||||
content-hash = "0fb3b53540e7a7fe173bf29a2031bd59f863a8dea94a29d51933de2375c3bfa2"
|
||||
+2
-2
@@ -4,9 +4,9 @@ build-backend = "poetry.core.masonry.api"
|
||||
|
||||
[project]
|
||||
name = "jcloud-docsgen"
|
||||
version = "0.2.0"
|
||||
version = "0.2.3"
|
||||
description = "A tool that generates Markdown documentation for software project source code"
|
||||
dependencies = ["docstring-parser"]
|
||||
dependencies = ["docstring-parser", "typing-extensions (>=4.16.0,<5.0.0)"]
|
||||
requires-python = ">=3.10"
|
||||
license = "Apache-2.0"
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ from ...exceptions import (
|
||||
InvalidNamespaceError,
|
||||
PythonArgumentStructureError,
|
||||
)
|
||||
from ...utils import 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,
|
||||
@@ -37,7 +37,11 @@ from .definitions import (
|
||||
PythonFunctionDefinition,
|
||||
)
|
||||
from .docstrings import PythonDocstring
|
||||
from .namespaces import PythonModuleNamespace, PythonPackageNamespace
|
||||
from .namespaces import (
|
||||
PythonModuleNamespace,
|
||||
PythonPackageNamespace,
|
||||
validate_namespace_name,
|
||||
)
|
||||
|
||||
__all__ = [
|
||||
'PythonDefinitionDocumentationIncludeSections',
|
||||
@@ -180,128 +184,6 @@ def _signature_argument_list(
|
||||
return args
|
||||
|
||||
|
||||
def _fit_row_length(expected: int, row: tuple) -> tuple:
|
||||
"""
|
||||
Fits the row length to the expected length.
|
||||
|
||||
If the row is too long, the tail, that makes it too long, is omitted.
|
||||
If it is too short, it is filled with ``None`` (at the end).
|
||||
|
||||
:param expected: The expected length.
|
||||
:type expected: int
|
||||
:param row: The row.
|
||||
:type row: tuple
|
||||
"""
|
||||
|
||||
if expected < 0:
|
||||
raise ValueError('expected must be larger than or equal 0.')
|
||||
|
||||
if len(row) > expected:
|
||||
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', ' '
|
||||
)
|
||||
if one_line_values
|
||||
else str(col if col is not None else missing_value)
|
||||
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.
|
||||
@@ -637,7 +519,7 @@ class PythonDefinitionDocumentationGenerator:
|
||||
)
|
||||
|
||||
if params_types:
|
||||
md += _markdown_table(
|
||||
md += markdown_table(
|
||||
['Parameter', 'Type', 'Kind', 'Default value', 'Description'],
|
||||
[
|
||||
(
|
||||
@@ -716,7 +598,7 @@ class PythonDefinitionDocumentationGenerator:
|
||||
md += self.level * '#' + '# Exceptions\n\n'
|
||||
|
||||
if self._docstring.raises:
|
||||
md += _markdown_table(
|
||||
md += markdown_table(
|
||||
('Exception', 'Description'),
|
||||
[
|
||||
(
|
||||
@@ -926,9 +808,12 @@ class PythonModuleDocumentationGenerator:
|
||||
),
|
||||
**kwargs,
|
||||
) -> None:
|
||||
if module_path.name.count('.') > 1:
|
||||
if not (
|
||||
module_path.suffix == '.py'
|
||||
and validate_namespace_name(module_path.stem)
|
||||
):
|
||||
raise InvalidNamespaceError(
|
||||
'namespace identifier cannot contain more than one dot',
|
||||
'invalid module file name',
|
||||
namespace_identifier=module_path.name,
|
||||
)
|
||||
|
||||
@@ -1107,12 +992,18 @@ class PythonDocumentationGenerator:
|
||||
)
|
||||
|
||||
for entry in directory.iterdir():
|
||||
if entry.is_dir() and (
|
||||
entry.parent / (f'{entry.stem}.py')
|
||||
).resolve() not in [e.resolve() for e in entry.parent.iterdir()]:
|
||||
namespace.add(self._namespace(entry))
|
||||
elif entry.suffix == '.py':
|
||||
namespace.add(PythonModuleNamespace(entry.stem))
|
||||
try:
|
||||
if entry.is_dir() and (
|
||||
entry.parent / (f'{entry.stem}.py')
|
||||
).resolve() not in [
|
||||
e.resolve() for e in entry.parent.iterdir()
|
||||
]:
|
||||
namespace.add(self._namespace(entry))
|
||||
elif entry.suffix == '.py':
|
||||
namespace.add(PythonModuleNamespace(entry.stem))
|
||||
except InvalidNamespaceError:
|
||||
# the name of the directory or module is invalid; ignore.
|
||||
pass
|
||||
|
||||
return namespace
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import keyword
|
||||
from typing import TypeAlias, Union
|
||||
|
||||
from ...exceptions import (
|
||||
@@ -24,27 +25,47 @@ from ...exceptions import (
|
||||
from ...utils import assert_that_is_instance
|
||||
|
||||
__all__ = [
|
||||
'validate_namespace_name',
|
||||
'PythonNamespace',
|
||||
'PythonPackageNamespace',
|
||||
'PythonModuleNamespace',
|
||||
]
|
||||
|
||||
|
||||
def validate_namespace_name(name: str) -> bool:
|
||||
"""
|
||||
Checks whether a namespace name is valid. Namespace names are valid
|
||||
if they contain no dots and are valid Python identifiers.
|
||||
|
||||
:param name: The namespace name to validate.
|
||||
:type name: str
|
||||
|
||||
:returns: Whether the namespace name is valid.
|
||||
:rtype: bool
|
||||
"""
|
||||
|
||||
if not isinstance(name, str):
|
||||
return False
|
||||
|
||||
return name.isidentifier() and not keyword.iskeyword(name)
|
||||
|
||||
|
||||
class PythonNamespace:
|
||||
"""
|
||||
The base class for all Python namespaces such as modules or packages.
|
||||
|
||||
:param name: The name of the namespace.
|
||||
:type name: str
|
||||
|
||||
:raises InvalidNamespaceError: If the namespace name is invalid.
|
||||
"""
|
||||
|
||||
def __init__(self, name: str) -> None:
|
||||
assert_that_is_instance(name, str)
|
||||
|
||||
if not name.strip():
|
||||
if not validate_namespace_name(name):
|
||||
raise InvalidNamespaceError(
|
||||
'invalid namespace',
|
||||
namespace_identifier=name,
|
||||
'invalid namespace', namespace_identifier=name
|
||||
)
|
||||
|
||||
self.name = name
|
||||
@@ -70,6 +91,8 @@ class PythonPackageNamespace(PythonNamespace):
|
||||
:type name: str
|
||||
:param sub_namespaces: The sub-namespaces.
|
||||
:type sub_namespaces: list[PythonNamespace]
|
||||
|
||||
:raises InvalidNamespaceError: If the namespace name is invalid.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
|
||||
@@ -34,6 +34,8 @@ __all__ = [
|
||||
'assert_that_is_instance',
|
||||
'non_empty_str',
|
||||
'get_relative_path_segments',
|
||||
'fit_row_length',
|
||||
'markdown_table',
|
||||
]
|
||||
|
||||
|
||||
@@ -237,3 +239,127 @@ def get_relative_path_segments(
|
||||
)
|
||||
.parts,
|
||||
)
|
||||
|
||||
|
||||
def fit_row_length(expected: int, row: tuple) -> tuple:
|
||||
"""
|
||||
Fits the row length to the expected length.
|
||||
|
||||
If the row is too long, the tail, that makes it too long, is omitted.
|
||||
If it is too short, it is filled with ``None`` (at the end).
|
||||
|
||||
:param expected: The expected length.
|
||||
:type expected: int
|
||||
:param row: The row.
|
||||
:type row: tuple
|
||||
"""
|
||||
|
||||
if expected < 0:
|
||||
raise ValueError('expected must be larger than or equal 0.')
|
||||
|
||||
if len(row) > expected:
|
||||
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()
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+9
@@ -0,0 +1,9 @@
|
||||
# Module `pkg.a.b`
|
||||
|
||||
## Function `fn`
|
||||
|
||||
### Function signature
|
||||
|
||||
```python
|
||||
fn()
|
||||
```
|
||||
+1
@@ -0,0 +1 @@
|
||||
def fn(): ...
|
||||
+1
@@ -0,0 +1 @@
|
||||
def fn(): ...
|
||||
+1
@@ -0,0 +1 @@
|
||||
def fn(): ...
|
||||
+1
@@ -0,0 +1 @@
|
||||
def fn(): ...
|
||||
+1
@@ -0,0 +1 @@
|
||||
def fn(): ...
|
||||
+1
@@ -0,0 +1 @@
|
||||
def fn(): ...
|
||||
+1
@@ -0,0 +1 @@
|
||||
def fn(): ...
|
||||
+1
@@ -0,0 +1 @@
|
||||
def fn(): ...
|
||||
+1
@@ -0,0 +1 @@
|
||||
def fn(): ...
|
||||
Whitespace-only changes.
Whitespace-only changes.
+1
@@ -0,0 +1 @@
|
||||
def fn(): ...
|
||||
+1
@@ -0,0 +1 @@
|
||||
def fn(): ...
|
||||
+1
-1
@@ -47,7 +47,7 @@ Return type: `User`
|
||||
| `user_id` | `str` | normal | -- | -- |
|
||||
| `name` | `str` | normal | -- | -- |
|
||||
| `email` | `str` | normal | -- | -- |
|
||||
| `age` | `int | None` | normal | `None` | -- |
|
||||
| `age` | `int \| None` | normal | `None` | -- |
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -25,176 +25,134 @@ from src.jcloud_docsgen.exceptions import InvalidNamespaceError
|
||||
[
|
||||
(
|
||||
pathlib.Path(
|
||||
(
|
||||
'tests/unit/core/python/_core/fil'
|
||||
'es_with_more_than_one_dot/a.b.c'
|
||||
),
|
||||
('tests/unit/core/python/_core/invalid_module_names/a.b.c'),
|
||||
),
|
||||
None,
|
||||
InvalidNamespaceError,
|
||||
'namespace identifier cannot contain more than one dot: a.b.c',
|
||||
'invalid module file name: a.b.c',
|
||||
),
|
||||
(
|
||||
pathlib.Path(
|
||||
('tests/unit/core/python/_core/invalid_module_names/a.b.c.d'),
|
||||
),
|
||||
None,
|
||||
InvalidNamespaceError,
|
||||
'invalid module file name: a.b.c.d',
|
||||
),
|
||||
(
|
||||
pathlib.Path(
|
||||
(
|
||||
'tests/unit/core/python/_core/file'
|
||||
's_with_more_than_one_dot/a.b.c.d'
|
||||
'tests/unit/core/python/_core/i'
|
||||
'nvalid_module_names/a.b.c.d.e'
|
||||
),
|
||||
),
|
||||
None,
|
||||
InvalidNamespaceError,
|
||||
'namespace identifier cannot contain more than one dot: a.b.c.d',
|
||||
'invalid module file name: a.b.c.d.e',
|
||||
),
|
||||
(
|
||||
pathlib.Path(
|
||||
(
|
||||
'tests/unit/core/python/_core/files'
|
||||
'_with_more_than_one_dot/a.b.c.d.e'
|
||||
'tests/unit/core/python/_core/in'
|
||||
'valid_module_names/a.b.c.d.e.f'
|
||||
),
|
||||
),
|
||||
None,
|
||||
InvalidNamespaceError,
|
||||
(
|
||||
'namespace identifier cannot cont'
|
||||
'ain more than one dot: a.b.c.d.e'
|
||||
),
|
||||
'invalid module file name: a.b.c.d.e.f',
|
||||
),
|
||||
(
|
||||
pathlib.Path(
|
||||
(
|
||||
'tests/unit/core/python/_core/files_'
|
||||
'with_more_than_one_dot/a.b.c.d.e.f'
|
||||
'tests/unit/core/python/_core/inv'
|
||||
'alid_module_names/a.b.c.d.e.f.g'
|
||||
),
|
||||
),
|
||||
None,
|
||||
InvalidNamespaceError,
|
||||
(
|
||||
'namespace identifier cannot conta'
|
||||
'in more than one dot: a.b.c.d.e.f'
|
||||
),
|
||||
'invalid module file name: a.b.c.d.e.f.g',
|
||||
),
|
||||
(
|
||||
pathlib.Path(
|
||||
(
|
||||
'tests/unit/core/python/_core/files_w'
|
||||
'ith_more_than_one_dot/a.b.c.d.e.f.g'
|
||||
'tests/unit/core/python/_core/inva'
|
||||
'lid_module_names/a.b.c.d.e.f.g.h'
|
||||
),
|
||||
),
|
||||
None,
|
||||
InvalidNamespaceError,
|
||||
(
|
||||
'namespace identifier cannot contai'
|
||||
'n more than one dot: a.b.c.d.e.f.g'
|
||||
),
|
||||
'invalid module file name: a.b.c.d.e.f.g.h',
|
||||
),
|
||||
(
|
||||
pathlib.Path(
|
||||
(
|
||||
'tests/unit/core/python/_core/files_wi'
|
||||
'th_more_than_one_dot/a.b.c.d.e.f.g.h'
|
||||
'tests/unit/core/python/_core/inval'
|
||||
'id_module_names/a.b.c.d.e.f.g.h.py'
|
||||
),
|
||||
),
|
||||
None,
|
||||
InvalidNamespaceError,
|
||||
(
|
||||
'namespace identifier cannot contain'
|
||||
' more than one dot: a.b.c.d.e.f.g.h'
|
||||
),
|
||||
'invalid module file name: a.b.c.d.e.f.g.h.py',
|
||||
),
|
||||
(
|
||||
pathlib.Path(
|
||||
(
|
||||
'tests/unit/core/python/_core/files_wit'
|
||||
'h_more_than_one_dot/a.b.c.d.e.f.g.h.py'
|
||||
'tests/unit/core/python/_core/inva'
|
||||
'lid_module_names/a.b.c.d.e.f.g.py'
|
||||
),
|
||||
),
|
||||
None,
|
||||
InvalidNamespaceError,
|
||||
(
|
||||
'namespace identifier cannot contain m'
|
||||
'ore than one dot: a.b.c.d.e.f.g.h.py'
|
||||
),
|
||||
'invalid module file name: a.b.c.d.e.f.g.py',
|
||||
),
|
||||
(
|
||||
pathlib.Path(
|
||||
(
|
||||
'tests/unit/core/python/_core/files_wi'
|
||||
'th_more_than_one_dot/a.b.c.d.e.f.g.py'
|
||||
'tests/unit/core/python/_core/in'
|
||||
'lid_module_names/a.b.c.d.e.f.py'
|
||||
),
|
||||
),
|
||||
None,
|
||||
InvalidNamespaceError,
|
||||
(
|
||||
'namespace identifier cannot contain '
|
||||
'more than one dot: a.b.c.d.e.f.g.py'
|
||||
),
|
||||
'invalid module file name: a.b.c.d.e.f.py',
|
||||
),
|
||||
(
|
||||
pathlib.Path(
|
||||
(
|
||||
'tests/unit/core/python/_core/files_w'
|
||||
'ith_more_than_one_dot/a.b.c.d.e.f.py'
|
||||
'tests/unit/core/python/_core/in'
|
||||
'valid_module_names/a.b.c.d.e.py'
|
||||
),
|
||||
),
|
||||
None,
|
||||
InvalidNamespaceError,
|
||||
(
|
||||
'namespace identifier cannot contain'
|
||||
' more than one dot: a.b.c.d.e.f.py'
|
||||
),
|
||||
'invalid module file name: a.b.c.d.e.py',
|
||||
),
|
||||
(
|
||||
pathlib.Path(
|
||||
(
|
||||
'tests/unit/core/python/_core/files_'
|
||||
'with_more_than_one_dot/a.b.c.d.e.py'
|
||||
'tests/unit/core/python/_core/i'
|
||||
'nvalid_module_names/a.b.c.d.py'
|
||||
),
|
||||
),
|
||||
None,
|
||||
InvalidNamespaceError,
|
||||
(
|
||||
'namespace identifier cannot contai'
|
||||
'n more than one dot: a.b.c.d.e.py'
|
||||
),
|
||||
'invalid module file name: a.b.c.d.py',
|
||||
),
|
||||
(
|
||||
pathlib.Path(
|
||||
(
|
||||
'tests/unit/core/python/_core/files'
|
||||
'_with_more_than_one_dot/a.b.c.d.py'
|
||||
),
|
||||
('tests/unit/core/python/_core/invalid_module_names/a.b.c.py'),
|
||||
),
|
||||
None,
|
||||
InvalidNamespaceError,
|
||||
(
|
||||
'namespace identifier cannot conta'
|
||||
'in more than one dot: a.b.c.d.py'
|
||||
),
|
||||
'invalid module file name: a.b.c.py',
|
||||
),
|
||||
(
|
||||
pathlib.Path(
|
||||
(
|
||||
'tests/unit/core/python/_core/file'
|
||||
's_with_more_than_one_dot/a.b.c.py'
|
||||
),
|
||||
('tests/unit/core/python/_core/invalid_module_names/a.b.py'),
|
||||
),
|
||||
None,
|
||||
InvalidNamespaceError,
|
||||
(
|
||||
'namespace identifier cannot cont'
|
||||
'ain more than one dot: a.b.c.py'
|
||||
),
|
||||
),
|
||||
(
|
||||
pathlib.Path(
|
||||
(
|
||||
'tests/unit/core/python/_core/fil'
|
||||
'es_with_more_than_one_dot/a.b.py'
|
||||
),
|
||||
),
|
||||
None,
|
||||
InvalidNamespaceError,
|
||||
'namespace identifier cannot contain more than one dot: a.b.py',
|
||||
'invalid module file name: a.b.py',
|
||||
),
|
||||
(
|
||||
pathlib.Path(
|
||||
@@ -205,7 +163,7 @@ from src.jcloud_docsgen.exceptions import InvalidNamespaceError
|
||||
),
|
||||
None,
|
||||
InvalidNamespaceError,
|
||||
'namespace identifier cannot contain more than one dot: a.b.py',
|
||||
'invalid module file name: a.b.py',
|
||||
),
|
||||
],
|
||||
)
|
||||
@@ -292,8 +250,8 @@ Return type: `int | float`
|
||||
|
||||
| Parameter | Type | Kind | Default value | Description |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| `a` | `int | float` | normal | -- | The first number. |
|
||||
| `b` | `int | float` | normal | -- | The second number. |
|
||||
| `a` | `int \\| float` | normal | -- | The first number. |
|
||||
| `b` | `int \\| float` | normal | -- | The second number. |
|
||||
|
||||
|
||||
|
||||
@@ -503,8 +461,8 @@ Return type: `int | float`
|
||||
|
||||
| Parameter | Type | Kind | Default value | Description |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| `a` | `int | float` | normal | -- | The first number. |
|
||||
| `b` | `int | float` | normal | -- | The second number. |
|
||||
| `a` | `int \\| float` | normal | -- | The first number. |
|
||||
| `b` | `int \\| float` | normal | -- | The second number. |
|
||||
|
||||
|
||||
|
||||
@@ -714,8 +672,8 @@ Return type: `int | float`
|
||||
|
||||
| Parameter | Type | Kind | Default value | Description |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| `a` | `int | float` | normal | -- | The first number. |
|
||||
| `b` | `int | float` | normal | -- | The second number. |
|
||||
| `a` | `int \\| float` | normal | -- | The first number. |
|
||||
| `b` | `int \\| float` | normal | -- | The second number. |
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -28,7 +28,6 @@ class StrSubclass(str): ...
|
||||
'namespace,expected_name',
|
||||
[
|
||||
(PythonModuleNamespace('a'), 'a'),
|
||||
(PythonModuleNamespace('1'), '1'),
|
||||
(PythonModuleNamespace(StrSubclass('a')), StrSubclass('a')),
|
||||
],
|
||||
)
|
||||
@@ -41,11 +40,7 @@ def test_PythonModuleNamespace_name_attribute(namespace, expected_name):
|
||||
[
|
||||
(PythonModuleNamespace('a'), PythonModuleNamespace('a'), True),
|
||||
(PythonModuleNamespace('b'), PythonModuleNamespace('b'), True),
|
||||
(PythonModuleNamespace('1'), PythonModuleNamespace('1'), True),
|
||||
(PythonModuleNamespace('42'), PythonModuleNamespace('42'), True),
|
||||
(PythonModuleNamespace('a'), PythonModuleNamespace('b'), False),
|
||||
(PythonModuleNamespace('0'), PythonModuleNamespace('-0'), False),
|
||||
(PythonModuleNamespace('1'), PythonModuleNamespace('a'), False),
|
||||
(PythonModuleNamespace('a'), 'a', False),
|
||||
(PythonModuleNamespace('a'), 'b', False),
|
||||
(PythonModuleNamespace('a'), PythonPackageNamespace('a', []), False),
|
||||
@@ -61,7 +56,6 @@ def test_PythonModuleNamespace___eq__(namespace1, namespace2, expected):
|
||||
'namespace,expected',
|
||||
[
|
||||
(PythonModuleNamespace('a'), "PythonModuleNamespace('a')"),
|
||||
(PythonModuleNamespace('1'), "PythonModuleNamespace('1')"),
|
||||
(
|
||||
PythonModuleNamespace(StrSubclass('a')),
|
||||
"PythonModuleNamespace('a')",
|
||||
|
||||
@@ -24,7 +24,6 @@ class StrSubclass(str): ...
|
||||
'namespace,expected_name',
|
||||
[
|
||||
(PythonNamespace('a'), 'a'),
|
||||
(PythonNamespace('1'), '1'),
|
||||
(PythonNamespace(StrSubclass('a')), StrSubclass('a')),
|
||||
],
|
||||
)
|
||||
@@ -36,7 +35,6 @@ def test_PythonNamespace_name_attribute(namespace, expected_name):
|
||||
'namespace,expected',
|
||||
[
|
||||
(PythonNamespace('a'), "PythonNamespace('a')"),
|
||||
(PythonNamespace('1'), "PythonNamespace('1')"),
|
||||
(PythonNamespace(StrSubclass('a')), "PythonNamespace('a')"),
|
||||
],
|
||||
)
|
||||
|
||||
@@ -38,13 +38,6 @@ class StrSubclass(str): ...
|
||||
),
|
||||
'a',
|
||||
),
|
||||
(
|
||||
PythonPackageNamespace(
|
||||
'1',
|
||||
[],
|
||||
),
|
||||
'1',
|
||||
),
|
||||
(
|
||||
PythonPackageNamespace(
|
||||
StrSubclass('a'),
|
||||
@@ -291,10 +284,6 @@ def test_PythonPackageNamespace___eq__(namespace1, namespace2, expected):
|
||||
PythonPackageNamespace('a', []),
|
||||
"PythonPackageNamespace('a', [])",
|
||||
),
|
||||
(
|
||||
PythonPackageNamespace('1', []),
|
||||
"PythonPackageNamespace('1', [])",
|
||||
),
|
||||
(
|
||||
PythonPackageNamespace(StrSubclass('a'), []),
|
||||
"PythonPackageNamespace('a', [])",
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
# Copyright 2026 jCloud
|
||||
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import pytest
|
||||
|
||||
from src.jcloud_docsgen.core.python.namespaces import validate_namespace_name
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
'name,expected',
|
||||
[
|
||||
('a', True),
|
||||
('namespace', True),
|
||||
('match', True),
|
||||
('case', True),
|
||||
('type', True),
|
||||
('_', True),
|
||||
('__', True),
|
||||
('___', True),
|
||||
('_a', True),
|
||||
('_a_', True),
|
||||
('_a.', False),
|
||||
('a.b', False),
|
||||
('a-b', False),
|
||||
('a.', False),
|
||||
('a-', False),
|
||||
('.a', False),
|
||||
('-a', False),
|
||||
('.a.', False),
|
||||
('-a-', False),
|
||||
('.', False),
|
||||
('a-.b', False),
|
||||
('"', False),
|
||||
('""', False),
|
||||
('def', False),
|
||||
('class', False),
|
||||
('import', False),
|
||||
],
|
||||
)
|
||||
def test_validate_namespace_name(name, expected):
|
||||
assert validate_namespace_name(name) == expected
|
||||
+5
-5
@@ -14,7 +14,7 @@
|
||||
|
||||
import pytest
|
||||
|
||||
from src.jcloud_docsgen.core.python._core import _fit_row_length
|
||||
from src.jcloud_docsgen.utils import fit_row_length
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
@@ -37,8 +37,8 @@ from src.jcloud_docsgen.core.python._core import _fit_row_length
|
||||
(3, (1, 2, 3), (1, 2, 3)),
|
||||
],
|
||||
)
|
||||
def test__fit_row_length(expected_length, row, expected):
|
||||
assert _fit_row_length(expected_length, row) == expected
|
||||
def test_fit_row_length(expected_length, row, expected):
|
||||
assert fit_row_length(expected_length, row) == expected
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
@@ -60,7 +60,7 @@ def test__fit_row_length(expected_length, row, expected):
|
||||
(-42, ValueError),
|
||||
],
|
||||
)
|
||||
def test__fit_row_length_exceptions(expected_length, row, expected_exception):
|
||||
def test_fit_row_length_exceptions(expected_length, row, expected_exception):
|
||||
with pytest.raises(expected_exception) as exc_info:
|
||||
_fit_row_length(expected_length, row)
|
||||
fit_row_length(expected_length, row)
|
||||
assert str(exc_info.value) == 'expected must be larger than or equal 0.'
|
||||
+71
-5
@@ -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(
|
||||
@@ -138,6 +138,72 @@ from src.jcloud_docsgen.core.python._core import _markdown_table
|
||||
"""| a |
|
||||
| --- |
|
||||
| line1\nline2 |""",
|
||||
),
|
||||
(
|
||||
['a'],
|
||||
[('line1\nline2 | 2',)],
|
||||
True,
|
||||
False,
|
||||
False,
|
||||
'--',
|
||||
"""| a |
|
||||
| --- |
|
||||
| line1\nline2 \\| 2 |""",
|
||||
),
|
||||
(
|
||||
['a'],
|
||||
[('line1\nline2 | 2',)],
|
||||
True,
|
||||
False,
|
||||
True,
|
||||
'--',
|
||||
"""| a |
|
||||
| --- |
|
||||
| line1 line2 \\| 2 |""",
|
||||
),
|
||||
(
|
||||
['a'],
|
||||
[('1 | 2',)],
|
||||
True,
|
||||
False,
|
||||
True,
|
||||
'--',
|
||||
"""| a |
|
||||
| --- |
|
||||
| 1 \\| 2 |""",
|
||||
),
|
||||
(
|
||||
['a'],
|
||||
[('1 |',)],
|
||||
True,
|
||||
False,
|
||||
True,
|
||||
'--',
|
||||
"""| a |
|
||||
| --- |
|
||||
| 1 \\| |""",
|
||||
),
|
||||
(
|
||||
['a'],
|
||||
[('|',)],
|
||||
True,
|
||||
False,
|
||||
True,
|
||||
'--',
|
||||
"""| a |
|
||||
| --- |
|
||||
| \\| |""",
|
||||
),
|
||||
(
|
||||
['a'],
|
||||
[('| 2',)],
|
||||
True,
|
||||
False,
|
||||
True,
|
||||
'--',
|
||||
"""| a |
|
||||
| --- |
|
||||
| \\| 2 |""",
|
||||
),
|
||||
(
|
||||
[],
|
||||
@@ -252,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,
|
||||
@@ -262,7 +328,7 @@ def test__markdown_table(
|
||||
expected,
|
||||
):
|
||||
assert (
|
||||
_markdown_table(
|
||||
markdown_table(
|
||||
header,
|
||||
body,
|
||||
allow_markdown_table=allow_markdown_table,
|
||||
@@ -402,7 +468,7 @@ def test__markdown_table(
|
||||
),
|
||||
],
|
||||
)
|
||||
def test__markdown_table_exceptions(
|
||||
def test_markdown_table_exceptions(
|
||||
header,
|
||||
body,
|
||||
allow_markdown_table,
|
||||
@@ -413,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,
|
||||
Reference in new issue
Block a user