Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Calls to std::ostringstream.str() in pybind11 modules do not work on Python 3.12 #655

Open
taranu opened this issue Nov 8, 2024 · 1 comment

Comments

@taranu
Copy link

taranu commented Nov 8, 2024

Python Version

3.12

pytest Version

8.3.3

Package Version

3.15.0

Description

Making a simple pybind11 module that binds a function calling ostringstream.str() appears to break in pytest with pytest-randomly on py3.12 (but not 3.11). To reproduce:

testrandomly.cc

#include <pybind11/pybind11.h>
#include <pybind11/stl.h>

namespace py = pybind11;

#include <sstream>

std::string to_string_float(float value) {
    std::ostringstream out;
    out << value;
    return out.str();
}

PYBIND11_MODULE(testrandomly, m)
{
    m.def("to_string_float", to_string_float);
}

Compiled with conda-forge provided g++ 14.1.0 and pybind11 2.13.1 by:
g++ -Wall -shared -fPIC -std=c++17 $(python3 -m pybind11 --includes) testrandomly.cc -o testrandomly$(python3-config --extension-suffix)

test_randomly.py

from testrandomly import to_string_float

assert to_string_float(1.0) == "1"

pytest --randomly-seed=0 test_randomly.py works on py3.11 with any seed.
pytest -p no:randomly test_randomly.py also works on py3.12.
pytest --randomly-seed=0 test_randomly.py fails on py3.12 with any seed like so:

test_randomly.py:3: in <module>
    assert to_string_float(1.0) == "1"
E   AssertionError: assert '' == '1'
E    +  where '' = <built-in method to_string_float of PyCapsule object at 0x7f4737916af0>(1.0)

std::to_string works just fine, hence I suspect that this is a strange interaction with ostringstream. It's possible that this is a pybind11 or py3.12 bug but I figured I'd file an issue here first because I can only reproduce it with pytest-randomly enabled and can't guess at why.

@adamchainz
Copy link
Member

Uhhh it would be incredibly surprising if anything in pytest-randomly was doing more than incidentally triggering this. My guess would be that it's one of the things that pytest-randomly imports that's actually fiddling with something that the function relies on.

Try editing your local copy to remove the optional imports, like xdist, factory boy, etc.:

try:
import xdist
except ImportError: # pragma: no cover
xdist = None
# factory-boy
try:
from factory.random import set_random_state as factory_set_random_state
have_factory_boy = True
except ImportError: # pragma: no cover
# old versions
try:
from factory.fuzzy import set_random_state as factory_set_random_state
have_factory_boy = True
except ImportError:
have_factory_boy = False
# faker
try:
from faker.generator import random as faker_random
have_faker = True
except ImportError: # pragma: no cover
have_faker = False
# model_bakery
try:
from model_bakery.random_gen import baker_random
have_model_bakery = True
except ImportError: # pragma: no cover
have_model_bakery = False
# numpy
try:
from numpy import random as np_random
have_numpy = True
except ImportError: # pragma: no cover
have_numpy = False

I think it will be a bug in one of those, or indeed pybind11 or Python 3.12.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants