mirror of
https://github.com/pybind/pybind11.git
synced 2024-12-01 17:37:15 +00:00
t pushMerge branch 'master' of https://github.com/pybind/pybind11 into lazy-error-string
This commit is contained in:
commit
98aff18132
@ -25,11 +25,12 @@ 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-default-member-init,
|
||||
modernize-use-noexcept,
|
||||
modernize-use-emplace,
|
||||
modernize-use-noexcept,
|
||||
modernize-use-nullptr,
|
||||
modernize-use-override,
|
||||
modernize-use-using,
|
||||
*performance*,
|
||||
|
50
.github/workflows/ci.yml
vendored
50
.github/workflows/ci.yml
vendored
@ -32,6 +32,7 @@ jobs:
|
||||
- '3.10'
|
||||
- 'pypy-3.7'
|
||||
- 'pypy-3.8'
|
||||
- 'pypy-3.9'
|
||||
|
||||
# Items in here will either be added to the build matrix (if not
|
||||
# present), or add new keys to an existing matrix element if all the
|
||||
@ -45,6 +46,10 @@ jobs:
|
||||
args: >
|
||||
-DPYBIND11_FINDPYTHON=ON
|
||||
-DCMAKE_CXX_FLAGS="-D_=1"
|
||||
- runs-on: ubuntu-latest
|
||||
python: 'pypy-3.8'
|
||||
args: >
|
||||
-DPYBIND11_FINDPYTHON=ON
|
||||
- runs-on: windows-2019
|
||||
python: '3.6'
|
||||
args: >
|
||||
@ -668,7 +673,7 @@ jobs:
|
||||
|
||||
|
||||
# This verifies that the documentation is not horribly broken, and does a
|
||||
# basic sanity check on the SDist.
|
||||
# basic validation check on the SDist.
|
||||
doxygen:
|
||||
name: "Documentation build test"
|
||||
runs-on: ubuntu-latest
|
||||
@ -756,55 +761,60 @@ jobs:
|
||||
- name: Python tests
|
||||
run: cmake --build build -t pytest
|
||||
|
||||
win32-msvc2017:
|
||||
name: "🐍 ${{ matrix.python }} • MSVC 2017 • x64"
|
||||
runs-on: windows-2016
|
||||
win32-debug:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
python:
|
||||
- 3.6
|
||||
- 3.7
|
||||
std:
|
||||
- 14
|
||||
- 3.8
|
||||
- 3.9
|
||||
|
||||
include:
|
||||
- python: 3.7
|
||||
std: 17
|
||||
args: >
|
||||
-DCMAKE_CXX_FLAGS="/permissive- /EHsc /GR"
|
||||
- python: 3.9
|
||||
args: -DCMAKE_CXX_STANDARD=20
|
||||
- python: 3.8
|
||||
args: -DCMAKE_CXX_STANDARD=17
|
||||
|
||||
name: "🐍 ${{ matrix.python }} • MSVC 2019 (Debug) • x86 ${{ matrix.args }}"
|
||||
runs-on: windows-2019
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Setup 🐍 ${{ matrix.python }}
|
||||
- name: Setup Python ${{ matrix.python }}
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: ${{ matrix.python }}
|
||||
architecture: x86
|
||||
|
||||
- name: Update CMake
|
||||
uses: jwlawson/actions-setup-cmake@v1.12
|
||||
|
||||
- name: Prepare MSVC
|
||||
uses: ilammy/msvc-dev-cmd@v1.10.0
|
||||
with:
|
||||
arch: x86
|
||||
|
||||
- name: Prepare env
|
||||
run: |
|
||||
python -m pip install -r tests/requirements.txt
|
||||
|
||||
# First build - C++11 mode and inplace
|
||||
- name: Configure
|
||||
- name: Configure ${{ matrix.args }}
|
||||
run: >
|
||||
cmake -S . -B build
|
||||
-G "Visual Studio 15 2017" -A x64
|
||||
-G "Visual Studio 16 2019" -A Win32
|
||||
-DCMAKE_BUILD_TYPE=Debug
|
||||
-DPYBIND11_WERROR=ON
|
||||
-DDOWNLOAD_CATCH=ON
|
||||
-DDOWNLOAD_EIGEN=ON
|
||||
-DCMAKE_CXX_STANDARD=${{ matrix.std }}
|
||||
${{ matrix.args }}
|
||||
- name: Build C++11
|
||||
run: cmake --build build --config Debug -j 2
|
||||
|
||||
- name: Build ${{ matrix.std }}
|
||||
run: cmake --build build -j 2
|
||||
- name: Python tests
|
||||
run: cmake --build build --config Debug -t pytest
|
||||
|
||||
- name: Run all checks
|
||||
run: cmake --build build -t check
|
||||
|
||||
windows-2022:
|
||||
strategy:
|
||||
|
10
.github/workflows/configure.yml
vendored
10
.github/workflows/configure.yml
vendored
@ -18,7 +18,7 @@ jobs:
|
||||
matrix:
|
||||
runs-on: [ubuntu-latest, macos-latest, windows-latest]
|
||||
arch: [x64]
|
||||
cmake: ["3.21"]
|
||||
cmake: ["3.23"]
|
||||
|
||||
include:
|
||||
- runs-on: ubuntu-latest
|
||||
@ -29,12 +29,8 @@ jobs:
|
||||
arch: x64
|
||||
cmake: 3.7
|
||||
|
||||
- runs-on: windows-2016
|
||||
arch: x86
|
||||
cmake: 3.8
|
||||
|
||||
- runs-on: windows-2016
|
||||
arch: x86
|
||||
- runs-on: windows-2019
|
||||
arch: x64 # x86 compilers seem to be missing on 2019 image
|
||||
cmake: 3.18
|
||||
|
||||
name: 🐍 3.7 • CMake ${{ matrix.cmake }} • ${{ matrix.runs-on }}
|
||||
|
@ -15,7 +15,7 @@
|
||||
repos:
|
||||
# Standard hooks
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: "v4.1.0"
|
||||
rev: "v4.2.0"
|
||||
hooks:
|
||||
- id: check-added-large-files
|
||||
- id: check-case-conflict
|
||||
@ -32,7 +32,7 @@ repos:
|
||||
|
||||
# Upgrade old Python syntax
|
||||
- repo: https://github.com/asottile/pyupgrade
|
||||
rev: "v2.31.0"
|
||||
rev: "v2.32.0"
|
||||
hooks:
|
||||
- id: pyupgrade
|
||||
args: [--py36-plus]
|
||||
@ -45,7 +45,7 @@ repos:
|
||||
|
||||
# Black, the code formatter, natively supports pre-commit
|
||||
- repo: https://github.com/psf/black
|
||||
rev: "22.1.0" # Keep in sync with blacken-docs
|
||||
rev: "22.3.0" # Keep in sync with blacken-docs
|
||||
hooks:
|
||||
- id: black
|
||||
|
||||
@ -55,7 +55,7 @@ repos:
|
||||
hooks:
|
||||
- id: blacken-docs
|
||||
additional_dependencies:
|
||||
- black==22.1.0 # keep in sync with black hook
|
||||
- black==22.3.0 # keep in sync with black hook
|
||||
|
||||
# Changes tabs to spaces
|
||||
- repo: https://github.com/Lucas-C/pre-commit-hooks
|
||||
@ -64,16 +64,17 @@ repos:
|
||||
- id: remove-tabs
|
||||
|
||||
- repo: https://github.com/sirosen/texthooks
|
||||
rev: "0.2.2"
|
||||
rev: "0.3.1"
|
||||
hooks:
|
||||
- id: fix-ligatures
|
||||
- id: fix-smartquotes
|
||||
|
||||
# Autoremoves unused imports
|
||||
- repo: https://github.com/hadialqattan/pycln
|
||||
rev: "v1.2.4"
|
||||
rev: "v1.3.1"
|
||||
hooks:
|
||||
- id: pycln
|
||||
stages: [manual]
|
||||
|
||||
# Checking for common mistakes
|
||||
- repo: https://github.com/pre-commit/pygrep-hooks
|
||||
@ -106,7 +107,7 @@ repos:
|
||||
|
||||
# PyLint has native support - not always usable, but works for us
|
||||
- repo: https://github.com/PyCQA/pylint
|
||||
rev: "v2.12.2"
|
||||
rev: "v2.13.5"
|
||||
hooks:
|
||||
- id: pylint
|
||||
files: ^pybind11
|
||||
@ -122,16 +123,16 @@ repos:
|
||||
|
||||
# Check static types with mypy
|
||||
- repo: https://github.com/pre-commit/mirrors-mypy
|
||||
rev: "v0.931"
|
||||
rev: "v0.942"
|
||||
hooks:
|
||||
- id: mypy
|
||||
args: [--show-error-codes]
|
||||
args: []
|
||||
exclude: ^(tests|docs)/
|
||||
additional_dependencies: [nox, rich]
|
||||
|
||||
# Checks the manifest for missing files (native support)
|
||||
- repo: https://github.com/mgedmin/check-manifest
|
||||
rev: "0.47"
|
||||
rev: "0.48"
|
||||
hooks:
|
||||
- id: check-manifest
|
||||
# This is a slow hook, so only run this if --hook-stage manual is passed
|
||||
@ -163,7 +164,7 @@ repos:
|
||||
|
||||
# Clang format the codebase automatically
|
||||
- repo: https://github.com/pre-commit/mirrors-clang-format
|
||||
rev: "v13.0.1"
|
||||
rev: "v14.0.1"
|
||||
hooks:
|
||||
- id: clang-format
|
||||
types_or: [c++, c, cuda]
|
||||
|
@ -87,7 +87,7 @@ buffer objects (e.g. a NumPy matrix).
|
||||
/* Request a buffer descriptor from Python */
|
||||
py::buffer_info info = b.request();
|
||||
|
||||
/* Some sanity checks ... */
|
||||
/* Some basic validation checks ... */
|
||||
if (info.format != py::format_descriptor<Scalar>::format())
|
||||
throw std::runtime_error("Incompatible format: expected a double array!");
|
||||
|
||||
|
@ -6,10 +6,129 @@ Changelog
|
||||
Starting with version 1.8.0, pybind11 releases use a `semantic versioning
|
||||
<http://semver.org>`_ policy.
|
||||
|
||||
Changes will be added here periodically from the "Suggested changelog entry"
|
||||
block in pull request descriptions.
|
||||
|
||||
IN DEVELOPMENT
|
||||
--------------
|
||||
|
||||
Changes will be added here periodically.
|
||||
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.
|
||||
|
||||
New features:
|
||||
|
||||
* ``type_caster<std::monostate>`` was added. ``std::monostate`` is a tag type
|
||||
that allows ``std::variant`` to act as an optional, or allows default
|
||||
construction of a ``std::variant`` holding a non-default constructible type.
|
||||
`#3818 <https://github.com/pybind/pybind11/pull/3818>`_
|
||||
|
||||
* Support bytearray casting to string.
|
||||
`#3707 <https://github.com/pybind/pybind11/pull/3707>`_
|
||||
|
||||
Changes:
|
||||
|
||||
* Python 2 support was removed completely.
|
||||
`#3688 <https://github.com/pybind/pybind11/pull/3688>`_
|
||||
|
||||
* The minimum version for MSVC is now 2017.
|
||||
`#3722 <https://github.com/pybind/pybind11/pull/3722>`_
|
||||
|
||||
* Improve exception handling in python ``str`` bindings.
|
||||
`#3826 <https://github.com/pybind/pybind11/pull/3826>`_
|
||||
|
||||
* The bindings for capsules now have more consistent exception handling.
|
||||
`#3825 <https://github.com/pybind/pybind11/pull/3825>`_
|
||||
|
||||
* Fix exception handling when ``pybind11::weakref()`` fails.
|
||||
`#3739 <https://github.com/pybind/pybind11/pull/3739>`_
|
||||
|
||||
|
||||
Bug fixes:
|
||||
|
||||
* ``PYBIND11_OBJECT_CVT`` and ``PYBIND11_OBJECT_CVT_DEFAULT`` macro can be used
|
||||
to define classes in namespaces other than pybind11.
|
||||
`#3797 <https://github.com/pybind/pybind11/pull/3797>`_
|
||||
|
||||
Build system improvements:
|
||||
|
||||
* Add MSVC builds in debug mode to CI.
|
||||
`#3784 <https://github.com/pybind/pybind11/pull/3784>`_
|
||||
|
||||
* MSVC 2022 C++20 coverage was added to GitHub Actions, including Eigen.
|
||||
`#3732 <https://github.com/pybind/pybind11/pull/3732>`_,
|
||||
`#3741 <https://github.com/pybind/pybind11/pull/3741>`_
|
||||
|
||||
* Avoid ``setup.py <command>`` usage in internal tests.
|
||||
`#3734 <https://github.com/pybind/pybind11/pull/3734>`_
|
||||
|
||||
|
||||
Backend and tidying up:
|
||||
|
||||
* Remove idioms in code comments. Use inclusive language.
|
||||
`#3809 <https://github.com/pybind/pybind11/pull/3809>`_
|
||||
|
||||
|
||||
Version 2.9.2 (Mar 29, 2022)
|
||||
----------------------------
|
||||
|
||||
Changes:
|
||||
|
||||
* Enum now has an ``__index__`` method on Python <3.8 too.
|
||||
`#3700 <https://github.com/pybind/pybind11/pull/3700>`_
|
||||
|
||||
* Local internals are now cleared after finalizing the interpreter.
|
||||
`#3744 <https://github.com/pybind/pybind11/pull/3744>`_
|
||||
|
||||
Bug fixes:
|
||||
|
||||
* Better support for Python 3.11 alphas.
|
||||
`#3694 <https://github.com/pybind/pybind11/pull/3694>`_
|
||||
|
||||
* ``PYBIND11_TYPE_CASTER`` now uses fully qualified symbols, so it can be used
|
||||
outside of ``pybind11::detail``.
|
||||
`#3758 <https://github.com/pybind/pybind11/pull/3758>`_
|
||||
|
||||
* Some fixes for PyPy 3.9.
|
||||
`#3768 <https://github.com/pybind/pybind11/pull/3768>`_
|
||||
|
||||
* Fixed a potential memleak in PyPy in ``get_type_override``.
|
||||
`#3774 <https://github.com/pybind/pybind11/pull/3774>`_
|
||||
|
||||
* Fix usage of ``VISIBILITY_INLINES_HIDDEN``.
|
||||
`#3721 <https://github.com/pybind/pybind11/pull/3721>`_
|
||||
|
||||
|
||||
Build system improvements:
|
||||
|
||||
* Uses ``sysconfig`` module to determine installation locations on Python >=
|
||||
3.10, instead of ``distutils`` which has been deprecated.
|
||||
`#3764 <https://github.com/pybind/pybind11/pull/3764>`_
|
||||
|
||||
* Support Catch 2.13.5+ (supporting GLIBC 2.34+).
|
||||
`#3679 <https://github.com/pybind/pybind11/pull/3679>`_
|
||||
|
||||
* Fix test failures with numpy 1.22 by ignoring whitespace when comparing
|
||||
``str()`` of dtypes.
|
||||
`#3682 <https://github.com/pybind/pybind11/pull/3682>`_
|
||||
|
||||
|
||||
Backend and tidying up:
|
||||
|
||||
* clang-tidy: added ``readability-qualified-auto``,
|
||||
``readability-braces-around-statements``,
|
||||
``cppcoreguidelines-prefer-member-initializer``,
|
||||
``clang-analyzer-optin.performance.Padding``,
|
||||
``cppcoreguidelines-pro-type-static-cast-downcast``, and
|
||||
``readability-inconsistent-declaration-parameter-name``.
|
||||
`#3702 <https://github.com/pybind/pybind11/pull/3702>`_,
|
||||
`#3699 <https://github.com/pybind/pybind11/pull/3699>`_,
|
||||
`#3716 <https://github.com/pybind/pybind11/pull/3716>`_,
|
||||
`#3709 <https://github.com/pybind/pybind11/pull/3709>`_
|
||||
|
||||
* clang-format was added to the pre-commit actions, and the entire code base
|
||||
automatically reformatted (after several iterations preparing for this leap).
|
||||
`#3713 <https://github.com/pybind/pybind11/pull/3713>`_
|
||||
|
||||
|
||||
Version 2.9.1 (Feb 2, 2022)
|
||||
|
@ -505,7 +505,10 @@ You can use these targets to build complex applications. For example, the
|
||||
target_link_libraries(example PRIVATE pybind11::module pybind11::lto pybind11::windows_extras)
|
||||
|
||||
pybind11_extension(example)
|
||||
if(NOT MSVC AND NOT ${CMAKE_BUILD_TYPE} MATCHES Debug|RelWithDebInfo)
|
||||
# Strip unnecessary sections of the binary on Linux/macOS
|
||||
pybind11_strip(example)
|
||||
endif()
|
||||
|
||||
set_target_properties(example PROPERTIES CXX_VISIBILITY_PRESET "hidden"
|
||||
CUDA_VISIBILITY_PRESET "hidden")
|
||||
|
@ -514,7 +514,7 @@ struct type_caster<std::basic_string_view<CharT, Traits>,
|
||||
template <typename CharT>
|
||||
struct type_caster<CharT, enable_if_t<is_std_char_type<CharT>::value>> {
|
||||
using StringType = std::basic_string<CharT>;
|
||||
using StringCaster = type_caster<StringType>;
|
||||
using StringCaster = make_caster<StringType>;
|
||||
StringCaster str_caster;
|
||||
bool none = false;
|
||||
CharT one_char = 0;
|
||||
@ -1155,15 +1155,18 @@ enable_if_t<!cast_is_temporary_value_reference<T>::value, T> cast_ref(object &&,
|
||||
// static_assert, even though if it's in dead code, so we provide a "trampoline" to pybind11::cast
|
||||
// that only does anything in cases where pybind11::cast is valid.
|
||||
template <typename T>
|
||||
enable_if_t<!cast_is_temporary_value_reference<T>::value, T> cast_safe(object &&o) {
|
||||
return pybind11::cast<T>(std::move(o));
|
||||
}
|
||||
template <typename T>
|
||||
enable_if_t<cast_is_temporary_value_reference<T>::value, T> cast_safe(object &&) {
|
||||
pybind11_fail("Internal error: cast_safe fallback invoked");
|
||||
}
|
||||
template <>
|
||||
inline void cast_safe<void>(object &&) {}
|
||||
template <typename T>
|
||||
enable_if_t<std::is_same<void, intrinsic_t<T>>::value, void> cast_safe(object &&) {}
|
||||
template <typename T>
|
||||
enable_if_t<detail::none_of<cast_is_temporary_value_reference<T>,
|
||||
std::is_same<void, intrinsic_t<T>>>::value,
|
||||
T>
|
||||
cast_safe(object &&o) {
|
||||
return pybind11::cast<T>(std::move(o));
|
||||
}
|
||||
|
||||
PYBIND11_NAMESPACE_END(detail)
|
||||
|
||||
@ -1243,8 +1246,8 @@ struct arg_v : arg {
|
||||
private:
|
||||
template <typename T>
|
||||
arg_v(arg &&base, T &&x, const char *descr = nullptr)
|
||||
: arg(base), value(reinterpret_steal<object>(
|
||||
detail::make_caster<T>::cast(x, return_value_policy::automatic, {}))),
|
||||
: arg(base), value(reinterpret_steal<object>(detail::make_caster<T>::cast(
|
||||
std::forward<T>(x), return_value_policy::automatic, {}))),
|
||||
descr(descr)
|
||||
#if !defined(NDEBUG)
|
||||
,
|
||||
@ -1491,7 +1494,7 @@ private:
|
||||
type_id<T>());
|
||||
#endif
|
||||
}
|
||||
args_list.append(o);
|
||||
args_list.append(std::move(o));
|
||||
}
|
||||
|
||||
void process(list &args_list, detail::args_proxy ap) {
|
||||
|
@ -992,6 +992,8 @@ constexpr const char
|
||||
struct error_scope {
|
||||
PyObject *type, *value, *trace;
|
||||
error_scope() { PyErr_Fetch(&type, &value, &trace); }
|
||||
error_scope(const error_scope &) = delete;
|
||||
error_scope &operator=(const error_scope &) = delete;
|
||||
~error_scope() { PyErr_Restore(type, value, trace); }
|
||||
};
|
||||
|
||||
|
@ -225,8 +225,8 @@ PYBIND11_NOINLINE detail::type_info *get_type_info(const std::type_index &tp,
|
||||
if (throw_if_missing) {
|
||||
std::string tname = tp.name();
|
||||
detail::clean_type_id(tname);
|
||||
pybind11_fail("pybind11::detail::get_type_info: unable to find type info for \"" + tname
|
||||
+ "\"");
|
||||
pybind11_fail("pybind11::detail::get_type_info: unable to find type info for \""
|
||||
+ std::move(tname) + '"');
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -668,7 +668,7 @@ struct type_caster<Type, enable_if_t<is_eigen_sparse<Type>::value>> {
|
||||
Type::Flags &(Eigen::RowMajor | Eigen::ColMajor),
|
||||
StorageIndex>(shape[0].cast<Index>(),
|
||||
shape[1].cast<Index>(),
|
||||
nnz,
|
||||
std::move(nnz),
|
||||
outerIndices.mutable_data(),
|
||||
innerIndices.mutable_data(),
|
||||
values.mutable_data());
|
||||
@ -686,7 +686,8 @@ 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(data, innerIndices, outerIndices),
|
||||
return matrix_type(std::make_tuple(
|
||||
std::move(data), std::move(innerIndices), std::move(outerIndices)),
|
||||
std::make_pair(src.rows(), src.cols()))
|
||||
.release();
|
||||
}
|
||||
|
@ -82,7 +82,7 @@ template <eval_mode mode = eval_expr, size_t N>
|
||||
object eval(const char (&s)[N], object global = globals(), object local = object()) {
|
||||
/* Support raw string literals by removing common leading whitespace */
|
||||
auto expr = (s[0] == '\n') ? str(module_::import("textwrap").attr("dedent")(s)) : str(s);
|
||||
return eval<mode>(expr, global, local);
|
||||
return eval<mode>(expr, std::move(global), std::move(local));
|
||||
}
|
||||
|
||||
inline void exec(const str &expr, object global = globals(), object local = object()) {
|
||||
@ -91,7 +91,7 @@ inline void exec(const str &expr, object global = globals(), object local = obje
|
||||
|
||||
template <size_t N>
|
||||
void exec(const char (&s)[N], object global = globals(), object local = object()) {
|
||||
eval<eval_statements>(s, global, local);
|
||||
eval<eval_statements>(s, std::move(global), std::move(local));
|
||||
}
|
||||
|
||||
#if defined(PYPY_VERSION)
|
||||
|
@ -263,7 +263,7 @@ private:
|
||||
static npy_api lookup() {
|
||||
module_ m = module_::import("numpy.core.multiarray");
|
||||
auto c = m.attr("_ARRAY_API");
|
||||
void **api_ptr = (void **) PyCapsule_GetPointer(c.ptr(), NULL);
|
||||
void **api_ptr = (void **) PyCapsule_GetPointer(c.ptr(), nullptr);
|
||||
npy_api api;
|
||||
#define DECL_NPY_API(Func) api.Func##_ = (decltype(api.Func##_)) api_ptr[API_##Func];
|
||||
DECL_NPY_API(PyArray_GetNDArrayCFeatureVersion);
|
||||
@ -540,18 +540,18 @@ public:
|
||||
PYBIND11_OBJECT_DEFAULT(dtype, object, detail::npy_api::get().PyArrayDescr_Check_);
|
||||
|
||||
explicit dtype(const buffer_info &info) {
|
||||
dtype descr(_dtype_from_pep3118()(PYBIND11_STR_TYPE(info.format)));
|
||||
dtype descr(_dtype_from_pep3118()(pybind11::str(info.format)));
|
||||
// If info.itemsize == 0, use the value calculated from the format string
|
||||
m_ptr = descr.strip_padding(info.itemsize != 0 ? info.itemsize : descr.itemsize())
|
||||
.release()
|
||||
.ptr();
|
||||
}
|
||||
|
||||
explicit dtype(const std::string &format) {
|
||||
m_ptr = from_args(pybind11::str(format)).release().ptr();
|
||||
}
|
||||
explicit dtype(const pybind11::str &format) : dtype(from_args(format)) {}
|
||||
|
||||
explicit dtype(const char *format) : dtype(std::string(format)) {}
|
||||
explicit dtype(const std::string &format) : dtype(pybind11::str(format)) {}
|
||||
|
||||
explicit dtype(const char *format) : dtype(pybind11::str(format)) {}
|
||||
|
||||
dtype(list names, list formats, list offsets, ssize_t itemsize) {
|
||||
dict args;
|
||||
@ -559,11 +559,18 @@ public:
|
||||
args["formats"] = std::move(formats);
|
||||
args["offsets"] = std::move(offsets);
|
||||
args["itemsize"] = pybind11::int_(itemsize);
|
||||
m_ptr = from_args(std::move(args)).release().ptr();
|
||||
m_ptr = from_args(args).release().ptr();
|
||||
}
|
||||
|
||||
explicit dtype(int typenum)
|
||||
: object(detail::npy_api::get().PyArray_DescrFromType_(typenum), stolen_t{}) {
|
||||
if (m_ptr == nullptr) {
|
||||
throw error_already_set();
|
||||
}
|
||||
}
|
||||
|
||||
/// This is essentially the same as calling numpy.dtype(args) in Python.
|
||||
static dtype from_args(object args) {
|
||||
static dtype from_args(const object &args) {
|
||||
PyObject *ptr = nullptr;
|
||||
if ((detail::npy_api::get().PyArray_DescrConverter_(args.ptr(), &ptr) == 0) || !ptr) {
|
||||
throw error_already_set();
|
||||
@ -596,6 +603,23 @@ public:
|
||||
return detail::array_descriptor_proxy(m_ptr)->type;
|
||||
}
|
||||
|
||||
/// type number of dtype.
|
||||
ssize_t num() const {
|
||||
// Note: The signature, `dtype::num` follows the naming of NumPy's public
|
||||
// Python API (i.e., ``dtype.num``), rather than its internal
|
||||
// C API (``PyArray_Descr::type_num``).
|
||||
return detail::array_descriptor_proxy(m_ptr)->type_num;
|
||||
}
|
||||
|
||||
/// Single character for byteorder
|
||||
char byteorder() const { return detail::array_descriptor_proxy(m_ptr)->byteorder; }
|
||||
|
||||
/// Alignment of the data type
|
||||
int alignment() const { return detail::array_descriptor_proxy(m_ptr)->alignment; }
|
||||
|
||||
/// Flags for the array descriptor
|
||||
char flags() const { return detail::array_descriptor_proxy(m_ptr)->flags; }
|
||||
|
||||
private:
|
||||
static object _dtype_from_pep3118() {
|
||||
static PyObject *obj = module_::import("numpy.core._internal")
|
||||
@ -614,7 +638,7 @@ private:
|
||||
}
|
||||
|
||||
struct field_descr {
|
||||
PYBIND11_STR_TYPE name;
|
||||
pybind11::str name;
|
||||
object format;
|
||||
pybind11::int_ offset;
|
||||
};
|
||||
@ -629,7 +653,7 @@ private:
|
||||
continue;
|
||||
}
|
||||
field_descriptors.push_back(
|
||||
{(PYBIND11_STR_TYPE) name, format.strip_padding(format.itemsize()), offset});
|
||||
{(pybind11::str) name, format.strip_padding(format.itemsize()), offset});
|
||||
}
|
||||
|
||||
std::sort(field_descriptors.begin(),
|
||||
@ -640,9 +664,9 @@ private:
|
||||
|
||||
list names, formats, offsets;
|
||||
for (auto &descr : field_descriptors) {
|
||||
names.append(descr.name);
|
||||
formats.append(descr.format);
|
||||
offsets.append(descr.offset);
|
||||
names.append(std::move(descr.name));
|
||||
formats.append(std::move(descr.format));
|
||||
offsets.append(std::move(descr.offset));
|
||||
}
|
||||
return dtype(std::move(names), std::move(formats), std::move(offsets), itemsize);
|
||||
}
|
||||
@ -940,7 +964,7 @@ protected:
|
||||
|
||||
void fail_dim_check(ssize_t dim, const std::string &msg) const {
|
||||
throw index_error(msg + ": " + std::to_string(dim) + " (ndim = " + std::to_string(ndim())
|
||||
+ ")");
|
||||
+ ')');
|
||||
}
|
||||
|
||||
template <typename... Ix>
|
||||
@ -1144,11 +1168,11 @@ struct format_descriptor<T, detail::enable_if_t<detail::is_pod_struct<T>::value>
|
||||
|
||||
template <size_t N>
|
||||
struct format_descriptor<char[N]> {
|
||||
static std::string format() { return std::to_string(N) + "s"; }
|
||||
static std::string format() { return std::to_string(N) + 's'; }
|
||||
};
|
||||
template <size_t N>
|
||||
struct format_descriptor<std::array<char, N>> {
|
||||
static std::string format() { return std::to_string(N) + "s"; }
|
||||
static std::string format() { return std::to_string(N) + 's'; }
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
@ -1288,7 +1312,8 @@ public:
|
||||
static pybind11::dtype dtype() {
|
||||
list shape;
|
||||
array_info<T>::append_extents(shape);
|
||||
return pybind11::dtype::from_args(pybind11::make_tuple(base_descr::dtype(), shape));
|
||||
return pybind11::dtype::from_args(
|
||||
pybind11::make_tuple(base_descr::dtype(), std::move(shape)));
|
||||
}
|
||||
};
|
||||
|
||||
@ -1334,7 +1359,7 @@ PYBIND11_NOINLINE void register_structured_dtype(any_container<field_descriptor>
|
||||
pybind11_fail(std::string("NumPy: unsupported field dtype: `") + field.name + "` @ "
|
||||
+ tinfo.name());
|
||||
}
|
||||
names.append(PYBIND11_STR_TYPE(field.name));
|
||||
names.append(pybind11::str(field.name));
|
||||
formats.append(field.descr);
|
||||
offsets.append(pybind11::int_(field.offset));
|
||||
}
|
||||
@ -1526,7 +1551,7 @@ public:
|
||||
void *data() const { return p_ptr; }
|
||||
|
||||
private:
|
||||
char *p_ptr{0};
|
||||
char *p_ptr{nullptr};
|
||||
container_type m_strides;
|
||||
};
|
||||
|
||||
|
@ -561,14 +561,14 @@ protected:
|
||||
for (auto *it = chain_start; it != nullptr; it = it->next) {
|
||||
if (options::show_function_signatures()) {
|
||||
if (index > 0) {
|
||||
signatures += "\n";
|
||||
signatures += '\n';
|
||||
}
|
||||
if (chain) {
|
||||
signatures += std::to_string(++index) + ". ";
|
||||
}
|
||||
signatures += rec->name;
|
||||
signatures += it->signature;
|
||||
signatures += "\n";
|
||||
signatures += '\n';
|
||||
}
|
||||
if (it->doc && it->doc[0] != '\0' && options::show_user_defined_docstrings()) {
|
||||
// If we're appending another docstring, and aren't printing function signatures,
|
||||
@ -577,15 +577,15 @@ protected:
|
||||
if (first_user_def) {
|
||||
first_user_def = false;
|
||||
} else {
|
||||
signatures += "\n";
|
||||
signatures += '\n';
|
||||
}
|
||||
}
|
||||
if (options::show_function_signatures()) {
|
||||
signatures += "\n";
|
||||
signatures += '\n';
|
||||
}
|
||||
signatures += it->doc;
|
||||
if (options::show_function_signatures()) {
|
||||
signatures += "\n";
|
||||
signatures += '\n';
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1055,7 +1055,7 @@ protected:
|
||||
msg += it2->signature;
|
||||
}
|
||||
|
||||
msg += "\n";
|
||||
msg += '\n';
|
||||
}
|
||||
msg += "\nInvoked with: ";
|
||||
auto args_ = reinterpret_borrow<tuple>(args_in);
|
||||
@ -1817,7 +1817,8 @@ private:
|
||||
if (holder_ptr) {
|
||||
init_holder_from_existing(v_h, holder_ptr, std::is_copy_constructible<holder_type>());
|
||||
v_h.set_holder_constructed();
|
||||
} else if (inst->owned || detail::always_construct_holder<holder_type>::value) {
|
||||
} else if (PYBIND11_SILENCE_MSVC_C4127(detail::always_construct_holder<holder_type>::value)
|
||||
|| inst->owned) {
|
||||
new (std::addressof(v_h.holder<holder_type>())) holder_type(v_h.value_ptr<type>());
|
||||
v_h.set_holder_constructed();
|
||||
}
|
||||
@ -2402,7 +2403,8 @@ template <return_value_policy Policy = return_value_policy::reference_internal,
|
||||
typename Type,
|
||||
typename... Extra>
|
||||
iterator make_iterator(Type &value, Extra &&...extra) {
|
||||
return make_iterator<Policy>(std::begin(value), std::end(value), extra...);
|
||||
return make_iterator<Policy>(
|
||||
std::begin(value), std::end(value), std::forward<Extra>(extra)...);
|
||||
}
|
||||
|
||||
/// Makes an iterator over the keys (`.first`) of a stl map-like container supporting
|
||||
@ -2411,7 +2413,8 @@ template <return_value_policy Policy = return_value_policy::reference_internal,
|
||||
typename Type,
|
||||
typename... Extra>
|
||||
iterator make_key_iterator(Type &value, Extra &&...extra) {
|
||||
return make_key_iterator<Policy>(std::begin(value), std::end(value), extra...);
|
||||
return make_key_iterator<Policy>(
|
||||
std::begin(value), std::end(value), std::forward<Extra>(extra)...);
|
||||
}
|
||||
|
||||
/// Makes an iterator over the values (`.second`) of a stl map-like container supporting
|
||||
@ -2420,7 +2423,8 @@ template <return_value_policy Policy = return_value_policy::reference_internal,
|
||||
typename Type,
|
||||
typename... Extra>
|
||||
iterator make_value_iterator(Type &value, Extra &&...extra) {
|
||||
return make_value_iterator<Policy>(std::begin(value), std::end(value), extra...);
|
||||
return make_value_iterator<Policy>(
|
||||
std::begin(value), std::end(value), std::forward<Extra>(extra)...);
|
||||
}
|
||||
|
||||
template <typename InputType, typename OutputType>
|
||||
@ -2485,7 +2489,7 @@ public:
|
||||
exception(handle scope, const char *name, handle base = PyExc_Exception) {
|
||||
std::string full_name
|
||||
= scope.attr("__name__").cast<std::string>() + std::string(".") + name;
|
||||
m_ptr = PyErr_NewException(const_cast<char *>(full_name.c_str()), base.ptr(), NULL);
|
||||
m_ptr = PyErr_NewException(const_cast<char *>(full_name.c_str()), base.ptr(), nullptr);
|
||||
if (hasattr(scope, "__dict__") && scope.attr("__dict__").contains(name)) {
|
||||
pybind11_fail("Error during initialization: multiple incompatible "
|
||||
"definitions with name \""
|
||||
@ -2694,9 +2698,9 @@ get_type_override(const void *this_ptr, const type_info *this_type, const char *
|
||||
d.ptr());
|
||||
if (result == nullptr)
|
||||
throw error_already_set();
|
||||
Py_DECREF(result);
|
||||
if (d["self"].is_none())
|
||||
return function();
|
||||
Py_DECREF(result);
|
||||
#endif
|
||||
|
||||
return override;
|
||||
|
@ -270,10 +270,7 @@ public:
|
||||
/// Copy constructor; always increases the reference count
|
||||
object(const object &o) : handle(o) { inc_ref(); }
|
||||
/// Move constructor; steals the object from ``other`` and preserves its reference count
|
||||
object(object &&other) noexcept {
|
||||
m_ptr = other.m_ptr;
|
||||
other.m_ptr = nullptr;
|
||||
}
|
||||
object(object &&other) noexcept : handle(other) { other.m_ptr = nullptr; }
|
||||
/// Destructor; automatically calls `handle::dec_ref()`
|
||||
~object() { dec_ref(); }
|
||||
|
||||
@ -636,13 +633,13 @@ inline handle get_function(handle value) {
|
||||
inline PyObject *dict_getitemstring(PyObject *v, const char *key) {
|
||||
PyObject *kv = nullptr, *rv = nullptr;
|
||||
kv = PyUnicode_FromString(key);
|
||||
if (kv == NULL) {
|
||||
if (kv == nullptr) {
|
||||
throw error_already_set();
|
||||
}
|
||||
|
||||
rv = PyDict_GetItemWithError(v, kv);
|
||||
Py_DECREF(kv);
|
||||
if (rv == NULL && PyErr_Occurred()) {
|
||||
if (rv == nullptr && PyErr_Occurred()) {
|
||||
throw error_already_set();
|
||||
}
|
||||
return rv;
|
||||
@ -650,7 +647,7 @@ inline PyObject *dict_getitemstring(PyObject *v, const char *key) {
|
||||
|
||||
inline PyObject *dict_getitem(PyObject *v, PyObject *key) {
|
||||
PyObject *rv = PyDict_GetItemWithError(v, key);
|
||||
if (rv == NULL && PyErr_Occurred()) {
|
||||
if (rv == nullptr && PyErr_Occurred()) {
|
||||
throw error_already_set();
|
||||
}
|
||||
return rv;
|
||||
@ -1071,12 +1068,12 @@ public:
|
||||
Name(const object &o) \
|
||||
: Parent(check_(o) ? o.inc_ref().ptr() : ConvertFun(o.ptr()), stolen_t{}) { \
|
||||
if (!m_ptr) \
|
||||
throw error_already_set(); \
|
||||
throw ::pybind11::error_already_set(); \
|
||||
} \
|
||||
/* NOLINTNEXTLINE(google-explicit-constructor) */ \
|
||||
Name(object &&o) : Parent(check_(o) ? o.release().ptr() : ConvertFun(o.ptr()), stolen_t{}) { \
|
||||
if (!m_ptr) \
|
||||
throw error_already_set(); \
|
||||
throw ::pybind11::error_already_set(); \
|
||||
}
|
||||
|
||||
#define PYBIND11_OBJECT_CVT_DEFAULT(Name, Parent, CheckFun, ConvertFun) \
|
||||
@ -1276,8 +1273,8 @@ public:
|
||||
}
|
||||
char *buffer = nullptr;
|
||||
ssize_t length = 0;
|
||||
if (PYBIND11_BYTES_AS_STRING_AND_SIZE(temp.ptr(), &buffer, &length)) {
|
||||
pybind11_fail("Unable to extract string contents! (invalid type)");
|
||||
if (PyBytes_AsStringAndSize(temp.ptr(), &buffer, &length) != 0) {
|
||||
throw error_already_set();
|
||||
}
|
||||
return std::string(buffer, (size_t) length);
|
||||
}
|
||||
@ -1332,14 +1329,7 @@ public:
|
||||
explicit bytes(const pybind11::str &s);
|
||||
|
||||
// NOLINTNEXTLINE(google-explicit-constructor)
|
||||
operator std::string() const {
|
||||
char *buffer = nullptr;
|
||||
ssize_t length = 0;
|
||||
if (PYBIND11_BYTES_AS_STRING_AND_SIZE(m_ptr, &buffer, &length)) {
|
||||
pybind11_fail("Unable to extract bytes contents!");
|
||||
}
|
||||
return std::string(buffer, (size_t) length);
|
||||
}
|
||||
operator std::string() const { return string_op<std::string>(); }
|
||||
|
||||
#ifdef PYBIND11_HAS_STRING_VIEW
|
||||
// enable_if is needed to avoid "ambiguous conversion" errors (see PR #3521).
|
||||
@ -1351,15 +1341,18 @@ public:
|
||||
// valid so long as the `bytes` instance remains alive and so generally should not outlive the
|
||||
// lifetime of the `bytes` instance.
|
||||
// NOLINTNEXTLINE(google-explicit-constructor)
|
||||
operator std::string_view() const {
|
||||
operator std::string_view() const { return string_op<std::string_view>(); }
|
||||
#endif
|
||||
private:
|
||||
template <typename T>
|
||||
T string_op() const {
|
||||
char *buffer = nullptr;
|
||||
ssize_t length = 0;
|
||||
if (PYBIND11_BYTES_AS_STRING_AND_SIZE(m_ptr, &buffer, &length)) {
|
||||
pybind11_fail("Unable to extract bytes contents!");
|
||||
if (PyBytes_AsStringAndSize(m_ptr, &buffer, &length) != 0) {
|
||||
throw error_already_set();
|
||||
}
|
||||
return {buffer, static_cast<size_t>(length)};
|
||||
}
|
||||
#endif
|
||||
};
|
||||
// Note: breathe >= 4.17.0 will fail to build docs if the below two constructors
|
||||
// are included in the doxygen group; close here and reopen after as a workaround
|
||||
@ -1370,13 +1363,13 @@ inline bytes::bytes(const pybind11::str &s) {
|
||||
if (PyUnicode_Check(s.ptr())) {
|
||||
temp = reinterpret_steal<object>(PyUnicode_AsUTF8String(s.ptr()));
|
||||
if (!temp) {
|
||||
pybind11_fail("Unable to extract string contents! (encoding issue)");
|
||||
throw error_already_set();
|
||||
}
|
||||
}
|
||||
char *buffer = nullptr;
|
||||
ssize_t length = 0;
|
||||
if (PYBIND11_BYTES_AS_STRING_AND_SIZE(temp.ptr(), &buffer, &length)) {
|
||||
pybind11_fail("Unable to extract string contents! (invalid type)");
|
||||
if (PyBytes_AsStringAndSize(temp.ptr(), &buffer, &length) != 0) {
|
||||
throw error_already_set();
|
||||
}
|
||||
auto obj = reinterpret_steal<object>(PYBIND11_BYTES_FROM_STRING_AND_SIZE(buffer, length));
|
||||
if (!obj) {
|
||||
@ -1388,8 +1381,8 @@ inline bytes::bytes(const pybind11::str &s) {
|
||||
inline str::str(const bytes &b) {
|
||||
char *buffer = nullptr;
|
||||
ssize_t length = 0;
|
||||
if (PYBIND11_BYTES_AS_STRING_AND_SIZE(b.ptr(), &buffer, &length)) {
|
||||
pybind11_fail("Unable to extract bytes contents!");
|
||||
if (PyBytes_AsStringAndSize(b.ptr(), &buffer, &length) != 0) {
|
||||
throw error_already_set();
|
||||
}
|
||||
auto obj = reinterpret_steal<object>(PyUnicode_FromStringAndSize(buffer, length));
|
||||
if (!obj) {
|
||||
@ -1556,8 +1549,8 @@ private:
|
||||
class slice : public object {
|
||||
public:
|
||||
PYBIND11_OBJECT_DEFAULT(slice, object, PySlice_Check)
|
||||
slice(handle start, handle stop, handle step) {
|
||||
m_ptr = PySlice_New(start.ptr(), stop.ptr(), step.ptr());
|
||||
slice(handle start, handle stop, handle step)
|
||||
: object(PySlice_New(start.ptr(), stop.ptr(), step.ptr()), stolen_t{}) {
|
||||
if (!m_ptr) {
|
||||
pybind11_fail("Could not allocate slice object!");
|
||||
}
|
||||
@ -1607,7 +1600,7 @@ public:
|
||||
void (*destructor)(PyObject *) = nullptr)
|
||||
: object(PyCapsule_New(const_cast<void *>(value), name, destructor), stolen_t{}) {
|
||||
if (!m_ptr) {
|
||||
pybind11_fail("Could not allocate capsule object!");
|
||||
throw error_already_set();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1615,34 +1608,44 @@ public:
|
||||
capsule(const void *value, void (*destruct)(PyObject *))
|
||||
: object(PyCapsule_New(const_cast<void *>(value), nullptr, destruct), stolen_t{}) {
|
||||
if (!m_ptr) {
|
||||
pybind11_fail("Could not allocate capsule object!");
|
||||
throw error_already_set();
|
||||
}
|
||||
}
|
||||
|
||||
capsule(const void *value, void (*destructor)(void *)) {
|
||||
m_ptr = PyCapsule_New(const_cast<void *>(value), nullptr, [](PyObject *o) {
|
||||
auto destructor = reinterpret_cast<void (*)(void *)>(PyCapsule_GetContext(o));
|
||||
void *ptr = PyCapsule_GetPointer(o, nullptr);
|
||||
if (destructor == nullptr) {
|
||||
if (PyErr_Occurred()) {
|
||||
throw error_already_set();
|
||||
}
|
||||
pybind11_fail("Unable to get capsule context");
|
||||
}
|
||||
const char *name = get_name_in_error_scope(o);
|
||||
void *ptr = PyCapsule_GetPointer(o, name);
|
||||
if (ptr == nullptr) {
|
||||
throw error_already_set();
|
||||
}
|
||||
destructor(ptr);
|
||||
});
|
||||
|
||||
if (!m_ptr) {
|
||||
pybind11_fail("Could not allocate capsule object!");
|
||||
}
|
||||
|
||||
if (PyCapsule_SetContext(m_ptr, (void *) destructor) != 0) {
|
||||
pybind11_fail("Could not set capsule context!");
|
||||
if (!m_ptr || PyCapsule_SetContext(m_ptr, (void *) destructor) != 0) {
|
||||
throw error_already_set();
|
||||
}
|
||||
}
|
||||
|
||||
explicit capsule(void (*destructor)()) {
|
||||
m_ptr = PyCapsule_New(reinterpret_cast<void *>(destructor), nullptr, [](PyObject *o) {
|
||||
auto destructor = reinterpret_cast<void (*)()>(PyCapsule_GetPointer(o, nullptr));
|
||||
const char *name = get_name_in_error_scope(o);
|
||||
auto destructor = reinterpret_cast<void (*)()>(PyCapsule_GetPointer(o, name));
|
||||
if (destructor == nullptr) {
|
||||
throw error_already_set();
|
||||
}
|
||||
destructor();
|
||||
});
|
||||
|
||||
if (!m_ptr) {
|
||||
pybind11_fail("Could not allocate capsule object!");
|
||||
throw error_already_set();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1657,8 +1660,7 @@ public:
|
||||
const auto *name = this->name();
|
||||
T *result = static_cast<T *>(PyCapsule_GetPointer(m_ptr, name));
|
||||
if (!result) {
|
||||
PyErr_Clear();
|
||||
pybind11_fail("Unable to extract capsule contents!");
|
||||
throw error_already_set();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -1666,12 +1668,37 @@ public:
|
||||
/// Replaces a capsule's pointer *without* calling the destructor on the existing one.
|
||||
void set_pointer(const void *value) {
|
||||
if (PyCapsule_SetPointer(m_ptr, const_cast<void *>(value)) != 0) {
|
||||
PyErr_Clear();
|
||||
pybind11_fail("Could not set capsule pointer");
|
||||
throw error_already_set();
|
||||
}
|
||||
}
|
||||
|
||||
const char *name() const { return PyCapsule_GetName(m_ptr); }
|
||||
const char *name() const {
|
||||
const char *name = PyCapsule_GetName(m_ptr);
|
||||
if ((name == nullptr) && PyErr_Occurred()) {
|
||||
throw error_already_set();
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
/// Replaces a capsule's name *without* calling the destructor on the existing one.
|
||||
void set_name(const char *new_name) {
|
||||
if (PyCapsule_SetName(m_ptr, new_name) != 0) {
|
||||
throw error_already_set();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
static const char *get_name_in_error_scope(PyObject *o) {
|
||||
error_scope error_guard;
|
||||
|
||||
const char *name = PyCapsule_GetName(o);
|
||||
if ((name == nullptr) && PyErr_Occurred()) {
|
||||
// write out and consume error raised by call to PyCapsule_GetName
|
||||
PyErr_WriteUnraisable(o);
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
};
|
||||
|
||||
class tuple : public object {
|
||||
@ -1920,8 +1947,8 @@ public:
|
||||
return memoryview::from_buffer(reinterpret_cast<void *>(ptr),
|
||||
sizeof(T),
|
||||
format_descriptor<T>::value,
|
||||
shape,
|
||||
strides,
|
||||
std::move(shape),
|
||||
std::move(strides),
|
||||
readonly);
|
||||
}
|
||||
|
||||
@ -1929,7 +1956,8 @@ public:
|
||||
static memoryview from_buffer(const T *ptr,
|
||||
detail::any_container<ssize_t> shape,
|
||||
detail::any_container<ssize_t> strides) {
|
||||
return memoryview::from_buffer(const_cast<T *>(ptr), shape, strides, true);
|
||||
return memoryview::from_buffer(
|
||||
const_cast<T *>(ptr), std::move(shape), std::move(strides), true);
|
||||
}
|
||||
|
||||
/** \rst
|
||||
|
@ -79,7 +79,7 @@ struct set_caster {
|
||||
for (auto &&value : src) {
|
||||
auto value_ = reinterpret_steal<object>(
|
||||
key_conv::cast(forward_like<T>(value), policy, parent));
|
||||
if (!value_ || !s.add(value_)) {
|
||||
if (!value_ || !s.add(std::move(value_))) {
|
||||
return handle();
|
||||
}
|
||||
}
|
||||
@ -372,7 +372,7 @@ struct variant_caster<V<Ts...>> {
|
||||
bool load_alternative(handle src, bool convert, type_list<U, Us...>) {
|
||||
auto caster = make_caster<U>();
|
||||
if (caster.load(src, convert)) {
|
||||
value = cast_op<U>(caster);
|
||||
value = cast_op<U>(std::move(caster));
|
||||
return true;
|
||||
}
|
||||
return load_alternative(src, convert, type_list<Us...>{});
|
||||
@ -406,6 +406,9 @@ struct variant_caster<V<Ts...>> {
|
||||
#if defined(PYBIND11_HAS_VARIANT)
|
||||
template <typename... Ts>
|
||||
struct type_caster<std::variant<Ts...>> : variant_caster<std::variant<Ts...>> {};
|
||||
|
||||
template <>
|
||||
struct type_caster<std::monostate> : public void_caster<std::monostate> {};
|
||||
#endif
|
||||
|
||||
PYBIND11_NAMESPACE_END(detail)
|
||||
|
@ -13,21 +13,28 @@
|
||||
#include <string>
|
||||
|
||||
#ifdef __has_include
|
||||
# if defined(PYBIND11_CPP17) && __has_include(<filesystem>)
|
||||
# if defined(PYBIND11_CPP17)
|
||||
# if __has_include(<filesystem>) && \
|
||||
PY_VERSION_HEX >= 0x03060000
|
||||
# include <filesystem>
|
||||
# define PYBIND11_HAS_FILESYSTEM 1
|
||||
# elif __has_include(<experimental/filesystem>)
|
||||
# include <experimental/filesystem>
|
||||
# define PYBIND11_HAS_EXPERIMENTAL_FILESYSTEM 1
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !defined(PYBIND11_HAS_FILESYSTEM) && !defined(PYBIND11_HAS_FILESYSTEM_IS_OPTIONAL)
|
||||
#if !defined(PYBIND11_HAS_FILESYSTEM) && !defined(PYBIND11_HAS_EXPERIMENTAL_FILESYSTEM) \
|
||||
&& !defined(PYBIND11_HAS_FILESYSTEM_IS_OPTIONAL)
|
||||
# error \
|
||||
"#include <filesystem> is not available. (Use -DPYBIND11_HAS_FILESYSTEM_IS_OPTIONAL to ignore.)"
|
||||
"Neither #include <filesystem> nor #include <experimental/filesystem is available. (Use -DPYBIND11_HAS_FILESYSTEM_IS_OPTIONAL to ignore.)"
|
||||
#endif
|
||||
|
||||
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
|
||||
PYBIND11_NAMESPACE_BEGIN(detail)
|
||||
|
||||
#if defined(PYBIND11_HAS_FILESYSTEM)
|
||||
#if defined(PYBIND11_HAS_FILESYSTEM) || defined(PYBIND11_HAS_EXPERIMENTAL_FILESYSTEM)
|
||||
template <typename T>
|
||||
struct path_caster {
|
||||
|
||||
@ -94,9 +101,16 @@ public:
|
||||
PYBIND11_TYPE_CASTER(T, const_name("os.PathLike"));
|
||||
};
|
||||
|
||||
#endif // PYBIND11_HAS_FILESYSTEM || defined(PYBIND11_HAS_EXPERIMENTAL_FILESYSTEM)
|
||||
|
||||
#if defined(PYBIND11_HAS_FILESYSTEM)
|
||||
template <>
|
||||
struct type_caster<std::filesystem::path> : public path_caster<std::filesystem::path> {};
|
||||
#endif // PYBIND11_HAS_FILESYSTEM
|
||||
#elif defined(PYBIND11_HAS_EXPERIMENTAL_FILESYSTEM)
|
||||
template <>
|
||||
struct type_caster<std::experimental::filesystem::path>
|
||||
: public path_caster<std::experimental::filesystem::path> {};
|
||||
#endif
|
||||
|
||||
PYBIND11_NAMESPACE_END(detail)
|
||||
PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)
|
||||
|
@ -232,7 +232,7 @@ void vector_modifiers(
|
||||
/// Slicing protocol
|
||||
cl.def(
|
||||
"__getitem__",
|
||||
[](const Vector &v, slice slice) -> Vector * {
|
||||
[](const Vector &v, const slice &slice) -> Vector * {
|
||||
size_t start = 0, stop = 0, step = 0, slicelength = 0;
|
||||
|
||||
if (!slice.compute(v.size(), &start, &stop, &step, &slicelength)) {
|
||||
@ -253,7 +253,7 @@ void vector_modifiers(
|
||||
|
||||
cl.def(
|
||||
"__setitem__",
|
||||
[](Vector &v, slice slice, const Vector &value) {
|
||||
[](Vector &v, const slice &slice, const Vector &value) {
|
||||
size_t start = 0, stop = 0, step = 0, slicelength = 0;
|
||||
if (!slice.compute(v.size(), &start, &stop, &step, &slicelength)) {
|
||||
throw error_already_set();
|
||||
@ -281,7 +281,7 @@ void vector_modifiers(
|
||||
|
||||
cl.def(
|
||||
"__delitem__",
|
||||
[](Vector &v, slice slice) {
|
||||
[](Vector &v, const slice &slice) {
|
||||
size_t start = 0, stop = 0, step = 0, slicelength = 0;
|
||||
|
||||
if (!slice.compute(v.size(), &start, &stop, &step, &slicelength)) {
|
||||
|
@ -24,8 +24,10 @@ profile = "black"
|
||||
[tool.mypy]
|
||||
files = ["pybind11"]
|
||||
python_version = "3.6"
|
||||
warn_unused_configs = true
|
||||
strict = true
|
||||
show_error_codes = true
|
||||
enable_error_code = ["ignore-without-code", "redundant-expr", "truthy-bool"]
|
||||
warn_unreachable = true
|
||||
|
||||
[[tool.mypy.overrides]]
|
||||
module = ["ghapi.*", "setuptools.*"]
|
||||
|
@ -25,8 +25,8 @@ void gil_acquire() { py::gil_scoped_acquire gil; }
|
||||
|
||||
constexpr char kModuleName[] = "cross_module_gil_utils";
|
||||
|
||||
struct PyModuleDef moduledef
|
||||
= {PyModuleDef_HEAD_INIT, kModuleName, NULL, 0, NULL, NULL, NULL, NULL, NULL};
|
||||
struct PyModuleDef moduledef = {
|
||||
PyModuleDef_HEAD_INIT, kModuleName, nullptr, 0, nullptr, nullptr, nullptr, nullptr, nullptr};
|
||||
|
||||
} // namespace
|
||||
|
||||
@ -34,7 +34,7 @@ extern "C" PYBIND11_EXPORT PyObject *PyInit_cross_module_gil_utils() {
|
||||
|
||||
PyObject *m = PyModule_Create(&moduledef);
|
||||
|
||||
if (m != NULL) {
|
||||
if (m != nullptr) {
|
||||
static_assert(sizeof(&gil_acquire) == sizeof(void *),
|
||||
"Function pointer must have the same size as void*");
|
||||
PyModule_AddObject(
|
||||
|
@ -289,8 +289,9 @@ py::list test_dtype_ctors() {
|
||||
dict["itemsize"] = py::int_(20);
|
||||
list.append(py::dtype::from_args(dict));
|
||||
list.append(py::dtype(names, formats, offsets, 20));
|
||||
list.append(py::dtype(py::buffer_info((void *) 0, sizeof(unsigned int), "I", 1)));
|
||||
list.append(py::dtype(py::buffer_info((void *) 0, 0, "T{i:a:f:b:}", 1)));
|
||||
list.append(py::dtype(py::buffer_info((void *) nullptr, sizeof(unsigned int), "I", 1)));
|
||||
list.append(py::dtype(py::buffer_info((void *) nullptr, 0, "T{i:a:f:b:}", 1)));
|
||||
list.append(py::dtype(py::detail::npy_api::NPY_DOUBLE_));
|
||||
return list;
|
||||
}
|
||||
|
||||
@ -440,6 +441,34 @@ TEST_SUBMODULE(numpy_dtypes, m) {
|
||||
}
|
||||
return list;
|
||||
});
|
||||
m.def("test_dtype_num", [dtype_names]() {
|
||||
py::list list;
|
||||
for (const auto &dt_name : dtype_names) {
|
||||
list.append(py::dtype(dt_name).num());
|
||||
}
|
||||
return list;
|
||||
});
|
||||
m.def("test_dtype_byteorder", [dtype_names]() {
|
||||
py::list list;
|
||||
for (const auto &dt_name : dtype_names) {
|
||||
list.append(py::dtype(dt_name).byteorder());
|
||||
}
|
||||
return list;
|
||||
});
|
||||
m.def("test_dtype_alignment", [dtype_names]() {
|
||||
py::list list;
|
||||
for (const auto &dt_name : dtype_names) {
|
||||
list.append(py::dtype(dt_name).alignment());
|
||||
}
|
||||
return list;
|
||||
});
|
||||
m.def("test_dtype_flags", [dtype_names]() {
|
||||
py::list list;
|
||||
for (const auto &dt_name : dtype_names) {
|
||||
list.append(py::dtype(dt_name).flags());
|
||||
}
|
||||
return list;
|
||||
});
|
||||
m.def("test_dtype_methods", []() {
|
||||
py::list list;
|
||||
auto dt1 = py::dtype::of<int32_t>();
|
||||
@ -581,5 +610,5 @@ TEST_SUBMODULE(numpy_dtypes, m) {
|
||||
[]() { PYBIND11_NUMPY_DTYPE(SimpleStruct, bool_, uint_, float_, ldbl_); });
|
||||
|
||||
// test_str_leak
|
||||
m.def("dtype_wrapper", [](py::object d) { return py::dtype::from_args(std::move(d)); });
|
||||
m.def("dtype_wrapper", [](const py::object &d) { return py::dtype::from_args(d); });
|
||||
}
|
||||
|
@ -160,6 +160,7 @@ def test_dtype(simple_dtype):
|
||||
d1,
|
||||
np.dtype("uint32"),
|
||||
d2,
|
||||
np.dtype("d"),
|
||||
]
|
||||
|
||||
assert m.test_dtype_methods() == [
|
||||
@ -175,8 +176,13 @@ def test_dtype(simple_dtype):
|
||||
np.zeros(1, m.trailing_padding_dtype())
|
||||
)
|
||||
|
||||
expected_chars = "bhilqBHILQefdgFDG?MmO"
|
||||
assert m.test_dtype_kind() == list("iiiiiuuuuuffffcccbMmO")
|
||||
assert m.test_dtype_char_() == list("bhilqBHILQefdgFDG?MmO")
|
||||
assert m.test_dtype_char_() == list(expected_chars)
|
||||
assert m.test_dtype_num() == [np.dtype(ch).num for ch in expected_chars]
|
||||
assert m.test_dtype_byteorder() == [np.dtype(ch).byteorder for ch in expected_chars]
|
||||
assert m.test_dtype_alignment() == [np.dtype(ch).alignment for ch in expected_chars]
|
||||
assert m.test_dtype_flags() == [chr(np.dtype(ch).flags) for ch in expected_chars]
|
||||
|
||||
|
||||
def test_recarray(simple_dtype, packed_dtype):
|
||||
|
@ -11,6 +11,34 @@
|
||||
|
||||
#include <utility>
|
||||
|
||||
namespace external {
|
||||
namespace detail {
|
||||
bool check(PyObject *o) { return PyFloat_Check(o) != 0; }
|
||||
|
||||
PyObject *conv(PyObject *o) {
|
||||
PyObject *ret = nullptr;
|
||||
if (PyLong_Check(o)) {
|
||||
double v = PyLong_AsDouble(o);
|
||||
if (!(v == -1.0 && PyErr_Occurred())) {
|
||||
ret = PyFloat_FromDouble(v);
|
||||
}
|
||||
} else {
|
||||
PyErr_SetString(PyExc_TypeError, "Unexpected type");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
PyObject *default_constructed() { return PyFloat_FromDouble(0.0); }
|
||||
} // namespace detail
|
||||
class float_ : public py::object {
|
||||
PYBIND11_OBJECT_CVT(float_, py::object, external::detail::check, external::detail::conv)
|
||||
|
||||
float_() : py::object(external::detail::default_constructed(), stolen_t{}) {}
|
||||
|
||||
double get_value() const { return PyFloat_AsDouble(this->ptr()); }
|
||||
};
|
||||
} // namespace external
|
||||
|
||||
TEST_SUBMODULE(pytypes, m) {
|
||||
// test_bool
|
||||
m.def("get_bool", [] { return py::bool_(false); });
|
||||
@ -131,6 +159,15 @@ TEST_SUBMODULE(pytypes, m) {
|
||||
return py::capsule([]() { py::print("destructing capsule"); });
|
||||
});
|
||||
|
||||
m.def("return_renamed_capsule_with_destructor", []() {
|
||||
py::print("creating capsule");
|
||||
auto cap = py::capsule([]() { py::print("destructing capsule"); });
|
||||
static const char *capsule_name = "test_name1";
|
||||
py::print("renaming capsule");
|
||||
cap.set_name(capsule_name);
|
||||
return cap;
|
||||
});
|
||||
|
||||
m.def("return_capsule_with_destructor_2", []() {
|
||||
py::print("creating capsule");
|
||||
return py::capsule((void *) 1234, [](void *ptr) {
|
||||
@ -138,6 +175,17 @@ TEST_SUBMODULE(pytypes, m) {
|
||||
});
|
||||
});
|
||||
|
||||
m.def("return_renamed_capsule_with_destructor_2", []() {
|
||||
py::print("creating capsule");
|
||||
auto cap = py::capsule((void *) 1234, [](void *ptr) {
|
||||
py::print("destructing capsule: {}"_s.format((size_t) ptr));
|
||||
});
|
||||
static const char *capsule_name = "test_name2";
|
||||
py::print("renaming capsule");
|
||||
cap.set_name(capsule_name);
|
||||
return cap;
|
||||
});
|
||||
|
||||
m.def("return_capsule_with_name_and_destructor", []() {
|
||||
auto capsule = py::capsule((void *) 12345, "pointer type description", [](PyObject *ptr) {
|
||||
if (ptr) {
|
||||
@ -545,4 +593,9 @@ TEST_SUBMODULE(pytypes, m) {
|
||||
py::detail::accessor_policies::tuple_item::set(o, (py::size_t) 0, s0);
|
||||
return o;
|
||||
});
|
||||
|
||||
m.def("square_float_", [](const external::float_ &x) -> double {
|
||||
double v = x.get_value();
|
||||
return v * v;
|
||||
});
|
||||
}
|
||||
|
@ -195,6 +195,19 @@ def test_capsule(capture):
|
||||
"""
|
||||
)
|
||||
|
||||
with capture:
|
||||
a = m.return_renamed_capsule_with_destructor()
|
||||
del a
|
||||
pytest.gc_collect()
|
||||
assert (
|
||||
capture.unordered
|
||||
== """
|
||||
creating capsule
|
||||
renaming capsule
|
||||
destructing capsule
|
||||
"""
|
||||
)
|
||||
|
||||
with capture:
|
||||
a = m.return_capsule_with_destructor_2()
|
||||
del a
|
||||
@ -207,6 +220,19 @@ def test_capsule(capture):
|
||||
"""
|
||||
)
|
||||
|
||||
with capture:
|
||||
a = m.return_renamed_capsule_with_destructor_2()
|
||||
del a
|
||||
pytest.gc_collect()
|
||||
assert (
|
||||
capture.unordered
|
||||
== """
|
||||
creating capsule
|
||||
renaming capsule
|
||||
destructing capsule: 1234
|
||||
"""
|
||||
)
|
||||
|
||||
with capture:
|
||||
a = m.return_capsule_with_name_and_destructor()
|
||||
del a
|
||||
@ -634,3 +660,8 @@ def test_implementation_details():
|
||||
assert m.tuple_item_set_ssize_t() == ("emely", "edmond")
|
||||
assert m.tuple_item_get_size_t(tup) == 93
|
||||
assert m.tuple_item_set_size_t() == ("candy", "cat")
|
||||
|
||||
|
||||
def test_external_float_():
|
||||
r1 = m.square_float_(2.0)
|
||||
assert r1 == 4.0
|
||||
|
@ -37,9 +37,10 @@ struct type_caster<boost::none_t> : void_caster<boost::none_t> {};
|
||||
// Test with `std::variant` in C++17 mode, or with `boost::variant` in C++11/14
|
||||
#if defined(PYBIND11_HAS_VARIANT)
|
||||
using std::variant;
|
||||
# define PYBIND11_TEST_VARIANT 1
|
||||
#elif defined(PYBIND11_TEST_BOOST)
|
||||
# include <boost/variant.hpp>
|
||||
# define PYBIND11_HAS_VARIANT 1
|
||||
# define PYBIND11_TEST_VARIANT 1
|
||||
using boost::variant;
|
||||
|
||||
namespace pybind11 {
|
||||
@ -424,7 +425,7 @@ TEST_SUBMODULE(stl, m) {
|
||||
m.def("parent_path", [](const std::filesystem::path &p) { return p.parent_path(); });
|
||||
#endif
|
||||
|
||||
#ifdef PYBIND11_HAS_VARIANT
|
||||
#ifdef PYBIND11_TEST_VARIANT
|
||||
static_assert(std::is_same<py::detail::variant_caster_visitor::result_type, py::handle>::value,
|
||||
"visitor::result_type is required by boost::variant in C++11 mode");
|
||||
|
||||
@ -435,6 +436,9 @@ TEST_SUBMODULE(stl, m) {
|
||||
result_type operator()(const std::string &) { return "std::string"; }
|
||||
result_type operator()(double) { return "double"; }
|
||||
result_type operator()(std::nullptr_t) { return "std::nullptr_t"; }
|
||||
# if defined(PYBIND11_HAS_VARIANT)
|
||||
result_type operator()(std::monostate) { return "std::monostate"; }
|
||||
# endif
|
||||
};
|
||||
|
||||
// test_variant
|
||||
@ -448,6 +452,18 @@ TEST_SUBMODULE(stl, m) {
|
||||
using V = variant<int, std::string>;
|
||||
return py::make_tuple(V(5), V("Hello"));
|
||||
});
|
||||
|
||||
# if defined(PYBIND11_HAS_VARIANT)
|
||||
// std::monostate tests.
|
||||
m.def("load_monostate_variant",
|
||||
[](const variant<std::monostate, int, std::string> &v) -> const char * {
|
||||
return py::detail::visit_helper<variant>::call(visitor(), v);
|
||||
});
|
||||
m.def("cast_monostate_variant", []() {
|
||||
using V = variant<std::monostate, int, std::string>;
|
||||
return py::make_tuple(V{}, V(5), V("Hello"));
|
||||
});
|
||||
# endif
|
||||
#endif
|
||||
|
||||
// #528: templated constructor
|
||||
|
@ -263,6 +263,22 @@ def test_variant(doc):
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.skipif(
|
||||
not hasattr(m, "load_monostate_variant"), reason="no std::monostate"
|
||||
)
|
||||
def test_variant_monostate(doc):
|
||||
assert m.load_monostate_variant(None) == "std::monostate"
|
||||
assert m.load_monostate_variant(1) == "int"
|
||||
assert m.load_monostate_variant("1") == "std::string"
|
||||
|
||||
assert m.cast_monostate_variant() == (None, 5, "Hello")
|
||||
|
||||
assert (
|
||||
doc(m.load_monostate_variant)
|
||||
== "load_monostate_variant(arg0: Union[None, int, str]) -> str"
|
||||
)
|
||||
|
||||
|
||||
def test_vec_of_reference_wrapper():
|
||||
"""#171: Can't return reference wrappers (or STL structures containing them)"""
|
||||
assert (
|
||||
|
Loading…
Reference in New Issue
Block a user