Imported Upstream version 1.15.6 upstream/1.15.6
authorDongHun Kwak <dh0128.kwak@samsung.com>
Wed, 31 Oct 2018 02:17:13 +0000 (11:17 +0900)
committerDongHun Kwak <dh0128.kwak@samsung.com>
Wed, 31 Oct 2018 02:17:13 +0000 (11:17 +0900)
15 files changed:
NEWS
PKG-INFO
cairo/cairomodule.c
cairo/error.c
cairo/font.c
cairo/private.h
cairo/region.c
setup.py
tests/test_api.py
tests/test_context.py
tests/test_enums.py
tests/test_error.py
tests/test_font.py
tests/test_hypothesis.py
tests/test_surface.py

diff --git a/NEWS b/NEWS
index 1b4bb8e..e82b4f5 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,6 +1,14 @@
 Since version 1.11.0 Pycairo uses `Semantic Versioning
 <http://semver.org/>`__ i.e. the newest version is the latest stable one.
 
+.. _v1.15.6:
+
+1.15.6 - 2018-01-30
+-------------------
+
+* Experimental PyPy and PyPy3 support :bug:`90`
+
+
 .. _v1.15.5:
 
 1.15.5 - 2018-01-29
index 3ad9769..26d4729 100644 (file)
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: pycairo
-Version: 1.15.5
+Version: 1.15.6
 Summary: Python interface for cairo
 Home-page: https://pycairo.readthedocs.io
 Author: Christoph Reiter
index 0f3b210..6ffae30 100644 (file)
@@ -41,36 +41,6 @@ xpyb_CAPI_t *xpyb_CAPI;
 PyObject *xpybVISUALTYPE_type;
 #endif
 
-#if PY_MAJOR_VERSION < 3
-
-/* A module specific exception */
-PyObject *_CairoError = NULL;
-
-#else
-
-/* Module initialization */
-struct cairo_state {
-  PyObject *ErrorObject;
-};
-
-#define GETSTATE(m) ((struct cairo_state*)PyModule_GetState(m))
-
-static struct PyModuleDef cairomoduledef;
-#endif
-
-/* Returns a borrowed reference of the error type. */
-PyObject *
-_Pycairo_Get_Error(void) {
-#if PY_MAJOR_VERSION < 3
-  assert(_CairoError != NULL);
-  return _CairoError;
-#else
-  PyObject *cairo_module = PyState_FindModule(&cairomoduledef);
-  assert(cairo_module != NULL);
-  return GETSTATE(cairo_module)->ErrorObject;
-#endif
-}
-
 /* C API.  Clients get at this via Pycairo_IMPORT or import_cairo(), defined in pycairo.h.
  */
 static Pycairo_CAPI_t CAPI = {
@@ -174,36 +144,22 @@ static PyMethodDef cairo_functions[] = {
 
 #if PY_MAJOR_VERSION >= 3
 
-static int
-cairo_traverse(PyObject *m, visitproc visit, void *arg)
-{
-  Py_VISIT(GETSTATE(m)->ErrorObject);
-  return 0;
-}
-
-static int
-cairo_clear(PyObject *m)
-{
-  Py_CLEAR(GETSTATE(m)->ErrorObject);
-  return 0;
-}
-
 static struct PyModuleDef cairomoduledef = {
   PyModuleDef_HEAD_INIT,
   "cairo",
   NULL,
-  sizeof(struct cairo_state),
+  0,
   cairo_functions,
-  0,  /* m_reload */
-  cairo_traverse,
-  cairo_clear,
-  0,  /* m_free - not needed, since all is done in m_clear */
+  0,
+  0,
+  0,
+  0,
 };
 #endif
 
 PYCAIRO_MOD_INIT(_cairo)
 {
-  PyObject *m, *capi, *error;
+  PyObject *m, *capi;
 
   if (PyType_Ready(&PycairoContext_Type) < 0)
     return PYCAIRO_MOD_ERROR_VAL;
@@ -324,6 +280,9 @@ PYCAIRO_MOD_INIT(_cairo)
   if (m == NULL)
     return PYCAIRO_MOD_ERROR_VAL;
 
+  if(init_error(m) < 0)
+    return PYCAIRO_MOD_ERROR_VAL;
+
   if(init_buffer_proxy() < 0)
     return PYCAIRO_MOD_ERROR_VAL;
 
@@ -469,26 +428,6 @@ PYCAIRO_MOD_INIT(_cairo)
                     (PyObject *)&PycairoTeeSurface_Type);
 #endif
 
-  /* Add 'cairo.Error' to the module */
-  error = error_get_type();
-  if (error == NULL)
-    return PYCAIRO_MOD_ERROR_VAL;
-
-#if PY_MAJOR_VERSION >= 3
-  GETSTATE(m)->ErrorObject = error;
-#else
-  _CairoError = error;
-#endif
-
-  Py_INCREF(error);
-  if (PyModule_AddObject(m, "Error", error) < 0)
-    return PYCAIRO_MOD_ERROR_VAL;
-
-  /* Alias for cairocffi */
-  Py_INCREF(error);
-  if (PyModule_AddObject(m, "CairoError", error) < 0)
-    return PYCAIRO_MOD_ERROR_VAL;
-
     /* constants */
 #ifdef CAIRO_HAS_ATSUI_FONT
   PyModule_AddIntConstant(m, "HAS_ATSUI_FONT", 1);
index bb20f5d..275e79a 100644 (file)
@@ -68,31 +68,42 @@ set_error (PyObject *error_type, cairo_status_t status)
 
 int
 Pycairo_Check_Status (cairo_status_t status) {
-    PyObject *suberror;
+    PyObject *module, *error, *suberror;
 
     if (PyErr_Occurred() != NULL)
         return 1;
 
+    if (status == CAIRO_STATUS_SUCCESS)
+        return 0;
+
+    module = PyImport_ImportModule ("cairo");
+    if (module == NULL)
+        return 1;
+    error = PyObject_GetAttrString (module, "Error");
+    Py_DECREF (module);
+    if (error == NULL)
+        return 1;
+
     switch (status) {
-        case CAIRO_STATUS_SUCCESS:
-            return 0;
         case CAIRO_STATUS_NO_MEMORY:
             suberror = error_get_type_combined (
-                _Pycairo_Get_Error(), PyExc_MemoryError, "cairo.MemoryError");
+                error, PyExc_MemoryError, "cairo.MemoryError");
             set_error (suberror, status);
             Py_DECREF (suberror);
             break;
         case CAIRO_STATUS_READ_ERROR:
         case CAIRO_STATUS_WRITE_ERROR:
             suberror = error_get_type_combined (
-                _Pycairo_Get_Error(), PyExc_IOError, "cairo.IOError");
+                error, PyExc_IOError, "cairo.IOError");
             set_error (suberror, status);
             Py_DECREF (suberror);
             break;
         default:
-            set_error (_Pycairo_Get_Error(), status);
+            set_error (error, status);
     }
 
+    Py_DECREF (error);
+
     return 1;
 }
 
@@ -100,20 +111,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 +182,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 *
@@ -219,16 +262,29 @@ static PyTypeObject PycairoError_Type = {
     0,                       /* tp_new */
 };
 
-/* Returns a new reference of the error type or NULL on error and sets
- * an exception.
- */
-PyObject *
-error_get_type(void) {
+int
+init_error (PyObject *module) {
+    PyObject *error;
+
     PycairoError_Type.tp_base = (PyTypeObject*)PyExc_Exception;
     if (PyType_Ready(&PycairoError_Type) < 0)
-        return NULL;
-    Py_INCREF(&PycairoError_Type);
-    return (PyObject*)&PycairoError_Type;
+        return -1;
+
+    error = (PyObject*)&PycairoError_Type;
+
+    Py_INCREF(error);
+    if (PyModule_AddObject(module, "Error", error) < 0) {
+        Py_DECREF (error);
+        return -1;
+    }
+
+    Py_INCREF(error);
+    if (PyModule_AddObject(module, "CairoError", error) < 0) {
+        Py_DECREF (error);
+        return -1;
+    }
+
+    return 0;
 }
 
 static PyObject *
index e474de7..921ca5a 100644 (file)
@@ -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 */
index 3398fb7..6352aa5 100644 (file)
@@ -45,6 +45,8 @@
 #define PYCAIRO_STRINGIFY(s) PYCAIRO_STRINGIFY_ARG(s)
 #define PYCAIRO_STRINGIFY_ARG(s) #s
 
+int init_error(PyObject *module);
+
 int Pycairo_fspath_converter (PyObject *obj, char** result);
 int Pycairo_fspath_none_converter (PyObject *obj, char** result);
 int Pycairo_writer_converter (PyObject *obj, PyObject** file);
@@ -58,8 +60,6 @@ int _PyTextCluster_AsTextCluster (PyObject *pyobj,
 
 int _conv_pyobject_to_ulong (PyObject *pyobj, unsigned long *result);
 
-PyObject *_Pycairo_Get_Error(void);
-
 PyObject* Pycairo_richcompare (void* a, void *b, int op);
 PyObject* Pycairo_tuple_getattro (PyObject *self, char **kwds, PyObject *name);
 
index 2a9ddec..7f40f7b 100644 (file)
@@ -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 */
index 3f1d481..d024c4e 100755 (executable)
--- a/setup.py
+++ b/setup.py
@@ -11,7 +11,7 @@ from distutils.core import Extension, setup, Command, Distribution
 from distutils.ccompiler import new_compiler
 
 
-PYCAIRO_VERSION = '1.15.5'
+PYCAIRO_VERSION = '1.15.6'
 CAIRO_VERSION_REQUIRED = '1.13.1'
 XPYB_VERSION_REQUIRED = '1.3'
 
index 1c3332a..d8902c5 100644 (file)
@@ -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:
index e9fb5a6..11f5bd9 100644 (file)
@@ -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):
index 7db0728..e8df2d9 100644 (file)
@@ -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__
index d7e12e7..8704405 100644 (file)
@@ -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())
index 1ff1591..73a4ae7 100644 (file)
@@ -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())
index 7db96e1..28b6d62 100644 (file)
@@ -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):
index 7387247..f909ece 100644 (file)
@@ -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)