-
Notifications
You must be signed in to change notification settings - Fork 17
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
98d3cf0
commit 1c569ca
Showing
5 changed files
with
224 additions
and
85 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
# Author: Felix Fontein <felix@fontein.de> | ||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or | ||
# https://www.gnu.org/licenses/gpl-3.0.txt) | ||
# SPDX-License-Identifier: GPL-3.0-or-later | ||
# SPDX-FileCopyrightText: 2022, Ansible Project | ||
""" | ||
Internal parsing code. | ||
""" | ||
|
||
import re | ||
import typing as t | ||
|
||
_ESCAPE_OR_COMMA = re.compile(r'\\(.)| *(,) *') | ||
_ESCAPE_OR_CLOSING = re.compile(r'\\(.)|([)])') | ||
|
||
|
||
def parse_parameters_escaped(text: str, index: int, parameter_count: int, | ||
) -> t.Tuple[t.List[str], int, t.Optional[str]]: | ||
result: t.List[str] = [] | ||
parameters_left = parameter_count | ||
while parameters_left > 1: | ||
parameters_left -= 1 | ||
value: t.List[str] = [] | ||
while True: | ||
match = _ESCAPE_OR_COMMA.search(text, pos=index) | ||
if not match: | ||
result.append(''.join(value)) | ||
return ( | ||
result, | ||
len(text), | ||
'Cannot find comma separating parameter' | ||
f' {parameter_count - parameters_left} from the next one' | ||
) | ||
value.append(text[index:match.start(0)]) | ||
index = match.end(0) | ||
if match.group(1): | ||
value.append(match.group(1)) | ||
else: | ||
break | ||
result.append(''.join(value)) | ||
value = [] | ||
while True: | ||
match = _ESCAPE_OR_CLOSING.search(text, pos=index) | ||
if not match: | ||
result.append(''.join(value)) | ||
return result, len(text), 'Cannot find closing ")" after last parameter' | ||
value.append(text[index:match.start(0)]) | ||
index = match.end(0) | ||
if match.group(1): | ||
value.append(match.group(1)) | ||
else: | ||
break | ||
result.append(''.join(value)) | ||
return result, index, None | ||
|
||
|
||
def parse_parameters_unescaped(text: str, index: int, parameter_count: int, | ||
) -> t.Tuple[t.List[str], int, t.Optional[str]]: | ||
result: t.List[str] = [] | ||
first = True | ||
parameters_left = parameter_count | ||
while parameters_left > 1: | ||
parameters_left -= 1 | ||
next_index = text.find(',', index) | ||
if next_index < 0: | ||
return ( | ||
result, | ||
len(text), | ||
'Cannot find comma separating parameter' | ||
f' {parameter_count - parameters_left} from the next one' | ||
) | ||
parameter = text[index:next_index].rstrip(' ') | ||
if not first: | ||
parameter = parameter.lstrip(' ') | ||
else: | ||
first = False | ||
result.append(parameter) | ||
index = next_index + 1 | ||
next_index = text.find(')', index) | ||
if next_index < 0: | ||
return result, len(text), 'Cannot find closing ")" after last parameter' | ||
parameter = text[index:next_index] | ||
if not first: | ||
parameter = parameter.lstrip(' ') | ||
result.append(parameter) | ||
index = next_index + 1 | ||
return result, index, None |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) | ||
# SPDX-License-Identifier: GPL-3.0-or-later | ||
# SPDX-FileCopyrightText: 2020, Ansible Project | ||
|
||
import pytest | ||
|
||
from antsibull_docs.markup.rstify import rst_escape, rst_ify | ||
|
||
RST_IFY_DATA = { | ||
# No substitutions | ||
'no-op': 'no-op', | ||
'no-op Z(test)': 'no-op Z(test)', | ||
# Simple cases of all substitutions | ||
'I(italic)': r'\ :emphasis:`italic`\ ', | ||
'B(bold)': r'\ :strong:`bold`\ ', | ||
'M(ansible.builtin.yum)': r'\ :ref:`ansible.builtin.yum' | ||
r' <ansible_collections.ansible.builtin.yum_module>`\ ', | ||
'U(https://docs.ansible.com)': r'\ https://docs.ansible.com\ ', | ||
'L(the user guide,https://docs.ansible.com/user-guide.html)': r'\ `the user guide' | ||
r' <https://docs.ansible.com/user-guide.html>`__\ ', | ||
'R(the user guide,user-guide)': r'\ :ref:`the user guide <user-guide>`\ ', | ||
'C(/usr/bin/file)': r'\ :literal:`/usr/bin/file`\ ', | ||
'HORIZONTALLINE': '\n\n.. raw:: html\n\n <hr>\n\n', | ||
# Multiple substitutions | ||
'The M(ansible.builtin.yum) module B(MUST) be given the C(package) parameter. See the R(looping docs,using-loops) for more info': | ||
r'The \ :ref:`ansible.builtin.yum <ansible_collections.ansible.builtin.yum_module>`\ module \ :strong:`MUST`\ be given the \ :literal:`package`\ parameter. See the \ :ref:`looping docs <using-loops>`\ for more info', | ||
# Problem cases | ||
'IBM(International Business Machines)': 'IBM(International Business Machines)', | ||
'L(the user guide, https://docs.ansible.com/)': r'\ `the user guide <https://docs.ansible.com/>`__\ ', | ||
'R(the user guide, user-guide)': r'\ :ref:`the user guide <user-guide>`\ ', | ||
} | ||
|
||
|
||
@pytest.mark.parametrize('text, expected', RST_IFY_DATA.items()) | ||
def test_rst_ify(text, expected): | ||
assert rst_ify(text, plugin_fqcn='foo.bar.baz', plugin_type='module')[0] == expected | ||
|
||
|
||
RST_ESCAPE_DATA = { | ||
'': '', | ||
'no-op': 'no-op', | ||
None: 'None', | ||
1: '1', | ||
'*': '\\*', | ||
'_': '\\_', | ||
'<': '\\<', | ||
'>': '\\>', | ||
'`': '\\`', | ||
'\\': '\\\\', | ||
'\\*': '\\\\\\*', | ||
'*\\': '\\*\\\\', | ||
':role:`test`': ':role:\\`test\\`', | ||
} | ||
|
||
|
||
@pytest.mark.parametrize('value, expected', RST_ESCAPE_DATA.items()) | ||
def test_escape_ify(value, expected): | ||
assert rst_escape(value) == expected |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
# Author: Felix Fontein <felix@fontein.de> | ||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) | ||
# SPDX-License-Identifier: GPL-3.0-or-later | ||
# SPDX-FileCopyrightText: 2022, Ansible Project | ||
|
||
import typing as t | ||
|
||
import pytest | ||
|
||
from antsibull_docs.markup._parser_impl import parse_parameters_escaped, parse_parameters_unescaped | ||
|
||
|
||
ESCAPED_TESTS = [ | ||
['(a)', 1, 1, ['a'], 3, None], | ||
['(a,b)', 1, 1, ['a,b'], 5, None], | ||
['(a,b,c)', 1, 1, ['a,b,c'], 7, None], | ||
['(a,b)', 1, 2, ['a', 'b'], 5, None], | ||
['(a,b,c)', 1, 2, ['a', 'b,c'], 7, None], | ||
['(a,b,c)', 1, 3, ['a', 'b', 'c'], 7, None], | ||
['(a\\,,b\\,\\),c\\))', 1, 3, ['a,', 'b,)', 'c)'], 15, None], | ||
['(a', 1, 1, [''], 2, 'Cannot find closing ")" after last parameter'], | ||
['(a', 1, 2, [''], 2, 'Cannot find comma separating parameter 1 from the next one'], | ||
['(a,b', 1, 2, ['a', ''], 4, 'Cannot find closing ")" after last parameter'], | ||
] | ||
|
||
|
||
@pytest.mark.parametrize( | ||
'text, index, parameter_count, expected_result, expected_index, expected_error', | ||
ESCAPED_TESTS, | ||
) | ||
def test_parse_parameters_escaped(text: str, index: int, parameter_count: int, | ||
expected_result: t.List[str], expected_index: int, | ||
expected_error: t.Optional[str]) -> None: | ||
result, end_index, error = parse_parameters_escaped(text, index, parameter_count) | ||
print(result, end_index, error) | ||
assert result == expected_result | ||
assert end_index == expected_index | ||
assert error == expected_error | ||
|
||
|
||
UNESCAPED_TESTS = [ | ||
['(a)', 1, 1, ['a'], 3, None], | ||
['(a,b)', 1, 1, ['a,b'], 5, None], | ||
['(a,b,c)', 1, 1, ['a,b,c'], 7, None], | ||
['(a,b)', 1, 2, ['a', 'b'], 5, None], | ||
['(a,b,c)', 1, 2, ['a', 'b,c'], 7, None], | ||
['(a,b,c)', 1, 3, ['a', 'b', 'c'], 7, None], | ||
['(a', 1, 1, [], 2, 'Cannot find closing ")" after last parameter'], | ||
['(a', 1, 2, [], 2, 'Cannot find comma separating parameter 1 from the next one'], | ||
['(a,b', 1, 2, ['a'], 4, 'Cannot find closing ")" after last parameter'], | ||
] | ||
|
||
|
||
@pytest.mark.parametrize( | ||
'text, index, parameter_count, expected_result, expected_index, expected_error', | ||
UNESCAPED_TESTS, | ||
) | ||
def test_parse_parameters_unescaped(text: str, index: int, parameter_count: int, | ||
expected_result: t.List[str], expected_index: int, | ||
expected_error: t.Optional[str]) -> None: | ||
result, end_index, error = parse_parameters_unescaped(text, index, parameter_count) | ||
print(result, end_index, error) | ||
assert result == expected_result | ||
assert end_index == expected_index | ||
assert error == expected_error |