From 21f52eb0c7778058ffe0c73317b1c1d5cecf7522 Mon Sep 17 00:00:00 2001 From: Tim Ohliger Date: Fri, 10 Jan 2025 11:59:37 +0100 Subject: [PATCH] Simplified special character check --- include/pybind11/pybind11.h | 7 ++++--- tests/test_pytypes.cpp | 2 +- tests/test_pytypes.py | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/include/pybind11/pybind11.h b/include/pybind11/pybind11.h index 5e277d5a1a..655bec3986 100644 --- a/include/pybind11/pybind11.h +++ b/include/pybind11/pybind11.h @@ -445,6 +445,9 @@ class cpp_function : public function { // signature. Using `@^`/`@$` we can force types to be arg/return types while `@!` pops // back to the previous state. std::stack is_return_value({false}); + // The following characters have special meaning in the signature parsing. Literals + // containing these are escaped with `!`. + std::string special_chars("!@%{}-"); for (const auto *pc = text; *pc != '\0'; ++pc) { const auto c = *pc; @@ -498,9 +501,7 @@ class cpp_function : public function { } else { signature += detail::quote_cpp_type_name(detail::clean_type_id(t->name())); } - } else if (c == '!' - && (*(pc + 1) == '!' || *(pc + 1) == '@' || *(pc + 1) == '%' - || *(pc + 1) == '{' || *(pc + 1) == '}' || *(pc + 1) == '-')) { + } else if (c == '!' && special_chars.find(*(pc + 1)) != std::string::npos) { // typing::Literal escapes special characters with ! signature += *++pc; } else if (c == '@') { diff --git a/tests/test_pytypes.cpp b/tests/test_pytypes.cpp index 209513db9d..5160e9f408 100644 --- a/tests/test_pytypes.cpp +++ b/tests/test_pytypes.cpp @@ -971,7 +971,7 @@ TEST_SUBMODULE(pytypes, m) { .value("BLUE", literals::Color::BLUE); m.def("annotate_literal", [](literals::LiteralFoo &o) -> py::object { return o; }); - // Literal with `@`, `%`, `{`, and `}` + // Literal with `@`, `%`, `{`, `}`, and `->` m.def("identity_literal_exclamation", [](const py::typing::Literal<"\"!\""> &x) { return x; }); m.def("identity_literal_at", [](const py::typing::Literal<"\"@\""> &x) { return x; }); m.def("identity_literal_percent", [](const py::typing::Literal<"\"%\""> &x) { return x; }); diff --git a/tests/test_pytypes.py b/tests/test_pytypes.py index 9edc6ea5ec..469137cc3c 100644 --- a/tests/test_pytypes.py +++ b/tests/test_pytypes.py @@ -1044,7 +1044,7 @@ def test_literal(doc): doc(m.annotate_literal) == 'annotate_literal(arg0: Literal[26, 0x1A, "hello world", b"hello world", u"hello world", True, Color.RED, None]) -> object' ) - # The characters !, @, %, and {} are used in the signature parser as special characters, but Literal should escape those for the parser to work. + # The characters !, @, %, {, } and -> are used in the signature parser as special characters, but Literal should escape those for the parser to work. assert ( doc(m.identity_literal_exclamation) == 'identity_literal_exclamation(arg0: Literal["!"]) -> Literal["!"]'