Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions changelogs/fragments/15-code-blocks.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
minor_changes:
- "Allow to find all literal blocks without language
(https://github.com/ansible-community/antsibull-docutils/pull/15)."
36 changes: 32 additions & 4 deletions src/antsibull_docutils/rst_code_finder.py
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,9 @@ def __init__(
callback: t.Callable[
[str, int, int, bool, bool, str, nodes.literal_block], None
],
warn_unknown_block: t.Callable[[int | str, int, nodes.literal_block], None],
warn_unknown_block: t.Callable[
[int | str, int, nodes.literal_block, bool], None
],
):
super().__init__(document)
self.__content_lines = content.splitlines()
Expand All @@ -216,7 +218,9 @@ def visit_literal_block(self, node: nodes.literal_block) -> None:
"""
if "antsibull-code-block" not in node.attributes:
# This could be a `::` block, or something else (unknown)
self.__warn_unknown_block(node.line or "unknown", 0, node)
self.__warn_unknown_block(
node.line or "unknown", 0, node, bool(node.attributes["classes"])
)
raise nodes.SkipNode

language = node.attributes["antsibull-code-language"]
Expand Down Expand Up @@ -316,13 +320,22 @@ def find_code_blocks_in_document(
document: nodes.document,
content: str,
warn_unknown_block: t.Callable[[int | str, int, str], None] | None = None,
warn_unknown_block_w_unknown_info: (
t.Callable[[int | str, int, str, bool], None] | None
) = None,
) -> t.Generator[CodeBlockInfo]:
"""
Given a parsed RST document, finds all code blocks.

All code blocks must be parsed with special directives
(see ``get_code_block_directives()``) that have appropriate metadata
registered with ``mark_antsibull_code_block()``.

You can provide callbacks:
* ``warn_unknown_block()`` will be called for every literal block
that's of unknown origin.
* ``warn_unknown_block_w_unknown_info()`` will be called for every
literal block that's of known or unknown origin.
"""
# If someone can figure out how to yield from a sub-function, we can avoid
# using this ugly list
Expand Down Expand Up @@ -357,9 +370,14 @@ def warn_unknown_block_cb(
line: int | str,
col: int,
node: nodes.literal_block,
unknown_directive: bool,
) -> None:
if warn_unknown_block:
if warn_unknown_block and unknown_directive:
warn_unknown_block(line, col, node.rawsource)
if warn_unknown_block_w_unknown_info:
warn_unknown_block_w_unknown_info(
line, col, node.rawsource, unknown_directive
)

# Process the document
try:
Expand All @@ -371,20 +389,29 @@ def warn_unknown_block_cb(
yield from results


def find_code_blocks(
def find_code_blocks( # pylint: disable=too-many-arguments
content: str,
*,
path: str | os.PathLike[str] | None = None,
root_prefix: str | os.PathLike[str] | None = None,
extra_directives: Mapping[str, t.Type[Directive]] | None = None,
warn_unknown_block: t.Callable[[int | str, int, str], None] | None = None,
warn_unknown_block_w_unknown_info: (
t.Callable[[int | str, int, str, bool], None] | None
) = None,
) -> t.Generator[CodeBlockInfo]:
"""
Given a RST document, finds all code blocks.

To add support for own types of code blocks, you can pass these
as ``extra_directives``. Use ``mark_antsibull_code_block()`` to
mark them to be found by ``find_code_blocks()``.

You can provide callbacks:
* ``warn_unknown_block()`` will be called for every literal block
that's of unknown origin.
* ``warn_unknown_block_w_unknown_info()`` will be called for every
literal block that's of known or unknown origin.
"""
directives = get_code_block_directives(extra_directives=extra_directives)

Expand All @@ -400,6 +427,7 @@ def find_code_blocks(
document=doc,
content=content,
warn_unknown_block=warn_unknown_block,
warn_unknown_block_w_unknown_info=warn_unknown_block_w_unknown_info,
)


Expand Down
28 changes: 25 additions & 3 deletions tests/test_rst_code_finder.py
Original file line number Diff line number Diff line change
Expand Up @@ -284,17 +284,37 @@ def test_find_code_blocks_ext():
foobar

Some invalid `markup <foo>

.. highlight:: python

::

def foo():
pass

.. literalinclude:: nox.py

| a
| b
c
"""
found_warnings = []
found_warnings_2 = []

def add_warning(line: int | str, col: int, message: str) -> None:
found_warnings.append((line, col, message))

def add_warning_2(
line: int | str, col: int, message: str, unknown_origin: bool
) -> None:
found_warnings_2.append((line, col, message, unknown_origin))

found_code_block_infos = list(
find_code_blocks(
source,
extra_directives={"foo": CodeBlockTest},
warn_unknown_block=add_warning,
warn_unknown_block_w_unknown_info=add_warning_2,
)
)
assert found_code_block_infos == [
Expand All @@ -317,9 +337,11 @@ def add_warning(line: int | str, col: int, message: str) -> None:
attributes={},
),
]
assert found_warnings == [
(6, 0, "bar"),
(12, 0, "bazbam"),
assert found_warnings == []
assert found_warnings_2 == [
(6, 0, "bar", False),
(12, 0, "bazbam", False),
(24, 0, "def foo():\n pass", False),
]


Expand Down