From 282eb720b1356387ff549a46e1a4e73086f957aa Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Wed, 2 Feb 2022 07:07:04 -0800 Subject: [PATCH 1/3] [Experiment] `std::type_index` & unnamed namespace Related to PRs #4313, #4315 --- include/pybind11/detail/internals.h | 2 ++ tests/CMakeLists.txt | 2 ++ tests/test_unnamed_namespace_a.cpp | 23 +++++++++++++++++++++++ tests/test_unnamed_namespace_a.py | 15 +++++++++++++++ tests/test_unnamed_namespace_b.cpp | 13 +++++++++++++ tests/test_unnamed_namespace_b.py | 5 +++++ 6 files changed, 60 insertions(+) create mode 100644 tests/test_unnamed_namespace_a.cpp create mode 100644 tests/test_unnamed_namespace_a.py create mode 100644 tests/test_unnamed_namespace_b.cpp create mode 100644 tests/test_unnamed_namespace_b.py diff --git a/include/pybind11/detail/internals.h b/include/pybind11/detail/internals.h index 6fd61098c4..572af423dc 100644 --- a/include/pybind11/detail/internals.h +++ b/include/pybind11/detail/internals.h @@ -209,6 +209,8 @@ struct internals { PYBIND11_TLS_FREE(tstate); } #endif + + std::unordered_map> std_type_index_registry; }; /// Additional type information which does not fit into the PyTypeObject. diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 491f215cef..285f43b5b9 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -156,6 +156,8 @@ set(PYBIND11_TEST_FILES test_tagbased_polymorphic test_thread test_union + test_unnamed_namespace_a + test_unnamed_namespace_b test_virtual_functions) # Invoking cmake with something like: diff --git a/tests/test_unnamed_namespace_a.cpp b/tests/test_unnamed_namespace_a.cpp new file mode 100644 index 0000000000..17501ca733 --- /dev/null +++ b/tests/test_unnamed_namespace_a.cpp @@ -0,0 +1,23 @@ +#include + +#include "pybind11_tests.h" + +namespace { +struct any_struct {}; +} // namespace + +TEST_SUBMODULE(unnamed_namespace_a, m) { + m.attr("name") = "A"; + + py::detail::get_internals() + .std_type_index_registry[std::type_index(typeid(any_struct))] + .push_back("A"); + + m.def("std_type_index_registry_dump", []() { + py::list items; + for (const auto &it : py::detail::get_internals().std_type_index_registry) { + items.append(py::make_tuple(it.first.name(), it.second)); + } + return items; + }); +} diff --git a/tests/test_unnamed_namespace_a.py b/tests/test_unnamed_namespace_a.py new file mode 100644 index 0000000000..ac2712bb67 --- /dev/null +++ b/tests/test_unnamed_namespace_a.py @@ -0,0 +1,15 @@ +import pytest + +from pybind11_tests import unnamed_namespace_a as m + + +def test_inspect(): + assert m.name == "A" + reg = m.std_type_index_registry_dump() + if len(reg) == 1: + assert tuple(sorted(reg[0][1])) == ("A", "B") + pytest.skip("std::type_index-EQ-BAD") + if len(reg) == 2: + assert tuple(sorted([reg[0][1][0], reg[1][1][0]])) == ("A", "B") + pytest.skip("std::type_index-NE-GOOD") + assert reg is None # Sure to fail. diff --git a/tests/test_unnamed_namespace_b.cpp b/tests/test_unnamed_namespace_b.cpp new file mode 100644 index 0000000000..4b5304c118 --- /dev/null +++ b/tests/test_unnamed_namespace_b.cpp @@ -0,0 +1,13 @@ +#include "pybind11_tests.h" + +namespace { +struct any_struct {}; +} // namespace + +TEST_SUBMODULE(unnamed_namespace_b, m) { + m.attr("name") = "B"; + + py::detail::get_internals() + .std_type_index_registry[std::type_index(typeid(any_struct))] + .push_back("B"); +} diff --git a/tests/test_unnamed_namespace_b.py b/tests/test_unnamed_namespace_b.py new file mode 100644 index 0000000000..4409bb45aa --- /dev/null +++ b/tests/test_unnamed_namespace_b.py @@ -0,0 +1,5 @@ +from pybind11_tests import unnamed_namespace_b as m + + +def test_inspect(): + assert m.name == "B" From db228274044da1df1746b86d3ad16e943b414bd0 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Sun, 6 Nov 2022 18:28:53 -0800 Subject: [PATCH 2/3] Add test_named_namespace_a, test_named_namespace_b --- include/pybind11/detail/internals.h | 5 ++++- tests/CMakeLists.txt | 4 ++++ tests/named_namespace_a.cpp | 25 +++++++++++++++++++++++++ tests/named_namespace_b.cpp | 14 ++++++++++++++ tests/test_named_namespace_a.py | 15 +++++++++++++++ tests/test_named_namespace_b.py | 5 +++++ tests/test_unnamed_namespace_a.cpp | 9 +++++---- tests/test_unnamed_namespace_a.py | 6 +++--- tests/test_unnamed_namespace_b.cpp | 6 +++--- tests/test_unnamed_namespace_b.py | 2 +- 10 files changed, 79 insertions(+), 12 deletions(-) create mode 100644 tests/named_namespace_a.cpp create mode 100644 tests/named_namespace_b.cpp create mode 100644 tests/test_named_namespace_a.py create mode 100644 tests/test_named_namespace_b.py diff --git a/include/pybind11/detail/internals.h b/include/pybind11/detail/internals.h index 572af423dc..8183ce8a58 100644 --- a/include/pybind11/detail/internals.h +++ b/include/pybind11/detail/internals.h @@ -210,7 +210,10 @@ struct internals { } #endif - std::unordered_map> std_type_index_registry; + std::unordered_map> + std_type_index_registry_unnamed_namespace; + std::unordered_map> + std_type_index_registry_named_namespace; }; /// Additional type information which does not fit into the PyTypeObject. diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 285f43b5b9..d615c690c6 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -142,6 +142,8 @@ set(PYBIND11_TEST_FILES test_methods_and_attributes test_modules test_multiple_inheritance + test_named_namespace_a.py + test_named_namespace_b.py test_numpy_array test_numpy_dtypes test_numpy_vectorize @@ -221,6 +223,8 @@ tests_extra_targets("test_exceptions.py;test_local_bindings.py;test_stl.py;test_ # And add additional targets for other tests. tests_extra_targets("test_exceptions.py" "cross_module_interleaved_error_already_set") tests_extra_targets("test_gil_scoped.py" "cross_module_gil_utils") +tests_extra_targets("test_named_namespace_a.py" "named_namespace_a") +tests_extra_targets("test_named_namespace_b.py" "named_namespace_b") set(PYBIND11_EIGEN_REPO "https://gitlab.com/libeigen/eigen.git" diff --git a/tests/named_namespace_a.cpp b/tests/named_namespace_a.cpp new file mode 100644 index 0000000000..f997119d30 --- /dev/null +++ b/tests/named_namespace_a.cpp @@ -0,0 +1,25 @@ +#include + +#include "pybind11_tests.h" + +namespace test_named_namespace { +struct any_struct {}; +} // namespace test_named_namespace + +PYBIND11_MODULE(named_namespace_a, m) { + m.attr("name") = "NA"; + + py::detail::get_internals() + .std_type_index_registry_named_namespace[std::type_index( + typeid(test_named_namespace::any_struct))] + .push_back("NA"); + + m.def("std_type_index_registry_dump", []() { + py::list items; + for (const auto &it : + py::detail::get_internals().std_type_index_registry_named_namespace) { + items.append(py::make_tuple(it.first.name(), it.second)); + } + return items; + }); +} diff --git a/tests/named_namespace_b.cpp b/tests/named_namespace_b.cpp new file mode 100644 index 0000000000..ca38e17800 --- /dev/null +++ b/tests/named_namespace_b.cpp @@ -0,0 +1,14 @@ +#include "pybind11_tests.h" + +namespace test_named_namespace { +struct any_struct {}; +} // namespace test_named_namespace + +PYBIND11_MODULE(named_namespace_b, m) { + m.attr("name") = "NB"; + + py::detail::get_internals() + .std_type_index_registry_named_namespace[std::type_index( + typeid(test_named_namespace::any_struct))] + .push_back("NB"); +} diff --git a/tests/test_named_namespace_a.py b/tests/test_named_namespace_a.py new file mode 100644 index 0000000000..e19f31f169 --- /dev/null +++ b/tests/test_named_namespace_a.py @@ -0,0 +1,15 @@ +import named_namespace_a as m +import pytest + + +def test_inspect(): + assert m.name == "NA" + reg = m.std_type_index_registry_dump() + if len(reg) == 1: + assert tuple(sorted(reg[0][1])) == ("NA", "NB") + pytest.skip("std::type_index-EQ-GOOD") + if len(reg) == 2: + assert reg[0][0] == reg[1][0] + assert tuple(sorted(reg[0][1] + reg[1][1])) == ("NA", "NB") + pytest.skip("std::type_index-NE-BAD") + assert reg is None # Sure to fail. diff --git a/tests/test_named_namespace_b.py b/tests/test_named_namespace_b.py new file mode 100644 index 0000000000..f00fd97af2 --- /dev/null +++ b/tests/test_named_namespace_b.py @@ -0,0 +1,5 @@ +import named_namespace_b as m + + +def test_inspect(): + assert m.name == "NB" diff --git a/tests/test_unnamed_namespace_a.cpp b/tests/test_unnamed_namespace_a.cpp index 17501ca733..00d55d5da0 100644 --- a/tests/test_unnamed_namespace_a.cpp +++ b/tests/test_unnamed_namespace_a.cpp @@ -7,15 +7,16 @@ struct any_struct {}; } // namespace TEST_SUBMODULE(unnamed_namespace_a, m) { - m.attr("name") = "A"; + m.attr("name") = "UA"; py::detail::get_internals() - .std_type_index_registry[std::type_index(typeid(any_struct))] - .push_back("A"); + .std_type_index_registry_unnamed_namespace[std::type_index(typeid(any_struct))] + .push_back("UA"); m.def("std_type_index_registry_dump", []() { py::list items; - for (const auto &it : py::detail::get_internals().std_type_index_registry) { + for (const auto &it : + py::detail::get_internals().std_type_index_registry_unnamed_namespace) { items.append(py::make_tuple(it.first.name(), it.second)); } return items; diff --git a/tests/test_unnamed_namespace_a.py b/tests/test_unnamed_namespace_a.py index ac2712bb67..ea882cc8d8 100644 --- a/tests/test_unnamed_namespace_a.py +++ b/tests/test_unnamed_namespace_a.py @@ -4,12 +4,12 @@ def test_inspect(): - assert m.name == "A" + assert m.name == "UA" reg = m.std_type_index_registry_dump() if len(reg) == 1: - assert tuple(sorted(reg[0][1])) == ("A", "B") + assert tuple(sorted(reg[0][1])) == ("UA", "UB") pytest.skip("std::type_index-EQ-BAD") if len(reg) == 2: - assert tuple(sorted([reg[0][1][0], reg[1][1][0]])) == ("A", "B") + assert tuple(sorted([reg[0][1][0], reg[1][1][0]])) == ("UA", "UB") pytest.skip("std::type_index-NE-GOOD") assert reg is None # Sure to fail. diff --git a/tests/test_unnamed_namespace_b.cpp b/tests/test_unnamed_namespace_b.cpp index 4b5304c118..c38691af2f 100644 --- a/tests/test_unnamed_namespace_b.cpp +++ b/tests/test_unnamed_namespace_b.cpp @@ -5,9 +5,9 @@ struct any_struct {}; } // namespace TEST_SUBMODULE(unnamed_namespace_b, m) { - m.attr("name") = "B"; + m.attr("name") = "UB"; py::detail::get_internals() - .std_type_index_registry[std::type_index(typeid(any_struct))] - .push_back("B"); + .std_type_index_registry_unnamed_namespace[std::type_index(typeid(any_struct))] + .push_back("UB"); } diff --git a/tests/test_unnamed_namespace_b.py b/tests/test_unnamed_namespace_b.py index 4409bb45aa..4c033597bd 100644 --- a/tests/test_unnamed_namespace_b.py +++ b/tests/test_unnamed_namespace_b.py @@ -2,4 +2,4 @@ def test_inspect(): - assert m.name == "B" + assert m.name == "UB" From 5b58918bb660e54bd65f3647beff99ef67cb4b6c Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Sun, 6 Nov 2022 19:04:00 -0800 Subject: [PATCH 3/3] Rename test_named_namespace_?.py to test_exc_named_namespace_?.py, to work around the same issue as described under PR #4054. --- tests/CMakeLists.txt | 8 ++++---- ...named_namespace_a.py => test_exc_named_namespace_a.py} | 0 ...named_namespace_b.py => test_exc_named_namespace_b.py} | 0 3 files changed, 4 insertions(+), 4 deletions(-) rename tests/{test_named_namespace_a.py => test_exc_named_namespace_a.py} (100%) rename tests/{test_named_namespace_b.py => test_exc_named_namespace_b.py} (100%) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index d615c690c6..20bc6de2a4 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -133,6 +133,8 @@ set(PYBIND11_TEST_FILES test_eigen_tensor_avoid_stl_array.cpp test_enum test_eval + test_exc_named_namespace_a.py + test_exc_named_namespace_b.py test_exceptions test_factory_constructors test_gil_scoped @@ -142,8 +144,6 @@ set(PYBIND11_TEST_FILES test_methods_and_attributes test_modules test_multiple_inheritance - test_named_namespace_a.py - test_named_namespace_b.py test_numpy_array test_numpy_dtypes test_numpy_vectorize @@ -223,8 +223,8 @@ tests_extra_targets("test_exceptions.py;test_local_bindings.py;test_stl.py;test_ # And add additional targets for other tests. tests_extra_targets("test_exceptions.py" "cross_module_interleaved_error_already_set") tests_extra_targets("test_gil_scoped.py" "cross_module_gil_utils") -tests_extra_targets("test_named_namespace_a.py" "named_namespace_a") -tests_extra_targets("test_named_namespace_b.py" "named_namespace_b") +tests_extra_targets("test_exc_named_namespace_a.py" "named_namespace_a") +tests_extra_targets("test_exc_named_namespace_b.py" "named_namespace_b") set(PYBIND11_EIGEN_REPO "https://gitlab.com/libeigen/eigen.git" diff --git a/tests/test_named_namespace_a.py b/tests/test_exc_named_namespace_a.py similarity index 100% rename from tests/test_named_namespace_a.py rename to tests/test_exc_named_namespace_a.py diff --git a/tests/test_named_namespace_b.py b/tests/test_exc_named_namespace_b.py similarity index 100% rename from tests/test_named_namespace_b.py rename to tests/test_exc_named_namespace_b.py