Repository navigation
Expand float and complex strict mode to allow ints and ints/float (for PEP 484 compatibility). - #5879
Conversation
|
I have started working on this too. |
This is known at compile time so it can be constexpr
|
Here is my implementation and documentation changes. It needs tests but I am going to stop for today. |
|
You will need to remove the constexpr check. I didn't realise it was a newer C++ feature |
Signed-off-by: Michael Carlstrom <rmc@carlstrom.com>
|
TODO: figure out why it doesn't work in C++11. |
Signed-off-by: Michael Carlstrom <rmc@carlstrom.com>
|
I have just found that a python float passed to an int argument will raise a TypeError. This is probably something we should resolve here because it effects these tests. m.def("func", [](int){});>>> func.__doc__
func(arg: typing.SupportsInt) -> None
>>> func(5.5)
TypeError
>>> func(numpy.float32(5.5)) # This works fine |
The int type caster allows anything that implements __int__ with explicit exception of the python float. I can't see any reason for this. This modifies the int casting behaviour to accept a float. If the argument is marked as noconvert() it will only accept int.
|
Here is my proposed change. You will need to update the tests. Here are my unittests |
|
I noticed something else to have address. According to the documentation all of int,float,complex support falling back on |
|
BTW, having looked at this so intensely ... bool py_err = py_value == (py_type) -1 && PyErr_Occurred();this will be OK if Python is healthy, but if something goes wrong (e.g. UB, or bug in Python beta testing) and So that condition basically errs on the unsafe side, it prioritizes the return value check over error detection. I think it'd be better to write: bool py_err = PyErr_Occurred();
if (py_err) assert(py_value == (py_type) -1);This prioritizes error detection over return value validation. WDYT? |
…ere (e.g. UB, or bug in Python beta testing). See also: pybind#5879 (comment)
Same. I looked through everything several times now. Thanks! |
|
FYI — This PR is included in PR #5988 |
As of pybind/pybind11#5879, pybind11 will convert Python `int` to C `float`/`double`. For `std::variant`, pybind11 will attempt to convert arguments in the order of the type. So if `double` occurs earlier in the variant, then `int`/`long` will never be produced. By putting `int`/`long` before `double`, pybind11 will attempt that conversion first and we'll continue to produce our deprecation warning correctly. Fixes matplotlib#31495
As of pybind/pybind11#5879, pybind11 will convert Python `int` to C `float`/`double`. For `std::variant`, pybind11 will attempt to convert arguments in the order of the type. So if `double` occurs earlier in the variant, then `int`/`long` will never be produced. By putting `int`/`long` before `double`, pybind11 will attempt that conversion first and we'll continue to produce our deprecation warning correctly. Fixes #31495
pinning pybind11<3 to dodge pybind11 3.x's overload-resolution change no longer even compiles: scipp 26.8.0's own lib/python/dtype.cpp and bind_data_access.h use pybind11 3.x-only API (dtype::normalized_num, dtype::num_of, py::make_scalar). Root-caused the actual regression instead of just pinning around it: bind_operators.h registers a double overload and an int64_t overload of each scalar operator (__add__, __iadd__, __eq__, ...) in that order. pybind11 3.x loosened float's implicit-conversion check to also accept a Python int (pybind/pybind11#5879), so the double overload - registered first - now wins for a plain int where int64_t used to, silently promoting int-valued scalars/results to float64 throughout scipp's Python layer. That's what actually failed 22 of upstream's own tests here, not a riscv64 codegen issue (confirmed against the official x86_64 PyPI wheel earlier). patches/scipp/26.8.0/0002 reorders registration to int64_t-first, so the exact-type overload wins under either pybind11 generation; nothing else changes. Verified the patch applies cleanly against the real 26.8.0 tag. Drop the now-unused PIP_CONSTRAINT/PIP_BUILD_CONSTRAINT env (no build-constraints.txt is written anymore).
Description
Breaking change to allow Python ints into float when under strict typing (
noconvert), to better match PEP 484 numeric tower rules.This change was also done to complex to allow floats and ints. Now that Python ints can be passed into floats it changes behavior for overload resolution. A method that takes float that is registered before a method that takes an int will now get executed when a Python int is passed in. This overload resolution also affects methods with
std::complex.Resolves #5878
Provides a work around for #5767
NOTE: This PR was reviewed extensively and is approved. However, because of the breaking change, it will be merged only after the next patch release.
Suggested changelog entry:
Breaking change for PEP 484 compatibility: Expand float and complex strict mode to allow ints and ints/float.
📚 Documentation preview 📚: https://pybind11--5879.org.readthedocs.build/