1. 02 Jun, 2022 1 commit
    • Sergei Lebedev's avatar
      error_already_set::what() is now constructed lazily (#1895) · a05bc3d2
      Sergei Lebedev authored
      * error_already_set::what() is now constructed lazily
      
      Prior to this commit throwing error_already_set was expensive due to the
      eager construction of the error string (which required traversing the
      Python stack). See #1853 for more context and an alternative take on the
      issue.
      
      Note that error_already_set no longer inherits from std::runtime_error
      because the latter has no default constructor.
      
      * Do not attempt to normalize if no exception occurred
      
      This is not supported on PyPy-2.7 5.8.0.
      
      * Extract exception name via tp_name
      
      This is faster than dynamically looking up __name__ via GetAttrString.
      Note though that the runtime of the code throwing an error_already_set
      will be dominated by stack unwinding so the improvement will not be
      noticeable.
      
      Before:
      
      396 ns ± 0.913 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
      
      After:
      
      277 ns ± 0.549 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
      
      Benchmark:
      
      const std::string foo() {
          PyErr_SetString(PyExc_KeyError, "");
          const std::string &s = py::detail::error_string();
          PyErr_Clear();
          return s;
      }
      
      PYBIND11_MODULE(foo, m) {
          m.def("foo", &::foo);
      }
      
      * Reverted error_already_set to subclass std::runtime_error
      
      * Revert "Extract exception name via tp_name"
      
      The implementation of __name__ is slightly more complex than that.
      It handles the module name prefix, and heap-allocated types. We could
      port it to pybind11 later on but for now it seems like an overkill.
      
      This reverts commit f1435c7e6b068a1ed13ebd3db597ea3bb15aa398.
      
      * Cosmit following @YannickJadoul's comments
      
      Note that detail::error_string() no longer calls PyException_SetTraceback
      as it is unncessary for pretty-printing the exception.
      
      * Fixed PyPy build
      
      * Moved normalization to error_already_set ctor
      
      * Fix merge bugs
      
      * Fix more merge errors
      
      * Improve formatting
      
      * Improve error message in rare case
      
      * Revert back if statements
      
      * Fix clang-tidy
      
      * Try removing mutable
      
      * Does build_mode release fix it
      
      * Set to Debug to expose segfault
      
      * Fix remove set error string
      
      * Do not run error_string() more than once
      
      * Trying setting the tracebackk to the value
      
      * guard if m_type is null
      
      * Try to debug PGI
      
      * One last try for PGI
      
      * Does reverting this fix PyPy
      
      * Reviewer suggestions
      
      * Remove unnecessary initialization
      
      * Add noexcept move and explicit fail throw
      
      * Optimize error_string creation
      
      * Fix typo
      
      * Revert noexcept
      
      * Fix merge conflict error
      
      * Abuse assignment operator
      
      * Revert operator abuse
      
      * See if we still need debug
      
      * Remove unnecessary mutable
      
      * Report "FATAL failure building pybind11::error_already_set error_string" and terminate process.
      
      * Try specifying noexcept again
      
      * Try explicit ctor
      
      * default ctor is noexcept too
      
      * Apply reviewer suggestions, simplify code, and make helper method private
      
      * Remove unnecessary include
      
      * Clang-Tidy fix
      
      * detail::obj_class_name(), fprintf with [STDERR], [STDOUT] tags, polish comments
      
      * consistently check m_lazy_what.empty() also in production builds
      
      * Make a comment slightly less ambiguous.
      
      * Bug fix: Remove `what();` from `restore()`.
      
      It sure would need to be guarded by `if (m_type)`, otherwise `what()` fails and masks that no error was set (see update unit test). But since `error_already_set` is copyable, there is no point in releasing m_type, m_value, m_trace, therefore we can just as well avoid the runtime overhead of force-building `m_lazy_what`, it may never be used.
      
      * Replace extremely opaque (unhelpful) error message with a truthful reflection of what we know.
      
      * Fix clang-tidy error [performance-move-constructor-init].
      
      * Make expected error message less specific.
      
      * Various changes.
      
      * bug fix: error_string(PyObject **, ...)
      
      * Putting back the two eager PyErr_NormalizeException() calls.
      
      * Change error_already_set() to call pybind11_fail() if the Python error indicator not set. The net result is that a std::runtime_error is thrown instead of error_already_set, but all tests pass as is.
      
      * Remove mutable (fixes oversight in the previous commit).
      
      * Normalize the exception only locally in error_string(). Python 3.6 & 3.7 test failures expected. This is meant for benchmarking, to determine if it is worth the trouble looking into the failures.
      
      * clang-tidy: use auto
      
      * Use `gil_scoped_acquire_local` in `error_already_set` destructor. See long comment.
      
      * For Python < 3.8: `PyErr_NormalizeException` before `PyErr_WriteUnraisable`
      
      * Go back to replacing the held Python exception with then normalized exception, if & when needed. Consistently document the side-effect.
      
      * Slightly rewording comment. (There were also other failures.)
      
      * Add 1-line comment for obj_class_name()
      
      * Benchmark code, with results in this commit message.
      
                function                   #calls  test time [s]  μs / call
      master    pure_unwind                729540      1.061      14.539876
                err_set_unwind_err_clear   681476      1.040      15.260282
                err_set_error_already_set  508038      1.049      20.640525
                error_already_set_restore  555578      1.052      18.933288
                pr1895_original_foo        244113      1.050      43.018168
                                                                             PR / master
      PR #1895  pure_unwind                736981      1.054      14.295685       98.32%
                err_set_unwind_err_clear   685820      1.045      15.237399       99.85%
                err_set_error_already_set  661374      1.046      15.811879       76.61%
                error_already_set_restore  669881      1.048      15.645176       82.63%
                pr1895_original_foo        318243      1.059      33.290806       77.39%
      
      master @ commit ad146b2a
      
      Running tests in directory "/usr/local/google/home/rwgk/forked/pybind11/tests":
      ============================= test session starts ==============================
      platform linux -- Python 3.9.10, pytest-6.2.3, py-1.10.0, pluggy-0.13.1 -- /usr/bin/python3
      cachedir: .pytest_cache
      rootdir: /usr/local/google/home/rwgk/forked/pybind11/tests, configfile: pytest.ini
      collecting ... collected 5 items
      
      test_perf_error_already_set.py::test_perf[pure_unwind]
      PERF pure_unwind,729540,1.061,14.539876
      PASSED
      test_perf_error_already_set.py::test_perf[err_set_unwind_err_clear]
      PERF err_set_unwind_err_clear,681476,1.040,15.260282
      PASSED
      test_perf_error_already_set.py::test_perf[err_set_error_already_set]
      PERF err_set_error_already_set,508038,1.049,20.640525
      PASSED
      test_perf_error_already_set.py::test_perf[error_already_set_restore]
      PERF error_already_set_restore,555578,1.052,18.933288
      PASSED
      test_perf_error_already_set.py::test_perf[pr1895_original_foo]
      PERF pr1895_original_foo,244113,1.050,43.018168
      PASSED
      
      ============================== 5 passed in 12.38s ==============================
      
      pr1895 @ commit 8dff51d12e4af11aff415ee966070368fe606664
      
      Running tests in directory "/usr/local/google/home/rwgk/forked/pybind11/tests":
      ============================= test session starts ==============================
      platform linux -- Python 3.9.10, pytest-6.2.3, py-1.10.0, pluggy-0.13.1 -- /usr/bin/python3
      cachedir: .pytest_cache
      rootdir: /usr/local/google/home/rwgk/forked/pybind11/tests, configfile: pytest.ini
      collecting ... collected 5 items
      
      test_perf_error_already_set.py::test_perf[pure_unwind]
      PERF pure_unwind,736981,1.054,14.295685
      PASSED
      test_perf_error_already_set.py::test_perf[err_set_unwind_err_clear]
      PERF err_set_unwind_err_clear,685820,1.045,15.237399
      PASSED
      test_perf_error_already_set.py::test_perf[err_set_error_already_set]
      PERF err_set_error_already_set,661374,1.046,15.811879
      PASSED
      test_perf_error_already_set.py::test_perf[error_already_set_restore]
      PERF error_already_set_restore,669881,1.048,15.645176
      PASSED
      test_perf_error_already_set.py::test_perf[pr1895_original_foo]
      PERF pr1895_original_foo,318243,1.059,33.290806
      PASSED
      
      ============================== 5 passed in 12.40s ==============================
      
      clang++ -o pybind11/tests/test_perf_error_already_set.os -c -std=c++17 -fPIC -fvisibility=hidden -Os -flto -Wall -Wextra -Wconversion -Wcast-qual -Wdeprecated -Wnon-virtual-dtor -Wunused-result -isystem /usr/include/python3.9 -isystem /usr/include/eigen3 -DPYBIND11_STRICT_ASSERTS_CLASS_HOLDER_VS_TYPE_CASTER_MIX -DPYBIND11_TEST_BOOST -Ipybind11/include -I/usr/local/google/home/rwgk/forked/pybind11/include -I/usr/local/google/home/rwgk/clone/pybind11/include /usr/local/google/home/rwgk/forked/pybind11/tests/test_perf_error_already_set.cpp
      
      clang++ -o lib/pybind11_tests.so -shared -fPIC -Os -flto -shared ...
      
      Debian clang version 13.0.1-3+build2
      Target: x86_64-pc-linux-gnu
      Thread model: posix
      
      * Changing call_repetitions_target_elapsed_secs to 0.1 for regular unit testing.
      
      * Adding in `recursion_depth`
      
      * Optimized ctor
      
      * Fix silly bug in recurse_first_then_call()
      
      * Add tests that have equivalent PyErr_Fetch(), PyErr_Restore() but no try-catch.
      
      * Add call_error_string to tests. Sample only recursion_depth 0, 100.
      
      * Show lazy-what speed-up in percent.
      
      * Include real_work in benchmarks.
      
      * Replace all PyErr_SetString() with generate_python_exception_with_traceback()
      
      * Better organization of test loops.
      
      * Add test_error_already_set_copy_move
      
      * Fix bug in newly added test (discovered by clang-tidy): actually use move ctor
      
      * MSVC detects the unreachable return
      
      * change test_perf_error_already_set.py back to quick mode
      
      * Inherit from std::exception (instead of std::runtime_error, which does not make sense anymore with the lazy what)
      
      * Special handling under Windows.
      
      * print with leading newline
      
      * Removing test_perf_error_already_set (copies are under https://github.com/rwgk/rwgk_tbx/commit/7765113fbb659e1ea004c5ba24fb578244bc6cfd).
      
      * Avoid gil and scope overhead if there is nothing to release.
      
      * Restore default move ctor. "member function" instead of "function" (note that "method" is Python terminology).
      
      * Delete error_already_set copy ctor.
      
      * Make restore() non-const again to resolve clang-tidy failure (still experimenting).
      
      * Bring back error_already_set copy ctor, to see if that resolves the 4 MSVC test failures.
      
      * Add noexcept to error_already_set copy & move ctors (as suggested by @skylion007 IIUC).
      
      * Trying one-by-one noexcept copy ctor for old compilers.
      
      * Add back test covering copy ctor. Add another simple test that exercises the copy ctor.
      
      * Exclude more older compilers from using the noexcept = default ctors. (The tests in the previous commit exposed that those are broken.)
      
      * Factor out & reuse gil_scoped_acquire_local as gil_scoped_acquire_simple
      
      * Guard gil_scoped_acquire_simple by _Py_IsFinalizing() check.
      
      * what() GIL safety
      
      * clang-tidy & Python 3.6 fixes
      
      * Use `gil_scoped_acquire` in dtor, copy ctor, `what()`. Remove `_Py_IsFinalizing()` checks (they are racy: https://github.com/python/cpython/pull/28525).
      
      * Remove error_scope from copy ctor.
      
      * Add `error_scope` to `get_internals()`, to cover the situation that `get_internals()` is called from the `error_already_set` dtor while a new Python error is in flight already. Also backing out `gil_scoped_acquire_simple` change.
      
      * Add `FlakyException` tests with failure triggers in `__init__` and `__str__`
      
      THIS IS STILL A WORK IN PROGRESS. This commit is only an important resting point.
      
      This commit is a first attempt at addressing the observation that `PyErr_NormalizeException()` completely replaces the original exception if `__init__` fails. This can be very confusing even in small applications, and extremely confusing in large ones.
      
      * Tweaks to resolve Py 3.6 and PyPy CI failures.
      
      * Normalize Python exception immediately in error_already_set ctor.
      
      For background see: https://github.com/pybind/pybind11/pull/1895#issuecomment-1135304081
      
      
      
      * Fix oversights based on CI failures (copy & move ctor initialization).
      
      * Move @pytest.mark.xfail("env.PYPY") after @pytest.mark.parametrize(...)
      
      * Use @pytest.mark.skipif (xfail does not work for segfaults, of course).
      
      * Remove unused obj_class_name_or() function (it was added only under this PR).
      
      * Remove already obsolete C++ comments and code that were added only under this PR.
      
      * Slightly better (newly added) comments.
      
      * Factor out detail::error_fetch_and_normalize. Preparation for producing identical results from error_already_set::what() and detail::error_string(). Note that this is a very conservative refactoring. It would be much better to first move detail::error_string into detail/error_string.h
      
      * Copy most of error_string() code to new error_fetch_and_normalize::complete_lazy_error_string()
      
      * Remove all error_string() code from detail/type_caster_base.h. Note that this commit includes a subtle bug fix: previously error_string() restored the Python error, which will upset pybind11_fail(). This never was a problem in practice because the two PyType_Ready() calls in detail/class.h do not usually fail.
      
      * Return const std::string& instead of const char * and move error_string() to pytypes.h
      
      * Remove gil_scope_acquire from error_fetch_and_normalize, add back to error_already_set
      
      * Better handling of FlakyException __str__ failure.
      
      * Move error_fetch_and_normalize::complete_lazy_error_string() implementation from pybind11.h to pytypes.h
      
      * Add error_fetch_and_normalize::release_py_object_references() and use from error_already_set dtor.
      
      * Use shared_ptr for m_fetched_error => 1. non-racy, copy ctor that does not need the GIL; 2. enables guard against duplicate restore() calls.
      
      * Add comments.
      
      * Trivial renaming of a newly introduced member function.
      
      * Workaround for PyPy
      
      * Bug fix (oversight). Only valgrind got this one.
      
      * Use shared_ptr custom deleter for m_fetched_error in error_already_set. This enables removing the dtor, copy ctor, move ctor completely.
      
      * Further small simplification. With the GIL held, simply deleting the raw_ptr takes care of everything.
      
      * IWYU cleanup
      
      ```
      iwyu version: include-what-you-use 0.17 based on Debian clang version 13.0.1-3+build2
      ```
      
      Command used:
      
      ```
      iwyu -c -std=c++17 -DPYBIND11_TEST_BOOST -Iinclude/pybind11 -I/usr/include/python3.9 -I/usr/include/eigen3 include/pybind11/pytypes.cpp
      ```
      
      pytypes.cpp is a temporary file: `#include "pytypes.h"`
      
      The raw output is very long and noisy.
      
      I decided to use `#include <cstddef>` instead of `#include <cstdio>` for `std::size_t` (iwyu sticks to the manual choice).
      
      I ignored all iwyu suggestions that are indirectly covered by `#include <Python.h>`.
      
      I manually verified that all added includes are actually needed.
      Co-authored-by: default avatarAaron Gokaslan <skylion.aaron@gmail.com>
      Co-authored-by: default avatarRalf W. Grosse-Kunstleve <rwgk@google.com>
      a05bc3d2
  2. 31 May, 2022 2 commits
  3. 26 May, 2022 1 commit
    • Ralf W. Grosse-Kunstleve's avatar
      Move `PyErr_NormalizeException()` up a few lines (#3971) · 2c549eb7
      Ralf W. Grosse-Kunstleve authored
      * Add error_already_set_what what tests, asserting the status quo.
      
      * Move PyErr_NormalizeException() up a few lines.
      
      * @pytest.mark.skipif("env.PYPY") from PR #1895 is required even for this much simpler PR
      
      * Move PyException_SetTraceback() with PyErr_NormalizeException() as suggested by @skylion007
      
      * Insert a std::move() as suggested by @skylion007
      2c549eb7
  4. 11 Feb, 2022 1 commit
    • Ralf W. Grosse-Kunstleve's avatar
      Python 2 removal part 1: tests (C++ code is intentionally ~untouched) (#3688) · 6493f496
      Ralf W. Grosse-Kunstleve authored
      
      
      * `#error BYE_BYE_GOLDEN_SNAKE`
      
      * Removing everything related to 2.7 from ci.yml
      
      * Commenting-out Centos7
      
      * Removing `PYTHON: 27` from .appveyor.yml
      
      * "PY2" removal, mainly from tests. C++ code is not touched.
      
      * Systematic removal of `u` prefix from `u"..."` and `u'...'` literals. Collateral cleanup of a couple minor other things.
      
      * Cleaning up around case-insensitive hits for `[^a-z]py.*2` in tests/.
      
      * Removing obsolete Python 2 mention in compiling.rst
      
      * Proper `#error` for Python 2.
      
      * Using PY_VERSION_HEX to guard `#error "PYTHON 2 IS NO LONGER SUPPORTED.`
      
      * chore: bump pre-commit
      
      * style: run pre-commit for pyupgrade 3+
      
      * tests: use sys.version_info, not PY
      
      * chore: more Python 2 removal
      
      * Uncommenting Centos7 block (PR #3691 showed that it is working again).
      
      * Update pre-commit hooks
      
      * Fix pre-commit hook
      
      * refactor: remove Python 2 from CMake
      
      * refactor: remove Python 2 from setup code
      
      * refactor: simplify, better static typing
      
      * feat: fail with nice messages
      
      * refactor: drop Python 2 C++ code
      
      * docs: cleanup for Python 3
      
      * revert: intree
      
      revert: intree
      
      * docs: minor touchup to py2 statement
      Co-authored-by: default avatarHenry Schreiner <henryschreineriii@gmail.com>
      Co-authored-by: default avatarAaron Gokaslan <skylion.aaron@gmail.com>
      6493f496
  5. 10 Feb, 2022 1 commit
  6. 08 Feb, 2022 1 commit
  7. 14 Jan, 2022 1 commit
    • Aaron Gokaslan's avatar
      Add support for nested C++11 exceptions (#3608) · d2ec8367
      Aaron Gokaslan authored
      * Add support for nested C++11 exceptions
      
      * Remove wrong include
      
      * Fix if directive
      
      * Fix missing skipif
      
      * Simplify code and try to work around MSVC bug
      
      * Clarify comment
      
      * Further simplify code
      
      * Remove the last extra throw statement
      
      * Qualify auto
      
      * Fix typo
      
      * Add missing return for consistency
      
      * Fix clang-tidy complaint
      
      * Fix python2 stub
      
      * Make clang-tidy happy
      
      * Fix compile error
      
      * Fix python2 function signature
      
      * Extract C++20 utility and backport
      
      * Cleanup code a bit more
      
      * Improve test case
      
      * Consolidate code and fix signature
      
      * Fix typo
      d2ec8367
  8. 09 Sep, 2021 1 commit
    • Ralf W. Grosse-Kunstleve's avatar
      CodeHealth: Enabling clang-tidy google-explicit-constructor (#3250) · 6abf2baa
      Ralf W. Grosse-Kunstleve authored
      * Adding google-explicit-constructor to .clang-tidy
      
      * clang-tidy explicit attr.h (all automatic)
      
      * clang-tidy explicit cast.h (all automatic)
      
      * clang-tidy detail/init.h (1 NOLINT)
      
      * clang-tidy detail/type_caster_base.h (2 NOLINT)
      
      * clang-tidy pybind11.h (7 NOLINT)
      
      * clang-tidy detail/common.h (3 NOLINT)
      
      * clang-tidy detail/descr.h (2 NOLINT)
      
      * clang-tidy pytypes.h (23 NOLINT, only 1 explicit)
      
      * clang-tidy eigen.h (7 NOLINT, 0 explicit)
      
      * Adding 2 explicit in functional.h
      
      * Adding 4 explicit in iostream.h
      
      * clang-tidy numpy.h (1 NOLINT, 1 explicit)
      
      * clang-tidy embed.h (0 NOLINT, 1 explicit)
      
      * clang-tidy tests/local_bindings.h (0 NOLINT, 4 explicit)
      
      * clang-tidy tests/pybind11_cross_module_tests.cpp (0 NOLINT, 1 explicit)
      
      * clang-tidy tests/pybind11_tests.h (0 NOLINT, 2 explicit)
      
      * clang-tidy tests/test_buffers.cpp (0 NOLINT, 2 explicit)
      
      * clang-tidy tests/test_builtin_casters.cpp (0 NOLINT, 4 explicit)
      
      * clang-tidy tests/test_class.cpp (0 NOLINT, 6 explicit)
      
      * clang-tidy tests/test_copy_move.cpp (0 NOLINT, 7 explicit)
      
      * clang-tidy tests/test_embed/external_module.cpp (0 NOLINT, 1 explicit)
      
      * clang-tidy tests/test_embed/test_interpreter.cpp (0 NOLINT, 1 explicit)
      
      * clang-tidy tests/object.h (0 NOLINT, 2 explicit)
      
      * clang-tidy batch of fully automatic fixes.
      
      * Workaround for MSVC 19.16.27045.0 C++17 Python 2 C++ syntax error.
      6abf2baa
  9. 24 Aug, 2021 1 commit
  10. 21 Jul, 2021 1 commit
    • jesse-sony's avatar
      Feature/local exception translator (#2650) · d65edfb0
      jesse-sony authored
      * Create a module_internals struct
      
      Since we now have two things that are going to be module local, it felt
      correct to add a struct to manage them.
      
      * Add local exception translators
      
      These are added via the  register_local_exception_translator function
      and are then applied before the global translators
      
      * Add unit tests to show the local exception translator works
      
      * Fix a bug in the unit test with the string value of KeyError
      
      * Fix a formatting issue
      
      * Rename registered_local_types_cpp()
      
      Rename it to get_registered_local_types_cpp() to disambiguate from the
      new member of module_internals
      
      * Add additional comments to new local exception code path
      
      * Add a register_local_exception function
      
      * Add additional unit tests for register_local_exception
      
      * Use get_local_internals like get_internals
      
      * Update documentation for new local exception feature
      
      * Add back a missing space
      
      * Clean-up some issues in the docs
      
      * Remove the code duplication when translating exceptions
      
      Separated out the exception processing into a standalone function in the
      details namespace.
      
      Clean-up some comments as per PR notes as well
      
      * Remove the code duplication in register_exception
      
      * Cleanup some formatting things caught by clang-format
      
      * Remove the templates from exception translators
      
      But I added a using declaration to alias the type.
      
      * Remove the extra local from local_internals variable names
      
      * Add an extra explanatory comment to local_internals
      
      * Fix a typo in the code
      d65edfb0
  11. 12 Jul, 2021 1 commit
    • Ralf W. Grosse-Kunstleve's avatar
      NOLINT reduction (#3096) · 2d468697
      Ralf W. Grosse-Kunstleve authored
      * Copying from prework_no_rst branch (PR #3087): test_numpy_array.cpp, test_stl.cpp
      
      * Manual changes reducing NOLINTs.
      
      * clang-format-diff.py
      
      * Minor adjustment to avoid MSVC warning C4702: unreachable code
      2d468697
  12. 22 Jun, 2021 1 commit
    • Aaron Gokaslan's avatar
      fix(clang-tidy): performance fixes applied in tests and CI (#3051) · dac74ebd
      Aaron Gokaslan authored
      * Initial fixes
      
      * Whoops
      
      * Finish clang-tidy manual fixes
      
      * Add two missing fixes
      
      * Revert
      
      * Update clang-tidy
      
      * Try to fix unreachable code error
      
      * Move nolint comment
      
      * Apply missing fix
      
      * Don't override clang-tidy config
      
      * Does this fix clang-tidy?
      
      * Make all clang-tidy errors visible
      
      * Add comments about NOLINTs and remove a few
      
      * Fix typo
      dac74ebd
  13. 27 May, 2021 1 commit
  14. 29 Oct, 2020 1 commit
    • Ralf W. Grosse-Kunstleve's avatar
      clang -Wnon-virtual-dtor compatibility (#2626) · 8290a5a0
      Ralf W. Grosse-Kunstleve authored
      * Adding missing virtual destructors, to silence clang -Wnon-virtual-dtor warnings.
      
      Tested with clang version 9.0.1-12 under an Ubuntu-like OS.
      Originally discovered in the Google-internal environment.
      
      * adding -Wnon-virtual-dtor for GNU|Intel|Clang
      8290a5a0
  15. 03 Oct, 2020 1 commit
  16. 15 Sep, 2020 1 commit
  17. 18 Aug, 2020 1 commit
  18. 16 Aug, 2020 1 commit
  19. 14 Nov, 2019 1 commit
  20. 12 May, 2019 1 commit
  21. 11 Jan, 2018 1 commit
  22. 29 Jul, 2017 2 commits
    • Jason Rhinelander's avatar
      Simplify error_already_set · 1682b673
      Jason Rhinelander authored
      `error_already_set` is more complicated than it needs to be, partly
      because it manages reference counts itself rather than using
      `py::object`, and partly because it tries to do more exception clearing
      than is needed.  This commit greatly simplifies it, and fixes #927.
      
      Using `py::object` instead of `PyObject *` means we can rely on
      implicit copy/move constructors.
      
      The current logic did both a `PyErr_Clear` on deletion *and* a
      `PyErr_Fetch` on creation.  I can't see how the `PyErr_Clear` on
      deletion is ever useful: the `Fetch` on creation itself clears the
      error, so the only way doing a `PyErr_Clear` on deletion could do
      anything if is some *other* exception was raised while the
      `error_already_set` object was alive--but in that case, clearing some
      other exception seems wrong.  (Code that is worried about an exception
      handler raising another exception would already catch a second
      `error_already_set` from exception code).
      
      The destructor itself called `clear()`, but `clear()` was a little bit
      more paranoid that needed: it called `restore()` to restore the
      currently captured error, but then immediately cleared it, using the
      `PyErr_Restore` to release the references.  That's unnecessary: it's
      valid for us to release the references manually.  This updates the code
      to simply release the references on the three objects (preserving the
      gil acquire).
      
      `clear()`, however, also had the side effect of clearing the current
      error, even if the current `error_already_set` didn't have a current
      error (e.g. because of a previous `restore()` or `clear()` call).  I
      don't really see how clearing the error here can ever actually be
      useful: the only way the current error could be set is if you called
      `restore()` (in which case the current stored error-related members have
      already been released), or if some *other* code raised the error, in
      which case `clear()` on *this* object is clearing an error for which it
      shouldn't be responsible.
      
      Neither of those seem like intentional or desirable features, and
      manually requesting deletion of the stored references similarly seems
      pointless, so I've just made `clear()` an empty method and marked it
      deprecated.
      
      This also fixes a minor potential issue with the destruction: it is
      technically possible for `value` to be null (though this seems likely to
      be rare in practice); this updates the check to look at `type` which
      will always be non-null for a `Fetch`ed exception.
      
      This also adds error_already_set round-trip throw tests to the test
      suite.
      1682b673
    • Jason Rhinelander's avatar
      abcf43d5
  23. 27 Jun, 2017 1 commit
  24. 02 Apr, 2017 1 commit
    • Roman Miroshnychenko's avatar
      Add a method to check Python exception types (#772) · 83a8a977
      Roman Miroshnychenko authored
      This commit adds `error_already_set::matches()` convenience method to
      check if the exception trapped by `error_already_set` matches a given
      Python exception type. This will address #700 by providing a less
      verbose way to check exceptions.
      83a8a977
  25. 12 Dec, 2016 1 commit
    • Jason Rhinelander's avatar
      Adds automatic casting on assignment of non-pyobject types (#551) · 3f1ff3f4
      Jason Rhinelander authored
      This adds automatic casting when assigning to python types like dict,
      list, and attributes.  Instead of:
      
          dict["key"] = py::cast(val);
          m.attr("foo") = py::cast(true);
          list.append(py::cast(42));
      
      you can now simply write:
      
          dict["key"] = val;
          m.attr("foo") = true;
          list.append(42);
      
      Casts needing extra parameters (e.g. for a non-default rvp) still
      require the py::cast() call. set::add() is also supported.
      
      All usage is channeled through a SFINAE implementation which either just returns or casts. 
      
      Combined non-converting handle and autocasting template methods via a
      helper method that either just returns (handle) or casts (C++ type).
      3f1ff3f4
  26. 16 Sep, 2016 1 commit
    • Jason Rhinelander's avatar
      Added py::register_exception for simple case (#296) · b3794f10
      Jason Rhinelander authored
      The custom exception handling added in PR #273 is robust, but is overly
      complex for declaring the most common simple C++ -> Python exception
      mapping that needs only to copy `what()`.  This add a simpler
      `py::register_exception<CppExp>(module, "PyExp");` function that greatly
      simplifies the common basic case of translation of a simple CppException
      into a simple PythonException, while not removing the more advanced
      capabilities of defining custom exception handlers.
      b3794f10
  27. 10 Sep, 2016 1 commit
    • Dean Moldovan's avatar
      Make error_already_set fetch and hold the Python error · 135ba8de
      Dean Moldovan authored
      This clears the Python error at the error_already_set throw site, thus
      allowing Python calls to be made in destructors which are triggered by
      the exception. This is preferable to the alternative, which would be
      guarding every Python API call with an error_scope.
      
      This effectively flips the behavior of error_already_set. Previously,
      it was assumed that the error stays in Python, so handling the exception
      in C++ would require explicitly calling PyErr_Clear(), but nothing was
      needed to propagate the error to Python. With this change, handling the
      error in C++ does not require a PyErr_Clear() call, but propagating the
      error to Python requires an explicit error_already_set::restore().
      
      The change does not break old code which explicitly calls PyErr_Clear()
      for cleanup, which should be the majority of user code. The need for an
      explicit restore() call does break old code, but this should be mostly
      confined to the library and not user code.
      135ba8de
  28. 07 Sep, 2016 1 commit
  29. 03 Sep, 2016 1 commit
    • Jason Rhinelander's avatar
      Make test initialization self-registering · 52f4be89
      Jason Rhinelander authored
      Adding or removing tests is a little bit cumbersome currently: the test
      needs to be added to CMakeLists.txt, the init function needs to be
      predeclared in pybind11_tests.cpp, then called in the plugin
      initialization.  While this isn't a big deal for tests that are being
      committed, it's more of a hassle when working on some new feature or
      test code for which I temporarily only care about building and linking
      the test being worked on rather than the entire test suite.
      
      This commit changes tests to self-register their initialization by
      having each test initialize a local object (which stores the
      initialization function in a static variable).  This makes changing the
      set of tests being build easy: one only needs to add or comment out
      test names in tests/CMakeLists.txt.
      
      A couple other minor changes that go along with this:
      
      - test_eigen.cpp is now included in the test list, then removed if eigen
        isn't available.  This lets you disable the eigen tests by commenting
        it out, just like all the other tests, but keeps the build working
        without eigen eigen isn't available.  (Also, if it's commented out, we
        don't even bother looking for and reporting the building with/without
        eigen status message).
      
      - pytest is now invoked with all the built test names (with .cpp changed
        to .py) so that it doesn't try to run tests that weren't built.
      52f4be89
  30. 19 Aug, 2016 1 commit
    • Dean Moldovan's avatar
      Port tests to pytest · a0c1ccf0
      Dean Moldovan authored
      Use simple asserts and pytest's powerful introspection to make testing
      simpler. This merges the old .py/.ref file pairs into simple .py files
      where the expected values are right next to the code being tested.
      
      This commit does not touch the C++ part of the code and replicates the
      Python tests exactly like the old .ref-file-based approach.
      a0c1ccf0
  31. 18 Jul, 2016 1 commit
    • Jason Rhinelander's avatar
      Rename examples files, as per #288 · b3f3d79f
      Jason Rhinelander authored
      This renames example files from `exampleN` to `example-description`.
      
      Specifically, the following renaming is applied:
      
      example1 -> example-methods-and-attributes
      example2 -> example-python-types
      example3 -> example-operator-overloading
      example4 -> example-constants-and-functions
      example5 -> example-callbacks (*)
      example6 -> example-sequence-and-iterators
      example7 -> example-buffers
      example8 -> example-custom-ref-counting
      example9 -> example-modules
      example10 -> example-numpy-vectorize
      example11 -> example-arg-keywords-and-defaults
      example12 -> example-virtual-functions
      example13 -> example-keep-alive
      example14 -> example-opaque-types
      example15 -> example-pickling
      example16 -> example-inheritance
      example17 -> example-stl-binders
      example18 -> example-eval
      example19 -> example-custom-exceptions
      
      * the inheritance parts of example5 are moved into example-inheritance
      (previously example16), and the remainder is left as example-callbacks.
      
      This commit also renames the internal variables ("Example1",
      "Example2", "Example4", etc.) into non-numeric names ("ExampleMandA",
      "ExamplePythonTypes", "ExampleWithEnum", etc.) to correspond to the
      file renaming.
      
      The order of tests is preserved, but this can easily be changed if
      there is some more natural ordering by updating the list in
      examples/CMakeLists.txt.
      b3f3d79f
  32. 11 Jul, 2016 1 commit