Skip to content

Commit 1bbaeb3

Browse files
authored
Adding dedicated test_const_name. (#3578)
* Adding dedicated test_const_name. Also exercises pybind11::detail::_ backward compatibility. See also: PR #3423 * Backing out tests involving int_to_str (requires C++17 or higher). * Suppressing clang-tidy errors. * Disabling test_const_name for MSVC 2015 due to bizarre failures. * Stacking @pytest.mark.parametrize (thanks to @Skylion007 for pointing out).
1 parent 9b4f71d commit 1bbaeb3

File tree

5 files changed

+110
-4
lines changed

5 files changed

+110
-4
lines changed

include/pybind11/detail/descr.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ constexpr descr<0> const_name(char const(&)[1]) { return {}; }
5959

6060
template <size_t Rem, size_t... Digits> struct int_to_str : int_to_str<Rem/10, Rem%10, Digits...> { };
6161
template <size_t...Digits> struct int_to_str<0, Digits...> {
62+
// WARNING: This only works with C++17 or higher.
6263
static constexpr auto digits = descr<sizeof...(Digits)>(('0' + Digits)...);
6364
};
6465

@@ -84,9 +85,12 @@ auto constexpr const_name() -> remove_cv_t<decltype(int_to_str<Size / 10, Size %
8485

8586
template <typename Type> constexpr descr<1, Type> const_name() { return {'%'}; }
8687

87-
// The "_" might be defined as a macro - don't define it if so.
88-
// Repeating the const_name code to avoid introducing a #define.
88+
// If "_" is defined as a macro, py::detail::_ cannot be provided.
89+
// It is therefore best to use py::detail::const_name universally.
90+
// This block is for backward compatibility only.
91+
// (The const_name code is repeated to avoid introducing a "_" #define ourselves.)
8992
#ifndef _
93+
#define PYBIND11_DETAIL_UNDERSCORE_BACKWARD_COMPATIBILITY
9094
template <size_t N>
9195
constexpr descr<N-1> _(char const(&text)[N]) { return const_name<N>(text); }
9296
template <bool B, size_t N1, size_t N2>
@@ -107,7 +111,7 @@ auto constexpr _() -> remove_cv_t<decltype(int_to_str<Size / 10, Size % 10>::dig
107111
return const_name<Size>();
108112
}
109113
template <typename Type> constexpr descr<1, Type> _() { return const_name<Type>(); }
110-
#endif
114+
#endif // #ifndef _
111115

112116
constexpr descr<0> concat() { return {}; }
113117

tests/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ set(PYBIND11_TEST_FILES
101101
test_callbacks.cpp
102102
test_chrono.cpp
103103
test_class.cpp
104+
test_const_name.cpp
104105
test_constants_and_functions.cpp
105106
test_copy_move.cpp
106107
test_custom_type_casters.cpp

tests/test_const_name.cpp

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
// Copyright (c) 2021 The Pybind Development Team.
2+
// All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
#include "pybind11_tests.h"
6+
7+
#if defined(_MSC_VER) && _MSC_VER < 1910
8+
9+
// MSVC 2015 fails in bizarre ways.
10+
# define PYBIND11_SKIP_TEST_CONST_NAME
11+
12+
#else // Only test with MSVC 2017 or newer.
13+
14+
// IUT = Implementation Under Test
15+
# define CONST_NAME_TESTS(TEST_FUNC, IUT) \
16+
std::string TEST_FUNC(int selector) { \
17+
switch (selector) { \
18+
case 0: \
19+
return IUT("").text; \
20+
case 1: \
21+
return IUT("A").text; \
22+
case 2: \
23+
return IUT("Bd").text; \
24+
case 3: \
25+
return IUT("Cef").text; \
26+
case 4: \
27+
return IUT<int>().text; /*NOLINT(bugprone-macro-parentheses)*/ \
28+
case 5: \
29+
return IUT<std::string>().text; /*NOLINT(bugprone-macro-parentheses)*/ \
30+
case 6: \
31+
return IUT<true>("T1", "T2").text; /*NOLINT(bugprone-macro-parentheses)*/ \
32+
case 7: \
33+
return IUT<false>("U1", "U2").text; /*NOLINT(bugprone-macro-parentheses)*/ \
34+
case 8: \
35+
/*NOLINTNEXTLINE(bugprone-macro-parentheses)*/ \
36+
return IUT<true>(IUT("D1"), IUT("D2")).text; \
37+
case 9: \
38+
/*NOLINTNEXTLINE(bugprone-macro-parentheses)*/ \
39+
return IUT<false>(IUT("E1"), IUT("E2")).text; \
40+
case 10: \
41+
return IUT("KeepAtEnd").text; \
42+
default: \
43+
break; \
44+
} \
45+
throw std::runtime_error("Invalid selector value."); \
46+
}
47+
48+
CONST_NAME_TESTS(const_name_tests, py::detail::const_name)
49+
50+
# ifdef PYBIND11_DETAIL_UNDERSCORE_BACKWARD_COMPATIBILITY
51+
CONST_NAME_TESTS(underscore_tests, py::detail::_)
52+
# endif
53+
54+
#endif // MSVC >= 2017
55+
56+
TEST_SUBMODULE(const_name, m) {
57+
#ifdef PYBIND11_SKIP_TEST_CONST_NAME
58+
m.attr("const_name_tests") = "PYBIND11_SKIP_TEST_CONST_NAME";
59+
#else
60+
m.def("const_name_tests", const_name_tests);
61+
#endif
62+
63+
#ifdef PYBIND11_SKIP_TEST_CONST_NAME
64+
m.attr("underscore_tests") = "PYBIND11_SKIP_TEST_CONST_NAME";
65+
#elif defined(PYBIND11_DETAIL_UNDERSCORE_BACKWARD_COMPATIBILITY)
66+
m.def("underscore_tests", underscore_tests);
67+
#else
68+
m.attr("underscore_tests") = "PYBIND11_DETAIL_UNDERSCORE_BACKWARD_COMPATIBILITY not defined.";
69+
#endif
70+
}

tests/test_const_name.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# -*- coding: utf-8 -*-
2+
import pytest
3+
4+
import env
5+
from pybind11_tests import const_name as m
6+
7+
8+
@pytest.mark.parametrize("func", (m.const_name_tests, m.underscore_tests))
9+
@pytest.mark.parametrize(
10+
"selector, expected",
11+
enumerate(
12+
(
13+
"",
14+
"A",
15+
"Bd",
16+
"Cef",
17+
"%",
18+
"%",
19+
"T1",
20+
"U2",
21+
"D1",
22+
"E2",
23+
"KeepAtEnd",
24+
)
25+
),
26+
)
27+
def test_const_name(func, selector, expected):
28+
if isinstance(func, type(u"") if env.PY2 else str):
29+
pytest.skip(func)
30+
text = func(selector)
31+
assert text == expected

tests/test_custom_type_casters.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ namespace pybind11 { namespace detail {
1919
template <> struct type_caster<ArgInspector1> {
2020
public:
2121
// Classic
22-
#ifndef _
22+
#ifdef PYBIND11_DETAIL_UNDERSCORE_BACKWARD_COMPATIBILITY
2323
PYBIND11_TYPE_CASTER(ArgInspector1, _("ArgInspector1"));
2424
#else
2525
PYBIND11_TYPE_CASTER(ArgInspector1, const_name("ArgInspector1"));

0 commit comments

Comments
 (0)