mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-26 07:02:11 +00:00
Merge branch 'master' into sh_merge_master
This commit is contained in:
commit
fd68dede10
6
.github/workflows/ci.yml
vendored
6
.github/workflows/ci.yml
vendored
@ -170,7 +170,7 @@ jobs:
|
|||||||
# MSVC, but for now, this action works:
|
# MSVC, but for now, this action works:
|
||||||
- name: Prepare compiler environment for Windows 🐍 2.7
|
- name: Prepare compiler environment for Windows 🐍 2.7
|
||||||
if: matrix.python == 2.7 && runner.os == 'Windows'
|
if: matrix.python == 2.7 && runner.os == 'Windows'
|
||||||
uses: ilammy/msvc-dev-cmd@v1.9.0
|
uses: ilammy/msvc-dev-cmd@v1.10.0
|
||||||
with:
|
with:
|
||||||
arch: x64
|
arch: x64
|
||||||
|
|
||||||
@ -761,7 +761,7 @@ jobs:
|
|||||||
uses: jwlawson/actions-setup-cmake@v1.11
|
uses: jwlawson/actions-setup-cmake@v1.11
|
||||||
|
|
||||||
- name: Prepare MSVC
|
- name: Prepare MSVC
|
||||||
uses: ilammy/msvc-dev-cmd@v1.9.0
|
uses: ilammy/msvc-dev-cmd@v1.10.0
|
||||||
with:
|
with:
|
||||||
arch: x86
|
arch: x86
|
||||||
|
|
||||||
@ -807,7 +807,7 @@ jobs:
|
|||||||
uses: jwlawson/actions-setup-cmake@v1.11
|
uses: jwlawson/actions-setup-cmake@v1.11
|
||||||
|
|
||||||
- name: Prepare MSVC
|
- name: Prepare MSVC
|
||||||
uses: ilammy/msvc-dev-cmd@v1.9.0
|
uses: ilammy/msvc-dev-cmd@v1.10.0
|
||||||
with:
|
with:
|
||||||
toolset: 14.0
|
toolset: 14.0
|
||||||
|
|
||||||
|
@ -69,14 +69,32 @@ repos:
|
|||||||
hooks:
|
hooks:
|
||||||
- id: pycln
|
- id: pycln
|
||||||
|
|
||||||
|
- repo: https://github.com/pre-commit/pygrep-hooks
|
||||||
|
rev: v1.9.0
|
||||||
|
hooks:
|
||||||
|
- id: python-check-blanket-noqa
|
||||||
|
- id: python-check-blanket-type-ignore
|
||||||
|
- id: python-no-log-warn
|
||||||
|
- id: rst-backticks
|
||||||
|
- id: rst-directive-colons
|
||||||
|
- id: rst-inline-touching-normal
|
||||||
|
|
||||||
# Flake8 also supports pre-commit natively (same author)
|
# Flake8 also supports pre-commit natively (same author)
|
||||||
- repo: https://github.com/PyCQA/flake8
|
- repo: https://github.com/PyCQA/flake8
|
||||||
rev: 3.9.2
|
rev: 4.0.1
|
||||||
hooks:
|
hooks:
|
||||||
- id: flake8
|
- id: flake8
|
||||||
additional_dependencies: [flake8-bugbear, pep8-naming]
|
additional_dependencies: &flake8_dependencies
|
||||||
|
- flake8-bugbear
|
||||||
|
- pep8-naming
|
||||||
exclude: ^(docs/.*|tools/.*)$
|
exclude: ^(docs/.*|tools/.*)$
|
||||||
|
|
||||||
|
- repo: https://github.com/asottile/yesqa
|
||||||
|
rev: v1.2.3
|
||||||
|
hooks:
|
||||||
|
- id: yesqa
|
||||||
|
additional_dependencies: *flake8_dependencies
|
||||||
|
|
||||||
# CMake formatting
|
# CMake formatting
|
||||||
- repo: https://github.com/cheshirekow/cmake-format-precommit
|
- repo: https://github.com/cheshirekow/cmake-format-precommit
|
||||||
rev: v0.6.13
|
rev: v0.6.13
|
||||||
@ -88,12 +106,9 @@ repos:
|
|||||||
|
|
||||||
# Check static types with mypy
|
# Check static types with mypy
|
||||||
- repo: https://github.com/pre-commit/mirrors-mypy
|
- repo: https://github.com/pre-commit/mirrors-mypy
|
||||||
rev: v0.910
|
rev: v0.910-1
|
||||||
hooks:
|
hooks:
|
||||||
- id: mypy
|
- id: mypy
|
||||||
# The default Python type ignores .pyi files, so let's rerun if detected
|
|
||||||
types: [text]
|
|
||||||
files: ^pybind11.*\.pyi?$
|
|
||||||
# Running per-file misbehaves a bit, so just run on all files, it's fast
|
# Running per-file misbehaves a bit, so just run on all files, it's fast
|
||||||
pass_filenames: false
|
pass_filenames: false
|
||||||
additional_dependencies: [typed_ast]
|
additional_dependencies: [typed_ast]
|
||||||
|
@ -1266,7 +1266,7 @@ Custom type setup
|
|||||||
=================
|
=================
|
||||||
|
|
||||||
For advanced use cases, such as enabling garbage collection support, you may
|
For advanced use cases, such as enabling garbage collection support, you may
|
||||||
wish to directly manipulate the `PyHeapTypeObject` corresponding to a
|
wish to directly manipulate the ``PyHeapTypeObject`` corresponding to a
|
||||||
``py::class_`` definition.
|
``py::class_`` definition.
|
||||||
|
|
||||||
You can do that using ``py::custom_type_setup``:
|
You can do that using ``py::custom_type_setup``:
|
||||||
|
@ -40,15 +40,15 @@ The essential structure of the ``main.cpp`` file looks like this:
|
|||||||
}
|
}
|
||||||
|
|
||||||
The interpreter must be initialized before using any Python API, which includes
|
The interpreter must be initialized before using any Python API, which includes
|
||||||
all the functions and classes in pybind11. The RAII guard class `scoped_interpreter`
|
all the functions and classes in pybind11. The RAII guard class ``scoped_interpreter``
|
||||||
takes care of the interpreter lifetime. After the guard is destroyed, the interpreter
|
takes care of the interpreter lifetime. After the guard is destroyed, the interpreter
|
||||||
shuts down and clears its memory. No Python functions can be called after this.
|
shuts down and clears its memory. No Python functions can be called after this.
|
||||||
|
|
||||||
Executing Python code
|
Executing Python code
|
||||||
=====================
|
=====================
|
||||||
|
|
||||||
There are a few different ways to run Python code. One option is to use `eval`,
|
There are a few different ways to run Python code. One option is to use ``eval``,
|
||||||
`exec` or `eval_file`, as explained in :ref:`eval`. Here is a quick example in
|
``exec`` or ``eval_file``, as explained in :ref:`eval`. Here is a quick example in
|
||||||
the context of an executable with an embedded interpreter:
|
the context of an executable with an embedded interpreter:
|
||||||
|
|
||||||
.. code-block:: cpp
|
.. code-block:: cpp
|
||||||
@ -108,7 +108,7 @@ The two approaches can also be combined:
|
|||||||
Importing modules
|
Importing modules
|
||||||
=================
|
=================
|
||||||
|
|
||||||
Python modules can be imported using `module_::import()`:
|
Python modules can be imported using ``module_::import()``:
|
||||||
|
|
||||||
.. code-block:: cpp
|
.. code-block:: cpp
|
||||||
|
|
||||||
@ -134,7 +134,7 @@ embedding the interpreter. This makes it easy to import local Python files:
|
|||||||
int n = result.cast<int>();
|
int n = result.cast<int>();
|
||||||
assert(n == 3);
|
assert(n == 3);
|
||||||
|
|
||||||
Modules can be reloaded using `module_::reload()` if the source is modified e.g.
|
Modules can be reloaded using ``module_::reload()`` if the source is modified e.g.
|
||||||
by an external process. This can be useful in scenarios where the application
|
by an external process. This can be useful in scenarios where the application
|
||||||
imports a user defined data processing script which needs to be updated after
|
imports a user defined data processing script which needs to be updated after
|
||||||
changes by the user. Note that this function does not reload modules recursively.
|
changes by the user. Note that this function does not reload modules recursively.
|
||||||
@ -144,7 +144,7 @@ changes by the user. Note that this function does not reload modules recursively
|
|||||||
Adding embedded modules
|
Adding embedded modules
|
||||||
=======================
|
=======================
|
||||||
|
|
||||||
Embedded binary modules can be added using the `PYBIND11_EMBEDDED_MODULE` macro.
|
Embedded binary modules can be added using the ``PYBIND11_EMBEDDED_MODULE`` macro.
|
||||||
Note that the definition must be placed at global scope. They can be imported
|
Note that the definition must be placed at global scope. They can be imported
|
||||||
like any other module.
|
like any other module.
|
||||||
|
|
||||||
@ -170,7 +170,7 @@ like any other module.
|
|||||||
|
|
||||||
Unlike extension modules where only a single binary module can be created, on
|
Unlike extension modules where only a single binary module can be created, on
|
||||||
the embedded side an unlimited number of modules can be added using multiple
|
the embedded side an unlimited number of modules can be added using multiple
|
||||||
`PYBIND11_EMBEDDED_MODULE` definitions (as long as they have unique names).
|
``PYBIND11_EMBEDDED_MODULE`` definitions (as long as they have unique names).
|
||||||
|
|
||||||
These modules are added to Python's list of builtins, so they can also be
|
These modules are added to Python's list of builtins, so they can also be
|
||||||
imported in pure Python files loaded by the interpreter. Everything interacts
|
imported in pure Python files loaded by the interpreter. Everything interacts
|
||||||
@ -216,9 +216,9 @@ naturally:
|
|||||||
Interpreter lifetime
|
Interpreter lifetime
|
||||||
====================
|
====================
|
||||||
|
|
||||||
The Python interpreter shuts down when `scoped_interpreter` is destroyed. After
|
The Python interpreter shuts down when ``scoped_interpreter`` is destroyed. After
|
||||||
this, creating a new instance will restart the interpreter. Alternatively, the
|
this, creating a new instance will restart the interpreter. Alternatively, the
|
||||||
`initialize_interpreter` / `finalize_interpreter` pair of functions can be used
|
``initialize_interpreter`` / ``finalize_interpreter`` pair of functions can be used
|
||||||
to directly set the state at any time.
|
to directly set the state at any time.
|
||||||
|
|
||||||
Modules created with pybind11 can be safely re-initialized after the interpreter
|
Modules created with pybind11 can be safely re-initialized after the interpreter
|
||||||
@ -230,8 +230,8 @@ global data. All the details can be found in the CPython documentation.
|
|||||||
|
|
||||||
.. warning::
|
.. warning::
|
||||||
|
|
||||||
Creating two concurrent `scoped_interpreter` guards is a fatal error. So is
|
Creating two concurrent ``scoped_interpreter`` guards is a fatal error. So is
|
||||||
calling `initialize_interpreter` for a second time after the interpreter
|
calling ``initialize_interpreter`` for a second time after the interpreter
|
||||||
has already been initialized.
|
has already been initialized.
|
||||||
|
|
||||||
Do not use the raw CPython API functions ``Py_Initialize`` and
|
Do not use the raw CPython API functions ``Py_Initialize`` and
|
||||||
@ -242,7 +242,7 @@ global data. All the details can be found in the CPython documentation.
|
|||||||
Sub-interpreter support
|
Sub-interpreter support
|
||||||
=======================
|
=======================
|
||||||
|
|
||||||
Creating multiple copies of `scoped_interpreter` is not possible because it
|
Creating multiple copies of ``scoped_interpreter`` is not possible because it
|
||||||
represents the main Python interpreter. Sub-interpreters are something different
|
represents the main Python interpreter. Sub-interpreters are something different
|
||||||
and they do permit the existence of multiple interpreters. This is an advanced
|
and they do permit the existence of multiple interpreters. This is an advanced
|
||||||
feature of the CPython API and should be handled with care. pybind11 does not
|
feature of the CPython API and should be handled with care. pybind11 does not
|
||||||
@ -258,5 +258,5 @@ We'll just mention a couple of caveats the sub-interpreters support in pybind11:
|
|||||||
2. Managing multiple threads, multiple interpreters and the GIL can be
|
2. Managing multiple threads, multiple interpreters and the GIL can be
|
||||||
challenging and there are several caveats here, even within the pure
|
challenging and there are several caveats here, even within the pure
|
||||||
CPython API (please refer to the Python docs for details). As for
|
CPython API (please refer to the Python docs for details). As for
|
||||||
pybind11, keep in mind that `gil_scoped_release` and `gil_scoped_acquire`
|
pybind11, keep in mind that ``gil_scoped_release`` and ``gil_scoped_acquire``
|
||||||
do not take sub-interpreters into account.
|
do not take sub-interpreters into account.
|
||||||
|
@ -96,18 +96,18 @@ A matching function is available for registering a local exception translator:
|
|||||||
|
|
||||||
|
|
||||||
It is possible to specify base class for the exception using the third
|
It is possible to specify base class for the exception using the third
|
||||||
parameter, a `handle`:
|
parameter, a ``handle``:
|
||||||
|
|
||||||
.. code-block:: cpp
|
.. code-block:: cpp
|
||||||
|
|
||||||
py::register_exception<CppExp>(module, "PyExp", PyExc_RuntimeError);
|
py::register_exception<CppExp>(module, "PyExp", PyExc_RuntimeError);
|
||||||
py::register_local_exception<CppExp>(module, "PyExp", PyExc_RuntimeError);
|
py::register_local_exception<CppExp>(module, "PyExp", PyExc_RuntimeError);
|
||||||
|
|
||||||
Then `PyExp` can be caught both as `PyExp` and `RuntimeError`.
|
Then ``PyExp`` can be caught both as ``PyExp`` and ``RuntimeError``.
|
||||||
|
|
||||||
The class objects of the built-in Python exceptions are listed in the Python
|
The class objects of the built-in Python exceptions are listed in the Python
|
||||||
documentation on `Standard Exceptions <https://docs.python.org/3/c-api/exceptions.html#standard-exceptions>`_.
|
documentation on `Standard Exceptions <https://docs.python.org/3/c-api/exceptions.html#standard-exceptions>`_.
|
||||||
The default base class is `PyExc_Exception`.
|
The default base class is ``PyExc_Exception``.
|
||||||
|
|
||||||
When more advanced exception translation is needed, the functions
|
When more advanced exception translation is needed, the functions
|
||||||
``py::register_exception_translator(translator)`` and
|
``py::register_exception_translator(translator)`` and
|
||||||
|
@ -232,7 +232,7 @@ is equivalent to the following pseudocode:
|
|||||||
});
|
});
|
||||||
|
|
||||||
The only requirement is that ``T`` is default-constructible, but otherwise any
|
The only requirement is that ``T`` is default-constructible, but otherwise any
|
||||||
scope guard will work. This is very useful in combination with `gil_scoped_release`.
|
scope guard will work. This is very useful in combination with ``gil_scoped_release``.
|
||||||
See :ref:`gil`.
|
See :ref:`gil`.
|
||||||
|
|
||||||
Multiple guards can also be specified as ``py::call_guard<T1, T2, T3...>``. The
|
Multiple guards can also be specified as ``py::call_guard<T1, T2, T3...>``. The
|
||||||
|
@ -84,7 +84,7 @@ could be realized as follows (important changes highlighted):
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
The ``call_go`` wrapper can also be simplified using the `call_guard` policy
|
The ``call_go`` wrapper can also be simplified using the ``call_guard`` policy
|
||||||
(see :ref:`call_policies`) which yields the same result:
|
(see :ref:`call_policies`) which yields the same result:
|
||||||
|
|
||||||
.. code-block:: cpp
|
.. code-block:: cpp
|
||||||
|
@ -28,7 +28,7 @@ Capturing standard output from ostream
|
|||||||
|
|
||||||
Often, a library will use the streams ``std::cout`` and ``std::cerr`` to print,
|
Often, a library will use the streams ``std::cout`` and ``std::cerr`` to print,
|
||||||
but this does not play well with Python's standard ``sys.stdout`` and ``sys.stderr``
|
but this does not play well with Python's standard ``sys.stdout`` and ``sys.stderr``
|
||||||
redirection. Replacing a library's printing with `py::print <print>` may not
|
redirection. Replacing a library's printing with ``py::print <print>`` may not
|
||||||
be feasible. This can be fixed using a guard around the library function that
|
be feasible. This can be fixed using a guard around the library function that
|
||||||
redirects output to the corresponding Python streams:
|
redirects output to the corresponding Python streams:
|
||||||
|
|
||||||
@ -62,9 +62,9 @@ This method respects flushes on the output streams and will flush if needed
|
|||||||
when the scoped guard is destroyed. This allows the output to be redirected in
|
when the scoped guard is destroyed. This allows the output to be redirected in
|
||||||
real time, such as to a Jupyter notebook. The two arguments, the C++ stream and
|
real time, such as to a Jupyter notebook. The two arguments, the C++ stream and
|
||||||
the Python output, are optional, and default to standard output if not given. An
|
the Python output, are optional, and default to standard output if not given. An
|
||||||
extra type, `py::scoped_estream_redirect <scoped_estream_redirect>`, is identical
|
extra type, ``py::scoped_estream_redirect <scoped_estream_redirect>``, is identical
|
||||||
except for defaulting to ``std::cerr`` and ``sys.stderr``; this can be useful with
|
except for defaulting to ``std::cerr`` and ``sys.stderr``; this can be useful with
|
||||||
`py::call_guard`, which allows multiple items, but uses the default constructor:
|
``py::call_guard``, which allows multiple items, but uses the default constructor:
|
||||||
|
|
||||||
.. code-block:: cpp
|
.. code-block:: cpp
|
||||||
|
|
||||||
@ -74,7 +74,7 @@ except for defaulting to ``std::cerr`` and ``sys.stderr``; this can be useful wi
|
|||||||
py::scoped_estream_redirect>());
|
py::scoped_estream_redirect>());
|
||||||
|
|
||||||
The redirection can also be done in Python with the addition of a context
|
The redirection can also be done in Python with the addition of a context
|
||||||
manager, using the `py::add_ostream_redirect() <add_ostream_redirect>` function:
|
manager, using the ``py::add_ostream_redirect() <add_ostream_redirect>`` function:
|
||||||
|
|
||||||
.. code-block:: cpp
|
.. code-block:: cpp
|
||||||
|
|
||||||
@ -103,7 +103,7 @@ arguments to disable one of the streams if needed.
|
|||||||
Evaluating Python expressions from strings and files
|
Evaluating Python expressions from strings and files
|
||||||
====================================================
|
====================================================
|
||||||
|
|
||||||
pybind11 provides the `eval`, `exec` and `eval_file` functions to evaluate
|
pybind11 provides the ``eval``, ``exec`` and ``eval_file`` functions to evaluate
|
||||||
Python expressions and statements. The following example illustrates how they
|
Python expressions and statements. The following example illustrates how they
|
||||||
can be used.
|
can be used.
|
||||||
|
|
||||||
|
@ -53,9 +53,10 @@ New features:
|
|||||||
`#3293 <https://github.com/pybind/pybind11/pull/3293>`_
|
`#3293 <https://github.com/pybind/pybind11/pull/3293>`_
|
||||||
|
|
||||||
* Improve the classes generated by ``bind_map``: `#3310 <https://github.com/pybind/pybind11/pull/3310>`_
|
* Improve the classes generated by ``bind_map``: `#3310 <https://github.com/pybind/pybind11/pull/3310>`_
|
||||||
* Change ``.items`` from an iterator to a dictionary view.
|
|
||||||
* Add ``.keys`` and ``.values`` (both dictionary views).
|
* Change ``.items`` from an iterator to a dictionary view.
|
||||||
* Allow ``__contains__`` to take any object.
|
* Add ``.keys`` and ``.values`` (both dictionary views).
|
||||||
|
* Allow ``__contains__`` to take any object.
|
||||||
|
|
||||||
* ``pybind11::custom_type_setup`` was added, for customizing the
|
* ``pybind11::custom_type_setup`` was added, for customizing the
|
||||||
``PyHeapTypeObject`` corresponding to a class, which may be useful for
|
``PyHeapTypeObject`` corresponding to a class, which may be useful for
|
||||||
@ -250,8 +251,8 @@ New features:
|
|||||||
|
|
||||||
Changes:
|
Changes:
|
||||||
|
|
||||||
* ``py::str`` changed to exclusively hold `PyUnicodeObject`. Previously
|
* ``py::str`` changed to exclusively hold ``PyUnicodeObject``. Previously
|
||||||
``py::str`` could also hold `bytes`, which is probably surprising, was
|
``py::str`` could also hold ``bytes``, which is probably surprising, was
|
||||||
never documented, and can mask bugs (e.g. accidental use of ``py::str``
|
never documented, and can mask bugs (e.g. accidental use of ``py::str``
|
||||||
instead of ``py::bytes``).
|
instead of ``py::bytes``).
|
||||||
`#2409 <https://github.com/pybind/pybind11/pull/2409>`_
|
`#2409 <https://github.com/pybind/pybind11/pull/2409>`_
|
||||||
@ -1404,7 +1405,7 @@ v2.2.0 (August 31, 2017)
|
|||||||
* Intel C++ compiler compatibility fixes.
|
* Intel C++ compiler compatibility fixes.
|
||||||
`#937 <https://github.com/pybind/pybind11/pull/937>`_.
|
`#937 <https://github.com/pybind/pybind11/pull/937>`_.
|
||||||
|
|
||||||
* Fixed implicit conversion of `py::enum_` to integer types on Python 2.7.
|
* Fixed implicit conversion of ``py::enum_`` to integer types on Python 2.7.
|
||||||
`#821 <https://github.com/pybind/pybind11/pull/821>`_.
|
`#821 <https://github.com/pybind/pybind11/pull/821>`_.
|
||||||
|
|
||||||
* Added ``py::hash`` to fetch the hash value of Python objects, and
|
* Added ``py::hash`` to fetch the hash value of Python objects, and
|
||||||
|
@ -17,9 +17,23 @@
|
|||||||
|
|
||||||
#include "numpy.h"
|
#include "numpy.h"
|
||||||
|
|
||||||
|
// The C4127 suppression was introduced for Eigen 3.4.0. In theory we could
|
||||||
|
// make it version specific, or even remove it later, but considering that
|
||||||
|
// 1. C4127 is generally far more distracting than useful for modern template code, and
|
||||||
|
// 2. we definitely want to ignore any MSVC warnings originating from Eigen code,
|
||||||
|
// it is probably best to keep this around indefinitely.
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
# pragma warning(push)
|
||||||
|
# pragma warning(disable: 4127) // C4127: conditional expression is constant
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <Eigen/Core>
|
#include <Eigen/Core>
|
||||||
#include <Eigen/SparseCore>
|
#include <Eigen/SparseCore>
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
# pragma warning(pop)
|
||||||
|
#endif
|
||||||
|
|
||||||
// Eigen prior to 3.2.7 doesn't have proper move constructors--but worse, some classes get implicit
|
// Eigen prior to 3.2.7 doesn't have proper move constructors--but worse, some classes get implicit
|
||||||
// move constructors that break things. We could detect this an explicitly copy, but an extra copy
|
// move constructors that break things. We could detect this an explicitly copy, but an extra copy
|
||||||
// of matrices seems highly undesirable.
|
// of matrices seems highly undesirable.
|
||||||
@ -559,7 +573,9 @@ struct type_caster<Type, enable_if_t<is_eigen_sparse<Type>::value>> {
|
|||||||
if (!values || !innerIndices || !outerIndices)
|
if (!values || !innerIndices || !outerIndices)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
value = Eigen::MappedSparseMatrix<Scalar, Type::Flags, StorageIndex>(
|
value = Eigen::MappedSparseMatrix<Scalar,
|
||||||
|
Type::Flags & (Eigen::RowMajor | Eigen::ColMajor),
|
||||||
|
StorageIndex>(
|
||||||
shape[0].cast<Index>(), shape[1].cast<Index>(), nnz,
|
shape[0].cast<Index>(), shape[1].cast<Index>(), nnz,
|
||||||
outerIndices.mutable_data(), innerIndices.mutable_data(), values.mutable_data());
|
outerIndices.mutable_data(), innerIndices.mutable_data(), values.mutable_data());
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
pybind11/exec.h: Support for evaluating Python expressions and statements
|
pybind11/eval.h: Support for evaluating Python expressions and statements
|
||||||
from strings and files
|
from strings and files
|
||||||
|
|
||||||
Copyright (c) 2016 Klemens Morgenstern <klemens.morgenstern@ed-chemnitz.de> and
|
Copyright (c) 2016 Klemens Morgenstern <klemens.morgenstern@ed-chemnitz.de> and
|
||||||
|
@ -2081,29 +2081,54 @@ struct iterator_state {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Note: these helpers take the iterator by non-const reference because some
|
// Note: these helpers take the iterator by non-const reference because some
|
||||||
// iterators in the wild can't be dereferenced when const. C++ needs the extra parens in decltype
|
// iterators in the wild can't be dereferenced when const. The & after Iterator
|
||||||
// to enforce an lvalue. The & after Iterator is required for MSVC < 16.9. SFINAE cannot be
|
// is required for MSVC < 16.9. SFINAE cannot be reused for result_type due to
|
||||||
// reused for result_type due to bugs in ICC, NVCC, and PGI compilers. See PR #3293.
|
// bugs in ICC, NVCC, and PGI compilers. See PR #3293.
|
||||||
template <typename Iterator, typename SFINAE = decltype((*std::declval<Iterator &>()))>
|
template <typename Iterator, typename SFINAE = decltype(*std::declval<Iterator &>())>
|
||||||
struct iterator_access {
|
struct iterator_access {
|
||||||
using result_type = decltype((*std::declval<Iterator &>()));
|
using result_type = decltype(*std::declval<Iterator &>());
|
||||||
// NOLINTNEXTLINE(readability-const-return-type) // PR #3263
|
// NOLINTNEXTLINE(readability-const-return-type) // PR #3263
|
||||||
result_type operator()(Iterator &it) const {
|
result_type operator()(Iterator &it) const {
|
||||||
return *it;
|
return *it;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Iterator, typename SFINAE = decltype(((*std::declval<Iterator &>()).first)) >
|
template <typename Iterator, typename SFINAE = decltype((*std::declval<Iterator &>()).first) >
|
||||||
struct iterator_key_access {
|
class iterator_key_access {
|
||||||
using result_type = decltype(((*std::declval<Iterator &>()).first));
|
private:
|
||||||
|
using pair_type = decltype(*std::declval<Iterator &>());
|
||||||
|
|
||||||
|
public:
|
||||||
|
/* If either the pair itself or the element of the pair is a reference, we
|
||||||
|
* want to return a reference, otherwise a value. When the decltype
|
||||||
|
* expression is parenthesized it is based on the value category of the
|
||||||
|
* expression; otherwise it is the declared type of the pair member.
|
||||||
|
* The use of declval<pair_type> in the second branch rather than directly
|
||||||
|
* using *std::declval<Iterator &>() is a workaround for nvcc
|
||||||
|
* (it's not used in the first branch because going via decltype and back
|
||||||
|
* through declval does not perfectly preserve references).
|
||||||
|
*/
|
||||||
|
using result_type = conditional_t<
|
||||||
|
std::is_reference<decltype(*std::declval<Iterator &>())>::value,
|
||||||
|
decltype(((*std::declval<Iterator &>()).first)),
|
||||||
|
decltype(std::declval<pair_type>().first)
|
||||||
|
>;
|
||||||
result_type operator()(Iterator &it) const {
|
result_type operator()(Iterator &it) const {
|
||||||
return (*it).first;
|
return (*it).first;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Iterator, typename SFINAE = decltype(((*std::declval<Iterator &>()).second))>
|
template <typename Iterator, typename SFINAE = decltype((*std::declval<Iterator &>()).second)>
|
||||||
struct iterator_value_access {
|
class iterator_value_access {
|
||||||
using result_type = decltype(((*std::declval<Iterator &>()).second));
|
private:
|
||||||
|
using pair_type = decltype(*std::declval<Iterator &>());
|
||||||
|
|
||||||
|
public:
|
||||||
|
using result_type = conditional_t<
|
||||||
|
std::is_reference<decltype(*std::declval<Iterator &>())>::value,
|
||||||
|
decltype(((*std::declval<Iterator &>()).second)),
|
||||||
|
decltype(std::declval<pair_type>().second)
|
||||||
|
>;
|
||||||
result_type operator()(Iterator &it) const {
|
result_type operator()(Iterator &it) const {
|
||||||
return (*it).second;
|
return (*it).second;
|
||||||
}
|
}
|
||||||
|
@ -192,9 +192,9 @@ set(PYBIND11_CLASS_SH_MODULE_LOCAL_TESTS test_class_sh_module_local.py)
|
|||||||
set(PYBIND11_EIGEN_REPO
|
set(PYBIND11_EIGEN_REPO
|
||||||
"https://gitlab.com/libeigen/eigen.git"
|
"https://gitlab.com/libeigen/eigen.git"
|
||||||
CACHE STRING "Eigen repository to use for tests")
|
CACHE STRING "Eigen repository to use for tests")
|
||||||
# This hash is for 3.3.8, using a hash for security reasons
|
# This hash is for 3.4.0, using a hash for security reasons
|
||||||
set(PYBIND11_EIGEN_VERSION
|
set(PYBIND11_EIGEN_VERSION
|
||||||
"dc252fbf00079ccab57948a164b1421703fe4361"
|
"929bc0e191d0927b1735b9a1ddc0e8b77e3a25ec"
|
||||||
CACHE STRING "Eigen version to use for tests")
|
CACHE STRING "Eigen version to use for tests")
|
||||||
|
|
||||||
# Check if Eigen is available; if not, remove from PYBIND11_TEST_FILES (but
|
# Check if Eigen is available; if not, remove from PYBIND11_TEST_FILES (but
|
||||||
|
@ -5,7 +5,7 @@ import struct
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
import env # noqa: F401
|
import env
|
||||||
from pybind11_tests import ConstructorStats
|
from pybind11_tests import ConstructorStats
|
||||||
from pybind11_tests import buffers as m
|
from pybind11_tests import buffers as m
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
import env # noqa: F401
|
import env
|
||||||
from pybind11_tests import IncType, UserType
|
from pybind11_tests import IncType, UserType
|
||||||
from pybind11_tests import builtin_casters as m
|
from pybind11_tests import builtin_casters as m
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ from threading import Thread
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
import env # NOQA: F401
|
import env # noqa: F401
|
||||||
from pybind11_tests import callbacks as m
|
from pybind11_tests import callbacks as m
|
||||||
|
|
||||||
|
|
||||||
|
@ -13,6 +13,9 @@
|
|||||||
#include <pybind11/stl.h>
|
#include <pybind11/stl.h>
|
||||||
|
|
||||||
#if defined(_MSC_VER)
|
#if defined(_MSC_VER)
|
||||||
|
#if _MSC_VER < 1910 // VS 2015's MSVC
|
||||||
|
# pragma warning(disable: 4127) // C4127: conditional expression is constant
|
||||||
|
#endif
|
||||||
# pragma warning(disable: 4996) // C4996: std::unary_negation is deprecated
|
# pragma warning(disable: 4996) // C4996: std::unary_negation is deprecated
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -96,13 +96,13 @@ Members:
|
|||||||
y >= object() # noqa: B015
|
y >= object() # noqa: B015
|
||||||
|
|
||||||
with pytest.raises(TypeError):
|
with pytest.raises(TypeError):
|
||||||
y | object() # noqa: B015
|
y | object()
|
||||||
|
|
||||||
with pytest.raises(TypeError):
|
with pytest.raises(TypeError):
|
||||||
y & object() # noqa: B015
|
y & object()
|
||||||
|
|
||||||
with pytest.raises(TypeError):
|
with pytest.raises(TypeError):
|
||||||
y ^ object() # noqa: B015
|
y ^ object()
|
||||||
|
|
||||||
assert int(m.UnscopedEnum.ETwo) == 2
|
assert int(m.UnscopedEnum.ETwo) == 2
|
||||||
assert str(m.UnscopedEnum(2)) == "UnscopedEnum.ETwo"
|
assert str(m.UnscopedEnum(2)) == "UnscopedEnum.ETwo"
|
||||||
|
@ -102,7 +102,7 @@ def test_properties():
|
|||||||
assert instance.def_property == 3
|
assert instance.def_property == 3
|
||||||
|
|
||||||
with pytest.raises(AttributeError) as excinfo:
|
with pytest.raises(AttributeError) as excinfo:
|
||||||
dummy = instance.def_property_writeonly # noqa: F841 unused var
|
dummy = instance.def_property_writeonly # unused var
|
||||||
assert "unreadable attribute" in str(excinfo.value)
|
assert "unreadable attribute" in str(excinfo.value)
|
||||||
|
|
||||||
instance.def_property_writeonly = 4
|
instance.def_property_writeonly = 4
|
||||||
@ -127,7 +127,7 @@ def test_static_properties():
|
|||||||
assert m.TestProperties.def_readwrite_static == 2
|
assert m.TestProperties.def_readwrite_static == 2
|
||||||
|
|
||||||
with pytest.raises(AttributeError) as excinfo:
|
with pytest.raises(AttributeError) as excinfo:
|
||||||
dummy = m.TestProperties.def_writeonly_static # noqa: F841 unused var
|
dummy = m.TestProperties.def_writeonly_static # unused var
|
||||||
assert "unreadable attribute" in str(excinfo.value)
|
assert "unreadable attribute" in str(excinfo.value)
|
||||||
|
|
||||||
m.TestProperties.def_writeonly_static = 3
|
m.TestProperties.def_writeonly_static = 3
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
import env # noqa: F401
|
import env
|
||||||
from pybind11_tests import pickling as m
|
from pybind11_tests import pickling as m
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -5,7 +5,7 @@ import sys
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
import env # noqa: F401
|
import env
|
||||||
from pybind11_tests import debug_enabled
|
from pybind11_tests import debug_enabled
|
||||||
from pybind11_tests import pytypes as m
|
from pybind11_tests import pytypes as m
|
||||||
|
|
||||||
@ -610,7 +610,7 @@ def test_weakref(create_weakref, create_weakref_with_callback):
|
|||||||
|
|
||||||
obj = WeaklyReferenced()
|
obj = WeaklyReferenced()
|
||||||
assert getweakrefcount(obj) == 0
|
assert getweakrefcount(obj) == 0
|
||||||
wr = create_weakref(obj) # noqa: F841
|
wr = create_weakref(obj)
|
||||||
assert getweakrefcount(obj) == 1
|
assert getweakrefcount(obj) == 1
|
||||||
|
|
||||||
obj = WeaklyReferenced()
|
obj = WeaklyReferenced()
|
||||||
|
@ -38,6 +38,17 @@ bool operator==(const NonZeroIterator<std::pair<A, B>>& it, const NonZeroSentine
|
|||||||
return !(*it).first || !(*it).second;
|
return !(*it).first || !(*it).second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Iterator where dereferencing returns prvalues instead of references. */
|
||||||
|
template<typename T>
|
||||||
|
class NonRefIterator {
|
||||||
|
const T* ptr_;
|
||||||
|
public:
|
||||||
|
explicit NonRefIterator(const T *ptr) : ptr_(ptr) {}
|
||||||
|
T operator*() const { return T(*ptr_); }
|
||||||
|
NonRefIterator& operator++() { ++ptr_; return *this; }
|
||||||
|
bool operator==(const NonRefIterator &other) const { return ptr_ == other.ptr_; }
|
||||||
|
};
|
||||||
|
|
||||||
class NonCopyableInt {
|
class NonCopyableInt {
|
||||||
public:
|
public:
|
||||||
explicit NonCopyableInt(int value) : value_(value) {}
|
explicit NonCopyableInt(int value) : value_(value) {}
|
||||||
@ -331,7 +342,7 @@ TEST_SUBMODULE(sequences_and_iterators, m) {
|
|||||||
py::class_<IntPairs>(m, "IntPairs")
|
py::class_<IntPairs>(m, "IntPairs")
|
||||||
.def(py::init<std::vector<std::pair<int, int>>>())
|
.def(py::init<std::vector<std::pair<int, int>>>())
|
||||||
.def("nonzero", [](const IntPairs& s) {
|
.def("nonzero", [](const IntPairs& s) {
|
||||||
return py::make_iterator(NonZeroIterator<std::pair<int, int>>(s.begin()), NonZeroSentinel());
|
return py::make_iterator(NonZeroIterator<std::pair<int, int>>(s.begin()), NonZeroSentinel());
|
||||||
}, py::keep_alive<0, 1>())
|
}, py::keep_alive<0, 1>())
|
||||||
.def("nonzero_keys", [](const IntPairs& s) {
|
.def("nonzero_keys", [](const IntPairs& s) {
|
||||||
return py::make_key_iterator(NonZeroIterator<std::pair<int, int>>(s.begin()), NonZeroSentinel());
|
return py::make_key_iterator(NonZeroIterator<std::pair<int, int>>(s.begin()), NonZeroSentinel());
|
||||||
@ -340,6 +351,20 @@ TEST_SUBMODULE(sequences_and_iterators, m) {
|
|||||||
return py::make_value_iterator(NonZeroIterator<std::pair<int, int>>(s.begin()), NonZeroSentinel());
|
return py::make_value_iterator(NonZeroIterator<std::pair<int, int>>(s.begin()), NonZeroSentinel());
|
||||||
}, py::keep_alive<0, 1>())
|
}, py::keep_alive<0, 1>())
|
||||||
|
|
||||||
|
// test iterator that returns values instead of references
|
||||||
|
.def("nonref", [](const IntPairs& s) {
|
||||||
|
return py::make_iterator(NonRefIterator<std::pair<int, int>>(s.begin()),
|
||||||
|
NonRefIterator<std::pair<int, int>>(s.end()));
|
||||||
|
}, py::keep_alive<0, 1>())
|
||||||
|
.def("nonref_keys", [](const IntPairs& s) {
|
||||||
|
return py::make_key_iterator(NonRefIterator<std::pair<int, int>>(s.begin()),
|
||||||
|
NonRefIterator<std::pair<int, int>>(s.end()));
|
||||||
|
}, py::keep_alive<0, 1>())
|
||||||
|
.def("nonref_values", [](const IntPairs& s) {
|
||||||
|
return py::make_value_iterator(NonRefIterator<std::pair<int, int>>(s.begin()),
|
||||||
|
NonRefIterator<std::pair<int, int>>(s.end()));
|
||||||
|
}, py::keep_alive<0, 1>())
|
||||||
|
|
||||||
// test single-argument make_iterator
|
// test single-argument make_iterator
|
||||||
.def("simple_iterator", [](IntPairs& self) {
|
.def("simple_iterator", [](IntPairs& self) {
|
||||||
return py::make_iterator(self);
|
return py::make_iterator(self);
|
||||||
|
@ -52,6 +52,13 @@ def test_generalized_iterators():
|
|||||||
next(it)
|
next(it)
|
||||||
|
|
||||||
|
|
||||||
|
def test_nonref_iterators():
|
||||||
|
pairs = m.IntPairs([(1, 2), (3, 4), (0, 5)])
|
||||||
|
assert list(pairs.nonref()) == [(1, 2), (3, 4), (0, 5)]
|
||||||
|
assert list(pairs.nonref_keys()) == [1, 3, 0]
|
||||||
|
assert list(pairs.nonref_values()) == [2, 4, 5]
|
||||||
|
|
||||||
|
|
||||||
def test_generalized_iterators_simple():
|
def test_generalized_iterators_simple():
|
||||||
assert list(m.IntPairs([(1, 2), (3, 4), (0, 5)]).simple_iterator()) == [
|
assert list(m.IntPairs([(1, 2), (3, 4), (0, 5)]).simple_iterator()) == [
|
||||||
(1, 2),
|
(1, 2),
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
import env # noqa: F401
|
import env
|
||||||
from pybind11_tests import stl_binders as m
|
from pybind11_tests import stl_binders as m
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user