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 <inform@tiker.net>
This commit is contained in:
Isuru Fernando 2020-07-07 08:58:16 -05:00 committed by GitHub
parent f2226aefe0
commit 0d70f0e18e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 39 additions and 10 deletions

View File

@ -192,9 +192,8 @@ matrix:
make pytest -j 2" make pytest -j 2"
set +ex set +ex
allow_failures: 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: 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: cache:
directories: directories:
- $HOME/.local/bin - $HOME/.local/bin
@ -278,15 +277,17 @@ install:
fi fi
export NPY_NUM_BUILD_JOBS=2 export NPY_NUM_BUILD_JOBS=2
echo "Installing pytest, numpy, scipy..."
local PIP_CMD="" local PIP_CMD=""
if [ -n "$PYPY" ]; then if [ -n "$PYPY" ]; then
# For expediency, install only versions that are available on the extra index. # 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 \ 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 $PY_CMD -m pip install --user --upgrade pytest
else else
echo "Installing pytest, numpy, scipy..."
$PY_CMD -m pip install --user --upgrade pytest numpy scipy $PY_CMD -m pip install --user --upgrade pytest numpy scipy
fi fi
echo "done." echo "done."

View File

@ -15,7 +15,7 @@
NAMESPACE_BEGIN(PYBIND11_NAMESPACE) NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
NAMESPACE_BEGIN(detail) NAMESPACE_BEGIN(detail)
#if PY_VERSION_HEX >= 0x03030000 #if PY_VERSION_HEX >= 0x03030000 && !defined(PYPY_VERSION)
# define PYBIND11_BUILTIN_QUALNAME # define PYBIND11_BUILTIN_QUALNAME
# define PYBIND11_SET_OLDPY_QUALNAME(obj, nameobj) # define PYBIND11_SET_OLDPY_QUALNAME(obj, nameobj)
#else #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. /// Give instances of this type a `__dict__` and opt into garbage collection.
inline void enable_dynamic_attributes(PyHeapTypeObject *heap_type) { inline void enable_dynamic_attributes(PyHeapTypeObject *heap_type) {
auto type = &heap_type->ht_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 " pybind11_fail(std::string(type->tp_name) + ": dynamic attributes are "
"currently not supported in " "currently not supported in "
"conjunction with PyPy!"); "conjunction with PyPy!");

View File

@ -66,6 +66,20 @@ void exec(const char (&s)[N], object global = globals(), object local = object()
eval<eval_statements>(s, global, local); eval<eval_statements>(s, global, local);
} }
#if defined(PYPY_VERSION) && PY_VERSION_HEX >= 0x3000000
template <eval_mode mode = eval_statements>
object eval_file(str, object, object) {
pybind11_fail("eval_file not supported in PyPy3. Use eval");
}
template <eval_mode mode = eval_statements>
object eval_file(str, object) {
pybind11_fail("eval_file not supported in PyPy3. Use eval");
}
template <eval_mode mode = eval_statements>
object eval_file(str) {
pybind11_fail("eval_file not supported in PyPy3. Use eval");
}
#else
template <eval_mode mode = eval_statements> template <eval_mode mode = eval_statements>
object eval_file(str fname, object global = globals(), object local = object()) { object eval_file(str fname, object global = globals(), object local = object()) {
if (!local) if (!local)
@ -113,5 +127,6 @@ object eval_file(str fname, object global = globals(), object local = object())
throw error_already_set(); throw error_already_set();
return reinterpret_steal<object>(result); return reinterpret_steal<object>(result);
} }
#endif
NAMESPACE_END(PYBIND11_NAMESPACE) NAMESPACE_END(PYBIND11_NAMESPACE)

View File

@ -215,6 +215,11 @@ def pytest_configure():
pytest.requires_eigen_and_scipy = skipif( pytest.requires_eigen_and_scipy = skipif(
not have_eigen or not scipy, reason="eigen and/or scipy are not installed") 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.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, pytest.unsupported_on_py2 = skipif(sys.version_info.major < 3,
reason="unsupported on Python 2.x") reason="unsupported on Python 2.x")
pytest.gc_collect = gc_collect pytest.gc_collect = gc_collect

View File

@ -1,4 +1,5 @@
import os import os
import pytest
from pybind11_tests import eval_ as m from pybind11_tests import eval_ as m
@ -10,8 +11,12 @@ def test_evals(capture):
assert m.test_eval() assert m.test_eval()
assert m.test_eval_single_statement() 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") filename = os.path.join(os.path.dirname(__file__), "test_eval_call.py")
assert m.test_eval_file(filename) assert m.test_eval_file(filename)
assert m.test_eval_failure()
assert m.test_eval_file_failure() assert m.test_eval_file_failure()

View File

@ -152,6 +152,7 @@ def test_internal_locals_differ():
assert m.local_cpp_types_addr() != cm.local_cpp_types_addr() assert m.local_cpp_types_addr() != cm.local_cpp_types_addr()
@pytest.bug_in_pypy
def test_stl_caster_vs_stl_bind(msg): def test_stl_caster_vs_stl_bind(msg):
"""One module uses a generic vector caster from `<pybind11/stl.h>` while the other """One module uses a generic vector caster from `<pybind11/stl.h>` while the other
exports `std::vector<int>` via `py:bind_vector` and `py::module_local`""" exports `std::vector<int>` via `py:bind_vector` and `py::module_local`"""

View File

@ -193,7 +193,7 @@ TEST_SUBMODULE(multiple_inheritance, m) {
.def_readwrite_static("static_value", &VanillaStaticMix2::static_value); .def_readwrite_static("static_value", &VanillaStaticMix2::static_value);
#if !defined(PYPY_VERSION) #if !(defined(PYPY_VERSION) && (PYPY_VERSION_NUM < 0x06000000))
struct WithDict { }; struct WithDict { };
struct VanillaDictMix1 : Vanilla, WithDict { }; struct VanillaDictMix1 : Vanilla, WithDict { };
struct VanillaDictMix2 : WithDict, Vanilla { }; struct VanillaDictMix2 : WithDict, Vanilla { };

View File

@ -10,6 +10,7 @@ def test_multiple_inheritance_cpp():
assert mt.bar() == 4 assert mt.bar() == 4
@pytest.bug_in_pypy
def test_multiple_inheritance_mix1(): def test_multiple_inheritance_mix1():
class Base1: class Base1:
def __init__(self, i): def __init__(self, i):
@ -49,6 +50,7 @@ def test_multiple_inheritance_mix2():
assert mt.bar() == 4 assert mt.bar() == 4
@pytest.bug_in_pypy
def test_multiple_inheritance_python(): def test_multiple_inheritance_python():
class MI1(m.Base1, m.Base2): class MI1(m.Base1, m.Base2):
@ -253,7 +255,7 @@ def test_mi_static_properties():
assert d.static_value == 0 assert d.static_value == 0
@pytest.unsupported_on_pypy @pytest.unsupported_on_pypy_lt_6
def test_mi_dynamic_attributes(): def test_mi_dynamic_attributes():
"""Mixing bases with and without dynamic attribute support""" """Mixing bases with and without dynamic attribute support"""