Merge branch 'master' into sh_merge_master

This commit is contained in:
Ralf W. Grosse-Kunstleve 2022-07-21 06:53:22 -07:00
commit 4d774ec218
24 changed files with 452 additions and 154 deletions

View File

@ -1,68 +1,70 @@
FormatStyle: file FormatStyle: file
Checks: ' Checks: |
*bugprone*, *bugprone*,
clang-analyzer-optin.performance.Padding, *performance*,
clang-analyzer-optin.cplusplus.VirtualCall, clang-analyzer-optin.cplusplus.VirtualCall,
cppcoreguidelines-init-variables, clang-analyzer-optin.performance.Padding,
cppcoreguidelines-prefer-member-initializer, cppcoreguidelines-init-variables,
cppcoreguidelines-pro-type-static-cast-downcast, cppcoreguidelines-prefer-member-initializer,
cppcoreguidelines-slicing, cppcoreguidelines-pro-type-static-cast-downcast,
google-explicit-constructor, cppcoreguidelines-slicing,
llvm-namespace-comment, google-explicit-constructor,
misc-definitions-in-headers, llvm-namespace-comment,
misc-misplaced-const, misc-definitions-in-headers,
misc-non-copyable-objects, misc-misplaced-const,
misc-static-assert, misc-non-copyable-objects,
misc-throw-by-value-catch-by-reference, misc-static-assert,
misc-uniqueptr-reset-release, misc-throw-by-value-catch-by-reference,
misc-unused-parameters, misc-uniqueptr-reset-release,
modernize-avoid-bind, misc-unused-parameters,
modernize-loop-convert, modernize-avoid-bind,
modernize-make-shared, modernize-loop-convert,
modernize-redundant-void-arg, modernize-make-shared,
modernize-replace-auto-ptr, modernize-redundant-void-arg,
modernize-replace-disallow-copy-and-assign-macro, modernize-replace-auto-ptr,
modernize-replace-random-shuffle, modernize-replace-disallow-copy-and-assign-macro,
modernize-shrink-to-fit, modernize-replace-random-shuffle,
modernize-use-auto, modernize-shrink-to-fit,
modernize-use-bool-literals, modernize-use-auto,
modernize-use-default-member-init, modernize-use-bool-literals,
modernize-use-equals-default, modernize-use-default-member-init,
modernize-use-equals-delete, modernize-use-emplace,
modernize-use-emplace, modernize-use-equals-default,
modernize-use-noexcept, modernize-use-equals-delete,
modernize-use-nullptr, modernize-use-noexcept,
modernize-use-override, modernize-use-nullptr,
modernize-use-using, modernize-use-override,
*performance*, modernize-use-using,
readability-avoid-const-params-in-decls, readability-avoid-const-params-in-decls,
readability-braces-around-statements, readability-braces-around-statements,
readability-const-return-type, readability-const-return-type,
readability-container-size-empty, readability-container-size-empty,
readability-delete-null-pointer, readability-delete-null-pointer,
readability-else-after-return, readability-else-after-return,
readability-implicit-bool-conversion, readability-implicit-bool-conversion,
readability-inconsistent-declaration-parameter-name, readability-inconsistent-declaration-parameter-name,
readability-make-member-function-const, readability-make-member-function-const,
readability-misplaced-array-index, readability-misplaced-array-index,
readability-non-const-parameter, readability-non-const-parameter,
readability-qualified-auto, readability-qualified-auto,
readability-redundant-function-ptr-dereference, readability-redundant-function-ptr-dereference,
readability-redundant-smartptr-get, readability-redundant-smartptr-get,
readability-redundant-string-cstr, readability-redundant-string-cstr,
readability-simplify-subscript-expr, readability-simplify-subscript-expr,
readability-static-accessed-through-instance, readability-static-accessed-through-instance,
readability-static-definition-in-anonymous-namespace, readability-static-definition-in-anonymous-namespace,
readability-string-compare, readability-string-compare,
readability-suspicious-call-argument, readability-suspicious-call-argument,
readability-uniqueptr-delete-release, readability-uniqueptr-delete-release,
-bugprone-exception-escape, -bugprone-easily-swappable-parameters,
-bugprone-reserved-identifier, -bugprone-exception-escape,
-bugprone-unused-raii, -bugprone-reserved-identifier,
' -bugprone-unused-raii,
CheckOptions: CheckOptions:
- key: modernize-use-equals-default.IgnoreMacros
value: false
- key: performance-for-range-copy.WarnOnAllAutoCopies - key: performance-for-range-copy.WarnOnAllAutoCopies
value: true value: true
- key: performance-inefficient-string-concatenation.StrictMode - key: performance-inefficient-string-concatenation.StrictMode
@ -73,5 +75,3 @@ CheckOptions:
value: true value: true
HeaderFilterRegex: 'pybind11/.*h' HeaderFilterRegex: 'pybind11/.*h'
WarningsAsErrors: '*'

View File

@ -235,12 +235,14 @@ directory inside your pybind11 git clone. Files will be modified in place,
so you can use git to monitor the changes. so you can use git to monitor the changes.
```bash ```bash
docker run --rm -v $PWD:/mounted_pybind11 -it silkeh/clang:12 docker run --rm -v $PWD:/mounted_pybind11 -it silkeh/clang:13
apt-get update && apt-get install -y python3-dev python3-pytest apt-get update && apt-get install -y python3-dev python3-pytest
cmake -S /mounted_pybind11/ -B build -DCMAKE_CXX_CLANG_TIDY="$(which clang-tidy);-fix" -DDOWNLOAD_EIGEN=ON -DDOWNLOAD_CATCH=ON -DCMAKE_CXX_STANDARD=17 cmake -S /mounted_pybind11/ -B build -DCMAKE_CXX_CLANG_TIDY="$(which clang-tidy);--use-color" -DDOWNLOAD_EIGEN=ON -DDOWNLOAD_CATCH=ON -DCMAKE_CXX_STANDARD=17
cmake --build build -j 2 -- --keep-going cmake --build build -j 2
``` ```
You can add `--fix` to the options list if you want.
### Include what you use ### Include what you use
To run include what you use, install (`brew install include-what-you-use` on To run include what you use, install (`brew install include-what-you-use` on

View File

@ -282,6 +282,14 @@ jobs:
std: 20 std: 20
- clang: 10 - clang: 10
std: 17 std: 17
- clang: 11
std: 20
- clang: 12
std: 20
- clang: 13
std: 20
- clang: 14
std: 20
name: "🐍 3 • Clang ${{ matrix.clang }} • C++${{ matrix.std }} • x64" name: "🐍 3 • Clang ${{ matrix.clang }} • C++${{ matrix.std }} • x64"
container: "silkeh/clang:${{ matrix.clang }}" container: "silkeh/clang:${{ matrix.clang }}"
@ -436,14 +444,14 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
gcc:
- 7
- latest
std:
- 11
include: include:
- gcc: 10 - { gcc: 7, std: 11 }
std: 20 - { gcc: 7, std: 17 }
- { gcc: 8, std: 14 }
- { gcc: 8, std: 17 }
- { gcc: 10, std: 17 }
- { gcc: 11, std: 20 }
- { gcc: 12, std: 20 }
name: "🐍 3 • GCC ${{ matrix.gcc }} • C++${{ matrix.std }}• x64" name: "🐍 3 • GCC ${{ matrix.gcc }} • C++${{ matrix.std }}• x64"
container: "gcc:${{ matrix.gcc }}" container: "gcc:${{ matrix.gcc }}"

View File

@ -37,7 +37,7 @@ jobs:
# in .github/CONTRIBUTING.md and update as needed. # in .github/CONTRIBUTING.md and update as needed.
name: Clang-Tidy name: Clang-Tidy
runs-on: ubuntu-latest runs-on: ubuntu-latest
container: silkeh/clang:12 container: silkeh/clang:13
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
@ -47,7 +47,7 @@ jobs:
- name: Configure - name: Configure
run: > run: >
cmake -S . -B build cmake -S . -B build
-DCMAKE_CXX_CLANG_TIDY="$(which clang-tidy)" -DCMAKE_CXX_CLANG_TIDY="$(which clang-tidy);--use-color;--warnings-as-errors=*"
-DDOWNLOAD_EIGEN=ON -DDOWNLOAD_EIGEN=ON
-DDOWNLOAD_CATCH=ON -DDOWNLOAD_CATCH=ON
-DCMAKE_CXX_STANDARD=17 -DCMAKE_CXX_STANDARD=17

View File

@ -73,7 +73,7 @@ repos:
# Autoremoves unused imports # Autoremoves unused imports
- repo: https://github.com/hadialqattan/pycln - repo: https://github.com/hadialqattan/pycln
rev: "v2.0.1" rev: "v2.0.4"
hooks: hooks:
- id: pycln - id: pycln
stages: [manual] stages: [manual]
@ -110,7 +110,7 @@ repos:
# PyLint has native support - not always usable, but works for us # PyLint has native support - not always usable, but works for us
- repo: https://github.com/PyCQA/pylint - repo: https://github.com/PyCQA/pylint
rev: "v2.14.4" rev: "v2.14.5"
hooks: hooks:
- id: pylint - id: pylint
files: ^pybind11 files: ^pybind11

3
docs/_static/css/custom.css vendored Normal file
View File

@ -0,0 +1,3 @@
.highlight .go {
color: #707070;
}

View File

@ -1,11 +0,0 @@
.wy-table-responsive table td,
.wy-table-responsive table th {
white-space: initial !important;
}
.rst-content table.docutils td {
vertical-align: top !important;
}
div[class^='highlight'] pre {
white-space: pre;
white-space: pre-wrap;
}

View File

@ -9,14 +9,20 @@ Starting with version 1.8.0, pybind11 releases use a `semantic versioning
Changes will be added here periodically from the "Suggested changelog entry" Changes will be added here periodically from the "Suggested changelog entry"
block in pull request descriptions. block in pull request descriptions.
IN DEVELOPMENT IN DEVELOPMENT
-------------- --------------
Changes will be summarized here periodically.
Version 2.10.0 (Jul 15, 2022)
-----------------------------
Removed support for Python 2.7, Python 3.5, and MSVC 2015. Support for MSVC Removed support for Python 2.7, Python 3.5, and MSVC 2015. Support for MSVC
2017 is limited due to availability of CI runners; we highly recommend MSVC 2017 is limited due to availability of CI runners; we highly recommend MSVC
2019 or 2022 be used. Initial support added for Python 3.11. 2019 or 2022 be used. Initial support added for Python 3.11.
New features: New features:
* ``py::anyset`` & ``py::frozenset`` were added, with copying (cast) to * ``py::anyset`` & ``py::frozenset`` were added, with copying (cast) to
@ -70,6 +76,9 @@ Changes:
requiring ``NDEBUG``, allowing use with release builds if desired. requiring ``NDEBUG``, allowing use with release builds if desired.
`#3913 <https://github.com/pybind/pybind11/pull/3913>`_ `#3913 <https://github.com/pybind/pybind11/pull/3913>`_
* Implicit conversion of the literal ``0`` to ``pybind11::handle`` is now disabled.
`#4008 <https://github.com/pybind/pybind11/pull/4008>`_
Bug fixes: Bug fixes:
@ -98,6 +107,14 @@ Bug fixes:
* Fix cast from pytype rvalue to another pytype. * Fix cast from pytype rvalue to another pytype.
`#3949 <https://github.com/pybind/pybind11/pull/3949>`_ `#3949 <https://github.com/pybind/pybind11/pull/3949>`_
* Ensure proper behavior when garbage collecting classes with dynamic attributes in Python >=3.9.
`#4051 <https://github.com/pybind/pybind11/pull/4051>`_
* A couple long-standing ``PYBIND11_NAMESPACE``
``__attribute__((visibility("hidden")))`` inconsistencies are now fixed
(affects only unusual environments).
`#4043 <https://github.com/pybind/pybind11/pull/4043>`_
* ``pybind11::detail::get_internals()`` is now resilient to in-flight Python * ``pybind11::detail::get_internals()`` is now resilient to in-flight Python
exceptions. exceptions.
`#3981 <https://github.com/pybind/pybind11/pull/3981>`_ `#3981 <https://github.com/pybind/pybind11/pull/3981>`_
@ -147,6 +164,9 @@ Performance and style:
* Optimize c++ to python function casting by using the rvalue caster. * Optimize c++ to python function casting by using the rvalue caster.
`#3966 <https://github.com/pybind/pybind11/pull/3966>`_ `#3966 <https://github.com/pybind/pybind11/pull/3966>`_
* Optimize Eigen sparse matrix casting by removing unnecessary temporary.
`#4064 <https://github.com/pybind/pybind11/pull/4064>`_
* Avoid potential implicit copy/assignment constructors causing double free in * Avoid potential implicit copy/assignment constructors causing double free in
``strdup_gaurd``. ``strdup_gaurd``.
`#3905 <https://github.com/pybind/pybind11/pull/3905>`_ `#3905 <https://github.com/pybind/pybind11/pull/3905>`_
@ -182,6 +202,9 @@ Build system improvements:
Backend and tidying up: Backend and tidying up:
* New theme for the documentation.
`#3109 <https://github.com/pybind/pybind11/pull/3109>`_
* Remove idioms in code comments. Use more inclusive language. * Remove idioms in code comments. Use more inclusive language.
`#3809 <https://github.com/pybind/pybind11/pull/3809>`_ `#3809 <https://github.com/pybind/pybind11/pull/3809>`_

View File

@ -35,6 +35,7 @@ DIR = Path(__file__).parent.resolve()
# ones. # ones.
extensions = [ extensions = [
"breathe", "breathe",
"sphinx_copybutton",
"sphinxcontrib.rsvgconverter", "sphinxcontrib.rsvgconverter",
"sphinxcontrib.moderncmakedomain", "sphinxcontrib.moderncmakedomain",
] ]
@ -125,23 +126,7 @@ todo_include_todos = False
# The theme to use for HTML and HTML Help pages. See the documentation for # The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes. # a list of builtin themes.
on_rtd = os.environ.get("READTHEDOCS", None) == "True" html_theme = "furo"
if not on_rtd: # only import and set the theme if we're building docs locally
import sphinx_rtd_theme
html_theme = "sphinx_rtd_theme"
html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
html_context = {"css_files": ["_static/theme_overrides.css"]}
else:
html_context = {
"css_files": [
"//media.readthedocs.org/css/sphinx_rtd_theme.css",
"//media.readthedocs.org/css/readthedocs-doc-embed.css",
"_static/theme_overrides.css",
]
}
# Theme options are theme-specific and customize the look and feel of a theme # Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the # further. For a list of options available for each theme, see the
@ -172,6 +157,10 @@ else:
# so a file named "default.css" will overwrite the builtin "default.css". # so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ["_static"] html_static_path = ["_static"]
html_css_files = [
"css/custom.css",
]
# Add any extra paths that contain custom files (such as robots.txt or # Add any extra paths that contain custom files (such as robots.txt or
# .htaccess) here, relative to this directory. These files are copied # .htaccess) here, relative to this directory. These files are copied
# directly to the root of the documentation. # directly to the root of the documentation.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 57 KiB

After

Width:  |  Height:  |  Size: 60 KiB

View File

@ -1,5 +1,6 @@
breathe==4.32.0 breathe==4.34.0
sphinx==4.4.0 furo==2022.6.21
sphinx_rtd_theme==1.0.0 sphinx==5.0.2
sphinx-copybutton==0.5.0
sphinxcontrib-moderncmakedomain==3.21.4 sphinxcontrib-moderncmakedomain==3.21.4
sphinxcontrib-svg2pdfconverter==1.2.0 sphinxcontrib-svg2pdfconverter==1.2.0

View File

@ -10,12 +10,12 @@
#pragma once #pragma once
#define PYBIND11_VERSION_MAJOR 2 #define PYBIND11_VERSION_MAJOR 2
#define PYBIND11_VERSION_MINOR 10 #define PYBIND11_VERSION_MINOR 11
#define PYBIND11_VERSION_PATCH 0.dev1 #define PYBIND11_VERSION_PATCH 0.dev1
// Similar to Python's convention: https://docs.python.org/3/c-api/apiabiversion.html // Similar to Python's convention: https://docs.python.org/3/c-api/apiabiversion.html
// Additional convention: 0xD = dev // Additional convention: 0xD = dev
#define PYBIND11_VERSION_HEX 0x020A00D1 #define PYBIND11_VERSION_HEX 0x020B00D1
#define PYBIND11_NAMESPACE_BEGIN(name) namespace name { #define PYBIND11_NAMESPACE_BEGIN(name) namespace name {
#define PYBIND11_NAMESPACE_END(name) } #define PYBIND11_NAMESPACE_END(name) }
@ -1170,6 +1170,24 @@ constexpr inline bool silence_msvc_c4127(bool cond) { return cond; }
# define PYBIND11_SILENCE_MSVC_C4127(...) __VA_ARGS__ # define PYBIND11_SILENCE_MSVC_C4127(...) __VA_ARGS__
#endif #endif
#if defined(__clang__) \
&& (defined(__apple_build_version__) /* AppleClang 13.0.0.13000029 was the only data point \
available. */ \
|| (__clang_major__ >= 7 \
&& __clang_major__ <= 12) /* Clang 3, 5, 13, 14, 15 do not generate the warning. */ \
)
# define PYBIND11_DETECTED_CLANG_WITH_MISLEADING_CALL_STD_MOVE_EXPLICITLY_WARNING
// Example:
// tests/test_kwargs_and_defaults.cpp:46:68: error: local variable 'args' will be copied despite
// being returned by name [-Werror,-Wreturn-std-move]
// m.def("args_function", [](py::args args) -> py::tuple { return args; });
// ^~~~
// test_kwargs_and_defaults.cpp:46:68: note: call 'std::move' explicitly to avoid copying
// m.def("args_function", [](py::args args) -> py::tuple { return args; });
// ^~~~
// std::move(args)
#endif
// Pybind offers detailed error messages by default for all builts that are debug (through the // Pybind offers detailed error messages by default for all builts that are debug (through the
// negation of ndebug). This can also be manually enabled by users, for any builds, through // negation of ndebug). This can also be manually enabled by users, for any builds, through
// defining PYBIND11_DETAILED_ERROR_MESSAGES. // defining PYBIND11_DETAILED_ERROR_MESSAGES.

View File

@ -695,9 +695,9 @@ struct type_caster<Type, enable_if_t<is_eigen_sparse<Type>::value>> {
array outerIndices((rowMajor ? src.rows() : src.cols()) + 1, src.outerIndexPtr()); array outerIndices((rowMajor ? src.rows() : src.cols()) + 1, src.outerIndexPtr());
array innerIndices(src.nonZeros(), src.innerIndexPtr()); array innerIndices(src.nonZeros(), src.innerIndexPtr());
return matrix_type(std::make_tuple( return matrix_type(pybind11::make_tuple(
std::move(data), std::move(innerIndices), std::move(outerIndices)), std::move(data), std::move(innerIndices), std::move(outerIndices)),
std::make_pair(src.rows(), src.cols())) pybind11::make_tuple(src.rows(), src.cols()))
.release(); .release();
} }

View File

@ -537,7 +537,7 @@ PYBIND11_NAMESPACE_END(detail)
class dtype : public object { class dtype : public object {
public: public:
PYBIND11_OBJECT_DEFAULT(dtype, object, detail::npy_api::get().PyArrayDescr_Check_); PYBIND11_OBJECT_DEFAULT(dtype, object, detail::npy_api::get().PyArrayDescr_Check_)
explicit dtype(const buffer_info &info) { explicit dtype(const buffer_info &info) {
dtype descr(_dtype_from_pep3118()(pybind11::str(info.format))); dtype descr(_dtype_from_pep3118()(pybind11::str(info.format)));
@ -1865,9 +1865,13 @@ private:
} }
auto result = returned_array::create(trivial, shape); auto result = returned_array::create(trivial, shape);
#ifdef PYBIND11_DETECTED_CLANG_WITH_MISLEADING_CALL_STD_MOVE_EXPLICITLY_WARNING
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wreturn-std-move"
#endif
if (size == 0) { if (size == 0) {
return std::move(result); return result;
} }
/* Call the function */ /* Call the function */
@ -1878,7 +1882,10 @@ private:
apply_trivial(buffers, params, mutable_data, size, i_seq, vi_seq, bi_seq); apply_trivial(buffers, params, mutable_data, size, i_seq, vi_seq, bi_seq);
} }
return std::move(result); return result;
#ifdef PYBIND11_DETECTED_CLANG_WITH_MISLEADING_CALL_STD_MOVE_EXPLICITLY_WARNING
# pragma clang diagnostic pop
#endif
} }
template <size_t... Index, size_t... VIndex, size_t... BIndex> template <size_t... Index, size_t... VIndex, size_t... BIndex>

View File

@ -155,23 +155,23 @@ public:
object operator-() const; object operator-() const;
object operator~() const; object operator~() const;
object operator+(object_api const &other) const; object operator+(object_api const &other) const;
object operator+=(object_api const &other) const; object operator+=(object_api const &other);
object operator-(object_api const &other) const; object operator-(object_api const &other) const;
object operator-=(object_api const &other) const; object operator-=(object_api const &other);
object operator*(object_api const &other) const; object operator*(object_api const &other) const;
object operator*=(object_api const &other) const; object operator*=(object_api const &other);
object operator/(object_api const &other) const; object operator/(object_api const &other) const;
object operator/=(object_api const &other) const; object operator/=(object_api const &other);
object operator|(object_api const &other) const; object operator|(object_api const &other) const;
object operator|=(object_api const &other) const; object operator|=(object_api const &other);
object operator&(object_api const &other) const; object operator&(object_api const &other) const;
object operator&=(object_api const &other) const; object operator&=(object_api const &other);
object operator^(object_api const &other) const; object operator^(object_api const &other) const;
object operator^=(object_api const &other) const; object operator^=(object_api const &other);
object operator<<(object_api const &other) const; object operator<<(object_api const &other) const;
object operator<<=(object_api const &other) const; object operator<<=(object_api const &other);
object operator>>(object_api const &other) const; object operator>>(object_api const &other) const;
object operator>>=(object_api const &other) const; object operator>>=(object_api const &other);
PYBIND11_DEPRECATED("Use py::str(obj) instead") PYBIND11_DEPRECATED("Use py::str(obj) instead")
pybind11::str str() const; pybind11::str str() const;
@ -190,6 +190,11 @@ private:
bool rich_compare(object_api const &other, int value) const; bool rich_compare(object_api const &other, int value) const;
}; };
template <typename T>
using is_pyobj_ptr_or_nullptr_t = detail::any_of<std::is_same<T, PyObject *>,
std::is_same<T, PyObject *const>,
std::is_same<T, std::nullptr_t>>;
PYBIND11_NAMESPACE_END(detail) PYBIND11_NAMESPACE_END(detail)
#if !defined(PYBIND11_HANDLE_REF_DEBUG) && !defined(NDEBUG) #if !defined(PYBIND11_HANDLE_REF_DEBUG) && !defined(NDEBUG)
@ -211,9 +216,23 @@ class handle : public detail::object_api<handle> {
public: public:
/// The default constructor creates a handle with a ``nullptr``-valued pointer /// The default constructor creates a handle with a ``nullptr``-valued pointer
handle() = default; handle() = default;
/// Creates a ``handle`` from the given raw Python object pointer
/// Enable implicit conversion from ``PyObject *`` and ``nullptr``.
/// Not using ``handle(PyObject *ptr)`` to avoid implicit conversion from ``0``.
template <typename T,
detail::enable_if_t<detail::is_pyobj_ptr_or_nullptr_t<T>::value, int> = 0>
// NOLINTNEXTLINE(google-explicit-constructor) // NOLINTNEXTLINE(google-explicit-constructor)
handle(PyObject *ptr) : m_ptr(ptr) {} // Allow implicit conversion from PyObject* handle(T ptr) : m_ptr(ptr) {}
/// Enable implicit conversion through ``T::operator PyObject *()``.
template <
typename T,
detail::enable_if_t<detail::all_of<detail::none_of<std::is_base_of<handle, T>,
detail::is_pyobj_ptr_or_nullptr_t<T>>,
std::is_convertible<T, PyObject *>>::value,
int> = 0>
// NOLINTNEXTLINE(google-explicit-constructor)
handle(T &obj) : m_ptr(obj) {}
/// Return the underlying ``PyObject *`` pointer /// Return the underlying ``PyObject *`` pointer
PyObject *ptr() const { return m_ptr; } PyObject *ptr() const { return m_ptr; }
@ -315,12 +334,15 @@ public:
} }
object &operator=(const object &other) { object &operator=(const object &other) {
other.inc_ref(); // Skip inc_ref and dec_ref if both objects are the same
// Use temporary variable to ensure `*this` remains valid while if (!this->is(other)) {
// `Py_XDECREF` executes, in case `*this` is accessible from Python. other.inc_ref();
handle temp(m_ptr); // Use temporary variable to ensure `*this` remains valid while
m_ptr = other.m_ptr; // `Py_XDECREF` executes, in case `*this` is accessible from Python.
temp.dec_ref(); handle temp(m_ptr);
m_ptr = other.m_ptr;
temp.dec_ref();
}
return *this; return *this;
} }
@ -334,6 +356,20 @@ public:
return *this; return *this;
} }
#define PYBIND11_INPLACE_OP(iop) \
object iop(object_api const &other) { return operator=(handle::iop(other)); }
PYBIND11_INPLACE_OP(operator+=)
PYBIND11_INPLACE_OP(operator-=)
PYBIND11_INPLACE_OP(operator*=)
PYBIND11_INPLACE_OP(operator/=)
PYBIND11_INPLACE_OP(operator|=)
PYBIND11_INPLACE_OP(operator&=)
PYBIND11_INPLACE_OP(operator^=)
PYBIND11_INPLACE_OP(operator<<=)
PYBIND11_INPLACE_OP(operator>>=)
#undef PYBIND11_INPLACE_OP
// Calling cast() on an object lvalue just copies (via handle::cast) // Calling cast() on an object lvalue just copies (via handle::cast)
template <typename T> template <typename T>
T cast() const &; T cast() const &;
@ -437,6 +473,12 @@ struct error_fetch_and_normalize {
+ " failed to obtain the name " + " failed to obtain the name "
"of the normalized active exception type."); "of the normalized active exception type.");
} }
#if defined(PYPY_VERSION)
// This behavior runs the risk of masking errors in the error handling, but avoids a
// conflict with PyPy, which relies on the normalization here to change OSError to
// FileNotFoundError (https://github.com/pybind/pybind11/issues/4075).
m_lazy_error_string = exc_type_name_norm;
#else
if (exc_type_name_norm != m_lazy_error_string) { if (exc_type_name_norm != m_lazy_error_string) {
std::string msg = std::string(called) std::string msg = std::string(called)
+ ": MISMATCH of original and normalized " + ": MISMATCH of original and normalized "
@ -448,6 +490,7 @@ struct error_fetch_and_normalize {
msg += ": " + format_value_and_trace(); msg += ": " + format_value_and_trace();
pybind11_fail(msg); pybind11_fail(msg);
} }
#endif
} }
error_fetch_and_normalize(const error_fetch_and_normalize &) = delete; error_fetch_and_normalize(const error_fetch_and_normalize &) = delete;
@ -1247,7 +1290,7 @@ public:
#define PYBIND11_OBJECT_CVT_DEFAULT(Name, Parent, CheckFun, ConvertFun) \ #define PYBIND11_OBJECT_CVT_DEFAULT(Name, Parent, CheckFun, ConvertFun) \
PYBIND11_OBJECT_CVT(Name, Parent, CheckFun, ConvertFun) \ PYBIND11_OBJECT_CVT(Name, Parent, CheckFun, ConvertFun) \
Name() : Parent() {} Name() = default;
#define PYBIND11_OBJECT_CHECK_FAILED(Name, o_ptr) \ #define PYBIND11_OBJECT_CHECK_FAILED(Name, o_ptr) \
::pybind11::type_error("Object of type '" \ ::pybind11::type_error("Object of type '" \
@ -1270,7 +1313,7 @@ public:
#define PYBIND11_OBJECT_DEFAULT(Name, Parent, CheckFun) \ #define PYBIND11_OBJECT_DEFAULT(Name, Parent, CheckFun) \
PYBIND11_OBJECT(Name, Parent, CheckFun) \ PYBIND11_OBJECT(Name, Parent, CheckFun) \
Name() : Parent() {} Name() = default;
/// \addtogroup pytypes /// \addtogroup pytypes
/// @{ /// @{
@ -2345,26 +2388,35 @@ bool object_api<D>::rich_compare(object_api const &other, int value) const {
return result; \ return result; \
} }
#define PYBIND11_MATH_OPERATOR_BINARY_INPLACE(iop, fn) \
template <typename D> \
object object_api<D>::iop(object_api const &other) { \
object result = reinterpret_steal<object>(fn(derived().ptr(), other.derived().ptr())); \
if (!result.ptr()) \
throw error_already_set(); \
return result; \
}
PYBIND11_MATH_OPERATOR_UNARY(operator~, PyNumber_Invert) PYBIND11_MATH_OPERATOR_UNARY(operator~, PyNumber_Invert)
PYBIND11_MATH_OPERATOR_UNARY(operator-, PyNumber_Negative) PYBIND11_MATH_OPERATOR_UNARY(operator-, PyNumber_Negative)
PYBIND11_MATH_OPERATOR_BINARY(operator+, PyNumber_Add) PYBIND11_MATH_OPERATOR_BINARY(operator+, PyNumber_Add)
PYBIND11_MATH_OPERATOR_BINARY(operator+=, PyNumber_InPlaceAdd) PYBIND11_MATH_OPERATOR_BINARY_INPLACE(operator+=, PyNumber_InPlaceAdd)
PYBIND11_MATH_OPERATOR_BINARY(operator-, PyNumber_Subtract) PYBIND11_MATH_OPERATOR_BINARY(operator-, PyNumber_Subtract)
PYBIND11_MATH_OPERATOR_BINARY(operator-=, PyNumber_InPlaceSubtract) PYBIND11_MATH_OPERATOR_BINARY_INPLACE(operator-=, PyNumber_InPlaceSubtract)
PYBIND11_MATH_OPERATOR_BINARY(operator*, PyNumber_Multiply) PYBIND11_MATH_OPERATOR_BINARY(operator*, PyNumber_Multiply)
PYBIND11_MATH_OPERATOR_BINARY(operator*=, PyNumber_InPlaceMultiply) PYBIND11_MATH_OPERATOR_BINARY_INPLACE(operator*=, PyNumber_InPlaceMultiply)
PYBIND11_MATH_OPERATOR_BINARY(operator/, PyNumber_TrueDivide) PYBIND11_MATH_OPERATOR_BINARY(operator/, PyNumber_TrueDivide)
PYBIND11_MATH_OPERATOR_BINARY(operator/=, PyNumber_InPlaceTrueDivide) PYBIND11_MATH_OPERATOR_BINARY_INPLACE(operator/=, PyNumber_InPlaceTrueDivide)
PYBIND11_MATH_OPERATOR_BINARY(operator|, PyNumber_Or) PYBIND11_MATH_OPERATOR_BINARY(operator|, PyNumber_Or)
PYBIND11_MATH_OPERATOR_BINARY(operator|=, PyNumber_InPlaceOr) PYBIND11_MATH_OPERATOR_BINARY_INPLACE(operator|=, PyNumber_InPlaceOr)
PYBIND11_MATH_OPERATOR_BINARY(operator&, PyNumber_And) PYBIND11_MATH_OPERATOR_BINARY(operator&, PyNumber_And)
PYBIND11_MATH_OPERATOR_BINARY(operator&=, PyNumber_InPlaceAnd) PYBIND11_MATH_OPERATOR_BINARY_INPLACE(operator&=, PyNumber_InPlaceAnd)
PYBIND11_MATH_OPERATOR_BINARY(operator^, PyNumber_Xor) PYBIND11_MATH_OPERATOR_BINARY(operator^, PyNumber_Xor)
PYBIND11_MATH_OPERATOR_BINARY(operator^=, PyNumber_InPlaceXor) PYBIND11_MATH_OPERATOR_BINARY_INPLACE(operator^=, PyNumber_InPlaceXor)
PYBIND11_MATH_OPERATOR_BINARY(operator<<, PyNumber_Lshift) PYBIND11_MATH_OPERATOR_BINARY(operator<<, PyNumber_Lshift)
PYBIND11_MATH_OPERATOR_BINARY(operator<<=, PyNumber_InPlaceLshift) PYBIND11_MATH_OPERATOR_BINARY_INPLACE(operator<<=, PyNumber_InPlaceLshift)
PYBIND11_MATH_OPERATOR_BINARY(operator>>, PyNumber_Rshift) PYBIND11_MATH_OPERATOR_BINARY(operator>>, PyNumber_Rshift)
PYBIND11_MATH_OPERATOR_BINARY(operator>>=, PyNumber_InPlaceRshift) PYBIND11_MATH_OPERATOR_BINARY_INPLACE(operator>>=, PyNumber_InPlaceRshift)
#undef PYBIND11_MATH_OPERATOR_UNARY #undef PYBIND11_MATH_OPERATOR_UNARY
#undef PYBIND11_MATH_OPERATOR_BINARY #undef PYBIND11_MATH_OPERATOR_BINARY

View File

@ -5,7 +5,17 @@ import nox
nox.needs_version = ">=2022.1.7" nox.needs_version = ">=2022.1.7"
nox.options.sessions = ["lint", "tests", "tests_packaging"] nox.options.sessions = ["lint", "tests", "tests_packaging"]
PYTHON_VERISONS = ["3.6", "3.7", "3.8", "3.9", "3.10", "3.11", "pypy3.7", "pypy3.8"] PYTHON_VERSIONS = [
"3.6",
"3.7",
"3.8",
"3.9",
"3.10",
"3.11",
"pypy3.7",
"pypy3.8",
"pypy3.9",
]
if os.environ.get("CI", None): if os.environ.get("CI", None):
nox.options.error_on_missing_interpreters = True nox.options.error_on_missing_interpreters = True
@ -20,7 +30,7 @@ def lint(session: nox.Session) -> None:
session.run("pre-commit", "run", "-a") session.run("pre-commit", "run", "-a")
@nox.session(python=PYTHON_VERISONS) @nox.session(python=PYTHON_VERSIONS)
def tests(session: nox.Session) -> None: def tests(session: nox.Session) -> None:
""" """
Run the tests (requires a compiler). Run the tests (requires a compiler).
@ -61,10 +71,10 @@ def docs(session: nox.Session) -> None:
session.chdir("docs") session.chdir("docs")
if "pdf" in session.posargs: if "pdf" in session.posargs:
session.run("sphinx-build", "-b", "latexpdf", ".", "_build") session.run("sphinx-build", "-M", "latexpdf", ".", "_build")
return return
session.run("sphinx-build", "-b", "html", ".", "_build") session.run("sphinx-build", "-M", "html", ".", "_build")
if "serve" in session.posargs: if "serve" in session.posargs:
session.log("Launching docs at http://localhost:8000/ - use Ctrl-C to quit") session.log("Launching docs at http://localhost:8000/ - use Ctrl-C to quit")

View File

@ -8,5 +8,5 @@ def _to_int(s: str) -> Union[int, str]:
return s return s
__version__ = "2.10.0.dev1" __version__ = "2.11.0.dev1"
version_info = tuple(_to_int(s) for s in __version__.split(".")) version_info = tuple(_to_int(s) for s in __version__.split("."))

View File

@ -7,7 +7,7 @@ if("${PYTHON_MODULE_EXTENSION}" MATCHES "pypy" OR "${Python_INTERPRETER_ID}" STR
return() return()
endif() endif()
find_package(Catch 2.13.5) find_package(Catch 2.13.9)
if(CATCH_FOUND) if(CATCH_FOUND)
message(STATUS "Building interpreter tests using Catch v${CATCH_VERSION}") message(STATUS "Building interpreter tests using Catch v${CATCH_VERSION}")

View File

@ -334,4 +334,14 @@ TEST_SUBMODULE(exceptions, m) {
e.restore(); e.restore();
} }
}); });
// https://github.com/pybind/pybind11/issues/4075
m.def("test_pypy_oserror_normalization", []() {
try {
py::module_::import("io").attr("open")("this_filename_must_not_exist", "r");
} catch (const py::error_already_set &e) {
return py::str(e.what()); // str must be built before e goes out of scope.
}
return py::str("UNEXPECTED");
});
} }

View File

@ -360,3 +360,9 @@ def test_error_already_set_double_restore():
"Internal error: pybind11::detail::error_fetch_and_normalize::restore()" "Internal error: pybind11::detail::error_fetch_and_normalize::restore()"
" called a second time. ORIGINAL ERROR: ValueError: Random error." " called a second time. ORIGINAL ERROR: ValueError: Random error."
) )
def test_pypy_oserror_normalization():
# https://github.com/pybind/pybind11/issues/4075
what = m.test_pypy_oserror_normalization()
assert "this_filename_must_not_exist" in what

View File

@ -43,7 +43,16 @@ TEST_SUBMODULE(kwargs_and_defaults, m) {
m.def("kw_func_udl_z", kw_func, "x"_a, "y"_a = 0); m.def("kw_func_udl_z", kw_func, "x"_a, "y"_a = 0);
// test_args_and_kwargs // test_args_and_kwargs
m.def("args_function", [](py::args args) -> py::tuple { return std::move(args); }); m.def("args_function", [](py::args args) -> py::tuple {
#ifdef PYBIND11_DETECTED_CLANG_WITH_MISLEADING_CALL_STD_MOVE_EXPLICITLY_WARNING
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wreturn-std-move"
#endif
return args;
#ifdef PYBIND11_DETECTED_CLANG_WITH_MISLEADING_CALL_STD_MOVE_EXPLICITLY_WARNING
# pragma clang diagnostic pop
#endif
});
m.def("args_kwargs_function", [](const py::args &args, const py::kwargs &kwargs) { m.def("args_kwargs_function", [](const py::args &args, const py::kwargs &kwargs) {
return py::make_tuple(args, kwargs); return py::make_tuple(args, kwargs);
}); });

View File

@ -39,7 +39,68 @@ class float_ : public py::object {
}; };
} // namespace external } // namespace external
namespace implicit_conversion_from_0_to_handle {
// Uncomment to trigger compiler error. Note: Before PR #4008 this used to compile successfully.
// void expected_to_trigger_compiler_error() { py::handle(0); }
} // namespace implicit_conversion_from_0_to_handle
// Used to validate systematically that PR #4008 does/did NOT change the behavior.
void pure_compile_tests_for_handle_from_PyObject_pointers() {
{
PyObject *ptr = Py_None;
py::handle{ptr};
}
{
PyObject *const ptr = Py_None;
py::handle{ptr};
}
// Uncomment to trigger compiler errors.
// PyObject const * ptr = Py_None; py::handle{ptr};
// PyObject const *const ptr = Py_None; py::handle{ptr};
// PyObject volatile * ptr = Py_None; py::handle{ptr};
// PyObject volatile *const ptr = Py_None; py::handle{ptr};
// PyObject const volatile * ptr = Py_None; py::handle{ptr};
// PyObject const volatile *const ptr = Py_None; py::handle{ptr};
}
namespace handle_from_move_only_type_with_operator_PyObject {
// Reduced from
// https://github.com/pytorch/pytorch/blob/279634f384662b7c3a9f8bf7ccc3a6afd2f05657/torch/csrc/utils/object_ptr.h
struct operator_ncnst {
operator_ncnst() = default;
operator_ncnst(operator_ncnst &&) = default;
operator PyObject *() /* */ { return Py_None; } // NOLINT(google-explicit-constructor)
};
struct operator_const {
operator_const() = default;
operator_const(operator_const &&) = default;
operator PyObject *() const { return Py_None; } // NOLINT(google-explicit-constructor)
};
bool from_ncnst() {
operator_ncnst obj;
auto h = py::handle(obj); // Critical part of test: does this compile?
return h.ptr() == Py_None; // Just something.
}
bool from_const() {
operator_const obj;
auto h = py::handle(obj); // Critical part of test: does this compile?
return h.ptr() == Py_None; // Just something.
}
void m_defs(py::module_ &m) {
m.def("handle_from_move_only_type_with_operator_PyObject_ncnst", from_ncnst);
m.def("handle_from_move_only_type_with_operator_PyObject_const", from_const);
}
} // namespace handle_from_move_only_type_with_operator_PyObject
TEST_SUBMODULE(pytypes, m) { TEST_SUBMODULE(pytypes, m) {
handle_from_move_only_type_with_operator_PyObject::m_defs(m);
// test_bool // test_bool
m.def("get_bool", [] { return py::bool_(false); }); m.def("get_bool", [] { return py::bool_(false); });
// test_int // test_int
@ -695,4 +756,38 @@ TEST_SUBMODULE(pytypes, m) {
} }
return o; return o;
}); });
// testing immutable object augmented assignment: #issue 3812
m.def("inplace_append", [](py::object &a, const py::object &b) {
a += b;
return a;
});
m.def("inplace_subtract", [](py::object &a, const py::object &b) {
a -= b;
return a;
});
m.def("inplace_multiply", [](py::object &a, const py::object &b) {
a *= b;
return a;
});
m.def("inplace_divide", [](py::object &a, const py::object &b) {
a /= b;
return a;
});
m.def("inplace_or", [](py::object &a, const py::object &b) {
a |= b;
return a;
});
m.def("inplace_and", [](py::object &a, const py::object &b) {
a &= b;
return a;
});
m.def("inplace_lshift", [](py::object &a, const py::object &b) {
a <<= b;
return a;
});
m.def("inplace_rshift", [](py::object &a, const py::object &b) {
a >>= b;
return a;
});
} }

View File

@ -9,6 +9,11 @@ from pybind11_tests import detailed_error_messages_enabled
from pybind11_tests import pytypes as m from pybind11_tests import pytypes as m
def test_handle_from_move_only_type_with_operator_PyObject(): # noqa: N802
assert m.handle_from_move_only_type_with_operator_PyObject_ncnst()
assert m.handle_from_move_only_type_with_operator_PyObject_const()
def test_bool(doc): def test_bool(doc):
assert doc(m.get_bool) == "get_bool() -> bool" assert doc(m.get_bool) == "get_bool() -> bool"
@ -734,3 +739,75 @@ def test_populate_obj_str_attrs():
new_attrs = {k: v for k, v in new_o.__dict__.items() if not k.startswith("_")} new_attrs = {k: v for k, v in new_o.__dict__.items() if not k.startswith("_")}
assert all(isinstance(v, str) for v in new_attrs.values()) assert all(isinstance(v, str) for v in new_attrs.values())
assert len(new_attrs) == pop assert len(new_attrs) == pop
@pytest.mark.parametrize(
"a,b", [("foo", "bar"), (1, 2), (1.0, 2.0), (list(range(3)), list(range(3, 6)))]
)
def test_inplace_append(a, b):
expected = a + b
assert m.inplace_append(a, b) == expected
@pytest.mark.parametrize("a,b", [(3, 2), (3.0, 2.0), (set(range(3)), set(range(2)))])
def test_inplace_subtract(a, b):
expected = a - b
assert m.inplace_subtract(a, b) == expected
@pytest.mark.parametrize("a,b", [(3, 2), (3.0, 2.0), ([1], 3)])
def test_inplace_multiply(a, b):
expected = a * b
assert m.inplace_multiply(a, b) == expected
@pytest.mark.parametrize("a,b", [(6, 3), (6.0, 3.0)])
def test_inplace_divide(a, b):
expected = a / b
assert m.inplace_divide(a, b) == expected
@pytest.mark.parametrize(
"a,b",
[
(False, True),
(
set(),
{
1,
},
),
],
)
def test_inplace_or(a, b):
expected = a | b
assert m.inplace_or(a, b) == expected
@pytest.mark.parametrize(
"a,b",
[
(True, False),
(
{1, 2, 3},
{
1,
},
),
],
)
def test_inplace_and(a, b):
expected = a & b
assert m.inplace_and(a, b) == expected
@pytest.mark.parametrize("a,b", [(8, 1), (-3, 2)])
def test_inplace_lshift(a, b):
expected = a << b
assert m.inplace_lshift(a, b) == expected
@pytest.mark.parametrize("a,b", [(8, 1), (-2, 2)])
def test_inplace_rshift(a, b):
expected = a >> b
assert m.inplace_rshift(a, b) == expected

View File

@ -342,9 +342,8 @@ TEST_SUBMODULE(virtual_functions, m) {
const AdderBase &adder, const AdderBase &adder,
const AdderBase::DataVisitor &visitor) { const AdderBase::DataVisitor &visitor) {
adder(first, second, [&](const AdderBase::Data &first_plus_second) { adder(first, second, [&](const AdderBase::Data &first_plus_second) {
adder(first_plus_second, // NOLINTNEXTLINE(readability-suspicious-call-argument)
third, adder(first_plus_second, third, visitor);
visitor); // NOLINT(readability-suspicious-call-argument)
}); });
}); });