From 790241bce25bb0bd60996fcd5750eef1dff9b658 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 11 Jul 2022 22:31:54 -0400 Subject: [PATCH 1/3] [pre-commit.ci] pre-commit autoupdate (#4058) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/asottile/pyupgrade: v2.34.0 → v2.37.1](https://github.com/asottile/pyupgrade/compare/v2.34.0...v2.37.1) - [github.com/hadialqattan/pycln: v1.3.5 → v2.0.1](https://github.com/hadialqattan/pycln/compare/v1.3.5...v2.0.1) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 4b9681984..ba9955a31 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -32,7 +32,7 @@ repos: # Upgrade old Python syntax - repo: https://github.com/asottile/pyupgrade - rev: "v2.34.0" + rev: "v2.37.1" hooks: - id: pyupgrade args: [--py36-plus] @@ -71,7 +71,7 @@ repos: # Autoremoves unused imports - repo: https://github.com/hadialqattan/pycln - rev: "v1.3.5" + rev: "v2.0.1" hooks: - id: pycln stages: [manual] From 023b3f32c83a0faab1a6702cba7fd7bc30589d31 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Tue, 12 Jul 2022 12:02:20 -0700 Subject: [PATCH 2/3] Undo accidental one-line change under PR #3913 (#4060) --- include/pybind11/cast.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/pybind11/cast.h b/include/pybind11/cast.h index 782fb20d4..a0e32281b 100644 --- a/include/pybind11/cast.h +++ b/include/pybind11/cast.h @@ -1625,7 +1625,7 @@ unpacking_collector collect_arguments(Args &&...args) { template template object object_api::operator()(Args &&...args) const { -#if defined(PYBIND11_DETAILED_ERROR_MESSAGES) +#ifndef NDEBUG if (!PyGILState_Check()) { pybind11_fail("pybind11::object_api<>::operator() PyGILState_Check() failure."); } From 203cc26f5b25799962f6550d1ae9850dd7531b68 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Tue, 12 Jul 2022 18:33:42 -0700 Subject: [PATCH 3/3] [smart_holder] Add test_namespace_visibility (#4050) * Add test_namespace_visibility To probe environment/toolchain/platform-specific behavior under the exact same conditions as normal tests. (An earlier version of this code was used to inform PR #4043.) * Disable flake8 in ubench/holder_comparison_*.py, to suppress new & useless diagnostics. * Disable namespace_visibility_1s.cpp (tosee if that resolves the MSVC and CUDA `test_cross_module_exception_translator` failures). * Turn off flake8 completely for ubench (the Strip unnecessary `# noqa`s action un-helpfully removed the added noqa). * Disable test_namespace_visibility completely. Just keep the two .cpp files, only setting the module docstring and doing nothing else. * Rename test_namespace_visibility.py to test_exc_namespace_visibility.py, so that it is imported by pytest before test_exceptions.py * Add `set_property(SOURCE namespace_visibility_1s.cpp PROPERTY LANGUAGE CUDA)` * Add reference to PR #4054 * Complete the documentation (comments in test_exc_namespace_visibility.py). * Rename namespace_visibility.h to namespace_visibility.inl, as suggested by @charlesbeattie --- tests/CMakeLists.txt | 13 ++++- tests/namespace_visibility.inl | 31 ++++++++++++ tests/namespace_visibility_1.cpp | 24 +++++++++ tests/namespace_visibility_1s.cpp | 17 +++++++ tests/namespace_visibility_2.cpp | 17 +++++++ tests/test_exc_namespace_visibility.py | 67 ++++++++++++++++++++++++++ 6 files changed, 167 insertions(+), 2 deletions(-) create mode 100644 tests/namespace_visibility.inl create mode 100644 tests/namespace_visibility_1.cpp create mode 100644 tests/namespace_visibility_1s.cpp create mode 100644 tests/namespace_visibility_2.cpp create mode 100644 tests/test_exc_namespace_visibility.py diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 4769ea677..e7aec339f 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -148,6 +148,7 @@ set(PYBIND11_TEST_FILES test_eigen test_enum test_eval + test_exc_namespace_visibility.py test_exceptions test_factory_constructors test_gil_scoped @@ -236,6 +237,8 @@ tests_extra_targets("test_exceptions.py" "cross_module_interleaved_error_already tests_extra_targets("test_gil_scoped.py" "cross_module_gil_utils") tests_extra_targets("test_class_sh_module_local.py" "class_sh_module_local_0;class_sh_module_local_1;class_sh_module_local_2") +tests_extra_targets("test_exc_namespace_visibility.py" + "namespace_visibility_1;namespace_visibility_2") set(PYBIND11_EIGEN_REPO "https://gitlab.com/libeigen/eigen.git" @@ -426,8 +429,14 @@ if(PYBIND11_CUDA_TESTS) endif() foreach(target ${test_targets}) - set(test_files ${PYBIND11_TEST_FILES}) - if(NOT "${target}" STREQUAL "pybind11_tests") + if("${target}" STREQUAL "pybind11_tests") + set(test_files ${PYBIND11_TEST_FILES}) + elseif("${target}" STREQUAL "namespace_visibility_1") + set(test_files namespace_visibility_1s.cpp) + if(PYBIND11_CUDA_TESTS) + set_property(SOURCE namespace_visibility_1s.cpp PROPERTY LANGUAGE CUDA) + endif() + else() set(test_files "") endif() diff --git a/tests/namespace_visibility.inl b/tests/namespace_visibility.inl new file mode 100644 index 000000000..9ff407a53 --- /dev/null +++ b/tests/namespace_visibility.inl @@ -0,0 +1,31 @@ +// Copyright (c) 2022 The Pybind Development Team. +// All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +#pragma once + +#include + +#ifdef __GNUG__ +# define PYBIND11_NS_VIS_U /* unspecified */ +# define PYBIND11_NS_VIS_H __attribute__((visibility("hidden"))) +#else +# define PYBIND11_NS_VIS_U +# define PYBIND11_NS_VIS_H +#endif + +#define PYBIND11_NS_VIS_FUNC \ + inline std::ptrdiff_t func() { \ + static std::ptrdiff_t value = 0; \ + return reinterpret_cast(&value); \ + } + +#define PYBIND11_NS_VIS_DEFS \ + m.def("ns_vis_uuu_func", pybind11_ns_vis_uuu::func); \ + m.def("ns_vis_uuh_func", pybind11_ns_vis_uuh::func); \ + m.def("ns_vis_uhu_func", pybind11_ns_vis_uhu::func); \ + m.def("ns_vis_uhh_func", pybind11_ns_vis_uhh::func); \ + m.def("ns_vis_huu_func", pybind11_ns_vis_huu::func); \ + m.def("ns_vis_huh_func", pybind11_ns_vis_huh::func); \ + m.def("ns_vis_hhu_func", pybind11_ns_vis_hhu::func); \ + m.def("ns_vis_hhh_func", pybind11_ns_vis_hhh::func); diff --git a/tests/namespace_visibility_1.cpp b/tests/namespace_visibility_1.cpp new file mode 100644 index 000000000..a5c0a43bd --- /dev/null +++ b/tests/namespace_visibility_1.cpp @@ -0,0 +1,24 @@ +#include "pybind11/pybind11.h" +#include "namespace_visibility.inl" + +// clang-format off +namespace pybind11_ns_vis_uuu PYBIND11_NS_VIS_U { PYBIND11_NS_VIS_FUNC } +namespace pybind11_ns_vis_uuh PYBIND11_NS_VIS_U { PYBIND11_NS_VIS_FUNC } +namespace pybind11_ns_vis_uhu PYBIND11_NS_VIS_U { PYBIND11_NS_VIS_FUNC } +namespace pybind11_ns_vis_uhh PYBIND11_NS_VIS_U { PYBIND11_NS_VIS_FUNC } +namespace pybind11_ns_vis_huu PYBIND11_NS_VIS_H { PYBIND11_NS_VIS_FUNC } +namespace pybind11_ns_vis_huh PYBIND11_NS_VIS_H { PYBIND11_NS_VIS_FUNC } +namespace pybind11_ns_vis_hhu PYBIND11_NS_VIS_H { PYBIND11_NS_VIS_FUNC } +namespace pybind11_ns_vis_hhh PYBIND11_NS_VIS_H { PYBIND11_NS_VIS_FUNC } +// ^ ^ +// bit used .............. here +// clang-format on + +void namespace_visibility_1s(pybind11::module_ &m); + +PYBIND11_MODULE(namespace_visibility_1, m) { + PYBIND11_NS_VIS_DEFS + + auto sm = m.def_submodule("submodule"); + namespace_visibility_1s(sm); +} diff --git a/tests/namespace_visibility_1s.cpp b/tests/namespace_visibility_1s.cpp new file mode 100644 index 000000000..810dd169d --- /dev/null +++ b/tests/namespace_visibility_1s.cpp @@ -0,0 +1,17 @@ +#include "pybind11/pybind11.h" +#include "namespace_visibility.inl" + +// clang-format off +namespace pybind11_ns_vis_uuu PYBIND11_NS_VIS_U { PYBIND11_NS_VIS_FUNC } +namespace pybind11_ns_vis_uuh PYBIND11_NS_VIS_U { PYBIND11_NS_VIS_FUNC } +namespace pybind11_ns_vis_uhu PYBIND11_NS_VIS_H { PYBIND11_NS_VIS_FUNC } +namespace pybind11_ns_vis_uhh PYBIND11_NS_VIS_H { PYBIND11_NS_VIS_FUNC } +namespace pybind11_ns_vis_huu PYBIND11_NS_VIS_U { PYBIND11_NS_VIS_FUNC } +namespace pybind11_ns_vis_huh PYBIND11_NS_VIS_U { PYBIND11_NS_VIS_FUNC } +namespace pybind11_ns_vis_hhu PYBIND11_NS_VIS_H { PYBIND11_NS_VIS_FUNC } +namespace pybind11_ns_vis_hhh PYBIND11_NS_VIS_H { PYBIND11_NS_VIS_FUNC } +// ^ ^ +// bit used ............. here +// clang-format on + +void namespace_visibility_1s(pybind11::module_ &m) { PYBIND11_NS_VIS_DEFS } diff --git a/tests/namespace_visibility_2.cpp b/tests/namespace_visibility_2.cpp new file mode 100644 index 000000000..0fb385979 --- /dev/null +++ b/tests/namespace_visibility_2.cpp @@ -0,0 +1,17 @@ +#include "pybind11/pybind11.h" +#include "namespace_visibility.inl" + +// clang-format off +namespace pybind11_ns_vis_uuu PYBIND11_NS_VIS_U { PYBIND11_NS_VIS_FUNC } +namespace pybind11_ns_vis_uuh PYBIND11_NS_VIS_H { PYBIND11_NS_VIS_FUNC } +namespace pybind11_ns_vis_uhu PYBIND11_NS_VIS_U { PYBIND11_NS_VIS_FUNC } +namespace pybind11_ns_vis_uhh PYBIND11_NS_VIS_H { PYBIND11_NS_VIS_FUNC } +namespace pybind11_ns_vis_huu PYBIND11_NS_VIS_U { PYBIND11_NS_VIS_FUNC } +namespace pybind11_ns_vis_huh PYBIND11_NS_VIS_H { PYBIND11_NS_VIS_FUNC } +namespace pybind11_ns_vis_hhu PYBIND11_NS_VIS_U { PYBIND11_NS_VIS_FUNC } +namespace pybind11_ns_vis_hhh PYBIND11_NS_VIS_H { PYBIND11_NS_VIS_FUNC } +// ^ ^ +// bit used ............ here +// clang-format on + +PYBIND11_MODULE(namespace_visibility_2, m) { PYBIND11_NS_VIS_DEFS } diff --git a/tests/test_exc_namespace_visibility.py b/tests/test_exc_namespace_visibility.py new file mode 100644 index 000000000..0f1cab9d5 --- /dev/null +++ b/tests/test_exc_namespace_visibility.py @@ -0,0 +1,67 @@ +# This is not really a unit test, but probing environment/toolchain/platform-specific +# behavior under the exact same conditions as normal tests. +# The results are useful to understanding the effects of, e.g., removing +# `-fvisibility=hidden` or `__attribute__((visibility("hidden")))`, or linking +# extensions statically with the core Python interpreter. + +# NOTE +# ==== +# The "exc_" in "test_exc_namespace_visibility.py" is a workaround, to avoid a +# test_cross_module_exception_translator (test_exceptions.py) failure. This +# test has to be imported (by pytest) before test_exceptions.py; pytest sorts +# lexically. See https://github.com/pybind/pybind11/pull/4054 for more information. + +import itertools + +import namespace_visibility_1 +import namespace_visibility_2 +import pytest + +# Please take a quick look at namespace_visibility.h first, to see what is being probed. +# +# EXPECTED is for -fvisibility=hidden or equivalent, as recommended in the docs. +EXPECTED_ALL_UNIQUE_POINTERS_OBSERVED = "AAC:AAc:AaC:Aac:aAC:aAc:aaC:aac" +# ^^^ +# namespace_visibility_1 pointer||| +# namespace_visibility_1.submodule pointer|| (identical letters means same pointer) +# namespace_visibility_2 pointer| +# Upper-case: namespace visibility unspecified +# Lower-case: namespace visibility hidden +# This test probes all 2**3 combinations of u/h ** number-of-sub/modules. +# +# Also observed: +# AAA:AAc:AaC:Aac:aAC:aAc:aaC:aac -fvisibility=default Linux +# AAA:AAc:AaA:Aac:aAC:aAc:aaC:aac -fvisibility=default macOS +# AAA:AAa:AaA:Aaa:aAA:aAa:aaA:aaa everything linked statically + + +def test_namespace_visibility(): + modules = ( + namespace_visibility_1, + namespace_visibility_1.submodule, + namespace_visibility_2, + ) + unique_pointer_labels = "ABC" + unique_pointers_observed = [] + # u = visibility unspecified + # h = visibility hidden + for visibility in itertools.product(*([("u", "h")] * len(modules))): + # See functions in namespace_visibility_*.cpp + func = "ns_vis_" + "".join(visibility) + "_func" + ptrs = [] + uq_ptrs_obs = "" + for vis, m in zip(visibility, modules): + ptr = getattr(m, func)() + ptrs.append(ptr) + lbl = unique_pointer_labels[ptrs.index(ptr)] + if vis == "h": + # Encode u/h info as upper/lower case to make the final result + # as compact as possible. + lbl = lbl.lower() + uq_ptrs_obs += lbl + unique_pointers_observed.append(uq_ptrs_obs) + all_unique_pointers_observed = ":".join(unique_pointers_observed) + if all_unique_pointers_observed != EXPECTED_ALL_UNIQUE_POINTERS_OBSERVED: + pytest.skip( + f"UNUSUAL all_unique_pointers_observed: {all_unique_pointers_observed}" + )