mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-11 08:03:55 +00:00
Merge branch 'master' into sh_merge_master
This commit is contained in:
commit
4d774ec218
126
.clang-tidy
126
.clang-tidy
@ -1,68 +1,70 @@
|
||||
FormatStyle: file
|
||||
|
||||
Checks: '
|
||||
*bugprone*,
|
||||
clang-analyzer-optin.performance.Padding,
|
||||
clang-analyzer-optin.cplusplus.VirtualCall,
|
||||
cppcoreguidelines-init-variables,
|
||||
cppcoreguidelines-prefer-member-initializer,
|
||||
cppcoreguidelines-pro-type-static-cast-downcast,
|
||||
cppcoreguidelines-slicing,
|
||||
google-explicit-constructor,
|
||||
llvm-namespace-comment,
|
||||
misc-definitions-in-headers,
|
||||
misc-misplaced-const,
|
||||
misc-non-copyable-objects,
|
||||
misc-static-assert,
|
||||
misc-throw-by-value-catch-by-reference,
|
||||
misc-uniqueptr-reset-release,
|
||||
misc-unused-parameters,
|
||||
modernize-avoid-bind,
|
||||
modernize-loop-convert,
|
||||
modernize-make-shared,
|
||||
modernize-redundant-void-arg,
|
||||
modernize-replace-auto-ptr,
|
||||
modernize-replace-disallow-copy-and-assign-macro,
|
||||
modernize-replace-random-shuffle,
|
||||
modernize-shrink-to-fit,
|
||||
modernize-use-auto,
|
||||
modernize-use-bool-literals,
|
||||
modernize-use-default-member-init,
|
||||
modernize-use-equals-default,
|
||||
modernize-use-equals-delete,
|
||||
modernize-use-emplace,
|
||||
modernize-use-noexcept,
|
||||
modernize-use-nullptr,
|
||||
modernize-use-override,
|
||||
modernize-use-using,
|
||||
*performance*,
|
||||
readability-avoid-const-params-in-decls,
|
||||
readability-braces-around-statements,
|
||||
readability-const-return-type,
|
||||
readability-container-size-empty,
|
||||
readability-delete-null-pointer,
|
||||
readability-else-after-return,
|
||||
readability-implicit-bool-conversion,
|
||||
readability-inconsistent-declaration-parameter-name,
|
||||
readability-make-member-function-const,
|
||||
readability-misplaced-array-index,
|
||||
readability-non-const-parameter,
|
||||
readability-qualified-auto,
|
||||
readability-redundant-function-ptr-dereference,
|
||||
readability-redundant-smartptr-get,
|
||||
readability-redundant-string-cstr,
|
||||
readability-simplify-subscript-expr,
|
||||
readability-static-accessed-through-instance,
|
||||
readability-static-definition-in-anonymous-namespace,
|
||||
readability-string-compare,
|
||||
readability-suspicious-call-argument,
|
||||
readability-uniqueptr-delete-release,
|
||||
-bugprone-exception-escape,
|
||||
-bugprone-reserved-identifier,
|
||||
-bugprone-unused-raii,
|
||||
'
|
||||
Checks: |
|
||||
*bugprone*,
|
||||
*performance*,
|
||||
clang-analyzer-optin.cplusplus.VirtualCall,
|
||||
clang-analyzer-optin.performance.Padding,
|
||||
cppcoreguidelines-init-variables,
|
||||
cppcoreguidelines-prefer-member-initializer,
|
||||
cppcoreguidelines-pro-type-static-cast-downcast,
|
||||
cppcoreguidelines-slicing,
|
||||
google-explicit-constructor,
|
||||
llvm-namespace-comment,
|
||||
misc-definitions-in-headers,
|
||||
misc-misplaced-const,
|
||||
misc-non-copyable-objects,
|
||||
misc-static-assert,
|
||||
misc-throw-by-value-catch-by-reference,
|
||||
misc-uniqueptr-reset-release,
|
||||
misc-unused-parameters,
|
||||
modernize-avoid-bind,
|
||||
modernize-loop-convert,
|
||||
modernize-make-shared,
|
||||
modernize-redundant-void-arg,
|
||||
modernize-replace-auto-ptr,
|
||||
modernize-replace-disallow-copy-and-assign-macro,
|
||||
modernize-replace-random-shuffle,
|
||||
modernize-shrink-to-fit,
|
||||
modernize-use-auto,
|
||||
modernize-use-bool-literals,
|
||||
modernize-use-default-member-init,
|
||||
modernize-use-emplace,
|
||||
modernize-use-equals-default,
|
||||
modernize-use-equals-delete,
|
||||
modernize-use-noexcept,
|
||||
modernize-use-nullptr,
|
||||
modernize-use-override,
|
||||
modernize-use-using,
|
||||
readability-avoid-const-params-in-decls,
|
||||
readability-braces-around-statements,
|
||||
readability-const-return-type,
|
||||
readability-container-size-empty,
|
||||
readability-delete-null-pointer,
|
||||
readability-else-after-return,
|
||||
readability-implicit-bool-conversion,
|
||||
readability-inconsistent-declaration-parameter-name,
|
||||
readability-make-member-function-const,
|
||||
readability-misplaced-array-index,
|
||||
readability-non-const-parameter,
|
||||
readability-qualified-auto,
|
||||
readability-redundant-function-ptr-dereference,
|
||||
readability-redundant-smartptr-get,
|
||||
readability-redundant-string-cstr,
|
||||
readability-simplify-subscript-expr,
|
||||
readability-static-accessed-through-instance,
|
||||
readability-static-definition-in-anonymous-namespace,
|
||||
readability-string-compare,
|
||||
readability-suspicious-call-argument,
|
||||
readability-uniqueptr-delete-release,
|
||||
-bugprone-easily-swappable-parameters,
|
||||
-bugprone-exception-escape,
|
||||
-bugprone-reserved-identifier,
|
||||
-bugprone-unused-raii,
|
||||
|
||||
CheckOptions:
|
||||
- key: modernize-use-equals-default.IgnoreMacros
|
||||
value: false
|
||||
- key: performance-for-range-copy.WarnOnAllAutoCopies
|
||||
value: true
|
||||
- key: performance-inefficient-string-concatenation.StrictMode
|
||||
@ -73,5 +75,3 @@ CheckOptions:
|
||||
value: true
|
||||
|
||||
HeaderFilterRegex: 'pybind11/.*h'
|
||||
|
||||
WarningsAsErrors: '*'
|
||||
|
8
.github/CONTRIBUTING.md
vendored
8
.github/CONTRIBUTING.md
vendored
@ -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.
|
||||
|
||||
```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
|
||||
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 --build build -j 2 -- --keep-going
|
||||
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
|
||||
```
|
||||
|
||||
You can add `--fix` to the options list if you want.
|
||||
|
||||
### Include what you use
|
||||
|
||||
To run include what you use, install (`brew install include-what-you-use` on
|
||||
|
22
.github/workflows/ci.yml
vendored
22
.github/workflows/ci.yml
vendored
@ -282,6 +282,14 @@ jobs:
|
||||
std: 20
|
||||
- clang: 10
|
||||
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"
|
||||
container: "silkeh/clang:${{ matrix.clang }}"
|
||||
@ -436,14 +444,14 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
gcc:
|
||||
- 7
|
||||
- latest
|
||||
std:
|
||||
- 11
|
||||
include:
|
||||
- gcc: 10
|
||||
std: 20
|
||||
- { gcc: 7, std: 11 }
|
||||
- { 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"
|
||||
container: "gcc:${{ matrix.gcc }}"
|
||||
|
4
.github/workflows/format.yml
vendored
4
.github/workflows/format.yml
vendored
@ -37,7 +37,7 @@ jobs:
|
||||
# in .github/CONTRIBUTING.md and update as needed.
|
||||
name: Clang-Tidy
|
||||
runs-on: ubuntu-latest
|
||||
container: silkeh/clang:12
|
||||
container: silkeh/clang:13
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
@ -47,7 +47,7 @@ jobs:
|
||||
- name: Configure
|
||||
run: >
|
||||
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_CATCH=ON
|
||||
-DCMAKE_CXX_STANDARD=17
|
||||
|
@ -73,7 +73,7 @@ repos:
|
||||
|
||||
# Autoremoves unused imports
|
||||
- repo: https://github.com/hadialqattan/pycln
|
||||
rev: "v2.0.1"
|
||||
rev: "v2.0.4"
|
||||
hooks:
|
||||
- id: pycln
|
||||
stages: [manual]
|
||||
@ -110,7 +110,7 @@ repos:
|
||||
|
||||
# PyLint has native support - not always usable, but works for us
|
||||
- repo: https://github.com/PyCQA/pylint
|
||||
rev: "v2.14.4"
|
||||
rev: "v2.14.5"
|
||||
hooks:
|
||||
- id: pylint
|
||||
files: ^pybind11
|
||||
|
3
docs/_static/css/custom.css
vendored
Normal file
3
docs/_static/css/custom.css
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
.highlight .go {
|
||||
color: #707070;
|
||||
}
|
11
docs/_static/theme_overrides.css
vendored
11
docs/_static/theme_overrides.css
vendored
@ -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;
|
||||
}
|
@ -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"
|
||||
block in pull request descriptions.
|
||||
|
||||
|
||||
|
||||
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
|
||||
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.
|
||||
|
||||
|
||||
New features:
|
||||
|
||||
* ``py::anyset`` & ``py::frozenset`` were added, with copying (cast) to
|
||||
@ -70,6 +76,9 @@ Changes:
|
||||
requiring ``NDEBUG``, allowing use with release builds if desired.
|
||||
`#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:
|
||||
|
||||
@ -98,6 +107,14 @@ Bug fixes:
|
||||
* Fix cast from pytype rvalue to another pytype.
|
||||
`#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
|
||||
exceptions.
|
||||
`#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.
|
||||
`#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
|
||||
``strdup_gaurd``.
|
||||
`#3905 <https://github.com/pybind/pybind11/pull/3905>`_
|
||||
@ -182,6 +202,9 @@ Build system improvements:
|
||||
|
||||
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.
|
||||
`#3809 <https://github.com/pybind/pybind11/pull/3809>`_
|
||||
|
||||
|
23
docs/conf.py
23
docs/conf.py
@ -35,6 +35,7 @@ DIR = Path(__file__).parent.resolve()
|
||||
# ones.
|
||||
extensions = [
|
||||
"breathe",
|
||||
"sphinx_copybutton",
|
||||
"sphinxcontrib.rsvgconverter",
|
||||
"sphinxcontrib.moderncmakedomain",
|
||||
]
|
||||
@ -125,23 +126,7 @@ todo_include_todos = False
|
||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes.
|
||||
|
||||
on_rtd = os.environ.get("READTHEDOCS", None) == "True"
|
||||
|
||||
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",
|
||||
]
|
||||
}
|
||||
html_theme = "furo"
|
||||
|
||||
# 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
|
||||
@ -172,6 +157,10 @@ else:
|
||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||
html_static_path = ["_static"]
|
||||
|
||||
html_css_files = [
|
||||
"css/custom.css",
|
||||
]
|
||||
|
||||
# Add any extra paths that contain custom files (such as robots.txt or
|
||||
# .htaccess) here, relative to this directory. These files are copied
|
||||
# directly to the root of the documentation.
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 57 KiB After Width: | Height: | Size: 60 KiB |
@ -1,5 +1,6 @@
|
||||
breathe==4.32.0
|
||||
sphinx==4.4.0
|
||||
sphinx_rtd_theme==1.0.0
|
||||
breathe==4.34.0
|
||||
furo==2022.6.21
|
||||
sphinx==5.0.2
|
||||
sphinx-copybutton==0.5.0
|
||||
sphinxcontrib-moderncmakedomain==3.21.4
|
||||
sphinxcontrib-svg2pdfconverter==1.2.0
|
||||
|
@ -10,12 +10,12 @@
|
||||
#pragma once
|
||||
|
||||
#define PYBIND11_VERSION_MAJOR 2
|
||||
#define PYBIND11_VERSION_MINOR 10
|
||||
#define PYBIND11_VERSION_MINOR 11
|
||||
#define PYBIND11_VERSION_PATCH 0.dev1
|
||||
|
||||
// Similar to Python's convention: https://docs.python.org/3/c-api/apiabiversion.html
|
||||
// Additional convention: 0xD = dev
|
||||
#define PYBIND11_VERSION_HEX 0x020A00D1
|
||||
#define PYBIND11_VERSION_HEX 0x020B00D1
|
||||
|
||||
#define PYBIND11_NAMESPACE_BEGIN(name) namespace 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__
|
||||
#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
|
||||
// negation of ndebug). This can also be manually enabled by users, for any builds, through
|
||||
// defining PYBIND11_DETAILED_ERROR_MESSAGES.
|
||||
|
@ -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 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::make_pair(src.rows(), src.cols()))
|
||||
pybind11::make_tuple(src.rows(), src.cols()))
|
||||
.release();
|
||||
}
|
||||
|
||||
|
@ -537,7 +537,7 @@ PYBIND11_NAMESPACE_END(detail)
|
||||
|
||||
class dtype : public object {
|
||||
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) {
|
||||
dtype descr(_dtype_from_pep3118()(pybind11::str(info.format)));
|
||||
@ -1865,9 +1865,13 @@ private:
|
||||
}
|
||||
|
||||
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) {
|
||||
return std::move(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Call the function */
|
||||
@ -1878,7 +1882,10 @@ private:
|
||||
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>
|
||||
|
@ -155,23 +155,23 @@ public:
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
|
||||
PYBIND11_DEPRECATED("Use py::str(obj) instead")
|
||||
pybind11::str str() const;
|
||||
@ -190,6 +190,11 @@ private:
|
||||
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)
|
||||
|
||||
#if !defined(PYBIND11_HANDLE_REF_DEBUG) && !defined(NDEBUG)
|
||||
@ -211,9 +216,23 @@ class handle : public detail::object_api<handle> {
|
||||
public:
|
||||
/// The default constructor creates a handle with a ``nullptr``-valued pointer
|
||||
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)
|
||||
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
|
||||
PyObject *ptr() const { return m_ptr; }
|
||||
@ -315,12 +334,15 @@ public:
|
||||
}
|
||||
|
||||
object &operator=(const object &other) {
|
||||
other.inc_ref();
|
||||
// Use temporary variable to ensure `*this` remains valid while
|
||||
// `Py_XDECREF` executes, in case `*this` is accessible from Python.
|
||||
handle temp(m_ptr);
|
||||
m_ptr = other.m_ptr;
|
||||
temp.dec_ref();
|
||||
// Skip inc_ref and dec_ref if both objects are the same
|
||||
if (!this->is(other)) {
|
||||
other.inc_ref();
|
||||
// Use temporary variable to ensure `*this` remains valid while
|
||||
// `Py_XDECREF` executes, in case `*this` is accessible from Python.
|
||||
handle temp(m_ptr);
|
||||
m_ptr = other.m_ptr;
|
||||
temp.dec_ref();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -334,6 +356,20 @@ public:
|
||||
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)
|
||||
template <typename T>
|
||||
T cast() const &;
|
||||
@ -437,6 +473,12 @@ struct error_fetch_and_normalize {
|
||||
+ " failed to obtain the name "
|
||||
"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) {
|
||||
std::string msg = std::string(called)
|
||||
+ ": MISMATCH of original and normalized "
|
||||
@ -448,6 +490,7 @@ struct error_fetch_and_normalize {
|
||||
msg += ": " + format_value_and_trace();
|
||||
pybind11_fail(msg);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
error_fetch_and_normalize(const error_fetch_and_normalize &) = delete;
|
||||
@ -1247,7 +1290,7 @@ public:
|
||||
|
||||
#define PYBIND11_OBJECT_CVT_DEFAULT(Name, Parent, CheckFun, ConvertFun) \
|
||||
PYBIND11_OBJECT_CVT(Name, Parent, CheckFun, ConvertFun) \
|
||||
Name() : Parent() {}
|
||||
Name() = default;
|
||||
|
||||
#define PYBIND11_OBJECT_CHECK_FAILED(Name, o_ptr) \
|
||||
::pybind11::type_error("Object of type '" \
|
||||
@ -1270,7 +1313,7 @@ public:
|
||||
|
||||
#define PYBIND11_OBJECT_DEFAULT(Name, Parent, CheckFun) \
|
||||
PYBIND11_OBJECT(Name, Parent, CheckFun) \
|
||||
Name() : Parent() {}
|
||||
Name() = default;
|
||||
|
||||
/// \addtogroup pytypes
|
||||
/// @{
|
||||
@ -2345,26 +2388,35 @@ bool object_api<D>::rich_compare(object_api const &other, int value) const {
|
||||
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_Negative)
|
||||
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_InPlaceSubtract)
|
||||
PYBIND11_MATH_OPERATOR_BINARY_INPLACE(operator-=, PyNumber_InPlaceSubtract)
|
||||
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_InPlaceTrueDivide)
|
||||
PYBIND11_MATH_OPERATOR_BINARY_INPLACE(operator/=, PyNumber_InPlaceTrueDivide)
|
||||
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_InPlaceAnd)
|
||||
PYBIND11_MATH_OPERATOR_BINARY_INPLACE(operator&=, PyNumber_InPlaceAnd)
|
||||
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_InPlaceLshift)
|
||||
PYBIND11_MATH_OPERATOR_BINARY_INPLACE(operator<<=, PyNumber_InPlaceLshift)
|
||||
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_BINARY
|
||||
|
18
noxfile.py
18
noxfile.py
@ -5,7 +5,17 @@ import nox
|
||||
nox.needs_version = ">=2022.1.7"
|
||||
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):
|
||||
nox.options.error_on_missing_interpreters = True
|
||||
@ -20,7 +30,7 @@ def lint(session: nox.Session) -> None:
|
||||
session.run("pre-commit", "run", "-a")
|
||||
|
||||
|
||||
@nox.session(python=PYTHON_VERISONS)
|
||||
@nox.session(python=PYTHON_VERSIONS)
|
||||
def tests(session: nox.Session) -> None:
|
||||
"""
|
||||
Run the tests (requires a compiler).
|
||||
@ -61,10 +71,10 @@ def docs(session: nox.Session) -> None:
|
||||
session.chdir("docs")
|
||||
|
||||
if "pdf" in session.posargs:
|
||||
session.run("sphinx-build", "-b", "latexpdf", ".", "_build")
|
||||
session.run("sphinx-build", "-M", "latexpdf", ".", "_build")
|
||||
return
|
||||
|
||||
session.run("sphinx-build", "-b", "html", ".", "_build")
|
||||
session.run("sphinx-build", "-M", "html", ".", "_build")
|
||||
|
||||
if "serve" in session.posargs:
|
||||
session.log("Launching docs at http://localhost:8000/ - use Ctrl-C to quit")
|
||||
|
@ -8,5 +8,5 @@ def _to_int(s: str) -> Union[int, str]:
|
||||
return s
|
||||
|
||||
|
||||
__version__ = "2.10.0.dev1"
|
||||
__version__ = "2.11.0.dev1"
|
||||
version_info = tuple(_to_int(s) for s in __version__.split("."))
|
||||
|
@ -7,7 +7,7 @@ if("${PYTHON_MODULE_EXTENSION}" MATCHES "pypy" OR "${Python_INTERPRETER_ID}" STR
|
||||
return()
|
||||
endif()
|
||||
|
||||
find_package(Catch 2.13.5)
|
||||
find_package(Catch 2.13.9)
|
||||
|
||||
if(CATCH_FOUND)
|
||||
message(STATUS "Building interpreter tests using Catch v${CATCH_VERSION}")
|
||||
|
@ -334,4 +334,14 @@ TEST_SUBMODULE(exceptions, m) {
|
||||
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");
|
||||
});
|
||||
}
|
||||
|
@ -360,3 +360,9 @@ def test_error_already_set_double_restore():
|
||||
"Internal error: pybind11::detail::error_fetch_and_normalize::restore()"
|
||||
" 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
|
||||
|
@ -43,7 +43,16 @@ TEST_SUBMODULE(kwargs_and_defaults, m) {
|
||||
m.def("kw_func_udl_z", kw_func, "x"_a, "y"_a = 0);
|
||||
|
||||
// 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) {
|
||||
return py::make_tuple(args, kwargs);
|
||||
});
|
||||
|
@ -39,7 +39,68 @@ class float_ : public py::object {
|
||||
};
|
||||
} // 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) {
|
||||
handle_from_move_only_type_with_operator_PyObject::m_defs(m);
|
||||
|
||||
// test_bool
|
||||
m.def("get_bool", [] { return py::bool_(false); });
|
||||
// test_int
|
||||
@ -695,4 +756,38 @@ TEST_SUBMODULE(pytypes, m) {
|
||||
}
|
||||
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;
|
||||
});
|
||||
}
|
||||
|
@ -9,6 +9,11 @@ from pybind11_tests import detailed_error_messages_enabled
|
||||
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):
|
||||
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("_")}
|
||||
assert all(isinstance(v, str) for v in new_attrs.values())
|
||||
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
|
||||
|
@ -342,9 +342,8 @@ TEST_SUBMODULE(virtual_functions, m) {
|
||||
const AdderBase &adder,
|
||||
const AdderBase::DataVisitor &visitor) {
|
||||
adder(first, second, [&](const AdderBase::Data &first_plus_second) {
|
||||
adder(first_plus_second,
|
||||
third,
|
||||
visitor); // NOLINT(readability-suspicious-call-argument)
|
||||
// NOLINTNEXTLINE(readability-suspicious-call-argument)
|
||||
adder(first_plus_second, third, visitor);
|
||||
});
|
||||
});
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user