Add basic PyPy support. See #90
Use PyObject_GetAttrString() for accessing exception args as that works on PyPy too. Set tp_hash=PyObject_HashNotImplemented for some types, as PyPy doesn't make them unhashable if tp_richcompare is set: https://bitbucket.org/pypy/pypy/issues/2740 Skip some tests due to: https://bitbucket.org/pypy/pypy/issues/2741 https://bitbucket.org/pypy/pypy/issues/2742 Skip test_image_surface_create_for_data_array(), as it hangs. And test_fspaths(). Needs investigating..
This commit is contained in:
parent
54c268fe65
commit
947f0055cf
11
.travis.yml
11
.travis.yml
|
@ -25,6 +25,11 @@ matrix:
|
|||
language: python
|
||||
python: "3.6"
|
||||
env: PYCAIRO_WARN=1 CFLAGS="-Werror -coverage"
|
||||
- os: linux
|
||||
dist: trusty
|
||||
language: python
|
||||
python: "pypy"
|
||||
env: PYCAIRO_WARN=1 CFLAGS="-Werror -coverage"
|
||||
- os: osx
|
||||
osx_image: xcode7.3
|
||||
language: generic
|
||||
|
@ -50,12 +55,12 @@ install:
|
|||
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then source ../venv/bin/activate; fi
|
||||
- python -m pip install --upgrade setuptools
|
||||
- python -m pip install --upgrade pytest flake8 sphinx sphinx_rtd_theme coverage codecov hypothesis
|
||||
- if [ "$TRAVIS_PYTHON_VERSION" != "3.3" ]; then python -m pip install --upgrade pygame; fi
|
||||
- if [[ "$TRAVIS_PYTHON_VERSION" != "3.3" ]] && [[ "$TRAVIS_PYTHON_VERSION" != "pypy" ]]; then python -m pip install --upgrade pygame; fi
|
||||
|
||||
script:
|
||||
- python -m coverage run --branch setup.py test
|
||||
- python -m codecov
|
||||
- python -m flake8 .
|
||||
- python setup.py sdist
|
||||
- python -m pip install "$(eval 'echo dist/*')"
|
||||
- if [ "$TRAVIS_PYTHON_VERSION" != "3.3" ]; then python -m sphinx -W -a -E -b html -n docs docs/_build; fi
|
||||
- if [[ "$TRAVIS_PYTHON_VERSION" != "pypy" ]]; then python -m pip install "$(eval 'echo dist/*')"; fi
|
||||
- if [[ "$TRAVIS_PYTHON_VERSION" != "3.3" ]]; then python -m sphinx -W -a -E -b html -n docs docs/_build; fi
|
||||
|
|
|
@ -100,20 +100,43 @@ typedef struct {
|
|||
PyBaseExceptionObject base;
|
||||
} PycairoErrorObject;
|
||||
|
||||
static PyObject *
|
||||
error_get_args(PycairoErrorObject *self) {
|
||||
PyObject *args;
|
||||
|
||||
args = PyObject_GetAttrString((PyObject *)self, "args");
|
||||
if (args == NULL)
|
||||
return NULL;
|
||||
|
||||
if (!PyTuple_Check(args)) {
|
||||
PyErr_SetString(PyExc_TypeError, ".args not a tuple");
|
||||
Py_DECREF(args);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
static int
|
||||
error_init(PycairoErrorObject *self, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
PyObject *status_obj;
|
||||
PyObject *status_obj, *error_args;
|
||||
|
||||
if (PycairoError_Type.tp_base->tp_init((PyObject *)self, args, kwds) < 0)
|
||||
return -1;
|
||||
|
||||
if(PyTuple_GET_SIZE(self->base.args) >= 2) {
|
||||
status_obj = PyTuple_GET_ITEM(self->base.args, 1);
|
||||
error_args = error_get_args(self);
|
||||
if (error_args == NULL)
|
||||
return -1;
|
||||
|
||||
if(PyTuple_GET_SIZE(error_args) >= 2) {
|
||||
status_obj = PyTuple_GET_ITEM(error_args, 1);
|
||||
} else {
|
||||
status_obj = Py_None;
|
||||
}
|
||||
|
||||
Py_DECREF(error_args);
|
||||
|
||||
if (PyObject_SetAttrString ((PyObject *)self, "__status", status_obj) < 0)
|
||||
return -1;
|
||||
|
||||
|
@ -148,12 +171,21 @@ static PyGetSetDef error_getset[] = {
|
|||
static PyObject *
|
||||
error_str(PycairoErrorObject *self)
|
||||
{
|
||||
PyObject *result, *error_args;
|
||||
|
||||
error_args = error_get_args(self);
|
||||
if (error_args == NULL)
|
||||
return NULL;
|
||||
|
||||
/* Default to printing just the message */
|
||||
if (PyTuple_GET_SIZE(self->base.args) >= 1) {
|
||||
return PyObject_Str(PyTuple_GET_ITEM(self->base.args, 0));
|
||||
if (PyTuple_GET_SIZE(error_args) >= 1) {
|
||||
result = PyObject_Str(PyTuple_GET_ITEM(error_args, 0));
|
||||
} else {
|
||||
return PycairoError_Type.tp_base->tp_str((PyObject*)self);
|
||||
result = PycairoError_Type.tp_base->tp_str((PyObject*)self);
|
||||
}
|
||||
|
||||
Py_DECREF(error_args);
|
||||
return result;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
|
|
|
@ -830,7 +830,7 @@ PyTypeObject PycairoFontOptions_Type = {
|
|||
0, /* tp_as_number */
|
||||
0, /* tp_as_sequence */
|
||||
0, /* tp_as_mapping */
|
||||
0, /* tp_hash */
|
||||
(hashfunc)PyObject_HashNotImplemented,/* tp_hash */
|
||||
0, /* tp_call */
|
||||
0, /* tp_str */
|
||||
0, /* tp_getattro */
|
||||
|
|
|
@ -137,7 +137,7 @@ PyTypeObject PycairoRectangleInt_Type = {
|
|||
0, /* tp_as_number */
|
||||
0, /* tp_as_sequence */
|
||||
0, /* tp_as_mapping */
|
||||
0, /* tp_hash */
|
||||
(hashfunc)PyObject_HashNotImplemented,/* tp_hash */
|
||||
0, /* tp_call */
|
||||
0, /* tp_str */
|
||||
0, /* tp_getattro */
|
||||
|
@ -556,7 +556,7 @@ PyTypeObject PycairoRegion_Type = {
|
|||
0, /* tp_as_number */
|
||||
0, /* tp_as_sequence */
|
||||
0, /* tp_as_mapping */
|
||||
0, /* tp_hash */
|
||||
(hashfunc)PyObject_HashNotImplemented,/* tp_hash */
|
||||
0, /* tp_call */
|
||||
0, /* tp_str */
|
||||
0, /* tp_getattro */
|
||||
|
|
|
@ -260,6 +260,7 @@ def test_constants():
|
|||
assert cairo.SVG_VERSION_1_2 == 1
|
||||
|
||||
|
||||
@pytest.mark.skipif(not hasattr(sys, "getrefcount"), reason="PyPy")
|
||||
def test_surface_get_set_mime_data_references():
|
||||
surface = cairo.ImageSurface(cairo.FORMAT_RGB24, 1, 1)
|
||||
if sys.version_info[0] == 2:
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import cairo
|
||||
import pytest
|
||||
import ctypes
|
||||
import platform
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
|
@ -49,6 +50,7 @@ def test_get_set_operator_limits(context):
|
|||
assert context.get_operator() == val
|
||||
|
||||
|
||||
@pytest.mark.skipif(platform.python_implementation() == "PyPy", reason="PyPy")
|
||||
def test_show_text_glyphs():
|
||||
surface = cairo.PDFSurface(None, 300, 300)
|
||||
context = cairo.Context(surface)
|
||||
|
@ -306,6 +308,7 @@ def test_scale(context):
|
|||
context.scale(object(), 0)
|
||||
|
||||
|
||||
@pytest.mark.skipif(platform.python_implementation() == "PyPy", reason="PyPy")
|
||||
def test_select_font_face(context):
|
||||
context.select_font_face("")
|
||||
with pytest.raises(TypeError):
|
||||
|
@ -458,6 +461,7 @@ def test_text_extents(context):
|
|||
context.text_extents()
|
||||
|
||||
|
||||
@pytest.mark.skipif(platform.python_implementation() == "PyPy", reason="PyPy")
|
||||
def test_text_path(context):
|
||||
context.text_path("foo")
|
||||
with pytest.raises(TypeError):
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
import pickle
|
||||
import re
|
||||
import platform
|
||||
|
||||
import pytest
|
||||
import cairo
|
||||
|
||||
|
||||
@pytest.mark.skipif(platform.python_implementation() == "PyPy", reason="PyPy")
|
||||
def test_type():
|
||||
t = cairo.Antialias
|
||||
assert int in t.__mro__
|
||||
|
|
|
@ -37,7 +37,7 @@ def test_error_check_status():
|
|||
err.status = cairo.Status.DEVICE_FINISHED
|
||||
assert err.status == cairo.Status.DEVICE_FINISHED
|
||||
|
||||
with pytest.raises(TypeError):
|
||||
with pytest.raises((TypeError, AttributeError)):
|
||||
del err.status
|
||||
|
||||
str(cairo.Error())
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import sys
|
||||
import platform
|
||||
|
||||
import cairo
|
||||
import pytest
|
||||
|
@ -166,6 +167,7 @@ def test_scaled_font_get_scale_matrix(scaled_font):
|
|||
assert isinstance(scaled_font.get_scale_matrix(), cairo.Matrix)
|
||||
|
||||
|
||||
@pytest.mark.skipif(platform.python_implementation() == "PyPy", reason="PyPy")
|
||||
def test_scaled_font_text_extents(scaled_font):
|
||||
with pytest.raises(TypeError):
|
||||
scaled_font.text_extents(object())
|
||||
|
@ -180,6 +182,7 @@ def test_scaled_font_glyph_extents(scaled_font):
|
|||
scaled_font.glyph_extents()
|
||||
|
||||
|
||||
@pytest.mark.skipif(platform.python_implementation() == "PyPy", reason="PyPy")
|
||||
def test_toy_font_face():
|
||||
with pytest.raises(TypeError):
|
||||
cairo.ToyFontFace(object())
|
||||
|
|
|
@ -5,6 +5,7 @@ import os
|
|||
import sys
|
||||
import tempfile
|
||||
import shutil
|
||||
import platform
|
||||
|
||||
import pytest
|
||||
import cairo
|
||||
|
@ -39,6 +40,7 @@ def cairo_ver():
|
|||
return tuple(map(int, cairo.cairo_version_string().split(".")))
|
||||
|
||||
|
||||
@pytest.mark.skipif(platform.python_implementation() == "PyPy", reason="PyPy")
|
||||
@given(path=fspaths())
|
||||
@settings(max_examples=500)
|
||||
def test_fspaths(tempdir_path, path):
|
||||
|
|
|
@ -7,6 +7,7 @@ import array
|
|||
import tempfile
|
||||
import struct
|
||||
import sysconfig
|
||||
import platform
|
||||
|
||||
import cairo
|
||||
import pytest
|
||||
|
@ -110,6 +111,7 @@ def test_tee_surface():
|
|||
tee.remove(s1)
|
||||
|
||||
|
||||
@pytest.mark.skipif(not hasattr(sys, "getrefcount"), reason="PyPy")
|
||||
def test_image_surface_get_data_refcount():
|
||||
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 10, 10)
|
||||
assert sys.getrefcount(surface) == 2
|
||||
|
@ -387,6 +389,7 @@ def test_supports_mime_type():
|
|||
surface.supports_mime_type(object())
|
||||
|
||||
|
||||
@pytest.mark.skipif(platform.python_implementation() == "PyPy", reason="PyPy")
|
||||
def test_image_surface_create_for_data_array():
|
||||
width, height = 255, 255
|
||||
data = array.array('B', [0] * width * height * 4)
|
||||
|
|
Loading…
Reference in New Issue