From 0d70f0e18eec60786499faba53de4d72583ba2f7 Mon Sep 17 00:00:00 2001 From: Isuru Fernando Date: Tue, 7 Jul 2020 08:58:16 -0500 Subject: [PATCH] PyPy3 support (#2146) * Error out eval_file * Enable dynamic attribute support for Pypy >= 6 * Add a test for dynamic attribute support * Skip test for eval_file on pypy * Workaround for __qualname__ on PyPy3 * Add a PyPy3.6 7.3.0 build * Only disable in PyPy3 * Fix travis testing * No numpy and scipy for pypy * Enable test on pypy2 * Fix logic in eval_file * Skip a few tests due to bugs in PyPy * scipy wheels are broken. make pypy2 a failrue Co-authored-by: Andreas Kloeckner --- .travis.yml | 11 ++++++----- include/pybind11/detail/class.h | 4 ++-- include/pybind11/eval.h | 15 +++++++++++++++ tests/conftest.py | 5 +++++ tests/test_eval.py | 7 ++++++- tests/test_local_bindings.py | 1 + tests/test_multiple_inheritance.cpp | 2 +- tests/test_multiple_inheritance.py | 4 +++- 8 files changed, 39 insertions(+), 10 deletions(-) diff --git a/.travis.yml b/.travis.yml index f9a906541..0e504582f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -192,9 +192,8 @@ matrix: make pytest -j 2" set +ex allow_failures: - - name: PyPy 7.3, Python 2.7, c++11, gcc 4.8 - - name: PyPy 7.3, Python 3.6, c++11, gcc 5 - name: Python 3.9 beta, c++17, gcc 7 (w/o numpy/scipy) + - name: PyPy 7.3, Python 2.7, c++11, gcc 4.8 cache: directories: - $HOME/.local/bin @@ -278,15 +277,17 @@ install: fi export NPY_NUM_BUILD_JOBS=2 - echo "Installing pytest, numpy, scipy..." local PIP_CMD="" if [ -n "$PYPY" ]; then # For expediency, install only versions that are available on the extra index. + echo "Not installing numpy, scipy as working wheels are not available" + # travis_wait 30 $PY_CMD -m pip install --user --upgrade --extra-index-url https://antocuni.github.io/pypy-wheels/manylinux2010 \ + # numpy scipy + echo "Installing pytest" travis_wait 30 \ - $PY_CMD -m pip install --user --upgrade --extra-index-url https://antocuni.github.io/pypy-wheels/manylinux2010 \ - numpy scipy $PY_CMD -m pip install --user --upgrade pytest else + echo "Installing pytest, numpy, scipy..." $PY_CMD -m pip install --user --upgrade pytest numpy scipy fi echo "done." diff --git a/include/pybind11/detail/class.h b/include/pybind11/detail/class.h index e5783d9f6..f6b89c20e 100644 --- a/include/pybind11/detail/class.h +++ b/include/pybind11/detail/class.h @@ -15,7 +15,7 @@ NAMESPACE_BEGIN(PYBIND11_NAMESPACE) NAMESPACE_BEGIN(detail) -#if PY_VERSION_HEX >= 0x03030000 +#if PY_VERSION_HEX >= 0x03030000 && !defined(PYPY_VERSION) # define PYBIND11_BUILTIN_QUALNAME # define PYBIND11_SET_OLDPY_QUALNAME(obj, nameobj) #else @@ -475,7 +475,7 @@ extern "C" inline int pybind11_clear(PyObject *self) { /// Give instances of this type a `__dict__` and opt into garbage collection. inline void enable_dynamic_attributes(PyHeapTypeObject *heap_type) { auto type = &heap_type->ht_type; -#if defined(PYPY_VERSION) +#if defined(PYPY_VERSION) && (PYPY_VERSION_NUM < 0x06000000) pybind11_fail(std::string(type->tp_name) + ": dynamic attributes are " "currently not supported in " "conjunction with PyPy!"); diff --git a/include/pybind11/eval.h b/include/pybind11/eval.h index ea85ba1db..422e629f5 100644 --- a/include/pybind11/eval.h +++ b/include/pybind11/eval.h @@ -66,6 +66,20 @@ void exec(const char (&s)[N], object global = globals(), object local = object() eval(s, global, local); } +#if defined(PYPY_VERSION) && PY_VERSION_HEX >= 0x3000000 +template +object eval_file(str, object, object) { + pybind11_fail("eval_file not supported in PyPy3. Use eval"); +} +template +object eval_file(str, object) { + pybind11_fail("eval_file not supported in PyPy3. Use eval"); +} +template +object eval_file(str) { + pybind11_fail("eval_file not supported in PyPy3. Use eval"); +} +#else template object eval_file(str fname, object global = globals(), object local = object()) { if (!local) @@ -113,5 +127,6 @@ object eval_file(str fname, object global = globals(), object local = object()) throw error_already_set(); return reinterpret_steal(result); } +#endif NAMESPACE_END(PYBIND11_NAMESPACE) diff --git a/tests/conftest.py b/tests/conftest.py index 57f681c66..58ebecaf9 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -215,6 +215,11 @@ def pytest_configure(): pytest.requires_eigen_and_scipy = skipif( not have_eigen or not scipy, reason="eigen and/or scipy are not installed") pytest.unsupported_on_pypy = skipif(pypy, reason="unsupported on PyPy") + pytest.bug_in_pypy = pytest.mark.xfail(pypy, reason="bug in PyPy") + pytest.unsupported_on_pypy3 = skipif(pypy and sys.version_info.major >= 3, + reason="unsupported on PyPy3") + pytest.unsupported_on_pypy_lt_6 = skipif(pypy and sys.pypy_version_info[0] < 6, + reason="unsupported on PyPy<6") pytest.unsupported_on_py2 = skipif(sys.version_info.major < 3, reason="unsupported on Python 2.x") pytest.gc_collect = gc_collect diff --git a/tests/test_eval.py b/tests/test_eval.py index bda4ef6bf..94228e7d2 100644 --- a/tests/test_eval.py +++ b/tests/test_eval.py @@ -1,4 +1,5 @@ import os +import pytest from pybind11_tests import eval_ as m @@ -10,8 +11,12 @@ def test_evals(capture): assert m.test_eval() assert m.test_eval_single_statement() + assert m.test_eval_failure() + + +@pytest.unsupported_on_pypy3 +def test_eval_file(): filename = os.path.join(os.path.dirname(__file__), "test_eval_call.py") assert m.test_eval_file(filename) - assert m.test_eval_failure() assert m.test_eval_file_failure() diff --git a/tests/test_local_bindings.py b/tests/test_local_bindings.py index b380376e2..be841a70c 100644 --- a/tests/test_local_bindings.py +++ b/tests/test_local_bindings.py @@ -152,6 +152,7 @@ def test_internal_locals_differ(): assert m.local_cpp_types_addr() != cm.local_cpp_types_addr() +@pytest.bug_in_pypy def test_stl_caster_vs_stl_bind(msg): """One module uses a generic vector caster from `` while the other exports `std::vector` via `py:bind_vector` and `py::module_local`""" diff --git a/tests/test_multiple_inheritance.cpp b/tests/test_multiple_inheritance.cpp index ba1674fb2..70e341785 100644 --- a/tests/test_multiple_inheritance.cpp +++ b/tests/test_multiple_inheritance.cpp @@ -193,7 +193,7 @@ TEST_SUBMODULE(multiple_inheritance, m) { .def_readwrite_static("static_value", &VanillaStaticMix2::static_value); -#if !defined(PYPY_VERSION) +#if !(defined(PYPY_VERSION) && (PYPY_VERSION_NUM < 0x06000000)) struct WithDict { }; struct VanillaDictMix1 : Vanilla, WithDict { }; struct VanillaDictMix2 : WithDict, Vanilla { }; diff --git a/tests/test_multiple_inheritance.py b/tests/test_multiple_inheritance.py index 475dd3b3d..7a6e4a085 100644 --- a/tests/test_multiple_inheritance.py +++ b/tests/test_multiple_inheritance.py @@ -10,6 +10,7 @@ def test_multiple_inheritance_cpp(): assert mt.bar() == 4 +@pytest.bug_in_pypy def test_multiple_inheritance_mix1(): class Base1: def __init__(self, i): @@ -49,6 +50,7 @@ def test_multiple_inheritance_mix2(): assert mt.bar() == 4 +@pytest.bug_in_pypy def test_multiple_inheritance_python(): class MI1(m.Base1, m.Base2): @@ -253,7 +255,7 @@ def test_mi_static_properties(): assert d.static_value == 0 -@pytest.unsupported_on_pypy +@pytest.unsupported_on_pypy_lt_6 def test_mi_dynamic_attributes(): """Mixing bases with and without dynamic attribute support"""