diff --git a/CHANGELOG.md b/CHANGELOG.md index df85f2b..a9f7aac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ All notable changes to this project will be documented in this file. - Register flags and positional arguments as Sphinx program options so the `:option:` role links to them. - Leave apostrophes inside words (`don't`, `it's`) alone in help text instead of turning them into broken inline literals. +- Make `:hook:` intercept `parse_intermixed_args()` as well as `parse_args()`. ## 1.13.1 diff --git a/roots/test-hook-intermixed/conf.py b/roots/test-hook-intermixed/conf.py new file mode 100644 index 0000000..9f2a54a --- /dev/null +++ b/roots/test-hook-intermixed/conf.py @@ -0,0 +1,8 @@ +from __future__ import annotations + +import sys +from pathlib import Path + +sys.path.insert(0, str(Path(__file__).parent)) +extensions = ["sphinx_argparse_cli"] +nitpicky = True diff --git a/roots/test-hook-intermixed/index.rst b/roots/test-hook-intermixed/index.rst new file mode 100644 index 0000000..5a80656 --- /dev/null +++ b/roots/test-hook-intermixed/index.rst @@ -0,0 +1,4 @@ +.. sphinx_argparse_cli:: + :module: parser + :func: main + :hook: diff --git a/roots/test-hook-intermixed/parser.py b/roots/test-hook-intermixed/parser.py new file mode 100644 index 0000000..3097bdb --- /dev/null +++ b/roots/test-hook-intermixed/parser.py @@ -0,0 +1,10 @@ +from __future__ import annotations + +from argparse import ArgumentParser + + +def main() -> None: + parser = ArgumentParser(prog="foo", add_help=False) + parser.add_argument("--flag", help="a flag") + args = parser.parse_intermixed_args() + print(args) # noqa: T201 diff --git a/src/sphinx_argparse_cli/_logic.py b/src/sphinx_argparse_cli/_logic.py index c655bb7..cb34051 100644 --- a/src/sphinx_argparse_cli/_logic.py +++ b/src/sphinx_argparse_cli/_logic.py @@ -94,14 +94,15 @@ def parser(self) -> ArgumentParser: raise self.error(msg) # noqa: B904 parser: ArgumentParser | None = None if "hook" in self.options: - original_parse_known_args = ArgumentParser.parse_known_args - ArgumentParser.parse_known_args = _parse_known_args_hook # type: ignore[method-assign,assignment] - try: - parser_creator() - except HookError as hooked: - parser = hooked.parser - finally: - ArgumentParser.parse_known_args = original_parse_known_args + # parse_intermixed_args bypasses parse_known_args since Python 3.12, so both entry points need the hook + with ( + patch.object(ArgumentParser, "parse_known_args", _parse_known_args_hook), + patch.object(ArgumentParser, "parse_known_intermixed_args", _parse_known_args_hook), + ): + try: + parser_creator() + except HookError as hooked: + parser = hooked.parser else: parser = parser_creator() diff --git a/tests/test_logic.py b/tests/test_logic.py index 8bd6d6b..fb61838 100644 --- a/tests/test_logic.py +++ b/tests/test_logic.py @@ -70,6 +70,24 @@ def test_hook(build_outcome: str) -> None: assert build_outcome +@pytest.mark.sphinx(buildername="text", testroot="hook-intermixed") +def test_hook_intermixed(build_outcome: str) -> None: + assert ( + build_outcome + == """foo - CLI interface +******************* + + foo [--flag FLAG] + + +foo options +=========== + +* **"--flag"** "FLAG" - a flag +""" + ) + + @pytest.mark.sphinx(buildername="text", testroot="hook-fail") def test_hook_fail(app: SphinxTestApp, warning: StringIO) -> None: app.build()